@react-spectrum/s2 3.0.0-nightly-7eae25e12-241205 → 3.0.0-nightly-8228e4efd-241207

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/Tabs.cjs CHANGED
@@ -531,12 +531,17 @@ function $b27519d6a701105b$var$CollapsingCollection({ children: children, contai
531
531
  }, [
532
532
  orientation
533
533
  ]);
534
- return /*#__PURE__*/ (0, $5oxdw$reactjsxruntime.jsx)($b27519d6a701105b$var$CollapseContext.Provider, {
535
- value: {
534
+ let ctx = (0, $5oxdw$react.useMemo)(()=>({
536
535
  containerRef: containerRef,
537
536
  showItems: orientation === 'vertical' ? true : showItems,
538
537
  setShowItems: setShowItems
539
- },
538
+ }), [
539
+ containerRef,
540
+ showItems,
541
+ setShowItems
542
+ ]);
543
+ return /*#__PURE__*/ (0, $5oxdw$reactjsxruntime.jsx)($b27519d6a701105b$var$CollapseContext.Provider, {
544
+ value: ctx,
540
545
  children: /*#__PURE__*/ (0, $5oxdw$reactjsxruntime.jsx)((0, $5oxdw$reactariacomponents.UNSTABLE_CollectionRendererContext).Provider, {
541
546
  value: $b27519d6a701105b$var$CollapsingCollectionRenderer,
542
547
  children: children
package/dist/Tabs.cjs.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"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","sources":["packages/@react-spectrum/s2/src/Tabs.tsx"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n TabListProps as AriaTabListProps,\n TabPanel as AriaTabPanel,\n TabPanelProps as AriaTabPanelProps,\n TabProps as AriaTabProps,\n TabsProps as AriaTabsProps,\n CollectionRenderer,\n ContextValue,\n Provider,\n Tab as RACTab,\n TabList as RACTabList,\n Tabs as RACTabs,\n TabListStateContext,\n UNSTABLE_CollectionRendererContext,\n UNSTABLE_DefaultCollectionRenderer\n} from 'react-aria-components';\nimport {centerBaseline} from './CenterBaseline';\nimport {Collection, DOMRef, DOMRefValue, FocusableRef, FocusableRefValue, Key, Node, Orientation, RefObject} from '@react-types/shared';\nimport {createContext, forwardRef, Fragment, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';\nimport {focusRing, size, style} from '../style' with {type: 'macro'};\nimport {getAllowedOverrides, StyleProps, StylesPropWithHeight, UnsafeStyles} from './style-utils' with {type: 'macro'};\nimport {IconContext} from './Icon';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {Picker, PickerItem} from './TabsPicker';\nimport {Text, TextContext} from './Content';\nimport {useControlledState} from '@react-stately/utils';\nimport {useDOMRef} from '@react-spectrum/utils';\nimport {useEffectEvent, useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale, useLocalizedStringFormatter} from '@react-aria/i18n';\nimport {useSpectrumContextProps} from './useSpectrumContextProps';\n\nexport interface TabsProps extends Omit<AriaTabsProps, 'className' | 'style' | 'children'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tabs. */\n children?: ReactNode,\n /**\n * The amount of space between the tabs.\n * @default 'regular'\n */\n density?: 'compact' | 'regular',\n /**\n * If the tabs should only display icons and no text.\n */\n isIconOnly?: boolean\n}\n\nexport interface TabProps extends Omit<AriaTabProps, 'children' | 'style' | 'className'>, StyleProps {\n /** The content to display in the tab. */\n children: ReactNode\n}\n\nexport interface TabListProps<T> extends Omit<AriaTabListProps<T>, 'style' | 'className'>, StyleProps {}\n\nexport interface TabPanelProps extends Omit<AriaTabPanelProps, 'children' | 'style' | 'className'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tab panels. */\n children?: ReactNode\n}\n\nexport const TabsContext = createContext<ContextValue<TabsProps, DOMRefValue<HTMLDivElement>>>(null);\nconst InternalTabsContext = createContext<TabsProps & {onFocus:() => void, pickerRef?: FocusableRef<HTMLButtonElement>}>({onFocus: () => {}});\n\nconst tabs = style({\n display: 'flex',\n flexShrink: 0,\n font: 'ui',\n flexDirection: {\n orientation: {\n horizontal: 'column'\n }\n }\n}, getAllowedOverrides({height: true}));\n\n/**\n * Tabs organize content into multiple sections and allow users to navigate between them. The content under the set of tabs should be related and form a coherent unit.\n */\nexport const Tabs = forwardRef(function Tabs(props: TabsProps, ref: DOMRef<HTMLDivElement>) {\n [props, ref] = useSpectrumContextProps(props, ref, TabsContext);\n let {\n density = 'regular',\n isDisabled,\n disabledKeys,\n orientation = 'horizontal',\n isIconOnly = false\n } = props;\n let domRef = useDOMRef(ref);\n let [value, setValue] = useControlledState(props.selectedKey, props.defaultSelectedKey ?? null!, props.onSelectionChange);\n let pickerRef = useRef<FocusableRefValue<HTMLButtonElement>>(null);\n\n return (\n <Provider\n values={[\n [InternalTabsContext, {\n density,\n isDisabled,\n orientation,\n disabledKeys,\n selectedKey: value,\n onSelectionChange: setValue,\n isIconOnly,\n onFocus: () => pickerRef.current?.focus(),\n pickerRef\n }]\n ]}>\n <CollapsingCollection containerRef={domRef}>\n <RACTabs\n {...props}\n ref={domRef}\n selectedKey={value}\n onSelectionChange={setValue}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tabs({...renderProps}, props.styles)}>\n {props.children}\n </RACTabs>\n </CollapsingCollection>\n </Provider>\n );\n});\n\nconst tablist = style({\n display: 'flex',\n gap: {\n orientation: {\n horizontal: {\n density: {\n compact: 24,\n regular: 32\n },\n isIconOnly: {\n density: {\n compact: 16,\n regular: 24\n }\n }\n }\n }\n },\n flexDirection: {\n orientation: {\n vertical: 'column'\n }\n },\n paddingEnd: {\n orientation: {\n vertical: 20\n }\n },\n paddingStart: {\n orientation: {\n vertical: 12\n }\n },\n flexShrink: 0,\n flexBasis: '[0%]'\n});\n\nexport function TabList<T extends object>(props: TabListProps<T>) {\n let {density, isDisabled, disabledKeys, orientation, isIconOnly, onFocus} = useContext(InternalTabsContext) ?? {};\n let {showItems} = useContext(CollapseContext) ?? {};\n let state = useContext(TabListStateContext);\n let [selectedTab, setSelectedTab] = useState<HTMLElement | undefined>(undefined);\n let tablistRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (tablistRef?.current && showItems) {\n let tab: HTMLElement | null = tablistRef.current.querySelector('[role=tab][data-selected=true]');\n\n if (tab != null) {\n setSelectedTab(tab);\n }\n } else if (tablistRef?.current) {\n let picker: HTMLElement | null = tablistRef.current.querySelector('button');\n if (picker != null) {\n setSelectedTab(picker);\n }\n }\n }, [tablistRef, state?.selectedItem?.key, showItems]);\n\n let prevFocused = useRef<boolean | undefined>(false);\n useLayoutEffect(() => {\n if (!showItems && !prevFocused.current && state?.selectionManager.isFocused) {\n onFocus();\n }\n prevFocused.current = state?.selectionManager.isFocused;\n }, [state?.selectionManager.isFocused, state?.selectionManager.focusedKey, showItems]);\n\n return (\n <div\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + style({position: 'relative'}, getAllowedOverrides())(null, props.styles)}>\n {showItems && orientation === 'vertical' &&\n <TabLine disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n <RACTabList\n {...props}\n ref={tablistRef}\n className={renderProps => tablist({...renderProps, isIconOnly, density})} />\n {orientation === 'horizontal' &&\n <TabLine showItems={showItems} disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n </div>\n );\n}\n\ninterface TabLineProps {\n disabledKeys: Iterable<Key> | undefined,\n isDisabled: boolean | undefined,\n selectedTab: HTMLElement | undefined,\n orientation?: Orientation,\n density?: 'compact' | 'regular',\n showItems?: boolean\n}\n\nconst selectedIndicator = style({\n position: 'absolute',\n backgroundColor: {\n default: 'neutral',\n isDisabled: 'disabled',\n forcedColors: {\n default: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n height: {\n orientation: {\n horizontal: '[2px]'\n }\n },\n width: {\n orientation: {\n vertical: '[2px]'\n }\n },\n bottom: {\n orientation: {\n horizontal: 0\n }\n },\n borderStyle: 'none',\n borderRadius: 'full',\n transitionDuration: 130,\n transitionTimingFunction: 'in-out'\n});\n\nfunction TabLine(props: TabLineProps & {isIconOnly?: boolean}) {\n let {\n disabledKeys,\n isDisabled: isTabsDisabled,\n selectedTab,\n orientation,\n density\n } = props;\n let {direction} = useLocale();\n let state = useContext(TabListStateContext);\n\n let isDisabled = useMemo(() => {\n return isTabsDisabled || isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys, isTabsDisabled]);\n\n let [style, setStyle] = useState<{transform: string | undefined, width: string | undefined, height: string | undefined}>({\n transform: undefined,\n width: undefined,\n height: undefined\n });\n\n let onResize = useCallback(() => {\n if (selectedTab) {\n let styleObj: { transform: string | undefined, width: string | undefined, height: string | undefined } = {\n transform: undefined,\n width: undefined,\n height: undefined\n };\n\n // In RTL, calculate the transform from the right edge of the tablist so that resizing the window doesn't break the Tabline position due to offsetLeft changes\n let offset = direction === 'rtl' ? -1 * ((selectedTab.offsetParent as HTMLElement)?.offsetWidth - selectedTab.offsetWidth - selectedTab.offsetLeft) : selectedTab.offsetLeft;\n styleObj.transform = orientation === 'vertical'\n ? `translateY(${selectedTab.offsetTop}px)`\n : `translateX(${offset}px)`;\n\n if (orientation === 'horizontal') {\n styleObj.width = `${selectedTab.offsetWidth}px`;\n } else {\n styleObj.height = `${selectedTab.offsetHeight}px`;\n }\n setStyle(styleObj);\n }\n }, [direction, setStyle, selectedTab, orientation]);\n\n useLayoutEffect(() => {\n onResize();\n }, [onResize, state?.selectedItem?.key, density]);\n\n let ref = useRef<HTMLElement | undefined>(selectedTab);\n // assign ref before the useResizeObserver useEffect runs\n useLayoutEffect(() => {\n ref.current = selectedTab;\n });\n useResizeObserver({ref, onResize});\n\n return (\n <div style={{...style}} className={selectedIndicator({isDisabled, orientation})} />\n );\n}\n\nconst tab = style({\n ...focusRing(),\n display: 'flex',\n color: {\n default: 'neutral-subdued',\n isSelected: 'neutral',\n isHovered: 'neutral-subdued',\n isDisabled: 'disabled',\n forcedColors: {\n isSelected: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n borderRadius: 'sm',\n gap: 'text-to-visual',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n },\n alignItems: 'center',\n position: 'relative',\n cursor: 'default',\n flexShrink: 0,\n transition: 'default',\n paddingX: {\n isIconOnly: size(6)\n }\n}, getAllowedOverrides());\n\nconst icon = style({\n display: 'block',\n flexShrink: 0,\n '--iconPrimary': {\n type: 'fill',\n value: 'currentColor'\n }\n});\n\nexport function Tab(props: TabProps) {\n let {density, isIconOnly} = useContext(InternalTabsContext) ?? {};\n\n return (\n <RACTab\n {...props}\n // @ts-ignore\n originalProps={props}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tab({...renderProps, density, isIconOnly}, props.styles)}>\n {({\n // @ts-ignore\n isMenu\n }) => {\n if (isMenu) {\n return props.children;\n } else {\n return (\n <Provider\n values={[\n [TextContext, {\n styles:\n style({\n order: 1,\n display: {\n isIconOnly: 'none'\n }\n })({isIconOnly})\n }],\n [IconContext, {\n render: centerBaseline({slot: 'icon', styles: style({order: 0})}),\n styles: icon\n }]\n ]}>\n {typeof props.children === 'string' ? <Text>{props.children}</Text> : props.children}\n </Provider>\n );\n }\n }}\n </RACTab>\n );\n}\n\nconst tabPanel = style({\n marginTop: 4,\n color: 'gray-800',\n flexGrow: 1,\n flexBasis: '[0%]',\n minHeight: 0,\n minWidth: 0\n}, getAllowedOverrides({height: true}));\n\nexport function TabPanel(props: TabPanelProps) {\n return (\n <AriaTabPanel\n {...props}\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + tabPanel(null, props.styles)} />\n );\n}\n\nfunction isAllTabsDisabled<T>(collection: Collection<Node<T>> | undefined, disabledKeys: Set<Key>) {\n let testKey: Key | null = null;\n if (collection && collection.size > 0) {\n testKey = collection.getFirstKey();\n\n let index = 0;\n while (testKey && index < collection.size) {\n // We have to check if the item in the collection has a key in disabledKeys or has the isDisabled prop set directly on it\n if (!disabledKeys.has(testKey) && !collection.getItem(testKey)?.props?.isDisabled) {\n return false;\n }\n\n testKey = collection.getKeyAfter(testKey);\n index++;\n }\n return true;\n }\n return false;\n}\n\nlet HiddenTabs = function (props: {\n listRef: RefObject<HTMLDivElement | null>,\n items: Array<Node<any>>,\n size?: string,\n density?: 'compact' | 'regular'\n}) {\n let {listRef, items, size, density} = props;\n\n return (\n <div\n // @ts-ignore\n inert=\"true\"\n ref={listRef}\n className={style({\n display: '[inherit]',\n flexDirection: '[inherit]',\n gap: '[inherit]',\n flexWrap: '[inherit]',\n position: 'absolute',\n inset: 0,\n visibility: 'hidden',\n overflow: 'hidden',\n opacity: 0\n })}>\n {items.map((item) => {\n // pull off individual props as an allow list, don't want refs or other props getting through\n return (\n <div\n data-hidden-tab\n style={item.props.UNSAFE_style}\n key={item.key}\n className={item.props.className({size, density})}>\n {item.props.children({size, density})}\n </div>\n );\n })}\n </div>\n );\n};\n\nlet TabsMenu = (props: {items: Array<Node<any>>, onSelectionChange: TabsProps['onSelectionChange']}) => {\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/s2');\n let {items} = props;\n let {density, onSelectionChange, selectedKey, isDisabled, disabledKeys, pickerRef, isIconOnly} = useContext(InternalTabsContext);\n let state = useContext(TabListStateContext);\n let allKeysDisabled = useMemo(() => {\n return isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys]);\n\n return (\n <UNSTABLE_CollectionRendererContext.Provider value={UNSTABLE_DefaultCollectionRenderer}>\n <div\n className={style({\n display: 'flex',\n alignItems: 'center',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n }})({density})}>\n <Picker\n ref={pickerRef ? pickerRef : undefined}\n isDisabled={isDisabled || allKeysDisabled}\n density={density!}\n isIconOnly={isIconOnly}\n items={items}\n disabledKeys={disabledKeys}\n selectedKey={selectedKey}\n onSelectionChange={onSelectionChange}\n aria-label={stringFormatter.format('tabs.selectorLabel')}>\n {(item: Node<any>) => {\n // need to determine the best way to handle icon only -> icon and text\n // good enough to aria-label the picker item?\n return (\n <PickerItem\n {...item.props.originalProps}\n isDisabled={isDisabled || allKeysDisabled}\n key={item.key}>\n {item.props.children({density, isMenu: true})}\n </PickerItem>\n );\n }}\n </Picker>\n </div>\n </UNSTABLE_CollectionRendererContext.Provider>\n );\n};\n\n// Context for passing the count for the custom renderer\nlet CollapseContext = createContext<{\n containerRef: RefObject<HTMLDivElement | null>,\n showItems: boolean,\n setShowItems:(value: boolean) => void\n} | null>(null);\n\nfunction CollapsingCollection({children, containerRef}) {\n let [showItems, _setShowItems] = useState(true);\n let {orientation} = useContext(InternalTabsContext);\n let setShowItems = useCallback((value: boolean) => {\n if (orientation === 'vertical') {\n // if orientation is vertical, we always show the items\n _setShowItems(true);\n } else {\n _setShowItems(value);\n }\n }, [orientation]);\n return (\n <CollapseContext.Provider value={{containerRef, showItems: orientation === 'vertical' ? true : showItems, setShowItems}}>\n <UNSTABLE_CollectionRendererContext.Provider value={CollapsingCollectionRenderer}>\n {children}\n </UNSTABLE_CollectionRendererContext.Provider>\n </CollapseContext.Provider>\n );\n}\n\nlet CollapsingCollectionRenderer: CollectionRenderer = {\n CollectionRoot({collection}) {\n return useCollectionRender(collection);\n },\n CollectionBranch({collection}) {\n return useCollectionRender(collection);\n }\n};\n\n\nlet useCollectionRender = (collection: Collection<Node<unknown>>) => {\n let {containerRef, showItems, setShowItems} = useContext(CollapseContext) ?? {};\n let {density = 'regular', orientation = 'horizontal', onSelectionChange} = useContext(InternalTabsContext);\n let {direction} = useLocale();\n\n let children = useMemo(() => {\n let result: Node<any>[] = [];\n for (let key of collection.getKeys()) {\n result.push(collection.getItem(key)!);\n }\n return result;\n }, [collection]);\n\n let listRef = useRef<HTMLDivElement | null>(null);\n let updateOverflow = useEffectEvent(() => {\n if (orientation === 'vertical' || !listRef.current || !containerRef?.current) {\n return;\n }\n let container = listRef.current;\n let containerRect = container.getBoundingClientRect();\n let tabs = container.querySelectorAll('[data-hidden-tab]');\n let lastTab = tabs[tabs.length - 1];\n let lastTabRect = lastTab.getBoundingClientRect();\n if (direction === 'ltr') {\n setShowItems?.(lastTabRect.right <= containerRect.right);\n } else {\n setShowItems?.(lastTabRect.left >= containerRect.left);\n }\n });\n\n useResizeObserver({ref: containerRef, onResize: updateOverflow});\n\n useLayoutEffect(() => {\n if (collection.size > 0) {\n queueMicrotask(updateOverflow);\n }\n }, [collection.size, updateOverflow]);\n\n useEffect(() => {\n // Recalculate visible tags when fonts are loaded.\n document.fonts?.ready.then(() => updateOverflow());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <>\n <HiddenTabs items={children} density={density} listRef={listRef} />\n {showItems ? (\n children.map(node => <Fragment key={node.key}>{node.render?.(node)}</Fragment>)\n ) : (\n <>\n <TabsMenu items={children} onSelectionChange={onSelectionChange} />\n </>\n )}\n </>\n );\n};\n"],"names":[],"version":3,"file":"Tabs.cjs.map"}
1
+ {"mappings":"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","sources":["packages/@react-spectrum/s2/src/Tabs.tsx"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n TabListProps as AriaTabListProps,\n TabPanel as AriaTabPanel,\n TabPanelProps as AriaTabPanelProps,\n TabProps as AriaTabProps,\n TabsProps as AriaTabsProps,\n CollectionRenderer,\n ContextValue,\n Provider,\n Tab as RACTab,\n TabList as RACTabList,\n Tabs as RACTabs,\n TabListStateContext,\n UNSTABLE_CollectionRendererContext,\n UNSTABLE_DefaultCollectionRenderer\n} from 'react-aria-components';\nimport {centerBaseline} from './CenterBaseline';\nimport {Collection, DOMRef, DOMRefValue, FocusableRef, FocusableRefValue, Key, Node, Orientation, RefObject} from '@react-types/shared';\nimport {createContext, forwardRef, Fragment, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';\nimport {focusRing, size, style} from '../style' with {type: 'macro'};\nimport {getAllowedOverrides, StyleProps, StylesPropWithHeight, UnsafeStyles} from './style-utils' with {type: 'macro'};\nimport {IconContext} from './Icon';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {Picker, PickerItem} from './TabsPicker';\nimport {Text, TextContext} from './Content';\nimport {useControlledState} from '@react-stately/utils';\nimport {useDOMRef} from '@react-spectrum/utils';\nimport {useEffectEvent, useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale, useLocalizedStringFormatter} from '@react-aria/i18n';\nimport {useSpectrumContextProps} from './useSpectrumContextProps';\n\nexport interface TabsProps extends Omit<AriaTabsProps, 'className' | 'style' | 'children'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tabs. */\n children?: ReactNode,\n /**\n * The amount of space between the tabs.\n * @default 'regular'\n */\n density?: 'compact' | 'regular',\n /**\n * If the tabs should only display icons and no text.\n */\n isIconOnly?: boolean\n}\n\nexport interface TabProps extends Omit<AriaTabProps, 'children' | 'style' | 'className'>, StyleProps {\n /** The content to display in the tab. */\n children: ReactNode\n}\n\nexport interface TabListProps<T> extends Omit<AriaTabListProps<T>, 'style' | 'className'>, StyleProps {}\n\nexport interface TabPanelProps extends Omit<AriaTabPanelProps, 'children' | 'style' | 'className'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tab panels. */\n children?: ReactNode\n}\n\nexport const TabsContext = createContext<ContextValue<TabsProps, DOMRefValue<HTMLDivElement>>>(null);\nconst InternalTabsContext = createContext<TabsProps & {onFocus:() => void, pickerRef?: FocusableRef<HTMLButtonElement>}>({onFocus: () => {}});\n\nconst tabs = style({\n display: 'flex',\n flexShrink: 0,\n font: 'ui',\n flexDirection: {\n orientation: {\n horizontal: 'column'\n }\n }\n}, getAllowedOverrides({height: true}));\n\n/**\n * Tabs organize content into multiple sections and allow users to navigate between them. The content under the set of tabs should be related and form a coherent unit.\n */\nexport const Tabs = forwardRef(function Tabs(props: TabsProps, ref: DOMRef<HTMLDivElement>) {\n [props, ref] = useSpectrumContextProps(props, ref, TabsContext);\n let {\n density = 'regular',\n isDisabled,\n disabledKeys,\n orientation = 'horizontal',\n isIconOnly = false\n } = props;\n let domRef = useDOMRef(ref);\n let [value, setValue] = useControlledState(props.selectedKey, props.defaultSelectedKey ?? null!, props.onSelectionChange);\n let pickerRef = useRef<FocusableRefValue<HTMLButtonElement>>(null);\n\n return (\n <Provider\n values={[\n [InternalTabsContext, {\n density,\n isDisabled,\n orientation,\n disabledKeys,\n selectedKey: value,\n onSelectionChange: setValue,\n isIconOnly,\n onFocus: () => pickerRef.current?.focus(),\n pickerRef\n }]\n ]}>\n <CollapsingCollection containerRef={domRef}>\n <RACTabs\n {...props}\n ref={domRef}\n selectedKey={value}\n onSelectionChange={setValue}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tabs({...renderProps}, props.styles)}>\n {props.children}\n </RACTabs>\n </CollapsingCollection>\n </Provider>\n );\n});\n\nconst tablist = style({\n display: 'flex',\n gap: {\n orientation: {\n horizontal: {\n density: {\n compact: 24,\n regular: 32\n },\n isIconOnly: {\n density: {\n compact: 16,\n regular: 24\n }\n }\n }\n }\n },\n flexDirection: {\n orientation: {\n vertical: 'column'\n }\n },\n paddingEnd: {\n orientation: {\n vertical: 20\n }\n },\n paddingStart: {\n orientation: {\n vertical: 12\n }\n },\n flexShrink: 0,\n flexBasis: '[0%]'\n});\n\nexport function TabList<T extends object>(props: TabListProps<T>) {\n let {density, isDisabled, disabledKeys, orientation, isIconOnly, onFocus} = useContext(InternalTabsContext) ?? {};\n let {showItems} = useContext(CollapseContext) ?? {};\n let state = useContext(TabListStateContext);\n let [selectedTab, setSelectedTab] = useState<HTMLElement | undefined>(undefined);\n let tablistRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (tablistRef?.current && showItems) {\n let tab: HTMLElement | null = tablistRef.current.querySelector('[role=tab][data-selected=true]');\n\n if (tab != null) {\n setSelectedTab(tab);\n }\n } else if (tablistRef?.current) {\n let picker: HTMLElement | null = tablistRef.current.querySelector('button');\n if (picker != null) {\n setSelectedTab(picker);\n }\n }\n }, [tablistRef, state?.selectedItem?.key, showItems]);\n\n let prevFocused = useRef<boolean | undefined>(false);\n useLayoutEffect(() => {\n if (!showItems && !prevFocused.current && state?.selectionManager.isFocused) {\n onFocus();\n }\n prevFocused.current = state?.selectionManager.isFocused;\n }, [state?.selectionManager.isFocused, state?.selectionManager.focusedKey, showItems]);\n\n return (\n <div\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + style({position: 'relative'}, getAllowedOverrides())(null, props.styles)}>\n {showItems && orientation === 'vertical' &&\n <TabLine disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n <RACTabList\n {...props}\n ref={tablistRef}\n className={renderProps => tablist({...renderProps, isIconOnly, density})} />\n {orientation === 'horizontal' &&\n <TabLine showItems={showItems} disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n </div>\n );\n}\n\ninterface TabLineProps {\n disabledKeys: Iterable<Key> | undefined,\n isDisabled: boolean | undefined,\n selectedTab: HTMLElement | undefined,\n orientation?: Orientation,\n density?: 'compact' | 'regular',\n showItems?: boolean\n}\n\nconst selectedIndicator = style({\n position: 'absolute',\n backgroundColor: {\n default: 'neutral',\n isDisabled: 'disabled',\n forcedColors: {\n default: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n height: {\n orientation: {\n horizontal: '[2px]'\n }\n },\n width: {\n orientation: {\n vertical: '[2px]'\n }\n },\n bottom: {\n orientation: {\n horizontal: 0\n }\n },\n borderStyle: 'none',\n borderRadius: 'full',\n transitionDuration: 130,\n transitionTimingFunction: 'in-out'\n});\n\nfunction TabLine(props: TabLineProps & {isIconOnly?: boolean}) {\n let {\n disabledKeys,\n isDisabled: isTabsDisabled,\n selectedTab,\n orientation,\n density\n } = props;\n let {direction} = useLocale();\n let state = useContext(TabListStateContext);\n\n let isDisabled = useMemo(() => {\n return isTabsDisabled || isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys, isTabsDisabled]);\n\n let [style, setStyle] = useState<{transform: string | undefined, width: string | undefined, height: string | undefined}>({\n transform: undefined,\n width: undefined,\n height: undefined\n });\n\n let onResize = useCallback(() => {\n if (selectedTab) {\n let styleObj: { transform: string | undefined, width: string | undefined, height: string | undefined } = {\n transform: undefined,\n width: undefined,\n height: undefined\n };\n\n // In RTL, calculate the transform from the right edge of the tablist so that resizing the window doesn't break the Tabline position due to offsetLeft changes\n let offset = direction === 'rtl' ? -1 * ((selectedTab.offsetParent as HTMLElement)?.offsetWidth - selectedTab.offsetWidth - selectedTab.offsetLeft) : selectedTab.offsetLeft;\n styleObj.transform = orientation === 'vertical'\n ? `translateY(${selectedTab.offsetTop}px)`\n : `translateX(${offset}px)`;\n\n if (orientation === 'horizontal') {\n styleObj.width = `${selectedTab.offsetWidth}px`;\n } else {\n styleObj.height = `${selectedTab.offsetHeight}px`;\n }\n setStyle(styleObj);\n }\n }, [direction, setStyle, selectedTab, orientation]);\n\n useLayoutEffect(() => {\n onResize();\n }, [onResize, state?.selectedItem?.key, density]);\n\n let ref = useRef<HTMLElement | undefined>(selectedTab);\n // assign ref before the useResizeObserver useEffect runs\n useLayoutEffect(() => {\n ref.current = selectedTab;\n });\n useResizeObserver({ref, onResize});\n\n return (\n <div style={{...style}} className={selectedIndicator({isDisabled, orientation})} />\n );\n}\n\nconst tab = style({\n ...focusRing(),\n display: 'flex',\n color: {\n default: 'neutral-subdued',\n isSelected: 'neutral',\n isHovered: 'neutral-subdued',\n isDisabled: 'disabled',\n forcedColors: {\n isSelected: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n borderRadius: 'sm',\n gap: 'text-to-visual',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n },\n alignItems: 'center',\n position: 'relative',\n cursor: 'default',\n flexShrink: 0,\n transition: 'default',\n paddingX: {\n isIconOnly: size(6)\n }\n}, getAllowedOverrides());\n\nconst icon = style({\n display: 'block',\n flexShrink: 0,\n '--iconPrimary': {\n type: 'fill',\n value: 'currentColor'\n }\n});\n\nexport function Tab(props: TabProps) {\n let {density, isIconOnly} = useContext(InternalTabsContext) ?? {};\n\n return (\n <RACTab\n {...props}\n // @ts-ignore\n originalProps={props}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tab({...renderProps, density, isIconOnly}, props.styles)}>\n {({\n // @ts-ignore\n isMenu\n }) => {\n if (isMenu) {\n return props.children;\n } else {\n return (\n <Provider\n values={[\n [TextContext, {\n styles:\n style({\n order: 1,\n display: {\n isIconOnly: 'none'\n }\n })({isIconOnly})\n }],\n [IconContext, {\n render: centerBaseline({slot: 'icon', styles: style({order: 0})}),\n styles: icon\n }]\n ]}>\n {typeof props.children === 'string' ? <Text>{props.children}</Text> : props.children}\n </Provider>\n );\n }\n }}\n </RACTab>\n );\n}\n\nconst tabPanel = style({\n marginTop: 4,\n color: 'gray-800',\n flexGrow: 1,\n flexBasis: '[0%]',\n minHeight: 0,\n minWidth: 0\n}, getAllowedOverrides({height: true}));\n\nexport function TabPanel(props: TabPanelProps) {\n return (\n <AriaTabPanel\n {...props}\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + tabPanel(null, props.styles)} />\n );\n}\n\nfunction isAllTabsDisabled<T>(collection: Collection<Node<T>> | undefined, disabledKeys: Set<Key>) {\n let testKey: Key | null = null;\n if (collection && collection.size > 0) {\n testKey = collection.getFirstKey();\n\n let index = 0;\n while (testKey && index < collection.size) {\n // We have to check if the item in the collection has a key in disabledKeys or has the isDisabled prop set directly on it\n if (!disabledKeys.has(testKey) && !collection.getItem(testKey)?.props?.isDisabled) {\n return false;\n }\n\n testKey = collection.getKeyAfter(testKey);\n index++;\n }\n return true;\n }\n return false;\n}\n\nlet HiddenTabs = function (props: {\n listRef: RefObject<HTMLDivElement | null>,\n items: Array<Node<any>>,\n size?: string,\n density?: 'compact' | 'regular'\n}) {\n let {listRef, items, size, density} = props;\n\n return (\n <div\n // @ts-ignore\n inert=\"true\"\n ref={listRef}\n className={style({\n display: '[inherit]',\n flexDirection: '[inherit]',\n gap: '[inherit]',\n flexWrap: '[inherit]',\n position: 'absolute',\n inset: 0,\n visibility: 'hidden',\n overflow: 'hidden',\n opacity: 0\n })}>\n {items.map((item) => {\n // pull off individual props as an allow list, don't want refs or other props getting through\n return (\n <div\n data-hidden-tab\n style={item.props.UNSAFE_style}\n key={item.key}\n className={item.props.className({size, density})}>\n {item.props.children({size, density})}\n </div>\n );\n })}\n </div>\n );\n};\n\nlet TabsMenu = (props: {items: Array<Node<any>>, onSelectionChange: TabsProps['onSelectionChange']}) => {\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/s2');\n let {items} = props;\n let {density, onSelectionChange, selectedKey, isDisabled, disabledKeys, pickerRef, isIconOnly} = useContext(InternalTabsContext);\n let state = useContext(TabListStateContext);\n let allKeysDisabled = useMemo(() => {\n return isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys]);\n\n return (\n <UNSTABLE_CollectionRendererContext.Provider value={UNSTABLE_DefaultCollectionRenderer}>\n <div\n className={style({\n display: 'flex',\n alignItems: 'center',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n }})({density})}>\n <Picker\n ref={pickerRef ? pickerRef : undefined}\n isDisabled={isDisabled || allKeysDisabled}\n density={density!}\n isIconOnly={isIconOnly}\n items={items}\n disabledKeys={disabledKeys}\n selectedKey={selectedKey}\n onSelectionChange={onSelectionChange}\n aria-label={stringFormatter.format('tabs.selectorLabel')}>\n {(item: Node<any>) => {\n // need to determine the best way to handle icon only -> icon and text\n // good enough to aria-label the picker item?\n return (\n <PickerItem\n {...item.props.originalProps}\n isDisabled={isDisabled || allKeysDisabled}\n key={item.key}>\n {item.props.children({density, isMenu: true})}\n </PickerItem>\n );\n }}\n </Picker>\n </div>\n </UNSTABLE_CollectionRendererContext.Provider>\n );\n};\n\n// Context for passing the count for the custom renderer\nlet CollapseContext = createContext<{\n containerRef: RefObject<HTMLDivElement | null>,\n showItems: boolean,\n setShowItems:(value: boolean) => void\n} | null>(null);\n\nfunction CollapsingCollection({children, containerRef}) {\n let [showItems, _setShowItems] = useState(true);\n let {orientation} = useContext(InternalTabsContext);\n let setShowItems = useCallback((value: boolean) => {\n if (orientation === 'vertical') {\n // if orientation is vertical, we always show the items\n _setShowItems(true);\n } else {\n _setShowItems(value);\n }\n }, [orientation]);\n let ctx = useMemo(() => ({\n containerRef,\n showItems: orientation === 'vertical' ? true : showItems,\n setShowItems\n }), [containerRef, showItems, setShowItems]);\n return (\n <CollapseContext.Provider value={ctx}>\n <UNSTABLE_CollectionRendererContext.Provider value={CollapsingCollectionRenderer}>\n {children}\n </UNSTABLE_CollectionRendererContext.Provider>\n </CollapseContext.Provider>\n );\n}\n\nlet CollapsingCollectionRenderer: CollectionRenderer = {\n CollectionRoot({collection}) {\n return useCollectionRender(collection);\n },\n CollectionBranch({collection}) {\n return useCollectionRender(collection);\n }\n};\n\n\nlet useCollectionRender = (collection: Collection<Node<unknown>>) => {\n let {containerRef, showItems, setShowItems} = useContext(CollapseContext) ?? {};\n let {density = 'regular', orientation = 'horizontal', onSelectionChange} = useContext(InternalTabsContext);\n let {direction} = useLocale();\n\n let children = useMemo(() => {\n let result: Node<any>[] = [];\n for (let key of collection.getKeys()) {\n result.push(collection.getItem(key)!);\n }\n return result;\n }, [collection]);\n\n let listRef = useRef<HTMLDivElement | null>(null);\n let updateOverflow = useEffectEvent(() => {\n if (orientation === 'vertical' || !listRef.current || !containerRef?.current) {\n return;\n }\n let container = listRef.current;\n let containerRect = container.getBoundingClientRect();\n let tabs = container.querySelectorAll('[data-hidden-tab]');\n let lastTab = tabs[tabs.length - 1];\n let lastTabRect = lastTab.getBoundingClientRect();\n if (direction === 'ltr') {\n setShowItems?.(lastTabRect.right <= containerRect.right);\n } else {\n setShowItems?.(lastTabRect.left >= containerRect.left);\n }\n });\n\n useResizeObserver({ref: containerRef, onResize: updateOverflow});\n\n useLayoutEffect(() => {\n if (collection.size > 0) {\n queueMicrotask(updateOverflow);\n }\n }, [collection.size, updateOverflow]);\n\n useEffect(() => {\n // Recalculate visible tags when fonts are loaded.\n document.fonts?.ready.then(() => updateOverflow());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <>\n <HiddenTabs items={children} density={density} listRef={listRef} />\n {showItems ? (\n children.map(node => <Fragment key={node.key}>{node.render?.(node)}</Fragment>)\n ) : (\n <>\n <TabsMenu items={children} onSelectionChange={onSelectionChange} />\n </>\n )}\n </>\n );\n};\n"],"names":[],"version":3,"file":"Tabs.cjs.map"}
package/dist/Tabs.css.map CHANGED
@@ -1 +1 @@
1
- {"mappings":"AC6Ea;EAAA;;;;EAAA;;;;EAAA;;;;;;EAAA;;;;EAyDG;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EA4FU;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EA2Fd;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EA+BC;;;;EAAA;;;;EAAA;;;;EA+BO;;;;EAAA;;;;EAQ4C;;;;EAa/C;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAmDA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAuCE;;;;EAAA;;;;EAAA;;;;EAAA;;;;;AA7ZN;EAAA;;;;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;;AAAA;EAAA;IAAA;;;;IAgPD;;;;IAAA;;;;;;AA3Fc;EAAA;IAAA;;;;IAAA;;;;IA2Fd;;;;IAAA;;;;IAAA;;;;;;AAAA","sources":["d333cabc54201ea1","packages/@react-spectrum/s2/src/Tabs.tsx"],"sourcesContent":["@import \"575a5a16650d7070\";\n@import \"7a0058ba44ec735a\";\n@import \"ea0c0ad20f1e1c01\";\n@import \"1a91a7d853a67795\";\n@import \"b645d7882760dc18\";\n@import \"5aa00674bbf9e612\";\n@import \"9d65793a05791106\";\n@import \"2976d7d1f8a0759d\";\n@import \"713e94facc5ee3f3\";\n@import \"64129d49d07323ce\";\n@import \"5458e36ec7f2a11f\";\n","/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n TabListProps as AriaTabListProps,\n TabPanel as AriaTabPanel,\n TabPanelProps as AriaTabPanelProps,\n TabProps as AriaTabProps,\n TabsProps as AriaTabsProps,\n CollectionRenderer,\n ContextValue,\n Provider,\n Tab as RACTab,\n TabList as RACTabList,\n Tabs as RACTabs,\n TabListStateContext,\n UNSTABLE_CollectionRendererContext,\n UNSTABLE_DefaultCollectionRenderer\n} from 'react-aria-components';\nimport {centerBaseline} from './CenterBaseline';\nimport {Collection, DOMRef, DOMRefValue, FocusableRef, FocusableRefValue, Key, Node, Orientation, RefObject} from '@react-types/shared';\nimport {createContext, forwardRef, Fragment, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';\nimport {focusRing, size, style} from '../style' with {type: 'macro'};\nimport {getAllowedOverrides, StyleProps, StylesPropWithHeight, UnsafeStyles} from './style-utils' with {type: 'macro'};\nimport {IconContext} from './Icon';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {Picker, PickerItem} from './TabsPicker';\nimport {Text, TextContext} from './Content';\nimport {useControlledState} from '@react-stately/utils';\nimport {useDOMRef} from '@react-spectrum/utils';\nimport {useEffectEvent, useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale, useLocalizedStringFormatter} from '@react-aria/i18n';\nimport {useSpectrumContextProps} from './useSpectrumContextProps';\n\nexport interface TabsProps extends Omit<AriaTabsProps, 'className' | 'style' | 'children'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tabs. */\n children?: ReactNode,\n /**\n * The amount of space between the tabs.\n * @default 'regular'\n */\n density?: 'compact' | 'regular',\n /**\n * If the tabs should only display icons and no text.\n */\n isIconOnly?: boolean\n}\n\nexport interface TabProps extends Omit<AriaTabProps, 'children' | 'style' | 'className'>, StyleProps {\n /** The content to display in the tab. */\n children: ReactNode\n}\n\nexport interface TabListProps<T> extends Omit<AriaTabListProps<T>, 'style' | 'className'>, StyleProps {}\n\nexport interface TabPanelProps extends Omit<AriaTabPanelProps, 'children' | 'style' | 'className'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tab panels. */\n children?: ReactNode\n}\n\nexport const TabsContext = createContext<ContextValue<TabsProps, DOMRefValue<HTMLDivElement>>>(null);\nconst InternalTabsContext = createContext<TabsProps & {onFocus:() => void, pickerRef?: FocusableRef<HTMLButtonElement>}>({onFocus: () => {}});\n\nconst tabs = style({\n display: 'flex',\n flexShrink: 0,\n font: 'ui',\n flexDirection: {\n orientation: {\n horizontal: 'column'\n }\n }\n}, getAllowedOverrides({height: true}));\n\n/**\n * Tabs organize content into multiple sections and allow users to navigate between them. The content under the set of tabs should be related and form a coherent unit.\n */\nexport const Tabs = forwardRef(function Tabs(props: TabsProps, ref: DOMRef<HTMLDivElement>) {\n [props, ref] = useSpectrumContextProps(props, ref, TabsContext);\n let {\n density = 'regular',\n isDisabled,\n disabledKeys,\n orientation = 'horizontal',\n isIconOnly = false\n } = props;\n let domRef = useDOMRef(ref);\n let [value, setValue] = useControlledState(props.selectedKey, props.defaultSelectedKey ?? null!, props.onSelectionChange);\n let pickerRef = useRef<FocusableRefValue<HTMLButtonElement>>(null);\n\n return (\n <Provider\n values={[\n [InternalTabsContext, {\n density,\n isDisabled,\n orientation,\n disabledKeys,\n selectedKey: value,\n onSelectionChange: setValue,\n isIconOnly,\n onFocus: () => pickerRef.current?.focus(),\n pickerRef\n }]\n ]}>\n <CollapsingCollection containerRef={domRef}>\n <RACTabs\n {...props}\n ref={domRef}\n selectedKey={value}\n onSelectionChange={setValue}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tabs({...renderProps}, props.styles)}>\n {props.children}\n </RACTabs>\n </CollapsingCollection>\n </Provider>\n );\n});\n\nconst tablist = style({\n display: 'flex',\n gap: {\n orientation: {\n horizontal: {\n density: {\n compact: 24,\n regular: 32\n },\n isIconOnly: {\n density: {\n compact: 16,\n regular: 24\n }\n }\n }\n }\n },\n flexDirection: {\n orientation: {\n vertical: 'column'\n }\n },\n paddingEnd: {\n orientation: {\n vertical: 20\n }\n },\n paddingStart: {\n orientation: {\n vertical: 12\n }\n },\n flexShrink: 0,\n flexBasis: '[0%]'\n});\n\nexport function TabList<T extends object>(props: TabListProps<T>) {\n let {density, isDisabled, disabledKeys, orientation, isIconOnly, onFocus} = useContext(InternalTabsContext) ?? {};\n let {showItems} = useContext(CollapseContext) ?? {};\n let state = useContext(TabListStateContext);\n let [selectedTab, setSelectedTab] = useState<HTMLElement | undefined>(undefined);\n let tablistRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (tablistRef?.current && showItems) {\n let tab: HTMLElement | null = tablistRef.current.querySelector('[role=tab][data-selected=true]');\n\n if (tab != null) {\n setSelectedTab(tab);\n }\n } else if (tablistRef?.current) {\n let picker: HTMLElement | null = tablistRef.current.querySelector('button');\n if (picker != null) {\n setSelectedTab(picker);\n }\n }\n }, [tablistRef, state?.selectedItem?.key, showItems]);\n\n let prevFocused = useRef<boolean | undefined>(false);\n useLayoutEffect(() => {\n if (!showItems && !prevFocused.current && state?.selectionManager.isFocused) {\n onFocus();\n }\n prevFocused.current = state?.selectionManager.isFocused;\n }, [state?.selectionManager.isFocused, state?.selectionManager.focusedKey, showItems]);\n\n return (\n <div\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + style({position: 'relative'}, getAllowedOverrides())(null, props.styles)}>\n {showItems && orientation === 'vertical' &&\n <TabLine disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n <RACTabList\n {...props}\n ref={tablistRef}\n className={renderProps => tablist({...renderProps, isIconOnly, density})} />\n {orientation === 'horizontal' &&\n <TabLine showItems={showItems} disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n </div>\n );\n}\n\ninterface TabLineProps {\n disabledKeys: Iterable<Key> | undefined,\n isDisabled: boolean | undefined,\n selectedTab: HTMLElement | undefined,\n orientation?: Orientation,\n density?: 'compact' | 'regular',\n showItems?: boolean\n}\n\nconst selectedIndicator = style({\n position: 'absolute',\n backgroundColor: {\n default: 'neutral',\n isDisabled: 'disabled',\n forcedColors: {\n default: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n height: {\n orientation: {\n horizontal: '[2px]'\n }\n },\n width: {\n orientation: {\n vertical: '[2px]'\n }\n },\n bottom: {\n orientation: {\n horizontal: 0\n }\n },\n borderStyle: 'none',\n borderRadius: 'full',\n transitionDuration: 130,\n transitionTimingFunction: 'in-out'\n});\n\nfunction TabLine(props: TabLineProps & {isIconOnly?: boolean}) {\n let {\n disabledKeys,\n isDisabled: isTabsDisabled,\n selectedTab,\n orientation,\n density\n } = props;\n let {direction} = useLocale();\n let state = useContext(TabListStateContext);\n\n let isDisabled = useMemo(() => {\n return isTabsDisabled || isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys, isTabsDisabled]);\n\n let [style, setStyle] = useState<{transform: string | undefined, width: string | undefined, height: string | undefined}>({\n transform: undefined,\n width: undefined,\n height: undefined\n });\n\n let onResize = useCallback(() => {\n if (selectedTab) {\n let styleObj: { transform: string | undefined, width: string | undefined, height: string | undefined } = {\n transform: undefined,\n width: undefined,\n height: undefined\n };\n\n // In RTL, calculate the transform from the right edge of the tablist so that resizing the window doesn't break the Tabline position due to offsetLeft changes\n let offset = direction === 'rtl' ? -1 * ((selectedTab.offsetParent as HTMLElement)?.offsetWidth - selectedTab.offsetWidth - selectedTab.offsetLeft) : selectedTab.offsetLeft;\n styleObj.transform = orientation === 'vertical'\n ? `translateY(${selectedTab.offsetTop}px)`\n : `translateX(${offset}px)`;\n\n if (orientation === 'horizontal') {\n styleObj.width = `${selectedTab.offsetWidth}px`;\n } else {\n styleObj.height = `${selectedTab.offsetHeight}px`;\n }\n setStyle(styleObj);\n }\n }, [direction, setStyle, selectedTab, orientation]);\n\n useLayoutEffect(() => {\n onResize();\n }, [onResize, state?.selectedItem?.key, density]);\n\n let ref = useRef<HTMLElement | undefined>(selectedTab);\n // assign ref before the useResizeObserver useEffect runs\n useLayoutEffect(() => {\n ref.current = selectedTab;\n });\n useResizeObserver({ref, onResize});\n\n return (\n <div style={{...style}} className={selectedIndicator({isDisabled, orientation})} />\n );\n}\n\nconst tab = style({\n ...focusRing(),\n display: 'flex',\n color: {\n default: 'neutral-subdued',\n isSelected: 'neutral',\n isHovered: 'neutral-subdued',\n isDisabled: 'disabled',\n forcedColors: {\n isSelected: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n borderRadius: 'sm',\n gap: 'text-to-visual',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n },\n alignItems: 'center',\n position: 'relative',\n cursor: 'default',\n flexShrink: 0,\n transition: 'default',\n paddingX: {\n isIconOnly: size(6)\n }\n}, getAllowedOverrides());\n\nconst icon = style({\n display: 'block',\n flexShrink: 0,\n '--iconPrimary': {\n type: 'fill',\n value: 'currentColor'\n }\n});\n\nexport function Tab(props: TabProps) {\n let {density, isIconOnly} = useContext(InternalTabsContext) ?? {};\n\n return (\n <RACTab\n {...props}\n // @ts-ignore\n originalProps={props}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tab({...renderProps, density, isIconOnly}, props.styles)}>\n {({\n // @ts-ignore\n isMenu\n }) => {\n if (isMenu) {\n return props.children;\n } else {\n return (\n <Provider\n values={[\n [TextContext, {\n styles:\n style({\n order: 1,\n display: {\n isIconOnly: 'none'\n }\n })({isIconOnly})\n }],\n [IconContext, {\n render: centerBaseline({slot: 'icon', styles: style({order: 0})}),\n styles: icon\n }]\n ]}>\n {typeof props.children === 'string' ? <Text>{props.children}</Text> : props.children}\n </Provider>\n );\n }\n }}\n </RACTab>\n );\n}\n\nconst tabPanel = style({\n marginTop: 4,\n color: 'gray-800',\n flexGrow: 1,\n flexBasis: '[0%]',\n minHeight: 0,\n minWidth: 0\n}, getAllowedOverrides({height: true}));\n\nexport function TabPanel(props: TabPanelProps) {\n return (\n <AriaTabPanel\n {...props}\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + tabPanel(null, props.styles)} />\n );\n}\n\nfunction isAllTabsDisabled<T>(collection: Collection<Node<T>> | undefined, disabledKeys: Set<Key>) {\n let testKey: Key | null = null;\n if (collection && collection.size > 0) {\n testKey = collection.getFirstKey();\n\n let index = 0;\n while (testKey && index < collection.size) {\n // We have to check if the item in the collection has a key in disabledKeys or has the isDisabled prop set directly on it\n if (!disabledKeys.has(testKey) && !collection.getItem(testKey)?.props?.isDisabled) {\n return false;\n }\n\n testKey = collection.getKeyAfter(testKey);\n index++;\n }\n return true;\n }\n return false;\n}\n\nlet HiddenTabs = function (props: {\n listRef: RefObject<HTMLDivElement | null>,\n items: Array<Node<any>>,\n size?: string,\n density?: 'compact' | 'regular'\n}) {\n let {listRef, items, size, density} = props;\n\n return (\n <div\n // @ts-ignore\n inert=\"true\"\n ref={listRef}\n className={style({\n display: '[inherit]',\n flexDirection: '[inherit]',\n gap: '[inherit]',\n flexWrap: '[inherit]',\n position: 'absolute',\n inset: 0,\n visibility: 'hidden',\n overflow: 'hidden',\n opacity: 0\n })}>\n {items.map((item) => {\n // pull off individual props as an allow list, don't want refs or other props getting through\n return (\n <div\n data-hidden-tab\n style={item.props.UNSAFE_style}\n key={item.key}\n className={item.props.className({size, density})}>\n {item.props.children({size, density})}\n </div>\n );\n })}\n </div>\n );\n};\n\nlet TabsMenu = (props: {items: Array<Node<any>>, onSelectionChange: TabsProps['onSelectionChange']}) => {\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/s2');\n let {items} = props;\n let {density, onSelectionChange, selectedKey, isDisabled, disabledKeys, pickerRef, isIconOnly} = useContext(InternalTabsContext);\n let state = useContext(TabListStateContext);\n let allKeysDisabled = useMemo(() => {\n return isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys]);\n\n return (\n <UNSTABLE_CollectionRendererContext.Provider value={UNSTABLE_DefaultCollectionRenderer}>\n <div\n className={style({\n display: 'flex',\n alignItems: 'center',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n }})({density})}>\n <Picker\n ref={pickerRef ? pickerRef : undefined}\n isDisabled={isDisabled || allKeysDisabled}\n density={density!}\n isIconOnly={isIconOnly}\n items={items}\n disabledKeys={disabledKeys}\n selectedKey={selectedKey}\n onSelectionChange={onSelectionChange}\n aria-label={stringFormatter.format('tabs.selectorLabel')}>\n {(item: Node<any>) => {\n // need to determine the best way to handle icon only -> icon and text\n // good enough to aria-label the picker item?\n return (\n <PickerItem\n {...item.props.originalProps}\n isDisabled={isDisabled || allKeysDisabled}\n key={item.key}>\n {item.props.children({density, isMenu: true})}\n </PickerItem>\n );\n }}\n </Picker>\n </div>\n </UNSTABLE_CollectionRendererContext.Provider>\n );\n};\n\n// Context for passing the count for the custom renderer\nlet CollapseContext = createContext<{\n containerRef: RefObject<HTMLDivElement | null>,\n showItems: boolean,\n setShowItems:(value: boolean) => void\n} | null>(null);\n\nfunction CollapsingCollection({children, containerRef}) {\n let [showItems, _setShowItems] = useState(true);\n let {orientation} = useContext(InternalTabsContext);\n let setShowItems = useCallback((value: boolean) => {\n if (orientation === 'vertical') {\n // if orientation is vertical, we always show the items\n _setShowItems(true);\n } else {\n _setShowItems(value);\n }\n }, [orientation]);\n return (\n <CollapseContext.Provider value={{containerRef, showItems: orientation === 'vertical' ? true : showItems, setShowItems}}>\n <UNSTABLE_CollectionRendererContext.Provider value={CollapsingCollectionRenderer}>\n {children}\n </UNSTABLE_CollectionRendererContext.Provider>\n </CollapseContext.Provider>\n );\n}\n\nlet CollapsingCollectionRenderer: CollectionRenderer = {\n CollectionRoot({collection}) {\n return useCollectionRender(collection);\n },\n CollectionBranch({collection}) {\n return useCollectionRender(collection);\n }\n};\n\n\nlet useCollectionRender = (collection: Collection<Node<unknown>>) => {\n let {containerRef, showItems, setShowItems} = useContext(CollapseContext) ?? {};\n let {density = 'regular', orientation = 'horizontal', onSelectionChange} = useContext(InternalTabsContext);\n let {direction} = useLocale();\n\n let children = useMemo(() => {\n let result: Node<any>[] = [];\n for (let key of collection.getKeys()) {\n result.push(collection.getItem(key)!);\n }\n return result;\n }, [collection]);\n\n let listRef = useRef<HTMLDivElement | null>(null);\n let updateOverflow = useEffectEvent(() => {\n if (orientation === 'vertical' || !listRef.current || !containerRef?.current) {\n return;\n }\n let container = listRef.current;\n let containerRect = container.getBoundingClientRect();\n let tabs = container.querySelectorAll('[data-hidden-tab]');\n let lastTab = tabs[tabs.length - 1];\n let lastTabRect = lastTab.getBoundingClientRect();\n if (direction === 'ltr') {\n setShowItems?.(lastTabRect.right <= containerRect.right);\n } else {\n setShowItems?.(lastTabRect.left >= containerRect.left);\n }\n });\n\n useResizeObserver({ref: containerRef, onResize: updateOverflow});\n\n useLayoutEffect(() => {\n if (collection.size > 0) {\n queueMicrotask(updateOverflow);\n }\n }, [collection.size, updateOverflow]);\n\n useEffect(() => {\n // Recalculate visible tags when fonts are loaded.\n document.fonts?.ready.then(() => updateOverflow());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <>\n <HiddenTabs items={children} density={density} listRef={listRef} />\n {showItems ? (\n children.map(node => <Fragment key={node.key}>{node.render?.(node)}</Fragment>)\n ) : (\n <>\n <TabsMenu items={children} onSelectionChange={onSelectionChange} />\n </>\n )}\n </>\n );\n};\n"],"names":[],"version":3,"file":"Tabs.css.map"}
1
+ {"mappings":"AC6Ea;EAAA;;;;EAAA;;;;EAAA;;;;;;EAAA;;;;EAyDG;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EA4FU;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EA2Fd;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EA+BC;;;;EAAA;;;;EAAA;;;;EA+BO;;;;EAAA;;;;EAQ4C;;;;EAa/C;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAmDA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAAA;;;;EAuCE;;;;EAAA;;;;EAAA;;;;EAAA;;;;;AA7ZN;EAAA;;;;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;EAAA;;;;;AAAA;;AAAA;EAAA;IAAA;;;;IAgPD;;;;IAAA;;;;;;AA3Fc;EAAA;IAAA;;;;IAAA;;;;IA2Fd;;;;IAAA;;;;IAAA;;;;;;AAAA","sources":["d333cabc54201ea1","packages/@react-spectrum/s2/src/Tabs.tsx"],"sourcesContent":["@import \"575a5a16650d7070\";\n@import \"7a0058ba44ec735a\";\n@import \"ea0c0ad20f1e1c01\";\n@import \"1a91a7d853a67795\";\n@import \"b645d7882760dc18\";\n@import \"5aa00674bbf9e612\";\n@import \"9d65793a05791106\";\n@import \"2976d7d1f8a0759d\";\n@import \"713e94facc5ee3f3\";\n@import \"64129d49d07323ce\";\n@import \"5458e36ec7f2a11f\";\n","/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n TabListProps as AriaTabListProps,\n TabPanel as AriaTabPanel,\n TabPanelProps as AriaTabPanelProps,\n TabProps as AriaTabProps,\n TabsProps as AriaTabsProps,\n CollectionRenderer,\n ContextValue,\n Provider,\n Tab as RACTab,\n TabList as RACTabList,\n Tabs as RACTabs,\n TabListStateContext,\n UNSTABLE_CollectionRendererContext,\n UNSTABLE_DefaultCollectionRenderer\n} from 'react-aria-components';\nimport {centerBaseline} from './CenterBaseline';\nimport {Collection, DOMRef, DOMRefValue, FocusableRef, FocusableRefValue, Key, Node, Orientation, RefObject} from '@react-types/shared';\nimport {createContext, forwardRef, Fragment, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';\nimport {focusRing, size, style} from '../style' with {type: 'macro'};\nimport {getAllowedOverrides, StyleProps, StylesPropWithHeight, UnsafeStyles} from './style-utils' with {type: 'macro'};\nimport {IconContext} from './Icon';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {Picker, PickerItem} from './TabsPicker';\nimport {Text, TextContext} from './Content';\nimport {useControlledState} from '@react-stately/utils';\nimport {useDOMRef} from '@react-spectrum/utils';\nimport {useEffectEvent, useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale, useLocalizedStringFormatter} from '@react-aria/i18n';\nimport {useSpectrumContextProps} from './useSpectrumContextProps';\n\nexport interface TabsProps extends Omit<AriaTabsProps, 'className' | 'style' | 'children'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tabs. */\n children?: ReactNode,\n /**\n * The amount of space between the tabs.\n * @default 'regular'\n */\n density?: 'compact' | 'regular',\n /**\n * If the tabs should only display icons and no text.\n */\n isIconOnly?: boolean\n}\n\nexport interface TabProps extends Omit<AriaTabProps, 'children' | 'style' | 'className'>, StyleProps {\n /** The content to display in the tab. */\n children: ReactNode\n}\n\nexport interface TabListProps<T> extends Omit<AriaTabListProps<T>, 'style' | 'className'>, StyleProps {}\n\nexport interface TabPanelProps extends Omit<AriaTabPanelProps, 'children' | 'style' | 'className'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tab panels. */\n children?: ReactNode\n}\n\nexport const TabsContext = createContext<ContextValue<TabsProps, DOMRefValue<HTMLDivElement>>>(null);\nconst InternalTabsContext = createContext<TabsProps & {onFocus:() => void, pickerRef?: FocusableRef<HTMLButtonElement>}>({onFocus: () => {}});\n\nconst tabs = style({\n display: 'flex',\n flexShrink: 0,\n font: 'ui',\n flexDirection: {\n orientation: {\n horizontal: 'column'\n }\n }\n}, getAllowedOverrides({height: true}));\n\n/**\n * Tabs organize content into multiple sections and allow users to navigate between them. The content under the set of tabs should be related and form a coherent unit.\n */\nexport const Tabs = forwardRef(function Tabs(props: TabsProps, ref: DOMRef<HTMLDivElement>) {\n [props, ref] = useSpectrumContextProps(props, ref, TabsContext);\n let {\n density = 'regular',\n isDisabled,\n disabledKeys,\n orientation = 'horizontal',\n isIconOnly = false\n } = props;\n let domRef = useDOMRef(ref);\n let [value, setValue] = useControlledState(props.selectedKey, props.defaultSelectedKey ?? null!, props.onSelectionChange);\n let pickerRef = useRef<FocusableRefValue<HTMLButtonElement>>(null);\n\n return (\n <Provider\n values={[\n [InternalTabsContext, {\n density,\n isDisabled,\n orientation,\n disabledKeys,\n selectedKey: value,\n onSelectionChange: setValue,\n isIconOnly,\n onFocus: () => pickerRef.current?.focus(),\n pickerRef\n }]\n ]}>\n <CollapsingCollection containerRef={domRef}>\n <RACTabs\n {...props}\n ref={domRef}\n selectedKey={value}\n onSelectionChange={setValue}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tabs({...renderProps}, props.styles)}>\n {props.children}\n </RACTabs>\n </CollapsingCollection>\n </Provider>\n );\n});\n\nconst tablist = style({\n display: 'flex',\n gap: {\n orientation: {\n horizontal: {\n density: {\n compact: 24,\n regular: 32\n },\n isIconOnly: {\n density: {\n compact: 16,\n regular: 24\n }\n }\n }\n }\n },\n flexDirection: {\n orientation: {\n vertical: 'column'\n }\n },\n paddingEnd: {\n orientation: {\n vertical: 20\n }\n },\n paddingStart: {\n orientation: {\n vertical: 12\n }\n },\n flexShrink: 0,\n flexBasis: '[0%]'\n});\n\nexport function TabList<T extends object>(props: TabListProps<T>) {\n let {density, isDisabled, disabledKeys, orientation, isIconOnly, onFocus} = useContext(InternalTabsContext) ?? {};\n let {showItems} = useContext(CollapseContext) ?? {};\n let state = useContext(TabListStateContext);\n let [selectedTab, setSelectedTab] = useState<HTMLElement | undefined>(undefined);\n let tablistRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (tablistRef?.current && showItems) {\n let tab: HTMLElement | null = tablistRef.current.querySelector('[role=tab][data-selected=true]');\n\n if (tab != null) {\n setSelectedTab(tab);\n }\n } else if (tablistRef?.current) {\n let picker: HTMLElement | null = tablistRef.current.querySelector('button');\n if (picker != null) {\n setSelectedTab(picker);\n }\n }\n }, [tablistRef, state?.selectedItem?.key, showItems]);\n\n let prevFocused = useRef<boolean | undefined>(false);\n useLayoutEffect(() => {\n if (!showItems && !prevFocused.current && state?.selectionManager.isFocused) {\n onFocus();\n }\n prevFocused.current = state?.selectionManager.isFocused;\n }, [state?.selectionManager.isFocused, state?.selectionManager.focusedKey, showItems]);\n\n return (\n <div\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + style({position: 'relative'}, getAllowedOverrides())(null, props.styles)}>\n {showItems && orientation === 'vertical' &&\n <TabLine disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n <RACTabList\n {...props}\n ref={tablistRef}\n className={renderProps => tablist({...renderProps, isIconOnly, density})} />\n {orientation === 'horizontal' &&\n <TabLine showItems={showItems} disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n </div>\n );\n}\n\ninterface TabLineProps {\n disabledKeys: Iterable<Key> | undefined,\n isDisabled: boolean | undefined,\n selectedTab: HTMLElement | undefined,\n orientation?: Orientation,\n density?: 'compact' | 'regular',\n showItems?: boolean\n}\n\nconst selectedIndicator = style({\n position: 'absolute',\n backgroundColor: {\n default: 'neutral',\n isDisabled: 'disabled',\n forcedColors: {\n default: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n height: {\n orientation: {\n horizontal: '[2px]'\n }\n },\n width: {\n orientation: {\n vertical: '[2px]'\n }\n },\n bottom: {\n orientation: {\n horizontal: 0\n }\n },\n borderStyle: 'none',\n borderRadius: 'full',\n transitionDuration: 130,\n transitionTimingFunction: 'in-out'\n});\n\nfunction TabLine(props: TabLineProps & {isIconOnly?: boolean}) {\n let {\n disabledKeys,\n isDisabled: isTabsDisabled,\n selectedTab,\n orientation,\n density\n } = props;\n let {direction} = useLocale();\n let state = useContext(TabListStateContext);\n\n let isDisabled = useMemo(() => {\n return isTabsDisabled || isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys, isTabsDisabled]);\n\n let [style, setStyle] = useState<{transform: string | undefined, width: string | undefined, height: string | undefined}>({\n transform: undefined,\n width: undefined,\n height: undefined\n });\n\n let onResize = useCallback(() => {\n if (selectedTab) {\n let styleObj: { transform: string | undefined, width: string | undefined, height: string | undefined } = {\n transform: undefined,\n width: undefined,\n height: undefined\n };\n\n // In RTL, calculate the transform from the right edge of the tablist so that resizing the window doesn't break the Tabline position due to offsetLeft changes\n let offset = direction === 'rtl' ? -1 * ((selectedTab.offsetParent as HTMLElement)?.offsetWidth - selectedTab.offsetWidth - selectedTab.offsetLeft) : selectedTab.offsetLeft;\n styleObj.transform = orientation === 'vertical'\n ? `translateY(${selectedTab.offsetTop}px)`\n : `translateX(${offset}px)`;\n\n if (orientation === 'horizontal') {\n styleObj.width = `${selectedTab.offsetWidth}px`;\n } else {\n styleObj.height = `${selectedTab.offsetHeight}px`;\n }\n setStyle(styleObj);\n }\n }, [direction, setStyle, selectedTab, orientation]);\n\n useLayoutEffect(() => {\n onResize();\n }, [onResize, state?.selectedItem?.key, density]);\n\n let ref = useRef<HTMLElement | undefined>(selectedTab);\n // assign ref before the useResizeObserver useEffect runs\n useLayoutEffect(() => {\n ref.current = selectedTab;\n });\n useResizeObserver({ref, onResize});\n\n return (\n <div style={{...style}} className={selectedIndicator({isDisabled, orientation})} />\n );\n}\n\nconst tab = style({\n ...focusRing(),\n display: 'flex',\n color: {\n default: 'neutral-subdued',\n isSelected: 'neutral',\n isHovered: 'neutral-subdued',\n isDisabled: 'disabled',\n forcedColors: {\n isSelected: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n borderRadius: 'sm',\n gap: 'text-to-visual',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n },\n alignItems: 'center',\n position: 'relative',\n cursor: 'default',\n flexShrink: 0,\n transition: 'default',\n paddingX: {\n isIconOnly: size(6)\n }\n}, getAllowedOverrides());\n\nconst icon = style({\n display: 'block',\n flexShrink: 0,\n '--iconPrimary': {\n type: 'fill',\n value: 'currentColor'\n }\n});\n\nexport function Tab(props: TabProps) {\n let {density, isIconOnly} = useContext(InternalTabsContext) ?? {};\n\n return (\n <RACTab\n {...props}\n // @ts-ignore\n originalProps={props}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tab({...renderProps, density, isIconOnly}, props.styles)}>\n {({\n // @ts-ignore\n isMenu\n }) => {\n if (isMenu) {\n return props.children;\n } else {\n return (\n <Provider\n values={[\n [TextContext, {\n styles:\n style({\n order: 1,\n display: {\n isIconOnly: 'none'\n }\n })({isIconOnly})\n }],\n [IconContext, {\n render: centerBaseline({slot: 'icon', styles: style({order: 0})}),\n styles: icon\n }]\n ]}>\n {typeof props.children === 'string' ? <Text>{props.children}</Text> : props.children}\n </Provider>\n );\n }\n }}\n </RACTab>\n );\n}\n\nconst tabPanel = style({\n marginTop: 4,\n color: 'gray-800',\n flexGrow: 1,\n flexBasis: '[0%]',\n minHeight: 0,\n minWidth: 0\n}, getAllowedOverrides({height: true}));\n\nexport function TabPanel(props: TabPanelProps) {\n return (\n <AriaTabPanel\n {...props}\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + tabPanel(null, props.styles)} />\n );\n}\n\nfunction isAllTabsDisabled<T>(collection: Collection<Node<T>> | undefined, disabledKeys: Set<Key>) {\n let testKey: Key | null = null;\n if (collection && collection.size > 0) {\n testKey = collection.getFirstKey();\n\n let index = 0;\n while (testKey && index < collection.size) {\n // We have to check if the item in the collection has a key in disabledKeys or has the isDisabled prop set directly on it\n if (!disabledKeys.has(testKey) && !collection.getItem(testKey)?.props?.isDisabled) {\n return false;\n }\n\n testKey = collection.getKeyAfter(testKey);\n index++;\n }\n return true;\n }\n return false;\n}\n\nlet HiddenTabs = function (props: {\n listRef: RefObject<HTMLDivElement | null>,\n items: Array<Node<any>>,\n size?: string,\n density?: 'compact' | 'regular'\n}) {\n let {listRef, items, size, density} = props;\n\n return (\n <div\n // @ts-ignore\n inert=\"true\"\n ref={listRef}\n className={style({\n display: '[inherit]',\n flexDirection: '[inherit]',\n gap: '[inherit]',\n flexWrap: '[inherit]',\n position: 'absolute',\n inset: 0,\n visibility: 'hidden',\n overflow: 'hidden',\n opacity: 0\n })}>\n {items.map((item) => {\n // pull off individual props as an allow list, don't want refs or other props getting through\n return (\n <div\n data-hidden-tab\n style={item.props.UNSAFE_style}\n key={item.key}\n className={item.props.className({size, density})}>\n {item.props.children({size, density})}\n </div>\n );\n })}\n </div>\n );\n};\n\nlet TabsMenu = (props: {items: Array<Node<any>>, onSelectionChange: TabsProps['onSelectionChange']}) => {\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/s2');\n let {items} = props;\n let {density, onSelectionChange, selectedKey, isDisabled, disabledKeys, pickerRef, isIconOnly} = useContext(InternalTabsContext);\n let state = useContext(TabListStateContext);\n let allKeysDisabled = useMemo(() => {\n return isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys]);\n\n return (\n <UNSTABLE_CollectionRendererContext.Provider value={UNSTABLE_DefaultCollectionRenderer}>\n <div\n className={style({\n display: 'flex',\n alignItems: 'center',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n }})({density})}>\n <Picker\n ref={pickerRef ? pickerRef : undefined}\n isDisabled={isDisabled || allKeysDisabled}\n density={density!}\n isIconOnly={isIconOnly}\n items={items}\n disabledKeys={disabledKeys}\n selectedKey={selectedKey}\n onSelectionChange={onSelectionChange}\n aria-label={stringFormatter.format('tabs.selectorLabel')}>\n {(item: Node<any>) => {\n // need to determine the best way to handle icon only -> icon and text\n // good enough to aria-label the picker item?\n return (\n <PickerItem\n {...item.props.originalProps}\n isDisabled={isDisabled || allKeysDisabled}\n key={item.key}>\n {item.props.children({density, isMenu: true})}\n </PickerItem>\n );\n }}\n </Picker>\n </div>\n </UNSTABLE_CollectionRendererContext.Provider>\n );\n};\n\n// Context for passing the count for the custom renderer\nlet CollapseContext = createContext<{\n containerRef: RefObject<HTMLDivElement | null>,\n showItems: boolean,\n setShowItems:(value: boolean) => void\n} | null>(null);\n\nfunction CollapsingCollection({children, containerRef}) {\n let [showItems, _setShowItems] = useState(true);\n let {orientation} = useContext(InternalTabsContext);\n let setShowItems = useCallback((value: boolean) => {\n if (orientation === 'vertical') {\n // if orientation is vertical, we always show the items\n _setShowItems(true);\n } else {\n _setShowItems(value);\n }\n }, [orientation]);\n let ctx = useMemo(() => ({\n containerRef,\n showItems: orientation === 'vertical' ? true : showItems,\n setShowItems\n }), [containerRef, showItems, setShowItems]);\n return (\n <CollapseContext.Provider value={ctx}>\n <UNSTABLE_CollectionRendererContext.Provider value={CollapsingCollectionRenderer}>\n {children}\n </UNSTABLE_CollectionRendererContext.Provider>\n </CollapseContext.Provider>\n );\n}\n\nlet CollapsingCollectionRenderer: CollectionRenderer = {\n CollectionRoot({collection}) {\n return useCollectionRender(collection);\n },\n CollectionBranch({collection}) {\n return useCollectionRender(collection);\n }\n};\n\n\nlet useCollectionRender = (collection: Collection<Node<unknown>>) => {\n let {containerRef, showItems, setShowItems} = useContext(CollapseContext) ?? {};\n let {density = 'regular', orientation = 'horizontal', onSelectionChange} = useContext(InternalTabsContext);\n let {direction} = useLocale();\n\n let children = useMemo(() => {\n let result: Node<any>[] = [];\n for (let key of collection.getKeys()) {\n result.push(collection.getItem(key)!);\n }\n return result;\n }, [collection]);\n\n let listRef = useRef<HTMLDivElement | null>(null);\n let updateOverflow = useEffectEvent(() => {\n if (orientation === 'vertical' || !listRef.current || !containerRef?.current) {\n return;\n }\n let container = listRef.current;\n let containerRect = container.getBoundingClientRect();\n let tabs = container.querySelectorAll('[data-hidden-tab]');\n let lastTab = tabs[tabs.length - 1];\n let lastTabRect = lastTab.getBoundingClientRect();\n if (direction === 'ltr') {\n setShowItems?.(lastTabRect.right <= containerRect.right);\n } else {\n setShowItems?.(lastTabRect.left >= containerRect.left);\n }\n });\n\n useResizeObserver({ref: containerRef, onResize: updateOverflow});\n\n useLayoutEffect(() => {\n if (collection.size > 0) {\n queueMicrotask(updateOverflow);\n }\n }, [collection.size, updateOverflow]);\n\n useEffect(() => {\n // Recalculate visible tags when fonts are loaded.\n document.fonts?.ready.then(() => updateOverflow());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <>\n <HiddenTabs items={children} density={density} listRef={listRef} />\n {showItems ? (\n children.map(node => <Fragment key={node.key}>{node.render?.(node)}</Fragment>)\n ) : (\n <>\n <TabsMenu items={children} onSelectionChange={onSelectionChange} />\n </>\n )}\n </>\n );\n};\n"],"names":[],"version":3,"file":"Tabs.css.map"}
package/dist/Tabs.mjs CHANGED
@@ -521,12 +521,17 @@ function $79e2b4a1b34d1592$var$CollapsingCollection({ children: children, contai
521
521
  }, [
522
522
  orientation
523
523
  ]);
524
- return /*#__PURE__*/ (0, $8bRfI$jsx)($79e2b4a1b34d1592$var$CollapseContext.Provider, {
525
- value: {
524
+ let ctx = (0, $8bRfI$useMemo)(()=>({
526
525
  containerRef: containerRef,
527
526
  showItems: orientation === 'vertical' ? true : showItems,
528
527
  setShowItems: setShowItems
529
- },
528
+ }), [
529
+ containerRef,
530
+ showItems,
531
+ setShowItems
532
+ ]);
533
+ return /*#__PURE__*/ (0, $8bRfI$jsx)($79e2b4a1b34d1592$var$CollapseContext.Provider, {
534
+ value: ctx,
530
535
  children: /*#__PURE__*/ (0, $8bRfI$jsx)((0, $8bRfI$UNSTABLE_CollectionRendererContext).Provider, {
531
536
  value: $79e2b4a1b34d1592$var$CollapsingCollectionRenderer,
532
537
  children: children
package/dist/Tabs.mjs.map CHANGED
@@ -1 +1 @@
1
- {"mappings":";;;;;;;;;;;;;;;;;;;AAAA;;;;;;;;;;CAUC;;;;;;;;;;;;;AAgEM,MAAM,0DAAc,CAAA,GAAA,oBAAY,EAAwD;AAC/F,MAAM,0DAAsB,CAAA,GAAA,oBAAY,EAAiF;IAAC,SAAS,KAAO;AAAC;AAE3I,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;AAcC,MAAM,0DAAO,CAAA,GAAA,iBAAS,EAAE,SAAS,KAAK,KAAgB,EAAE,GAA2B;IACxF,CAAC,OAAO,IAAI,GAAG,CAAA,GAAA,yCAAsB,EAAE,OAAO,KAAK;IACnD,IAAI,WACF,UAAU,uBACV,UAAU,gBACV,YAAY,eACZ,cAAc,0BACd,aAAa,OACd,GAAG;IACJ,IAAI,SAAS,CAAA,GAAA,gBAAQ,EAAE;IACvB,IAAI,CAAC,OAAO,SAAS,GAAG,CAAA,GAAA,yBAAiB,EAAE,MAAM,WAAW,EAAE,MAAM,kBAAkB,IAAI,MAAO,MAAM,iBAAiB;IACxH,IAAI,YAAY,CAAA,GAAA,aAAK,EAAwC;IAE7D,qBACE,gBAAC,CAAA,GAAA,eAAO;QACN,QAAQ;YACN;gBAAC;gBAAqB;6BACpB;gCACA;iCACA;kCACA;oBACA,aAAa;oBACb,mBAAmB;gCACnB;oBACA,SAAS,IAAM,UAAU,OAAO,EAAE;+BAClC;gBACF;aAAE;SACH;kBACD,cAAA,gBAAC;YAAqB,cAAc;sBAClC,cAAA,gBAAC,CAAA,GAAA,WAAM;gBACJ,GAAG,KAAK;gBACT,KAAK;gBACL,aAAa;gBACb,mBAAmB;gBACnB,OAAO,MAAM,YAAY;gBACzB,WAAW,CAAA,cAAe,AAAC,CAAA,MAAM,gBAAgB,IAAI,EAAC,IAAK,2BAAK;wBAAC,GAAG,WAAW;oBAAA,GAAG,MAAM,MAAM;0BAC7F,MAAM,QAAQ;;;;AAKzB;AAEA,MAAM;;;;;;;;;;;;;;;;;;;;;;;;AAqCC,SAAS,0CAA0B,MAAsB;IAC9D,IAAI,WAAC,OAAO,cAAE,UAAU,gBAAE,YAAY,eAAE,WAAW,cAAE,UAAU,WAAE,OAAO,EAAC,GAAG,CAAA,GAAA,iBAAS,EAAE,8CAAwB,CAAC;IAChH,IAAI,aAAC,SAAS,EAAC,GAAG,CAAA,GAAA,iBAAS,EAAE,0CAAoB,CAAC;IAClD,IAAI,QAAQ,CAAA,GAAA,iBAAS,EAAE,CAAA,GAAA,0BAAkB;IACzC,IAAI,CAAC,aAAa,eAAe,GAAG,CAAA,GAAA,eAAO,EAA2B;IACtE,IAAI,aAAa,CAAA,GAAA,aAAK,EAAkB;IAExC,CAAA,GAAA,sBAAc,EAAE;QACd,IAAI,YAAY,WAAW,WAAW;YACpC,IAAI,MAA0B,WAAW,OAAO,CAAC,aAAa,CAAC;YAE/D,IAAI,OAAO,MACT,eAAe;QAEnB,OAAO,IAAI,YAAY,SAAS;YAC9B,IAAI,SAA6B,WAAW,OAAO,CAAC,aAAa,CAAC;YAClE,IAAI,UAAU,MACZ,eAAe;QAEnB;IACF,GAAG;QAAC;QAAY,OAAO,cAAc;QAAK;KAAU;IAEpD,IAAI,cAAc,CAAA,GAAA,aAAK,EAAuB;IAC9C,CAAA,GAAA,sBAAc,EAAE;QACd,IAAI,CAAC,aAAa,CAAC,YAAY,OAAO,IAAI,OAAO,iBAAiB,WAChE;QAEF,YAAY,OAAO,GAAG,OAAO,iBAAiB;IAChD,GAAG;QAAC,OAAO,iBAAiB;QAAW,OAAO,iBAAiB;QAAY;KAAU;IAErF,qBACE,iBAAC;QACC,OAAO,OAAM,YAAY;QACzB,WAAW,AAAC,CAAA,OAAM,gBAAgB,IAAI,EAAC,IAAK;;;;;;;;UAAqD,MAAM,OAAM,MAAM;;YAClH,aAAa,gBAAgB,4BAC5B,gBAAC;gBAAQ,cAAc;gBAAc,YAAY;gBAAY,aAAa;gBAAa,aAAa;gBAAa,SAAS;;0BAC5H,gBAAC,CAAA,GAAA,cAAS;gBACP,GAAG,MAAK;gBACT,KAAK;gBACL,WAAW,CAAA,cAAe,8BAAQ;wBAAC,GAAG,WAAW;oCAAE;iCAAY;oBAAO;;YACvE,gBAAgB,8BACf,gBAAC;gBAAQ,WAAW;gBAAW,cAAc;gBAAc,YAAY;gBAAY,aAAa;gBAAa,aAAa;gBAAa,SAAS;;;;AAGxJ;AAWA,MAAM;;;;;;;;;;;;;;;;;;;;;;;;AA+BN,SAAS,8BAAQ,KAA4C;IAC3D,IAAI,gBACF,YAAY,EACZ,YAAY,cAAc,eAC1B,WAAW,eACX,WAAW,WACX,OAAO,EACR,GAAG;IACJ,IAAI,aAAC,SAAS,EAAC,GAAG,CAAA,GAAA,gBAAQ;IAC1B,IAAI,QAAQ,CAAA,GAAA,iBAAS,EAAE,CAAA,GAAA,0BAAkB;IAEzC,IAAI,aAAa,CAAA,GAAA,cAAM,EAAE;QACvB,OAAO,kBAAkB,wCAAkB,OAAO,YAAY,eAAe,IAAI,IAAI,gBAAgB,IAAI;IAC3G,GAAG;QAAC,OAAO;QAAY;QAAc;KAAe;IAEpD,IAAI,CAAC,OAAO,SAAS,GAAG,CAAA,GAAA,eAAO,EAA0F;QACvH,WAAW;QACX,OAAO;QACP,QAAQ;IACV;IAEA,IAAI,WAAW,CAAA,GAAA,kBAAU,EAAE;QACzB,IAAI,aAAa;YACf,IAAI,WAAqG;gBACvG,WAAW;gBACX,OAAO;gBACP,QAAQ;YACV;YAEA,8JAA8J;YAC9J,IAAI,SAAS,cAAc,QAAQ,KAAM,CAAA,AAAC,YAAY,YAAY,EAAkB,cAAc,YAAY,WAAW,GAAG,YAAY,UAAU,AAAD,IAAK,YAAY,UAAU;YAC5K,SAAS,SAAS,GAAG,gBAAgB,aACjC,CAAC,WAAW,EAAE,YAAY,SAAS,CAAC,GAAG,CAAC,GACxC,CAAC,WAAW,EAAE,OAAO,GAAG,CAAC;YAE7B,IAAI,gBAAgB,cAClB,SAAS,KAAK,GAAG,GAAG,YAAY,WAAW,CAAC,EAAE,CAAC;iBAE/C,SAAS,MAAM,GAAG,GAAG,YAAY,YAAY,CAAC,EAAE,CAAC;YAEnD,SAAS;QACX;IACF,GAAG;QAAC;QAAW;QAAU;QAAa;KAAY;IAElD,CAAA,GAAA,sBAAc,EAAE;QACd;IACF,GAAG;QAAC;QAAU,OAAO,cAAc;QAAK;KAAQ;IAEhD,IAAI,MAAM,CAAA,GAAA,aAAK,EAA2B;IAC1C,yDAAyD;IACzD,CAAA,GAAA,sBAAc,EAAE;QACd,IAAI,OAAO,GAAG;IAChB;IACA,CAAA,GAAA,wBAAgB,EAAE;aAAC;kBAAK;IAAQ;IAEhC,qBACE,gBAAC;QAAI,OAAO;YAAC,GAAG,KAAK;QAAA;QAAG,WAAW,wCAAkB;wBAAC;yBAAY;QAAW;;AAEjF;AAEA,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+BN,MAAM;AASC,SAAS,0CAAI,MAAe;IACjC,IAAI,WAAC,OAAO,cAAE,UAAU,EAAC,GAAG,CAAA,GAAA,iBAAS,EAAE,8CAAwB,CAAC;IAEhE,qBACE,gBAAC,CAAA,GAAA,UAAK;QACH,GAAG,MAAK;QACT,aAAa;QACb,eAAe;QACf,OAAO,OAAM,YAAY;QACzB,WAAW,CAAA,cAAe,AAAC,CAAA,OAAM,gBAAgB,IAAI,EAAC,IAAK,0BAAI;gBAAC,GAAG,WAAW;yBAAE;4BAAS;YAAU,GAAG,OAAM,MAAM;kBACjH,CAAC,UACE,aAAa;QACb,MAAM,EACP;YACD,IAAI,QACF,OAAO,OAAM,QAAQ;iBAErB,qBACE,gBAAC,CAAA,GAAA,eAAO;gBACN,QAAQ;oBACN;wBAAC,CAAA,GAAA,yCAAU;wBAAG;4BACZ,QACE;;;;;8BAKG;4CAAC;4BAAU;wBAClB;qBAAE;oBACF;wBAAC,CAAA,GAAA,yCAAU;wBAAG;4BACZ,QAAQ,CAAA,GAAA,yCAAa,EAAE;gCAAC,MAAM;gCAAQ,MAAM;4BAAmB;4BAC/D,QAAQ;wBACV;qBAAE;iBACH;0BACA,OAAO,OAAM,QAAQ,KAAK,yBAAW,gBAAC,CAAA,GAAA,yCAAG;8BAAG,OAAM,QAAQ;qBAAW,OAAM,QAAQ;;QAI5F;;AAGN;AAEA,MAAM;;;;;;;;;;;;;;;;;;;;;;;;AASC,SAAS,0CAAS,KAAoB;IAC3C,qBACE,gBAAC,CAAA,GAAA,eAAW;QACT,GAAG,KAAK;QACT,OAAO,MAAM,YAAY;QACzB,WAAW,AAAC,CAAA,MAAM,gBAAgB,IAAI,EAAC,IAAK,+BAAS,MAAM,MAAM,MAAM;;AAE7E;AAEA,SAAS,wCAAqB,UAA2C,EAAE,YAAsB;IAC/F,IAAI,UAAsB;IAC1B,IAAI,cAAc,WAAW,IAAI,GAAG,GAAG;QACrC,UAAU,WAAW,WAAW;QAEhC,IAAI,QAAQ;QACZ,MAAO,WAAW,QAAQ,WAAW,IAAI,CAAE;YACzC,yHAAyH;YACzH,IAAI,CAAC,aAAa,GAAG,CAAC,YAAY,CAAC,WAAW,OAAO,CAAC,UAAU,OAAO,YACrE,OAAO;YAGT,UAAU,WAAW,WAAW,CAAC;YACjC;QACF;QACA,OAAO;IACT;IACA,OAAO;AACT;AAEA,IAAI,mCAAa,SAAU,KAK1B;IACC,IAAI,WAAC,OAAO,SAAE,KAAK,QAAE,IAAI,WAAE,OAAO,EAAC,GAAG;IAEtC,qBACE,gBAAC;QACC,aAAa;QACb,OAAM;QACN,KAAK;QACL,SAAS;kBAWR,MAAM,GAAG,CAAC,CAAC;YACV,6FAA6F;YAC7F,qBACE,gBAAC;gBACC,iBAAe;gBACf,OAAO,KAAK,KAAK,CAAC,YAAY;gBAE9B,WAAW,KAAK,KAAK,CAAC,SAAS,CAAC;0BAAC;6BAAM;gBAAO;0BAC7C,KAAK,KAAK,CAAC,QAAQ,CAAC;0BAAC;6BAAM;gBAAO;eAF9B,KAAK,GAAG;QAKnB;;AAGN;AAEA,IAAI,iCAAW,CAAC;IACd,IAAI,kBAAkB,CAAA,GAAA,kCAA0B,EAAE,CAAA,GAAA,+CAAW,GAAG;IAChE,IAAI,SAAC,KAAK,EAAC,GAAG;IACd,IAAI,WAAC,OAAO,qBAAE,iBAAiB,eAAE,WAAW,cAAE,UAAU,gBAAE,YAAY,aAAE,SAAS,cAAE,UAAU,EAAC,GAAG,CAAA,GAAA,iBAAS,EAAE;IAC5G,IAAI,QAAQ,CAAA,GAAA,iBAAS,EAAE,CAAA,GAAA,0BAAkB;IACzC,IAAI,kBAAkB,CAAA,GAAA,cAAM,EAAE;QAC5B,OAAO,wCAAkB,OAAO,YAAY,eAAe,IAAI,IAAI,gBAAgB,IAAI;IACzF,GAAG;QAAC,OAAO;QAAY;KAAa;IAEpC,qBACE,gBAAC,CAAA,GAAA,yCAAiC,EAAE,QAAQ;QAAC,OAAO,CAAA,GAAA,yCAAiC;kBACnF,cAAA,gBAAC;YACC,WAAW;;;;;;;cAQL;yBAAC;YAAO;sBACd,cAAA,gBAAC,CAAA,GAAA,yCAAK;gBACJ,KAAK,YAAY,YAAY;gBAC7B,YAAY,cAAc;gBAC1B,SAAS;gBACT,YAAY;gBACZ,OAAO;gBACP,cAAc;gBACd,aAAa;gBACb,mBAAmB;gBACnB,cAAY,gBAAgB,MAAM,CAAC;0BAClC,CAAC;oBACA,sEAAsE;oBACtE,6CAA6C;oBAC7C,qBACE,0BAAC,CAAA,GAAA,yCAAS;wBACP,GAAG,KAAK,KAAK,CAAC,aAAa;wBAC5B,YAAY,cAAc;wBAC1B,KAAK,KAAK,GAAG;uBACZ,KAAK,KAAK,CAAC,QAAQ,CAAC;iCAAC;wBAAS,QAAQ;oBAAI;gBAGjD;;;;AAKV;AAEA,wDAAwD;AACxD,IAAI,sDAAkB,CAAA,GAAA,oBAAY,EAIxB;AAEV,SAAS,2CAAqB,YAAC,QAAQ,gBAAE,YAAY,EAAC;IACpD,IAAI,CAAC,WAAW,cAAc,GAAG,CAAA,GAAA,eAAO,EAAE;IAC1C,IAAI,eAAC,WAAW,EAAC,GAAG,CAAA,GAAA,iBAAS,EAAE;IAC/B,IAAI,eAAe,CAAA,GAAA,kBAAU,EAAE,CAAC;QAC9B,IAAI,gBAAgB,YAClB,uDAAuD;QACvD,cAAc;aAEd,cAAc;IAElB,GAAG;QAAC;KAAY;IAChB,qBACE,gBAAC,sCAAgB,QAAQ;QAAC,OAAO;0BAAC;YAAc,WAAW,gBAAgB,aAAa,OAAO;0BAAW;QAAY;kBACpH,cAAA,gBAAC,CAAA,GAAA,yCAAiC,EAAE,QAAQ;YAAC,OAAO;sBACjD;;;AAIT;AAEA,IAAI,qDAAmD;IACrD,gBAAe,cAAC,UAAU,EAAC;QACzB,OAAO,0CAAoB;IAC7B;IACA,kBAAiB,cAAC,UAAU,EAAC;QAC3B,OAAO,0CAAoB;IAC7B;AACF;AAGA,IAAI,4CAAsB,CAAC;IACzB,IAAI,gBAAC,YAAY,aAAE,SAAS,gBAAE,YAAY,EAAC,GAAG,CAAA,GAAA,iBAAS,EAAE,0CAAoB,CAAC;IAC9E,IAAI,WAAC,UAAU,wBAAW,cAAc,iCAAc,iBAAiB,EAAC,GAAG,CAAA,GAAA,iBAAS,EAAE;IACtF,IAAI,aAAC,SAAS,EAAC,GAAG,CAAA,GAAA,gBAAQ;IAE1B,IAAI,WAAW,CAAA,GAAA,cAAM,EAAE;QACrB,IAAI,SAAsB,EAAE;QAC5B,KAAK,IAAI,OAAO,WAAW,OAAO,GAChC,OAAO,IAAI,CAAC,WAAW,OAAO,CAAC;QAEjC,OAAO;IACT,GAAG;QAAC;KAAW;IAEf,IAAI,UAAU,CAAA,GAAA,aAAK,EAAyB;IAC5C,IAAI,iBAAiB,CAAA,GAAA,qBAAa,EAAE;QAClC,IAAI,gBAAgB,cAAc,CAAC,QAAQ,OAAO,IAAI,CAAC,cAAc,SACnE;QAEF,IAAI,YAAY,QAAQ,OAAO;QAC/B,IAAI,gBAAgB,UAAU,qBAAqB;QACnD,IAAI,OAAO,UAAU,gBAAgB,CAAC;QACtC,IAAI,UAAU,IAAI,CAAC,KAAK,MAAM,GAAG,EAAE;QACnC,IAAI,cAAc,QAAQ,qBAAqB;QAC/C,IAAI,cAAc,OAChB,eAAe,YAAY,KAAK,IAAI,cAAc,KAAK;aAEvD,eAAe,YAAY,IAAI,IAAI,cAAc,IAAI;IAEzD;IAEA,CAAA,GAAA,wBAAgB,EAAE;QAAC,KAAK;QAAc,UAAU;IAAc;IAE9D,CAAA,GAAA,sBAAc,EAAE;QACd,IAAI,WAAW,IAAI,GAAG,GACpB,eAAe;IAEnB,GAAG;QAAC,WAAW,IAAI;QAAE;KAAe;IAEpC,CAAA,GAAA,gBAAQ,EAAE;QACR,kDAAkD;QAClD,SAAS,KAAK,EAAE,MAAM,KAAK,IAAM;IACjC,uDAAuD;IACzD,GAAG,EAAE;IAEL,qBACE;;0BACE,gBAAC;gBAAW,OAAO;gBAAU,SAAS;gBAAS,SAAS;;YACvD,YACC,SAAS,GAAG,CAAC,CAAA,qBAAQ,gBAAC,CAAA,GAAA,gBAAO;8BAAkB,KAAK,MAAM,GAAG;mBAAzB,KAAK,GAAG,mBAE5C;0BACE,cAAA,gBAAC;oBAAS,OAAO;oBAAU,mBAAmB;;;;;AAKxD","sources":["packages/@react-spectrum/s2/src/Tabs.tsx"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n TabListProps as AriaTabListProps,\n TabPanel as AriaTabPanel,\n TabPanelProps as AriaTabPanelProps,\n TabProps as AriaTabProps,\n TabsProps as AriaTabsProps,\n CollectionRenderer,\n ContextValue,\n Provider,\n Tab as RACTab,\n TabList as RACTabList,\n Tabs as RACTabs,\n TabListStateContext,\n UNSTABLE_CollectionRendererContext,\n UNSTABLE_DefaultCollectionRenderer\n} from 'react-aria-components';\nimport {centerBaseline} from './CenterBaseline';\nimport {Collection, DOMRef, DOMRefValue, FocusableRef, FocusableRefValue, Key, Node, Orientation, RefObject} from '@react-types/shared';\nimport {createContext, forwardRef, Fragment, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';\nimport {focusRing, size, style} from '../style' with {type: 'macro'};\nimport {getAllowedOverrides, StyleProps, StylesPropWithHeight, UnsafeStyles} from './style-utils' with {type: 'macro'};\nimport {IconContext} from './Icon';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {Picker, PickerItem} from './TabsPicker';\nimport {Text, TextContext} from './Content';\nimport {useControlledState} from '@react-stately/utils';\nimport {useDOMRef} from '@react-spectrum/utils';\nimport {useEffectEvent, useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale, useLocalizedStringFormatter} from '@react-aria/i18n';\nimport {useSpectrumContextProps} from './useSpectrumContextProps';\n\nexport interface TabsProps extends Omit<AriaTabsProps, 'className' | 'style' | 'children'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tabs. */\n children?: ReactNode,\n /**\n * The amount of space between the tabs.\n * @default 'regular'\n */\n density?: 'compact' | 'regular',\n /**\n * If the tabs should only display icons and no text.\n */\n isIconOnly?: boolean\n}\n\nexport interface TabProps extends Omit<AriaTabProps, 'children' | 'style' | 'className'>, StyleProps {\n /** The content to display in the tab. */\n children: ReactNode\n}\n\nexport interface TabListProps<T> extends Omit<AriaTabListProps<T>, 'style' | 'className'>, StyleProps {}\n\nexport interface TabPanelProps extends Omit<AriaTabPanelProps, 'children' | 'style' | 'className'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tab panels. */\n children?: ReactNode\n}\n\nexport const TabsContext = createContext<ContextValue<TabsProps, DOMRefValue<HTMLDivElement>>>(null);\nconst InternalTabsContext = createContext<TabsProps & {onFocus:() => void, pickerRef?: FocusableRef<HTMLButtonElement>}>({onFocus: () => {}});\n\nconst tabs = style({\n display: 'flex',\n flexShrink: 0,\n font: 'ui',\n flexDirection: {\n orientation: {\n horizontal: 'column'\n }\n }\n}, getAllowedOverrides({height: true}));\n\n/**\n * Tabs organize content into multiple sections and allow users to navigate between them. The content under the set of tabs should be related and form a coherent unit.\n */\nexport const Tabs = forwardRef(function Tabs(props: TabsProps, ref: DOMRef<HTMLDivElement>) {\n [props, ref] = useSpectrumContextProps(props, ref, TabsContext);\n let {\n density = 'regular',\n isDisabled,\n disabledKeys,\n orientation = 'horizontal',\n isIconOnly = false\n } = props;\n let domRef = useDOMRef(ref);\n let [value, setValue] = useControlledState(props.selectedKey, props.defaultSelectedKey ?? null!, props.onSelectionChange);\n let pickerRef = useRef<FocusableRefValue<HTMLButtonElement>>(null);\n\n return (\n <Provider\n values={[\n [InternalTabsContext, {\n density,\n isDisabled,\n orientation,\n disabledKeys,\n selectedKey: value,\n onSelectionChange: setValue,\n isIconOnly,\n onFocus: () => pickerRef.current?.focus(),\n pickerRef\n }]\n ]}>\n <CollapsingCollection containerRef={domRef}>\n <RACTabs\n {...props}\n ref={domRef}\n selectedKey={value}\n onSelectionChange={setValue}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tabs({...renderProps}, props.styles)}>\n {props.children}\n </RACTabs>\n </CollapsingCollection>\n </Provider>\n );\n});\n\nconst tablist = style({\n display: 'flex',\n gap: {\n orientation: {\n horizontal: {\n density: {\n compact: 24,\n regular: 32\n },\n isIconOnly: {\n density: {\n compact: 16,\n regular: 24\n }\n }\n }\n }\n },\n flexDirection: {\n orientation: {\n vertical: 'column'\n }\n },\n paddingEnd: {\n orientation: {\n vertical: 20\n }\n },\n paddingStart: {\n orientation: {\n vertical: 12\n }\n },\n flexShrink: 0,\n flexBasis: '[0%]'\n});\n\nexport function TabList<T extends object>(props: TabListProps<T>) {\n let {density, isDisabled, disabledKeys, orientation, isIconOnly, onFocus} = useContext(InternalTabsContext) ?? {};\n let {showItems} = useContext(CollapseContext) ?? {};\n let state = useContext(TabListStateContext);\n let [selectedTab, setSelectedTab] = useState<HTMLElement | undefined>(undefined);\n let tablistRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (tablistRef?.current && showItems) {\n let tab: HTMLElement | null = tablistRef.current.querySelector('[role=tab][data-selected=true]');\n\n if (tab != null) {\n setSelectedTab(tab);\n }\n } else if (tablistRef?.current) {\n let picker: HTMLElement | null = tablistRef.current.querySelector('button');\n if (picker != null) {\n setSelectedTab(picker);\n }\n }\n }, [tablistRef, state?.selectedItem?.key, showItems]);\n\n let prevFocused = useRef<boolean | undefined>(false);\n useLayoutEffect(() => {\n if (!showItems && !prevFocused.current && state?.selectionManager.isFocused) {\n onFocus();\n }\n prevFocused.current = state?.selectionManager.isFocused;\n }, [state?.selectionManager.isFocused, state?.selectionManager.focusedKey, showItems]);\n\n return (\n <div\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + style({position: 'relative'}, getAllowedOverrides())(null, props.styles)}>\n {showItems && orientation === 'vertical' &&\n <TabLine disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n <RACTabList\n {...props}\n ref={tablistRef}\n className={renderProps => tablist({...renderProps, isIconOnly, density})} />\n {orientation === 'horizontal' &&\n <TabLine showItems={showItems} disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n </div>\n );\n}\n\ninterface TabLineProps {\n disabledKeys: Iterable<Key> | undefined,\n isDisabled: boolean | undefined,\n selectedTab: HTMLElement | undefined,\n orientation?: Orientation,\n density?: 'compact' | 'regular',\n showItems?: boolean\n}\n\nconst selectedIndicator = style({\n position: 'absolute',\n backgroundColor: {\n default: 'neutral',\n isDisabled: 'disabled',\n forcedColors: {\n default: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n height: {\n orientation: {\n horizontal: '[2px]'\n }\n },\n width: {\n orientation: {\n vertical: '[2px]'\n }\n },\n bottom: {\n orientation: {\n horizontal: 0\n }\n },\n borderStyle: 'none',\n borderRadius: 'full',\n transitionDuration: 130,\n transitionTimingFunction: 'in-out'\n});\n\nfunction TabLine(props: TabLineProps & {isIconOnly?: boolean}) {\n let {\n disabledKeys,\n isDisabled: isTabsDisabled,\n selectedTab,\n orientation,\n density\n } = props;\n let {direction} = useLocale();\n let state = useContext(TabListStateContext);\n\n let isDisabled = useMemo(() => {\n return isTabsDisabled || isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys, isTabsDisabled]);\n\n let [style, setStyle] = useState<{transform: string | undefined, width: string | undefined, height: string | undefined}>({\n transform: undefined,\n width: undefined,\n height: undefined\n });\n\n let onResize = useCallback(() => {\n if (selectedTab) {\n let styleObj: { transform: string | undefined, width: string | undefined, height: string | undefined } = {\n transform: undefined,\n width: undefined,\n height: undefined\n };\n\n // In RTL, calculate the transform from the right edge of the tablist so that resizing the window doesn't break the Tabline position due to offsetLeft changes\n let offset = direction === 'rtl' ? -1 * ((selectedTab.offsetParent as HTMLElement)?.offsetWidth - selectedTab.offsetWidth - selectedTab.offsetLeft) : selectedTab.offsetLeft;\n styleObj.transform = orientation === 'vertical'\n ? `translateY(${selectedTab.offsetTop}px)`\n : `translateX(${offset}px)`;\n\n if (orientation === 'horizontal') {\n styleObj.width = `${selectedTab.offsetWidth}px`;\n } else {\n styleObj.height = `${selectedTab.offsetHeight}px`;\n }\n setStyle(styleObj);\n }\n }, [direction, setStyle, selectedTab, orientation]);\n\n useLayoutEffect(() => {\n onResize();\n }, [onResize, state?.selectedItem?.key, density]);\n\n let ref = useRef<HTMLElement | undefined>(selectedTab);\n // assign ref before the useResizeObserver useEffect runs\n useLayoutEffect(() => {\n ref.current = selectedTab;\n });\n useResizeObserver({ref, onResize});\n\n return (\n <div style={{...style}} className={selectedIndicator({isDisabled, orientation})} />\n );\n}\n\nconst tab = style({\n ...focusRing(),\n display: 'flex',\n color: {\n default: 'neutral-subdued',\n isSelected: 'neutral',\n isHovered: 'neutral-subdued',\n isDisabled: 'disabled',\n forcedColors: {\n isSelected: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n borderRadius: 'sm',\n gap: 'text-to-visual',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n },\n alignItems: 'center',\n position: 'relative',\n cursor: 'default',\n flexShrink: 0,\n transition: 'default',\n paddingX: {\n isIconOnly: size(6)\n }\n}, getAllowedOverrides());\n\nconst icon = style({\n display: 'block',\n flexShrink: 0,\n '--iconPrimary': {\n type: 'fill',\n value: 'currentColor'\n }\n});\n\nexport function Tab(props: TabProps) {\n let {density, isIconOnly} = useContext(InternalTabsContext) ?? {};\n\n return (\n <RACTab\n {...props}\n // @ts-ignore\n originalProps={props}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tab({...renderProps, density, isIconOnly}, props.styles)}>\n {({\n // @ts-ignore\n isMenu\n }) => {\n if (isMenu) {\n return props.children;\n } else {\n return (\n <Provider\n values={[\n [TextContext, {\n styles:\n style({\n order: 1,\n display: {\n isIconOnly: 'none'\n }\n })({isIconOnly})\n }],\n [IconContext, {\n render: centerBaseline({slot: 'icon', styles: style({order: 0})}),\n styles: icon\n }]\n ]}>\n {typeof props.children === 'string' ? <Text>{props.children}</Text> : props.children}\n </Provider>\n );\n }\n }}\n </RACTab>\n );\n}\n\nconst tabPanel = style({\n marginTop: 4,\n color: 'gray-800',\n flexGrow: 1,\n flexBasis: '[0%]',\n minHeight: 0,\n minWidth: 0\n}, getAllowedOverrides({height: true}));\n\nexport function TabPanel(props: TabPanelProps) {\n return (\n <AriaTabPanel\n {...props}\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + tabPanel(null, props.styles)} />\n );\n}\n\nfunction isAllTabsDisabled<T>(collection: Collection<Node<T>> | undefined, disabledKeys: Set<Key>) {\n let testKey: Key | null = null;\n if (collection && collection.size > 0) {\n testKey = collection.getFirstKey();\n\n let index = 0;\n while (testKey && index < collection.size) {\n // We have to check if the item in the collection has a key in disabledKeys or has the isDisabled prop set directly on it\n if (!disabledKeys.has(testKey) && !collection.getItem(testKey)?.props?.isDisabled) {\n return false;\n }\n\n testKey = collection.getKeyAfter(testKey);\n index++;\n }\n return true;\n }\n return false;\n}\n\nlet HiddenTabs = function (props: {\n listRef: RefObject<HTMLDivElement | null>,\n items: Array<Node<any>>,\n size?: string,\n density?: 'compact' | 'regular'\n}) {\n let {listRef, items, size, density} = props;\n\n return (\n <div\n // @ts-ignore\n inert=\"true\"\n ref={listRef}\n className={style({\n display: '[inherit]',\n flexDirection: '[inherit]',\n gap: '[inherit]',\n flexWrap: '[inherit]',\n position: 'absolute',\n inset: 0,\n visibility: 'hidden',\n overflow: 'hidden',\n opacity: 0\n })}>\n {items.map((item) => {\n // pull off individual props as an allow list, don't want refs or other props getting through\n return (\n <div\n data-hidden-tab\n style={item.props.UNSAFE_style}\n key={item.key}\n className={item.props.className({size, density})}>\n {item.props.children({size, density})}\n </div>\n );\n })}\n </div>\n );\n};\n\nlet TabsMenu = (props: {items: Array<Node<any>>, onSelectionChange: TabsProps['onSelectionChange']}) => {\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/s2');\n let {items} = props;\n let {density, onSelectionChange, selectedKey, isDisabled, disabledKeys, pickerRef, isIconOnly} = useContext(InternalTabsContext);\n let state = useContext(TabListStateContext);\n let allKeysDisabled = useMemo(() => {\n return isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys]);\n\n return (\n <UNSTABLE_CollectionRendererContext.Provider value={UNSTABLE_DefaultCollectionRenderer}>\n <div\n className={style({\n display: 'flex',\n alignItems: 'center',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n }})({density})}>\n <Picker\n ref={pickerRef ? pickerRef : undefined}\n isDisabled={isDisabled || allKeysDisabled}\n density={density!}\n isIconOnly={isIconOnly}\n items={items}\n disabledKeys={disabledKeys}\n selectedKey={selectedKey}\n onSelectionChange={onSelectionChange}\n aria-label={stringFormatter.format('tabs.selectorLabel')}>\n {(item: Node<any>) => {\n // need to determine the best way to handle icon only -> icon and text\n // good enough to aria-label the picker item?\n return (\n <PickerItem\n {...item.props.originalProps}\n isDisabled={isDisabled || allKeysDisabled}\n key={item.key}>\n {item.props.children({density, isMenu: true})}\n </PickerItem>\n );\n }}\n </Picker>\n </div>\n </UNSTABLE_CollectionRendererContext.Provider>\n );\n};\n\n// Context for passing the count for the custom renderer\nlet CollapseContext = createContext<{\n containerRef: RefObject<HTMLDivElement | null>,\n showItems: boolean,\n setShowItems:(value: boolean) => void\n} | null>(null);\n\nfunction CollapsingCollection({children, containerRef}) {\n let [showItems, _setShowItems] = useState(true);\n let {orientation} = useContext(InternalTabsContext);\n let setShowItems = useCallback((value: boolean) => {\n if (orientation === 'vertical') {\n // if orientation is vertical, we always show the items\n _setShowItems(true);\n } else {\n _setShowItems(value);\n }\n }, [orientation]);\n return (\n <CollapseContext.Provider value={{containerRef, showItems: orientation === 'vertical' ? true : showItems, setShowItems}}>\n <UNSTABLE_CollectionRendererContext.Provider value={CollapsingCollectionRenderer}>\n {children}\n </UNSTABLE_CollectionRendererContext.Provider>\n </CollapseContext.Provider>\n );\n}\n\nlet CollapsingCollectionRenderer: CollectionRenderer = {\n CollectionRoot({collection}) {\n return useCollectionRender(collection);\n },\n CollectionBranch({collection}) {\n return useCollectionRender(collection);\n }\n};\n\n\nlet useCollectionRender = (collection: Collection<Node<unknown>>) => {\n let {containerRef, showItems, setShowItems} = useContext(CollapseContext) ?? {};\n let {density = 'regular', orientation = 'horizontal', onSelectionChange} = useContext(InternalTabsContext);\n let {direction} = useLocale();\n\n let children = useMemo(() => {\n let result: Node<any>[] = [];\n for (let key of collection.getKeys()) {\n result.push(collection.getItem(key)!);\n }\n return result;\n }, [collection]);\n\n let listRef = useRef<HTMLDivElement | null>(null);\n let updateOverflow = useEffectEvent(() => {\n if (orientation === 'vertical' || !listRef.current || !containerRef?.current) {\n return;\n }\n let container = listRef.current;\n let containerRect = container.getBoundingClientRect();\n let tabs = container.querySelectorAll('[data-hidden-tab]');\n let lastTab = tabs[tabs.length - 1];\n let lastTabRect = lastTab.getBoundingClientRect();\n if (direction === 'ltr') {\n setShowItems?.(lastTabRect.right <= containerRect.right);\n } else {\n setShowItems?.(lastTabRect.left >= containerRect.left);\n }\n });\n\n useResizeObserver({ref: containerRef, onResize: updateOverflow});\n\n useLayoutEffect(() => {\n if (collection.size > 0) {\n queueMicrotask(updateOverflow);\n }\n }, [collection.size, updateOverflow]);\n\n useEffect(() => {\n // Recalculate visible tags when fonts are loaded.\n document.fonts?.ready.then(() => updateOverflow());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <>\n <HiddenTabs items={children} density={density} listRef={listRef} />\n {showItems ? (\n children.map(node => <Fragment key={node.key}>{node.render?.(node)}</Fragment>)\n ) : (\n <>\n <TabsMenu items={children} onSelectionChange={onSelectionChange} />\n </>\n )}\n </>\n );\n};\n"],"names":[],"version":3,"file":"Tabs.mjs.map"}
1
+ {"mappings":"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","sources":["packages/@react-spectrum/s2/src/Tabs.tsx"],"sourcesContent":["/*\n * Copyright 2024 Adobe. All rights reserved.\n * This file is licensed to you under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License. You may obtain a copy\n * of the License at http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software distributed under\n * the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS\n * OF ANY KIND, either express or implied. See the License for the specific language\n * governing permissions and limitations under the License.\n */\n\nimport {\n TabListProps as AriaTabListProps,\n TabPanel as AriaTabPanel,\n TabPanelProps as AriaTabPanelProps,\n TabProps as AriaTabProps,\n TabsProps as AriaTabsProps,\n CollectionRenderer,\n ContextValue,\n Provider,\n Tab as RACTab,\n TabList as RACTabList,\n Tabs as RACTabs,\n TabListStateContext,\n UNSTABLE_CollectionRendererContext,\n UNSTABLE_DefaultCollectionRenderer\n} from 'react-aria-components';\nimport {centerBaseline} from './CenterBaseline';\nimport {Collection, DOMRef, DOMRefValue, FocusableRef, FocusableRefValue, Key, Node, Orientation, RefObject} from '@react-types/shared';\nimport {createContext, forwardRef, Fragment, ReactNode, useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';\nimport {focusRing, size, style} from '../style' with {type: 'macro'};\nimport {getAllowedOverrides, StyleProps, StylesPropWithHeight, UnsafeStyles} from './style-utils' with {type: 'macro'};\nimport {IconContext} from './Icon';\n// @ts-ignore\nimport intlMessages from '../intl/*.json';\nimport {Picker, PickerItem} from './TabsPicker';\nimport {Text, TextContext} from './Content';\nimport {useControlledState} from '@react-stately/utils';\nimport {useDOMRef} from '@react-spectrum/utils';\nimport {useEffectEvent, useLayoutEffect, useResizeObserver} from '@react-aria/utils';\nimport {useLocale, useLocalizedStringFormatter} from '@react-aria/i18n';\nimport {useSpectrumContextProps} from './useSpectrumContextProps';\n\nexport interface TabsProps extends Omit<AriaTabsProps, 'className' | 'style' | 'children'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tabs. */\n children?: ReactNode,\n /**\n * The amount of space between the tabs.\n * @default 'regular'\n */\n density?: 'compact' | 'regular',\n /**\n * If the tabs should only display icons and no text.\n */\n isIconOnly?: boolean\n}\n\nexport interface TabProps extends Omit<AriaTabProps, 'children' | 'style' | 'className'>, StyleProps {\n /** The content to display in the tab. */\n children: ReactNode\n}\n\nexport interface TabListProps<T> extends Omit<AriaTabListProps<T>, 'style' | 'className'>, StyleProps {}\n\nexport interface TabPanelProps extends Omit<AriaTabPanelProps, 'children' | 'style' | 'className'>, UnsafeStyles {\n /** Spectrum-defined styles, returned by the `style()` macro. */\n styles?: StylesPropWithHeight,\n /** The content to display in the tab panels. */\n children?: ReactNode\n}\n\nexport const TabsContext = createContext<ContextValue<TabsProps, DOMRefValue<HTMLDivElement>>>(null);\nconst InternalTabsContext = createContext<TabsProps & {onFocus:() => void, pickerRef?: FocusableRef<HTMLButtonElement>}>({onFocus: () => {}});\n\nconst tabs = style({\n display: 'flex',\n flexShrink: 0,\n font: 'ui',\n flexDirection: {\n orientation: {\n horizontal: 'column'\n }\n }\n}, getAllowedOverrides({height: true}));\n\n/**\n * Tabs organize content into multiple sections and allow users to navigate between them. The content under the set of tabs should be related and form a coherent unit.\n */\nexport const Tabs = forwardRef(function Tabs(props: TabsProps, ref: DOMRef<HTMLDivElement>) {\n [props, ref] = useSpectrumContextProps(props, ref, TabsContext);\n let {\n density = 'regular',\n isDisabled,\n disabledKeys,\n orientation = 'horizontal',\n isIconOnly = false\n } = props;\n let domRef = useDOMRef(ref);\n let [value, setValue] = useControlledState(props.selectedKey, props.defaultSelectedKey ?? null!, props.onSelectionChange);\n let pickerRef = useRef<FocusableRefValue<HTMLButtonElement>>(null);\n\n return (\n <Provider\n values={[\n [InternalTabsContext, {\n density,\n isDisabled,\n orientation,\n disabledKeys,\n selectedKey: value,\n onSelectionChange: setValue,\n isIconOnly,\n onFocus: () => pickerRef.current?.focus(),\n pickerRef\n }]\n ]}>\n <CollapsingCollection containerRef={domRef}>\n <RACTabs\n {...props}\n ref={domRef}\n selectedKey={value}\n onSelectionChange={setValue}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tabs({...renderProps}, props.styles)}>\n {props.children}\n </RACTabs>\n </CollapsingCollection>\n </Provider>\n );\n});\n\nconst tablist = style({\n display: 'flex',\n gap: {\n orientation: {\n horizontal: {\n density: {\n compact: 24,\n regular: 32\n },\n isIconOnly: {\n density: {\n compact: 16,\n regular: 24\n }\n }\n }\n }\n },\n flexDirection: {\n orientation: {\n vertical: 'column'\n }\n },\n paddingEnd: {\n orientation: {\n vertical: 20\n }\n },\n paddingStart: {\n orientation: {\n vertical: 12\n }\n },\n flexShrink: 0,\n flexBasis: '[0%]'\n});\n\nexport function TabList<T extends object>(props: TabListProps<T>) {\n let {density, isDisabled, disabledKeys, orientation, isIconOnly, onFocus} = useContext(InternalTabsContext) ?? {};\n let {showItems} = useContext(CollapseContext) ?? {};\n let state = useContext(TabListStateContext);\n let [selectedTab, setSelectedTab] = useState<HTMLElement | undefined>(undefined);\n let tablistRef = useRef<HTMLDivElement>(null);\n\n useLayoutEffect(() => {\n if (tablistRef?.current && showItems) {\n let tab: HTMLElement | null = tablistRef.current.querySelector('[role=tab][data-selected=true]');\n\n if (tab != null) {\n setSelectedTab(tab);\n }\n } else if (tablistRef?.current) {\n let picker: HTMLElement | null = tablistRef.current.querySelector('button');\n if (picker != null) {\n setSelectedTab(picker);\n }\n }\n }, [tablistRef, state?.selectedItem?.key, showItems]);\n\n let prevFocused = useRef<boolean | undefined>(false);\n useLayoutEffect(() => {\n if (!showItems && !prevFocused.current && state?.selectionManager.isFocused) {\n onFocus();\n }\n prevFocused.current = state?.selectionManager.isFocused;\n }, [state?.selectionManager.isFocused, state?.selectionManager.focusedKey, showItems]);\n\n return (\n <div\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + style({position: 'relative'}, getAllowedOverrides())(null, props.styles)}>\n {showItems && orientation === 'vertical' &&\n <TabLine disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n <RACTabList\n {...props}\n ref={tablistRef}\n className={renderProps => tablist({...renderProps, isIconOnly, density})} />\n {orientation === 'horizontal' &&\n <TabLine showItems={showItems} disabledKeys={disabledKeys} isDisabled={isDisabled} selectedTab={selectedTab} orientation={orientation} density={density} />}\n </div>\n );\n}\n\ninterface TabLineProps {\n disabledKeys: Iterable<Key> | undefined,\n isDisabled: boolean | undefined,\n selectedTab: HTMLElement | undefined,\n orientation?: Orientation,\n density?: 'compact' | 'regular',\n showItems?: boolean\n}\n\nconst selectedIndicator = style({\n position: 'absolute',\n backgroundColor: {\n default: 'neutral',\n isDisabled: 'disabled',\n forcedColors: {\n default: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n height: {\n orientation: {\n horizontal: '[2px]'\n }\n },\n width: {\n orientation: {\n vertical: '[2px]'\n }\n },\n bottom: {\n orientation: {\n horizontal: 0\n }\n },\n borderStyle: 'none',\n borderRadius: 'full',\n transitionDuration: 130,\n transitionTimingFunction: 'in-out'\n});\n\nfunction TabLine(props: TabLineProps & {isIconOnly?: boolean}) {\n let {\n disabledKeys,\n isDisabled: isTabsDisabled,\n selectedTab,\n orientation,\n density\n } = props;\n let {direction} = useLocale();\n let state = useContext(TabListStateContext);\n\n let isDisabled = useMemo(() => {\n return isTabsDisabled || isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys, isTabsDisabled]);\n\n let [style, setStyle] = useState<{transform: string | undefined, width: string | undefined, height: string | undefined}>({\n transform: undefined,\n width: undefined,\n height: undefined\n });\n\n let onResize = useCallback(() => {\n if (selectedTab) {\n let styleObj: { transform: string | undefined, width: string | undefined, height: string | undefined } = {\n transform: undefined,\n width: undefined,\n height: undefined\n };\n\n // In RTL, calculate the transform from the right edge of the tablist so that resizing the window doesn't break the Tabline position due to offsetLeft changes\n let offset = direction === 'rtl' ? -1 * ((selectedTab.offsetParent as HTMLElement)?.offsetWidth - selectedTab.offsetWidth - selectedTab.offsetLeft) : selectedTab.offsetLeft;\n styleObj.transform = orientation === 'vertical'\n ? `translateY(${selectedTab.offsetTop}px)`\n : `translateX(${offset}px)`;\n\n if (orientation === 'horizontal') {\n styleObj.width = `${selectedTab.offsetWidth}px`;\n } else {\n styleObj.height = `${selectedTab.offsetHeight}px`;\n }\n setStyle(styleObj);\n }\n }, [direction, setStyle, selectedTab, orientation]);\n\n useLayoutEffect(() => {\n onResize();\n }, [onResize, state?.selectedItem?.key, density]);\n\n let ref = useRef<HTMLElement | undefined>(selectedTab);\n // assign ref before the useResizeObserver useEffect runs\n useLayoutEffect(() => {\n ref.current = selectedTab;\n });\n useResizeObserver({ref, onResize});\n\n return (\n <div style={{...style}} className={selectedIndicator({isDisabled, orientation})} />\n );\n}\n\nconst tab = style({\n ...focusRing(),\n display: 'flex',\n color: {\n default: 'neutral-subdued',\n isSelected: 'neutral',\n isHovered: 'neutral-subdued',\n isDisabled: 'disabled',\n forcedColors: {\n isSelected: 'Highlight',\n isDisabled: 'GrayText'\n }\n },\n borderRadius: 'sm',\n gap: 'text-to-visual',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n },\n alignItems: 'center',\n position: 'relative',\n cursor: 'default',\n flexShrink: 0,\n transition: 'default',\n paddingX: {\n isIconOnly: size(6)\n }\n}, getAllowedOverrides());\n\nconst icon = style({\n display: 'block',\n flexShrink: 0,\n '--iconPrimary': {\n type: 'fill',\n value: 'currentColor'\n }\n});\n\nexport function Tab(props: TabProps) {\n let {density, isIconOnly} = useContext(InternalTabsContext) ?? {};\n\n return (\n <RACTab\n {...props}\n // @ts-ignore\n originalProps={props}\n style={props.UNSAFE_style}\n className={renderProps => (props.UNSAFE_className || '') + tab({...renderProps, density, isIconOnly}, props.styles)}>\n {({\n // @ts-ignore\n isMenu\n }) => {\n if (isMenu) {\n return props.children;\n } else {\n return (\n <Provider\n values={[\n [TextContext, {\n styles:\n style({\n order: 1,\n display: {\n isIconOnly: 'none'\n }\n })({isIconOnly})\n }],\n [IconContext, {\n render: centerBaseline({slot: 'icon', styles: style({order: 0})}),\n styles: icon\n }]\n ]}>\n {typeof props.children === 'string' ? <Text>{props.children}</Text> : props.children}\n </Provider>\n );\n }\n }}\n </RACTab>\n );\n}\n\nconst tabPanel = style({\n marginTop: 4,\n color: 'gray-800',\n flexGrow: 1,\n flexBasis: '[0%]',\n minHeight: 0,\n minWidth: 0\n}, getAllowedOverrides({height: true}));\n\nexport function TabPanel(props: TabPanelProps) {\n return (\n <AriaTabPanel\n {...props}\n style={props.UNSAFE_style}\n className={(props.UNSAFE_className || '') + tabPanel(null, props.styles)} />\n );\n}\n\nfunction isAllTabsDisabled<T>(collection: Collection<Node<T>> | undefined, disabledKeys: Set<Key>) {\n let testKey: Key | null = null;\n if (collection && collection.size > 0) {\n testKey = collection.getFirstKey();\n\n let index = 0;\n while (testKey && index < collection.size) {\n // We have to check if the item in the collection has a key in disabledKeys or has the isDisabled prop set directly on it\n if (!disabledKeys.has(testKey) && !collection.getItem(testKey)?.props?.isDisabled) {\n return false;\n }\n\n testKey = collection.getKeyAfter(testKey);\n index++;\n }\n return true;\n }\n return false;\n}\n\nlet HiddenTabs = function (props: {\n listRef: RefObject<HTMLDivElement | null>,\n items: Array<Node<any>>,\n size?: string,\n density?: 'compact' | 'regular'\n}) {\n let {listRef, items, size, density} = props;\n\n return (\n <div\n // @ts-ignore\n inert=\"true\"\n ref={listRef}\n className={style({\n display: '[inherit]',\n flexDirection: '[inherit]',\n gap: '[inherit]',\n flexWrap: '[inherit]',\n position: 'absolute',\n inset: 0,\n visibility: 'hidden',\n overflow: 'hidden',\n opacity: 0\n })}>\n {items.map((item) => {\n // pull off individual props as an allow list, don't want refs or other props getting through\n return (\n <div\n data-hidden-tab\n style={item.props.UNSAFE_style}\n key={item.key}\n className={item.props.className({size, density})}>\n {item.props.children({size, density})}\n </div>\n );\n })}\n </div>\n );\n};\n\nlet TabsMenu = (props: {items: Array<Node<any>>, onSelectionChange: TabsProps['onSelectionChange']}) => {\n let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/s2');\n let {items} = props;\n let {density, onSelectionChange, selectedKey, isDisabled, disabledKeys, pickerRef, isIconOnly} = useContext(InternalTabsContext);\n let state = useContext(TabListStateContext);\n let allKeysDisabled = useMemo(() => {\n return isAllTabsDisabled(state?.collection, disabledKeys ? new Set(disabledKeys) : new Set());\n }, [state?.collection, disabledKeys]);\n\n return (\n <UNSTABLE_CollectionRendererContext.Provider value={UNSTABLE_DefaultCollectionRenderer}>\n <div\n className={style({\n display: 'flex',\n alignItems: 'center',\n height: {\n density: {\n compact: 32,\n regular: 48\n }\n }})({density})}>\n <Picker\n ref={pickerRef ? pickerRef : undefined}\n isDisabled={isDisabled || allKeysDisabled}\n density={density!}\n isIconOnly={isIconOnly}\n items={items}\n disabledKeys={disabledKeys}\n selectedKey={selectedKey}\n onSelectionChange={onSelectionChange}\n aria-label={stringFormatter.format('tabs.selectorLabel')}>\n {(item: Node<any>) => {\n // need to determine the best way to handle icon only -> icon and text\n // good enough to aria-label the picker item?\n return (\n <PickerItem\n {...item.props.originalProps}\n isDisabled={isDisabled || allKeysDisabled}\n key={item.key}>\n {item.props.children({density, isMenu: true})}\n </PickerItem>\n );\n }}\n </Picker>\n </div>\n </UNSTABLE_CollectionRendererContext.Provider>\n );\n};\n\n// Context for passing the count for the custom renderer\nlet CollapseContext = createContext<{\n containerRef: RefObject<HTMLDivElement | null>,\n showItems: boolean,\n setShowItems:(value: boolean) => void\n} | null>(null);\n\nfunction CollapsingCollection({children, containerRef}) {\n let [showItems, _setShowItems] = useState(true);\n let {orientation} = useContext(InternalTabsContext);\n let setShowItems = useCallback((value: boolean) => {\n if (orientation === 'vertical') {\n // if orientation is vertical, we always show the items\n _setShowItems(true);\n } else {\n _setShowItems(value);\n }\n }, [orientation]);\n let ctx = useMemo(() => ({\n containerRef,\n showItems: orientation === 'vertical' ? true : showItems,\n setShowItems\n }), [containerRef, showItems, setShowItems]);\n return (\n <CollapseContext.Provider value={ctx}>\n <UNSTABLE_CollectionRendererContext.Provider value={CollapsingCollectionRenderer}>\n {children}\n </UNSTABLE_CollectionRendererContext.Provider>\n </CollapseContext.Provider>\n );\n}\n\nlet CollapsingCollectionRenderer: CollectionRenderer = {\n CollectionRoot({collection}) {\n return useCollectionRender(collection);\n },\n CollectionBranch({collection}) {\n return useCollectionRender(collection);\n }\n};\n\n\nlet useCollectionRender = (collection: Collection<Node<unknown>>) => {\n let {containerRef, showItems, setShowItems} = useContext(CollapseContext) ?? {};\n let {density = 'regular', orientation = 'horizontal', onSelectionChange} = useContext(InternalTabsContext);\n let {direction} = useLocale();\n\n let children = useMemo(() => {\n let result: Node<any>[] = [];\n for (let key of collection.getKeys()) {\n result.push(collection.getItem(key)!);\n }\n return result;\n }, [collection]);\n\n let listRef = useRef<HTMLDivElement | null>(null);\n let updateOverflow = useEffectEvent(() => {\n if (orientation === 'vertical' || !listRef.current || !containerRef?.current) {\n return;\n }\n let container = listRef.current;\n let containerRect = container.getBoundingClientRect();\n let tabs = container.querySelectorAll('[data-hidden-tab]');\n let lastTab = tabs[tabs.length - 1];\n let lastTabRect = lastTab.getBoundingClientRect();\n if (direction === 'ltr') {\n setShowItems?.(lastTabRect.right <= containerRect.right);\n } else {\n setShowItems?.(lastTabRect.left >= containerRect.left);\n }\n });\n\n useResizeObserver({ref: containerRef, onResize: updateOverflow});\n\n useLayoutEffect(() => {\n if (collection.size > 0) {\n queueMicrotask(updateOverflow);\n }\n }, [collection.size, updateOverflow]);\n\n useEffect(() => {\n // Recalculate visible tags when fonts are loaded.\n document.fonts?.ready.then(() => updateOverflow());\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return (\n <>\n <HiddenTabs items={children} density={density} listRef={listRef} />\n {showItems ? (\n children.map(node => <Fragment key={node.key}>{node.render?.(node)}</Fragment>)\n ) : (\n <>\n <TabsMenu items={children} onSelectionChange={onSelectionChange} />\n </>\n )}\n </>\n );\n};\n"],"names":[],"version":3,"file":"Tabs.mjs.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-spectrum/s2",
3
- "version": "3.0.0-nightly-7eae25e12-241205",
3
+ "version": "3.0.0-nightly-8228e4efd-241207",
4
4
  "description": "Spectrum 2 UI components in React",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -57,24 +57,24 @@
57
57
  "src"
58
58
  ],
59
59
  "dependencies": {
60
- "@react-aria/collections": "3.0.0-nightly-7eae25e12-241205",
61
- "@react-aria/i18n": "^3.0.0-nightly-7eae25e12-241205",
62
- "@react-aria/interactions": "^3.0.0-nightly-7eae25e12-241205",
63
- "@react-aria/utils": "^3.0.0-nightly-7eae25e12-241205",
64
- "@react-spectrum/utils": "^3.0.0-nightly-7eae25e12-241205",
65
- "@react-stately/layout": "^3.0.0-nightly-7eae25e12-241205",
66
- "@react-stately/utils": "^3.0.0-nightly-7eae25e12-241205",
67
- "@react-stately/virtualizer": "^3.0.0-nightly-7eae25e12-241205",
68
- "@react-types/color": "^3.0.0-nightly-7eae25e12-241205",
69
- "@react-types/dialog": "^3.0.0-nightly-7eae25e12-241205",
70
- "@react-types/grid": "^3.0.0-nightly-7eae25e12-241205",
71
- "@react-types/provider": "^3.0.0-nightly-7eae25e12-241205",
72
- "@react-types/shared": "^3.0.0-nightly-7eae25e12-241205",
73
- "@react-types/table": "^3.0.0-nightly-7eae25e12-241205",
74
- "@react-types/textfield": "^3.0.0-nightly-7eae25e12-241205",
60
+ "@react-aria/collections": "3.0.0-nightly-8228e4efd-241207",
61
+ "@react-aria/i18n": "^3.0.0-nightly-8228e4efd-241207",
62
+ "@react-aria/interactions": "^3.0.0-nightly-8228e4efd-241207",
63
+ "@react-aria/utils": "^3.0.0-nightly-8228e4efd-241207",
64
+ "@react-spectrum/utils": "^3.0.0-nightly-8228e4efd-241207",
65
+ "@react-stately/layout": "^3.0.0-nightly-8228e4efd-241207",
66
+ "@react-stately/utils": "^3.0.0-nightly-8228e4efd-241207",
67
+ "@react-stately/virtualizer": "^3.0.0-nightly-8228e4efd-241207",
68
+ "@react-types/color": "^3.0.0-nightly-8228e4efd-241207",
69
+ "@react-types/dialog": "^3.0.0-nightly-8228e4efd-241207",
70
+ "@react-types/grid": "^3.0.0-nightly-8228e4efd-241207",
71
+ "@react-types/provider": "^3.0.0-nightly-8228e4efd-241207",
72
+ "@react-types/shared": "^3.0.0-nightly-8228e4efd-241207",
73
+ "@react-types/table": "^3.0.0-nightly-8228e4efd-241207",
74
+ "@react-types/textfield": "^3.0.0-nightly-8228e4efd-241207",
75
75
  "csstype": "^3.0.2",
76
- "react-aria": "^3.0.0-nightly-7eae25e12-241205",
77
- "react-aria-components": "^3.0.0-nightly-7eae25e12-241205"
76
+ "react-aria": "^3.0.0-nightly-8228e4efd-241207",
77
+ "react-aria-components": "^3.0.0-nightly-8228e4efd-241207"
78
78
  },
79
79
  "peerDependencies": {
80
80
  "@testing-library/react": "^15.0.7",
package/src/Tabs.tsx CHANGED
@@ -543,8 +543,13 @@ function CollapsingCollection({children, containerRef}) {
543
543
  _setShowItems(value);
544
544
  }
545
545
  }, [orientation]);
546
+ let ctx = useMemo(() => ({
547
+ containerRef,
548
+ showItems: orientation === 'vertical' ? true : showItems,
549
+ setShowItems
550
+ }), [containerRef, showItems, setShowItems]);
546
551
  return (
547
- <CollapseContext.Provider value={{containerRef, showItems: orientation === 'vertical' ? true : showItems, setShowItems}}>
552
+ <CollapseContext.Provider value={ctx}>
548
553
  <UNSTABLE_CollectionRendererContext.Provider value={CollapsingCollectionRenderer}>
549
554
  {children}
550
555
  </UNSTABLE_CollectionRendererContext.Provider>