@bitrise/bitkit-v2 0.3.499 → 0.3.500
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/BitkitAvatar/BitkitAvatar.d.ts +9 -0
- package/dist/components/BitkitAvatar/BitkitAvatar.js +5 -2
- package/dist/components/BitkitAvatar/BitkitAvatar.js.map +1 -1
- package/dist/components/BitkitSelect/BitkitSelect.js +3 -1
- package/dist/components/BitkitSelect/BitkitSelect.js.map +1 -1
- package/dist/components/BitkitSelectMenu/BitkitSelectMenu.d.ts +2 -0
- package/dist/components/BitkitSelectMenu/BitkitSelectMenu.js +2 -1
- package/dist/components/BitkitSelectMenu/BitkitSelectMenu.js.map +1 -1
- package/dist/components/BitkitUIHeader/UIHeaderNavButton.d.ts +3 -0
- package/dist/components/BitkitUIHeader/UIHeaderNavButton.js +4 -3
- package/dist/components/BitkitUIHeader/UIHeaderNavButton.js.map +1 -1
- package/dist/components/BitkitUISideNav/UISideNavWorkspaceSelector.d.ts +3 -0
- package/dist/components/BitkitUISideNav/UISideNavWorkspaceSelector.js +1 -0
- package/dist/components/BitkitUISideNav/UISideNavWorkspaceSelector.js.map +1 -1
- package/dist/theme/slot-recipes/Avatar.recipe.js +5 -1
- package/dist/theme/slot-recipes/Avatar.recipe.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AvatarRootProps } from '@chakra-ui/react/avatar';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
import { BitkitIconComponent } from '../../icons';
|
|
3
4
|
export type BitkitAvatarProps = Omit<AvatarRootProps, 'variant' | 'backgroundColor' | 'background' | 'bg' | 'colorPalette'> & ({
|
|
4
5
|
variant: 'image';
|
|
@@ -7,6 +8,8 @@ export type BitkitAvatarProps = Omit<AvatarRootProps, 'variant' | 'backgroundCol
|
|
|
7
8
|
icon?: never;
|
|
8
9
|
iconColor?: never;
|
|
9
10
|
backgroundColor?: never;
|
|
11
|
+
/** Replaces the initials when there is no image to show. Rendered as decoration (`aria-hidden`): give it no accessible name of its own, the avatar's `name` is announced next to it. */
|
|
12
|
+
fallback?: ReactNode;
|
|
10
13
|
} | {
|
|
11
14
|
variant: 'image+icon';
|
|
12
15
|
src: string;
|
|
@@ -14,6 +17,8 @@ export type BitkitAvatarProps = Omit<AvatarRootProps, 'variant' | 'backgroundCol
|
|
|
14
17
|
icon: BitkitIconComponent;
|
|
15
18
|
iconColor?: never;
|
|
16
19
|
backgroundColor?: never;
|
|
20
|
+
/** Replaces the initials when there is no image to show. Rendered as decoration (`aria-hidden`): give it no accessible name of its own, the avatar's `name` is announced next to it. */
|
|
21
|
+
fallback?: ReactNode;
|
|
17
22
|
} | {
|
|
18
23
|
variant: 'icon';
|
|
19
24
|
src?: never;
|
|
@@ -21,6 +26,7 @@ export type BitkitAvatarProps = Omit<AvatarRootProps, 'variant' | 'backgroundCol
|
|
|
21
26
|
icon: BitkitIconComponent;
|
|
22
27
|
iconColor?: AvatarRootProps['color'];
|
|
23
28
|
backgroundColor?: AvatarRootProps['color'];
|
|
29
|
+
fallback?: never;
|
|
24
30
|
} | {
|
|
25
31
|
variant: 'letters';
|
|
26
32
|
src?: never;
|
|
@@ -28,6 +34,7 @@ export type BitkitAvatarProps = Omit<AvatarRootProps, 'variant' | 'backgroundCol
|
|
|
28
34
|
icon?: never;
|
|
29
35
|
iconColor?: never;
|
|
30
36
|
backgroundColor?: never;
|
|
37
|
+
fallback?: never;
|
|
31
38
|
} | {
|
|
32
39
|
variant: 'user';
|
|
33
40
|
src: string;
|
|
@@ -35,6 +42,8 @@ export type BitkitAvatarProps = Omit<AvatarRootProps, 'variant' | 'backgroundCol
|
|
|
35
42
|
icon?: never;
|
|
36
43
|
iconColor?: never;
|
|
37
44
|
backgroundColor?: never;
|
|
45
|
+
/** Replaces the initials when there is no image to show. Rendered as decoration (`aria-hidden`): give it no accessible name of its own, the avatar's `name` is announced next to it. */
|
|
46
|
+
fallback?: ReactNode;
|
|
38
47
|
});
|
|
39
48
|
declare const BitkitAvatar: import('react').ForwardRefExoticComponent<BitkitAvatarProps & import('react').RefAttributes<HTMLDivElement>>;
|
|
40
49
|
export default BitkitAvatar;
|
|
@@ -16,7 +16,7 @@ var processFallbackName = (name) => {
|
|
|
16
16
|
return str && str.length >= 2 ? `${str[0]} ${str[str.length - 1]}` : str;
|
|
17
17
|
};
|
|
18
18
|
var BitkitAvatar = forwardRef((props, ref) => {
|
|
19
|
-
const { size, variant, src, name, icon: Icon, colorVariant = pickPalette(name), iconColor, backgroundColor, ...rest } = props;
|
|
19
|
+
const { size, variant, src, name, icon: Icon, colorVariant = pickPalette(name), iconColor, backgroundColor, fallback, ...rest } = props;
|
|
20
20
|
const recipe = useSlotRecipe({ key: "avatar" });
|
|
21
21
|
const styleVariant = variant === "user" && [
|
|
22
22
|
"24",
|
|
@@ -37,7 +37,10 @@ var BitkitAvatar = forwardRef((props, ref) => {
|
|
|
37
37
|
backgroundColor,
|
|
38
38
|
...rest,
|
|
39
39
|
children: [
|
|
40
|
-
|
|
40
|
+
fallback ? /* @__PURE__ */ jsx(Avatar.Fallback, {
|
|
41
|
+
"aria-hidden": true,
|
|
42
|
+
children: fallback
|
|
43
|
+
}) : !!fallbackName && /* @__PURE__ */ jsx(Avatar.Fallback, { name: fallbackName }),
|
|
41
44
|
!!src && /* @__PURE__ */ jsx(Avatar.Image, { src }),
|
|
42
45
|
!!Icon && variant === "icon" && /* @__PURE__ */ jsx(Icon, {
|
|
43
46
|
css: styles.icon,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitAvatar.js","names":[],"sources":["../../../lib/components/BitkitAvatar/BitkitAvatar.tsx"],"sourcesContent":["import { Avatar, type AvatarRootProps } from '@chakra-ui/react/avatar';\nimport { Box } from '@chakra-ui/react/box';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { forwardRef } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport avatarSlotRecipe from '../../theme/slot-recipes/Avatar.recipe';\n\nexport type BitkitAvatarProps = Omit<\n AvatarRootProps,\n 'variant' | 'backgroundColor' | 'background' | 'bg' | 'colorPalette'\n> &\n (\n | {\n variant: 'image';\n src: string;\n name: string;\n icon?: never;\n iconColor?: never;\n backgroundColor?: never;\n }\n | {\n variant: 'image+icon';\n src: string;\n name: string;\n icon: BitkitIconComponent;\n iconColor?: never;\n backgroundColor?: never;\n }\n | {\n variant: 'icon';\n src?: never;\n name?: never;\n icon: BitkitIconComponent;\n iconColor?: AvatarRootProps['color'];\n backgroundColor?: AvatarRootProps['color'];\n }\n | {\n variant: 'letters';\n src?: never;\n name: string;\n icon?: never;\n iconColor?: never;\n backgroundColor?: never;\n }\n | {\n variant: 'user';\n src: string;\n name: string;\n icon?: never;\n iconColor?: never;\n backgroundColor?: never;\n }\n );\n\ntype AvatarColorVariant =\n 'neutral' | 'purple' | 'indigo' | 'blue' | 'green' | 'yellow' | 'red' | 'orange' | 'turquoise';\n\nconst COLORS = Object.keys(avatarSlotRecipe.variants?.colorVariant || {}) as AvatarColorVariant[];\n\nconst pickPalette = (name?: string): AvatarColorVariant => {\n if (!name || name.length === 0) return 'neutral';\n const str = name.trim();\n return COLORS[(str.charCodeAt(0) + str.charCodeAt(str.length - 1)) % COLORS.length];\n};\n\nconst processFallbackName = (name?: string) => {\n const str = name?.trim() || '';\n return str && str.length >= 2 ? `${str[0]} ${str[str.length - 1]}` : str;\n};\n\nconst BitkitAvatar = forwardRef<HTMLDivElement, BitkitAvatarProps>((props, ref) => {\n const {\n size,\n variant,\n src,\n name,\n icon: Icon,\n colorVariant = pickPalette(name),\n iconColor,\n backgroundColor,\n ...rest\n } = props;\n\n const recipe = useSlotRecipe({ key: 'avatar' });\n const styleVariant = variant === 'user' && ['24', '32', '40', '48'].includes(size as string) ? 'circle' : 'rounded';\n const styles = recipe({ size, variant: styleVariant });\n const fallbackName = processFallbackName(name);\n\n return (\n <Avatar.Root\n ref={ref}\n size={size}\n variant={styleVariant}\n colorVariant={colorVariant}\n backgroundColor={backgroundColor}\n {...rest}\n >\n {!!fallbackName && <Avatar.Fallback name={fallbackName}
|
|
1
|
+
{"version":3,"file":"BitkitAvatar.js","names":[],"sources":["../../../lib/components/BitkitAvatar/BitkitAvatar.tsx"],"sourcesContent":["import { Avatar, type AvatarRootProps } from '@chakra-ui/react/avatar';\nimport { Box } from '@chakra-ui/react/box';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { forwardRef, type ReactNode } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport avatarSlotRecipe from '../../theme/slot-recipes/Avatar.recipe';\n\nexport type BitkitAvatarProps = Omit<\n AvatarRootProps,\n 'variant' | 'backgroundColor' | 'background' | 'bg' | 'colorPalette'\n> &\n (\n | {\n variant: 'image';\n src: string;\n name: string;\n icon?: never;\n iconColor?: never;\n backgroundColor?: never;\n /** Replaces the initials when there is no image to show. Rendered as decoration (`aria-hidden`): give it no accessible name of its own, the avatar's `name` is announced next to it. */\n fallback?: ReactNode;\n }\n | {\n variant: 'image+icon';\n src: string;\n name: string;\n icon: BitkitIconComponent;\n iconColor?: never;\n backgroundColor?: never;\n /** Replaces the initials when there is no image to show. Rendered as decoration (`aria-hidden`): give it no accessible name of its own, the avatar's `name` is announced next to it. */\n fallback?: ReactNode;\n }\n | {\n variant: 'icon';\n src?: never;\n name?: never;\n icon: BitkitIconComponent;\n iconColor?: AvatarRootProps['color'];\n backgroundColor?: AvatarRootProps['color'];\n fallback?: never;\n }\n | {\n variant: 'letters';\n src?: never;\n name: string;\n icon?: never;\n iconColor?: never;\n backgroundColor?: never;\n fallback?: never;\n }\n | {\n variant: 'user';\n src: string;\n name: string;\n icon?: never;\n iconColor?: never;\n backgroundColor?: never;\n /** Replaces the initials when there is no image to show. Rendered as decoration (`aria-hidden`): give it no accessible name of its own, the avatar's `name` is announced next to it. */\n fallback?: ReactNode;\n }\n );\n\ntype AvatarColorVariant =\n 'neutral' | 'purple' | 'indigo' | 'blue' | 'green' | 'yellow' | 'red' | 'orange' | 'turquoise';\n\nconst COLORS = Object.keys(avatarSlotRecipe.variants?.colorVariant || {}) as AvatarColorVariant[];\n\nconst pickPalette = (name?: string): AvatarColorVariant => {\n if (!name || name.length === 0) return 'neutral';\n const str = name.trim();\n return COLORS[(str.charCodeAt(0) + str.charCodeAt(str.length - 1)) % COLORS.length];\n};\n\nconst processFallbackName = (name?: string) => {\n const str = name?.trim() || '';\n return str && str.length >= 2 ? `${str[0]} ${str[str.length - 1]}` : str;\n};\n\nconst BitkitAvatar = forwardRef<HTMLDivElement, BitkitAvatarProps>((props, ref) => {\n const {\n size,\n variant,\n src,\n name,\n icon: Icon,\n colorVariant = pickPalette(name),\n iconColor,\n backgroundColor,\n fallback,\n ...rest\n } = props;\n\n const recipe = useSlotRecipe({ key: 'avatar' });\n const styleVariant = variant === 'user' && ['24', '32', '40', '48'].includes(size as string) ? 'circle' : 'rounded';\n const styles = recipe({ size, variant: styleVariant });\n const fallbackName = processFallbackName(name);\n\n return (\n <Avatar.Root\n ref={ref}\n size={size}\n variant={styleVariant}\n colorVariant={colorVariant}\n backgroundColor={backgroundColor}\n {...rest}\n >\n {fallback ? (\n <Avatar.Fallback aria-hidden>{fallback}</Avatar.Fallback>\n ) : (\n !!fallbackName && <Avatar.Fallback name={fallbackName} />\n )}\n {!!src && <Avatar.Image src={src} />}\n {!!Icon && variant === 'icon' && <Icon css={styles.icon} color={iconColor} size=\"24\" />}\n {!!Icon && variant === 'image+icon' && (\n <Box css={styles.badgeContainer}>\n <Icon css={styles.badge} size=\"16\" />\n </Box>\n )}\n </Avatar.Root>\n );\n});\n\nBitkitAvatar.displayName = 'BitkitAvatar';\n\nexport default BitkitAvatar;\n"],"mappings":";;;;;;;AAkEA,IAAM,SAAS,OAAO,KAAK,iBAAiB,UAAU,gBAAgB,CAAC,CAAC;AAExE,IAAM,eAAe,SAAsC;CACzD,IAAI,CAAC,QAAQ,KAAK,WAAW,GAAG,OAAO;CACvC,MAAM,MAAM,KAAK,KAAK;CACtB,OAAO,QAAQ,IAAI,WAAW,CAAC,IAAI,IAAI,WAAW,IAAI,SAAS,CAAC,KAAK,OAAO;AAC9E;AAEA,IAAM,uBAAuB,SAAkB;CAC7C,MAAM,MAAM,MAAM,KAAK,KAAK;CAC5B,OAAO,OAAO,IAAI,UAAU,IAAI,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,SAAS,OAAO;AACvE;AAEA,IAAM,eAAe,YAA+C,OAAO,QAAQ;CACjF,MAAM,EACJ,MACA,SACA,KACA,MACA,MAAM,MACN,eAAe,YAAY,IAAI,GAC/B,WACA,iBACA,UACA,GAAG,SACD;CAEJ,MAAM,SAAS,cAAc,EAAE,KAAK,SAAS,CAAC;CAC9C,MAAM,eAAe,YAAY,UAAU;EAAC;EAAM;EAAM;EAAM;CAAI,CAAC,CAAC,SAAS,IAAc,IAAI,WAAW;CAC1G,MAAM,SAAS,OAAO;EAAE;EAAM,SAAS;CAAa,CAAC;CACrD,MAAM,eAAe,oBAAoB,IAAI;CAE7C,OACE,qBAAC,OAAO,MAAR;EACO;EACC;EACN,SAAS;EACK;EACG;EACjB,GAAI;EANN,UAAA;GAQG,WACC,oBAAC,OAAO,UAAR;IAAiB,eAAA;IAAa,UAAA;GAA0B,CAAA,IAExD,CAAC,CAAC,gBAAgB,oBAAC,OAAO,UAAR,EAAiB,MAAM,aAAe,CAAA;GAEzD,CAAC,CAAC,OAAO,oBAAC,OAAO,OAAR,EAAmB,IAAM,CAAA;GAClC,CAAC,CAAC,QAAQ,YAAY,UAAU,oBAAC,MAAD;IAAM,KAAK,OAAO;IAAM,OAAO;IAAW,MAAK;GAAM,CAAA;GACrF,CAAC,CAAC,QAAQ,YAAY,gBACrB,oBAAC,KAAD;IAAK,KAAK,OAAO;IACf,UAAA,oBAAC,MAAD;KAAM,KAAK,OAAO;KAAO,MAAK;IAAM,CAAA;GACjC,CAAA;EAEI;;AAEjB,CAAC;AAED,aAAa,cAAc"}
|
|
@@ -21,6 +21,7 @@ var SelectValue = ({ placeholder, state, size }) => {
|
|
|
21
21
|
const items = useSelectContext().selectedItems;
|
|
22
22
|
const Icon = items[0]?.icon;
|
|
23
23
|
const avatar = items[0]?.avatar;
|
|
24
|
+
const avatarFallback = items[0]?.avatarFallback;
|
|
24
25
|
const label = items[0]?.label;
|
|
25
26
|
const showAvatar = avatar !== void 0;
|
|
26
27
|
const { avatarSize, iconSize } = selectSizeMap[size];
|
|
@@ -34,7 +35,8 @@ var SelectValue = ({ placeholder, state, size }) => {
|
|
|
34
35
|
variant: "image",
|
|
35
36
|
src: avatar ?? "",
|
|
36
37
|
name: label,
|
|
37
|
-
size: avatarSize
|
|
38
|
+
size: avatarSize,
|
|
39
|
+
fallback: avatarFallback
|
|
38
40
|
})
|
|
39
41
|
}) : Icon && /* @__PURE__ */ jsx(Icon, {
|
|
40
42
|
css: styles.valueIcon,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitSelect.js","names":[],"sources":["../../../lib/components/BitkitSelect/BitkitSelect.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { createListCollection } from '@chakra-ui/react/collection';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Select, type SelectRootProps, type SelectTriggerProps, useSelectContext } from '@chakra-ui/react/select';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, useContext } from 'react';\n\nimport { IconErrorCircleFilled, IconWarningYellow } from '../../icons';\nimport AssetSelectChevron from '../../utilities/AssetSelectChevron.tsx';\nimport BitkitPortalContext from '../../utilities/BitkitPortalContext';\nimport { withSubComponents } from '../../utilities/withSubComponents.ts';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField.tsx';\nimport BitkitSelectMenu, {\n type BitkitSelectMenuEmptyStateProps,\n type BitkitSelectMenuErrorStateProps,\n type BitkitSelectMenuItemProps,\n type BitkitSelectMenuScrollProps,\n type BitkitSelectMenuSearchProps,\n} from '../BitkitSelectMenu/BitkitSelectMenu.tsx';\nimport BitkitSelectMenuAction, {\n type BitkitSelectMenuActionChild,\n} from '../BitkitSelectMenu/BitkitSelectMenuAction.tsx';\nimport { selectSizeMap } from '../BitkitSelectMenu/SelectMenuShell.tsx';\n\nexport type BitkitSelectTriggerProps = SelectTriggerProps;\n\nexport type BitkitSelectProps = Omit<BitkitFieldProps, 'children' | 'onChange' | 'state'> & {\n children?: BitkitSelectMenuActionChild;\n defaultValue?: string;\n isLoading?: boolean;\n items: Array<BitkitSelectMenuItemProps>;\n onValueChange?: (newVal: string) => void;\n placeholder?: string;\n disablePortal?: boolean;\n selectProps?: Omit<SelectRootProps, 'collection' | 'defaultValue' | 'onValueChange' | 'size' | 'value'>;\n size?: 'md' | 'lg';\n state?: 'disabled' | 'error' | 'readOnly' | 'warning';\n triggerProps?: BitkitSelectTriggerProps;\n value?: string;\n} & BitkitSelectMenuSearchProps &\n BitkitSelectMenuScrollProps &\n BitkitSelectMenuEmptyStateProps &\n BitkitSelectMenuErrorStateProps;\n\ntype SelectValueProps = {\n placeholder?: string;\n size: NonNullable<BitkitSelectProps['size']>;\n state?: BitkitSelectProps['state'];\n};\n\nconst SelectValue = ({ placeholder, state, size }: SelectValueProps) => {\n const select = useSelectContext();\n const items = select.selectedItems as Array<BitkitSelectMenuItemProps>;\n\n const Icon = items[0]?.icon;\n const avatar = items[0]?.avatar;\n const label = items[0]?.label;\n const showAvatar = avatar !== undefined;\n\n const { avatarSize, iconSize } = selectSizeMap[size];\n\n const recipe = useSlotRecipe({ key: 'select' });\n const styles = recipe({ size });\n\n return items[0] ? (\n <Select.ValueText placeholder={placeholder ?? (state === 'readOnly' ? '(not selected)' : 'Select an option')}>\n {showAvatar ? (\n // Same avatar handling as the menu item (see BitkitSelectMenu.tsx). The `data-slot`\n // lets the trigger recipe shrink its vertical padding so the avatar row keeps the\n // 48/40 trigger height (see the `&:has([data-slot=\"avatar\"])` rule in Select.recipe.ts).\n <Box data-slot=\"avatar\" css={styles.avatar}>\n <BitkitAvatar variant=\"image\" src={avatar ?? ''} name={label} size={avatarSize} />\n </Box>\n ) : (\n Icon && <Icon css={styles.valueIcon} size={iconSize} flexShrink={0} />\n )}\n <Text as=\"span\" overflow=\"hidden\" textOverflow=\"ellipsis\" whiteSpace=\"nowrap\" minWidth=\"0\">\n {label}\n </Text>\n </Select.ValueText>\n ) : (\n <Select.ValueText\n placeholder={placeholder ?? (state === 'readOnly' ? '(not selected)' : 'Select an option')}\n display=\"block\"\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n whiteSpace=\"nowrap\"\n />\n );\n};\n\nconst BitkitSelect = forwardRef<HTMLDivElement, BitkitSelectProps>((props: BitkitSelectProps, ref) => {\n const {\n children,\n defaultValue,\n emptyHelperText,\n emptyLabel,\n errorHelperText,\n errorLabel,\n isLoading,\n items,\n onScrolledToBottom,\n onSearchChange,\n onValueChange,\n placeholder,\n disablePortal,\n searchPlaceholder,\n searchValue,\n selectProps,\n size = 'lg',\n state,\n triggerProps,\n value,\n ...fieldProps\n } = props;\n\n const collection = createListCollection({\n items,\n groupBy: (item) => item.group || '',\n isItemDisabled: (item) => !!item.disabled,\n });\n\n const { disablePortal: disablePortalFromContext } = useContext(BitkitPortalContext);\n const isInvalid = state === 'error' || !!fieldProps.errorText;\n\n return (\n <BitkitField ref={ref} state={state} {...fieldProps}>\n <Select.Root\n collection={collection}\n // Chakra pins the list to the trigger's width; ours grows with its options, up to the recipe's cap.\n positioning={{ sameWidth: false }}\n size={size}\n {...selectProps}\n defaultValue={defaultValue ? [defaultValue] : undefined}\n disabled={state === 'disabled'}\n hasStatusIcon={state === 'error' || state === 'warning'}\n invalid={isInvalid}\n onValueChange={(newVal) => onValueChange?.(newVal.value[0])}\n readOnly={state === 'readOnly'}\n // Bypass Zag's isScrollable(contentEl) gate — our Content is overflow:hidden flex\n // column, so the real scroll container is itemList. See BitkitMultiselect for why.\n scrollToIndexFn={({ getElement }) => getElement()?.scrollIntoView({ block: 'nearest' })}\n // Stay controlled whenever `value` is provided — including `''` (\"nothing selected\"). A\n // truthiness check (`value ? … : undefined`) passes `undefined` for `''`, which flips\n // Select.Root to uncontrolled: it then ignores `value`, so resets don't take and\n // onValueChange stops firing when the same option is re-selected.\n value={value === undefined ? undefined : value ? [value] : []}\n >\n <Select.Control className=\"group\">\n <Select.HiddenSelect />\n <Select.Trigger {...triggerProps} aria-readonly={state === 'readOnly' || undefined}>\n <SelectValue placeholder={placeholder} size={size} state={state} />\n </Select.Trigger>\n <Select.IndicatorGroup>\n {state === 'error' && (\n <Select.Indicator>\n <IconErrorCircleFilled size={size === 'lg' ? '24' : '16'} color=\"icon/negative\" />\n </Select.Indicator>\n )}\n {state === 'warning' && (\n <Select.Indicator>\n <IconWarningYellow size={size === 'lg' ? '24' : '16'} />\n </Select.Indicator>\n )}\n <Select.Indicator asChild>\n <AssetSelectChevron />\n </Select.Indicator>\n </Select.IndicatorGroup>\n </Select.Control>\n <Portal disabled={disablePortal || disablePortalFromContext}>\n <Select.Positioner>\n <BitkitSelectMenu\n collection={collection}\n emptyHelperText={emptyHelperText}\n emptyLabel={emptyLabel}\n errorHelperText={errorHelperText}\n errorLabel={errorLabel}\n isLoading={isLoading}\n onScrolledToBottom={onScrolledToBottom}\n onSearchChange={onSearchChange}\n searchPlaceholder={searchPlaceholder}\n searchValue={searchValue}\n size={size}\n >\n {children}\n </BitkitSelectMenu>\n </Select.Positioner>\n </Portal>\n </Select.Root>\n </BitkitField>\n );\n});\n\nBitkitSelect.displayName = 'BitkitSelect';\n\nexport default withSubComponents(BitkitSelect, { Action: BitkitSelectMenuAction });\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoDA,IAAM,eAAe,EAAE,aAAa,OAAO,WAA6B;CAEtE,MAAM,QADS,iBACD,CAAA,CAAO;CAErB,MAAM,OAAO,MAAM,EAAE,EAAE;CACvB,MAAM,SAAS,MAAM,EAAE,EAAE;CACzB,MAAM,QAAQ,MAAM,EAAE,EAAE;CACxB,MAAM,aAAa,WAAW,KAAA;CAE9B,MAAM,EAAE,YAAY,aAAa,cAAc;CAG/C,MAAM,SADS,cAAc,EAAE,KAAK,SAAS,CAC9B,CAAA,CAAO,EAAE,KAAK,CAAC;CAE9B,OAAO,MAAM,KACX,qBAAC,OAAO,WAAR;EAAkB,aAAa,gBAAgB,UAAU,aAAa,mBAAmB;EAAzF,UAAA,CACG,aAIC,oBAAC,KAAD;GAAK,aAAU;GAAS,KAAK,OAAO;GAClC,UAAA,oBAAC,cAAD;IAAc,SAAQ;IAAQ,KAAK,UAAU;IAAI,MAAM;IAAO,MAAM;GAAa,CAAA;EAC9E,CAAA,IAEL,QAAQ,oBAAC,MAAD;GAAM,KAAK,OAAO;GAAW,MAAM;GAAU,YAAY;EAAI,CAAA,GAEvE,oBAAC,MAAD;GAAM,IAAG;GAAO,UAAS;GAAS,cAAa;GAAW,YAAW;GAAS,UAAS;GACpF,UAAA;EACG,CAAA,CACU;CAElB,CAAA,IAAA,oBAAC,OAAO,WAAR;EACE,aAAa,gBAAgB,UAAU,aAAa,mBAAmB;EACvE,SAAQ;EACR,UAAS;EACT,cAAa;EACb,YAAW;CACZ,CAAA;AAEL;AAEA,IAAM,eAAe,YAA+C,OAA0B,QAAQ;CACpG,MAAM,EACJ,UACA,cACA,iBACA,YACA,iBACA,YACA,WACA,OACA,oBACA,gBACA,eACA,aACA,eACA,mBACA,aACA,aACA,OAAO,MACP,OACA,cACA,OACA,GAAG,eACD;CAEJ,MAAM,aAAa,qBAAqB;EACtC;EACA,UAAU,SAAS,KAAK,SAAS;EACjC,iBAAiB,SAAS,CAAC,CAAC,KAAK;CACnC,CAAC;CAED,MAAM,EAAE,eAAe,6BAA6B,WAAW,mBAAmB;CAClF,MAAM,YAAY,UAAU,WAAW,CAAC,CAAC,WAAW;CAEpD,OACE,oBAAC,aAAD;EAAkB;EAAY;EAAO,GAAI;EACvC,UAAA,qBAAC,OAAO,MAAR;GACc;GAEZ,aAAa,EAAE,WAAW,MAAM;GAC1B;GACN,GAAI;GACJ,cAAc,eAAe,CAAC,YAAY,IAAI,KAAA;GAC9C,UAAU,UAAU;GACpB,eAAe,UAAU,WAAW,UAAU;GAC9C,SAAS;GACT,gBAAgB,WAAW,gBAAgB,OAAO,MAAM,EAAE;GAC1D,UAAU,UAAU;GAGpB,kBAAkB,EAAE,iBAAiB,WAAW,CAAC,EAAE,eAAe,EAAE,OAAO,UAAU,CAAC;GAKtF,OAAO,UAAU,KAAA,IAAY,KAAA,IAAY,QAAQ,CAAC,KAAK,IAAI,CAAC;GAnB9D,UAAA,CAqBE,qBAAC,OAAO,SAAR;IAAgB,WAAU;IAA1B,UAAA;KACE,oBAAC,OAAO,cAAR,CAAsB,CAAA;KACtB,oBAAC,OAAO,SAAR;MAAgB,GAAI;MAAc,iBAAe,UAAU,cAAc,KAAA;MACvE,UAAA,oBAAC,aAAD;OAA0B;OAAmB;OAAa;MAAQ,CAAA;KACpD,CAAA;KAChB,qBAAC,OAAO,gBAAR,EAAA,UAAA;MACG,UAAU,WACT,oBAAC,OAAO,WAAR,EAAA,UACE,oBAAC,uBAAD;OAAuB,MAAM,SAAS,OAAO,OAAO;OAAM,OAAM;MAAiB,CAAA,EACjE,CAAA;MAEnB,UAAU,aACT,oBAAC,OAAO,WAAR,EAAA,UACE,oBAAC,mBAAD,EAAmB,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA,EACvC,CAAA;MAEpB,oBAAC,OAAO,WAAR;OAAkB,SAAA;OAChB,UAAA,oBAAC,oBAAD,CAAqB,CAAA;MACL,CAAA;KACG,EAAA,CAAA;IACT;GAChB,CAAA,GAAA,oBAAC,QAAD;IAAQ,UAAU,iBAAiB;IACjC,UAAA,oBAAC,OAAO,YAAR,EAAA,UACE,oBAAC,kBAAD;KACc;KACK;KACL;KACK;KACL;KACD;KACS;KACJ;KACG;KACN;KACP;KAEL;IACe,CAAA,EACD,CAAA;GACb,CAAA,CACG;;CACF,CAAA;AAEjB,CAAC;AAED,aAAa,cAAc;AAE3B,IAAA,uBAAe,kBAAkB,cAAc,EAAE,QAAQ,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"BitkitSelect.js","names":[],"sources":["../../../lib/components/BitkitSelect/BitkitSelect.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { createListCollection } from '@chakra-ui/react/collection';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Select, type SelectRootProps, type SelectTriggerProps, useSelectContext } from '@chakra-ui/react/select';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, useContext } from 'react';\n\nimport { IconErrorCircleFilled, IconWarningYellow } from '../../icons';\nimport AssetSelectChevron from '../../utilities/AssetSelectChevron.tsx';\nimport BitkitPortalContext from '../../utilities/BitkitPortalContext';\nimport { withSubComponents } from '../../utilities/withSubComponents.ts';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField.tsx';\nimport BitkitSelectMenu, {\n type BitkitSelectMenuEmptyStateProps,\n type BitkitSelectMenuErrorStateProps,\n type BitkitSelectMenuItemProps,\n type BitkitSelectMenuScrollProps,\n type BitkitSelectMenuSearchProps,\n} from '../BitkitSelectMenu/BitkitSelectMenu.tsx';\nimport BitkitSelectMenuAction, {\n type BitkitSelectMenuActionChild,\n} from '../BitkitSelectMenu/BitkitSelectMenuAction.tsx';\nimport { selectSizeMap } from '../BitkitSelectMenu/SelectMenuShell.tsx';\n\nexport type BitkitSelectTriggerProps = SelectTriggerProps;\n\nexport type BitkitSelectProps = Omit<BitkitFieldProps, 'children' | 'onChange' | 'state'> & {\n children?: BitkitSelectMenuActionChild;\n defaultValue?: string;\n isLoading?: boolean;\n items: Array<BitkitSelectMenuItemProps>;\n onValueChange?: (newVal: string) => void;\n placeholder?: string;\n disablePortal?: boolean;\n selectProps?: Omit<SelectRootProps, 'collection' | 'defaultValue' | 'onValueChange' | 'size' | 'value'>;\n size?: 'md' | 'lg';\n state?: 'disabled' | 'error' | 'readOnly' | 'warning';\n triggerProps?: BitkitSelectTriggerProps;\n value?: string;\n} & BitkitSelectMenuSearchProps &\n BitkitSelectMenuScrollProps &\n BitkitSelectMenuEmptyStateProps &\n BitkitSelectMenuErrorStateProps;\n\ntype SelectValueProps = {\n placeholder?: string;\n size: NonNullable<BitkitSelectProps['size']>;\n state?: BitkitSelectProps['state'];\n};\n\nconst SelectValue = ({ placeholder, state, size }: SelectValueProps) => {\n const select = useSelectContext();\n const items = select.selectedItems as Array<BitkitSelectMenuItemProps>;\n\n const Icon = items[0]?.icon;\n const avatar = items[0]?.avatar;\n const avatarFallback = items[0]?.avatarFallback;\n const label = items[0]?.label;\n const showAvatar = avatar !== undefined;\n\n const { avatarSize, iconSize } = selectSizeMap[size];\n\n const recipe = useSlotRecipe({ key: 'select' });\n const styles = recipe({ size });\n\n return items[0] ? (\n <Select.ValueText placeholder={placeholder ?? (state === 'readOnly' ? '(not selected)' : 'Select an option')}>\n {showAvatar ? (\n // Same avatar handling as the menu item (see BitkitSelectMenu.tsx). The `data-slot`\n // lets the trigger recipe shrink its vertical padding so the avatar row keeps the\n // 48/40 trigger height (see the `&:has([data-slot=\"avatar\"])` rule in Select.recipe.ts).\n <Box data-slot=\"avatar\" css={styles.avatar}>\n <BitkitAvatar variant=\"image\" src={avatar ?? ''} name={label} size={avatarSize} fallback={avatarFallback} />\n </Box>\n ) : (\n Icon && <Icon css={styles.valueIcon} size={iconSize} flexShrink={0} />\n )}\n <Text as=\"span\" overflow=\"hidden\" textOverflow=\"ellipsis\" whiteSpace=\"nowrap\" minWidth=\"0\">\n {label}\n </Text>\n </Select.ValueText>\n ) : (\n <Select.ValueText\n placeholder={placeholder ?? (state === 'readOnly' ? '(not selected)' : 'Select an option')}\n display=\"block\"\n overflow=\"hidden\"\n textOverflow=\"ellipsis\"\n whiteSpace=\"nowrap\"\n />\n );\n};\n\nconst BitkitSelect = forwardRef<HTMLDivElement, BitkitSelectProps>((props: BitkitSelectProps, ref) => {\n const {\n children,\n defaultValue,\n emptyHelperText,\n emptyLabel,\n errorHelperText,\n errorLabel,\n isLoading,\n items,\n onScrolledToBottom,\n onSearchChange,\n onValueChange,\n placeholder,\n disablePortal,\n searchPlaceholder,\n searchValue,\n selectProps,\n size = 'lg',\n state,\n triggerProps,\n value,\n ...fieldProps\n } = props;\n\n const collection = createListCollection({\n items,\n groupBy: (item) => item.group || '',\n isItemDisabled: (item) => !!item.disabled,\n });\n\n const { disablePortal: disablePortalFromContext } = useContext(BitkitPortalContext);\n const isInvalid = state === 'error' || !!fieldProps.errorText;\n\n return (\n <BitkitField ref={ref} state={state} {...fieldProps}>\n <Select.Root\n collection={collection}\n // Chakra pins the list to the trigger's width; ours grows with its options, up to the recipe's cap.\n positioning={{ sameWidth: false }}\n size={size}\n {...selectProps}\n defaultValue={defaultValue ? [defaultValue] : undefined}\n disabled={state === 'disabled'}\n hasStatusIcon={state === 'error' || state === 'warning'}\n invalid={isInvalid}\n onValueChange={(newVal) => onValueChange?.(newVal.value[0])}\n readOnly={state === 'readOnly'}\n // Bypass Zag's isScrollable(contentEl) gate — our Content is overflow:hidden flex\n // column, so the real scroll container is itemList. See BitkitMultiselect for why.\n scrollToIndexFn={({ getElement }) => getElement()?.scrollIntoView({ block: 'nearest' })}\n // Stay controlled whenever `value` is provided — including `''` (\"nothing selected\"). A\n // truthiness check (`value ? … : undefined`) passes `undefined` for `''`, which flips\n // Select.Root to uncontrolled: it then ignores `value`, so resets don't take and\n // onValueChange stops firing when the same option is re-selected.\n value={value === undefined ? undefined : value ? [value] : []}\n >\n <Select.Control className=\"group\">\n <Select.HiddenSelect />\n <Select.Trigger {...triggerProps} aria-readonly={state === 'readOnly' || undefined}>\n <SelectValue placeholder={placeholder} size={size} state={state} />\n </Select.Trigger>\n <Select.IndicatorGroup>\n {state === 'error' && (\n <Select.Indicator>\n <IconErrorCircleFilled size={size === 'lg' ? '24' : '16'} color=\"icon/negative\" />\n </Select.Indicator>\n )}\n {state === 'warning' && (\n <Select.Indicator>\n <IconWarningYellow size={size === 'lg' ? '24' : '16'} />\n </Select.Indicator>\n )}\n <Select.Indicator asChild>\n <AssetSelectChevron />\n </Select.Indicator>\n </Select.IndicatorGroup>\n </Select.Control>\n <Portal disabled={disablePortal || disablePortalFromContext}>\n <Select.Positioner>\n <BitkitSelectMenu\n collection={collection}\n emptyHelperText={emptyHelperText}\n emptyLabel={emptyLabel}\n errorHelperText={errorHelperText}\n errorLabel={errorLabel}\n isLoading={isLoading}\n onScrolledToBottom={onScrolledToBottom}\n onSearchChange={onSearchChange}\n searchPlaceholder={searchPlaceholder}\n searchValue={searchValue}\n size={size}\n >\n {children}\n </BitkitSelectMenu>\n </Select.Positioner>\n </Portal>\n </Select.Root>\n </BitkitField>\n );\n});\n\nBitkitSelect.displayName = 'BitkitSelect';\n\nexport default withSubComponents(BitkitSelect, { Action: BitkitSelectMenuAction });\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoDA,IAAM,eAAe,EAAE,aAAa,OAAO,WAA6B;CAEtE,MAAM,QADS,iBACD,CAAA,CAAO;CAErB,MAAM,OAAO,MAAM,EAAE,EAAE;CACvB,MAAM,SAAS,MAAM,EAAE,EAAE;CACzB,MAAM,iBAAiB,MAAM,EAAE,EAAE;CACjC,MAAM,QAAQ,MAAM,EAAE,EAAE;CACxB,MAAM,aAAa,WAAW,KAAA;CAE9B,MAAM,EAAE,YAAY,aAAa,cAAc;CAG/C,MAAM,SADS,cAAc,EAAE,KAAK,SAAS,CAC9B,CAAA,CAAO,EAAE,KAAK,CAAC;CAE9B,OAAO,MAAM,KACX,qBAAC,OAAO,WAAR;EAAkB,aAAa,gBAAgB,UAAU,aAAa,mBAAmB;EAAzF,UAAA,CACG,aAIC,oBAAC,KAAD;GAAK,aAAU;GAAS,KAAK,OAAO;GAClC,UAAA,oBAAC,cAAD;IAAc,SAAQ;IAAQ,KAAK,UAAU;IAAI,MAAM;IAAO,MAAM;IAAY,UAAU;GAAiB,CAAA;EACxG,CAAA,IAEL,QAAQ,oBAAC,MAAD;GAAM,KAAK,OAAO;GAAW,MAAM;GAAU,YAAY;EAAI,CAAA,GAEvE,oBAAC,MAAD;GAAM,IAAG;GAAO,UAAS;GAAS,cAAa;GAAW,YAAW;GAAS,UAAS;GACpF,UAAA;EACG,CAAA,CACU;CAElB,CAAA,IAAA,oBAAC,OAAO,WAAR;EACE,aAAa,gBAAgB,UAAU,aAAa,mBAAmB;EACvE,SAAQ;EACR,UAAS;EACT,cAAa;EACb,YAAW;CACZ,CAAA;AAEL;AAEA,IAAM,eAAe,YAA+C,OAA0B,QAAQ;CACpG,MAAM,EACJ,UACA,cACA,iBACA,YACA,iBACA,YACA,WACA,OACA,oBACA,gBACA,eACA,aACA,eACA,mBACA,aACA,aACA,OAAO,MACP,OACA,cACA,OACA,GAAG,eACD;CAEJ,MAAM,aAAa,qBAAqB;EACtC;EACA,UAAU,SAAS,KAAK,SAAS;EACjC,iBAAiB,SAAS,CAAC,CAAC,KAAK;CACnC,CAAC;CAED,MAAM,EAAE,eAAe,6BAA6B,WAAW,mBAAmB;CAClF,MAAM,YAAY,UAAU,WAAW,CAAC,CAAC,WAAW;CAEpD,OACE,oBAAC,aAAD;EAAkB;EAAY;EAAO,GAAI;EACvC,UAAA,qBAAC,OAAO,MAAR;GACc;GAEZ,aAAa,EAAE,WAAW,MAAM;GAC1B;GACN,GAAI;GACJ,cAAc,eAAe,CAAC,YAAY,IAAI,KAAA;GAC9C,UAAU,UAAU;GACpB,eAAe,UAAU,WAAW,UAAU;GAC9C,SAAS;GACT,gBAAgB,WAAW,gBAAgB,OAAO,MAAM,EAAE;GAC1D,UAAU,UAAU;GAGpB,kBAAkB,EAAE,iBAAiB,WAAW,CAAC,EAAE,eAAe,EAAE,OAAO,UAAU,CAAC;GAKtF,OAAO,UAAU,KAAA,IAAY,KAAA,IAAY,QAAQ,CAAC,KAAK,IAAI,CAAC;GAnB9D,UAAA,CAqBE,qBAAC,OAAO,SAAR;IAAgB,WAAU;IAA1B,UAAA;KACE,oBAAC,OAAO,cAAR,CAAsB,CAAA;KACtB,oBAAC,OAAO,SAAR;MAAgB,GAAI;MAAc,iBAAe,UAAU,cAAc,KAAA;MACvE,UAAA,oBAAC,aAAD;OAA0B;OAAmB;OAAa;MAAQ,CAAA;KACpD,CAAA;KAChB,qBAAC,OAAO,gBAAR,EAAA,UAAA;MACG,UAAU,WACT,oBAAC,OAAO,WAAR,EAAA,UACE,oBAAC,uBAAD;OAAuB,MAAM,SAAS,OAAO,OAAO;OAAM,OAAM;MAAiB,CAAA,EACjE,CAAA;MAEnB,UAAU,aACT,oBAAC,OAAO,WAAR,EAAA,UACE,oBAAC,mBAAD,EAAmB,MAAM,SAAS,OAAO,OAAO,KAAO,CAAA,EACvC,CAAA;MAEpB,oBAAC,OAAO,WAAR;OAAkB,SAAA;OAChB,UAAA,oBAAC,oBAAD,CAAqB,CAAA;MACL,CAAA;KACG,EAAA,CAAA;IACT;GAChB,CAAA,GAAA,oBAAC,QAAD;IAAQ,UAAU,iBAAiB;IACjC,UAAA,oBAAC,OAAO,YAAR,EAAA,UACE,oBAAC,kBAAD;KACc;KACK;KACL;KACK;KACL;KACD;KACS;KACJ;KACG;KACN;KACP;KAEL;IACe,CAAA,EACD,CAAA;GACb,CAAA,CACG;;CACF,CAAA;AAEjB,CAAC;AAED,aAAa,cAAc;AAE3B,IAAA,uBAAe,kBAAkB,cAAc,EAAE,QAAQ,uBAAuB,CAAC"}
|
|
@@ -24,6 +24,8 @@ export type BitkitSelectMenuItemProps = {
|
|
|
24
24
|
* of `label`; omitting the prop renders no avatar and leaves the row's leading slot to
|
|
25
25
|
* `icon`. */
|
|
26
26
|
avatar?: string | null;
|
|
27
|
+
/** Replaces the initials when `avatar` is `null` or its image fails to load. Decorative (`aria-hidden`): `label` names the row. */
|
|
28
|
+
avatarFallback?: ReactNode;
|
|
27
29
|
helperText?: ReactNode;
|
|
28
30
|
/** A `BitkitBadge` after the label. Forced to `colorVariant="neutral"` on a disabled item. */
|
|
29
31
|
badge?: ReactElement<BitkitBadgeProps>;
|
|
@@ -60,7 +60,8 @@ var SelectMenuItem = ({ NS, avatarSize, item, iconSize, spinnerSize, styles }) =
|
|
|
60
60
|
variant: "image",
|
|
61
61
|
src: item.avatar ?? "",
|
|
62
62
|
name: item.label,
|
|
63
|
-
size: avatarSize
|
|
63
|
+
size: avatarSize,
|
|
64
|
+
fallback: item.avatarFallback
|
|
64
65
|
})
|
|
65
66
|
}),
|
|
66
67
|
/* @__PURE__ */ jsxs(Box, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BitkitSelectMenu.js","names":[],"sources":["../../../lib/components/BitkitSelectMenu/BitkitSelectMenu.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { type ListCollection } from '@chakra-ui/react/collection';\nimport { Combobox } from '@chakra-ui/react/combobox';\nimport { Select, type SelectContentProps } from '@chakra-ui/react/select';\nimport { Spinner } from '@chakra-ui/react/spinner';\nimport { type SystemStyleObject, useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { cloneElement, forwardRef, type ReactElement, type ReactNode } from 'react';\n\nimport { type BitkitIconComponent, IconCheck } from '../../icons';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\nimport { type BitkitBadgeProps } from '../BitkitBadge/BitkitBadge';\nimport { type BitkitSelectMenuActionChild } from './BitkitSelectMenuAction';\nimport { SelectMenuShell, selectSizeMap, type SelectSizes } from './SelectMenuShell';\n\nexport { type BitkitSelectMenuActionProps } from './BitkitSelectMenuAction';\n\nexport type BitkitSelectMenuSearchProps = {\n /** When provided, a search input is rendered above the menu items. `searchValue` is required alongside. */\n onSearchChange?: (searchText: string) => void;\n searchPlaceholder?: string;\n searchValue?: string;\n};\n\nexport type BitkitSelectMenuScrollProps = {\n /** Fires when the item list reaches its end. Position only: keep your own loading and end-of-list guards. */\n onScrolledToBottom?: () => void;\n};\n\nexport type BitkitSelectMenuItemProps = {\n value: string;\n label: string;\n group?: string;\n icon?: BitkitIconComponent;\n /** The item's avatar. A URL renders that image; `null` renders the avatar with the initials\n * of `label`; omitting the prop renders no avatar and leaves the row's leading slot to\n * `icon`. */\n avatar?: string | null;\n helperText?: ReactNode;\n /** A `BitkitBadge` after the label. Forced to `colorVariant=\"neutral\"` on a disabled item. */\n badge?: ReactElement<BitkitBadgeProps>;\n disabled?: boolean;\n loading?: boolean;\n};\n\nexport type BitkitSelectMenuEmptyStateProps = {\n emptyLabel?: string;\n emptyHelperText?: string;\n};\n\nexport type BitkitSelectMenuErrorStateProps = {\n errorLabel?: string;\n errorHelperText?: string;\n};\n\nexport type BitkitSelectMenuProps = {\n children?: BitkitSelectMenuActionChild;\n collection: ListCollection<BitkitSelectMenuItemProps>;\n /** Forwarded to the underlying Select/Combobox.Content. Kept for internal callers\n * (e.g. BitkitCalendar's in-grid selects that need to tweak max-height / width). The\n * public components (BitkitSelect, BitkitCombobox) do not expose this escape hatch. */\n contentProps?: SelectContentProps;\n isLoading?: boolean;\n size?: 'md' | 'lg';\n variant?: 'select' | 'combobox';\n} & BitkitSelectMenuSearchProps &\n BitkitSelectMenuScrollProps &\n BitkitSelectMenuEmptyStateProps &\n BitkitSelectMenuErrorStateProps;\n\nconst BitkitSelectMenu = forwardRef<HTMLDivElement, BitkitSelectMenuProps>((props, ref) => {\n const { children, collection, variant = 'select', size, ...shellProps } = props;\n const NS = variant === 'combobox' ? Combobox : Select;\n const recipe = useSlotRecipe({ key: 'select' });\n const styles = recipe({ size });\n const { avatarSize, iconSize, spinnerSize } = selectSizeMap[size ?? 'lg'];\n\n return (\n <SelectMenuShell\n NS={NS}\n collection={collection}\n contentRef={ref}\n iconSize={iconSize}\n renderItem={(item) => (\n <SelectMenuItem\n key={item.value}\n NS={NS}\n avatarSize={avatarSize}\n item={item}\n iconSize={iconSize}\n spinnerSize={spinnerSize}\n styles={styles}\n />\n )}\n spinnerSize={spinnerSize}\n styles={styles}\n {...shellProps}\n >\n {children}\n </SelectMenuShell>\n );\n});\n\nBitkitSelectMenu.displayName = 'BitkitSelectMenu';\n\ntype SelectMenuItemRenderProps = {\n NS: typeof Select | typeof Combobox;\n avatarSize: SelectSizes['avatarSize'];\n item: BitkitSelectMenuItemProps;\n iconSize: SelectSizes['iconSize'];\n spinnerSize: SelectSizes['spinnerSize'];\n styles: Record<string, SystemStyleObject>;\n};\n\nconst SelectMenuItem = ({ NS, avatarSize, item, iconSize, spinnerSize, styles }: SelectMenuItemRenderProps) => {\n const Icon = item.icon;\n const showAvatar = item.avatar !== undefined;\n\n if (item.loading) {\n // Rendered as a plain Box, not NS.Item — Zag's state machine won't track it as\n // an option, so keyboard nav skips it and it can't be selected.\n return (\n <Box css={styles.item}>\n <Spinner variant=\"purple\" size={spinnerSize} css={styles.itemLoading} />\n <Text css={styles.itemLoadingLabel}>Loading...</Text>\n </Box>\n );\n }\n\n return (\n <NS.Item css={styles.item} item={item}>\n {showAvatar && (\n <Box data-slot=\"avatar\" css={styles.avatar}>\n <BitkitAvatar
|
|
1
|
+
{"version":3,"file":"BitkitSelectMenu.js","names":[],"sources":["../../../lib/components/BitkitSelectMenu/BitkitSelectMenu.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { type ListCollection } from '@chakra-ui/react/collection';\nimport { Combobox } from '@chakra-ui/react/combobox';\nimport { Select, type SelectContentProps } from '@chakra-ui/react/select';\nimport { Spinner } from '@chakra-ui/react/spinner';\nimport { type SystemStyleObject, useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { cloneElement, forwardRef, type ReactElement, type ReactNode } from 'react';\n\nimport { type BitkitIconComponent, IconCheck } from '../../icons';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\nimport { type BitkitBadgeProps } from '../BitkitBadge/BitkitBadge';\nimport { type BitkitSelectMenuActionChild } from './BitkitSelectMenuAction';\nimport { SelectMenuShell, selectSizeMap, type SelectSizes } from './SelectMenuShell';\n\nexport { type BitkitSelectMenuActionProps } from './BitkitSelectMenuAction';\n\nexport type BitkitSelectMenuSearchProps = {\n /** When provided, a search input is rendered above the menu items. `searchValue` is required alongside. */\n onSearchChange?: (searchText: string) => void;\n searchPlaceholder?: string;\n searchValue?: string;\n};\n\nexport type BitkitSelectMenuScrollProps = {\n /** Fires when the item list reaches its end. Position only: keep your own loading and end-of-list guards. */\n onScrolledToBottom?: () => void;\n};\n\nexport type BitkitSelectMenuItemProps = {\n value: string;\n label: string;\n group?: string;\n icon?: BitkitIconComponent;\n /** The item's avatar. A URL renders that image; `null` renders the avatar with the initials\n * of `label`; omitting the prop renders no avatar and leaves the row's leading slot to\n * `icon`. */\n avatar?: string | null;\n /** Replaces the initials when `avatar` is `null` or its image fails to load. Decorative (`aria-hidden`): `label` names the row. */\n avatarFallback?: ReactNode;\n helperText?: ReactNode;\n /** A `BitkitBadge` after the label. Forced to `colorVariant=\"neutral\"` on a disabled item. */\n badge?: ReactElement<BitkitBadgeProps>;\n disabled?: boolean;\n loading?: boolean;\n};\n\nexport type BitkitSelectMenuEmptyStateProps = {\n emptyLabel?: string;\n emptyHelperText?: string;\n};\n\nexport type BitkitSelectMenuErrorStateProps = {\n errorLabel?: string;\n errorHelperText?: string;\n};\n\nexport type BitkitSelectMenuProps = {\n children?: BitkitSelectMenuActionChild;\n collection: ListCollection<BitkitSelectMenuItemProps>;\n /** Forwarded to the underlying Select/Combobox.Content. Kept for internal callers\n * (e.g. BitkitCalendar's in-grid selects that need to tweak max-height / width). The\n * public components (BitkitSelect, BitkitCombobox) do not expose this escape hatch. */\n contentProps?: SelectContentProps;\n isLoading?: boolean;\n size?: 'md' | 'lg';\n variant?: 'select' | 'combobox';\n} & BitkitSelectMenuSearchProps &\n BitkitSelectMenuScrollProps &\n BitkitSelectMenuEmptyStateProps &\n BitkitSelectMenuErrorStateProps;\n\nconst BitkitSelectMenu = forwardRef<HTMLDivElement, BitkitSelectMenuProps>((props, ref) => {\n const { children, collection, variant = 'select', size, ...shellProps } = props;\n const NS = variant === 'combobox' ? Combobox : Select;\n const recipe = useSlotRecipe({ key: 'select' });\n const styles = recipe({ size });\n const { avatarSize, iconSize, spinnerSize } = selectSizeMap[size ?? 'lg'];\n\n return (\n <SelectMenuShell\n NS={NS}\n collection={collection}\n contentRef={ref}\n iconSize={iconSize}\n renderItem={(item) => (\n <SelectMenuItem\n key={item.value}\n NS={NS}\n avatarSize={avatarSize}\n item={item}\n iconSize={iconSize}\n spinnerSize={spinnerSize}\n styles={styles}\n />\n )}\n spinnerSize={spinnerSize}\n styles={styles}\n {...shellProps}\n >\n {children}\n </SelectMenuShell>\n );\n});\n\nBitkitSelectMenu.displayName = 'BitkitSelectMenu';\n\ntype SelectMenuItemRenderProps = {\n NS: typeof Select | typeof Combobox;\n avatarSize: SelectSizes['avatarSize'];\n item: BitkitSelectMenuItemProps;\n iconSize: SelectSizes['iconSize'];\n spinnerSize: SelectSizes['spinnerSize'];\n styles: Record<string, SystemStyleObject>;\n};\n\nconst SelectMenuItem = ({ NS, avatarSize, item, iconSize, spinnerSize, styles }: SelectMenuItemRenderProps) => {\n const Icon = item.icon;\n const showAvatar = item.avatar !== undefined;\n\n if (item.loading) {\n // Rendered as a plain Box, not NS.Item — Zag's state machine won't track it as\n // an option, so keyboard nav skips it and it can't be selected.\n return (\n <Box css={styles.item}>\n <Spinner variant=\"purple\" size={spinnerSize} css={styles.itemLoading} />\n <Text css={styles.itemLoadingLabel}>Loading...</Text>\n </Box>\n );\n }\n\n return (\n <NS.Item css={styles.item} item={item}>\n {showAvatar && (\n <Box data-slot=\"avatar\" css={styles.avatar}>\n <BitkitAvatar\n variant=\"image\"\n src={item.avatar ?? ''}\n name={item.label}\n size={avatarSize}\n fallback={item.avatarFallback}\n />\n </Box>\n )}\n <Box css={styles.itemContent}>\n <Box display=\"flex\" alignItems=\"center\" gap=\"8\">\n {Icon && !showAvatar && <Icon css={styles.itemIcon} size={iconSize} />}\n <Text css={styles.itemLabel}>{item.label}</Text>\n </Box>\n {item.helperText && <Text css={styles.itemHelperText}>{item.helperText}</Text>}\n </Box>\n {item.badge && (\n <Box css={styles.itemBadge}>\n {item.disabled ? cloneElement(item.badge, { colorVariant: 'neutral' }) : item.badge}\n </Box>\n )}\n <NS.ItemIndicator asChild>\n <IconCheck size={iconSize} css={styles.itemIndicator} />\n </NS.ItemIndicator>\n </NS.Item>\n );\n};\n\nexport default BitkitSelectMenu;\n"],"mappings":";;;;;;;;;;;;AAwEA,IAAM,mBAAmB,YAAmD,OAAO,QAAQ;CACzF,MAAM,EAAE,UAAU,YAAY,UAAU,UAAU,MAAM,GAAG,eAAe;CAC1E,MAAM,KAAK,YAAY,aAAa,WAAW;CAE/C,MAAM,SADS,cAAc,EAAE,KAAK,SAAS,CAC9B,CAAA,CAAO,EAAE,KAAK,CAAC;CAC9B,MAAM,EAAE,YAAY,UAAU,gBAAgB,cAAc,QAAQ;CAEpE,OACE,oBAAC,iBAAD;EACM;EACQ;EACZ,YAAY;EACF;EACV,aAAa,SACX,oBAAC,gBAAD;GAEM;GACQ;GACN;GACI;GACG;GACL;EACT,GAPM,KAAK,KAOX;EAEU;EACL;EACR,GAAI;EAEH;CACc,CAAA;AAErB,CAAC;AAED,iBAAiB,cAAc;AAW/B,IAAM,kBAAkB,EAAE,IAAI,YAAY,MAAM,UAAU,aAAa,aAAwC;CAC7G,MAAM,OAAO,KAAK;CAClB,MAAM,aAAa,KAAK,WAAW,KAAA;CAEnC,IAAI,KAAK,SAGP,OACE,qBAAC,KAAD;EAAK,KAAK,OAAO;EAAjB,UAAA,CACE,oBAAC,SAAD;GAAS,SAAQ;GAAS,MAAM;GAAa,KAAK,OAAO;EAAc,CAAA,GACvE,oBAAC,MAAD;GAAM,KAAK,OAAO;GAAkB,UAAA;EAAgB,CAAA,CACjD;;CAIT,OACE,qBAAC,GAAG,MAAJ;EAAS,KAAK,OAAO;EAAY;EAAjC,UAAA;GACG,cACC,oBAAC,KAAD;IAAK,aAAU;IAAS,KAAK,OAAO;IAClC,UAAA,oBAAC,cAAD;KACE,SAAQ;KACR,KAAK,KAAK,UAAU;KACpB,MAAM,KAAK;KACX,MAAM;KACN,UAAU,KAAK;IAChB,CAAA;GACE,CAAA;GAEP,qBAAC,KAAD;IAAK,KAAK,OAAO;IAAjB,UAAA,CACE,qBAAC,KAAD;KAAK,SAAQ;KAAO,YAAW;KAAS,KAAI;KAA5C,UAAA,CACG,QAAQ,CAAC,cAAc,oBAAC,MAAD;MAAM,KAAK,OAAO;MAAU,MAAM;KAAW,CAAA,GACrE,oBAAC,MAAD;MAAM,KAAK,OAAO;MAAY,UAAA,KAAK;KAAY,CAAA,CAC5C;IACJ,CAAA,GAAA,KAAK,cAAc,oBAAC,MAAD;KAAM,KAAK,OAAO;KAAiB,UAAA,KAAK;IAAiB,CAAA,CAC1E;;GACJ,KAAK,SACJ,oBAAC,KAAD;IAAK,KAAK,OAAO;IACd,UAAA,KAAK,WAAW,aAAa,KAAK,OAAO,EAAE,cAAc,UAAU,CAAC,IAAI,KAAK;GAC3E,CAAA;GAEP,oBAAC,GAAG,eAAJ;IAAkB,SAAA;IAChB,UAAA,oBAAC,WAAD;KAAW,MAAM;KAAU,KAAK,OAAO;IAAgB,CAAA;GACvC,CAAA;EACX;;AAEb"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { HTMLChakraProps } from '@chakra-ui/react/styled-system';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
export interface BitkitUIHeaderNavButtonProps extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'> {
|
|
4
|
+
/** Replaces the avatar's initials when the workspace has no logo, or its logo fails to load. Decorative (`aria-hidden`): the button's `label` names it. */
|
|
5
|
+
fallback?: ReactNode;
|
|
3
6
|
/** The accessible name. */
|
|
4
7
|
label?: string;
|
|
5
8
|
/** The current workspace. Shown as the avatar's initials when it has no logo. */
|
|
@@ -16,10 +16,11 @@ import { Box } from "@chakra-ui/react/box";
|
|
|
16
16
|
* It shows the current workspace, so switching workspaces is one tap away from anywhere.
|
|
17
17
|
*/
|
|
18
18
|
var UIHeaderNavButton = forwardRef((props, ref) => {
|
|
19
|
-
const { label = "Open navigation", name, src, ...rest } = props;
|
|
19
|
+
const { fallback, label = "Open navigation", name, src, ...rest } = props;
|
|
20
20
|
const { styles } = useUIHeaderContext();
|
|
21
|
-
const avatarProps = src ? {
|
|
22
|
-
|
|
21
|
+
const avatarProps = src || fallback ? {
|
|
22
|
+
fallback,
|
|
23
|
+
src: src ?? "",
|
|
23
24
|
variant: "image"
|
|
24
25
|
} : { variant: "letters" };
|
|
25
26
|
return /* @__PURE__ */ jsxs(UIHeaderControlBase, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UIHeaderNavButton.js","names":[],"sources":["../../../lib/components/BitkitUIHeader/UIHeaderNavButton.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { type HTMLChakraProps } from '@chakra-ui/react/styled-system';\nimport { forwardRef } from 'react';\n\nimport { IconMenuHamburger } from '../../icons';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\nimport { useUIHeaderContext } from './UIHeaderContext';\nimport { UIHeaderControlBase } from './UIHeaderControl';\n\nexport interface BitkitUIHeaderNavButtonProps extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'> {\n /** The accessible name. */\n label?: string;\n /** The current workspace. Shown as the avatar's initials when it has no logo. */\n name: string;\n /** The workspace's logo. Without one the avatar falls back to its initials. */\n src?: string;\n}\n\n/**\n * Opens `BitkitUISideNav` on mobile, where the navigation is a drawer rather than a rail. It sits\n * in the header's `leading` slot, which is hidden from the `tablet` breakpoint up.\n *\n * The two components do not know about each other: this button's `onClick` sets the navigation's\n * `open`, and the navigation asks to close through its own `onOpenChange`.\n *\n * It shows the current workspace, so switching workspaces is one tap away from anywhere.\n */\nconst UIHeaderNavButton = forwardRef<HTMLButtonElement, BitkitUIHeaderNavButtonProps>((props, ref) => {\n const { label = 'Open navigation', name, src, ...rest } = props;\n\n const { styles } = useUIHeaderContext();\n\n const avatarProps
|
|
1
|
+
{"version":3,"file":"UIHeaderNavButton.js","names":[],"sources":["../../../lib/components/BitkitUIHeader/UIHeaderNavButton.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { type HTMLChakraProps } from '@chakra-ui/react/styled-system';\nimport { forwardRef, type ReactNode } from 'react';\n\nimport { IconMenuHamburger } from '../../icons';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\nimport { useUIHeaderContext } from './UIHeaderContext';\nimport { UIHeaderControlBase } from './UIHeaderControl';\n\nexport interface BitkitUIHeaderNavButtonProps extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled'> {\n /** Replaces the avatar's initials when the workspace has no logo, or its logo fails to load. Decorative (`aria-hidden`): the button's `label` names it. */\n fallback?: ReactNode;\n /** The accessible name. */\n label?: string;\n /** The current workspace. Shown as the avatar's initials when it has no logo. */\n name: string;\n /** The workspace's logo. Without one the avatar falls back to its initials. */\n src?: string;\n}\n\n/**\n * Opens `BitkitUISideNav` on mobile, where the navigation is a drawer rather than a rail. It sits\n * in the header's `leading` slot, which is hidden from the `tablet` breakpoint up.\n *\n * The two components do not know about each other: this button's `onClick` sets the navigation's\n * `open`, and the navigation asks to close through its own `onOpenChange`.\n *\n * It shows the current workspace, so switching workspaces is one tap away from anywhere.\n */\nconst UIHeaderNavButton = forwardRef<HTMLButtonElement, BitkitUIHeaderNavButtonProps>((props, ref) => {\n const { fallback, label = 'Open navigation', name, src, ...rest } = props;\n\n const { styles } = useUIHeaderContext();\n\n const avatarProps =\n src || fallback ? ({ fallback, src: src ?? '', variant: 'image' } as const) : ({ variant: 'letters' } as const);\n\n return (\n <UIHeaderControlBase ref={ref} footprint=\"navButton\" label={label} {...rest}>\n <BitkitAvatar name={name} {...avatarProps} />\n <Box css={styles.navButtonBadge}>\n <IconMenuHamburger css={styles.navButtonIcon} size=\"16\" />\n </Box>\n </UIHeaderControlBase>\n );\n});\n\nUIHeaderNavButton.displayName = 'BitkitUIHeader.NavButton';\n\nexport default UIHeaderNavButton;\n"],"mappings":";;;;;;;;;;;;;;;;;AA6BA,IAAM,oBAAoB,YAA6D,OAAO,QAAQ;CACpG,MAAM,EAAE,UAAU,QAAQ,mBAAmB,MAAM,KAAK,GAAG,SAAS;CAEpE,MAAM,EAAE,WAAW,mBAAmB;CAEtC,MAAM,cACJ,OAAO,WAAY;EAAE;EAAU,KAAK,OAAO;EAAI,SAAS;CAAQ,IAAe,EAAE,SAAS,UAAU;CAEtG,OACE,qBAAC,qBAAD;EAA0B;EAAK,WAAU;EAAmB;EAAO,GAAI;EAAvE,UAAA,CACE,oBAAC,cAAD;GAAoB;GAAM,GAAI;EAAc,CAAA,GAC5C,oBAAC,KAAD;GAAK,KAAK,OAAO;GACf,UAAA,oBAAC,mBAAD;IAAmB,KAAK,OAAO;IAAe,MAAK;GAAM,CAAA;EACtD,CAAA,CACc;;AAEzB,CAAC;AAED,kBAAkB,cAAc"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Select, SelectTriggerProps } from '@chakra-ui/react/select';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
2
3
|
import { BitkitSelectMenuEmptyStateProps, BitkitSelectMenuErrorStateProps, BitkitSelectMenuItemProps, BitkitSelectMenuScrollProps, BitkitSelectMenuSearchProps } from '../BitkitSelectMenu/BitkitSelectMenu';
|
|
3
4
|
import { BitkitSelectMenuActionChild } from '../BitkitSelectMenu/BitkitSelectMenuAction';
|
|
4
5
|
export type BitkitUISideNavWorkspaceProps = Pick<BitkitSelectMenuItemProps, 'label' | 'value'> & {
|
|
@@ -7,6 +8,8 @@ export type BitkitUISideNavWorkspaceProps = Pick<BitkitSelectMenuItemProps, 'lab
|
|
|
7
8
|
* a workspace always has one, unlike a plain menu item.
|
|
8
9
|
*/
|
|
9
10
|
avatar?: string;
|
|
11
|
+
/** Replaces the initials when the workspace has no logo, or its logo fails to load. Decorative (`aria-hidden`): `label` names the workspace. */
|
|
12
|
+
avatarFallback?: ReactNode;
|
|
10
13
|
};
|
|
11
14
|
/**
|
|
12
15
|
* The list length at which the design adds the search input. Below it the menu is short enough
|
|
@@ -77,6 +77,7 @@ var UISideNavWorkspaceSelector = forwardRef((props, ref) => {
|
|
|
77
77
|
/* @__PURE__ */ jsx(BitkitAvatar, {
|
|
78
78
|
borderColor: "border/minimal",
|
|
79
79
|
borderWidth: "1",
|
|
80
|
+
fallback: selected?.avatarFallback,
|
|
80
81
|
name: selected?.label ?? "",
|
|
81
82
|
size: "40",
|
|
82
83
|
src: selected?.avatar ?? "",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UISideNavWorkspaceSelector.js","names":[],"sources":["../../../lib/components/BitkitUISideNav/UISideNavWorkspaceSelector.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { createListCollection } from '@chakra-ui/react/collection';\nimport { useControllableState } from '@chakra-ui/react/hooks';\nimport { useFilter } from '@chakra-ui/react/locale';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Select, type SelectTriggerProps } from '@chakra-ui/react/select';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, useId, useMemo, useRef, useState } from 'react';\n\nimport { IconChevronDown } from '../../icons';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\nimport BitkitSelectMenu, {\n type BitkitSelectMenuEmptyStateProps,\n type BitkitSelectMenuErrorStateProps,\n type BitkitSelectMenuItemProps,\n type BitkitSelectMenuScrollProps,\n type BitkitSelectMenuSearchProps,\n} from '../BitkitSelectMenu/BitkitSelectMenu';\nimport { type BitkitSelectMenuActionChild } from '../BitkitSelectMenu/BitkitSelectMenuAction';\nimport { useUISideNavContext } from './UISideNavContext';\n\nexport type BitkitUISideNavWorkspaceProps = Pick<BitkitSelectMenuItemProps, 'label' | 'value'> & {\n /**\n * The workspace's logo. Leave it off and the avatar falls back to the initials of `label` —\n * a workspace always has one, unlike a plain menu item.\n */\n avatar?: string;\n};\n\n/**\n * The list length at which the design adds the search input. Below it the menu is short enough\n * to read at a glance and a search field would only be in the way. Exported for the stories,\n * which label each list by the side of this it falls on — not part of the package's surface.\n */\nexport const searchableFrom = 6;\n\nexport type BitkitUISideNavWorkspaceSelectorProps = Omit<SelectTriggerProps, 'children' | 'onChange'> & {\n /**\n * A single `BitkitSelectMenuAction` shown under the list, typically \"Create workspace\". Its\n * presence is the toggle — there is no boolean for it.\n */\n children?: BitkitSelectMenuActionChild;\n isLoading?: boolean;\n /** The small uppercase caption above the workspace name. */\n label?: string;\n /**\n * Fires when the menu opens and when it closes — where a list loaded on demand belongs. The\n * menu also opens from the keyboard, which fires no click on the trigger.\n */\n onOpenChange?: (open: boolean) => void;\n onValueChange?: (value: string) => void;\n /** The selected workspace's `value`. Leave it off to let the selector track the choice itself. */\n value?: string;\n workspaces: Array<BitkitUISideNavWorkspaceProps>;\n // The copy is the design's, not the consumer's, so the placeholder is not on the way through.\n} & Omit<BitkitSelectMenuSearchProps, 'searchPlaceholder'> &\n BitkitSelectMenuScrollProps &\n BitkitSelectMenuEmptyStateProps &\n BitkitSelectMenuErrorStateProps;\n\nconst UISideNavWorkspaceSelector = forwardRef<HTMLButtonElement, BitkitUISideNavWorkspaceSelectorProps>(\n (props, ref) => {\n const {\n children,\n css,\n emptyHelperText,\n emptyLabel,\n errorHelperText,\n errorLabel,\n isLoading,\n label = 'Workspace',\n onOpenChange,\n onScrolledToBottom,\n onSearchChange,\n onValueChange,\n searchValue,\n value,\n workspaces,\n ...rest\n } = props;\n\n const { isMobile, menuContainerRef, setMenuOpen, styles } = useUISideNavContext();\n const id = useId();\n const labelId = `${id}-label`;\n const valueId = `${id}-value`;\n const { contains } = useFilter({ sensitivity: 'base' });\n\n const [ownQuery, setOwnQuery] = useState('');\n const [currentValue, setCurrentValue] = useControllableState<string | undefined>({\n defaultValue: undefined,\n value,\n });\n\n // A consumer that passes `onSearchChange` is searching somewhere we cannot see — a server, a\n // paged list — so `workspaces` is already the result and its length says nothing about how\n // many there are. They keep the input and the filtering; otherwise both are ours.\n const isSearchDelegated = onSearchChange !== undefined;\n const query = isSearchDelegated ? searchValue : ownQuery;\n const hasSearch = isSearchDelegated || workspaces.length >= searchableFrom;\n\n const collection = useMemo(() => {\n const matches = ownQuery ? workspaces.filter((workspace) => contains(workspace.label, ownQuery)) : workspaces;\n\n // `null` rather than nothing for a workspace without a logo: that is what tells the menu to\n // draw the initials, where an absent `avatar` would leave the row with no avatar at all.\n const items: Array<BitkitSelectMenuItemProps> = matches.map((workspace) => ({\n ...workspace,\n avatar: workspace.avatar ?? null,\n }));\n\n return createListCollection({ items });\n }, [contains, ownQuery, workspaces]);\n\n // `workspaces` is the search result while the search is delegated, so the selected workspace\n // can drop out of it mid-query. The cell keeps naming the workspace you are actually in.\n const lastSelected = useRef<BitkitUISideNavWorkspaceProps>(undefined);\n const matched = workspaces.find((workspace) => workspace.value === currentValue);\n if (matched) lastSelected.current = matched;\n const selected = matched ?? (lastSelected.current?.value === currentValue ? lastSelected.current : undefined);\n\n return (\n <Select.Root\n collection={collection}\n css={styles.workspaceRoot}\n ids={{ label: labelId }}\n onOpenChange={(details) => {\n setMenuOpen(details.open);\n if (!details.open) setOwnQuery('');\n onOpenChange?.(details.open);\n }}\n onValueChange={(details) => {\n setCurrentValue(details.value[0]);\n onValueChange?.(details.value[0]);\n }}\n // Tucked into the rail rather than hung off it: inset from the rail's edge and lapping\n // over the workspace cell, so the menu reads as the cell unfolding.\n positioning={\n isMobile\n ? { gutter: 0, offset: { crossAxis: 16 }, overflowPadding: 16 }\n : { gutter: -8, offset: { crossAxis: 16 }, placement: 'bottom-start' }\n }\n size=\"lg\"\n value={currentValue === undefined ? [] : [currentValue]}\n >\n <Select.Control css={styles.workspaceControl}>\n <Select.HiddenSelect />\n <Select.Trigger\n ref={ref}\n unstyled\n aria-labelledby={`${labelId} ${valueId}`}\n {...rest}\n css={[styles.workspace, css]}\n >\n <BitkitAvatar\n borderColor=\"border/minimal\"\n borderWidth=\"1\"\n name={selected?.label ?? ''}\n size=\"40\"\n src={selected?.avatar ?? ''}\n variant=\"image\"\n />\n <Box css={styles.workspaceTextBlock}>\n <Text css={styles.workspaceLabel} id={labelId}>\n {label}\n </Text>\n <Text css={styles.workspaceValue} id={valueId}>\n {selected?.label}\n </Text>\n </Box>\n <Select.Indicator css={styles.workspaceChevron}>\n <IconChevronDown />\n </Select.Indicator>\n </Select.Trigger>\n </Select.Control>\n {/*\n In the drawer the menu goes to the panel rather than the document: the panel scrolls\n under its own header, so a menu left in the flow would travel with the rows and be\n clipped by them, and anywhere outside the panel is outside the dialog's focus trap.\n */}\n <Portal container={isMobile ? menuContainerRef : undefined}>\n <Select.Positioner>\n <BitkitSelectMenu\n collection={collection}\n contentProps={{ css: styles.workspaceMenu }}\n emptyHelperText={emptyHelperText}\n emptyLabel={emptyLabel}\n errorHelperText={errorHelperText}\n errorLabel={errorLabel}\n isLoading={isLoading}\n onScrolledToBottom={onScrolledToBottom}\n onSearchChange={hasSearch ? (onSearchChange ?? setOwnQuery) : undefined}\n searchPlaceholder=\"Search your workspaces\"\n searchValue={query}\n size=\"lg\"\n >\n {children}\n </BitkitSelectMenu>\n </Select.Positioner>\n </Portal>\n </Select.Root>\n );\n },\n);\n\nUISideNavWorkspaceSelector.displayName = 'BitkitUISideNav.WorkspaceSelector';\n\nexport default UISideNavWorkspaceSelector;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"UISideNavWorkspaceSelector.js","names":[],"sources":["../../../lib/components/BitkitUISideNav/UISideNavWorkspaceSelector.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { createListCollection } from '@chakra-ui/react/collection';\nimport { useControllableState } from '@chakra-ui/react/hooks';\nimport { useFilter } from '@chakra-ui/react/locale';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Select, type SelectTriggerProps } from '@chakra-ui/react/select';\nimport { Text } from '@chakra-ui/react/text';\nimport { forwardRef, type ReactNode, useId, useMemo, useRef, useState } from 'react';\n\nimport { IconChevronDown } from '../../icons';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\nimport BitkitSelectMenu, {\n type BitkitSelectMenuEmptyStateProps,\n type BitkitSelectMenuErrorStateProps,\n type BitkitSelectMenuItemProps,\n type BitkitSelectMenuScrollProps,\n type BitkitSelectMenuSearchProps,\n} from '../BitkitSelectMenu/BitkitSelectMenu';\nimport { type BitkitSelectMenuActionChild } from '../BitkitSelectMenu/BitkitSelectMenuAction';\nimport { useUISideNavContext } from './UISideNavContext';\n\nexport type BitkitUISideNavWorkspaceProps = Pick<BitkitSelectMenuItemProps, 'label' | 'value'> & {\n /**\n * The workspace's logo. Leave it off and the avatar falls back to the initials of `label` —\n * a workspace always has one, unlike a plain menu item.\n */\n avatar?: string;\n /** Replaces the initials when the workspace has no logo, or its logo fails to load. Decorative (`aria-hidden`): `label` names the workspace. */\n avatarFallback?: ReactNode;\n};\n\n/**\n * The list length at which the design adds the search input. Below it the menu is short enough\n * to read at a glance and a search field would only be in the way. Exported for the stories,\n * which label each list by the side of this it falls on — not part of the package's surface.\n */\nexport const searchableFrom = 6;\n\nexport type BitkitUISideNavWorkspaceSelectorProps = Omit<SelectTriggerProps, 'children' | 'onChange'> & {\n /**\n * A single `BitkitSelectMenuAction` shown under the list, typically \"Create workspace\". Its\n * presence is the toggle — there is no boolean for it.\n */\n children?: BitkitSelectMenuActionChild;\n isLoading?: boolean;\n /** The small uppercase caption above the workspace name. */\n label?: string;\n /**\n * Fires when the menu opens and when it closes — where a list loaded on demand belongs. The\n * menu also opens from the keyboard, which fires no click on the trigger.\n */\n onOpenChange?: (open: boolean) => void;\n onValueChange?: (value: string) => void;\n /** The selected workspace's `value`. Leave it off to let the selector track the choice itself. */\n value?: string;\n workspaces: Array<BitkitUISideNavWorkspaceProps>;\n // The copy is the design's, not the consumer's, so the placeholder is not on the way through.\n} & Omit<BitkitSelectMenuSearchProps, 'searchPlaceholder'> &\n BitkitSelectMenuScrollProps &\n BitkitSelectMenuEmptyStateProps &\n BitkitSelectMenuErrorStateProps;\n\nconst UISideNavWorkspaceSelector = forwardRef<HTMLButtonElement, BitkitUISideNavWorkspaceSelectorProps>(\n (props, ref) => {\n const {\n children,\n css,\n emptyHelperText,\n emptyLabel,\n errorHelperText,\n errorLabel,\n isLoading,\n label = 'Workspace',\n onOpenChange,\n onScrolledToBottom,\n onSearchChange,\n onValueChange,\n searchValue,\n value,\n workspaces,\n ...rest\n } = props;\n\n const { isMobile, menuContainerRef, setMenuOpen, styles } = useUISideNavContext();\n const id = useId();\n const labelId = `${id}-label`;\n const valueId = `${id}-value`;\n const { contains } = useFilter({ sensitivity: 'base' });\n\n const [ownQuery, setOwnQuery] = useState('');\n const [currentValue, setCurrentValue] = useControllableState<string | undefined>({\n defaultValue: undefined,\n value,\n });\n\n // A consumer that passes `onSearchChange` is searching somewhere we cannot see — a server, a\n // paged list — so `workspaces` is already the result and its length says nothing about how\n // many there are. They keep the input and the filtering; otherwise both are ours.\n const isSearchDelegated = onSearchChange !== undefined;\n const query = isSearchDelegated ? searchValue : ownQuery;\n const hasSearch = isSearchDelegated || workspaces.length >= searchableFrom;\n\n const collection = useMemo(() => {\n const matches = ownQuery ? workspaces.filter((workspace) => contains(workspace.label, ownQuery)) : workspaces;\n\n // `null` rather than nothing for a workspace without a logo: that is what tells the menu to\n // draw the initials, where an absent `avatar` would leave the row with no avatar at all.\n const items: Array<BitkitSelectMenuItemProps> = matches.map((workspace) => ({\n ...workspace,\n avatar: workspace.avatar ?? null,\n }));\n\n return createListCollection({ items });\n }, [contains, ownQuery, workspaces]);\n\n // `workspaces` is the search result while the search is delegated, so the selected workspace\n // can drop out of it mid-query. The cell keeps naming the workspace you are actually in.\n const lastSelected = useRef<BitkitUISideNavWorkspaceProps>(undefined);\n const matched = workspaces.find((workspace) => workspace.value === currentValue);\n if (matched) lastSelected.current = matched;\n const selected = matched ?? (lastSelected.current?.value === currentValue ? lastSelected.current : undefined);\n\n return (\n <Select.Root\n collection={collection}\n css={styles.workspaceRoot}\n ids={{ label: labelId }}\n onOpenChange={(details) => {\n setMenuOpen(details.open);\n if (!details.open) setOwnQuery('');\n onOpenChange?.(details.open);\n }}\n onValueChange={(details) => {\n setCurrentValue(details.value[0]);\n onValueChange?.(details.value[0]);\n }}\n // Tucked into the rail rather than hung off it: inset from the rail's edge and lapping\n // over the workspace cell, so the menu reads as the cell unfolding.\n positioning={\n isMobile\n ? { gutter: 0, offset: { crossAxis: 16 }, overflowPadding: 16 }\n : { gutter: -8, offset: { crossAxis: 16 }, placement: 'bottom-start' }\n }\n size=\"lg\"\n value={currentValue === undefined ? [] : [currentValue]}\n >\n <Select.Control css={styles.workspaceControl}>\n <Select.HiddenSelect />\n <Select.Trigger\n ref={ref}\n unstyled\n aria-labelledby={`${labelId} ${valueId}`}\n {...rest}\n css={[styles.workspace, css]}\n >\n <BitkitAvatar\n borderColor=\"border/minimal\"\n borderWidth=\"1\"\n fallback={selected?.avatarFallback}\n name={selected?.label ?? ''}\n size=\"40\"\n src={selected?.avatar ?? ''}\n variant=\"image\"\n />\n <Box css={styles.workspaceTextBlock}>\n <Text css={styles.workspaceLabel} id={labelId}>\n {label}\n </Text>\n <Text css={styles.workspaceValue} id={valueId}>\n {selected?.label}\n </Text>\n </Box>\n <Select.Indicator css={styles.workspaceChevron}>\n <IconChevronDown />\n </Select.Indicator>\n </Select.Trigger>\n </Select.Control>\n {/*\n In the drawer the menu goes to the panel rather than the document: the panel scrolls\n under its own header, so a menu left in the flow would travel with the rows and be\n clipped by them, and anywhere outside the panel is outside the dialog's focus trap.\n */}\n <Portal container={isMobile ? menuContainerRef : undefined}>\n <Select.Positioner>\n <BitkitSelectMenu\n collection={collection}\n contentProps={{ css: styles.workspaceMenu }}\n emptyHelperText={emptyHelperText}\n emptyLabel={emptyLabel}\n errorHelperText={errorHelperText}\n errorLabel={errorLabel}\n isLoading={isLoading}\n onScrolledToBottom={onScrolledToBottom}\n onSearchChange={hasSearch ? (onSearchChange ?? setOwnQuery) : undefined}\n searchPlaceholder=\"Search your workspaces\"\n searchValue={query}\n size=\"lg\"\n >\n {children}\n </BitkitSelectMenu>\n </Select.Positioner>\n </Portal>\n </Select.Root>\n );\n },\n);\n\nUISideNavWorkspaceSelector.displayName = 'BitkitUISideNav.WorkspaceSelector';\n\nexport default UISideNavWorkspaceSelector;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Avatar.recipe.js","names":[],"sources":["../../../lib/theme/slot-recipes/Avatar.recipe.ts"],"sourcesContent":["import { avatarAnatomy } from '@chakra-ui/react/anatomy';\nimport { defineSlotRecipe } from '@chakra-ui/react/styled-system';\n\nconst avatarSlotRecipe = defineSlotRecipe({\n slots: [...avatarAnatomy.keys(), 'icon', 'badge', 'badgeContainer'],\n className: 'avatar',\n base: {\n root: {\n alignItems: 'center',\n border: '1px solid',\n borderColor: 'border/minimal',\n display: 'inline-flex',\n flexShrink: '0',\n justifyContent: 'center',\n position: 'relative',\n userSelect: 'none',\n verticalAlign: 'top',\n '&:has([data-part=image][data-state=visible])': {\n backgroundColor: 'transparent',\n },\n },\n image: {\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n },\n fallback: {},\n icon: {},\n badge: {\n width: 16,\n height: 16,\n },\n badgeContainer: {\n display: 'flex',\n boxShadow: 'elevation/sm',\n position: 'absolute',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'text/secondary',\n backgroundColor: 'background/primary',\n },\n },\n\n variants: {\n size: {\n '24': {\n root: { width: 24, height: 24, borderRadius: 4 },\n image: { borderRadius: 'calc({radii.4} - 1px)' },\n fallback: { textStyle: 'comp/avatar/24', borderRadius: 'calc({radii.4} - 1px)' },\n icon: { width: 16, height: 16 },\n badgeContainer: { display: 'none' },\n },\n '32': {\n root: { width: 32, height: 32, borderRadius: 6 },\n image: { borderRadius: 'calc({radii.6} - 1px)' },\n fallback: { textStyle: 'comp/avatar/32', borderRadius: 'calc({radii.6} - 1px)' },\n icon: { width: 20, height: 20 },\n badgeContainer: { width: 16, height: 16, bottom: -5, right: -5, borderRadius: 4 },\n },\n '40': {\n root: { width: 40, height: 40, borderRadius: 8 },\n image: { borderRadius: 'calc({radii.8} - 1px)' },\n fallback: { textStyle: 'comp/avatar/40', borderRadius: 'calc({radii.8} - 1px)' },\n icon: { width: 24, height: 24 },\n badgeContainer: { width: 16, height: 16, bottom: -2, right: -2, borderRadius: 4 },\n },\n '48': {\n root: { width: 48, height: 48, borderRadius: '10' },\n image: { borderRadius: 'calc({radii.10} - 1px)' },\n fallback: { textStyle: 'comp/avatar/48', borderRadius: 'calc({radii.10} - 1px)' },\n icon: { width: 32, height: 32 },\n badgeContainer: { width: 24, height: 24, bottom: -7, right: -7, borderRadius: '50%' },\n },\n '64': {\n root: { width: 64, height: 64, borderRadius: 12 },\n image: { borderRadius: 'calc({radii.12} - 1px)' },\n fallback: { textStyle: 'comp/avatar/64', borderRadius: 'calc({radii.12} - 1px)' },\n icon: { width: 48, height: 48 },\n badgeContainer: { width: 24, height: 24, bottom: -5, right: -5, borderRadius: '50%' },\n },\n '128': {\n root: { width: 128, height: 128, borderRadius: 16 },\n image: { borderRadius: 'calc({radii.16} - 1px)' },\n fallback: { textStyle: 'comp/avatar/128', borderRadius: 'calc({radii.16} - 1px)' },\n icon: { width: 96, height: 96 },\n badgeContainer: { display: 'none' },\n },\n },\n\n variant: {\n circle: {\n root: { borderRadius: '50%' },\n image: { borderRadius: '50%' },\n fallback: { borderRadius: '50%' },\n },\n rounded: {},\n },\n\n colorVariant: {\n neutral: { root: { color: 'color/neutral/strong', backgroundColor: 'color/neutral/subtle' } },\n purple: { root: { color: 'color/purple/strong', backgroundColor: 'color/purple/subtle' } },\n indigo: { root: { color: 'color/indigo/strong', backgroundColor: 'color/indigo/subtle' } },\n blue: { root: { color: 'color/blue/strong', backgroundColor: 'color/blue/subtle' } },\n green: { root: { color: 'color/green/strong', backgroundColor: 'color/green/subtle' } },\n yellow: { root: { color: 'color/yellow/strong', backgroundColor: 'color/yellow/subtle' } },\n red: { root: { color: 'color/red/strong', backgroundColor: 'color/red/subtle' } },\n orange: { root: { color: 'color/orange/strong', backgroundColor: 'color/orange/subtle' } },\n turquoise: { root: { color: 'color/turquoise/strong', backgroundColor: 'color/turquoise/subtle' } },\n },\n },\n\n defaultVariants: {\n colorVariant: 'neutral',\n size: '32',\n variant: 'circle',\n },\n});\n\nexport default avatarSlotRecipe;\n"],"mappings":";;;AAGA,IAAM,mBAAmB,iBAAiB;CACxC,OAAO;EAAC,GAAG,cAAc,KAAK;EAAG;EAAQ;EAAS;CAAgB;CAClE,WAAW;CACX,MAAM;EACJ,MAAM;GACJ,YAAY;GACZ,QAAQ;GACR,aAAa;GACb,SAAS;GACT,YAAY;GACZ,gBAAgB;GAChB,UAAU;GACV,YAAY;GACZ,eAAe;GACf,gDAAgD,EAC9C,iBAAiB,cACnB;EACF;EACA,OAAO;GACL,OAAO;GACP,QAAQ;GACR,WAAW;EACb;EACA,UAAU,
|
|
1
|
+
{"version":3,"file":"Avatar.recipe.js","names":[],"sources":["../../../lib/theme/slot-recipes/Avatar.recipe.ts"],"sourcesContent":["import { avatarAnatomy } from '@chakra-ui/react/anatomy';\nimport { defineSlotRecipe } from '@chakra-ui/react/styled-system';\n\nconst avatarSlotRecipe = defineSlotRecipe({\n slots: [...avatarAnatomy.keys(), 'icon', 'badge', 'badgeContainer'],\n className: 'avatar',\n base: {\n root: {\n alignItems: 'center',\n border: '1px solid',\n borderColor: 'border/minimal',\n display: 'inline-flex',\n flexShrink: '0',\n justifyContent: 'center',\n position: 'relative',\n userSelect: 'none',\n verticalAlign: 'top',\n '&:has([data-part=image][data-state=visible])': {\n backgroundColor: 'transparent',\n },\n },\n image: {\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n },\n fallback: {\n '&:has(> *)': {\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n },\n },\n icon: {},\n badge: {\n width: 16,\n height: 16,\n },\n badgeContainer: {\n display: 'flex',\n boxShadow: 'elevation/sm',\n position: 'absolute',\n alignItems: 'center',\n justifyContent: 'center',\n color: 'text/secondary',\n backgroundColor: 'background/primary',\n },\n },\n\n variants: {\n size: {\n '24': {\n root: { width: 24, height: 24, borderRadius: 4 },\n image: { borderRadius: 'calc({radii.4} - 1px)' },\n fallback: { textStyle: 'comp/avatar/24', borderRadius: 'calc({radii.4} - 1px)' },\n icon: { width: 16, height: 16 },\n badgeContainer: { display: 'none' },\n },\n '32': {\n root: { width: 32, height: 32, borderRadius: 6 },\n image: { borderRadius: 'calc({radii.6} - 1px)' },\n fallback: { textStyle: 'comp/avatar/32', borderRadius: 'calc({radii.6} - 1px)' },\n icon: { width: 20, height: 20 },\n badgeContainer: { width: 16, height: 16, bottom: -5, right: -5, borderRadius: 4 },\n },\n '40': {\n root: { width: 40, height: 40, borderRadius: 8 },\n image: { borderRadius: 'calc({radii.8} - 1px)' },\n fallback: { textStyle: 'comp/avatar/40', borderRadius: 'calc({radii.8} - 1px)' },\n icon: { width: 24, height: 24 },\n badgeContainer: { width: 16, height: 16, bottom: -2, right: -2, borderRadius: 4 },\n },\n '48': {\n root: { width: 48, height: 48, borderRadius: '10' },\n image: { borderRadius: 'calc({radii.10} - 1px)' },\n fallback: { textStyle: 'comp/avatar/48', borderRadius: 'calc({radii.10} - 1px)' },\n icon: { width: 32, height: 32 },\n badgeContainer: { width: 24, height: 24, bottom: -7, right: -7, borderRadius: '50%' },\n },\n '64': {\n root: { width: 64, height: 64, borderRadius: 12 },\n image: { borderRadius: 'calc({radii.12} - 1px)' },\n fallback: { textStyle: 'comp/avatar/64', borderRadius: 'calc({radii.12} - 1px)' },\n icon: { width: 48, height: 48 },\n badgeContainer: { width: 24, height: 24, bottom: -5, right: -5, borderRadius: '50%' },\n },\n '128': {\n root: { width: 128, height: 128, borderRadius: 16 },\n image: { borderRadius: 'calc({radii.16} - 1px)' },\n fallback: { textStyle: 'comp/avatar/128', borderRadius: 'calc({radii.16} - 1px)' },\n icon: { width: 96, height: 96 },\n badgeContainer: { display: 'none' },\n },\n },\n\n variant: {\n circle: {\n root: { borderRadius: '50%' },\n image: { borderRadius: '50%' },\n fallback: { borderRadius: '50%' },\n },\n rounded: {},\n },\n\n colorVariant: {\n neutral: { root: { color: 'color/neutral/strong', backgroundColor: 'color/neutral/subtle' } },\n purple: { root: { color: 'color/purple/strong', backgroundColor: 'color/purple/subtle' } },\n indigo: { root: { color: 'color/indigo/strong', backgroundColor: 'color/indigo/subtle' } },\n blue: { root: { color: 'color/blue/strong', backgroundColor: 'color/blue/subtle' } },\n green: { root: { color: 'color/green/strong', backgroundColor: 'color/green/subtle' } },\n yellow: { root: { color: 'color/yellow/strong', backgroundColor: 'color/yellow/subtle' } },\n red: { root: { color: 'color/red/strong', backgroundColor: 'color/red/subtle' } },\n orange: { root: { color: 'color/orange/strong', backgroundColor: 'color/orange/subtle' } },\n turquoise: { root: { color: 'color/turquoise/strong', backgroundColor: 'color/turquoise/subtle' } },\n },\n },\n\n defaultVariants: {\n colorVariant: 'neutral',\n size: '32',\n variant: 'circle',\n },\n});\n\nexport default avatarSlotRecipe;\n"],"mappings":"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"}
|