@bitrise/bitkit-v2 0.3.202 → 0.3.203

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,13 @@
1
1
  import { SelectRootProps, SelectTriggerProps } from '@chakra-ui/react/select';
2
2
  import { BitkitFieldProps } from '../BitkitField/BitkitField';
3
- import { BitkitSelectMenuCreateItemProps, BitkitSelectMenuEmptyStateProps, BitkitSelectMenuItemProps, BitkitSelectMenuSearchProps } from '../BitkitSelectMenu/BitkitSelectMenu';
3
+ import { BitkitMultiselectMenuItemProps } from '../BitkitMultiselectMenu/BitkitMultiselectMenu';
4
+ import { BitkitSelectMenuCreateItemProps, BitkitSelectMenuEmptyStateProps, BitkitSelectMenuSearchProps } from '../BitkitSelectMenu/BitkitSelectMenu';
4
5
  export type BitkitMultiselectTriggerProps = SelectTriggerProps;
5
6
  export type BitkitMultiselectProps = Omit<BitkitFieldProps, 'children' | 'state'> & {
6
7
  constrained?: boolean;
7
8
  defaultValue?: Array<string>;
8
9
  isLoading?: boolean;
9
- items: Array<BitkitSelectMenuItemProps>;
10
+ items: Array<BitkitMultiselectMenuItemProps>;
10
11
  onValueChange?: (newVal: Array<string>) => void;
11
12
  placeholder?: string;
12
13
  selectProps?: Omit<SelectRootProps, 'collection' | 'defaultValue' | 'multiple' | 'onValueChange' | 'value'>;
@@ -2,8 +2,8 @@ import AssetSelectChevron from "../../utilities/AssetSelectChevron.js";
2
2
  import IconErrorCircleFilled from "../../icons/IconErrorCircleFilled.js";
3
3
  import IconWarningYellow from "../../icons/IconWarningYellow.js";
4
4
  import BitkitCloseButton from "../BitkitCloseButton/BitkitCloseButton.js";
5
- import BitkitSelectMenu from "../BitkitSelectMenu/BitkitSelectMenu.js";
6
5
  import BitkitField from "../BitkitField/BitkitField.js";
6
+ import BitkitMultiselectMenu from "../BitkitMultiselectMenu/BitkitMultiselectMenu.js";
7
7
  import BitkitTag from "../BitkitTag/BitkitTag.js";
8
8
  import { Box } from "@chakra-ui/react/box";
9
9
  import { useSlotRecipe } from "@chakra-ui/react/styled-system";
@@ -158,13 +158,12 @@ var BitkitMultiselect = forwardRef((props, ref) => {
158
158
  })
159
159
  ]
160
160
  }),
