@dxos/react-ui-tabs 0.9.0 → 0.9.1-main.c7dcc2e112

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.
@@ -1,10 +1,11 @@
1
1
  // src/Tabs.tsx
2
2
  import { useArrowNavigationGroup, useFocusFinders, useFocusableGroup } from "@fluentui/react-tabster";
3
3
  import { createContext } from "@radix-ui/react-context";
4
+ import { Slot } from "@radix-ui/react-slot";
4
5
  import * as TabsPrimitive from "@radix-ui/react-tabs";
5
6
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
6
- import React, { forwardRef, useCallback, useLayoutEffect } from "react";
7
- import { Button, IconButton, useForwardedRef } from "@dxos/react-ui";
7
+ import React, { useCallback, useLayoutEffect } from "react";
8
+ import { Button, IconButton, composableProps, slottable, useForwardedRef } from "@dxos/react-ui";
8
9
  import { useAttention } from "@dxos/react-ui-attention";
9
10
  import { mx } from "@dxos/ui-theme";
10
11
  var TABS_NAME = "Tabs";
@@ -14,10 +15,10 @@ var [TabsContextProvider, useTabsContext] = createContext(TABS_NAME, {
14
15
  setActivePart: () => {
15
16
  }
16
17
  });
17
- var TabsRoot = /* @__PURE__ */ forwardRef(({ children, classNames, activePart: propsActivePart, onActivePartChange, defaultActivePart, value: propsValue, onValueChange, defaultValue, orientation = "vertical", activationMode = "manual", attendableId, ...props }, forwardedRef) => {
18
+ var TabsRoot = slottable(({ children, activePart: propsActivePart, onActivePartChange, defaultActivePart, value: propsValue, onValueChange, defaultValue, orientation = "vertical", activationMode = "manual", attendableId, suppressRegionFocus = false, asChild, ...props }, forwardedRef) => {
18
19
  const tabsRoot = useForwardedRef(forwardedRef);
19
- const _1 = useArrowNavigationGroup();
20
- const _2 = useFocusableGroup();
20
+ useArrowNavigationGroup();
21
+ useFocusableGroup();
21
22
  const [activePart = "list", setActivePart] = useControllableState({
22
23
  prop: propsActivePart,
23
24
  onChange: onActivePartChange,
@@ -34,13 +35,37 @@ var TabsRoot = /* @__PURE__ */ forwardRef(({ children, classNames, activePart: p
34
35
  }, [
35
36
  value
36
37
  ]);
37
- const { findFirstFocusable } = useFocusFinders();
38
+ const { findFirstFocusable, findNextFocusable } = useFocusFinders();
38
39
  useLayoutEffect(() => {
39
- if (tabsRoot.current) {
40
- findFirstFocusable(tabsRoot.current)?.focus();
40
+ if (suppressRegionFocus) {
41
+ return;
41
42
  }
43
+ const root = tabsRoot.current;
44
+ if (!root) {
45
+ return;
46
+ }
47
+ if (activePart === "list") {
48
+ const tablist = root.querySelector('[role="tablist"]');
49
+ findFirstFocusable(tablist)?.focus();
50
+ return;
51
+ }
52
+ const panel = root.querySelector('[role="tabpanel"][data-state="active"]');
53
+ if (!panel) {
54
+ return;
55
+ }
56
+ let target = findFirstFocusable(panel);
57
+ if (target === panel) {
58
+ target = findNextFocusable(panel, {
59
+ container: panel
60
+ }) ?? void 0;
61
+ }
62
+ target?.focus();
42
63
  }, [
43
- activePart
64
+ activePart,
65
+ value,
66
+ findFirstFocusable,
67
+ findNextFocusable,
68
+ suppressRegionFocus
44
69
  ]);
45
70
  return /* @__PURE__ */ React.createElement(TabsContextProvider, {
46
71
  orientation,
@@ -49,8 +74,8 @@ var TabsRoot = /* @__PURE__ */ forwardRef(({ children, classNames, activePart: p
49
74
  value,
50
75
  attendableId
51
76
  }, /* @__PURE__ */ React.createElement(TabsPrimitive.Root, {
52
- ...props,
53
- className: mx("overflow-hidden", classNames),
77
+ ...composableProps(props),
78
+ asChild,
54
79
  orientation,
55
80
  activationMode,
56
81
  "data-active": activePart,
@@ -60,14 +85,15 @@ var TabsRoot = /* @__PURE__ */ forwardRef(({ children, classNames, activePart: p
60
85
  }, children));
61
86
  });
62
87
  TabsRoot.displayName = "Tabs.Root";
63
- var TabsViewport = ({ classNames, children, ...props }) => {
88
+ var TabsViewport = slottable(({ children, asChild, ...props }, forwardedRef) => {
64
89
  const { activePart } = useTabsContext("TabsViewport");
65
- return /* @__PURE__ */ React.createElement("div", {
66
- ...props,
90
+ const Comp = asChild ? Slot : "div";
91
+ return /* @__PURE__ */ React.createElement(Comp, {
92
+ ...composableProps(props),
67
93
  "data-active": activePart,
68
- className: mx(classNames)
94
+ ref: forwardedRef
69
95
  }, children);
70
- };
96
+ });
71
97
  TabsViewport.displayName = "Tabs.Viewport";
72
98
  var TabsTablist = ({ children, classNames, ...props }) => {
73
99
  const { orientation } = useTabsContext("TabsTablist");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/Tabs.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { useArrowNavigationGroup, useFocusFinders, useFocusableGroup } from '@fluentui/react-tabster';\nimport { createContext } from '@radix-ui/react-context';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, { type ComponentPropsWithoutRef, type MouseEvent, forwardRef, useCallback, useLayoutEffect } from 'react';\n\nimport {\n Button,\n type ButtonProps,\n IconButton,\n type IconButtonProps,\n type ThemedClassName,\n useForwardedRef,\n} from '@dxos/react-ui';\nimport { useAttention } from '@dxos/react-ui-attention';\nimport { mx } from '@dxos/ui-theme';\n\n// TODO(burdon): Move to @dxos/react-ui.\n\ntype TabsActivePart = 'list' | 'panel';\n\nconst TABS_NAME = 'Tabs';\n\n//\n// Context\n//\n\ntype TabsContextValue = {\n activePart: TabsActivePart;\n setActivePart: (nextActivePart: TabsActivePart) => void;\n attendableId?: string;\n} & Pick<TabsPrimitive.TabsProps, 'orientation' | 'value'>;\n\nconst [TabsContextProvider, useTabsContext] = createContext<TabsContextValue>(TABS_NAME, {\n orientation: 'vertical',\n activePart: 'list',\n setActivePart: () => {},\n});\n\n//\n// Root\n//\n\ntype TabsRootProps = ThemedClassName<TabsPrimitive.TabsProps> &\n Partial<\n Pick<TabsContextValue, 'activePart' | 'attendableId'> & {\n onActivePartChange: (nextActivePart: TabsActivePart) => void;\n defaultActivePart: TabsActivePart;\n }\n >;\n\nconst TabsRoot = forwardRef<HTMLDivElement, TabsRootProps>(\n (\n {\n children,\n classNames,\n activePart: propsActivePart,\n onActivePartChange,\n defaultActivePart,\n value: propsValue,\n onValueChange,\n defaultValue,\n orientation = 'vertical',\n activationMode = 'manual',\n attendableId,\n ...props\n },\n forwardedRef,\n ) => {\n const tabsRoot = useForwardedRef(forwardedRef);\n\n // TODO(thure): Without these, we get Groupper/Mover `API used before initialization`, but why?\n const _1 = useArrowNavigationGroup();\n const _2 = useFocusableGroup();\n const [activePart = 'list', setActivePart] = useControllableState({\n prop: propsActivePart,\n onChange: onActivePartChange,\n defaultProp: defaultActivePart,\n });\n\n const [value, setValue] = useControllableState({\n prop: propsValue,\n onChange: onValueChange,\n defaultProp: defaultValue,\n });\n\n const handleValueChange = useCallback(\n (nextValue: string) => {\n setActivePart('panel');\n setValue(nextValue);\n },\n [value],\n );\n\n const { findFirstFocusable } = useFocusFinders();\n\n useLayoutEffect(() => {\n if (tabsRoot.current) {\n findFirstFocusable(tabsRoot.current)?.focus();\n }\n }, [activePart]);\n\n return (\n <TabsContextProvider\n orientation={orientation}\n activePart={activePart}\n setActivePart={setActivePart}\n value={value}\n attendableId={attendableId}\n >\n <TabsPrimitive.Root\n {...props}\n className={mx('overflow-hidden', classNames)}\n orientation={orientation}\n activationMode={activationMode}\n data-active={activePart}\n value={value}\n onValueChange={handleValueChange}\n ref={tabsRoot}\n >\n {children}\n </TabsPrimitive.Root>\n </TabsContextProvider>\n );\n },\n);\n\nTabsRoot.displayName = 'Tabs.Root';\n\n//\n// Viewport\n//\n\ntype TabsViewportProps = ThemedClassName<ComponentPropsWithoutRef<'div'>>;\n\nconst TabsViewport = ({ classNames, children, ...props }: TabsViewportProps) => {\n const { activePart } = useTabsContext('TabsViewport');\n return (\n <div {...props} data-active={activePart} className={mx(classNames)}>\n {children}\n </div>\n );\n};\n\nTabsViewport.displayName = 'Tabs.Viewport';\n\n//\n// Tablist\n//\n\ntype TabsTablistProps = ThemedClassName<TabsPrimitive.TabsListProps>;\n\nconst TabsTablist = ({ children, classNames, ...props }: TabsTablistProps) => {\n const { orientation } = useTabsContext('TabsTablist');\n return (\n <TabsPrimitive.List\n {...props}\n data-arrow-keys={orientation === 'vertical' ? 'up down' : 'left right'}\n className={mx(\n 'max-h-full w-full',\n // TODO(burdon): Should be embeddable inside Toolbar (if horizontal).\n orientation === 'vertical' ? 'overflow-y-auto' : 'flex p-1 gap-1 items-stretch justify-start overflow-x-auto',\n classNames,\n )}\n >\n {children}\n </TabsPrimitive.List>\n );\n};\n\nTabsTablist.displayName = 'Tabs.Tablist';\n\n//\n// BackButton\n//\n\nconst TabsBackButton = ({ onClick, classNames, ...props }: ButtonProps) => {\n const { setActivePart } = useTabsContext('TabsBackButton');\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('list');\n return onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return <Button {...props} classNames={['@md:hidden text-start', classNames]} onClick={handleClick} />;\n};\n\nTabsBackButton.displayName = 'Tabs.BackButton';\n\n//\n// TabGroupHeading\n//\n\ntype TabsTabGroupHeadingProps = ThemedClassName<ComponentPropsWithoutRef<'h2'>>;\n\nconst TabsTabGroupHeading = ({ children, classNames, ...props }: TabsTabGroupHeadingProps) => (\n <h2 {...props} className={mx('my-1 px-2 text-sm text-un-accent', classNames)}>\n {children}\n </h2>\n);\n\nTabsTabGroupHeading.displayName = 'Tabs.TabGroupHeading';\n\n//\n// Tab\n//\n\ntype TabsTabProps = ButtonProps & Pick<TabsPrimitive.TabsTriggerProps, 'value'>;\n\nconst TabsTab = ({ value, classNames, children, onClick, ...props }: TabsTabProps) => {\n const { setActivePart, orientation, value: contextValue, attendableId } = useTabsContext('TabsTab');\n const { hasAttention } = useAttention(attendableId);\n\n const handleClick = useCallback(\n // NOTE: This handler is only called if the tab is *already active*.\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('panel');\n onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return (\n <TabsPrimitive.Trigger value={value} asChild>\n <Button\n {...props}\n variant={\n orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'\n }\n classNames={[\n orientation === 'vertical' && 'block justify-start text-start w-full',\n orientation === 'vertical' && 'dx-selected',\n classNames,\n ]}\n onClick={handleClick}\n >\n {children}\n </Button>\n </TabsPrimitive.Trigger>\n );\n};\n\nTabsTab.displayName = 'Tabs.Tab';\n\n//\n// IconTab\n//\n\ntype TabsIconTabProps = IconButtonProps & Pick<TabsPrimitive.TabsTriggerProps, 'value'>;\n\nconst TabsIconTab = ({ value, classNames, onClick, ...props }: TabsIconTabProps) => {\n const { setActivePart, orientation, value: contextValue, attendableId } = useTabsContext('TabsTab');\n const { hasAttention } = useAttention(attendableId);\n\n // NOTE: This handler is only called if the tab is *already active*.\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('panel');\n onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return (\n <TabsPrimitive.Trigger value={value} asChild>\n <IconButton\n {...props}\n variant={\n orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'\n }\n classNames={[\n orientation === 'vertical' && 'justify-start text-start w-full',\n orientation === 'vertical' && 'dx-selected',\n classNames,\n ]}\n onClick={handleClick}\n />\n </TabsPrimitive.Trigger>\n );\n};\n\nTabsIconTab.displayName = 'Tabs.IconTab';\n\n//\n// Panel\n//\n// Do NOT wrap TabsPanel children in React.Activity.\n// Radix TabsPrimitive.Content already unmounts inactive panels (no forceMount) — inactive tab\n// content is not in the DOM and effects do not run, which is the desired behaviour.\n// React.Activity (experimental in React 19) is a reconciler-level symbol that deactivates its\n// subtree when mode='hidden'. It was redundant here and prevented initial render of active panels.\n//\n\ntype TabsPanelProps = ThemedClassName<TabsPrimitive.TabsContentProps>;\n\nconst TabsPanel = ({ classNames, children, ...props }: TabsPanelProps) => (\n <TabsPrimitive.Content {...props} className={mx('p-0! dx-focus-ring-inset-over-all', classNames)}>\n {children}\n </TabsPrimitive.Content>\n);\n\nTabsPanel.displayName = 'Tabs.Panel';\n\ntype TabsTabPrimitiveProps = TabsPrimitive.TabsTriggerProps;\n\n//\n// Tabs\n//\n\nexport const Tabs = {\n Root: TabsRoot,\n Tablist: TabsTablist,\n Tab: TabsTab,\n IconTab: TabsIconTab,\n TabPrimitive: TabsPrimitive.Trigger,\n TabGroupHeading: TabsTabGroupHeading,\n Viewport: TabsViewport,\n Panel: TabsPanel,\n BackButton: TabsBackButton,\n};\n\nexport type {\n TabsActivePart,\n TabsRootProps,\n TabsTablistProps,\n TabsTabProps,\n TabsTabPrimitiveProps,\n TabsTabGroupHeadingProps,\n TabsViewportProps,\n TabsPanelProps,\n};\n"],
5
- "mappings": "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",
6
- "names": ["useArrowNavigationGroup", "useFocusFinders", "useFocusableGroup", "createContext", "TabsPrimitive", "useControllableState", "React", "forwardRef", "useCallback", "useLayoutEffect", "Button", "IconButton", "useForwardedRef", "useAttention", "mx", "TABS_NAME", "TabsContextProvider", "useTabsContext", "orientation", "activePart", "setActivePart", "TabsRoot", "children", "classNames", "propsActivePart", "onActivePartChange", "defaultActivePart", "value", "propsValue", "onValueChange", "defaultValue", "activationMode", "attendableId", "props", "forwardedRef", "tabsRoot", "_1", "_2", "prop", "onChange", "defaultProp", "setValue", "handleValueChange", "nextValue", "findFirstFocusable", "current", "focus", "Root", "className", "data-active", "ref", "displayName", "TabsViewport", "div", "TabsTablist", "List", "data-arrow-keys", "TabsBackButton", "onClick", "handleClick", "event", "TabsTabGroupHeading", "h2", "TabsTab", "contextValue", "hasAttention", "Trigger", "asChild", "variant", "TabsIconTab", "TabsPanel", "Content", "Tabs", "Tablist", "Tab", "IconTab", "TabPrimitive", "TabGroupHeading", "Viewport", "Panel", "BackButton"]
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { useArrowNavigationGroup, useFocusFinders, useFocusableGroup } from '@fluentui/react-tabster';\nimport { createContext } from '@radix-ui/react-context';\nimport { Slot } from '@radix-ui/react-slot';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, { type ComponentPropsWithoutRef, type MouseEvent, useCallback, useLayoutEffect } from 'react';\n\nimport {\n Button,\n type ButtonProps,\n IconButton,\n type IconButtonProps,\n type SlottableProps,\n type ThemedClassName,\n composableProps,\n slottable,\n useForwardedRef,\n} from '@dxos/react-ui';\nimport { useAttention } from '@dxos/react-ui-attention';\nimport { mx } from '@dxos/ui-theme';\n\n// TODO(burdon): Rewrite this; there are too many hacks/quirks.\n\ntype TabsActivePart = 'list' | 'panel';\n\nconst TABS_NAME = 'Tabs';\n\n//\n// Context\n//\n\ntype TabsContextValue = {\n activePart: TabsActivePart;\n setActivePart: (nextActivePart: TabsActivePart) => void;\n attendableId?: string;\n} & Pick<TabsPrimitive.TabsProps, 'orientation' | 'value'>;\n\nconst [TabsContextProvider, useTabsContext] = createContext<TabsContextValue>(TABS_NAME, {\n orientation: 'vertical',\n activePart: 'list',\n setActivePart: () => {},\n});\n\n//\n// Root\n//\n\ntype TabsRootCustomProps = TabsPrimitive.TabsProps &\n Partial<\n Pick<TabsContextValue, 'activePart' | 'attendableId'> & {\n onActivePartChange: (nextActivePart: TabsActivePart) => void;\n defaultActivePart: TabsActivePart;\n /** Skip master-detail focus moves (e.g. when a child form owns initial focus). */\n suppressRegionFocus?: boolean;\n }\n >;\n\ntype TabsRootProps = SlottableProps<TabsRootCustomProps>;\n\nconst TabsRoot = slottable<HTMLDivElement, TabsRootCustomProps>(\n (\n {\n children,\n activePart: propsActivePart,\n onActivePartChange,\n defaultActivePart,\n value: propsValue,\n onValueChange,\n defaultValue,\n orientation = 'vertical',\n activationMode = 'manual',\n attendableId,\n suppressRegionFocus = false,\n asChild,\n ...props\n },\n forwardedRef,\n ) => {\n const tabsRoot = useForwardedRef(forwardedRef);\n\n // TODO(thure): Without these, we get Groupper/Mover `API used before initialization`, but why?\n useArrowNavigationGroup();\n useFocusableGroup();\n const [activePart = 'list', setActivePart] = useControllableState({\n prop: propsActivePart,\n onChange: onActivePartChange,\n defaultProp: defaultActivePart,\n });\n\n const [value, setValue] = useControllableState({\n prop: propsValue,\n onChange: onValueChange,\n defaultProp: defaultValue,\n });\n\n const handleValueChange = useCallback(\n (nextValue: string) => {\n setActivePart('panel');\n setValue(nextValue);\n },\n [value],\n );\n\n const { findFirstFocusable, findNextFocusable } = useFocusFinders();\n\n useLayoutEffect(() => {\n if (suppressRegionFocus) {\n return;\n }\n\n const root = tabsRoot.current;\n if (!root) {\n return;\n }\n\n if (activePart === 'list') {\n const tablist = root.querySelector<HTMLElement>('[role=\"tablist\"]');\n findFirstFocusable(tablist)?.focus();\n return;\n }\n\n const panel = root.querySelector<HTMLElement>('[role=\"tabpanel\"][data-state=\"active\"]');\n if (!panel) {\n return;\n }\n\n // Radix marks the active panel focusable for roving tabindex; skip it so content receives focus.\n let target = findFirstFocusable(panel);\n if (target === panel) {\n target = findNextFocusable(panel, { container: panel }) ?? undefined;\n }\n target?.focus();\n }, [activePart, value, findFirstFocusable, findNextFocusable, suppressRegionFocus]);\n\n return (\n <TabsContextProvider\n orientation={orientation}\n activePart={activePart}\n setActivePart={setActivePart}\n value={value}\n attendableId={attendableId}\n >\n <TabsPrimitive.Root\n {...composableProps<HTMLDivElement>(props)}\n asChild={asChild}\n orientation={orientation}\n activationMode={activationMode}\n data-active={activePart}\n value={value}\n onValueChange={handleValueChange}\n ref={tabsRoot}\n >\n {children}\n </TabsPrimitive.Root>\n </TabsContextProvider>\n );\n },\n);\n\nTabsRoot.displayName = 'Tabs.Root';\n\n//\n// Viewport\n//\n\ntype TabsViewportProps = SlottableProps<\n Omit<ComponentPropsWithoutRef<'div'>, 'className' | 'style' | 'children' | 'role'>\n>;\n\nconst TabsViewport = slottable<\n HTMLDivElement,\n Omit<ComponentPropsWithoutRef<'div'>, 'className' | 'style' | 'children' | 'role'>\n>(({ children, asChild, ...props }, forwardedRef) => {\n const { activePart } = useTabsContext('TabsViewport');\n const Comp = asChild ? Slot : 'div';\n return (\n <Comp {...composableProps<HTMLDivElement>(props)} data-active={activePart} ref={forwardedRef}>\n {children}\n </Comp>\n );\n});\n\nTabsViewport.displayName = 'Tabs.Viewport';\n\n//\n// Tablist\n//\n\ntype TabsTablistProps = ThemedClassName<TabsPrimitive.TabsListProps>;\n\nconst TabsTablist = ({ children, classNames, ...props }: TabsTablistProps) => {\n const { orientation } = useTabsContext('TabsTablist');\n return (\n <TabsPrimitive.List\n {...props}\n data-arrow-keys={orientation === 'vertical' ? 'up down' : 'left right'}\n className={mx(\n 'max-h-full w-full',\n // TODO(burdon): Should be embeddable inside Toolbar (if horizontal).\n orientation === 'vertical' ? 'overflow-y-auto' : 'flex p-1 gap-1 items-stretch justify-start overflow-x-auto',\n classNames,\n )}\n >\n {children}\n </TabsPrimitive.List>\n );\n};\n\nTabsTablist.displayName = 'Tabs.Tablist';\n\n//\n// BackButton\n//\n\nconst TabsBackButton = ({ onClick, classNames, ...props }: ButtonProps) => {\n const { setActivePart } = useTabsContext('TabsBackButton');\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('list');\n return onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return <Button {...props} classNames={['@md:hidden text-start', classNames]} onClick={handleClick} />;\n};\n\nTabsBackButton.displayName = 'Tabs.BackButton';\n\n//\n// TabGroupHeading\n//\n\ntype TabsTabGroupHeadingProps = ThemedClassName<ComponentPropsWithoutRef<'h2'>>;\n\nconst TabsTabGroupHeading = ({ children, classNames, ...props }: TabsTabGroupHeadingProps) => (\n <h2 {...props} className={mx('my-1 px-2 text-sm text-un-accent', classNames)}>\n {children}\n </h2>\n);\n\nTabsTabGroupHeading.displayName = 'Tabs.TabGroupHeading';\n\n//\n// Tab\n//\n\ntype TabsTabProps = ButtonProps & Pick<TabsPrimitive.TabsTriggerProps, 'value'>;\n\nconst TabsTab = ({ value, classNames, children, onClick, ...props }: TabsTabProps) => {\n const { setActivePart, orientation, value: contextValue, attendableId } = useTabsContext('TabsTab');\n const { hasAttention } = useAttention(attendableId);\n\n const handleClick = useCallback(\n // NOTE: This handler is only called if the tab is *already active*.\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('panel');\n onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return (\n <TabsPrimitive.Trigger value={value} asChild>\n <Button\n {...props}\n variant={\n orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'\n }\n classNames={[\n orientation === 'vertical' && 'block justify-start text-start w-full',\n orientation === 'vertical' && 'dx-selected',\n classNames,\n ]}\n onClick={handleClick}\n >\n {children}\n </Button>\n </TabsPrimitive.Trigger>\n );\n};\n\nTabsTab.displayName = 'Tabs.Tab';\n\n//\n// IconTab\n//\n\ntype TabsIconTabProps = IconButtonProps & Pick<TabsPrimitive.TabsTriggerProps, 'value'>;\n\nconst TabsIconTab = ({ value, classNames, onClick, ...props }: TabsIconTabProps) => {\n const { setActivePart, orientation, value: contextValue, attendableId } = useTabsContext('TabsTab');\n const { hasAttention } = useAttention(attendableId);\n\n // NOTE: This handler is only called if the tab is *already active*.\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('panel');\n onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return (\n <TabsPrimitive.Trigger value={value} asChild>\n <IconButton\n {...props}\n variant={\n orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'\n }\n classNames={[\n orientation === 'vertical' && 'justify-start text-start w-full',\n orientation === 'vertical' && 'dx-selected',\n classNames,\n ]}\n onClick={handleClick}\n />\n </TabsPrimitive.Trigger>\n );\n};\n\nTabsIconTab.displayName = 'Tabs.IconTab';\n\n//\n// Panel\n//\n// Do NOT wrap TabsPanel children in React.Activity.\n// Radix TabsPrimitive.Content already unmounts inactive panels (no forceMount) — inactive tab\n// content is not in the DOM and effects do not run, which is the desired behaviour.\n// React.Activity (experimental in React 19) is a reconciler-level symbol that deactivates its\n// subtree when mode='hidden'. It was redundant here and prevented initial render of active panels.\n//\n\ntype TabsPanelProps = ThemedClassName<TabsPrimitive.TabsContentProps>;\n\nconst TabsPanel = ({ classNames, children, ...props }: TabsPanelProps) => (\n <TabsPrimitive.Content {...props} className={mx('p-0! dx-focus-ring-inset-over-all', classNames)}>\n {children}\n </TabsPrimitive.Content>\n);\n\nTabsPanel.displayName = 'Tabs.Panel';\n\ntype TabsTabPrimitiveProps = TabsPrimitive.TabsTriggerProps;\n\n//\n// Tabs\n//\n\nexport const Tabs = {\n Root: TabsRoot,\n Tablist: TabsTablist,\n Tab: TabsTab,\n IconTab: TabsIconTab,\n TabPrimitive: TabsPrimitive.Trigger,\n TabGroupHeading: TabsTabGroupHeading,\n Viewport: TabsViewport,\n Panel: TabsPanel,\n BackButton: TabsBackButton,\n};\n\nexport type {\n TabsActivePart,\n TabsRootProps,\n TabsTablistProps,\n TabsTabProps,\n TabsTabPrimitiveProps,\n TabsTabGroupHeadingProps,\n TabsViewportProps,\n TabsPanelProps,\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["useArrowNavigationGroup", "useFocusFinders", "useFocusableGroup", "createContext", "Slot", "TabsPrimitive", "useControllableState", "React", "useCallback", "useLayoutEffect", "Button", "IconButton", "composableProps", "slottable", "useForwardedRef", "useAttention", "mx", "TABS_NAME", "TabsContextProvider", "useTabsContext", "orientation", "activePart", "setActivePart", "TabsRoot", "children", "propsActivePart", "onActivePartChange", "defaultActivePart", "value", "propsValue", "onValueChange", "defaultValue", "activationMode", "attendableId", "suppressRegionFocus", "asChild", "props", "forwardedRef", "tabsRoot", "prop", "onChange", "defaultProp", "setValue", "handleValueChange", "nextValue", "findFirstFocusable", "findNextFocusable", "root", "current", "tablist", "querySelector", "focus", "panel", "target", "container", "undefined", "Root", "data-active", "ref", "displayName", "TabsViewport", "Comp", "TabsTablist", "classNames", "List", "data-arrow-keys", "className", "TabsBackButton", "onClick", "handleClick", "event", "TabsTabGroupHeading", "h2", "TabsTab", "contextValue", "hasAttention", "Trigger", "variant", "TabsIconTab", "TabsPanel", "Content", "Tabs", "Tablist", "Tab", "IconTab", "TabPrimitive", "TabGroupHeading", "Viewport", "Panel", "BackButton"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"src/Tabs.tsx":{"bytes":26241,"imports":[{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-tabs","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":368,"imports":[{"path":"src/Tabs.tsx","kind":"import-statement","original":"./Tabs"}],"format":"esm"}},"outputs":{"dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14203},"dist/lib/browser/index.mjs":{"imports":[{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-tabs","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"exports":["Tabs"],"entryPoint":"src/index.ts","inputs":{"src/Tabs.tsx":{"bytesInOutput":6267},"src/index.ts":{"bytesInOutput":0}},"bytes":6337}}}
1
+ {"inputs":{"src/Tabs.tsx":{"bytes":29707,"imports":[{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"@radix-ui/react-tabs","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":368,"imports":[{"path":"src/Tabs.tsx","kind":"import-statement","original":"./Tabs"}],"format":"esm"}},"outputs":{"dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16099},"dist/lib/browser/index.mjs":{"imports":[{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"@radix-ui/react-tabs","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"exports":["Tabs"],"entryPoint":"src/index.ts","inputs":{"src/Tabs.tsx":{"bytesInOutput":6965},"src/index.ts":{"bytesInOutput":0}},"bytes":7035}}}
@@ -3,10 +3,11 @@ import { createRequire } from 'node:module';const require = createRequire(import
3
3
  // src/Tabs.tsx
4
4
  import { useArrowNavigationGroup, useFocusFinders, useFocusableGroup } from "@fluentui/react-tabster";
5
5
  import { createContext } from "@radix-ui/react-context";
6
+ import { Slot } from "@radix-ui/react-slot";
6
7
  import * as TabsPrimitive from "@radix-ui/react-tabs";
7
8
  import { useControllableState } from "@radix-ui/react-use-controllable-state";
8
- import React, { forwardRef, useCallback, useLayoutEffect } from "react";
9
- import { Button, IconButton, useForwardedRef } from "@dxos/react-ui";
9
+ import React, { useCallback, useLayoutEffect } from "react";
10
+ import { Button, IconButton, composableProps, slottable, useForwardedRef } from "@dxos/react-ui";
10
11
  import { useAttention } from "@dxos/react-ui-attention";
11
12
  import { mx } from "@dxos/ui-theme";
12
13
  var TABS_NAME = "Tabs";
@@ -16,10 +17,10 @@ var [TabsContextProvider, useTabsContext] = createContext(TABS_NAME, {
16
17
  setActivePart: () => {
17
18
  }
18
19
  });
19
- var TabsRoot = /* @__PURE__ */ forwardRef(({ children, classNames, activePart: propsActivePart, onActivePartChange, defaultActivePart, value: propsValue, onValueChange, defaultValue, orientation = "vertical", activationMode = "manual", attendableId, ...props }, forwardedRef) => {
20
+ var TabsRoot = slottable(({ children, activePart: propsActivePart, onActivePartChange, defaultActivePart, value: propsValue, onValueChange, defaultValue, orientation = "vertical", activationMode = "manual", attendableId, suppressRegionFocus = false, asChild, ...props }, forwardedRef) => {
20
21
  const tabsRoot = useForwardedRef(forwardedRef);
21
- const _1 = useArrowNavigationGroup();
22
- const _2 = useFocusableGroup();
22
+ useArrowNavigationGroup();
23
+ useFocusableGroup();
23
24
  const [activePart = "list", setActivePart] = useControllableState({
24
25
  prop: propsActivePart,
25
26
  onChange: onActivePartChange,
@@ -36,13 +37,37 @@ var TabsRoot = /* @__PURE__ */ forwardRef(({ children, classNames, activePart: p
36
37
  }, [
37
38
  value
38
39
  ]);
39
- const { findFirstFocusable } = useFocusFinders();
40
+ const { findFirstFocusable, findNextFocusable } = useFocusFinders();
40
41
  useLayoutEffect(() => {
41
- if (tabsRoot.current) {
42
- findFirstFocusable(tabsRoot.current)?.focus();
42
+ if (suppressRegionFocus) {
43
+ return;
43
44
  }
45
+ const root = tabsRoot.current;
46
+ if (!root) {
47
+ return;
48
+ }
49
+ if (activePart === "list") {
50
+ const tablist = root.querySelector('[role="tablist"]');
51
+ findFirstFocusable(tablist)?.focus();
52
+ return;
53
+ }
54
+ const panel = root.querySelector('[role="tabpanel"][data-state="active"]');
55
+ if (!panel) {
56
+ return;
57
+ }
58
+ let target = findFirstFocusable(panel);
59
+ if (target === panel) {
60
+ target = findNextFocusable(panel, {
61
+ container: panel
62
+ }) ?? void 0;
63
+ }
64
+ target?.focus();
44
65
  }, [
45
- activePart
66
+ activePart,
67
+ value,
68
+ findFirstFocusable,
69
+ findNextFocusable,
70
+ suppressRegionFocus
46
71
  ]);
47
72
  return /* @__PURE__ */ React.createElement(TabsContextProvider, {
48
73
  orientation,
@@ -51,8 +76,8 @@ var TabsRoot = /* @__PURE__ */ forwardRef(({ children, classNames, activePart: p
51
76
  value,
52
77
  attendableId
53
78
  }, /* @__PURE__ */ React.createElement(TabsPrimitive.Root, {
54
- ...props,
55
- className: mx("overflow-hidden", classNames),
79
+ ...composableProps(props),
80
+ asChild,
56
81
  orientation,
57
82
  activationMode,
58
83
  "data-active": activePart,
@@ -62,14 +87,15 @@ var TabsRoot = /* @__PURE__ */ forwardRef(({ children, classNames, activePart: p
62
87
  }, children));
63
88
  });
64
89
  TabsRoot.displayName = "Tabs.Root";
65
- var TabsViewport = ({ classNames, children, ...props }) => {
90
+ var TabsViewport = slottable(({ children, asChild, ...props }, forwardedRef) => {
66
91
  const { activePart } = useTabsContext("TabsViewport");
67
- return /* @__PURE__ */ React.createElement("div", {
68
- ...props,
92
+ const Comp = asChild ? Slot : "div";
93
+ return /* @__PURE__ */ React.createElement(Comp, {
94
+ ...composableProps(props),
69
95
  "data-active": activePart,
70
- className: mx(classNames)
96
+ ref: forwardedRef
71
97
  }, children);
72
- };
98
+ });
73
99
  TabsViewport.displayName = "Tabs.Viewport";
74
100
  var TabsTablist = ({ children, classNames, ...props }) => {
75
101
  const { orientation } = useTabsContext("TabsTablist");
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/Tabs.tsx"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { useArrowNavigationGroup, useFocusFinders, useFocusableGroup } from '@fluentui/react-tabster';\nimport { createContext } from '@radix-ui/react-context';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, { type ComponentPropsWithoutRef, type MouseEvent, forwardRef, useCallback, useLayoutEffect } from 'react';\n\nimport {\n Button,\n type ButtonProps,\n IconButton,\n type IconButtonProps,\n type ThemedClassName,\n useForwardedRef,\n} from '@dxos/react-ui';\nimport { useAttention } from '@dxos/react-ui-attention';\nimport { mx } from '@dxos/ui-theme';\n\n// TODO(burdon): Move to @dxos/react-ui.\n\ntype TabsActivePart = 'list' | 'panel';\n\nconst TABS_NAME = 'Tabs';\n\n//\n// Context\n//\n\ntype TabsContextValue = {\n activePart: TabsActivePart;\n setActivePart: (nextActivePart: TabsActivePart) => void;\n attendableId?: string;\n} & Pick<TabsPrimitive.TabsProps, 'orientation' | 'value'>;\n\nconst [TabsContextProvider, useTabsContext] = createContext<TabsContextValue>(TABS_NAME, {\n orientation: 'vertical',\n activePart: 'list',\n setActivePart: () => {},\n});\n\n//\n// Root\n//\n\ntype TabsRootProps = ThemedClassName<TabsPrimitive.TabsProps> &\n Partial<\n Pick<TabsContextValue, 'activePart' | 'attendableId'> & {\n onActivePartChange: (nextActivePart: TabsActivePart) => void;\n defaultActivePart: TabsActivePart;\n }\n >;\n\nconst TabsRoot = forwardRef<HTMLDivElement, TabsRootProps>(\n (\n {\n children,\n classNames,\n activePart: propsActivePart,\n onActivePartChange,\n defaultActivePart,\n value: propsValue,\n onValueChange,\n defaultValue,\n orientation = 'vertical',\n activationMode = 'manual',\n attendableId,\n ...props\n },\n forwardedRef,\n ) => {\n const tabsRoot = useForwardedRef(forwardedRef);\n\n // TODO(thure): Without these, we get Groupper/Mover `API used before initialization`, but why?\n const _1 = useArrowNavigationGroup();\n const _2 = useFocusableGroup();\n const [activePart = 'list', setActivePart] = useControllableState({\n prop: propsActivePart,\n onChange: onActivePartChange,\n defaultProp: defaultActivePart,\n });\n\n const [value, setValue] = useControllableState({\n prop: propsValue,\n onChange: onValueChange,\n defaultProp: defaultValue,\n });\n\n const handleValueChange = useCallback(\n (nextValue: string) => {\n setActivePart('panel');\n setValue(nextValue);\n },\n [value],\n );\n\n const { findFirstFocusable } = useFocusFinders();\n\n useLayoutEffect(() => {\n if (tabsRoot.current) {\n findFirstFocusable(tabsRoot.current)?.focus();\n }\n }, [activePart]);\n\n return (\n <TabsContextProvider\n orientation={orientation}\n activePart={activePart}\n setActivePart={setActivePart}\n value={value}\n attendableId={attendableId}\n >\n <TabsPrimitive.Root\n {...props}\n className={mx('overflow-hidden', classNames)}\n orientation={orientation}\n activationMode={activationMode}\n data-active={activePart}\n value={value}\n onValueChange={handleValueChange}\n ref={tabsRoot}\n >\n {children}\n </TabsPrimitive.Root>\n </TabsContextProvider>\n );\n },\n);\n\nTabsRoot.displayName = 'Tabs.Root';\n\n//\n// Viewport\n//\n\ntype TabsViewportProps = ThemedClassName<ComponentPropsWithoutRef<'div'>>;\n\nconst TabsViewport = ({ classNames, children, ...props }: TabsViewportProps) => {\n const { activePart } = useTabsContext('TabsViewport');\n return (\n <div {...props} data-active={activePart} className={mx(classNames)}>\n {children}\n </div>\n );\n};\n\nTabsViewport.displayName = 'Tabs.Viewport';\n\n//\n// Tablist\n//\n\ntype TabsTablistProps = ThemedClassName<TabsPrimitive.TabsListProps>;\n\nconst TabsTablist = ({ children, classNames, ...props }: TabsTablistProps) => {\n const { orientation } = useTabsContext('TabsTablist');\n return (\n <TabsPrimitive.List\n {...props}\n data-arrow-keys={orientation === 'vertical' ? 'up down' : 'left right'}\n className={mx(\n 'max-h-full w-full',\n // TODO(burdon): Should be embeddable inside Toolbar (if horizontal).\n orientation === 'vertical' ? 'overflow-y-auto' : 'flex p-1 gap-1 items-stretch justify-start overflow-x-auto',\n classNames,\n )}\n >\n {children}\n </TabsPrimitive.List>\n );\n};\n\nTabsTablist.displayName = 'Tabs.Tablist';\n\n//\n// BackButton\n//\n\nconst TabsBackButton = ({ onClick, classNames, ...props }: ButtonProps) => {\n const { setActivePart } = useTabsContext('TabsBackButton');\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('list');\n return onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return <Button {...props} classNames={['@md:hidden text-start', classNames]} onClick={handleClick} />;\n};\n\nTabsBackButton.displayName = 'Tabs.BackButton';\n\n//\n// TabGroupHeading\n//\n\ntype TabsTabGroupHeadingProps = ThemedClassName<ComponentPropsWithoutRef<'h2'>>;\n\nconst TabsTabGroupHeading = ({ children, classNames, ...props }: TabsTabGroupHeadingProps) => (\n <h2 {...props} className={mx('my-1 px-2 text-sm text-un-accent', classNames)}>\n {children}\n </h2>\n);\n\nTabsTabGroupHeading.displayName = 'Tabs.TabGroupHeading';\n\n//\n// Tab\n//\n\ntype TabsTabProps = ButtonProps & Pick<TabsPrimitive.TabsTriggerProps, 'value'>;\n\nconst TabsTab = ({ value, classNames, children, onClick, ...props }: TabsTabProps) => {\n const { setActivePart, orientation, value: contextValue, attendableId } = useTabsContext('TabsTab');\n const { hasAttention } = useAttention(attendableId);\n\n const handleClick = useCallback(\n // NOTE: This handler is only called if the tab is *already active*.\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('panel');\n onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return (\n <TabsPrimitive.Trigger value={value} asChild>\n <Button\n {...props}\n variant={\n orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'\n }\n classNames={[\n orientation === 'vertical' && 'block justify-start text-start w-full',\n orientation === 'vertical' && 'dx-selected',\n classNames,\n ]}\n onClick={handleClick}\n >\n {children}\n </Button>\n </TabsPrimitive.Trigger>\n );\n};\n\nTabsTab.displayName = 'Tabs.Tab';\n\n//\n// IconTab\n//\n\ntype TabsIconTabProps = IconButtonProps & Pick<TabsPrimitive.TabsTriggerProps, 'value'>;\n\nconst TabsIconTab = ({ value, classNames, onClick, ...props }: TabsIconTabProps) => {\n const { setActivePart, orientation, value: contextValue, attendableId } = useTabsContext('TabsTab');\n const { hasAttention } = useAttention(attendableId);\n\n // NOTE: This handler is only called if the tab is *already active*.\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('panel');\n onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return (\n <TabsPrimitive.Trigger value={value} asChild>\n <IconButton\n {...props}\n variant={\n orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'\n }\n classNames={[\n orientation === 'vertical' && 'justify-start text-start w-full',\n orientation === 'vertical' && 'dx-selected',\n classNames,\n ]}\n onClick={handleClick}\n />\n </TabsPrimitive.Trigger>\n );\n};\n\nTabsIconTab.displayName = 'Tabs.IconTab';\n\n//\n// Panel\n//\n// Do NOT wrap TabsPanel children in React.Activity.\n// Radix TabsPrimitive.Content already unmounts inactive panels (no forceMount) — inactive tab\n// content is not in the DOM and effects do not run, which is the desired behaviour.\n// React.Activity (experimental in React 19) is a reconciler-level symbol that deactivates its\n// subtree when mode='hidden'. It was redundant here and prevented initial render of active panels.\n//\n\ntype TabsPanelProps = ThemedClassName<TabsPrimitive.TabsContentProps>;\n\nconst TabsPanel = ({ classNames, children, ...props }: TabsPanelProps) => (\n <TabsPrimitive.Content {...props} className={mx('p-0! dx-focus-ring-inset-over-all', classNames)}>\n {children}\n </TabsPrimitive.Content>\n);\n\nTabsPanel.displayName = 'Tabs.Panel';\n\ntype TabsTabPrimitiveProps = TabsPrimitive.TabsTriggerProps;\n\n//\n// Tabs\n//\n\nexport const Tabs = {\n Root: TabsRoot,\n Tablist: TabsTablist,\n Tab: TabsTab,\n IconTab: TabsIconTab,\n TabPrimitive: TabsPrimitive.Trigger,\n TabGroupHeading: TabsTabGroupHeading,\n Viewport: TabsViewport,\n Panel: TabsPanel,\n BackButton: TabsBackButton,\n};\n\nexport type {\n TabsActivePart,\n TabsRootProps,\n TabsTablistProps,\n TabsTabProps,\n TabsTabPrimitiveProps,\n TabsTabGroupHeadingProps,\n TabsViewportProps,\n TabsPanelProps,\n};\n"],
5
- "mappings": "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",
6
- "names": ["useArrowNavigationGroup", "useFocusFinders", "useFocusableGroup", "createContext", "TabsPrimitive", "useControllableState", "React", "forwardRef", "useCallback", "useLayoutEffect", "Button", "IconButton", "useForwardedRef", "useAttention", "mx", "TABS_NAME", "TabsContextProvider", "useTabsContext", "orientation", "activePart", "setActivePart", "TabsRoot", "children", "classNames", "propsActivePart", "onActivePartChange", "defaultActivePart", "value", "propsValue", "onValueChange", "defaultValue", "activationMode", "attendableId", "props", "forwardedRef", "tabsRoot", "_1", "_2", "prop", "onChange", "defaultProp", "setValue", "handleValueChange", "nextValue", "findFirstFocusable", "current", "focus", "Root", "className", "data-active", "ref", "displayName", "TabsViewport", "div", "TabsTablist", "List", "data-arrow-keys", "TabsBackButton", "onClick", "handleClick", "event", "TabsTabGroupHeading", "h2", "TabsTab", "contextValue", "hasAttention", "Trigger", "asChild", "variant", "TabsIconTab", "TabsPanel", "Content", "Tabs", "Tablist", "Tab", "IconTab", "TabPrimitive", "TabGroupHeading", "Viewport", "Panel", "BackButton"]
4
+ "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { useArrowNavigationGroup, useFocusFinders, useFocusableGroup } from '@fluentui/react-tabster';\nimport { createContext } from '@radix-ui/react-context';\nimport { Slot } from '@radix-ui/react-slot';\nimport * as TabsPrimitive from '@radix-ui/react-tabs';\nimport { useControllableState } from '@radix-ui/react-use-controllable-state';\nimport React, { type ComponentPropsWithoutRef, type MouseEvent, useCallback, useLayoutEffect } from 'react';\n\nimport {\n Button,\n type ButtonProps,\n IconButton,\n type IconButtonProps,\n type SlottableProps,\n type ThemedClassName,\n composableProps,\n slottable,\n useForwardedRef,\n} from '@dxos/react-ui';\nimport { useAttention } from '@dxos/react-ui-attention';\nimport { mx } from '@dxos/ui-theme';\n\n// TODO(burdon): Rewrite this; there are too many hacks/quirks.\n\ntype TabsActivePart = 'list' | 'panel';\n\nconst TABS_NAME = 'Tabs';\n\n//\n// Context\n//\n\ntype TabsContextValue = {\n activePart: TabsActivePart;\n setActivePart: (nextActivePart: TabsActivePart) => void;\n attendableId?: string;\n} & Pick<TabsPrimitive.TabsProps, 'orientation' | 'value'>;\n\nconst [TabsContextProvider, useTabsContext] = createContext<TabsContextValue>(TABS_NAME, {\n orientation: 'vertical',\n activePart: 'list',\n setActivePart: () => {},\n});\n\n//\n// Root\n//\n\ntype TabsRootCustomProps = TabsPrimitive.TabsProps &\n Partial<\n Pick<TabsContextValue, 'activePart' | 'attendableId'> & {\n onActivePartChange: (nextActivePart: TabsActivePart) => void;\n defaultActivePart: TabsActivePart;\n /** Skip master-detail focus moves (e.g. when a child form owns initial focus). */\n suppressRegionFocus?: boolean;\n }\n >;\n\ntype TabsRootProps = SlottableProps<TabsRootCustomProps>;\n\nconst TabsRoot = slottable<HTMLDivElement, TabsRootCustomProps>(\n (\n {\n children,\n activePart: propsActivePart,\n onActivePartChange,\n defaultActivePart,\n value: propsValue,\n onValueChange,\n defaultValue,\n orientation = 'vertical',\n activationMode = 'manual',\n attendableId,\n suppressRegionFocus = false,\n asChild,\n ...props\n },\n forwardedRef,\n ) => {\n const tabsRoot = useForwardedRef(forwardedRef);\n\n // TODO(thure): Without these, we get Groupper/Mover `API used before initialization`, but why?\n useArrowNavigationGroup();\n useFocusableGroup();\n const [activePart = 'list', setActivePart] = useControllableState({\n prop: propsActivePart,\n onChange: onActivePartChange,\n defaultProp: defaultActivePart,\n });\n\n const [value, setValue] = useControllableState({\n prop: propsValue,\n onChange: onValueChange,\n defaultProp: defaultValue,\n });\n\n const handleValueChange = useCallback(\n (nextValue: string) => {\n setActivePart('panel');\n setValue(nextValue);\n },\n [value],\n );\n\n const { findFirstFocusable, findNextFocusable } = useFocusFinders();\n\n useLayoutEffect(() => {\n if (suppressRegionFocus) {\n return;\n }\n\n const root = tabsRoot.current;\n if (!root) {\n return;\n }\n\n if (activePart === 'list') {\n const tablist = root.querySelector<HTMLElement>('[role=\"tablist\"]');\n findFirstFocusable(tablist)?.focus();\n return;\n }\n\n const panel = root.querySelector<HTMLElement>('[role=\"tabpanel\"][data-state=\"active\"]');\n if (!panel) {\n return;\n }\n\n // Radix marks the active panel focusable for roving tabindex; skip it so content receives focus.\n let target = findFirstFocusable(panel);\n if (target === panel) {\n target = findNextFocusable(panel, { container: panel }) ?? undefined;\n }\n target?.focus();\n }, [activePart, value, findFirstFocusable, findNextFocusable, suppressRegionFocus]);\n\n return (\n <TabsContextProvider\n orientation={orientation}\n activePart={activePart}\n setActivePart={setActivePart}\n value={value}\n attendableId={attendableId}\n >\n <TabsPrimitive.Root\n {...composableProps<HTMLDivElement>(props)}\n asChild={asChild}\n orientation={orientation}\n activationMode={activationMode}\n data-active={activePart}\n value={value}\n onValueChange={handleValueChange}\n ref={tabsRoot}\n >\n {children}\n </TabsPrimitive.Root>\n </TabsContextProvider>\n );\n },\n);\n\nTabsRoot.displayName = 'Tabs.Root';\n\n//\n// Viewport\n//\n\ntype TabsViewportProps = SlottableProps<\n Omit<ComponentPropsWithoutRef<'div'>, 'className' | 'style' | 'children' | 'role'>\n>;\n\nconst TabsViewport = slottable<\n HTMLDivElement,\n Omit<ComponentPropsWithoutRef<'div'>, 'className' | 'style' | 'children' | 'role'>\n>(({ children, asChild, ...props }, forwardedRef) => {\n const { activePart } = useTabsContext('TabsViewport');\n const Comp = asChild ? Slot : 'div';\n return (\n <Comp {...composableProps<HTMLDivElement>(props)} data-active={activePart} ref={forwardedRef}>\n {children}\n </Comp>\n );\n});\n\nTabsViewport.displayName = 'Tabs.Viewport';\n\n//\n// Tablist\n//\n\ntype TabsTablistProps = ThemedClassName<TabsPrimitive.TabsListProps>;\n\nconst TabsTablist = ({ children, classNames, ...props }: TabsTablistProps) => {\n const { orientation } = useTabsContext('TabsTablist');\n return (\n <TabsPrimitive.List\n {...props}\n data-arrow-keys={orientation === 'vertical' ? 'up down' : 'left right'}\n className={mx(\n 'max-h-full w-full',\n // TODO(burdon): Should be embeddable inside Toolbar (if horizontal).\n orientation === 'vertical' ? 'overflow-y-auto' : 'flex p-1 gap-1 items-stretch justify-start overflow-x-auto',\n classNames,\n )}\n >\n {children}\n </TabsPrimitive.List>\n );\n};\n\nTabsTablist.displayName = 'Tabs.Tablist';\n\n//\n// BackButton\n//\n\nconst TabsBackButton = ({ onClick, classNames, ...props }: ButtonProps) => {\n const { setActivePart } = useTabsContext('TabsBackButton');\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('list');\n return onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return <Button {...props} classNames={['@md:hidden text-start', classNames]} onClick={handleClick} />;\n};\n\nTabsBackButton.displayName = 'Tabs.BackButton';\n\n//\n// TabGroupHeading\n//\n\ntype TabsTabGroupHeadingProps = ThemedClassName<ComponentPropsWithoutRef<'h2'>>;\n\nconst TabsTabGroupHeading = ({ children, classNames, ...props }: TabsTabGroupHeadingProps) => (\n <h2 {...props} className={mx('my-1 px-2 text-sm text-un-accent', classNames)}>\n {children}\n </h2>\n);\n\nTabsTabGroupHeading.displayName = 'Tabs.TabGroupHeading';\n\n//\n// Tab\n//\n\ntype TabsTabProps = ButtonProps & Pick<TabsPrimitive.TabsTriggerProps, 'value'>;\n\nconst TabsTab = ({ value, classNames, children, onClick, ...props }: TabsTabProps) => {\n const { setActivePart, orientation, value: contextValue, attendableId } = useTabsContext('TabsTab');\n const { hasAttention } = useAttention(attendableId);\n\n const handleClick = useCallback(\n // NOTE: This handler is only called if the tab is *already active*.\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('panel');\n onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return (\n <TabsPrimitive.Trigger value={value} asChild>\n <Button\n {...props}\n variant={\n orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'\n }\n classNames={[\n orientation === 'vertical' && 'block justify-start text-start w-full',\n orientation === 'vertical' && 'dx-selected',\n classNames,\n ]}\n onClick={handleClick}\n >\n {children}\n </Button>\n </TabsPrimitive.Trigger>\n );\n};\n\nTabsTab.displayName = 'Tabs.Tab';\n\n//\n// IconTab\n//\n\ntype TabsIconTabProps = IconButtonProps & Pick<TabsPrimitive.TabsTriggerProps, 'value'>;\n\nconst TabsIconTab = ({ value, classNames, onClick, ...props }: TabsIconTabProps) => {\n const { setActivePart, orientation, value: contextValue, attendableId } = useTabsContext('TabsTab');\n const { hasAttention } = useAttention(attendableId);\n\n // NOTE: This handler is only called if the tab is *already active*.\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n setActivePart('panel');\n onClick?.(event);\n },\n [setActivePart, onClick],\n );\n\n return (\n <TabsPrimitive.Trigger value={value} asChild>\n <IconButton\n {...props}\n variant={\n orientation === 'horizontal' && contextValue === value ? (hasAttention ? 'primary' : 'default') : 'ghost'\n }\n classNames={[\n orientation === 'vertical' && 'justify-start text-start w-full',\n orientation === 'vertical' && 'dx-selected',\n classNames,\n ]}\n onClick={handleClick}\n />\n </TabsPrimitive.Trigger>\n );\n};\n\nTabsIconTab.displayName = 'Tabs.IconTab';\n\n//\n// Panel\n//\n// Do NOT wrap TabsPanel children in React.Activity.\n// Radix TabsPrimitive.Content already unmounts inactive panels (no forceMount) — inactive tab\n// content is not in the DOM and effects do not run, which is the desired behaviour.\n// React.Activity (experimental in React 19) is a reconciler-level symbol that deactivates its\n// subtree when mode='hidden'. It was redundant here and prevented initial render of active panels.\n//\n\ntype TabsPanelProps = ThemedClassName<TabsPrimitive.TabsContentProps>;\n\nconst TabsPanel = ({ classNames, children, ...props }: TabsPanelProps) => (\n <TabsPrimitive.Content {...props} className={mx('p-0! dx-focus-ring-inset-over-all', classNames)}>\n {children}\n </TabsPrimitive.Content>\n);\n\nTabsPanel.displayName = 'Tabs.Panel';\n\ntype TabsTabPrimitiveProps = TabsPrimitive.TabsTriggerProps;\n\n//\n// Tabs\n//\n\nexport const Tabs = {\n Root: TabsRoot,\n Tablist: TabsTablist,\n Tab: TabsTab,\n IconTab: TabsIconTab,\n TabPrimitive: TabsPrimitive.Trigger,\n TabGroupHeading: TabsTabGroupHeading,\n Viewport: TabsViewport,\n Panel: TabsPanel,\n BackButton: TabsBackButton,\n};\n\nexport type {\n TabsActivePart,\n TabsRootProps,\n TabsTablistProps,\n TabsTabProps,\n TabsTabPrimitiveProps,\n TabsTabGroupHeadingProps,\n TabsViewportProps,\n TabsPanelProps,\n};\n"],
5
+ "mappings": "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",
6
+ "names": ["useArrowNavigationGroup", "useFocusFinders", "useFocusableGroup", "createContext", "Slot", "TabsPrimitive", "useControllableState", "React", "useCallback", "useLayoutEffect", "Button", "IconButton", "composableProps", "slottable", "useForwardedRef", "useAttention", "mx", "TABS_NAME", "TabsContextProvider", "useTabsContext", "orientation", "activePart", "setActivePart", "TabsRoot", "children", "propsActivePart", "onActivePartChange", "defaultActivePart", "value", "propsValue", "onValueChange", "defaultValue", "activationMode", "attendableId", "suppressRegionFocus", "asChild", "props", "forwardedRef", "tabsRoot", "prop", "onChange", "defaultProp", "setValue", "handleValueChange", "nextValue", "findFirstFocusable", "findNextFocusable", "root", "current", "tablist", "querySelector", "focus", "panel", "target", "container", "undefined", "Root", "data-active", "ref", "displayName", "TabsViewport", "Comp", "TabsTablist", "classNames", "List", "data-arrow-keys", "className", "TabsBackButton", "onClick", "handleClick", "event", "TabsTabGroupHeading", "h2", "TabsTab", "contextValue", "hasAttention", "Trigger", "variant", "TabsIconTab", "TabsPanel", "Content", "Tabs", "Tablist", "Tab", "IconTab", "TabPrimitive", "TabGroupHeading", "Viewport", "Panel", "BackButton"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"src/Tabs.tsx":{"bytes":26241,"imports":[{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-tabs","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":368,"imports":[{"path":"src/Tabs.tsx","kind":"import-statement","original":"./Tabs"}],"format":"esm"}},"outputs":{"dist/lib/node-esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":14205},"dist/lib/node-esm/index.mjs":{"imports":[{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-tabs","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"exports":["Tabs"],"entryPoint":"src/index.ts","inputs":{"src/Tabs.tsx":{"bytesInOutput":6267},"src/index.ts":{"bytesInOutput":0}},"bytes":6430}}}
1
+ {"inputs":{"src/Tabs.tsx":{"bytes":29707,"imports":[{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"@radix-ui/react-tabs","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"format":"esm"},"src/index.ts":{"bytes":368,"imports":[{"path":"src/Tabs.tsx","kind":"import-statement","original":"./Tabs"}],"format":"esm"}},"outputs":{"dist/lib/node-esm/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":16101},"dist/lib/node-esm/index.mjs":{"imports":[{"path":"@fluentui/react-tabster","kind":"import-statement","external":true},{"path":"@radix-ui/react-context","kind":"import-statement","external":true},{"path":"@radix-ui/react-slot","kind":"import-statement","external":true},{"path":"@radix-ui/react-tabs","kind":"import-statement","external":true},{"path":"@radix-ui/react-use-controllable-state","kind":"import-statement","external":true},{"path":"react","kind":"import-statement","external":true},{"path":"@dxos/react-ui","kind":"import-statement","external":true},{"path":"@dxos/react-ui-attention","kind":"import-statement","external":true},{"path":"@dxos/ui-theme","kind":"import-statement","external":true}],"exports":["Tabs"],"entryPoint":"src/index.ts","inputs":{"src/Tabs.tsx":{"bytesInOutput":6965},"src/index.ts":{"bytesInOutput":0}},"bytes":7128}}}
@@ -1,21 +1,20 @@
1
1
  import * as TabsPrimitive from '@radix-ui/react-tabs';
2
2
  import React, { type ComponentPropsWithoutRef } from 'react';
3
- import { type ButtonProps, type IconButtonProps, type ThemedClassName } from '@dxos/react-ui';
3
+ import { type ButtonProps, type IconButtonProps, type SlottableProps, type ThemedClassName } from '@dxos/react-ui';
4
4
  type TabsActivePart = 'list' | 'panel';
5
5
  type TabsContextValue = {
6
6
  activePart: TabsActivePart;
7
7
  setActivePart: (nextActivePart: TabsActivePart) => void;
8
8
  attendableId?: string;
9
9
  } & Pick<TabsPrimitive.TabsProps, 'orientation' | 'value'>;
10
- type TabsRootProps = ThemedClassName<TabsPrimitive.TabsProps> & Partial<Pick<TabsContextValue, 'activePart' | 'attendableId'> & {
10
+ type TabsRootCustomProps = TabsPrimitive.TabsProps & Partial<Pick<TabsContextValue, 'activePart' | 'attendableId'> & {
11
11
  onActivePartChange: (nextActivePart: TabsActivePart) => void;
12
12
  defaultActivePart: TabsActivePart;
13
+ /** Skip master-detail focus moves (e.g. when a child form owns initial focus). */
14
+ suppressRegionFocus?: boolean;
13
15
  }>;
14
- type TabsViewportProps = ThemedClassName<ComponentPropsWithoutRef<'div'>>;
15
- declare function TabsViewport({ classNames, children, ...props }: TabsViewportProps): React.JSX.Element;
16
- declare namespace TabsViewport {
17
- var displayName: string;
18
- }
16
+ type TabsRootProps = SlottableProps<TabsRootCustomProps>;
17
+ type TabsViewportProps = SlottableProps<Omit<ComponentPropsWithoutRef<'div'>, 'className' | 'style' | 'children' | 'role'>>;
19
18
  type TabsTablistProps = ThemedClassName<TabsPrimitive.TabsListProps>;
20
19
  declare function TabsTablist({ children, classNames, ...props }: TabsTablistProps): React.JSX.Element;
21
20
  declare namespace TabsTablist {
@@ -47,12 +46,16 @@ declare namespace TabsPanel {
47
46
  }
48
47
  type TabsTabPrimitiveProps = TabsPrimitive.TabsTriggerProps;
49
48
  export declare const Tabs: {
50
- Root: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsProps, "className"> & {
51
- classNames?: import("@dxos/ui-types").ClassNameValue;
52
- } & Partial<Pick<TabsContextValue, "activePart" | "attendableId"> & {
49
+ Root: React.ForwardRefExoticComponent<Omit<TabsPrimitive.TabsProps & Partial<Pick<TabsContextValue, "activePart" | "attendableId"> & {
53
50
  onActivePartChange: (nextActivePart: TabsActivePart) => void;
54
51
  defaultActivePart: TabsActivePart;
55
- }> & React.RefAttributes<HTMLDivElement>>;
52
+ /** Skip master-detail focus moves (e.g. when a child form owns initial focus). */
53
+ suppressRegionFocus?: boolean;
54
+ }> & {
55
+ asChild?: boolean;
56
+ }, "className"> & {
57
+ classNames?: import("@dxos/ui-types").ClassNameValue;
58
+ } & Pick<React.HTMLAttributes<Element>, "children" | "className" | "role" | "style"> & React.RefAttributes<HTMLDivElement>>;
56
59
  Tablist: {
57
60
  ({ children, classNames, ...props }: TabsTablistProps): React.JSX.Element;
58
61
  displayName: string;
@@ -70,10 +73,11 @@ export declare const Tabs: {
70
73
  ({ children, classNames, ...props }: TabsTabGroupHeadingProps): React.JSX.Element;
71
74
  displayName: string;
72
75
  };
73
- Viewport: {
74
- ({ classNames, children, ...props }: TabsViewportProps): React.JSX.Element;
75
- displayName: string;
76
- };
76
+ Viewport: React.ForwardRefExoticComponent<Omit<Omit<Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "children" | "className" | "role" | "style"> & {
77
+ asChild?: boolean;
78
+ }, "className"> & {
79
+ classNames?: import("@dxos/ui-types").ClassNameValue;
80
+ } & Pick<React.HTMLAttributes<Element>, "children" | "className" | "role" | "style"> & React.RefAttributes<HTMLDivElement>>;
77
81
  Panel: {
78
82
  ({ classNames, children, ...props }: TabsPanelProps): React.JSX.Element;
79
83
  displayName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/Tabs.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,aAAa,MAAM,sBAAsB,CAAC;AAEtD,OAAO,KAAK,EAAE,EAAE,KAAK,wBAAwB,EAA6D,MAAM,OAAO,CAAC;AAExH,OAAO,EAEL,KAAK,WAAW,EAEhB,KAAK,eAAe,EACpB,KAAK,eAAe,EAErB,MAAM,gBAAgB,CAAC;AAMxB,KAAK,cAAc,GAAG,MAAM,GAAG,OAAO,CAAC;AAQvC,KAAK,gBAAgB,GAAG;IACtB,UAAU,EAAE,cAAc,CAAC;IAC3B,aAAa,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,IAAI,CAAC;IACxD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,GAAG,IAAI,CAAC,aAAa,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC;AAY3D,KAAK,aAAa,GAAG,eAAe,CAAC,aAAa,CAAC,SAAS,CAAC,GAC3D,OAAO,CACL,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,cAAc,CAAC,GAAG;IACtD,kBAAkB,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,IAAI,CAAC;IAC7D,iBAAiB,EAAE,cAAc,CAAC;CACnC,CACF,CAAC;AAoFJ,KAAK,iBAAiB,GAAG,eAAe,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,CAAC;8BAEpD,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,iBAAiB;;;;AAe3E,KAAK,gBAAgB,GAAG,eAAe,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;6BAEhD,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB;;;;gCAwBjD,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE,WAAW;;;;AAmBtE,KAAK,wBAAwB,GAAG,eAAe,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC,CAAC;qCAEnD,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,KAAK,EAAE,EAAE,wBAAwB;;;;AAYzF,KAAK,YAAY,GAAG,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;yBAE/D,EAAE,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,YAAY;;;;AAuCjF,KAAK,gBAAgB,GAAG,eAAe,GAAG,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;6BAEnE,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,gBAAgB;;;;AA2C/E,KAAK,cAAc,GAAG,eAAe,CAAC,aAAa,CAAC,gBAAgB,CAAC,CAAC;2BAEnD,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc;;;;AAQrE,KAAK,qBAAqB,GAAG,aAAa,CAAC,gBAAgB,CAAC;AAM5D,eAAO,MAAM,IAAI;IACf,IAAI;;;4BA1QoB,CAAC,cAAc,EAAE,cAAc,KAAK,IAAI;2BACzC,cAAc;;IA0QrC,OAAO;6CAjKgD,gBAAgB;;;IAkKvE,GAAG;6DAvGgE,YAAY;;;IAwG/E,OAAO;mDA/DsD,gBAAgB;;;IAgE7E,YAAY;IACZ,eAAe;6CAxHgD,wBAAwB;;;IAyHvF,QAAQ;6CAvLgD,iBAAiB;;;IAwLzE,KAAK;6CAtBgD,cAAc;;;IAuBnE,UAAU;4CAhJ+C,WAAW;;;CAiJrE,CAAC;AAEF,YAAY,EACV,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,cAAc,GACf,CAAC"}
1
+ {"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/Tabs.tsx"],"names":[],"mappings":"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"}
@@ -3,16 +3,19 @@ import React from 'react';
3
3
  import { TabsRootProps } from './Tabs';
4
4
  declare const meta: {
5
5
  title: string;
6
- component: React.ForwardRefExoticComponent<Omit<import("@radix-ui/react-tabs").TabsProps, "className"> & {
7
- classNames?: import("@dxos/ui-types").ClassNameValue;
8
- } & Partial<Pick<{
6
+ component: React.ForwardRefExoticComponent<Omit<import("@radix-ui/react-tabs").TabsProps & Partial<Pick<{
9
7
  activePart: import("./Tabs").TabsActivePart;
10
8
  setActivePart: (nextActivePart: import("./Tabs").TabsActivePart) => void;
11
9
  attendableId?: string;
12
10
  } & Pick<import("@radix-ui/react-tabs").TabsProps, "orientation" | "value">, "activePart" | "attendableId"> & {
13
11
  onActivePartChange: (nextActivePart: import("./Tabs").TabsActivePart) => void;
14
12
  defaultActivePart: import("./Tabs").TabsActivePart;
15
- }> & React.RefAttributes<HTMLDivElement>>;
13
+ suppressRegionFocus?: boolean;
14
+ }> & {
15
+ asChild?: boolean;
16
+ }, "className"> & {
17
+ classNames?: import("@dxos/ui-types").ClassNameValue;
18
+ } & Pick<React.HTMLAttributes<Element>, "children" | "className" | "role" | "style"> & React.RefAttributes<HTMLDivElement>>;
16
19
  render: ({ orientation }: TabsRootProps) => React.JSX.Element;
17
20
  decorators: import("@storybook/react").Decorator[];
18
21
  parameters: {
@@ -1 +1 @@
1
- {"version":3,"file":"Tabs.stories.d.ts","sourceRoot":"","sources":["../../../src/Tabs.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,OAAO,EAAQ,aAAa,EAAE,MAAM,QAAQ,CAAC;AAwC7C,QAAA,MAAM,IAAI;;;;;;;;;;;;8BApC6B,aAAa;;;QA0ChD,MAAM;;CAE2B,CAAC;eAEvB,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAGnC,eAAO,MAAM,UAAU,EAAE,KAIxB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAItB,CAAC"}
1
+ {"version":3,"file":"Tabs.stories.d.ts","sourceRoot":"","sources":["../../../src/Tabs.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAa,KAAK,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,OAAO,EAAQ,aAAa,EAAE,MAAM,QAAQ,CAAC;AAwC7C,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;8BApC6B,aAAa;;;QA0ChD,MAAM;;CAE2B,CAAC;eAEvB,IAAI;AAEnB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAGnC,eAAO,MAAM,UAAU,EAAE,KAIxB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAItB,CAAC"}