@bitrise/bitkit-v2 0.3.443 → 0.3.444
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.
|
@@ -8,7 +8,7 @@ import { chakra, useRecipe } from "@chakra-ui/react/styled-system";
|
|
|
8
8
|
import { cloneElement, forwardRef, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
9
9
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
import { Portal } from "@chakra-ui/react/portal";
|
|
11
|
-
import { Menu } from "@chakra-ui/react/menu";
|
|
11
|
+
import { Menu, useMenuStyles } from "@chakra-ui/react/menu";
|
|
12
12
|
import { Text } from "@chakra-ui/react/text";
|
|
13
13
|
import { createContext as createContext$1, mergeRefs, useSafeLayoutEffect } from "@chakra-ui/react";
|
|
14
14
|
import { Tabs, useTabsContext, useTabsStyles } from "@chakra-ui/react/tabs";
|
|
@@ -156,6 +156,47 @@ var getVisibleIndices = (total, count, selectedIndex) => {
|
|
|
156
156
|
}
|
|
157
157
|
return visible;
|
|
158
158
|
};
|
|
159
|
+
var MoreMenuItem = ({ isCompact, item, onSelect, variant }) => {
|
|
160
|
+
const menuStyles = useMenuStyles();
|
|
161
|
+
const { badge, children, disabled, icon: Icon, iconColor, secondaryText, statusColor, value } = item.props;
|
|
162
|
+
const isCanvas = variant === "canvas";
|
|
163
|
+
const isContained = variant === "contained";
|
|
164
|
+
const helperText = isContained ? secondaryText : void 0;
|
|
165
|
+
const ownIconColor = isContained ? iconColor : void 0;
|
|
166
|
+
const helperStyles = disabled ? {
|
|
167
|
+
...menuStyles.itemHelper,
|
|
168
|
+
color: "text/on-disabled"
|
|
169
|
+
} : menuStyles.itemHelper;
|
|
170
|
+
return /* @__PURE__ */ jsxs(Menu.Item, {
|
|
171
|
+
"data-helper": helperText ? "" : void 0,
|
|
172
|
+
disabled,
|
|
173
|
+
onSelect,
|
|
174
|
+
value,
|
|
175
|
+
children: [
|
|
176
|
+
Icon && /* @__PURE__ */ jsx(Icon, {
|
|
177
|
+
color: disabled ? "icon/on-disabled" : ownIconColor,
|
|
178
|
+
size: isCompact ? "16" : "24"
|
|
179
|
+
}),
|
|
180
|
+
/* @__PURE__ */ jsxs(Box, {
|
|
181
|
+
flex: "1",
|
|
182
|
+
children: [/* @__PURE__ */ jsx(Text, {
|
|
183
|
+
color: disabled ? "text/on-disabled" : void 0,
|
|
184
|
+
children
|
|
185
|
+
}), !!helperText && /* @__PURE__ */ jsx(Text, {
|
|
186
|
+
css: helperStyles,
|
|
187
|
+
children: helperText
|
|
188
|
+
})]
|
|
189
|
+
}),
|
|
190
|
+
!isCanvas && badge,
|
|
191
|
+
isCanvas && statusColor && /* @__PURE__ */ jsx(chakra.span, {
|
|
192
|
+
boxSize: "8",
|
|
193
|
+
borderRadius: "full",
|
|
194
|
+
flexShrink: 0,
|
|
195
|
+
backgroundColor: STATUS_COLOR_TOKEN[statusColor]
|
|
196
|
+
})
|
|
197
|
+
]
|
|
198
|
+
});
|
|
199
|
+
};
|
|
159
200
|
var AddButton = forwardRef((props, ref) => {
|
|
160
201
|
const { label = "Add tab", ...rest } = props;
|
|
161
202
|
return /* @__PURE__ */ jsx(BitkitControlButton, {
|
|
@@ -300,21 +341,11 @@ var List = forwardRef((props, ref) => {
|
|
|
300
341
|
css: styles.moreTrigger,
|
|
301
342
|
children: [hiddenItems.length, " more…"]
|
|
302
343
|
})
|
|
303
|
-
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, { children: /* @__PURE__ */ jsx(Menu.Content, { children: hiddenItems.map((item) => /* @__PURE__ */
|
|
304
|
-
|
|
305
|
-
|
|
344
|
+
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Menu.Positioner, { children: /* @__PURE__ */ jsx(Menu.Content, { children: hiddenItems.map((item) => /* @__PURE__ */ jsx(MoreMenuItem, {
|
|
345
|
+
isCompact,
|
|
346
|
+
item,
|
|
306
347
|
onSelect: () => api.setValue(item.props.value),
|
|
307
|
-
|
|
308
|
-
children: [/* @__PURE__ */ jsx(Text, {
|
|
309
|
-
flex: "1",
|
|
310
|
-
color: item.props.disabled ? "text/on-disabled" : "inherit",
|
|
311
|
-
children: item.props.children
|
|
312
|
-
}), variant === "canvas" && item.props.statusColor && /* @__PURE__ */ jsx(chakra.span, {
|
|
313
|
-
boxSize: "8",
|
|
314
|
-
borderRadius: "full",
|
|
315
|
-
flexShrink: 0,
|
|
316
|
-
backgroundColor: STATUS_COLOR_TOKEN[item.props.statusColor]
|
|
317
|
-
})]
|
|
348
|
+
variant
|
|
318
349
|
}, item.props.value)) }) }) })]
|
|
319
350
|
}),
|
|
320
351
|
addButton && /* @__PURE__ */ jsx(Box, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitTabs.js","names":[],"sources":["../../../lib/components/BitkitTabs/BitkitTabs.tsx"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport { createContext, mergeRefs, useSafeLayoutEffect } from '@chakra-ui/react';\nimport { Box } from '@chakra-ui/react/box';\nimport { Menu } from '@chakra-ui/react/menu';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { chakra, type Tokens, useRecipe } from '@chakra-ui/react/styled-system';\nimport { Tabs, useTabsContext, useTabsStyles } from '@chakra-ui/react/tabs';\nimport { Text } from '@chakra-ui/react/text';\nimport {\n cloneElement,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { type BitkitIconComponent, IconCross, IconPlus } from '../../icons';\nimport { flattenChildren } from '../../utilities/flattenChildren';\nimport { getTextContent } from '../../utilities/getTextContent';\nimport BitkitControlButton, { type BitkitControlButtonProps } from '../BitkitControlButton/BitkitControlButton';\n\n/**\n * Root props. `onValueChange` is re-declared with a concrete `{ value }` arg so the callback\n * parameter is inferred at the call site: the base `Tabs.RootProps` intersection breaks\n * contextual typing, which otherwise leaves consumers' `({ value }) => …` flagged as an\n * implicit `any` under `noImplicitAny`.\n */\nexport type BitkitTabsRootProps = Omit<Tabs.RootProps, 'onValueChange'> & {\n onValueChange?: (details: { value: string }) => void;\n};\n\nexport const [RootPropsProvider, useRootPropsContext] = createContext<BitkitTabsRootProps>({\n name: 'RootPropsContext',\n hookName: 'useRootPropsContext',\n providerName: '<RootProps />',\n});\n\nconst Root = forwardRef<HTMLDivElement, BitkitTabsRootProps>((props, ref) => {\n return (\n <RootPropsProvider value={props}>\n <Tabs.Root ref={ref} {...props} />\n </RootPropsProvider>\n );\n});\n\n/** Status-dot colors for the `canvas` variant. */\nexport type BitkitTabsStatusColor = 'neutral' | 'purple' | 'red' | 'yellow';\n\nconst STATUS_COLOR_TOKEN: Record<BitkitTabsStatusColor, string> = {\n neutral: 'color/neutral/muted',\n purple: 'interactive/bold',\n red: 'color/red/base',\n yellow: 'color/yellow/bold',\n};\n\n// Falls back to `string` where the consumer's `chakra typegen` did not run, for the reason given on\n// `BitkitStatusColorToken` in BitkitPageSidebar.\ntype BitkitTabsIconColor = [Extract<Tokens['colors'], `icon/${string}`>] extends [never]\n ? string\n : Extract<Tokens['colors'], `icon/${string}`>;\n\nexport type BitkitTabsTriggerProps = Tabs.TriggerProps & {\n badge?: ReactNode;\n children?: string;\n icon?: BitkitIconComponent;\n /**\n * `contained` variant only: an `icon/*` token for the icon when it carries meaning of its own,\n * such as a trend arrow. It wins over the hover and selected colours; a disabled tab keeps its own.\n */\n iconColor?: BitkitTabsIconColor;\n /** `canvas` variant only — when provided, a close button reveals on hover and calls this handler when clicked. */\n onClose?: () => void;\n secondaryText?: ReactNode;\n /** `canvas` variant only — shows a status indicator dot. When hovered (and `onClose` is set), the close button replaces it. */\n statusColor?: BitkitTabsStatusColor;\n};\n\nRoot.displayName = 'BitkitTabs.Root';\n\n// Canvas and line md tabs are the small ones: 16px icons, and an md overflow menu to match.\nconst isCompactTabs = (variant: BitkitTabsRootProps['variant'], size: BitkitTabsRootProps['size']) =>\n variant === 'canvas' || (variant === 'line' && size === 'md');\n\nconst Trigger = forwardRef<HTMLButtonElement, BitkitTabsTriggerProps>((props, ref) => {\n const {\n badge,\n children,\n className,\n icon: Icon,\n iconColor,\n onClose,\n onKeyDown,\n secondaryText,\n statusColor,\n ...rest\n } = props;\n // Mirror the recipe's defaultVariants: an unset `variant` must take the line branch below, not\n // fall through to the contained one, and an unset `size` the lg icon size.\n const { size = 'lg', variant = 'line' } = useRootPropsContext();\n const closeButtonRecipe = useRecipe({ key: 'closeButton' });\n\n // Close button and status dot are exclusive to the canvas variant.\n const isCanvas = variant === 'canvas';\n const closable = isCanvas && !!onClose && !rest.disabled;\n const hasStatus = isCanvas && !!statusColor && !rest.disabled;\n const showTrailing = closable || hasStatus;\n const mergedClassName = showTrailing ? (className ? `group ${className}` : 'group') : className;\n // The close button is always visible when there is no status dot; when the dot is shown it is\n // revealed on hover/focus instead (replacing the dot).\n const revealCloseOnInteraction = closable && hasStatus;\n const revealOnInteraction = { opacity: 1, pointerEvents: 'auto' } as const;\n\n const handleCloseClick = (event: MouseEvent<HTMLSpanElement>) => {\n event.stopPropagation();\n event.preventDefault();\n onClose?.();\n };\n\n // The close control is not in the tab order; keyboard users close the focused tab with Delete/Backspace.\n const handleTriggerKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (closable && (event.key === 'Delete' || event.key === 'Backspace')) {\n event.preventDefault();\n // Move focus to a sibling tab before removal so keyboard navigation can continue.\n const trigger = event.currentTarget;\n // Skip overflowed (`hidden`) tabs — they aren't focusable.\n const triggers = [\n ...(trigger.closest('[role=\"tablist\"]')?.querySelectorAll<HTMLElement>('[role=\"tab\"]:not([hidden])') ?? []),\n ];\n const index = triggers.indexOf(trigger);\n (triggers[index + 1] ?? triggers[index - 1])?.focus();\n onClose?.();\n }\n onKeyDown?.(event);\n };\n\n const trailing = showTrailing ? (\n <chakra.span\n position=\"relative\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n boxSize=\"24\"\n flexShrink={0}\n >\n {hasStatus && statusColor && (\n <chakra.span\n position=\"absolute\"\n inset={0}\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n pointerEvents=\"none\"\n transition=\"opacity 0.1s\"\n _groupHover={closable ? { opacity: 0 } : undefined}\n _groupFocusWithin={closable ? { opacity: 0 } : undefined}\n >\n <chakra.span boxSize=\"8\" borderRadius=\"full\" backgroundColor={STATUS_COLOR_TOKEN[statusColor]} />\n </chakra.span>\n )}\n {closable && (\n <chakra.span\n aria-hidden\n tabIndex={-1}\n onClick={handleCloseClick}\n css={closeButtonRecipe({ size: 'xs' })}\n position=\"absolute\"\n inset={0}\n color=\"icon/primary\"\n opacity={revealCloseOnInteraction ? 0 : 1}\n pointerEvents={revealCloseOnInteraction ? 'none' : 'auto'}\n transition=\"opacity 0.1s\"\n _groupHover={revealCloseOnInteraction ? revealOnInteraction : undefined}\n _groupFocusWithin={revealCloseOnInteraction ? revealOnInteraction : undefined}\n >\n <IconCross size=\"16\" />\n </chakra.span>\n )}\n </chakra.span>\n ) : null;\n\n const isCompact = isCompactTabs(variant, size);\n const hasOwnIconColor = variant === 'contained' && !!iconColor && !rest.disabled;\n const icon = Icon && (\n <Icon color={hasOwnIconColor ? iconColor : 'var(--tabs-icon-color)'} size={isCompact ? '16' : '24'} />\n );\n const canvasPadding = isCanvas\n ? { paddingInlineEnd: showTrailing ? '8' : Icon ? '16' : undefined, paddingInlineStart: Icon ? '8' : undefined }\n : undefined;\n\n return (\n <Tabs.Trigger ref={ref} {...rest} {...canvasPadding} className={mergedClassName} onKeyDown={handleTriggerKeyDown}>\n {isCanvas ? (\n <>\n <Box display=\"flex\" alignItems=\"center\" gap=\"8\">\n {icon}\n {children}\n </Box>\n {trailing}\n </>\n ) : variant === 'line' ? (\n <>\n <Box display=\"flex\" alignItems=\"center\" gap=\"8\">\n {icon}\n {children}\n </Box>\n {badge}\n </>\n ) : (\n <>\n <Box display=\"flex\" flexDirection=\"column\">\n <Box display=\"flex\" alignItems=\"flex-start\" gap=\"16\">\n {children}\n {badge}\n </Box>\n {!!secondaryText && (\n <Text as=\"span\" textStyle=\"body/md/regular\" color={rest.disabled ? 'text/on-disabled' : 'text/secondary'}>\n {secondaryText}\n </Text>\n )}\n </Box>\n {icon}\n </>\n )}\n </Tabs.Trigger>\n );\n});\n\nTrigger.displayName = 'BitkitTabs.Trigger';\n\ntype TabItem = ReactElement<BitkitTabsTriggerProps>;\n\n// Returns the set of visible tab indices for the overflow, always keeping the selected tab\n// visible: if it would overflow, it takes the last visible slot.\nconst getVisibleIndices = (total: number, count: number, selectedIndex: number) => {\n const visible = new Set<number>();\n for (let i = 0; i < count; i += 1) visible.add(i);\n if (selectedIndex >= 0 && selectedIndex < total && !visible.has(selectedIndex)) {\n visible.delete(count - 1);\n visible.add(selectedIndex);\n }\n return visible;\n};\n\nexport type BitkitTabsAddButtonProps = Omit<\n Extract<BitkitControlButtonProps, { href?: undefined }>,\n 'icon' | 'label' | 'size'\n> & {\n /** Accessible label / tooltip for the add button. */\n label?: string;\n};\n\n// \"+\" button to add a tab. Place it as a child of `List`; it always renders at the end of the row\n// (after the overflow menu). A compact `xxs` control button (16px icon, 4px padding) per the design.\nconst AddButton = forwardRef<HTMLButtonElement, BitkitTabsAddButtonProps>((props, ref) => {\n const { label = 'Add tab', ...rest } = props;\n return <BitkitControlButton ref={ref} icon={IconPlus} label={label} size=\"xxs\" {...rest} />;\n});\n\nAddButton.displayName = 'BitkitTabs.AddButton';\n\n// A stretched trigger (line tabs on mobile, or a consumer's own `flex`/`width`) is as wide as\n// its share of the list, not its content, so its laid-out width would count the free space as\n// needed space. Measure it unstretched, and unrounded: two 163.5px tabs read as 164 + 164 through\n// `offsetWidth` and overflow a 327px row.\n// The whole inline style is restored, because resetting the `flex` shorthand would also wipe any\n// inline flex longhands the consumer set.\nconst measureContentWidth = (node: HTMLElement) => {\n const { cssText } = node.style;\n node.style.flex = '0 0 auto';\n node.style.width = 'max-content';\n const contentWidth = node.getBoundingClientRect().width;\n node.style.cssText = cssText;\n return contentWidth;\n};\n\n// Overflow-aware List (all variants): measures the tabs and collapses the overflowing ones into a\n// \"N more…\" menu. The more-button look comes from the variant's `moreTrigger` recipe slot.\nconst List = forwardRef<HTMLDivElement, Tabs.ListProps>((props, ref) => {\n // Semantic/labelling attributes belong on the actual tablist, not the visual wrapper.\n const { children, css, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, ...rest } = props;\n const { size = 'lg', variant = 'line' } = useRootPropsContext();\n const api = useTabsContext();\n const styles = useTabsStyles();\n const isCompact = isCompactTabs(variant, size);\n\n // Split children: tab triggers participate in overflow; the optional add button always renders last.\n const allChildren = flattenChildren(children);\n const addButton = allChildren.find((child) => child.type === AddButton) ?? null;\n // Only Trigger elements are measured/overflowed; anything else (fragments, stray nodes) is ignored.\n const items = allChildren.filter((child) => child.type === Trigger) as TabItem[];\n // Re-measure whenever the tab set OR any width-affecting input changes: the variant and size, each\n // tab's value/label, icon/status/close/disabled state, and the text of its badge and secondaryText,\n // so a count going from 3 to 12 invalidates the cache.\n const measureKey = [\n variant,\n size,\n ...items.map((item) => {\n const p = item.props;\n return [\n p.value,\n String(p.children),\n p.icon ? 'i' : '',\n getTextContent(p.badge),\n getTextContent(p.secondaryText),\n p.statusColor ?? '',\n p.onClose ? 'c' : '',\n p.disabled ? 'd' : '',\n ].join(':');\n }),\n ].join('|');\n const selectedIndex = items.findIndex((item) => item.props.value === api.value);\n // Width reservations for the more button, sized for a two-digit count (\"10 more…\"), and for the\n // always-visible add button. Any slack here hides a tab that would have fitted.\n const moreReserve = isCompact ? 88 : 104;\n const addReserve = addButton ? 48 : 0;\n\n const listRef = useRef<HTMLDivElement | null>(null);\n const widthsRef = useRef<number[]>([]);\n // Horizontal padding of the list, cached during the measure pass so the resize hot path doesn't\n // call getComputedStyle on every tick.\n const paddingRef = useRef(0);\n // `measuredKey` is state (not a ref) so finishing the measure pass always re-renders and flips\n // `measuring` off — even when recompute keeps the same visibleCount (which would skip a re-render).\n const [measuredKey, setMeasuredKey] = useState<string | null>(null);\n const [visibleCount, setVisibleCount] = useState(items.length);\n\n const setListRef = useMemo(() => mergeRefs(listRef, ref), [ref]);\n\n const recompute = useCallback(() => {\n const el = listRef.current;\n const widths = widthsRef.current;\n if (!el || !widths.length) return;\n const available = el.clientWidth - paddingRef.current - addReserve;\n const totalWidth = widths.reduce((sum, w) => sum + w, 0);\n if (totalWidth <= available) {\n setVisibleCount(widths.length);\n return;\n }\n let used = moreReserve;\n let count = 0;\n for (let i = 0; i < widths.length; i += 1) {\n if (used + widths[i] > available) break;\n used += widths[i];\n count += 1;\n }\n setVisibleCount(Math.max(count, 1));\n }, [addReserve, moreReserve]);\n\n // Measure once per width-affecting change (all tabs are rendered visible during this pass).\n // Isomorphic layout effect: avoids the SSR \"useLayoutEffect does nothing on the server\" warning.\n const measuring = measuredKey !== measureKey;\n useSafeLayoutEffect(() => {\n const el = listRef.current;\n if (!el) return;\n if (measuredKey !== measureKey) {\n const tabEls = el.querySelectorAll<HTMLElement>('[data-tab-trigger]');\n widthsRef.current = Array.from(tabEls, measureContentWidth);\n const cs = getComputedStyle(el);\n paddingRef.current = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);\n setMeasuredKey(measureKey);\n }\n recompute();\n }, [measureKey, measuredKey, recompute]);\n\n // Swapping the fallback font for the webfont changes the tabs' widths without resizing the list,\n // so no ResizeObserver fires for it: measure again once the fonts are in.\n useEffect(() => {\n let cancelled = false;\n void document.fonts?.ready.then(() => {\n if (!cancelled) setMeasuredKey(null);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n const el = listRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n // Coalesce resize bursts into one recompute per frame to avoid a read/write layout storm.\n let raf = 0;\n const observer = new ResizeObserver(() => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(recompute);\n });\n observer.observe(el);\n return () => {\n cancelAnimationFrame(raf);\n observer.disconnect();\n };\n }, [recompute]);\n\n const showAll = measuring || visibleCount >= items.length;\n const visible = showAll ? null : getVisibleIndices(items.length, visibleCount, selectedIndex);\n const hiddenItems = visible ? items.filter((_, i) => !visible.has(i)) : [];\n\n return (\n // The visual row carries the list styling (background, baseline border, leading padding) and is\n // measured for overflow. The tablist itself only wraps the tabs (`display: contents` keeps the\n // flex layout intact), so the more/add controls stay outside `role=\"tablist\"` per the ARIA spec.\n <Box ref={setListRef} css={[styles.list, css]} data-overflowing={hiddenItems.length > 0 ? '' : undefined} {...rest}>\n <Tabs.List display=\"contents\" id={id} aria-label={ariaLabel} aria-labelledby={ariaLabelledby}>\n {items.map((item, i) =>\n cloneElement(item, {\n key: item.props.value,\n 'data-tab-trigger': '',\n hidden: visible ? !visible.has(i) : undefined,\n } as Partial<BitkitTabsTriggerProps>),\n )}\n </Tabs.List>\n {hiddenItems.length > 0 && (\n <Menu.Root size={isCompact ? 'md' : 'lg'} positioning={{ gutter: 0, shift: -4 }}>\n <Menu.Trigger asChild>\n <chakra.button type=\"button\" css={styles.moreTrigger}>\n {hiddenItems.length} more…\n </chakra.button>\n </Menu.Trigger>\n <Portal>\n <Menu.Positioner>\n <Menu.Content>\n {hiddenItems.map((item) => (\n <Menu.Item\n key={item.props.value}\n value={item.props.value}\n disabled={item.props.disabled}\n onSelect={() => api.setValue(item.props.value)}\n alignItems=\"center\"\n >\n <Text flex=\"1\" color={item.props.disabled ? 'text/on-disabled' : 'inherit'}>\n {item.props.children}\n </Text>\n {variant === 'canvas' && item.props.statusColor && (\n <chakra.span\n boxSize=\"8\"\n borderRadius=\"full\"\n flexShrink={0}\n backgroundColor={STATUS_COLOR_TOKEN[item.props.statusColor]}\n />\n )}\n </Menu.Item>\n ))}\n </Menu.Content>\n </Menu.Positioner>\n </Portal>\n </Menu.Root>\n )}\n {addButton && (\n <Box display=\"flex\" alignItems=\"center\" flexShrink={0} paddingInline=\"8\">\n {addButton}\n </Box>\n )}\n </Box>\n );\n});\n\nList.displayName = 'BitkitTabs.List';\n\nconst BitkitTabs: Omit<typeof Tabs, 'Root' | 'Trigger' | 'List'> & {\n AddButton: typeof AddButton;\n List: typeof List;\n Root: typeof Root;\n Trigger: typeof Trigger;\n} = {\n ...Tabs,\n AddButton,\n List,\n Root,\n Trigger,\n};\n\nBitkitTabs.Content.displayName = 'BitkitTabs.Content';\nBitkitTabs.ContentGroup.displayName = 'BitkitTabs.ContentGroup';\nBitkitTabs.Root.displayName = 'BitkitTabs.Root';\n\nexport default BitkitTabs;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BitkitTabs.js","names":[],"sources":["../../../lib/components/BitkitTabs/BitkitTabs.tsx"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport { createContext, mergeRefs, useSafeLayoutEffect } from '@chakra-ui/react';\nimport { Box } from '@chakra-ui/react/box';\nimport { Menu, useMenuStyles } from '@chakra-ui/react/menu';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { chakra, type Tokens, useRecipe } from '@chakra-ui/react/styled-system';\nimport { Tabs, useTabsContext, useTabsStyles } from '@chakra-ui/react/tabs';\nimport { Text } from '@chakra-ui/react/text';\nimport {\n cloneElement,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\n\nimport { type BitkitIconComponent, IconCross, IconPlus } from '../../icons';\nimport { flattenChildren } from '../../utilities/flattenChildren';\nimport { getTextContent } from '../../utilities/getTextContent';\nimport BitkitControlButton, { type BitkitControlButtonProps } from '../BitkitControlButton/BitkitControlButton';\n\n/**\n * Root props. `onValueChange` is re-declared with a concrete `{ value }` arg so the callback\n * parameter is inferred at the call site: the base `Tabs.RootProps` intersection breaks\n * contextual typing, which otherwise leaves consumers' `({ value }) => …` flagged as an\n * implicit `any` under `noImplicitAny`.\n */\nexport type BitkitTabsRootProps = Omit<Tabs.RootProps, 'onValueChange'> & {\n onValueChange?: (details: { value: string }) => void;\n};\n\nexport const [RootPropsProvider, useRootPropsContext] = createContext<BitkitTabsRootProps>({\n name: 'RootPropsContext',\n hookName: 'useRootPropsContext',\n providerName: '<RootProps />',\n});\n\nconst Root = forwardRef<HTMLDivElement, BitkitTabsRootProps>((props, ref) => {\n return (\n <RootPropsProvider value={props}>\n <Tabs.Root ref={ref} {...props} />\n </RootPropsProvider>\n );\n});\n\n/** Status-dot colors for the `canvas` variant. */\nexport type BitkitTabsStatusColor = 'neutral' | 'purple' | 'red' | 'yellow';\n\nconst STATUS_COLOR_TOKEN: Record<BitkitTabsStatusColor, string> = {\n neutral: 'color/neutral/muted',\n purple: 'interactive/bold',\n red: 'color/red/base',\n yellow: 'color/yellow/bold',\n};\n\n// Falls back to `string` where the consumer's `chakra typegen` did not run, for the reason given on\n// `BitkitStatusColorToken` in BitkitPageSidebar.\ntype BitkitTabsIconColor = [Extract<Tokens['colors'], `icon/${string}`>] extends [never]\n ? string\n : Extract<Tokens['colors'], `icon/${string}`>;\n\nexport type BitkitTabsTriggerProps = Tabs.TriggerProps & {\n badge?: ReactNode;\n children?: string;\n icon?: BitkitIconComponent;\n /**\n * `contained` variant only: an `icon/*` token for the icon when it carries meaning of its own,\n * such as a trend arrow. It wins over the hover and selected colours; a disabled tab keeps its own.\n */\n iconColor?: BitkitTabsIconColor;\n /** `canvas` variant only — when provided, a close button reveals on hover and calls this handler when clicked. */\n onClose?: () => void;\n secondaryText?: ReactNode;\n /** `canvas` variant only — shows a status indicator dot. When hovered (and `onClose` is set), the close button replaces it. */\n statusColor?: BitkitTabsStatusColor;\n};\n\nRoot.displayName = 'BitkitTabs.Root';\n\n// Canvas and line md tabs are the small ones: 16px icons, and an md overflow menu to match.\nconst isCompactTabs = (variant: BitkitTabsRootProps['variant'], size: BitkitTabsRootProps['size']) =>\n variant === 'canvas' || (variant === 'line' && size === 'md');\n\nconst Trigger = forwardRef<HTMLButtonElement, BitkitTabsTriggerProps>((props, ref) => {\n const {\n badge,\n children,\n className,\n icon: Icon,\n iconColor,\n onClose,\n onKeyDown,\n secondaryText,\n statusColor,\n ...rest\n } = props;\n // Mirror the recipe's defaultVariants: an unset `variant` must take the line branch below, not\n // fall through to the contained one, and an unset `size` the lg icon size.\n const { size = 'lg', variant = 'line' } = useRootPropsContext();\n const closeButtonRecipe = useRecipe({ key: 'closeButton' });\n\n // Close button and status dot are exclusive to the canvas variant.\n const isCanvas = variant === 'canvas';\n const closable = isCanvas && !!onClose && !rest.disabled;\n const hasStatus = isCanvas && !!statusColor && !rest.disabled;\n const showTrailing = closable || hasStatus;\n const mergedClassName = showTrailing ? (className ? `group ${className}` : 'group') : className;\n // The close button is always visible when there is no status dot; when the dot is shown it is\n // revealed on hover/focus instead (replacing the dot).\n const revealCloseOnInteraction = closable && hasStatus;\n const revealOnInteraction = { opacity: 1, pointerEvents: 'auto' } as const;\n\n const handleCloseClick = (event: MouseEvent<HTMLSpanElement>) => {\n event.stopPropagation();\n event.preventDefault();\n onClose?.();\n };\n\n // The close control is not in the tab order; keyboard users close the focused tab with Delete/Backspace.\n const handleTriggerKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n if (closable && (event.key === 'Delete' || event.key === 'Backspace')) {\n event.preventDefault();\n // Move focus to a sibling tab before removal so keyboard navigation can continue.\n const trigger = event.currentTarget;\n // Skip overflowed (`hidden`) tabs — they aren't focusable.\n const triggers = [\n ...(trigger.closest('[role=\"tablist\"]')?.querySelectorAll<HTMLElement>('[role=\"tab\"]:not([hidden])') ?? []),\n ];\n const index = triggers.indexOf(trigger);\n (triggers[index + 1] ?? triggers[index - 1])?.focus();\n onClose?.();\n }\n onKeyDown?.(event);\n };\n\n const trailing = showTrailing ? (\n <chakra.span\n position=\"relative\"\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n boxSize=\"24\"\n flexShrink={0}\n >\n {hasStatus && statusColor && (\n <chakra.span\n position=\"absolute\"\n inset={0}\n display=\"flex\"\n alignItems=\"center\"\n justifyContent=\"center\"\n pointerEvents=\"none\"\n transition=\"opacity 0.1s\"\n _groupHover={closable ? { opacity: 0 } : undefined}\n _groupFocusWithin={closable ? { opacity: 0 } : undefined}\n >\n <chakra.span boxSize=\"8\" borderRadius=\"full\" backgroundColor={STATUS_COLOR_TOKEN[statusColor]} />\n </chakra.span>\n )}\n {closable && (\n <chakra.span\n aria-hidden\n tabIndex={-1}\n onClick={handleCloseClick}\n css={closeButtonRecipe({ size: 'xs' })}\n position=\"absolute\"\n inset={0}\n color=\"icon/primary\"\n opacity={revealCloseOnInteraction ? 0 : 1}\n pointerEvents={revealCloseOnInteraction ? 'none' : 'auto'}\n transition=\"opacity 0.1s\"\n _groupHover={revealCloseOnInteraction ? revealOnInteraction : undefined}\n _groupFocusWithin={revealCloseOnInteraction ? revealOnInteraction : undefined}\n >\n <IconCross size=\"16\" />\n </chakra.span>\n )}\n </chakra.span>\n ) : null;\n\n const isCompact = isCompactTabs(variant, size);\n const hasOwnIconColor = variant === 'contained' && !!iconColor && !rest.disabled;\n const icon = Icon && (\n <Icon color={hasOwnIconColor ? iconColor : 'var(--tabs-icon-color)'} size={isCompact ? '16' : '24'} />\n );\n const canvasPadding = isCanvas\n ? { paddingInlineEnd: showTrailing ? '8' : Icon ? '16' : undefined, paddingInlineStart: Icon ? '8' : undefined }\n : undefined;\n\n return (\n <Tabs.Trigger ref={ref} {...rest} {...canvasPadding} className={mergedClassName} onKeyDown={handleTriggerKeyDown}>\n {isCanvas ? (\n <>\n <Box display=\"flex\" alignItems=\"center\" gap=\"8\">\n {icon}\n {children}\n </Box>\n {trailing}\n </>\n ) : variant === 'line' ? (\n <>\n <Box display=\"flex\" alignItems=\"center\" gap=\"8\">\n {icon}\n {children}\n </Box>\n {badge}\n </>\n ) : (\n <>\n <Box display=\"flex\" flexDirection=\"column\">\n <Box display=\"flex\" alignItems=\"flex-start\" gap=\"16\">\n {children}\n {badge}\n </Box>\n {!!secondaryText && (\n <Text as=\"span\" textStyle=\"body/md/regular\" color={rest.disabled ? 'text/on-disabled' : 'text/secondary'}>\n {secondaryText}\n </Text>\n )}\n </Box>\n {icon}\n </>\n )}\n </Tabs.Trigger>\n );\n});\n\nTrigger.displayName = 'BitkitTabs.Trigger';\n\ntype TabItem = ReactElement<BitkitTabsTriggerProps>;\n\n// Returns the set of visible tab indices for the overflow, always keeping the selected tab\n// visible: if it would overflow, it takes the last visible slot.\nconst getVisibleIndices = (total: number, count: number, selectedIndex: number) => {\n const visible = new Set<number>();\n for (let i = 0; i < count; i += 1) visible.add(i);\n if (selectedIndex >= 0 && selectedIndex < total && !visible.has(selectedIndex)) {\n visible.delete(count - 1);\n visible.add(selectedIndex);\n }\n return visible;\n};\n\ntype MoreMenuItemProps = {\n isCompact: boolean;\n item: TabItem;\n onSelect: () => void;\n variant: BitkitTabsRootProps['variant'];\n};\n\nconst MoreMenuItem = ({ isCompact, item, onSelect, variant }: MoreMenuItemProps) => {\n const menuStyles = useMenuStyles();\n const { badge, children, disabled, icon: Icon, iconColor, secondaryText, statusColor, value } = item.props;\n\n const isCanvas = variant === 'canvas';\n const isContained = variant === 'contained';\n const helperText = isContained ? secondaryText : undefined;\n\n const ownIconColor = isContained ? iconColor : undefined;\n const helperStyles = disabled ? { ...menuStyles.itemHelper, color: 'text/on-disabled' } : menuStyles.itemHelper;\n\n return (\n <Menu.Item data-helper={helperText ? '' : undefined} disabled={disabled} onSelect={onSelect} value={value}>\n {Icon && <Icon color={disabled ? 'icon/on-disabled' : ownIconColor} size={isCompact ? '16' : '24'} />}\n <Box flex=\"1\">\n <Text color={disabled ? 'text/on-disabled' : undefined}>{children}</Text>\n {!!helperText && <Text css={helperStyles}>{helperText}</Text>}\n </Box>\n {!isCanvas && badge}\n {isCanvas && statusColor && (\n <chakra.span boxSize=\"8\" borderRadius=\"full\" flexShrink={0} backgroundColor={STATUS_COLOR_TOKEN[statusColor]} />\n )}\n </Menu.Item>\n );\n};\n\nexport type BitkitTabsAddButtonProps = Omit<\n Extract<BitkitControlButtonProps, { href?: undefined }>,\n 'icon' | 'label' | 'size'\n> & {\n /** Accessible label / tooltip for the add button. */\n label?: string;\n};\n\n// \"+\" button to add a tab. Place it as a child of `List`; it always renders at the end of the row\n// (after the overflow menu). A compact `xxs` control button (16px icon, 4px padding) per the design.\nconst AddButton = forwardRef<HTMLButtonElement, BitkitTabsAddButtonProps>((props, ref) => {\n const { label = 'Add tab', ...rest } = props;\n return <BitkitControlButton ref={ref} icon={IconPlus} label={label} size=\"xxs\" {...rest} />;\n});\n\nAddButton.displayName = 'BitkitTabs.AddButton';\n\n// A stretched trigger (line tabs on mobile, or a consumer's own `flex`/`width`) is as wide as\n// its share of the list, not its content, so its laid-out width would count the free space as\n// needed space. Measure it unstretched, and unrounded: two 163.5px tabs read as 164 + 164 through\n// `offsetWidth` and overflow a 327px row.\n// The whole inline style is restored, because resetting the `flex` shorthand would also wipe any\n// inline flex longhands the consumer set.\nconst measureContentWidth = (node: HTMLElement) => {\n const { cssText } = node.style;\n node.style.flex = '0 0 auto';\n node.style.width = 'max-content';\n const contentWidth = node.getBoundingClientRect().width;\n node.style.cssText = cssText;\n return contentWidth;\n};\n\n// Overflow-aware List (all variants): measures the tabs and collapses the overflowing ones into a\n// \"N more…\" menu. The more-button look comes from the variant's `moreTrigger` recipe slot.\nconst List = forwardRef<HTMLDivElement, Tabs.ListProps>((props, ref) => {\n // Semantic/labelling attributes belong on the actual tablist, not the visual wrapper.\n const { children, css, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, ...rest } = props;\n const { size = 'lg', variant = 'line' } = useRootPropsContext();\n const api = useTabsContext();\n const styles = useTabsStyles();\n const isCompact = isCompactTabs(variant, size);\n\n // Split children: tab triggers participate in overflow; the optional add button always renders last.\n const allChildren = flattenChildren(children);\n const addButton = allChildren.find((child) => child.type === AddButton) ?? null;\n // Only Trigger elements are measured/overflowed; anything else (fragments, stray nodes) is ignored.\n const items = allChildren.filter((child) => child.type === Trigger) as TabItem[];\n // Re-measure whenever the tab set OR any width-affecting input changes: the variant and size, each\n // tab's value/label, icon/status/close/disabled state, and the text of its badge and secondaryText,\n // so a count going from 3 to 12 invalidates the cache.\n const measureKey = [\n variant,\n size,\n ...items.map((item) => {\n const p = item.props;\n return [\n p.value,\n String(p.children),\n p.icon ? 'i' : '',\n getTextContent(p.badge),\n getTextContent(p.secondaryText),\n p.statusColor ?? '',\n p.onClose ? 'c' : '',\n p.disabled ? 'd' : '',\n ].join(':');\n }),\n ].join('|');\n const selectedIndex = items.findIndex((item) => item.props.value === api.value);\n // Width reservations for the more button, sized for a two-digit count (\"10 more…\"), and for the\n // always-visible add button. Any slack here hides a tab that would have fitted.\n const moreReserve = isCompact ? 88 : 104;\n const addReserve = addButton ? 48 : 0;\n\n const listRef = useRef<HTMLDivElement | null>(null);\n const widthsRef = useRef<number[]>([]);\n // Horizontal padding of the list, cached during the measure pass so the resize hot path doesn't\n // call getComputedStyle on every tick.\n const paddingRef = useRef(0);\n // `measuredKey` is state (not a ref) so finishing the measure pass always re-renders and flips\n // `measuring` off — even when recompute keeps the same visibleCount (which would skip a re-render).\n const [measuredKey, setMeasuredKey] = useState<string | null>(null);\n const [visibleCount, setVisibleCount] = useState(items.length);\n\n const setListRef = useMemo(() => mergeRefs(listRef, ref), [ref]);\n\n const recompute = useCallback(() => {\n const el = listRef.current;\n const widths = widthsRef.current;\n if (!el || !widths.length) return;\n const available = el.clientWidth - paddingRef.current - addReserve;\n const totalWidth = widths.reduce((sum, w) => sum + w, 0);\n if (totalWidth <= available) {\n setVisibleCount(widths.length);\n return;\n }\n let used = moreReserve;\n let count = 0;\n for (let i = 0; i < widths.length; i += 1) {\n if (used + widths[i] > available) break;\n used += widths[i];\n count += 1;\n }\n setVisibleCount(Math.max(count, 1));\n }, [addReserve, moreReserve]);\n\n // Measure once per width-affecting change (all tabs are rendered visible during this pass).\n // Isomorphic layout effect: avoids the SSR \"useLayoutEffect does nothing on the server\" warning.\n const measuring = measuredKey !== measureKey;\n useSafeLayoutEffect(() => {\n const el = listRef.current;\n if (!el) return;\n if (measuredKey !== measureKey) {\n const tabEls = el.querySelectorAll<HTMLElement>('[data-tab-trigger]');\n widthsRef.current = Array.from(tabEls, measureContentWidth);\n const cs = getComputedStyle(el);\n paddingRef.current = parseFloat(cs.paddingLeft) + parseFloat(cs.paddingRight);\n setMeasuredKey(measureKey);\n }\n recompute();\n }, [measureKey, measuredKey, recompute]);\n\n // Swapping the fallback font for the webfont changes the tabs' widths without resizing the list,\n // so no ResizeObserver fires for it: measure again once the fonts are in.\n useEffect(() => {\n let cancelled = false;\n void document.fonts?.ready.then(() => {\n if (!cancelled) setMeasuredKey(null);\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n const el = listRef.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n // Coalesce resize bursts into one recompute per frame to avoid a read/write layout storm.\n let raf = 0;\n const observer = new ResizeObserver(() => {\n cancelAnimationFrame(raf);\n raf = requestAnimationFrame(recompute);\n });\n observer.observe(el);\n return () => {\n cancelAnimationFrame(raf);\n observer.disconnect();\n };\n }, [recompute]);\n\n const showAll = measuring || visibleCount >= items.length;\n const visible = showAll ? null : getVisibleIndices(items.length, visibleCount, selectedIndex);\n const hiddenItems = visible ? items.filter((_, i) => !visible.has(i)) : [];\n\n return (\n // The visual row carries the list styling (background, baseline border, leading padding) and is\n // measured for overflow. The tablist itself only wraps the tabs (`display: contents` keeps the\n // flex layout intact), so the more/add controls stay outside `role=\"tablist\"` per the ARIA spec.\n <Box ref={setListRef} css={[styles.list, css]} data-overflowing={hiddenItems.length > 0 ? '' : undefined} {...rest}>\n <Tabs.List display=\"contents\" id={id} aria-label={ariaLabel} aria-labelledby={ariaLabelledby}>\n {items.map((item, i) =>\n cloneElement(item, {\n key: item.props.value,\n 'data-tab-trigger': '',\n hidden: visible ? !visible.has(i) : undefined,\n } as Partial<BitkitTabsTriggerProps>),\n )}\n </Tabs.List>\n {hiddenItems.length > 0 && (\n <Menu.Root size={isCompact ? 'md' : 'lg'} positioning={{ gutter: 0, shift: -4 }}>\n <Menu.Trigger asChild>\n <chakra.button type=\"button\" css={styles.moreTrigger}>\n {hiddenItems.length} more…\n </chakra.button>\n </Menu.Trigger>\n <Portal>\n <Menu.Positioner>\n <Menu.Content>\n {hiddenItems.map((item) => (\n <MoreMenuItem\n isCompact={isCompact}\n item={item}\n key={item.props.value}\n onSelect={() => api.setValue(item.props.value)}\n variant={variant}\n />\n ))}\n </Menu.Content>\n </Menu.Positioner>\n </Portal>\n </Menu.Root>\n )}\n {addButton && (\n <Box display=\"flex\" alignItems=\"center\" flexShrink={0} paddingInline=\"8\">\n {addButton}\n </Box>\n )}\n </Box>\n );\n});\n\nList.displayName = 'BitkitTabs.List';\n\nconst BitkitTabs: Omit<typeof Tabs, 'Root' | 'Trigger' | 'List'> & {\n AddButton: typeof AddButton;\n List: typeof List;\n Root: typeof Root;\n Trigger: typeof Trigger;\n} = {\n ...Tabs,\n AddButton,\n List,\n Root,\n Trigger,\n};\n\nBitkitTabs.Content.displayName = 'BitkitTabs.Content';\nBitkitTabs.ContentGroup.displayName = 'BitkitTabs.ContentGroup';\nBitkitTabs.Root.displayName = 'BitkitTabs.Root';\n\nexport default BitkitTabs;\n"],"mappings":"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"}
|