161
- /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Select.Positioner, { children: /* @__PURE__ */ jsx(BitkitSelectMenu, {
161
+ /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Select.Positioner, { children: /* @__PURE__ */ jsx(BitkitMultiselectMenu, {
162
162
  collection,
163
163
  createItemLabel,
164
164
  emptyHelperText,
165
165
  emptyLabel,
166
166
  isLoading,
167
- multiple: true,
168
167
  onCreateItem,
169
168
  ...hasSearch ? {
170
169
  hasSearch: true,
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitMultiselect.js","names":[],"sources":["../../../lib/components/BitkitMultiselect/BitkitMultiselect.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, type ReactNode } from 'react';\n\nimport { IconErrorCircleFilled, IconWarningYellow } from '../../icons';\nimport AssetSelectChevron from '../../utilities/AssetSelectChevron';\nimport BitkitCloseButton from '../BitkitCloseButton/BitkitCloseButton';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField';\nimport BitkitSelectMenu, {\n type BitkitSelectMenuCreateItemProps,\n type BitkitSelectMenuEmptyStateProps,\n type BitkitSelectMenuItemProps,\n type BitkitSelectMenuSearchProps,\n} from '../BitkitSelectMenu/BitkitSelectMenu';\nimport BitkitTag from '../BitkitTag/BitkitTag';\n\nexport type BitkitMultiselectTriggerProps = SelectTriggerProps;\n\nexport type BitkitMultiselectProps = Omit<BitkitFieldProps, 'children' | 'state'> & {\n constrained?: boolean;\n defaultValue?: Array<string>;\n isLoading?: boolean;\n items: Array<BitkitSelectMenuItemProps>;\n onValueChange?: (newVal: Array<string>) => void;\n placeholder?: string;\n selectProps?: Omit<SelectRootProps, 'collection' | 'defaultValue' | 'multiple' | 'onValueChange' | 'value'>;\n size?: 'md' | 'lg';\n state?: 'disabled' | 'error' | 'readOnly' | 'warning';\n triggerProps?: BitkitMultiselectTriggerProps;\n value?: Array<string>;\n} & BitkitSelectMenuCreateItemProps &\n BitkitSelectMenuSearchProps &\n BitkitSelectMenuEmptyStateProps;\n\ntype MultiselectState = BitkitMultiselectProps['state'];\n\nconst NON_INTERACTIVE_STATES: ReadonlyArray<MultiselectState> = ['disabled', 'readOnly', 'error', 'warning'];\n\n/** Whether the clear-all button should be rendered (and the overlay should reserve extra room for it). */\nconst shouldShowClearButton = (constrained: boolean, selectionCount: number, state: MultiselectState): boolean =>\n !constrained && selectionCount > 0 && !NON_INTERACTIVE_STATES.includes(state);\n\ntype MultiselectOverlayProps = {\n constrained: boolean;\n placeholder?: string;\n size: 'md' | 'lg';\n state?: MultiselectState;\n};\n\nconst MultiselectOverlay = ({ constrained, placeholder, size, state }: MultiselectOverlayProps) => {\n const select = useSelectContext();\n const recipe = useSlotRecipe({ key: 'multiselect' });\n const styles = recipe({ constrained, size });\n\n const selectedItems = select.selectedItems as Array<BitkitSelectMenuItemProps>;\n const selectedValues = select.value;\n const isDisabled = state === 'disabled';\n const isReadOnly = state === 'readOnly';\n const tagState = isDisabled ? 'disabled' : undefined;\n // Overlay reserves ~96px on the right when the clear-all is visible (to keep the chevron +\n // clear button out of the tag row), otherwise ~48px (chevron only). Using spacing tokens\n // because '80' (the minimum that fits both icons with gaps) isn't a valid token; '96' is\n // the next one up.\n const overlayPaddingEnd = shouldShowClearButton(constrained, selectedValues.length, state) ? '96' : '48';\n\n const resolvedPlaceholder = placeholder ?? (isReadOnly ? '(not selected)' : 'Select options');\n const canRemove = !isDisabled && !isReadOnly;\n\n const hasSelection = selectedValues.length > 0;\n\n const renderTags = () => {\n if (constrained) {\n return (\n <>\n {hasSelection && (\n <TagSlot>\n <BitkitTag\n size=\"sm\"\n colorPalette=\"neutral\"\n labelText={String(selectedValues.length)}\n state={tagState}\n onRemove={canRemove ? () => select.clearValue() : undefined}\n />\n </TagSlot>\n )}\n <Text as=\"span\" css={styles.placeholderText} data-placeholder={hasSelection ? undefined : ''}>\n {resolvedPlaceholder}\n </Text>\n </>\n );\n }\n\n if (selectedItems.length === 0) {\n return (\n <Text as=\"span\" css={styles.placeholderText} data-placeholder=\"\">\n {resolvedPlaceholder}\n </Text>\n );\n }\n\n return selectedItems.map((item) => (\n <TagSlot key={item.value}>\n <BitkitTag\n size=\"sm\"\n colorPalette=\"neutral\"\n labelText={item.label}\n state={tagState}\n onRemove={canRemove ? () => select.setValue(selectedValues.filter((v) => v !== item.value)) : undefined}\n />\n </TagSlot>\n ));\n };\n\n return (\n <Box css={styles.overlay} pointerEvents=\"none\" paddingInlineEnd={overlayPaddingEnd}>\n <Box css={styles.tagsBlock}>{renderTags()}</Box>\n </Box>\n );\n};\n\nconst TagSlot = ({ children }: { children: ReactNode }) => (\n <Box data-slot=\"tag\" display=\"inline-flex\" pointerEvents=\"auto\">\n {children}\n </Box>\n);\n\ntype ClearAllButtonProps = {\n state?: MultiselectState;\n};\n\nconst ClearAllButton = ({ state }: ClearAllButtonProps) => {\n const select = useSelectContext();\n\n // Constrained mode has its own inline clear-all on the counter tag; this is the non-constrained trigger-level clear.\n if (!shouldShowClearButton(false, select.value.length, state)) return null;\n\n return (\n <BitkitCloseButton size=\"sm\" colorPalette=\"neutral\" aria-label=\"Clear all\" onClick={() => select.clearValue()} />\n );\n};\n\nconst BitkitMultiselect = forwardRef<HTMLDivElement, BitkitMultiselectProps>((props, ref) => {\n const {\n constrained = false,\n createItemLabel,\n defaultValue,\n emptyHelperText,\n emptyLabel,\n hasSearch,\n isLoading,\n items,\n onCreateItem,\n onSearchChange,\n onValueChange,\n placeholder,\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 recipe = useSlotRecipe({ key: 'multiselect' });\n const styles = recipe({ constrained, size });\n\n const iconSize = size === 'lg' ? '24' : '16';\n const isInvalid = state === 'error' || !!fieldProps.errorText;\n\n return (\n <BitkitField ref={ref} state={state} {...fieldProps}>\n <Select.Root\n collection={collection}\n multiple\n {...selectProps}\n defaultValue={defaultValue}\n disabled={state === 'disabled'}\n invalid={isInvalid}\n onValueChange={(details) => onValueChange?.(details.value)}\n readOnly={state === 'readOnly'}\n // Zag's default scrollIntoView gates on `isScrollable(contentEl)`. Our content is\n // overflow:hidden + flex column (so the sticky-bottom create row stays visible while\n // the inner itemList Box scrolls). That gate fails, so keyboard highlight never\n // scrolls the items into view. Providing scrollToIndexFn bypasses the gate and lets\n // the browser's native scrollIntoView walk up to the real scroll container (itemList).\n scrollToIndexFn={({ getElement }) => getElement()?.scrollIntoView({ block: 'nearest' })}\n value={value}\n >\n <Select.HiddenSelect />\n <Select.Control css={styles.control} className=\"group\">\n <Select.Trigger css={styles.trigger} {...triggerProps} />\n <MultiselectOverlay constrained={constrained} placeholder={placeholder} size={size} state={state} />\n <Select.IndicatorGroup css={styles.indicatorGroup}>\n {!constrained && <ClearAllButton state={state} />}\n {state === 'error' && (\n <Select.Indicator css={styles.indicator}>\n <IconErrorCircleFilled size={iconSize} color=\"icon/negative\" />\n </Select.Indicator>\n )}\n {state === 'warning' && (\n <Select.Indicator css={styles.indicator}>\n <IconWarningYellow size={iconSize} />\n </Select.Indicator>\n )}\n <Select.Indicator css={styles.indicator} asChild>\n <AssetSelectChevron />\n </Select.Indicator>\n </Select.IndicatorGroup>\n </Select.Control>\n <Portal>\n <Select.Positioner>\n <BitkitSelectMenu\n collection={collection}\n createItemLabel={createItemLabel}\n emptyHelperText={emptyHelperText}\n emptyLabel={emptyLabel}\n isLoading={isLoading}\n multiple\n onCreateItem={onCreateItem}\n {...(hasSearch\n ? { hasSearch: true as const, onSearchChange, searchValue }\n : { hasSearch: false as const })}\n size={size}\n />\n </Select.Positioner>\n </Portal>\n </Select.Root>\n </BitkitField>\n );\n});\n\nBitkitMultiselect.displayName = 'BitkitMultiselect';\n\nexport default BitkitMultiselect;\n"],"mappings":"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"}
1
+ {"version":3,"file":"BitkitMultiselect.js","names":[],"sources":["../../../lib/components/BitkitMultiselect/BitkitMultiselect.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, type ReactNode } from 'react';\n\nimport { IconErrorCircleFilled, IconWarningYellow } from '../../icons';\nimport AssetSelectChevron from '../../utilities/AssetSelectChevron';\nimport BitkitCloseButton from '../BitkitCloseButton/BitkitCloseButton';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField';\nimport BitkitMultiselectMenu, {\n type BitkitMultiselectMenuItemProps,\n} from '../BitkitMultiselectMenu/BitkitMultiselectMenu';\nimport {\n type BitkitSelectMenuCreateItemProps,\n type BitkitSelectMenuEmptyStateProps,\n type BitkitSelectMenuSearchProps,\n} from '../BitkitSelectMenu/BitkitSelectMenu';\nimport BitkitTag from '../BitkitTag/BitkitTag';\n\nexport type BitkitMultiselectTriggerProps = SelectTriggerProps;\n\nexport type BitkitMultiselectProps = Omit<BitkitFieldProps, 'children' | 'state'> & {\n constrained?: boolean;\n defaultValue?: Array<string>;\n isLoading?: boolean;\n items: Array<BitkitMultiselectMenuItemProps>;\n onValueChange?: (newVal: Array<string>) => void;\n placeholder?: string;\n selectProps?: Omit<SelectRootProps, 'collection' | 'defaultValue' | 'multiple' | 'onValueChange' | 'value'>;\n size?: 'md' | 'lg';\n state?: 'disabled' | 'error' | 'readOnly' | 'warning';\n triggerProps?: BitkitMultiselectTriggerProps;\n value?: Array<string>;\n} & BitkitSelectMenuCreateItemProps &\n BitkitSelectMenuSearchProps &\n BitkitSelectMenuEmptyStateProps;\n\ntype MultiselectState = BitkitMultiselectProps['state'];\n\nconst NON_INTERACTIVE_STATES: ReadonlyArray<MultiselectState> = ['disabled', 'readOnly', 'error', 'warning'];\n\n/** Whether the clear-all button should be rendered (and the overlay should reserve extra room for it). */\nconst shouldShowClearButton = (constrained: boolean, selectionCount: number, state: MultiselectState): boolean =>\n !constrained && selectionCount > 0 && !NON_INTERACTIVE_STATES.includes(state);\n\ntype MultiselectOverlayProps = {\n constrained: boolean;\n placeholder?: string;\n size: 'md' | 'lg';\n state?: MultiselectState;\n};\n\nconst MultiselectOverlay = ({ constrained, placeholder, size, state }: MultiselectOverlayProps) => {\n const select = useSelectContext();\n const recipe = useSlotRecipe({ key: 'multiselect' });\n const styles = recipe({ constrained, size });\n\n const selectedItems = select.selectedItems as Array<BitkitMultiselectMenuItemProps>;\n const selectedValues = select.value;\n const isDisabled = state === 'disabled';\n const isReadOnly = state === 'readOnly';\n const tagState = isDisabled ? 'disabled' : undefined;\n // Overlay reserves ~96px on the right when the clear-all is visible (to keep the chevron +\n // clear button out of the tag row), otherwise ~48px (chevron only). Using spacing tokens\n // because '80' (the minimum that fits both icons with gaps) isn't a valid token; '96' is\n // the next one up.\n const overlayPaddingEnd = shouldShowClearButton(constrained, selectedValues.length, state) ? '96' : '48';\n\n const resolvedPlaceholder = placeholder ?? (isReadOnly ? '(not selected)' : 'Select options');\n const canRemove = !isDisabled && !isReadOnly;\n\n const hasSelection = selectedValues.length > 0;\n\n const renderTags = () => {\n if (constrained) {\n return (\n <>\n {hasSelection && (\n <TagSlot>\n <BitkitTag\n size=\"sm\"\n colorPalette=\"neutral\"\n labelText={String(selectedValues.length)}\n state={tagState}\n onRemove={canRemove ? () => select.clearValue() : undefined}\n />\n </TagSlot>\n )}\n <Text as=\"span\" css={styles.placeholderText} data-placeholder={hasSelection ? undefined : ''}>\n {resolvedPlaceholder}\n </Text>\n </>\n );\n }\n\n if (selectedItems.length === 0) {\n return (\n <Text as=\"span\" css={styles.placeholderText} data-placeholder=\"\">\n {resolvedPlaceholder}\n </Text>\n );\n }\n\n return selectedItems.map((item) => (\n <TagSlot key={item.value}>\n <BitkitTag\n size=\"sm\"\n colorPalette=\"neutral\"\n labelText={item.label}\n state={tagState}\n onRemove={canRemove ? () => select.setValue(selectedValues.filter((v) => v !== item.value)) : undefined}\n />\n </TagSlot>\n ));\n };\n\n return (\n <Box css={styles.overlay} pointerEvents=\"none\" paddingInlineEnd={overlayPaddingEnd}>\n <Box css={styles.tagsBlock}>{renderTags()}</Box>\n </Box>\n );\n};\n\nconst TagSlot = ({ children }: { children: ReactNode }) => (\n <Box data-slot=\"tag\" display=\"inline-flex\" pointerEvents=\"auto\">\n {children}\n </Box>\n);\n\ntype ClearAllButtonProps = {\n state?: MultiselectState;\n};\n\nconst ClearAllButton = ({ state }: ClearAllButtonProps) => {\n const select = useSelectContext();\n\n // Constrained mode has its own inline clear-all on the counter tag; this is the non-constrained trigger-level clear.\n if (!shouldShowClearButton(false, select.value.length, state)) return null;\n\n return (\n <BitkitCloseButton size=\"sm\" colorPalette=\"neutral\" aria-label=\"Clear all\" onClick={() => select.clearValue()} />\n );\n};\n\nconst BitkitMultiselect = forwardRef<HTMLDivElement, BitkitMultiselectProps>((props, ref) => {\n const {\n constrained = false,\n createItemLabel,\n defaultValue,\n emptyHelperText,\n emptyLabel,\n hasSearch,\n isLoading,\n items,\n onCreateItem,\n onSearchChange,\n onValueChange,\n placeholder,\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 recipe = useSlotRecipe({ key: 'multiselect' });\n const styles = recipe({ constrained, size });\n\n const iconSize = size === 'lg' ? '24' : '16';\n const isInvalid = state === 'error' || !!fieldProps.errorText;\n\n return (\n <BitkitField ref={ref} state={state} {...fieldProps}>\n <Select.Root\n collection={collection}\n multiple\n {...selectProps}\n defaultValue={defaultValue}\n disabled={state === 'disabled'}\n invalid={isInvalid}\n onValueChange={(details) => onValueChange?.(details.value)}\n readOnly={state === 'readOnly'}\n // Zag's default scrollIntoView gates on `isScrollable(contentEl)`. Our content is\n // overflow:hidden + flex column (so the sticky-bottom create row stays visible while\n // the inner itemList Box scrolls). That gate fails, so keyboard highlight never\n // scrolls the items into view. Providing scrollToIndexFn bypasses the gate and lets\n // the browser's native scrollIntoView walk up to the real scroll container (itemList).\n scrollToIndexFn={({ getElement }) => getElement()?.scrollIntoView({ block: 'nearest' })}\n value={value}\n >\n <Select.HiddenSelect />\n <Select.Control css={styles.control} className=\"group\">\n <Select.Trigger css={styles.trigger} {...triggerProps} />\n <MultiselectOverlay constrained={constrained} placeholder={placeholder} size={size} state={state} />\n <Select.IndicatorGroup css={styles.indicatorGroup}>\n {!constrained && <ClearAllButton state={state} />}\n {state === 'error' && (\n <Select.Indicator css={styles.indicator}>\n <IconErrorCircleFilled size={iconSize} color=\"icon/negative\" />\n </Select.Indicator>\n )}\n {state === 'warning' && (\n <Select.Indicator css={styles.indicator}>\n <IconWarningYellow size={iconSize} />\n </Select.Indicator>\n )}\n <Select.Indicator css={styles.indicator} asChild>\n <AssetSelectChevron />\n </Select.Indicator>\n </Select.IndicatorGroup>\n </Select.Control>\n <Portal>\n <Select.Positioner>\n <BitkitMultiselectMenu\n collection={collection}\n createItemLabel={createItemLabel}\n emptyHelperText={emptyHelperText}\n emptyLabel={emptyLabel}\n isLoading={isLoading}\n onCreateItem={onCreateItem}\n {...(hasSearch\n ? { hasSearch: true as const, onSearchChange, searchValue }\n : { hasSearch: false as const })}\n size={size}\n />\n </Select.Positioner>\n </Portal>\n </Select.Root>\n </BitkitField>\n );\n});\n\nBitkitMultiselect.displayName = 'BitkitMultiselect';\n\nexport default BitkitMultiselect;\n"],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { ListCollection } from '@chakra-ui/react/collection';
2
+ import { BitkitSelectMenuCreateItemProps, BitkitSelectMenuEmptyStateProps, BitkitSelectMenuSearchProps } from '../BitkitSelectMenu/BitkitSelectMenu';
3
+ export type BitkitMultiselectMenuItemProps = {
4
+ value: string;
5
+ label: string;
6
+ group?: string;
7
+ helperText?: string;
8
+ disabled?: boolean;
9
+ loading?: boolean;
10
+ };
11
+ export type BitkitMultiselectMenuProps = {
12
+ collection: ListCollection<BitkitMultiselectMenuItemProps>;
13
+ isLoading?: boolean;
14
+ size?: 'md' | 'lg';
15
+ } & BitkitSelectMenuCreateItemProps & BitkitSelectMenuSearchProps & BitkitSelectMenuEmptyStateProps;
16
+ declare const BitkitMultiselectMenu: import('react').ForwardRefExoticComponent<BitkitMultiselectMenuProps & import('react').RefAttributes<HTMLDivElement>>;
17
+ export default BitkitMultiselectMenu;
@@ -0,0 +1,66 @@
1
+ import IconCheck from "../../icons/IconCheck.js";
2
+ import { SelectMenuShell } from "../BitkitSelectMenu/SelectMenuShell.js";
3
+ import { Box } from "@chakra-ui/react/box";
4
+ import { useSlotRecipe } from "@chakra-ui/react/styled-system";
5
+ import { Text } from "@chakra-ui/react/text";
6
+ import { forwardRef } from "react";
7
+ import { jsx, jsxs } from "react/jsx-runtime";
8
+ import { Spinner } from "@chakra-ui/react/spinner";
9
+ import { Select } from "@chakra-ui/react/select";
10
+ //#region lib/components/BitkitMultiselectMenu/BitkitMultiselectMenu.tsx
11
+ var BitkitMultiselectMenu = forwardRef((props, ref) => {
12
+ const { collection, size, ...shellProps } = props;
13
+ const styles = useSlotRecipe({ key: "select" })({ size });
14
+ return /* @__PURE__ */ jsx(SelectMenuShell, {
15
+ NS: Select,
16
+ collection,
17
+ contentRef: ref,
18
+ iconSize: size === "md" ? "16" : "24",
19
+ renderItem: (item) => /* @__PURE__ */ jsx(MultiselectMenuItem, {
20
+ item,
21
+ styles
22
+ }, item.value),
23
+ size,
24
+ styles,
25
+ ...shellProps
26
+ });
27
+ });
28
+ BitkitMultiselectMenu.displayName = "BitkitMultiselectMenu";
29
+ var MultiselectMenuItem = ({ item, styles }) => {
30
+ if (item.loading) return /* @__PURE__ */ jsxs(Box, {
31
+ css: styles.item,
32
+ children: [/* @__PURE__ */ jsx(Spinner, {
33
+ variant: "purple",
34
+ css: styles.itemLoading
35
+ }), /* @__PURE__ */ jsx(Text, {
36
+ css: styles.itemLoadingLabel,
37
+ children: "Loading..."
38
+ })]
39
+ });
40
+ return /* @__PURE__ */ jsxs(Select.Item, {
41
+ css: styles.item,
42
+ item,
43
+ children: [/* @__PURE__ */ jsx(Box, {
44
+ css: styles.checkbox,
45
+ "data-slot": "checkbox",
46
+ children: /* @__PURE__ */ jsx(IconCheck, {
47
+ size: "16",
48
+ css: styles.checkmark,
49
+ "data-slot": "checkmark"
50
+ })
51
+ }), /* @__PURE__ */ jsxs(Box, {
52
+ css: styles.itemContent,
53
+ children: [/* @__PURE__ */ jsx(Text, {
54
+ css: styles.itemLabel,
55
+ children: item.label
56
+ }), item.helperText && /* @__PURE__ */ jsx(Text, {
57
+ css: styles.itemHelperText,
58
+ children: item.helperText
59
+ })]
60
+ })]
61
+ });
62
+ };
63
+ //#endregion
64
+ export { BitkitMultiselectMenu as default };
65
+
66
+ //# sourceMappingURL=BitkitMultiselectMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BitkitMultiselectMenu.js","names":[],"sources":["../../../lib/components/BitkitMultiselectMenu/BitkitMultiselectMenu.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { type ListCollection } from '@chakra-ui/react/collection';\nimport { Select } 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 { forwardRef } from 'react';\n\nimport { IconCheck } from '../../icons';\nimport {\n type BitkitSelectMenuCreateItemProps,\n type BitkitSelectMenuEmptyStateProps,\n type BitkitSelectMenuSearchProps,\n} from '../BitkitSelectMenu/BitkitSelectMenu';\nimport { SelectMenuShell } from '../BitkitSelectMenu/SelectMenuShell';\n\nexport type BitkitMultiselectMenuItemProps = {\n value: string;\n label: string;\n group?: string;\n helperText?: string;\n disabled?: boolean;\n loading?: boolean;\n};\n\nexport type BitkitMultiselectMenuProps = {\n collection: ListCollection<BitkitMultiselectMenuItemProps>;\n isLoading?: boolean;\n size?: 'md' | 'lg';\n} & BitkitSelectMenuCreateItemProps &\n BitkitSelectMenuSearchProps &\n BitkitSelectMenuEmptyStateProps;\n\nconst BitkitMultiselectMenu = forwardRef<HTMLDivElement, BitkitMultiselectMenuProps>((props, ref) => {\n const { collection, size, ...shellProps } = props;\n const recipe = useSlotRecipe({ key: 'select' });\n const styles = recipe({ size });\n const iconSize = size === 'md' ? '16' : '24';\n\n return (\n <SelectMenuShell\n NS={Select}\n collection={collection}\n contentRef={ref}\n iconSize={iconSize}\n renderItem={(item) => <MultiselectMenuItem key={item.value} item={item} styles={styles} />}\n size={size}\n styles={styles}\n {...shellProps}\n />\n );\n});\n\nBitkitMultiselectMenu.displayName = 'BitkitMultiselectMenu';\n\ntype MultiselectMenuItemRenderProps = {\n item: BitkitMultiselectMenuItemProps;\n styles: Record<string, SystemStyleObject>;\n};\n\nconst MultiselectMenuItem = ({ item, styles }: MultiselectMenuItemRenderProps) => {\n if (item.loading) {\n // Rendered as a plain Box, not Select.Item — Zag's state machine won't track it\n // as an option, so keyboard nav skips it and it can't be selected.\n return (\n <Box css={styles.item}>\n <Spinner variant=\"purple\" css={styles.itemLoading} />\n <Text css={styles.itemLoadingLabel}>Loading...</Text>\n </Box>\n );\n }\n\n return (\n <Select.Item css={styles.item} item={item}>\n <Box css={styles.checkbox} data-slot=\"checkbox\">\n <IconCheck size=\"16\" css={styles.checkmark} data-slot=\"checkmark\" />\n </Box>\n <Box css={styles.itemContent}>\n <Text css={styles.itemLabel}>{item.label}</Text>\n {item.helperText && <Text css={styles.itemHelperText}>{item.helperText}</Text>}\n </Box>\n </Select.Item>\n );\n};\n\nexport default BitkitMultiselectMenu;\n"],"mappings":";;;;;;;;;;AAiCA,IAAM,wBAAwB,YAAwD,OAAO,QAAQ;CACnG,MAAM,EAAE,YAAY,MAAM,GAAG,eAAe;CAE5C,MAAM,SADS,cAAc,EAAE,KAAK,UAAU,CAAC,CACzB,EAAE,MAAM,CAAC;AAG/B,QACE,oBAAC,iBAAD;EACE,IAAI;EACQ;EACZ,YAAY;EACF,UAPG,SAAS,OAAO,OAAO;EAQpC,aAAa,SAAS,oBAAC,qBAAD;GAA4C;GAAc;GAAU,EAA1C,KAAK,MAAqC;EACpF;EACE;EACR,GAAI;EACJ,CAAA;EAEJ;AAEF,sBAAsB,cAAc;AAOpC,IAAM,uBAAuB,EAAE,MAAM,aAA6C;AAChF,KAAI,KAAK,QAGP,QACE,qBAAC,KAAD;EAAK,KAAK,OAAO;YAAjB,CACE,oBAAC,SAAD;GAAS,SAAQ;GAAS,KAAK,OAAO;GAAe,CAAA,EACrD,oBAAC,MAAD;GAAM,KAAK,OAAO;aAAkB;GAAiB,CAAA,CACjD;;AAIV,QACE,qBAAC,OAAO,MAAR;EAAa,KAAK,OAAO;EAAY;YAArC,CACE,oBAAC,KAAD;GAAK,KAAK,OAAO;GAAU,aAAU;aACnC,oBAAC,WAAD;IAAW,MAAK;IAAK,KAAK,OAAO;IAAW,aAAU;IAAc,CAAA;GAChE,CAAA,EACN,qBAAC,KAAD;GAAK,KAAK,OAAO;aAAjB,CACE,oBAAC,MAAD;IAAM,KAAK,OAAO;cAAY,KAAK;IAAa,CAAA,EAC/C,KAAK,cAAc,oBAAC,MAAD;IAAM,KAAK,OAAO;cAAiB,KAAK;IAAkB,CAAA,CAC1E;KACM"}
@@ -48,7 +48,7 @@ var BitkitNativeSelect = forwardRef((props, ref) => {
48
48
  statusIcon,
49
49
  /* @__PURE__ */ jsx(NativeSelect.Indicator, {
50
50
  asChild: true,
51
- children: /* @__PURE__ */ jsx(AssetSelectChevron, {})
51
+ children: /* @__PURE__ */ jsx(AssetSelectChevron, { pointerEvents: "none" })
52
52
  })
53
53
  ]
54
54
  })
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitNativeSelect.js","names":[],"sources":["../../../lib/components/BitkitNativeSelect/BitkitNativeSelect.tsx"],"sourcesContent":["import { NativeSelect, type NativeSelectRootProps } from '@chakra-ui/react/native-select';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { splitProps } from '@zag-js/utils';\nimport { type ChangeEventHandler, forwardRef, type ReactNode } from 'react';\n\nimport { IconErrorCircleFilled, IconWarningYellow } from '../../icons';\nimport AssetSelectChevron from '../../utilities/AssetSelectChevron.tsx';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField.tsx';\n\nconst FIELD_PROPS = ['defaultValue', 'name', 'onChange', 'placeholder', 'value'] as const;\n\nexport interface BitkitNativeSelectProps extends Omit<\n BitkitFieldProps,\n 'children' | 'disabled' | 'invalid' | 'onChange' | 'readOnly'\n> {\n children: ReactNode;\n defaultValue?: string;\n name?: string;\n onChange?: ChangeEventHandler<HTMLSelectElement>;\n placeholder?: string;\n selectProps?: NativeSelectRootProps;\n size?: 'md' | 'lg';\n state?: 'disabled' | 'error' | 'readOnly' | 'warning';\n value?: string;\n}\n\nconst BitkitNativeSelect = forwardRef<HTMLSelectElement, BitkitNativeSelectProps>(\n (props: BitkitNativeSelectProps, ref) => {\n const { children, selectProps, size = 'md', state, ...rest } = props;\n const [nativeFieldProps, bitkitFieldProps] = splitProps(rest, [...FIELD_PROPS]);\n\n const recipe = useSlotRecipe({ key: 'nativeSelect' });\n const styles = recipe();\n\n const hasWarning = state === 'warning' || !!bitkitFieldProps.warningText;\n const isInvalid = state === 'error' || !!bitkitFieldProps.errorText;\n\n let statusIcon = undefined;\n if (isInvalid) {\n statusIcon = (\n <IconErrorCircleFilled size={size === 'lg' ? '24' : '16'} css={styles.statusIcon} color=\"icon/negative\" />\n );\n } else if (hasWarning) {\n statusIcon = (\n <IconWarningYellow size={size === 'lg' ? '24' : '16'} css={styles.statusIcon} color=\"icon/warning\" />\n );\n }\n\n return (\n <BitkitField state={state} {...bitkitFieldProps}>\n <NativeSelect.Root size={size} {...selectProps} className=\"group\">\n <NativeSelect.Field ref={ref} {...nativeFieldProps}>\n {children}\n </NativeSelect.Field>\n {statusIcon}\n <NativeSelect.Indicator asChild>\n <AssetSelectChevron />\n </NativeSelect.Indicator>\n </NativeSelect.Root>\n </BitkitField>\n );\n },\n);\n\nBitkitNativeSelect.displayName = 'BitkitNativeSelect';\n\nexport default BitkitNativeSelect;\n"],"mappings":";;;;;;;;;;AASA,IAAM,cAAc;CAAC;CAAgB;CAAQ;CAAY;CAAe;CAAQ;AAiBhF,IAAM,qBAAqB,YACxB,OAAgC,QAAQ;CACvC,MAAM,EAAE,UAAU,aAAa,OAAO,MAAM,OAAO,GAAG,SAAS;CAC/D,MAAM,CAAC,kBAAkB,oBAAoB,WAAW,MAAM,CAAC,GAAG,YAAY,CAAC;CAG/E,MAAM,SADS,cAAc,EAAE,KAAK,gBAAgB,CAAC,EAC9B;CAEvB,MAAM,aAAa,UAAU,aAAa,CAAC,CAAC,iBAAiB;CAC7D,MAAM,YAAY,UAAU,WAAW,CAAC,CAAC,iBAAiB;CAE1D,IAAI,aAAa,KAAA;AACjB,KAAI,UACF,cACE,oBAAC,uBAAD;EAAuB,MAAM,SAAS,OAAO,OAAO;EAAM,KAAK,OAAO;EAAY,OAAM;EAAkB,CAAA;UAEnG,WACT,cACE,oBAAC,mBAAD;EAAmB,MAAM,SAAS,OAAO,OAAO;EAAM,KAAK,OAAO;EAAY,OAAM;EAAiB,CAAA;AAIzG,QACE,oBAAC,aAAD;EAAoB;EAAO,GAAI;YAC7B,qBAAC,aAAa,MAAd;GAAyB;GAAM,GAAI;GAAa,WAAU;aAA1D;IACE,oBAAC,aAAa,OAAd;KAAyB;KAAK,GAAI;KAC/B;KACkB,CAAA;IACpB;IACD,oBAAC,aAAa,WAAd;KAAwB,SAAA;eACtB,oBAAC,oBAAD,EAAsB,CAAA;KACC,CAAA;IACP;;EACR,CAAA;EAGnB;AAED,mBAAmB,cAAc"}
1
+ {"version":3,"file":"BitkitNativeSelect.js","names":[],"sources":["../../../lib/components/BitkitNativeSelect/BitkitNativeSelect.tsx"],"sourcesContent":["import { NativeSelect, type NativeSelectRootProps } from '@chakra-ui/react/native-select';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { splitProps } from '@zag-js/utils';\nimport { type ChangeEventHandler, forwardRef, type ReactNode } from 'react';\n\nimport { IconErrorCircleFilled, IconWarningYellow } from '../../icons';\nimport AssetSelectChevron from '../../utilities/AssetSelectChevron.tsx';\nimport BitkitField, { type BitkitFieldProps } from '../BitkitField/BitkitField.tsx';\n\nconst FIELD_PROPS = ['defaultValue', 'name', 'onChange', 'placeholder', 'value'] as const;\n\nexport interface BitkitNativeSelectProps extends Omit<\n BitkitFieldProps,\n 'children' | 'disabled' | 'invalid' | 'onChange' | 'readOnly'\n> {\n children: ReactNode;\n defaultValue?: string;\n name?: string;\n onChange?: ChangeEventHandler<HTMLSelectElement>;\n placeholder?: string;\n selectProps?: NativeSelectRootProps;\n size?: 'md' | 'lg';\n state?: 'disabled' | 'error' | 'readOnly' | 'warning';\n value?: string;\n}\n\nconst BitkitNativeSelect = forwardRef<HTMLSelectElement, BitkitNativeSelectProps>(\n (props: BitkitNativeSelectProps, ref) => {\n const { children, selectProps, size = 'md', state, ...rest } = props;\n const [nativeFieldProps, bitkitFieldProps] = splitProps(rest, [...FIELD_PROPS]);\n\n const recipe = useSlotRecipe({ key: 'nativeSelect' });\n const styles = recipe();\n\n const hasWarning = state === 'warning' || !!bitkitFieldProps.warningText;\n const isInvalid = state === 'error' || !!bitkitFieldProps.errorText;\n\n let statusIcon = undefined;\n if (isInvalid) {\n statusIcon = (\n <IconErrorCircleFilled size={size === 'lg' ? '24' : '16'} css={styles.statusIcon} color=\"icon/negative\" />\n );\n } else if (hasWarning) {\n statusIcon = (\n <IconWarningYellow size={size === 'lg' ? '24' : '16'} css={styles.statusIcon} color=\"icon/warning\" />\n );\n }\n\n return (\n <BitkitField state={state} {...bitkitFieldProps}>\n <NativeSelect.Root size={size} {...selectProps} className=\"group\">\n <NativeSelect.Field ref={ref} {...nativeFieldProps}>\n {children}\n </NativeSelect.Field>\n {statusIcon}\n <NativeSelect.Indicator asChild>\n <AssetSelectChevron pointerEvents=\"none\" />\n </NativeSelect.Indicator>\n </NativeSelect.Root>\n </BitkitField>\n );\n },\n);\n\nBitkitNativeSelect.displayName = 'BitkitNativeSelect';\n\nexport default BitkitNativeSelect;\n"],"mappings":";;;;;;;;;;AASA,IAAM,cAAc;CAAC;CAAgB;CAAQ;CAAY;CAAe;CAAQ;AAiBhF,IAAM,qBAAqB,YACxB,OAAgC,QAAQ;CACvC,MAAM,EAAE,UAAU,aAAa,OAAO,MAAM,OAAO,GAAG,SAAS;CAC/D,MAAM,CAAC,kBAAkB,oBAAoB,WAAW,MAAM,CAAC,GAAG,YAAY,CAAC;CAG/E,MAAM,SADS,cAAc,EAAE,KAAK,gBAAgB,CAAC,EAC9B;CAEvB,MAAM,aAAa,UAAU,aAAa,CAAC,CAAC,iBAAiB;CAC7D,MAAM,YAAY,UAAU,WAAW,CAAC,CAAC,iBAAiB;CAE1D,IAAI,aAAa,KAAA;AACjB,KAAI,UACF,cACE,oBAAC,uBAAD;EAAuB,MAAM,SAAS,OAAO,OAAO;EAAM,KAAK,OAAO;EAAY,OAAM;EAAkB,CAAA;UAEnG,WACT,cACE,oBAAC,mBAAD;EAAmB,MAAM,SAAS,OAAO,OAAO;EAAM,KAAK,OAAO;EAAY,OAAM;EAAiB,CAAA;AAIzG,QACE,oBAAC,aAAD;EAAoB;EAAO,GAAI;YAC7B,qBAAC,aAAa,MAAd;GAAyB;GAAM,GAAI;GAAa,WAAU;aAA1D;IACE,oBAAC,aAAa,OAAd;KAAyB;KAAK,GAAI;KAC/B;KACkB,CAAA;IACpB;IACD,oBAAC,aAAa,WAAd;KAAwB,SAAA;eACtB,oBAAC,oBAAD,EAAoB,eAAc,QAAS,CAAA;KACpB,CAAA;IACP;;EACR,CAAA;EAGnB;AAED,mBAAmB,cAAc"}
@@ -34,11 +34,9 @@ export type BitkitSelectMenuProps = {
34
34
  collection: ListCollection<BitkitSelectMenuItemProps>;
35
35
  /** Forwarded to the underlying Select/Combobox.Content. Kept for internal callers
36
36
  * (e.g. BitkitCalendar's in-grid selects that need to tweak max-height / width). The
37
- * three public components (BitkitSelect, BitkitCombobox, BitkitMultiselect) intentionally
38
- * do not expose this escape hatch. */
37
+ * public components (BitkitSelect, BitkitCombobox) do not expose this escape hatch. */
39
38
  contentProps?: SelectContentProps;
40
39
  isLoading?: boolean;
41
- multiple?: boolean;
42
40
  size?: 'md' | 'lg';
43
41
  variant?: 'select' | 'combobox';
44
42
  } & BitkitSelectMenuCreateItemProps & BitkitSelectMenuSearchProps & BitkitSelectMenuEmptyStateProps;
@@ -1,130 +1,54 @@
1
1
  import IconCheck from "../../icons/IconCheck.js";
2
- import IconCross from "../../icons/IconCross.js";
3
- import IconMagnifier from "../../icons/IconMagnifier.js";
4
- import IconPlus from "../../icons/IconPlus.js";
5
2
  import BitkitAvatar from "../BitkitAvatar/BitkitAvatar.js";
3
+ import { SelectMenuShell } from "./SelectMenuShell.js";
6
4
  import { Box } from "@chakra-ui/react/box";
7
- import { chakra, useSlotRecipe } from "@chakra-ui/react/styled-system";
5
+ import { useSlotRecipe } from "@chakra-ui/react/styled-system";
8
6
  import { Text } from "@chakra-ui/react/text";
9
7
  import { forwardRef } from "react";
10
- import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
11
9
  import { Spinner } from "@chakra-ui/react/spinner";
12
10
  import { Select } from "@chakra-ui/react/select";
13
11
  import { Combobox } from "@chakra-ui/react/combobox";
14
- import { Separator } from "@chakra-ui/react/separator";
15
12
  //#region lib/components/BitkitSelectMenu/BitkitSelectMenu.tsx
16
- /**
17
- * Zag's Select.Content keyDown handler fires ITEM.CLICK (selecting the highlighted item) and
18
- * preventDefaults on Enter/Space regardless of which descendant is focused. For the create
19
- * row (a real <button>/<a> sibling of the items list), that hijacks its native activation.
20
- * Stopping propagation at the element keeps its own onClick firing via the browser's native
21
- * keyboard-activation path.
22
- */
23
- var stopMenuSelectionKeys = (event) => {
24
- if (event.key === "Enter" || event.key === " ") event.stopPropagation();
25
- };
26
13
  var BitkitSelectMenu = forwardRef((props, ref) => {
27
- const { collection, contentProps = {}, createItemLabel = "Create item", emptyHelperText, emptyLabel = "No matching options", hasSearch = false, isLoading = false, multiple = false, onCreateItem, onSearchChange, searchValue, size, variant = "select" } = props;
14
+ const { collection, variant = "select", size, ...shellProps } = props;
28
15
  const NS = variant === "combobox" ? Combobox : Select;
29
16
  const styles = useSlotRecipe({ key: "select" })({ size });
30
17
  const iconSize = size === "md" ? "16" : "24";
31
- const isEmpty = collection.size === 0;
32
- const hasCreate = !!onCreateItem;
33
- return /* @__PURE__ */ jsxs(NS.Content, {
34
- css: styles.content,
35
- ref,
36
- ...contentProps,
37
- children: [
38
- !hasSearch && hasCreate && /* @__PURE__ */ jsx("span", {
39
- "data-autofocus": "",
40
- tabIndex: -1,
41
- "aria-hidden": "true"
42
- }),
43
- hasSearch && searchValue !== void 0 && onSearchChange && /* @__PURE__ */ jsx(SelectMenuSearch, {
44
- iconSize,
45
- styles,
46
- value: searchValue,
47
- onSearchChange
48
- }),
49
- /* @__PURE__ */ jsxs(Box, {
50
- css: styles.itemList,
51
- children: [
52
- isLoading && /* @__PURE__ */ jsxs(Box, {
53
- display: "flex",
54
- alignItems: "center",
55
- gap: "12",
56
- justifyContent: "left",
57
- css: styles.item,
58
- children: [/* @__PURE__ */ jsx(Spinner, { variant: "purple" }), /* @__PURE__ */ jsx(Text, {
59
- color: "text/secondary",
60
- textStyle: size === "md" ? "body/md/regular" : "body/lg/regular",
61
- children: "Loading..."
62
- })]
63
- }),
64
- !isLoading && isEmpty && /* @__PURE__ */ jsxs(Box, {
65
- css: styles.emptyState,
66
- children: [/* @__PURE__ */ jsx(Text, {
67
- css: styles.itemLabel,
68
- children: emptyLabel
69
- }), emptyHelperText && /* @__PURE__ */ jsx(Text, {
70
- css: styles.itemHelperText,
71
- children: emptyHelperText
72
- })]
73
- }),
74
- !isLoading && !isEmpty && collection.group().map(([type, group]) => /* @__PURE__ */ jsxs(NS.ItemGroup, { children: [type && /* @__PURE__ */ jsxs(NS.ItemGroupLabel, {
75
- css: styles.itemGroupLabel,
76
- children: [/* @__PURE__ */ jsx(Text, {
77
- color: "text/tertiary",
78
- flexShrink: "0",
79
- textStyle: "heading/h6",
80
- children: type
81
- }), /* @__PURE__ */ jsx(Separator, { flex: "1" })]
82
- }), group.map((item) => /* @__PURE__ */ jsx(SelectMenuItem, {
83
- NS,
84
- item,
85
- multiple,
86
- iconSize,
87
- styles
88
- }, item.value))] }, type))
89
- ]
90
- }),
91
- onCreateItem && /* @__PURE__ */ jsxs(chakra.button, {
92
- type: "button",
93
- css: styles.createItem,
94
- onClick: onCreateItem,
95
- onKeyDown: stopMenuSelectionKeys,
96
- children: [/* @__PURE__ */ jsx(IconPlus, {
97
- size: iconSize,
98
- color: "button/secondary/icon"
99
- }), createItemLabel]
100
- })
101
- ]
18
+ return /* @__PURE__ */ jsx(SelectMenuShell, {
19
+ NS,
20
+ collection,
21
+ contentRef: ref,
22
+ iconSize,
23
+ renderItem: (item) => /* @__PURE__ */ jsx(SelectMenuItem, {
24
+ NS,
25
+ item,
26
+ iconSize,
27
+ styles
28
+ }, item.value),
29
+ size,
30
+ styles,
31
+ ...shellProps
102
32
  });
103
33
  });
104
34
  BitkitSelectMenu.displayName = "BitkitSelectMenu";
105
- var SelectMenuItem = ({ NS, item, multiple, iconSize, styles }) => {
35
+ var SelectMenuItem = ({ NS, item, iconSize, styles }) => {
106
36
  const Icon = item.icon;
107
- const isLoading = !!item.loading;
108
- return /* @__PURE__ */ jsx(NS.Item, {
37
+ if (item.loading) return /* @__PURE__ */ jsxs(Box, {
109
38
  css: styles.item,
110
- item,
111
- children: isLoading ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Spinner, {
39
+ children: [/* @__PURE__ */ jsx(Spinner, {
112
40
  variant: "purple",
113
41
  css: styles.itemLoading
114
42
  }), /* @__PURE__ */ jsx(Text, {
115
43
  css: styles.itemLoadingLabel,
116
44
  children: "Loading..."
117
- })] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
118
- multiple && /* @__PURE__ */ jsx(Box, {
119
- css: styles.checkbox,
120
- "data-slot": "checkbox",
121
- children: /* @__PURE__ */ jsx(IconCheck, {
122
- size: "16",
123
- css: styles.checkmark,
124
- "data-slot": "checkmark"
125
- })
126
- }),
127
- !multiple && item.avatar && /* @__PURE__ */ jsx(Box, {
45
+ })]
46
+ });
47
+ return /* @__PURE__ */ jsxs(NS.Item, {
48
+ css: styles.item,
49
+ item,
50
+ children: [
51
+ item.avatar && /* @__PURE__ */ jsx(Box, {
128
52
  "data-slot": "avatar",
129
53
  css: { "[data-disabled] &": { opacity: .5 } },
130
54
  children: /* @__PURE__ */ jsx(BitkitAvatar, {
@@ -140,7 +64,7 @@ var SelectMenuItem = ({ NS, item, multiple, iconSize, styles }) => {
140
64
  display: "flex",
141
65
  alignItems: "center",
142
66
  gap: "8",
143
- children: [!multiple && !item.avatar && Icon && /* @__PURE__ */ jsx(Icon, {
67
+ children: [Icon && !item.avatar && /* @__PURE__ */ jsx(Icon, {
144
68
  color: "icon/primary",
145
69
  size: iconSize
146
70
  }), /* @__PURE__ */ jsx(Text, {
@@ -152,42 +76,16 @@ var SelectMenuItem = ({ NS, item, multiple, iconSize, styles }) => {
152
76
  children: item.helperText
153
77
  })]
154
78
  }),
155
- !multiple && /* @__PURE__ */ jsx(NS.ItemIndicator, {
79
+ /* @__PURE__ */ jsx(NS.ItemIndicator, {
156
80
  asChild: true,
157
81
  children: /* @__PURE__ */ jsx(IconCheck, {
158
82
  size: iconSize,
159
83
  css: styles.itemIndicator
160
84
  })
161
85
  })
162
- ] })
86
+ ]
163
87
  });
164
88
  };
165
- var SelectMenuSearch = ({ iconSize, onSearchChange, styles, value }) => /* @__PURE__ */ jsxs(Box, {
166
- css: styles.searchInputGroup,
167
- children: [
168
- /* @__PURE__ */ jsx(IconMagnifier, {
169
- size: iconSize,
170
- color: "icon/tertiary"
171
- }),
172
- /* @__PURE__ */ jsx(chakra.input, {
173
- "aria-label": "Search",
174
- css: styles.searchInput,
175
- placeholder: "Search...",
176
- value,
177
- onChange: (event) => onSearchChange(event.target.value),
178
- onKeyDown: (event) => {
179
- if (event.key === " ") event.stopPropagation();
180
- }
181
- }),
182
- value && /* @__PURE__ */ jsx(chakra.button, {
183
- type: "button",
184
- css: styles.searchClear,
185
- "aria-label": "Clear search",
186
- onClick: () => onSearchChange(""),
187
- children: /* @__PURE__ */ jsx(IconCross, { size: iconSize })
188
- })
189
- ]
190
- });
191
89
  //#endregion
192
90
  export { BitkitSelectMenu as default };
193
91
 
@@ -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 { Separator } from '@chakra-ui/react/separator';\nimport { Spinner } from '@chakra-ui/react/spinner';\nimport { chakra, type SystemStyleObject, useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { type ChangeEvent, forwardRef, type KeyboardEvent as ReactKeyboardEvent } from 'react';\n\nimport { type BitkitIconComponent, IconCheck, IconCross, IconMagnifier, IconPlus } from '../../icons';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\n\n/**\n * Zag's Select.Content keyDown handler fires ITEM.CLICK (selecting the highlighted item) and\n * preventDefaults on Enter/Space regardless of which descendant is focused. For the create\n * row (a real <button>/<a> sibling of the items list), that hijacks its native activation.\n * Stopping propagation at the element keeps its own onClick firing via the browser's native\n * keyboard-activation path.\n */\nconst stopMenuSelectionKeys = (event: ReactKeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.stopPropagation();\n }\n};\n\nexport type BitkitSelectMenuCreateItemProps = {\n createItemLabel?: string;\n onCreateItem?: () => void;\n};\n\nexport type BitkitSelectMenuSearchProps = {\n hasSearch?: boolean;\n} & (\n | {\n hasSearch: true;\n onSearchChange: (searchText: string) => void;\n searchValue: string;\n }\n | {\n hasSearch?: false;\n onSearchChange?: never;\n searchValue?: never;\n }\n);\n\nexport type BitkitSelectMenuItemProps = {\n value: string;\n label: string;\n group?: string;\n icon?: BitkitIconComponent;\n avatar?: string;\n helperText?: string;\n disabled?: boolean;\n loading?: boolean;\n};\n\nexport type BitkitSelectMenuEmptyStateProps = {\n emptyLabel?: string;\n emptyHelperText?: string;\n};\n\nexport type BitkitSelectMenuProps = {\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 * three public components (BitkitSelect, BitkitCombobox, BitkitMultiselect) intentionally\n * do not expose this escape hatch. */\n contentProps?: SelectContentProps;\n isLoading?: boolean;\n multiple?: boolean;\n size?: 'md' | 'lg';\n variant?: 'select' | 'combobox';\n} & BitkitSelectMenuCreateItemProps &\n BitkitSelectMenuSearchProps &\n BitkitSelectMenuEmptyStateProps;\n\nconst BitkitSelectMenu = forwardRef<HTMLDivElement, BitkitSelectMenuProps>((props: BitkitSelectMenuProps, ref) => {\n const {\n collection,\n contentProps = {},\n createItemLabel = 'Create item',\n emptyHelperText,\n emptyLabel = 'No matching options',\n hasSearch = false,\n isLoading = false,\n multiple = false,\n onCreateItem,\n onSearchChange,\n searchValue,\n size,\n variant = 'select',\n } = props;\n\n const NS = variant === 'combobox' ? Combobox : Select;\n\n const recipe = useSlotRecipe({ key: 'select' });\n const styles = recipe({ size });\n\n const iconSize = size === 'md' ? '16' : '24';\n const isEmpty = collection.size === 0;\n\n const hasCreate = !!onCreateItem;\n\n return (\n <NS.Content css={styles.content} ref={ref} {...contentProps}>\n {/*\n Without a search input, Zag's getInitialFocus (see @zag-js/dom-query) picks the first\n tabbable descendant as the menu's initial focus target — which would be the create\n button, visually confusing. A hidden [data-autofocus] span wins over tabbables in\n getInitialFocus's querySelector, so we focus an invisible element instead and Zag's\n aria-activedescendant drives the highlight like a normal Select would. When search\n is present, the search input naturally takes initial focus and this sentinel is\n unnecessary.\n */}\n {!hasSearch && hasCreate && <span data-autofocus=\"\" tabIndex={-1} aria-hidden=\"true\" />}\n {hasSearch && searchValue !== undefined && onSearchChange && (\n <SelectMenuSearch iconSize={iconSize} styles={styles} value={searchValue} onSearchChange={onSearchChange} />\n )}\n <Box css={styles.itemList}>\n {isLoading && (\n <Box display=\"flex\" alignItems=\"center\" gap=\"12\" justifyContent=\"left\" css={styles.item}>\n <Spinner variant=\"purple\" />\n <Text color=\"text/secondary\" textStyle={size === 'md' ? 'body/md/regular' : 'body/lg/regular'}>\n Loading...\n </Text>\n </Box>\n )}\n {!isLoading && isEmpty && (\n <Box css={styles.emptyState}>\n <Text css={styles.itemLabel}>{emptyLabel}</Text>\n {emptyHelperText && <Text css={styles.itemHelperText}>{emptyHelperText}</Text>}\n </Box>\n )}\n {!isLoading &&\n !isEmpty &&\n collection.group().map(([type, group]) => (\n <NS.ItemGroup key={type}>\n {type && (\n <NS.ItemGroupLabel css={styles.itemGroupLabel}>\n <Text color=\"text/tertiary\" flexShrink=\"0\" textStyle=\"heading/h6\">\n {type}\n </Text>\n <Separator flex=\"1\" />\n </NS.ItemGroupLabel>\n )}\n {group.map((item) => (\n <SelectMenuItem\n key={item.value}\n NS={NS}\n item={item}\n multiple={multiple}\n iconSize={iconSize}\n styles={styles}\n />\n ))}\n </NS.ItemGroup>\n ))}\n </Box>\n {onCreateItem && (\n <chakra.button type=\"button\" css={styles.createItem} onClick={onCreateItem} onKeyDown={stopMenuSelectionKeys}>\n <IconPlus size={iconSize} color=\"button/secondary/icon\" />\n {createItemLabel}\n </chakra.button>\n )}\n </NS.Content>\n );\n});\n\nBitkitSelectMenu.displayName = 'BitkitSelectMenu';\n\ntype SelectMenuItemRenderProps = {\n NS: typeof Select | typeof Combobox;\n item: BitkitSelectMenuItemProps;\n multiple: boolean;\n iconSize: '16' | '24';\n styles: Record<string, SystemStyleObject>;\n};\n\nconst SelectMenuItem = ({ NS, item, multiple, iconSize, styles }: SelectMenuItemRenderProps) => {\n const Icon = item.icon;\n const isLoading = !!item.loading;\n\n return (\n <NS.Item css={styles.item} item={item}>\n {isLoading ? (\n <>\n <Spinner variant=\"purple\" css={styles.itemLoading} />\n <Text css={styles.itemLoadingLabel}>Loading...</Text>\n </>\n ) : (\n <>\n {multiple && (\n <Box css={styles.checkbox} data-slot=\"checkbox\">\n <IconCheck size=\"16\" css={styles.checkmark} data-slot=\"checkmark\" />\n </Box>\n )}\n {!multiple && item.avatar && (\n <Box data-slot=\"avatar\" css={{ '[data-disabled] &': { opacity: 0.5 } }}>\n <BitkitAvatar\n variant=\"image\"\n src={item.avatar}\n name={item.label}\n size={iconSize === '24' ? '32' : '24'}\n />\n </Box>\n )}\n <Box css={styles.itemContent}>\n <Box display=\"flex\" alignItems=\"center\" gap=\"8\">\n {!multiple && !item.avatar && Icon && <Icon color=\"icon/primary\" 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 {!multiple && (\n <NS.ItemIndicator asChild>\n <IconCheck size={iconSize} css={styles.itemIndicator} />\n </NS.ItemIndicator>\n )}\n </>\n )}\n </NS.Item>\n );\n};\n\ntype SelectMenuSearchProps = {\n iconSize: '16' | '24';\n onSearchChange: (searchText: string) => void;\n styles: Record<string, SystemStyleObject>;\n value: string;\n};\n\nconst SelectMenuSearch = ({ iconSize, onSearchChange, styles, value }: SelectMenuSearchProps) => (\n <Box css={styles.searchInputGroup}>\n <IconMagnifier size={iconSize} color=\"icon/tertiary\" />\n <chakra.input\n aria-label=\"Search\"\n css={styles.searchInput}\n placeholder=\"Search...\"\n value={value}\n onChange={(event: ChangeEvent<HTMLInputElement>) => onSearchChange(event.target.value)}\n onKeyDown={(event) => {\n // Zag's Select.Content keyDown listener fires ITEM.CLICK + preventDefault on Space\n // regardless of which descendant is focused. That would eat the space before the\n // input can type it. Enter is left alone so \"type-then-Enter-to-select\" still works.\n if (event.key === ' ') event.stopPropagation();\n }}\n />\n {value && (\n <chakra.button\n type=\"button\"\n css={styles.searchClear}\n aria-label=\"Clear search\"\n onClick={() => onSearchChange('')}\n >\n <IconCross size={iconSize} />\n </chakra.button>\n )}\n </Box>\n);\n\nexport default BitkitSelectMenu;\n"],"mappings":"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"}
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 { forwardRef } from 'react';\n\nimport { type BitkitIconComponent, IconCheck } from '../../icons';\nimport BitkitAvatar from '../BitkitAvatar/BitkitAvatar';\nimport { SelectMenuShell } from './SelectMenuShell';\n\nexport type BitkitSelectMenuCreateItemProps = {\n createItemLabel?: string;\n onCreateItem?: () => void;\n};\n\nexport type BitkitSelectMenuSearchProps = {\n hasSearch?: boolean;\n} & (\n | {\n hasSearch: true;\n onSearchChange: (searchText: string) => void;\n searchValue: string;\n }\n | {\n hasSearch?: false;\n onSearchChange?: never;\n searchValue?: never;\n }\n);\n\nexport type BitkitSelectMenuItemProps = {\n value: string;\n label: string;\n group?: string;\n icon?: BitkitIconComponent;\n avatar?: string;\n helperText?: string;\n disabled?: boolean;\n loading?: boolean;\n};\n\nexport type BitkitSelectMenuEmptyStateProps = {\n emptyLabel?: string;\n emptyHelperText?: string;\n};\n\nexport type BitkitSelectMenuProps = {\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} & BitkitSelectMenuCreateItemProps &\n BitkitSelectMenuSearchProps &\n BitkitSelectMenuEmptyStateProps;\n\nconst BitkitSelectMenu = forwardRef<HTMLDivElement, BitkitSelectMenuProps>((props, ref) => {\n const { 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 iconSize = size === 'md' ? '16' : '24';\n\n return (\n <SelectMenuShell\n NS={NS}\n collection={collection}\n contentRef={ref}\n iconSize={iconSize}\n renderItem={(item) => <SelectMenuItem key={item.value} NS={NS} item={item} iconSize={iconSize} styles={styles} />}\n size={size}\n styles={styles}\n {...shellProps}\n />\n );\n});\n\nBitkitSelectMenu.displayName = 'BitkitSelectMenu';\n\ntype SelectMenuItemRenderProps = {\n NS: typeof Select | typeof Combobox;\n item: BitkitSelectMenuItemProps;\n iconSize: '16' | '24';\n styles: Record<string, SystemStyleObject>;\n};\n\nconst SelectMenuItem = ({ NS, item, iconSize, styles }: SelectMenuItemRenderProps) => {\n const Icon = item.icon;\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\" 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 {item.avatar && (\n <Box data-slot=\"avatar\" css={{ '[data-disabled] &': { opacity: 0.5 } }}>\n <BitkitAvatar variant=\"image\" src={item.avatar} name={item.label} size={iconSize === '24' ? '32' : '24'} />\n </Box>\n )}\n <Box css={styles.itemContent}>\n <Box display=\"flex\" alignItems=\"center\" gap=\"8\">\n {Icon && !item.avatar && <Icon color=\"icon/primary\" 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 <NS.ItemIndicator asChild>\n <IconCheck size={iconSize} css={styles.itemIndicator} />\n </NS.ItemIndicator>\n </NS.Item>\n );\n};\n\nexport default BitkitSelectMenu;\n"],"mappings":";;;;;;;;;;;;AA8DA,IAAM,mBAAmB,YAAmD,OAAO,QAAQ;CACzF,MAAM,EAAE,YAAY,UAAU,UAAU,MAAM,GAAG,eAAe;CAChE,MAAM,KAAK,YAAY,aAAa,WAAW;CAE/C,MAAM,SADS,cAAc,EAAE,KAAK,UAAU,CAAC,CACzB,EAAE,MAAM,CAAC;CAC/B,MAAM,WAAW,SAAS,OAAO,OAAO;AAExC,QACE,oBAAC,iBAAD;EACM;EACQ;EACZ,YAAY;EACF;EACV,aAAa,SAAS,oBAAC,gBAAD;GAAqC;GAAU;GAAgB;GAAkB;GAAU,EAAtE,KAAK,MAAiE;EAC3G;EACE;EACR,GAAI;EACJ,CAAA;EAEJ;AAEF,iBAAiB,cAAc;AAS/B,IAAM,kBAAkB,EAAE,IAAI,MAAM,UAAU,aAAwC;CACpF,MAAM,OAAO,KAAK;AAElB,KAAI,KAAK,QAGP,QACE,qBAAC,KAAD;EAAK,KAAK,OAAO;YAAjB,CACE,oBAAC,SAAD;GAAS,SAAQ;GAAS,KAAK,OAAO;GAAe,CAAA,EACrD,oBAAC,MAAD;GAAM,KAAK,OAAO;aAAkB;GAAiB,CAAA,CACjD;;AAIV,QACE,qBAAC,GAAG,MAAJ;EAAS,KAAK,OAAO;EAAY;YAAjC;GACG,KAAK,UACJ,oBAAC,KAAD;IAAK,aAAU;IAAS,KAAK,EAAE,qBAAqB,EAAE,SAAS,IAAK,EAAE;cACpE,oBAAC,cAAD;KAAc,SAAQ;KAAQ,KAAK,KAAK;KAAQ,MAAM,KAAK;KAAO,MAAM,aAAa,OAAO,OAAO;KAAQ,CAAA;IACvG,CAAA;GAER,qBAAC,KAAD;IAAK,KAAK,OAAO;cAAjB,CACE,qBAAC,KAAD;KAAK,SAAQ;KAAO,YAAW;KAAS,KAAI;eAA5C,CACG,QAAQ,CAAC,KAAK,UAAU,oBAAC,MAAD;MAAM,OAAM;MAAe,MAAM;MAAY,CAAA,EACtE,oBAAC,MAAD;MAAM,KAAK,OAAO;gBAAY,KAAK;MAAa,CAAA,CAC5C;QACL,KAAK,cAAc,oBAAC,MAAD;KAAM,KAAK,OAAO;eAAiB,KAAK;KAAkB,CAAA,CAC1E;;GACN,oBAAC,GAAG,eAAJ;IAAkB,SAAA;cAChB,oBAAC,WAAD;KAAW,MAAM;KAAU,KAAK,OAAO;KAAiB,CAAA;IACvC,CAAA;GACX"}
@@ -0,0 +1,29 @@
1
+ import { ListCollection } from '@chakra-ui/react/collection';
2
+ import { Combobox } from '@chakra-ui/react/combobox';
3
+ import { Select, SelectContentProps } from '@chakra-ui/react/select';
4
+ import { SystemStyleObject } from '@chakra-ui/react/styled-system';
5
+ import { ReactNode, Ref } from 'react';
6
+ import { BitkitSelectMenuCreateItemProps, BitkitSelectMenuEmptyStateProps, BitkitSelectMenuSearchProps } from './BitkitSelectMenu';
7
+ /**
8
+ * Internal shared shell for BitkitSelectMenu and BitkitMultiselectMenu.
9
+ * Handles Content wrapper, search, loading, empty state, groups, and create button —
10
+ * the caller only provides per-item rendering via renderItem.
11
+ */
12
+ export type SelectMenuShellProps<T extends {
13
+ value: string;
14
+ group?: string;
15
+ }> = {
16
+ NS: typeof Select | typeof Combobox;
17
+ collection: ListCollection<T>;
18
+ contentProps?: SelectContentProps;
19
+ contentRef?: Ref<HTMLDivElement>;
20
+ iconSize: '16' | '24';
21
+ isLoading?: boolean;
22
+ renderItem: (item: T) => ReactNode;
23
+ size?: 'md' | 'lg';
24
+ styles: Record<string, SystemStyleObject>;
25
+ } & BitkitSelectMenuCreateItemProps & BitkitSelectMenuSearchProps & BitkitSelectMenuEmptyStateProps;
26
+ export declare const SelectMenuShell: <T extends {
27
+ value: string;
28
+ group?: string;
29
+ }>({ NS, collection, contentProps, contentRef, createItemLabel, emptyHelperText, emptyLabel, hasSearch, iconSize, isLoading, onCreateItem, onSearchChange, renderItem, searchValue, size, styles, }: SelectMenuShellProps<T>) => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,115 @@
1
+ import IconCross from "../../icons/IconCross.js";
2
+ import IconMagnifier from "../../icons/IconMagnifier.js";
3
+ import IconPlus from "../../icons/IconPlus.js";
4
+ import BitkitGroupHeading from "../BitkitGroupHeading/BitkitGroupHeading.js";
5
+ import { Box } from "@chakra-ui/react/box";
6
+ import { chakra } from "@chakra-ui/react/styled-system";
7
+ import { Text } from "@chakra-ui/react/text";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ import { Spinner } from "@chakra-ui/react/spinner";
10
+ //#region lib/components/BitkitSelectMenu/SelectMenuShell.tsx
11
+ var SelectMenuShell = ({ NS, collection, contentProps, contentRef, createItemLabel = "Create item", emptyHelperText, emptyLabel = "No matching options", hasSearch = false, iconSize, isLoading = false, onCreateItem, onSearchChange, renderItem, searchValue, size, styles }) => {
12
+ const isEmpty = collection.size === 0;
13
+ return /* @__PURE__ */ jsxs(NS.Content, {
14
+ css: styles.content,
15
+ ref: contentRef,
16
+ ...contentProps,
17
+ children: [
18
+ !hasSearch && onCreateItem && /* @__PURE__ */ jsx("span", {
19
+ "data-autofocus": "",
20
+ tabIndex: -1,
21
+ "aria-hidden": "true"
22
+ }),
23
+ hasSearch && searchValue !== void 0 && onSearchChange && /* @__PURE__ */ jsx(SelectMenuSearch, {
24
+ iconSize,
25
+ styles,
26
+ value: searchValue,
27
+ onSearchChange
28
+ }),
29
+ /* @__PURE__ */ jsxs(Box, {
30
+ css: styles.itemList,
31
+ children: [
32
+ isLoading && /* @__PURE__ */ jsxs(Box, {
33
+ display: "flex",
34
+ alignItems: "center",
35
+ gap: "12",
36
+ justifyContent: "left",
37
+ css: styles.item,
38
+ children: [/* @__PURE__ */ jsx(Spinner, { variant: "purple" }), /* @__PURE__ */ jsx(Text, {
39
+ color: "text/secondary",
40
+ textStyle: size === "md" ? "body/md/regular" : "body/lg/regular",
41
+ children: "Loading..."
42
+ })]
43
+ }),
44
+ !isLoading && isEmpty && /* @__PURE__ */ jsxs(Box, {
45
+ css: styles.emptyState,
46
+ children: [/* @__PURE__ */ jsx(Text, {
47
+ css: styles.itemLabel,
48
+ children: emptyLabel
49
+ }), emptyHelperText && /* @__PURE__ */ jsx(Text, {
50
+ css: styles.itemHelperText,
51
+ children: emptyHelperText
52
+ })]
53
+ }),
54
+ !isLoading && !isEmpty && collection.group().map(([type, group]) => /* @__PURE__ */ jsxs(NS.ItemGroup, { children: [type && /* @__PURE__ */ jsx(NS.ItemGroupLabel, {
55
+ asChild: true,
56
+ children: /* @__PURE__ */ jsx(BitkitGroupHeading, {
57
+ label: type,
58
+ paddingBlock: "12",
59
+ paddingInline: "16"
60
+ })
61
+ }), group.map(renderItem)] }, type))
62
+ ]
63
+ }),
64
+ onCreateItem && /* @__PURE__ */ jsxs(chakra.button, {
65
+ type: "button",
66
+ css: styles.createItem,
67
+ onClick: onCreateItem,
68
+ onKeyDown: stopMenuSelectionKeys,
69
+ children: [/* @__PURE__ */ jsx(IconPlus, {
70
+ size: iconSize,
71
+ color: "button/secondary/icon"
72
+ }), createItemLabel]
73
+ })
74
+ ]
75
+ });
76
+ };
77
+ /**
78
+ * Zag's Select.Content keyDown handler fires ITEM.CLICK and preventDefaults on Enter/Space
79
+ * regardless of which descendant is focused. For the create row (a real <button> sibling of
80
+ * the items list), that hijacks its native activation. Stopping propagation at the element
81
+ * keeps its own onClick firing via the browser's native keyboard-activation path.
82
+ */
83
+ var stopMenuSelectionKeys = (event) => {
84
+ if (event.key === "Enter" || event.key === " ") event.stopPropagation();
85
+ };
86
+ var SelectMenuSearch = ({ iconSize, onSearchChange, styles, value }) => /* @__PURE__ */ jsxs(Box, {
87
+ css: styles.searchInputGroup,
88
+ children: [
89
+ /* @__PURE__ */ jsx(IconMagnifier, {
90
+ size: iconSize,
91
+ color: "icon/tertiary"
92
+ }),
93
+ /* @__PURE__ */ jsx(chakra.input, {
94
+ "aria-label": "Search",
95
+ css: styles.searchInput,
96
+ placeholder: "Search...",
97
+ value,
98
+ onChange: (event) => onSearchChange(event.target.value),
99
+ onKeyDown: (event) => {
100
+ if (event.key === " ") event.stopPropagation();
101
+ }
102
+ }),
103
+ value && /* @__PURE__ */ jsx(chakra.button, {
104
+ type: "button",
105
+ css: styles.searchClear,
106
+ "aria-label": "Clear search",
107
+ onClick: () => onSearchChange(""),
108
+ children: /* @__PURE__ */ jsx(IconCross, { size: iconSize })
109
+ })
110
+ ]
111
+ });
112
+ //#endregion
113
+ export { SelectMenuShell };
114
+
115
+ //# sourceMappingURL=SelectMenuShell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SelectMenuShell.js","names":[],"sources":["../../../lib/components/BitkitSelectMenu/SelectMenuShell.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport { type ListCollection } from '@chakra-ui/react/collection';\nimport { type Combobox } from '@chakra-ui/react/combobox';\nimport { type Select, type SelectContentProps } from '@chakra-ui/react/select';\nimport { Spinner } from '@chakra-ui/react/spinner';\nimport { chakra, type SystemStyleObject } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { type ChangeEvent, type KeyboardEvent as ReactKeyboardEvent, type ReactNode, type Ref } from 'react';\n\nimport { IconCross, IconMagnifier, IconPlus } from '../../icons';\nimport BitkitGroupHeading from '../BitkitGroupHeading/BitkitGroupHeading';\nimport {\n type BitkitSelectMenuCreateItemProps,\n type BitkitSelectMenuEmptyStateProps,\n type BitkitSelectMenuSearchProps,\n} from './BitkitSelectMenu';\n\n/**\n * Internal shared shell for BitkitSelectMenu and BitkitMultiselectMenu.\n * Handles Content wrapper, search, loading, empty state, groups, and create button —\n * the caller only provides per-item rendering via renderItem.\n */\nexport type SelectMenuShellProps<T extends { value: string; group?: string }> = {\n NS: typeof Select | typeof Combobox;\n collection: ListCollection<T>;\n contentProps?: SelectContentProps;\n contentRef?: Ref<HTMLDivElement>;\n iconSize: '16' | '24';\n isLoading?: boolean;\n renderItem: (item: T) => ReactNode;\n size?: 'md' | 'lg';\n styles: Record<string, SystemStyleObject>;\n} & BitkitSelectMenuCreateItemProps &\n BitkitSelectMenuSearchProps &\n BitkitSelectMenuEmptyStateProps;\n\nexport const SelectMenuShell = <T extends { value: string; group?: string }>({\n NS,\n collection,\n contentProps,\n contentRef,\n createItemLabel = 'Create item',\n emptyHelperText,\n emptyLabel = 'No matching options',\n hasSearch = false,\n iconSize,\n isLoading = false,\n onCreateItem,\n onSearchChange,\n renderItem,\n searchValue,\n size,\n styles,\n}: SelectMenuShellProps<T>) => {\n const isEmpty = collection.size === 0;\n\n return (\n <NS.Content css={styles.content} ref={contentRef} {...contentProps}>\n {/*\n Without a search input, Zag's getInitialFocus (see @zag-js/dom-query) picks the first\n tabbable descendant as the menu's initial focus target — which would be the create\n button, visually confusing. A hidden [data-autofocus] span wins over tabbables in\n getInitialFocus's querySelector, so we focus an invisible element instead and Zag's\n aria-activedescendant drives the highlight like a normal Select would.\n */}\n {!hasSearch && onCreateItem && <span data-autofocus=\"\" tabIndex={-1} aria-hidden=\"true\" />}\n {hasSearch && searchValue !== undefined && onSearchChange && (\n <SelectMenuSearch iconSize={iconSize} styles={styles} value={searchValue} onSearchChange={onSearchChange} />\n )}\n <Box css={styles.itemList}>\n {isLoading && (\n <Box display=\"flex\" alignItems=\"center\" gap=\"12\" justifyContent=\"left\" css={styles.item}>\n <Spinner variant=\"purple\" />\n <Text color=\"text/secondary\" textStyle={size === 'md' ? 'body/md/regular' : 'body/lg/regular'}>\n Loading...\n </Text>\n </Box>\n )}\n {!isLoading && isEmpty && (\n <Box css={styles.emptyState}>\n <Text css={styles.itemLabel}>{emptyLabel}</Text>\n {emptyHelperText && <Text css={styles.itemHelperText}>{emptyHelperText}</Text>}\n </Box>\n )}\n {!isLoading &&\n !isEmpty &&\n collection.group().map(([type, group]) => (\n <NS.ItemGroup key={type}>\n {type && (\n <NS.ItemGroupLabel asChild>\n <BitkitGroupHeading label={type} paddingBlock=\"12\" paddingInline=\"16\" />\n </NS.ItemGroupLabel>\n )}\n {group.map(renderItem)}\n </NS.ItemGroup>\n ))}\n </Box>\n {onCreateItem && (\n <chakra.button type=\"button\" css={styles.createItem} onClick={onCreateItem} onKeyDown={stopMenuSelectionKeys}>\n <IconPlus size={iconSize} color=\"button/secondary/icon\" />\n {createItemLabel}\n </chakra.button>\n )}\n </NS.Content>\n );\n};\n\n/**\n * Zag's Select.Content keyDown handler fires ITEM.CLICK and preventDefaults on Enter/Space\n * regardless of which descendant is focused. For the create row (a real <button> sibling of\n * the items list), that hijacks its native activation. Stopping propagation at the element\n * keeps its own onClick firing via the browser's native keyboard-activation path.\n */\nconst stopMenuSelectionKeys = (event: ReactKeyboardEvent) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.stopPropagation();\n }\n};\n\ntype SelectMenuSearchProps = {\n iconSize: '16' | '24';\n onSearchChange: (searchText: string) => void;\n styles: Record<string, SystemStyleObject>;\n value: string;\n};\n\nconst SelectMenuSearch = ({ iconSize, onSearchChange, styles, value }: SelectMenuSearchProps) => (\n <Box css={styles.searchInputGroup}>\n <IconMagnifier size={iconSize} color=\"icon/tertiary\" />\n <chakra.input\n aria-label=\"Search\"\n css={styles.searchInput}\n placeholder=\"Search...\"\n value={value}\n onChange={(event: ChangeEvent<HTMLInputElement>) => onSearchChange(event.target.value)}\n onKeyDown={(event) => {\n // Zag's Select.Content keyDown listener fires ITEM.CLICK + preventDefault on Space\n // regardless of which descendant is focused. That would eat the space before the\n // input can type it. Enter is left alone so \"type-then-Enter-to-select\" still works.\n if (event.key === ' ') event.stopPropagation();\n }}\n />\n {value && (\n <chakra.button\n type=\"button\"\n css={styles.searchClear}\n aria-label=\"Clear search\"\n onClick={() => onSearchChange('')}\n >\n <IconCross size={iconSize} />\n </chakra.button>\n )}\n </Box>\n);\n"],"mappings":";;;;;;;;;;AAoCA,IAAa,mBAAgE,EAC3E,IACA,YACA,cACA,YACA,kBAAkB,eAClB,iBACA,aAAa,uBACb,YAAY,OACZ,UACA,YAAY,OACZ,cACA,gBACA,YACA,aACA,MACA,aAC6B;CAC7B,MAAM,UAAU,WAAW,SAAS;AAEpC,QACE,qBAAC,GAAG,SAAJ;EAAY,KAAK,OAAO;EAAS,KAAK;EAAY,GAAI;YAAtD;GAQG,CAAC,aAAa,gBAAgB,oBAAC,QAAD;IAAM,kBAAe;IAAG,UAAU;IAAI,eAAY;IAAS,CAAA;GACzF,aAAa,gBAAgB,KAAA,KAAa,kBACzC,oBAAC,kBAAD;IAA4B;IAAkB;IAAQ,OAAO;IAA6B;IAAkB,CAAA;GAE9G,qBAAC,KAAD;IAAK,KAAK,OAAO;cAAjB;KACG,aACC,qBAAC,KAAD;MAAK,SAAQ;MAAO,YAAW;MAAS,KAAI;MAAK,gBAAe;MAAO,KAAK,OAAO;gBAAnF,CACE,oBAAC,SAAD,EAAS,SAAQ,UAAW,CAAA,EAC5B,oBAAC,MAAD;OAAM,OAAM;OAAiB,WAAW,SAAS,OAAO,oBAAoB;iBAAmB;OAExF,CAAA,CACH;;KAEP,CAAC,aAAa,WACb,qBAAC,KAAD;MAAK,KAAK,OAAO;gBAAjB,CACE,oBAAC,MAAD;OAAM,KAAK,OAAO;iBAAY;OAAkB,CAAA,EAC/C,mBAAmB,oBAAC,MAAD;OAAM,KAAK,OAAO;iBAAiB;OAAuB,CAAA,CAC1E;;KAEP,CAAC,aACA,CAAC,WACD,WAAW,OAAO,CAAC,KAAK,CAAC,MAAM,WAC7B,qBAAC,GAAG,WAAJ,EAAA,UAAA,CACG,QACC,oBAAC,GAAG,gBAAJ;MAAmB,SAAA;gBACjB,oBAAC,oBAAD;OAAoB,OAAO;OAAM,cAAa;OAAK,eAAc;OAAO,CAAA;MACtD,CAAA,EAErB,MAAM,IAAI,WAAW,CACT,EAAA,EAPI,KAOJ,CACf;KACA;;GACL,gBACC,qBAAC,OAAO,QAAR;IAAe,MAAK;IAAS,KAAK,OAAO;IAAY,SAAS;IAAc,WAAW;cAAvF,CACE,oBAAC,UAAD;KAAU,MAAM;KAAU,OAAM;KAA0B,CAAA,EACzD,gBACa;;GAEP;;;;;;;;;AAUjB,IAAM,yBAAyB,UAA8B;AAC3D,KAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,IACzC,OAAM,iBAAiB;;AAW3B,IAAM,oBAAoB,EAAE,UAAU,gBAAgB,QAAQ,YAC5D,qBAAC,KAAD;CAAK,KAAK,OAAO;WAAjB;EACE,oBAAC,eAAD;GAAe,MAAM;GAAU,OAAM;GAAkB,CAAA;EACvD,oBAAC,OAAO,OAAR;GACE,cAAW;GACX,KAAK,OAAO;GACZ,aAAY;GACL;GACP,WAAW,UAAyC,eAAe,MAAM,OAAO,MAAM;GACtF,YAAY,UAAU;AAIpB,QAAI,MAAM,QAAQ,IAAK,OAAM,iBAAiB;;GAEhD,CAAA;EACD,SACC,oBAAC,OAAO,QAAR;GACE,MAAK;GACL,KAAK,OAAO;GACZ,cAAW;GACX,eAAe,eAAe,GAAG;aAEjC,oBAAC,WAAD,EAAW,MAAM,UAAY,CAAA;GACf,CAAA;EAEd"}
@@ -38,6 +38,7 @@ export { default as BitkitLinkButton, type BitkitLinkButtonProps } from './Bitki
38
38
  export { default as BitkitMarkdown, type BitkitMarkdownProps } from './BitkitMarkdown/BitkitMarkdown';
39
39
  export { default as BitkitMarkdownCard, type BitkitMarkdownCardProps } from './BitkitMarkdownCard/BitkitMarkdownCard';
40
40
  export { default as BitkitMultiselect, type BitkitMultiselectProps } from './BitkitMultiselect/BitkitMultiselect';
41
+ export { default as BitkitMultiselectMenu, type BitkitMultiselectMenuItemProps, type BitkitMultiselectMenuProps, } from './BitkitMultiselectMenu/BitkitMultiselectMenu';
41
42
  export { default as BitkitNativeSelect, type BitkitNativeSelectProps } from './BitkitNativeSelect/BitkitNativeSelect';
42
43
  export { default as BitkitNoteCard, type BitkitNoteCardProps } from './BitkitNoteCard/BitkitNoteCard';
43
44
  export { default as BitkitNumberInput, type BitkitNumberInputProps } from './BitkitNumberInput/BitkitNumberInput';
package/dist/main.js CHANGED
@@ -288,6 +288,7 @@ import BitkitAlert from "./components/BitkitAlert/BitkitAlert.js";
288
288
  import BitkitAvatar from "./components/BitkitAvatar/BitkitAvatar.js";
289
289
  import BitkitBadge from "./components/BitkitBadge/BitkitBadge.js";
290
290
  import BitkitButton from "./components/BitkitButton/BitkitButton.js";
291
+ import BitkitGroupHeading from "./components/BitkitGroupHeading/BitkitGroupHeading.js";
291
292
  import BitkitSelectMenu from "./components/BitkitSelectMenu/BitkitSelectMenu.js";
292
293
  import BitkitCalendar from "./components/BitkitCalendar/BitkitCalendar.js";
293
294
  import BitkitCard from "./components/BitkitCard/BitkitCard.js";
@@ -312,7 +313,6 @@ import BitkitEmptyState from "./components/BitkitEmptyState/BitkitEmptyState.js"
312
313
  import BitkitExpandableCard from "./components/BitkitExpandableCard/BitkitExpandableCard.js";
313
314
  import BitkitExplainerList_default from "./components/BitkitExplainerList/BitkitExplainerList.js";
314
315
  import BitkitFileInput from "./components/BitkitFileInput/BitkitFileInput.js";
315
- import BitkitGroupHeading from "./components/BitkitGroupHeading/BitkitGroupHeading.js";
316
316
  import BitkitIconButton from "./components/BitkitIconButton/BitkitIconButton.js";
317
317
  import BitkitInlineLoading from "./components/BitkitInlineLoading/BitkitInlineLoading.js";
318
318
  import BitkitLabeledData from "./components/BitkitLabeledData/BitkitLabeledData.js";
@@ -322,6 +322,7 @@ import BitkitOrderedList_default from "./components/BitkitOrderedList/BitkitOrde
322
322
  import BitkitUnorderedList_default from "./components/BitkitUnorderedList/BitkitUnorderedList.js";
323
323
  import BitkitMarkdown from "./components/BitkitMarkdown/BitkitMarkdown.js";
324
324
  import BitkitMarkdownCard from "./components/BitkitMarkdownCard/BitkitMarkdownCard.js";
325
+ import BitkitMultiselectMenu from "./components/BitkitMultiselectMenu/BitkitMultiselectMenu.js";
325
326
  import BitkitTag from "./components/BitkitTag/BitkitTag.js";
326
327
  import BitkitMultiselect from "./components/BitkitMultiselect/BitkitMultiselect.js";
327
328
  import BitkitNativeSelect from "./components/BitkitNativeSelect/BitkitNativeSelect.js";
@@ -355,4 +356,4 @@ import BitkitToggleButton from "./components/BitkitToggleButton/BitkitToggleButt
355
356
  import BitkitTreeView, { createTreeCollection } from "./components/BitkitTreeView/BitkitTreeView.js";
356
357
  import bitkitTheme from "./theme/index.js";
357
358
  import Provider from "./providers/BitkitProvider.js";
358
- export { BitkitAccordion, BitkitActionBar, BitkitAlert, BitkitAvatar, BitkitBadge, BitkitButton, BitkitCalendar, BitkitCard, BitkitCheckbox, BitkitCheckboxGroup, BitkitCloseButton, BitkitCodeSnippet, BitkitCollapsible, BitkitColorButton, BitkitCombobox, BitkitControlButton, BitkitDefinitionTooltip, BitkitDialog, BitkitDialogBody, BitkitDialogButtons, BitkitDialogContent, BitkitDialogRoot, BitkitDraggableCard, BitkitDrawer, BitkitEmptyState, BitkitExpandableCard, BitkitExplainerList_default as BitkitExplainerList, BitkitField, BitkitFileInput, BitkitGroupHeading, BitkitIconButton, BitkitInlineLoading, BitkitLabel, BitkitLabelTooltip, BitkitLabeledData, BitkitLink, BitkitLinkButton, BitkitMarkdown, BitkitMarkdownCard, BitkitMultiselect, BitkitNativeSelect, BitkitNoteCard, BitkitNumberInput, BitkitOrderedList_default as BitkitOrderedList, BitkitOverflowContent, BitkitOverflowTooltip, BitkitPageFooter_default as BitkitPageFooter, BitkitPagination, BitkitPaginationLoadMore, Provider as BitkitProvider, BitkitRadio, BitkitRadioGroup, BitkitRibbon, BitkitSearchInput, BitkitSectionHeading, BitkitSegmentedControl_default as BitkitSegmentedControl, BitkitSelect, BitkitSelectMenu, BitkitSelectableTag_default as BitkitSelectableTag, BitkitSettingsCard_default as BitkitSettingsCard, BitkitSidebar_default as BitkitSidebar, BitkitSplitButton_default as BitkitSplitButton, BitkitStat, BitkitSteps_default as BitkitSteps, BitkitStepsCard_default as BitkitStepsCard, BitkitTabs, BitkitTag, BitkitTagsInput, BitkitTextInput, BitkitToggle, BitkitToggleButton, BitkitTooltip, BitkitTreeView, BitkitUnorderedList_default as BitkitUnorderedList, IconAbortCircle, IconAbortCircleFilled, IconAddons, IconAgent, IconAnchor, IconAndroid, IconApp, IconAppSettings, IconAppStore, IconAppStoreColor, IconApple, IconArchive, IconArchiveDelete, IconArchiveRestore, IconArrowBackAndDown, IconArrowBackAndUp, IconArrowDown, IconArrowForwardAndDown, IconArrowForwardAndUp, IconArrowLeft, IconArrowNortheast, IconArrowNorthwest, IconArrowRight, IconArrowUp, IconArrowsHorizontal, IconArrowsVertical, IconAutomation, IconAws, IconAwsColor, IconBadge3RdParty, IconBadgeBitrise, IconBadgeUpgrade, IconBadgeVersionOk, IconBazel, IconBell, IconBitbot, IconBitbotError, IconBitbucket, IconBitbucketColor, IconBitbucketNeutral, IconBitbucketWhite, IconBlockCircle, IconBook, IconBoxArrowDown, IconBoxDot, IconBoxLinesOverflow, IconBoxLinesWrap, IconBranch, IconBrowserstackColor, IconBug, IconBuild, IconBuildCache, IconBuildCacheFilled, IconBuildEnvSetup, IconCalendar, IconChangePlan, IconChat, IconCheck, IconCheckCircle, IconCheckCircleFilled, IconChevronDown, IconChevronLeft, IconChevronRight, IconChevronUp, IconCi, IconCiFilled, IconCircle, IconCircleDashed, IconCircleHalfFilled, IconClaude, IconClaudeColor, IconClock, IconCode, IconCodePush, IconCodeSigning, IconCoffee, IconCommit, IconConfigure, IconConnectedAccounts, IconContainer, IconCopy, IconCordova, IconCpu, IconCreditcard, IconCredits, IconCross, IconCrossCircle, IconCrossCircleFilled, IconCrown, IconCycle, IconDashboard, IconDashboardFilled, IconDeployment, IconDetails, IconDoc, IconDollar, IconDot, IconDotnet, IconDotnetColor, IconDotnetText, IconDotnetTextColor, IconDoubleCircle, IconDownload, IconDragHandle, IconEc2Ami, IconEnterprise, IconErrorCircle, IconErrorCircleFilled, IconExpand, IconExtraBuildCapacity, IconEye, IconEyeSlash, IconFastlane, IconFileDoc, IconFilePdf, IconFilePlist, IconFileZip, IconFilter, IconFlag, IconFlutter, IconFolder, IconFullscreen, IconFullscreenExit, IconGauge, IconGit, IconGithub, IconGitlab, IconGitlabColor, IconGitlabWhite, IconGlobe, IconGo, IconGoogleColor, IconGooglePlay, IconGooglePlayColor, IconGradle, IconGroup, IconHashtag, IconHeadset, IconHeart, IconHistory, IconHourglass, IconImage, IconInfoCircle, IconInfoCircleFilled, IconInsights, IconInsightsFilled, IconInstall, IconInteraction, IconInvoice, IconIonic, IconJapanese, IconJava, IconJavaColor, IconJavaDuke, IconJavaDukeColor, IconKey, IconKotlin, IconKotlinColor, IconKotlinWhite, IconLaptop, IconLaunchdarkly, IconLegacyApp, IconLightbulb, IconLink, IconLinux, IconLock, IconLockOpen, IconLogin, IconLogout, IconMacos, IconMagicWand, IconMagnifier, IconMail, IconMedal, IconMemory, IconMenuGrid, IconMenuHamburger, IconMessage, IconMessageAlert, IconMessageQuestion, IconMicrophone, IconMinus, IconMinusCircle, IconMinusCircleFilled, IconMobile, IconMobileLandscape, IconMonitorChart, IconMoreHorizontal, IconMoreVertical, IconNews, IconNextjs, IconNodejs, IconOpenInNew, IconOther, IconOutsideContributor, IconOverview, IconPause, IconPencil, IconPeople, IconPercent, IconPerson, IconPersonWithDesk, IconPlay, IconPlus, IconPlusCircle, IconPlusCircleFilled, IconPower, IconProject, IconProjectSettings, IconPull, IconPush, IconPuzzle, IconPython, IconPythonColor, IconQuestionCircle, IconQuestionCircleFilled, IconReact, IconRefresh, IconRegex, IconRelease, IconReleaseFilled, IconRemoteAccess, IconReplace, IconResponsiveness, IconReviewerApproved, IconReviewerAssigned, IconReviewerRejected, IconRuby, IconRubyColor, IconSave, IconSecurityShield, IconSettings, IconSettingsFilled, IconShuffle, IconSiren, IconSkip, IconSkipCircle, IconSkipCircleFilled, IconSlack, IconSlackColor, IconSparkle, IconSparkleFilled, IconSpinnerOnDisabled, IconSpinnerPurple, IconSpinnerPurpleDouble, IconSpinnerWhite, IconStability, IconStack, IconStar, IconStep, IconStop, IconStopwatch, IconTag, IconTasks, IconTeams, IconTeamsColor, IconTemplateCode, IconTerminal, IconTestQuarantine, IconThemeDarkToggle, IconThumbDown, IconThumbUp, IconTools, IconTrash, IconTrigger, IconUbuntu, IconUbuntuColor, IconUnity3D, IconUpload, IconValidateShield, IconVideo, IconWarning, IconWarningYellow, IconWebUi, IconWebhooks, IconWorkflow, IconWorkflowFlow, IconXTwitter, IconXamarin, IconXcode, bitkitIcon, bitkitTheme as bitriseTheme, createBitkitToast, createTreeCollection };
359
+ export { BitkitAccordion, BitkitActionBar, BitkitAlert, BitkitAvatar, BitkitBadge, BitkitButton, BitkitCalendar, BitkitCard, BitkitCheckbox, BitkitCheckboxGroup, BitkitCloseButton, BitkitCodeSnippet, BitkitCollapsible, BitkitColorButton, BitkitCombobox, BitkitControlButton, BitkitDefinitionTooltip, BitkitDialog, BitkitDialogBody, BitkitDialogButtons, BitkitDialogContent, BitkitDialogRoot, BitkitDraggableCard, BitkitDrawer, BitkitEmptyState, BitkitExpandableCard, BitkitExplainerList_default as BitkitExplainerList, BitkitField, BitkitFileInput, BitkitGroupHeading, BitkitIconButton, BitkitInlineLoading, BitkitLabel, BitkitLabelTooltip, BitkitLabeledData, BitkitLink, BitkitLinkButton, BitkitMarkdown, BitkitMarkdownCard, BitkitMultiselect, BitkitMultiselectMenu, BitkitNativeSelect, BitkitNoteCard, BitkitNumberInput, BitkitOrderedList_default as BitkitOrderedList, BitkitOverflowContent, BitkitOverflowTooltip, BitkitPageFooter_default as BitkitPageFooter, BitkitPagination, BitkitPaginationLoadMore, Provider as BitkitProvider, BitkitRadio, BitkitRadioGroup, BitkitRibbon, BitkitSearchInput, BitkitSectionHeading, BitkitSegmentedControl_default as BitkitSegmentedControl, BitkitSelect, BitkitSelectMenu, BitkitSelectableTag_default as BitkitSelectableTag, BitkitSettingsCard_default as BitkitSettingsCard, BitkitSidebar_default as BitkitSidebar, BitkitSplitButton_default as BitkitSplitButton, BitkitStat, BitkitSteps_default as BitkitSteps, BitkitStepsCard_default as BitkitStepsCard, BitkitTabs, BitkitTag, BitkitTagsInput, BitkitTextInput, BitkitToggle, BitkitToggleButton, BitkitTooltip, BitkitTreeView, BitkitUnorderedList_default as BitkitUnorderedList, IconAbortCircle, IconAbortCircleFilled, IconAddons, IconAgent, IconAnchor, IconAndroid, IconApp, IconAppSettings, IconAppStore, IconAppStoreColor, IconApple, IconArchive, IconArchiveDelete, IconArchiveRestore, IconArrowBackAndDown, IconArrowBackAndUp, IconArrowDown, IconArrowForwardAndDown, IconArrowForwardAndUp, IconArrowLeft, IconArrowNortheast, IconArrowNorthwest, IconArrowRight, IconArrowUp, IconArrowsHorizontal, IconArrowsVertical, IconAutomation, IconAws, IconAwsColor, IconBadge3RdParty, IconBadgeBitrise, IconBadgeUpgrade, IconBadgeVersionOk, IconBazel, IconBell, IconBitbot, IconBitbotError, IconBitbucket, IconBitbucketColor, IconBitbucketNeutral, IconBitbucketWhite, IconBlockCircle, IconBook, IconBoxArrowDown, IconBoxDot, IconBoxLinesOverflow, IconBoxLinesWrap, IconBranch, IconBrowserstackColor, IconBug, IconBuild, IconBuildCache, IconBuildCacheFilled, IconBuildEnvSetup, IconCalendar, IconChangePlan, IconChat, IconCheck, IconCheckCircle, IconCheckCircleFilled, IconChevronDown, IconChevronLeft, IconChevronRight, IconChevronUp, IconCi, IconCiFilled, IconCircle, IconCircleDashed, IconCircleHalfFilled, IconClaude, IconClaudeColor, IconClock, IconCode, IconCodePush, IconCodeSigning, IconCoffee, IconCommit, IconConfigure, IconConnectedAccounts, IconContainer, IconCopy, IconCordova, IconCpu, IconCreditcard, IconCredits, IconCross, IconCrossCircle, IconCrossCircleFilled, IconCrown, IconCycle, IconDashboard, IconDashboardFilled, IconDeployment, IconDetails, IconDoc, IconDollar, IconDot, IconDotnet, IconDotnetColor, IconDotnetText, IconDotnetTextColor, IconDoubleCircle, IconDownload, IconDragHandle, IconEc2Ami, IconEnterprise, IconErrorCircle, IconErrorCircleFilled, IconExpand, IconExtraBuildCapacity, IconEye, IconEyeSlash, IconFastlane, IconFileDoc, IconFilePdf, IconFilePlist, IconFileZip, IconFilter, IconFlag, IconFlutter, IconFolder, IconFullscreen, IconFullscreenExit, IconGauge, IconGit, IconGithub, IconGitlab, IconGitlabColor, IconGitlabWhite, IconGlobe, IconGo, IconGoogleColor, IconGooglePlay, IconGooglePlayColor, IconGradle, IconGroup, IconHashtag, IconHeadset, IconHeart, IconHistory, IconHourglass, IconImage, IconInfoCircle, IconInfoCircleFilled, IconInsights, IconInsightsFilled, IconInstall, IconInteraction, IconInvoice, IconIonic, IconJapanese, IconJava, IconJavaColor, IconJavaDuke, IconJavaDukeColor, IconKey, IconKotlin, IconKotlinColor, IconKotlinWhite, IconLaptop, IconLaunchdarkly, IconLegacyApp, IconLightbulb, IconLink, IconLinux, IconLock, IconLockOpen, IconLogin, IconLogout, IconMacos, IconMagicWand, IconMagnifier, IconMail, IconMedal, IconMemory, IconMenuGrid, IconMenuHamburger, IconMessage, IconMessageAlert, IconMessageQuestion, IconMicrophone, IconMinus, IconMinusCircle, IconMinusCircleFilled, IconMobile, IconMobileLandscape, IconMonitorChart, IconMoreHorizontal, IconMoreVertical, IconNews, IconNextjs, IconNodejs, IconOpenInNew, IconOther, IconOutsideContributor, IconOverview, IconPause, IconPencil, IconPeople, IconPercent, IconPerson, IconPersonWithDesk, IconPlay, IconPlus, IconPlusCircle, IconPlusCircleFilled, IconPower, IconProject, IconProjectSettings, IconPull, IconPush, IconPuzzle, IconPython, IconPythonColor, IconQuestionCircle, IconQuestionCircleFilled, IconReact, IconRefresh, IconRegex, IconRelease, IconReleaseFilled, IconRemoteAccess, IconReplace, IconResponsiveness, IconReviewerApproved, IconReviewerAssigned, IconReviewerRejected, IconRuby, IconRubyColor, IconSave, IconSecurityShield, IconSettings, IconSettingsFilled, IconShuffle, IconSiren, IconSkip, IconSkipCircle, IconSkipCircleFilled, IconSlack, IconSlackColor, IconSparkle, IconSparkleFilled, IconSpinnerOnDisabled, IconSpinnerPurple, IconSpinnerPurpleDouble, IconSpinnerWhite, IconStability, IconStack, IconStar, IconStep, IconStop, IconStopwatch, IconTag, IconTasks, IconTeams, IconTeamsColor, IconTemplateCode, IconTerminal, IconTestQuarantine, IconThemeDarkToggle, IconThumbDown, IconThumbUp, IconTools, IconTrash, IconTrigger, IconUbuntu, IconUbuntuColor, IconUnity3D, IconUpload, IconValidateShield, IconVideo, IconWarning, IconWarningYellow, IconWebUi, IconWebhooks, IconWorkflow, IconWorkflowFlow, IconXTwitter, IconXamarin, IconXcode, bitkitIcon, bitkitTheme as bitriseTheme, createBitkitToast, createTreeCollection };
@@ -36,13 +36,6 @@ var base = {
36
36
  color: "icon/interactive",
37
37
  display: "flex",
38
38
  justifyContent: "center"
39
- },
40
- itemGroupLabel: {
41
- alignItems: "center",
42
- display: "flex",
43
- gap: "16",
44
- paddingBlock: "12",
45
- paddingInline: "16"
46
39
  }
47
40
  };
48
41
  var variants = { size: {
@@ -1 +1 @@
1
- {"version":3,"file":"ComboboxAndSelect.common.js","names":[],"sources":["../../../lib/theme/common/ComboboxAndSelect.common.ts"],"sourcesContent":["import { type SystemStyleObject } from '@chakra-ui/react/styled-system';\n\nimport { rem } from '../themeUtils';\n\nexport const base: Record<string, SystemStyleObject> = {\n content: {\n background: 'background/primary',\n border: '1px solid',\n borderColor: 'border/minimal',\n zIndex: 'select',\n overflowY: 'auto',\n boxShadow: 'elevation/lg',\n _open: {\n animationStyle: 'slide-fade-in',\n animationDuration: 'fast',\n },\n _closed: {\n animationStyle: 'slide-fade-out',\n animationDuration: 'fastest',\n },\n },\n item: {\n position: 'relative',\n userSelect: 'none',\n display: 'flex',\n alignItems: 'center',\n gap: '12',\n cursor: 'option',\n justifyContent: 'space-between',\n flex: '1',\n textAlign: 'start',\n lineHeight: rem(24),\n _highlighted: {\n bg: 'background/hover',\n },\n _selected: {\n bg: 'background/selected',\n },\n },\n itemIndicator: {\n alignItems: 'center',\n color: 'icon/interactive',\n display: 'flex',\n justifyContent: 'center',\n },\n itemGroupLabel: {\n alignItems: 'center',\n display: 'flex',\n gap: '16',\n paddingBlock: '12',\n paddingInline: '16',\n },\n};\n\nexport const variants: Record<'size', Record<'md' | 'lg', Record<string, SystemStyleObject>>> = {\n size: {\n lg: {\n item: {\n paddingInline: '16',\n paddingBlock: '12',\n textStyle: 'body/lg/regular',\n _selected: {\n textStyle: 'body/lg/semibold',\n },\n },\n itemIndicator: {\n width: '24',\n height: '24',\n },\n },\n md: {\n item: {\n paddingBlock: '8',\n paddingInline: '16',\n textStyle: 'body/md/regular',\n _selected: {\n textStyle: 'body/md/semibold',\n },\n },\n itemIndicator: {\n width: '16',\n height: '16',\n },\n },\n },\n};\n"],"mappings":";;AAIA,IAAa,OAA0C;CACrD,SAAS;EACP,YAAY;EACZ,QAAQ;EACR,aAAa;EACb,QAAQ;EACR,WAAW;EACX,WAAW;EACX,OAAO;GACL,gBAAgB;GAChB,mBAAmB;GACpB;EACD,SAAS;GACP,gBAAgB;GAChB,mBAAmB;GACpB;EACF;CACD,MAAM;EACJ,UAAU;EACV,YAAY;EACZ,SAAS;EACT,YAAY;EACZ,KAAK;EACL,QAAQ;EACR,gBAAgB;EAChB,MAAM;EACN,WAAW;EACX,YAAY,IAAI,GAAG;EACnB,cAAc,EACZ,IAAI,oBACL;EACD,WAAW,EACT,IAAI,uBACL;EACF;CACD,eAAe;EACb,YAAY;EACZ,OAAO;EACP,SAAS;EACT,gBAAgB;EACjB;CACD,gBAAgB;EACd,YAAY;EACZ,SAAS;EACT,KAAK;EACL,cAAc;EACd,eAAe;EAChB;CACF;AAED,IAAa,WAAmF,EAC9F,MAAM;CACJ,IAAI;EACF,MAAM;GACJ,eAAe;GACf,cAAc;GACd,WAAW;GACX,WAAW,EACT,WAAW,oBACZ;GACF;EACD,eAAe;GACb,OAAO;GACP,QAAQ;GACT;EACF;CACD,IAAI;EACF,MAAM;GACJ,cAAc;GACd,eAAe;GACf,WAAW;GACX,WAAW,EACT,WAAW,oBACZ;GACF;EACD,eAAe;GACb,OAAO;GACP,QAAQ;GACT;EACF;CACF,EACF"}
1
+ {"version":3,"file":"ComboboxAndSelect.common.js","names":[],"sources":["../../../lib/theme/common/ComboboxAndSelect.common.ts"],"sourcesContent":["import { type SystemStyleObject } from '@chakra-ui/react/styled-system';\n\nimport { rem } from '../themeUtils';\n\nexport const base: Record<string, SystemStyleObject> = {\n content: {\n background: 'background/primary',\n border: '1px solid',\n borderColor: 'border/minimal',\n zIndex: 'select',\n overflowY: 'auto',\n boxShadow: 'elevation/lg',\n _open: {\n animationStyle: 'slide-fade-in',\n animationDuration: 'fast',\n },\n _closed: {\n animationStyle: 'slide-fade-out',\n animationDuration: 'fastest',\n },\n },\n item: {\n position: 'relative',\n userSelect: 'none',\n display: 'flex',\n alignItems: 'center',\n gap: '12',\n cursor: 'option',\n justifyContent: 'space-between',\n flex: '1',\n textAlign: 'start',\n lineHeight: rem(24),\n _highlighted: {\n bg: 'background/hover',\n },\n _selected: {\n bg: 'background/selected',\n },\n },\n itemIndicator: {\n alignItems: 'center',\n color: 'icon/interactive',\n display: 'flex',\n justifyContent: 'center',\n },\n};\n\nexport const variants: Record<'size', Record<'md' | 'lg', Record<string, SystemStyleObject>>> = {\n size: {\n lg: {\n item: {\n paddingInline: '16',\n paddingBlock: '12',\n textStyle: 'body/lg/regular',\n _selected: {\n textStyle: 'body/lg/semibold',\n },\n },\n itemIndicator: {\n width: '24',\n height: '24',\n },\n },\n md: {\n item: {\n paddingBlock: '8',\n paddingInline: '16',\n textStyle: 'body/md/regular',\n _selected: {\n textStyle: 'body/md/semibold',\n },\n },\n itemIndicator: {\n width: '16',\n height: '16',\n },\n },\n },\n};\n"],"mappings":";;AAIA,IAAa,OAA0C;CACrD,SAAS;EACP,YAAY;EACZ,QAAQ;EACR,aAAa;EACb,QAAQ;EACR,WAAW;EACX,WAAW;EACX,OAAO;GACL,gBAAgB;GAChB,mBAAmB;GACpB;EACD,SAAS;GACP,gBAAgB;GAChB,mBAAmB;GACpB;EACF;CACD,MAAM;EACJ,UAAU;EACV,YAAY;EACZ,SAAS;EACT,YAAY;EACZ,KAAK;EACL,QAAQ;EACR,gBAAgB;EAChB,MAAM;EACN,WAAW;EACX,YAAY,IAAI,GAAG;EACnB,cAAc,EACZ,IAAI,oBACL;EACD,WAAW,EACT,IAAI,uBACL;EACF;CACD,eAAe;EACb,YAAY;EACZ,OAAO;EACP,SAAS;EACT,gBAAgB;EACjB;CACF;AAED,IAAa,WAAmF,EAC9F,MAAM;CACJ,IAAI;EACF,MAAM;GACJ,eAAe;GACf,cAAc;GACd,WAAW;GACX,WAAW,EACT,WAAW,oBACZ;GACF;EACD,eAAe;GACb,OAAO;GACP,QAAQ;GACT;EACF;CACD,IAAI;EACF,MAAM;GACJ,cAAc;GACd,eAAe;GACf,WAAW;GACX,WAAW,EACT,WAAW,oBACZ;GACF;EACD,eAAe;GACb,OAAO;GACP,QAAQ;GACT;EACF;CACF,EACF"}
@@ -1,2 +1,2 @@
1
- declare const sectionHeadingRecipe: import('@chakra-ui/react').SlotRecipeDefinition<"label" | "icon" | "root" | "helperText" | "titleBlock" | "contentBlock" | "helperBlock", import('@chakra-ui/react').SlotRecipeVariantRecord<"label" | "icon" | "root" | "helperText" | "titleBlock" | "contentBlock" | "helperBlock">>;
1
+ declare const sectionHeadingRecipe: import('@chakra-ui/react').SlotRecipeDefinition<"label" | "icon" | "root" | "titleBlock" | "helperText" | "contentBlock" | "helperBlock", import('@chakra-ui/react').SlotRecipeVariantRecord<"label" | "icon" | "root" | "titleBlock" | "helperText" | "contentBlock" | "helperBlock">>;
2
2
  export default sectionHeadingRecipe;
@@ -6,7 +6,6 @@ var AssetSelectChevron = forwardRef((props, ref) => /* @__PURE__ */ jsx(Icon, {
6
6
  asChild: true,
7
7
  ref,
8
8
  transition: "0.2s ease",
9
- pointerEvents: "none",
10
9
  _open: { transform: "rotate(180deg)" },
11
10
  _disabled: {
12
11
  cursor: "not-allowed",
@@ -1 +1 @@
1
- {"version":3,"file":"AssetSelectChevron.js","names":[],"sources":["../../lib/utilities/AssetSelectChevron.tsx"],"sourcesContent":["import { Icon, type IconProps } from '@chakra-ui/react/icon';\nimport { forwardRef, type Ref } from 'react';\n\nconst AssetSelectChevron = forwardRef((props: IconProps, ref: Ref<SVGSVGElement>) => (\n <Icon\n asChild\n ref={ref}\n transition=\"0.2s ease\"\n pointerEvents=\"none\"\n _open={{\n transform: 'rotate(180deg)',\n }}\n _disabled={{\n cursor: 'not-allowed',\n color: 'icon/disabled',\n }}\n color=\"icon/secondary\"\n _groupFocusWithin={{\n color: 'icon/primary',\n }}\n _groupHover={{\n color: 'icon/primary',\n }}\n {...props}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\">\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M6.29285 10.2071L7.70706 8.79289L12 13.0858L16.2928 8.79289L17.7071 10.2071L12 15.9142L6.29285 10.2071Z\"\n fill=\"currentColor\"\n />\n </svg>\n </Icon>\n));\n\nAssetSelectChevron.displayName = 'AssetSelectChevron';\n\nexport default AssetSelectChevron;\n"],"mappings":";;;;AAGA,IAAM,qBAAqB,YAAY,OAAkB,QACvD,oBAAC,MAAD;CACE,SAAA;CACK;CACL,YAAW;CACX,eAAc;CACd,OAAO,EACL,WAAW,kBACZ;CACD,WAAW;EACT,QAAQ;EACR,OAAO;EACR;CACD,OAAM;CACN,mBAAmB,EACjB,OAAO,gBACR;CACD,aAAa,EACX,OAAO,gBACR;CACD,GAAI;WAEJ,oBAAC,OAAD;EAAK,OAAM;EAA6B,SAAQ;EAAY,OAAM;EAAK,QAAO;YAC5E,oBAAC,QAAD;GACE,UAAS;GACT,UAAS;GACT,GAAE;GACF,MAAK;GACL,CAAA;EACE,CAAA;CACD,CAAA,CACP;AAEF,mBAAmB,cAAc"}
1
+ {"version":3,"file":"AssetSelectChevron.js","names":[],"sources":["../../lib/utilities/AssetSelectChevron.tsx"],"sourcesContent":["import { Icon, type IconProps } from '@chakra-ui/react/icon';\nimport { forwardRef, type Ref } from 'react';\n\nconst AssetSelectChevron = forwardRef((props: IconProps, ref: Ref<SVGSVGElement>) => (\n <Icon\n asChild\n ref={ref}\n transition=\"0.2s ease\"\n _open={{\n transform: 'rotate(180deg)',\n }}\n _disabled={{\n cursor: 'not-allowed',\n color: 'icon/disabled',\n }}\n color=\"icon/secondary\"\n _groupFocusWithin={{\n color: 'icon/primary',\n }}\n _groupHover={{\n color: 'icon/primary',\n }}\n {...props}\n >\n <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"24\" height=\"24\">\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M6.29285 10.2071L7.70706 8.79289L12 13.0858L16.2928 8.79289L17.7071 10.2071L12 15.9142L6.29285 10.2071Z\"\n fill=\"currentColor\"\n />\n </svg>\n </Icon>\n));\n\nAssetSelectChevron.displayName = 'AssetSelectChevron';\n\nexport default AssetSelectChevron;\n"],"mappings":";;;;AAGA,IAAM,qBAAqB,YAAY,OAAkB,QACvD,oBAAC,MAAD;CACE,SAAA;CACK;CACL,YAAW;CACX,OAAO,EACL,WAAW,kBACZ;CACD,WAAW;EACT,QAAQ;EACR,OAAO;EACR;CACD,OAAM;CACN,mBAAmB,EACjB,OAAO,gBACR;CACD,aAAa,EACX,OAAO,gBACR;CACD,GAAI;WAEJ,oBAAC,OAAD;EAAK,OAAM;EAA6B,SAAQ;EAAY,OAAM;EAAK,QAAO;YAC5E,oBAAC,QAAD;GACE,UAAS;GACT,UAAS;GACT,GAAE;GACF,MAAK;GACL,CAAA;EACE,CAAA;CACD,CAAA,CACP;AAEF,mBAAmB,cAAc"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bitrise/bitkit-v2",
3
3
  "private": false,
4
- "version": "0.3.202",
4
+ "version": "0.3.203",
5
5
  "description": "Bitrise Design System Components built with Chakra UI V3",
6
6
  "keywords": [
7
7
  "react",