@bitrise/bitkit-v2 0.3.220 → 0.3.222

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.
Files changed (29) hide show
  1. package/AGENTS.md +15 -0
  2. package/dist/components/BitkitActionMenu/BitkitActionMenu.d.ts +16 -3
  3. package/dist/components/BitkitActionMenu/BitkitActionMenu.js +31 -11
  4. package/dist/components/BitkitActionMenu/BitkitActionMenu.js.map +1 -1
  5. package/dist/components/BitkitButton/BitkitButton.d.ts +27 -4
  6. package/dist/components/BitkitButton/BitkitButton.js +85 -8
  7. package/dist/components/BitkitButton/BitkitButton.js.map +1 -1
  8. package/dist/components/BitkitCheckboxGroup/BitkitCheckboxGroup.d.ts +5 -1
  9. package/dist/components/BitkitCheckboxGroup/BitkitCheckboxGroup.js +4 -3
  10. package/dist/components/BitkitCheckboxGroup/BitkitCheckboxGroup.js.map +1 -1
  11. package/dist/components/BitkitControlButton/BitkitControlButton.d.ts +11 -2
  12. package/dist/components/BitkitControlButton/BitkitControlButton.js +46 -3
  13. package/dist/components/BitkitControlButton/BitkitControlButton.js.map +1 -1
  14. package/dist/components/BitkitIconButton/BitkitIconButton.d.ts +25 -3
  15. package/dist/components/BitkitIconButton/BitkitIconButton.js +80 -7
  16. package/dist/components/BitkitIconButton/BitkitIconButton.js.map +1 -1
  17. package/dist/components/BitkitLink/BitkitLink.d.ts +1 -0
  18. package/dist/components/BitkitLink/BitkitLink.js +18 -3
  19. package/dist/components/BitkitLink/BitkitLink.js.map +1 -1
  20. package/dist/components/BitkitNoteCard/BitkitNoteCard.js +11 -8
  21. package/dist/components/BitkitNoteCard/BitkitNoteCard.js.map +1 -1
  22. package/dist/components/BitkitRadioGroup/BitkitRadioGroup.d.ts +5 -1
  23. package/dist/components/BitkitRadioGroup/BitkitRadioGroup.js +4 -3
  24. package/dist/components/BitkitRadioGroup/BitkitRadioGroup.js.map +1 -1
  25. package/dist/components/BitkitSplitButton/BitkitSplitButton.d.ts +4 -4
  26. package/dist/components/BitkitSplitButton/BitkitSplitButton.js +11 -3
  27. package/dist/components/BitkitSplitButton/BitkitSplitButton.js.map +1 -1
  28. package/docs/v1-to-v2-migration-guide.md +33 -1
  29. package/package.json +1 -1
package/AGENTS.md CHANGED
@@ -91,6 +91,21 @@ Bitkit components use consistent prop names across the library:
91
91
  <BitkitButton icon={IconCheck}>Save</BitkitButton>
92
92
  <BitkitAccordion.ItemTrigger suffix={<Badge>3</Badge>}>Files</BitkitAccordion.ItemTrigger>
93
93
  ```
94
+ - **Buttons can render as links** — `BitkitButton`, `BitkitIconButton`, and `BitkitControlButton` render an `<a>` when `href` is passed. The button-recipe styles apply to the anchor. Pass `isExternal` to auto-add `target="_blank" rel="noreferrer noopener"`. For routing libraries (Next.js, React Router), use `asChild` with your own anchor element:
95
+ ```tsx
96
+ <BitkitButton href="/internal">Internal link</BitkitButton>
97
+ <BitkitButton href="https://example.com" isExternal>External</BitkitButton>
98
+ <BitkitButton asChild icon={IconCheck}>
99
+ <NextLink href="/route">Routed</NextLink>
100
+ </BitkitButton>
101
+ ```
102
+ `state="loading"` is button-only — not valid in anchor mode.
103
+ - **`BitkitLink` external convenience** — `BitkitLink` accepts `isExternal` for the same auto target+rel behavior.
104
+ - **`BitkitActionMenu.Item` as a link** — pass `href` to make a menu item render as an anchor; `target`, `rel`, and `isExternal` work the same way as on the button family. Without `href` it stays a normal menu item:
105
+ ```tsx
106
+ <BitkitActionMenu.Item href="/settings" value="settings">Settings</BitkitActionMenu.Item>
107
+ <BitkitActionMenu.Item href="https://example.com" isExternal value="docs">Open docs</BitkitActionMenu.Item>
108
+ ```
94
109
  - **Form components are flat** — `BitkitTextInput`, `BitkitSelect`, `BitkitCombobox`, etc. expose `label`, `errorText`, `helperText`, etc. directly as props. No need to wrap in a separate field component.
95
110
  - **`BitkitDialog` non-dismissible + post-close callback** — pass `closable={false}` to make the dialog fully non-dismissible: the close button is rendered but disabled (kept for layout consistency), ESC is blocked, and outside clicks are ignored. The only way out is an explicit footer action. Pass `onExitComplete` to run code after the close animation finishes (navigation, focus restoration, cleanup):
96
111
  ```tsx
@@ -5,11 +5,24 @@ interface BitkitMenuRootProps extends Omit<MenuRootProps, 'children'> {
5
5
  trigger: ReactNode;
6
6
  children?: ReactNode;
7
7
  }
8
- export interface BitkitMenuItemProps extends MenuItemProps {
8
+ interface BitkitMenuItemCommonProps extends MenuItemProps {
9
9
  danger?: boolean;
10
- secondaryText?: ReactNode;
11
10
  icon?: BitkitIconComponent;
11
+ secondaryText?: ReactNode;
12
+ }
13
+ interface BitkitMenuItemAsButtonProps extends BitkitMenuItemCommonProps {
14
+ href?: undefined;
15
+ isExternal?: undefined;
16
+ rel?: undefined;
17
+ target?: undefined;
18
+ }
19
+ interface BitkitMenuItemAsAnchorProps extends BitkitMenuItemCommonProps {
20
+ href: string;
21
+ isExternal?: boolean;
22
+ rel?: string;
23
+ target?: string;
12
24
  }
25
+ export type BitkitMenuItemProps = BitkitMenuItemAsButtonProps | BitkitMenuItemAsAnchorProps;
13
26
  export interface BitkitMenuGroupProps extends MenuItemGroupProps {
14
27
  label: ReactNode;
15
28
  }
@@ -22,7 +35,7 @@ declare const BitkitActionMenu: {
22
35
  (): import("react/jsx-runtime").JSX.Element;
23
36
  displayName: string;
24
37
  };
25
- Item: import('react').ForwardRefExoticComponent<BitkitMenuItemProps & import('react').RefAttributes<HTMLDivElement>>;
38
+ Item: import('react').ForwardRefExoticComponent<BitkitMenuItemProps & import('react').RefAttributes<HTMLElement>>;
26
39
  Group: import('react').ForwardRefExoticComponent<BitkitMenuGroupProps & import('react').RefAttributes<HTMLDivElement>>;
27
40
  };
28
41
  export default BitkitActionMenu;
@@ -1,7 +1,7 @@
1
1
  import { Box } from "@chakra-ui/react/box";
2
2
  import { Text } from "@chakra-ui/react/text";
3
3
  import { createContext, forwardRef, useContext } from "react";
4
- import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { Portal } from "@chakra-ui/react/portal";
6
6
  import { Menu, useMenuStyles } from "@chakra-ui/react/menu";
7
7
  import { Separator } from "@chakra-ui/react/separator";
@@ -20,20 +20,40 @@ var Root = ({ trigger, children, ...props }) => {
20
20
  });
21
21
  };
22
22
  Root.displayName = "BitkitActionMenu.Root";
23
- var Item = forwardRef(({ danger, secondaryText, icon: Icon, children, ...props }, ref) => {
23
+ var Item = forwardRef((props, ref) => {
24
+ const { children, danger, icon: Icon, secondaryText } = props;
24
25
  const style = useMenuStyles();
25
26
  const menuCtx = useContext(BitkitMenuContext);
26
- return /* @__PURE__ */ jsxs(Menu.Item, {
27
+ const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [Icon && /* @__PURE__ */ jsx(Icon, { size: menuCtx === "lg" ? "24" : "16" }), /* @__PURE__ */ jsxs(Box, {
28
+ flex: "1",
29
+ children: [/* @__PURE__ */ jsx(Text, { children }), secondaryText && /* @__PURE__ */ jsx(Text, {
30
+ css: style.itemHelper,
31
+ children: secondaryText
32
+ })]
33
+ })] });
34
+ if (props.href !== void 0) {
35
+ const { children: _children, danger: _danger, href, icon: _icon, isExternal, rel, secondaryText: _secondaryText, target, ...rest } = props;
36
+ const effectiveTarget = isExternal ? "_blank" : target;
37
+ const effectiveRel = isExternal ? rel ? `${rel} noreferrer noopener` : "noreferrer noopener" : rel;
38
+ return /* @__PURE__ */ jsx(Menu.Item, {
39
+ asChild: true,
40
+ "data-danger": danger,
41
+ ...rest,
42
+ children: /* @__PURE__ */ jsx("a", {
43
+ ref,
44
+ href,
45
+ rel: effectiveRel,
46
+ target: effectiveTarget,
47
+ children: content
48
+ })
49
+ });
50
+ }
51
+ const { children: _children, danger: _danger, icon: _icon, secondaryText: _secondaryText, ...rest } = props;
52
+ return /* @__PURE__ */ jsx(Menu.Item, {
27
53
  "data-danger": danger,
28
54
  ref,
29
- ...props,
30
- children: [Icon && /* @__PURE__ */ jsx(Icon, { size: menuCtx === "lg" ? "24" : "16" }), /* @__PURE__ */ jsxs(Box, {
31
- flex: "1",
32
- children: [/* @__PURE__ */ jsx(Text, { children }), secondaryText && /* @__PURE__ */ jsx(Text, {
33
- css: style.itemHelper,
34
- children: secondaryText
35
- })]
36
- })]
55
+ ...rest,
56
+ children: content
37
57
  });
38
58
  });
39
59
  Item.displayName = "BitkitActionMenu.Item";
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitActionMenu.js","names":[],"sources":["../../../lib/components/BitkitActionMenu/BitkitActionMenu.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport {\n Menu,\n type MenuItemGroupProps,\n type MenuItemProps,\n type MenuRootProps,\n useMenuStyles,\n} from '@chakra-ui/react/menu';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Separator as ChakraSeparator } from '@chakra-ui/react/separator';\nimport { Text } from '@chakra-ui/react/text';\nimport { createContext, forwardRef, type ReactNode, useContext } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\n\nconst BitkitMenuContext = createContext<MenuRootProps['size']>('lg');\n\ninterface BitkitMenuRootProps extends Omit<MenuRootProps, 'children'> {\n trigger: ReactNode;\n children?: ReactNode;\n}\n\nconst Root = ({ trigger, children, ...props }: BitkitMenuRootProps) => {\n return (\n <Menu.Root {...props}>\n <Menu.Trigger asChild>{trigger}</Menu.Trigger>\n <Portal>\n <Menu.Positioner>\n <BitkitMenuContext.Provider value={props.size}>\n <Menu.Content>{children}</Menu.Content>\n </BitkitMenuContext.Provider>\n </Menu.Positioner>\n </Portal>\n </Menu.Root>\n );\n};\nRoot.displayName = 'BitkitActionMenu.Root';\n\nexport interface BitkitMenuItemProps extends MenuItemProps {\n danger?: boolean;\n secondaryText?: ReactNode;\n icon?: BitkitIconComponent;\n}\nconst Item = forwardRef<HTMLDivElement, BitkitMenuItemProps>(\n ({ danger, secondaryText, icon: Icon, children, ...props }, ref) => {\n const style = useMenuStyles();\n const menuCtx = useContext(BitkitMenuContext);\n return (\n <Menu.Item data-danger={danger} ref={ref} {...props}>\n {Icon && <Icon size={menuCtx === 'lg' ? '24' : '16'} />}\n <Box flex=\"1\">\n <Text>{children}</Text>\n {secondaryText && <Text css={style.itemHelper}>{secondaryText}</Text>}\n </Box>\n </Menu.Item>\n );\n },\n);\nItem.displayName = 'BitkitActionMenu.Item';\n\nexport interface BitkitMenuGroupProps extends MenuItemGroupProps {\n label: ReactNode;\n}\nconst Group = forwardRef<HTMLDivElement, BitkitMenuGroupProps>(({ label, children, ...props }, ref) => {\n return (\n <Menu.ItemGroup ref={ref} {...props}>\n <Menu.ItemGroupLabel>\n <Text>{label}</Text>\n <ChakraSeparator flex=\"1\" />\n </Menu.ItemGroupLabel>\n {children}\n </Menu.ItemGroup>\n );\n});\nGroup.displayName = 'BitkitActionMenu.Group';\n\nconst Separator = () => {\n return <Menu.Separator />;\n};\nSeparator.displayName = 'BitkitActionMenu.Separator';\n\nconst BitkitActionMenu = {\n Root,\n Separator,\n Item,\n Group,\n};\n\nexport default BitkitActionMenu;\n"],"mappings":";;;;;;;;AAeA,IAAM,oBAAoB,cAAqC,IAAI;AAOnE,IAAM,QAAQ,EAAE,SAAS,UAAU,GAAG,YAAiC;CACrE,OACE,qBAAC,KAAK,MAAN;EAAW,GAAI;YAAf,CACE,oBAAC,KAAK,SAAN;GAAc,SAAA;aAAS;EAAsB,CAAA,GAC7C,oBAAC,QAAD,EAAA,UACE,oBAAC,KAAK,YAAN,EAAA,UACE,oBAAC,kBAAkB,UAAnB;GAA4B,OAAO,MAAM;aACvC,oBAAC,KAAK,SAAN,EAAe,SAAuB,CAAA;EACZ,CAAA,EACb,CAAA,EACX,CAAA,CACC;;AAEf;AACA,KAAK,cAAc;AAOnB,IAAM,OAAO,YACV,EAAE,QAAQ,eAAe,MAAM,MAAM,UAAU,GAAG,SAAS,QAAQ;CAClE,MAAM,QAAQ,cAAc;CAC5B,MAAM,UAAU,WAAW,iBAAiB;CAC5C,OACE,qBAAC,KAAK,MAAN;EAAW,eAAa;EAAa;EAAK,GAAI;YAA9C,CACG,QAAQ,oBAAC,MAAD,EAAM,MAAM,YAAY,OAAO,OAAO,KAAO,CAAA,GACtD,qBAAC,KAAD;GAAK,MAAK;aAAV,CACE,oBAAC,MAAD,EAAO,SAAe,CAAA,GACrB,iBAAiB,oBAAC,MAAD;IAAM,KAAK,MAAM;cAAa;GAAoB,CAAA,CACjE;IACI;;AAEf,CACF;AACA,KAAK,cAAc;AAKnB,IAAM,QAAQ,YAAkD,EAAE,OAAO,UAAU,GAAG,SAAS,QAAQ;CACrG,OACE,qBAAC,KAAK,WAAN;EAAqB;EAAK,GAAI;YAA9B,CACE,qBAAC,KAAK,gBAAN,EAAA,UAAA,CACE,oBAAC,MAAD,EAAA,UAAO,MAAY,CAAA,GACnB,oBAAC,WAAD,EAAiB,MAAK,IAAK,CAAA,CACR,EAAA,CAAA,GACpB,QACa;;AAEpB,CAAC;AACD,MAAM,cAAc;AAEpB,IAAM,oBAAkB;CACtB,OAAO,oBAAC,KAAK,WAAN,CAAiB,CAAA;AAC1B;AACA,YAAU,cAAc;AAExB,IAAM,mBAAmB;CACvB;CACA,WAAA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"BitkitActionMenu.js","names":[],"sources":["../../../lib/components/BitkitActionMenu/BitkitActionMenu.tsx"],"sourcesContent":["import { Box } from '@chakra-ui/react/box';\nimport {\n Menu,\n type MenuItemGroupProps,\n type MenuItemProps,\n type MenuRootProps,\n useMenuStyles,\n} from '@chakra-ui/react/menu';\nimport { Portal } from '@chakra-ui/react/portal';\nimport { Separator as ChakraSeparator } from '@chakra-ui/react/separator';\nimport { Text } from '@chakra-ui/react/text';\nimport { createContext, forwardRef, type ReactNode, type Ref, useContext } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\n\nconst BitkitMenuContext = createContext<MenuRootProps['size']>('lg');\n\ninterface BitkitMenuRootProps extends Omit<MenuRootProps, 'children'> {\n trigger: ReactNode;\n children?: ReactNode;\n}\n\nconst Root = ({ trigger, children, ...props }: BitkitMenuRootProps) => {\n return (\n <Menu.Root {...props}>\n <Menu.Trigger asChild>{trigger}</Menu.Trigger>\n <Portal>\n <Menu.Positioner>\n <BitkitMenuContext.Provider value={props.size}>\n <Menu.Content>{children}</Menu.Content>\n </BitkitMenuContext.Provider>\n </Menu.Positioner>\n </Portal>\n </Menu.Root>\n );\n};\nRoot.displayName = 'BitkitActionMenu.Root';\n\ninterface BitkitMenuItemCommonProps extends MenuItemProps {\n danger?: boolean;\n icon?: BitkitIconComponent;\n secondaryText?: ReactNode;\n}\n\ninterface BitkitMenuItemAsButtonProps extends BitkitMenuItemCommonProps {\n href?: undefined;\n isExternal?: undefined;\n rel?: undefined;\n target?: undefined;\n}\n\ninterface BitkitMenuItemAsAnchorProps extends BitkitMenuItemCommonProps {\n href: string;\n isExternal?: boolean;\n rel?: string;\n target?: string;\n}\n\nexport type BitkitMenuItemProps = BitkitMenuItemAsButtonProps | BitkitMenuItemAsAnchorProps;\n\nconst Item = forwardRef<HTMLElement, BitkitMenuItemProps>((props, ref) => {\n const { children, danger, icon: Icon, secondaryText } = props;\n const style = useMenuStyles();\n const menuCtx = useContext(BitkitMenuContext);\n\n const content = (\n <>\n {Icon && <Icon size={menuCtx === 'lg' ? '24' : '16'} />}\n <Box flex=\"1\">\n <Text>{children}</Text>\n {secondaryText && <Text css={style.itemHelper}>{secondaryText}</Text>}\n </Box>\n </>\n );\n\n if (props.href !== undefined) {\n const {\n children: _children,\n danger: _danger,\n href,\n icon: _icon,\n isExternal,\n rel,\n secondaryText: _secondaryText,\n target,\n ...rest\n } = props;\n const effectiveTarget = isExternal ? '_blank' : target;\n const effectiveRel = isExternal ? (rel ? `${rel} noreferrer noopener` : 'noreferrer noopener') : rel;\n return (\n <Menu.Item asChild data-danger={danger} {...rest}>\n <a ref={ref as Ref<HTMLAnchorElement>} href={href} rel={effectiveRel} target={effectiveTarget}>\n {content}\n </a>\n </Menu.Item>\n );\n }\n\n const { children: _children, danger: _danger, icon: _icon, secondaryText: _secondaryText, ...rest } = props;\n return (\n <Menu.Item data-danger={danger} ref={ref as Ref<HTMLDivElement>} {...rest}>\n {content}\n </Menu.Item>\n );\n});\nItem.displayName = 'BitkitActionMenu.Item';\n\nexport interface BitkitMenuGroupProps extends MenuItemGroupProps {\n label: ReactNode;\n}\nconst Group = forwardRef<HTMLDivElement, BitkitMenuGroupProps>(({ label, children, ...props }, ref) => {\n return (\n <Menu.ItemGroup ref={ref} {...props}>\n <Menu.ItemGroupLabel>\n <Text>{label}</Text>\n <ChakraSeparator flex=\"1\" />\n </Menu.ItemGroupLabel>\n {children}\n </Menu.ItemGroup>\n );\n});\nGroup.displayName = 'BitkitActionMenu.Group';\n\nconst Separator = () => {\n return <Menu.Separator />;\n};\nSeparator.displayName = 'BitkitActionMenu.Separator';\n\nconst BitkitActionMenu = {\n Root,\n Separator,\n Item,\n Group,\n};\n\nexport default BitkitActionMenu;\n"],"mappings":";;;;;;;;AAeA,IAAM,oBAAoB,cAAqC,IAAI;AAOnE,IAAM,QAAQ,EAAE,SAAS,UAAU,GAAG,YAAiC;CACrE,OACE,qBAAC,KAAK,MAAN;EAAW,GAAI;YAAf,CACE,oBAAC,KAAK,SAAN;GAAc,SAAA;aAAS;EAAsB,CAAA,GAC7C,oBAAC,QAAD,EAAA,UACE,oBAAC,KAAK,YAAN,EAAA,UACE,oBAAC,kBAAkB,UAAnB;GAA4B,OAAO,MAAM;aACvC,oBAAC,KAAK,SAAN,EAAe,SAAuB,CAAA;EACZ,CAAA,EACb,CAAA,EACX,CAAA,CACC;;AAEf;AACA,KAAK,cAAc;AAwBnB,IAAM,OAAO,YAA8C,OAAO,QAAQ;CACxE,MAAM,EAAE,UAAU,QAAQ,MAAM,MAAM,kBAAkB;CACxD,MAAM,QAAQ,cAAc;CAC5B,MAAM,UAAU,WAAW,iBAAiB;CAE5C,MAAM,UACJ,qBAAA,YAAA,EAAA,UAAA,CACG,QAAQ,oBAAC,MAAD,EAAM,MAAM,YAAY,OAAO,OAAO,KAAO,CAAA,GACtD,qBAAC,KAAD;EAAK,MAAK;YAAV,CACE,oBAAC,MAAD,EAAO,SAAe,CAAA,GACrB,iBAAiB,oBAAC,MAAD;GAAM,KAAK,MAAM;aAAa;EAAoB,CAAA,CACjE;GACL,EAAA,CAAA;CAGJ,IAAI,MAAM,SAAS,KAAA,GAAW;EAC5B,MAAM,EACJ,UAAU,WACV,QAAQ,SACR,MACA,MAAM,OACN,YACA,KACA,eAAe,gBACf,QACA,GAAG,SACD;EACJ,MAAM,kBAAkB,aAAa,WAAW;EAChD,MAAM,eAAe,aAAc,MAAM,GAAG,IAAI,wBAAwB,wBAAyB;EACjG,OACE,oBAAC,KAAK,MAAN;GAAW,SAAA;GAAQ,eAAa;GAAQ,GAAI;aAC1C,oBAAC,KAAD;IAAQ;IAAqC;IAAM,KAAK;IAAc,QAAQ;cAC3E;GACA,CAAA;EACM,CAAA;CAEf;CAEA,MAAM,EAAE,UAAU,WAAW,QAAQ,SAAS,MAAM,OAAO,eAAe,gBAAgB,GAAG,SAAS;CACtG,OACE,oBAAC,KAAK,MAAN;EAAW,eAAa;EAAa;EAA4B,GAAI;YAClE;CACQ,CAAA;AAEf,CAAC;AACD,KAAK,cAAc;AAKnB,IAAM,QAAQ,YAAkD,EAAE,OAAO,UAAU,GAAG,SAAS,QAAQ;CACrG,OACE,qBAAC,KAAK,WAAN;EAAqB;EAAK,GAAI;YAA9B,CACE,qBAAC,KAAK,gBAAN,EAAA,UAAA,CACE,oBAAC,MAAD,EAAA,UAAO,MAAY,CAAA,GACnB,oBAAC,WAAD,EAAiB,MAAK,IAAK,CAAA,CACR,EAAA,CAAA,GACpB,QACa;;AAEpB,CAAC;AACD,MAAM,cAAc;AAEpB,IAAM,oBAAkB;CACtB,OAAO,oBAAC,KAAK,WAAN,CAAiB,CAAA;AAC1B;AACA,YAAU,cAAc;AAExB,IAAM,mBAAmB;CACvB;CACA,WAAA;CACA;CACA;AACF"}
@@ -1,10 +1,33 @@
1
1
  import { ButtonProps } from '@chakra-ui/react/button';
2
+ import { HTMLChakraProps, RecipeProps } from '@chakra-ui/react/styled-system';
3
+ import { ReactElement } from 'react';
2
4
  import { BitkitIconComponent } from '../../icons';
3
- export interface BitkitButtonProps extends Omit<ButtonProps, 'children' | 'colorPalette' | 'disabled' | 'loading' | 'loadingText' | 'spinner' | 'spinnerPlacement'> {
4
- children: string;
5
+ type BitkitButtonOmittedFromButton = 'asChild' | 'children' | 'colorPalette' | 'disabled' | 'loading' | 'loadingText' | 'spinner' | 'spinnerPlacement';
6
+ interface BitkitButtonCommonProps {
5
7
  icon?: BitkitIconComponent;
6
- state?: 'disabled' | 'loading' | 'skeleton';
7
8
  suffixIcon?: BitkitIconComponent;
8
9
  }
9
- declare const BitkitButton: import('react').ForwardRefExoticComponent<BitkitButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
10
+ export interface BitkitButtonAsButtonProps extends BitkitButtonCommonProps, Omit<ButtonProps, BitkitButtonOmittedFromButton> {
11
+ asChild?: false;
12
+ children: string;
13
+ href?: undefined;
14
+ isExternal?: undefined;
15
+ state?: 'disabled' | 'loading' | 'skeleton';
16
+ }
17
+ export interface BitkitButtonAsAnchorProps extends BitkitButtonCommonProps, Omit<HTMLChakraProps<'a'>, 'children' | 'colorPalette'>, RecipeProps<'button'> {
18
+ asChild?: false;
19
+ children: string;
20
+ href: string;
21
+ isExternal?: boolean;
22
+ state?: 'disabled' | 'skeleton';
23
+ }
24
+ interface BitkitButtonAsChildProps extends BitkitButtonCommonProps, Omit<ButtonProps, BitkitButtonOmittedFromButton> {
25
+ asChild: true;
26
+ children: ReactElement;
27
+ href?: undefined;
28
+ isExternal?: undefined;
29
+ state?: 'disabled' | 'loading' | 'skeleton';
30
+ }
31
+ export type BitkitButtonProps = BitkitButtonAsButtonProps | BitkitButtonAsAnchorProps | BitkitButtonAsChildProps;
32
+ declare const BitkitButton: import('react').ForwardRefExoticComponent<BitkitButtonProps & import('react').RefAttributes<HTMLElement>>;
10
33
  export default BitkitButton;
@@ -1,20 +1,97 @@
1
- import { forwardRef } from "react";
2
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { chakra, useRecipe } from "@chakra-ui/react/styled-system";
2
+ import { Children, cloneElement, forwardRef } from "react";
3
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
3
4
  import { Skeleton } from "@chakra-ui/react/skeleton";
4
5
  import { Button } from "@chakra-ui/react/button";
5
6
  //#region lib/components/BitkitButton/BitkitButton.tsx
6
7
  var BitkitButton = forwardRef((props, ref) => {
7
- const { children, icon: Icon, size, state, suffixIcon: SuffixIcon, ...rest } = props;
8
- const iconSize = size === "sm" ? "16" : "24";
8
+ const buttonRecipe = useRecipe({ key: "button" });
9
+ const Icon = props.icon;
10
+ const SuffixIcon = props.suffixIcon;
11
+ const iconSize = props.size === "sm" ? "16" : "24";
12
+ const isDisabled = props.state === "disabled";
13
+ const isSkeleton = props.state === "skeleton";
14
+ if (props.asChild) {
15
+ const { asChild: _asChild, children, icon: _icon, state, suffixIcon: _suffixIcon, ...buttonRest } = props;
16
+ const onlyChild = Children.only(children);
17
+ const buttonElement = /* @__PURE__ */ jsx(Button, {
18
+ asChild: true,
19
+ disabled: isDisabled,
20
+ loading: state === "loading",
21
+ ref,
22
+ ...buttonRest,
23
+ children: cloneElement(onlyChild, void 0, /* @__PURE__ */ jsxs(Fragment$1, { children: [
24
+ Icon && /* @__PURE__ */ jsx(Icon, {
25
+ marginInlineStart: "-4",
26
+ size: iconSize
27
+ }),
28
+ onlyChild.props.children,
29
+ SuffixIcon && /* @__PURE__ */ jsx(SuffixIcon, {
30
+ marginInlineEnd: "-4",
31
+ size: iconSize
32
+ })
33
+ ] }))
34
+ });
35
+ return isSkeleton ? /* @__PURE__ */ jsx(Skeleton, {
36
+ asChild: true,
37
+ loading: true,
38
+ children: buttonElement
39
+ }) : buttonElement;
40
+ }
41
+ if (props.href !== void 0) {
42
+ const { children, css, href, icon: _icon, isExternal, onClick, onKeyDown, rel, size, state: _state, suffixIcon: _suffixIcon, target, variant, ...anchorRest } = props;
43
+ const effectiveTarget = isExternal ? "_blank" : target;
44
+ const effectiveRel = isExternal ? rel ? `${rel} noreferrer noopener` : "noreferrer noopener" : rel;
45
+ const handleClick = isDisabled ? (e) => {
46
+ e.preventDefault();
47
+ e.stopPropagation();
48
+ } : onClick;
49
+ const handleKeyDown = isDisabled ? (e) => {
50
+ if (e.key === "Enter" || e.key === " ") {
51
+ e.preventDefault();
52
+ e.stopPropagation();
53
+ }
54
+ } : onKeyDown;
55
+ const anchorElement = /* @__PURE__ */ jsxs(chakra.a, {
56
+ ref,
57
+ ...anchorRest,
58
+ "aria-disabled": isDisabled || void 0,
59
+ css: [buttonRecipe({
60
+ size,
61
+ variant
62
+ }), css],
63
+ href: isDisabled ? void 0 : href,
64
+ onClick: handleClick,
65
+ onKeyDown: handleKeyDown,
66
+ rel: effectiveRel,
67
+ target: effectiveTarget,
68
+ children: [
69
+ Icon && /* @__PURE__ */ jsx(Icon, {
70
+ marginInlineStart: "-4",
71
+ size: iconSize
72
+ }),
73
+ children,
74
+ SuffixIcon && /* @__PURE__ */ jsx(SuffixIcon, {
75
+ marginInlineEnd: "-4",
76
+ size: iconSize
77
+ })
78
+ ]
79
+ });
80
+ return isSkeleton ? /* @__PURE__ */ jsx(Skeleton, {
81
+ asChild: true,
82
+ loading: true,
83
+ children: anchorElement
84
+ }) : anchorElement;
85
+ }
86
+ const { children, icon: _icon, state, suffixIcon: _suffixIcon, ...buttonRest } = props;
9
87
  return /* @__PURE__ */ jsx(Skeleton, {
10
88
  asChild: true,
11
- loading: state === "skeleton",
89
+ loading: isSkeleton,
12
90
  children: /* @__PURE__ */ jsxs(Button, {
13
- disabled: state === "disabled",
91
+ disabled: isDisabled,
14
92
  loading: state === "loading",
15
93
  ref,
16
- size,
17
- ...rest,
94
+ ...buttonRest,
18
95
  children: [
19
96
  Icon && /* @__PURE__ */ jsx(Icon, {
20
97
  marginInlineStart: "-4",
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitButton.js","names":[],"sources":["../../../lib/components/BitkitButton/BitkitButton.tsx"],"sourcesContent":["import { Button, type ButtonProps } from '@chakra-ui/react/button';\nimport { Skeleton } from '@chakra-ui/react/skeleton';\nimport { forwardRef } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\n\nexport interface BitkitButtonProps extends Omit<\n ButtonProps,\n 'children' | 'colorPalette' | 'disabled' | 'loading' | 'loadingText' | 'spinner' | 'spinnerPlacement'\n> {\n children: string;\n icon?: BitkitIconComponent;\n state?: 'disabled' | 'loading' | 'skeleton';\n suffixIcon?: BitkitIconComponent;\n}\n\nconst BitkitButton = forwardRef<HTMLButtonElement, BitkitButtonProps>((props, ref) => {\n const { children, icon: Icon, size, state, suffixIcon: SuffixIcon, ...rest } = props;\n\n const iconSize = size === 'sm' ? '16' : '24';\n\n return (\n <Skeleton asChild loading={state === 'skeleton'}>\n <Button disabled={state === 'disabled'} loading={state === 'loading'} ref={ref} size={size} {...rest}>\n {Icon && <Icon marginInlineStart=\"-4\" size={iconSize} />}\n {children}\n {SuffixIcon && <SuffixIcon marginInlineEnd=\"-4\" size={iconSize} />}\n </Button>\n </Skeleton>\n );\n});\n\nBitkitButton.displayName = 'BitkitButton';\n\nexport default BitkitButton;\n"],"mappings":";;;;;AAgBA,IAAM,eAAe,YAAkD,OAAO,QAAQ;CACpF,MAAM,EAAE,UAAU,MAAM,MAAM,MAAM,OAAO,YAAY,YAAY,GAAG,SAAS;CAE/E,MAAM,WAAW,SAAS,OAAO,OAAO;CAExC,OACE,oBAAC,UAAD;EAAU,SAAA;EAAQ,SAAS,UAAU;YACnC,qBAAC,QAAD;GAAQ,UAAU,UAAU;GAAY,SAAS,UAAU;GAAgB;GAAW;GAAM,GAAI;aAAhG;IACG,QAAQ,oBAAC,MAAD;KAAM,mBAAkB;KAAK,MAAM;IAAW,CAAA;IACtD;IACA,cAAc,oBAAC,YAAD;KAAY,iBAAgB;KAAK,MAAM;IAAW,CAAA;GAC3D;;CACA,CAAA;AAEd,CAAC;AAED,aAAa,cAAc"}
1
+ {"version":3,"file":"BitkitButton.js","names":[],"sources":["../../../lib/components/BitkitButton/BitkitButton.tsx"],"sourcesContent":["import { Button, type ButtonProps } from '@chakra-ui/react/button';\nimport { Skeleton } from '@chakra-ui/react/skeleton';\nimport { chakra, type HTMLChakraProps, type RecipeProps, useRecipe } from '@chakra-ui/react/styled-system';\nimport {\n Children,\n cloneElement,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type ReactElement,\n type ReactNode,\n type Ref,\n} from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\n\ntype BitkitButtonOmittedFromButton =\n | 'asChild'\n | 'children'\n | 'colorPalette'\n | 'disabled'\n | 'loading'\n | 'loadingText'\n | 'spinner'\n | 'spinnerPlacement';\n\ninterface BitkitButtonCommonProps {\n icon?: BitkitIconComponent;\n suffixIcon?: BitkitIconComponent;\n}\n\nexport interface BitkitButtonAsButtonProps\n extends BitkitButtonCommonProps, Omit<ButtonProps, BitkitButtonOmittedFromButton> {\n asChild?: false;\n children: string;\n href?: undefined;\n isExternal?: undefined;\n state?: 'disabled' | 'loading' | 'skeleton';\n}\n\nexport interface BitkitButtonAsAnchorProps\n extends BitkitButtonCommonProps, Omit<HTMLChakraProps<'a'>, 'children' | 'colorPalette'>, RecipeProps<'button'> {\n asChild?: false;\n children: string;\n href: string;\n isExternal?: boolean;\n state?: 'disabled' | 'skeleton';\n}\n\ninterface BitkitButtonAsChildProps extends BitkitButtonCommonProps, Omit<ButtonProps, BitkitButtonOmittedFromButton> {\n asChild: true;\n children: ReactElement;\n href?: undefined;\n isExternal?: undefined;\n state?: 'disabled' | 'loading' | 'skeleton';\n}\n\nexport type BitkitButtonProps = BitkitButtonAsButtonProps | BitkitButtonAsAnchorProps | BitkitButtonAsChildProps;\n\n// The forwarded ref is typed as HTMLElement to cover all three modes (button, anchor, slot/asChild),\n// since asChild can render any element (router Link, custom wrappers, etc.). Inner narrow casts\n// satisfy the wrapped Chakra components without affecting the consumer-visible ref shape.\nconst BitkitButton = forwardRef<HTMLElement, BitkitButtonProps>((props, ref) => {\n const buttonRecipe = useRecipe({ key: 'button' });\n const Icon = props.icon;\n const SuffixIcon = props.suffixIcon;\n const iconSize = props.size === 'sm' ? '16' : '24';\n const isDisabled = props.state === 'disabled';\n const isSkeleton = props.state === 'skeleton';\n\n // --- Slot mode (asChild) ---\n if (props.asChild) {\n const { asChild: _asChild, children, icon: _icon, state, suffixIcon: _suffixIcon, ...buttonRest } = props;\n const onlyChild = Children.only(children) as ReactElement<{ children?: ReactNode }>;\n const buttonElement = (\n <Button\n asChild\n disabled={isDisabled}\n loading={state === 'loading'}\n ref={ref as Ref<HTMLButtonElement>}\n {...buttonRest}\n >\n {cloneElement(\n onlyChild,\n undefined,\n <>\n {Icon && <Icon marginInlineStart=\"-4\" size={iconSize} />}\n {onlyChild.props.children}\n {SuffixIcon && <SuffixIcon marginInlineEnd=\"-4\" size={iconSize} />}\n </>,\n )}\n </Button>\n );\n return isSkeleton ? (\n <Skeleton asChild loading>\n {buttonElement}\n </Skeleton>\n ) : (\n buttonElement\n );\n }\n\n // --- Anchor mode (href) ---\n if (props.href !== undefined) {\n const {\n children,\n css,\n href,\n icon: _icon,\n isExternal,\n onClick,\n onKeyDown,\n rel,\n size,\n state: _state,\n suffixIcon: _suffixIcon,\n target,\n variant,\n ...anchorRest\n } = props;\n const effectiveTarget = isExternal ? '_blank' : target;\n const effectiveRel = isExternal ? (rel ? `${rel} noreferrer noopener` : 'noreferrer noopener') : rel;\n const handleClick = isDisabled\n ? (e: MouseEvent<HTMLAnchorElement>) => {\n e.preventDefault();\n e.stopPropagation();\n }\n : onClick;\n const handleKeyDown = isDisabled\n ? (e: KeyboardEvent<HTMLAnchorElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n : onKeyDown;\n const anchorElement = (\n <chakra.a\n ref={ref as Ref<HTMLAnchorElement>}\n {...anchorRest}\n aria-disabled={isDisabled || undefined}\n css={[buttonRecipe({ size, variant }), css]}\n href={isDisabled ? undefined : href}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n rel={effectiveRel}\n target={effectiveTarget}\n >\n {Icon && <Icon marginInlineStart=\"-4\" size={iconSize} />}\n {children}\n {SuffixIcon && <SuffixIcon marginInlineEnd=\"-4\" size={iconSize} />}\n </chakra.a>\n );\n return isSkeleton ? (\n <Skeleton asChild loading>\n {anchorElement}\n </Skeleton>\n ) : (\n anchorElement\n );\n }\n\n // --- Button mode (default) ---\n const { children, icon: _icon, state, suffixIcon: _suffixIcon, ...buttonRest } = props;\n return (\n <Skeleton asChild loading={isSkeleton}>\n <Button disabled={isDisabled} loading={state === 'loading'} ref={ref as Ref<HTMLButtonElement>} {...buttonRest}>\n {Icon && <Icon marginInlineStart=\"-4\" size={iconSize} />}\n {children}\n {SuffixIcon && <SuffixIcon marginInlineEnd=\"-4\" size={iconSize} />}\n </Button>\n </Skeleton>\n );\n});\n\nBitkitButton.displayName = 'BitkitButton';\n\nexport default BitkitButton;\n"],"mappings":";;;;;;AA8DA,IAAM,eAAe,YAA4C,OAAO,QAAQ;CAC9E,MAAM,eAAe,UAAU,EAAE,KAAK,SAAS,CAAC;CAChD,MAAM,OAAO,MAAM;CACnB,MAAM,aAAa,MAAM;CACzB,MAAM,WAAW,MAAM,SAAS,OAAO,OAAO;CAC9C,MAAM,aAAa,MAAM,UAAU;CACnC,MAAM,aAAa,MAAM,UAAU;CAGnC,IAAI,MAAM,SAAS;EACjB,MAAM,EAAE,SAAS,UAAU,UAAU,MAAM,OAAO,OAAO,YAAY,aAAa,GAAG,eAAe;EACpG,MAAM,YAAY,SAAS,KAAK,QAAQ;EACxC,MAAM,gBACJ,oBAAC,QAAD;GACE,SAAA;GACA,UAAU;GACV,SAAS,UAAU;GACd;GACL,GAAI;aAEH,aACC,WACA,KAAA,GACA,qBAAA,YAAA,EAAA,UAAA;IACG,QAAQ,oBAAC,MAAD;KAAM,mBAAkB;KAAK,MAAM;IAAW,CAAA;IACtD,UAAU,MAAM;IAChB,cAAc,oBAAC,YAAD;KAAY,iBAAgB;KAAK,MAAM;IAAW,CAAA;GACjE,EAAA,CAAA,CACJ;EACM,CAAA;EAEV,OAAO,aACL,oBAAC,UAAD;GAAU,SAAA;GAAQ,SAAA;aACf;EACO,CAAA,IAEV;CAEJ;CAGA,IAAI,MAAM,SAAS,KAAA,GAAW;EAC5B,MAAM,EACJ,UACA,KACA,MACA,MAAM,OACN,YACA,SACA,WACA,KACA,MACA,OAAO,QACP,YAAY,aACZ,QACA,SACA,GAAG,eACD;EACJ,MAAM,kBAAkB,aAAa,WAAW;EAChD,MAAM,eAAe,aAAc,MAAM,GAAG,IAAI,wBAAwB,wBAAyB;EACjG,MAAM,cAAc,cACf,MAAqC;GACpC,EAAE,eAAe;GACjB,EAAE,gBAAgB;EACpB,IACA;EACJ,MAAM,gBAAgB,cACjB,MAAwC;GACvC,IAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;IACtC,EAAE,eAAe;IACjB,EAAE,gBAAgB;GACpB;EACF,IACA;EACJ,MAAM,gBACJ,qBAAC,OAAO,GAAR;GACO;GACL,GAAI;GACJ,iBAAe,cAAc,KAAA;GAC7B,KAAK,CAAC,aAAa;IAAE;IAAM;GAAQ,CAAC,GAAG,GAAG;GAC1C,MAAM,aAAa,KAAA,IAAY;GAC/B,SAAS;GACT,WAAW;GACX,KAAK;GACL,QAAQ;aATV;IAWG,QAAQ,oBAAC,MAAD;KAAM,mBAAkB;KAAK,MAAM;IAAW,CAAA;IACtD;IACA,cAAc,oBAAC,YAAD;KAAY,iBAAgB;KAAK,MAAM;IAAW,CAAA;GACzD;;EAEZ,OAAO,aACL,oBAAC,UAAD;GAAU,SAAA;GAAQ,SAAA;aACf;EACO,CAAA,IAEV;CAEJ;CAGA,MAAM,EAAE,UAAU,MAAM,OAAO,OAAO,YAAY,aAAa,GAAG,eAAe;CACjF,OACE,oBAAC,UAAD;EAAU,SAAA;EAAQ,SAAS;YACzB,qBAAC,QAAD;GAAQ,UAAU;GAAY,SAAS,UAAU;GAAgB;GAA+B,GAAI;aAApG;IACG,QAAQ,oBAAC,MAAD;KAAM,mBAAkB;KAAK,MAAM;IAAW,CAAA;IACtD;IACA,cAAc,oBAAC,YAAD;KAAY,iBAAgB;KAAK,MAAM;IAAW,CAAA;GAC3D;;CACA,CAAA;AAEd,CAAC;AAED,aAAa,cAAc"}
@@ -5,8 +5,12 @@ export interface BitkitCheckboxGroupProps extends Fieldset.RootProps {
5
5
  checkboxGroupProps?: CheckboxGroupProps;
6
6
  children: ReactNode;
7
7
  errorText?: string;
8
+ /**
9
+ * Visible legend rendered above the group. Optional — if you omit it, pass `aria-label` or
10
+ * `aria-labelledby` instead so the fieldset still has an accessible name.
11
+ */
12
+ groupLabel?: string;
8
13
  helperText?: string;
9
- label: string;
10
14
  name?: CheckboxGroupProps['name'];
11
15
  onValueChange: CheckboxGroupProps['onValueChange'];
12
16
  value: CheckboxGroupProps['value'];
@@ -4,19 +4,20 @@ import { CheckboxGroup } from "@chakra-ui/react/checkbox";
4
4
  import { Fieldset } from "@chakra-ui/react/fieldset";
5
5
  //#region lib/components/BitkitCheckboxGroup/BitkitCheckboxGroup.tsx
6
6
  var BitkitCheckboxGroup = forwardRef((props, ref) => {
7
- const { checkboxGroupProps, children, errorText, helperText, label, name, onValueChange, value, ...rest } = props;
7
+ const { checkboxGroupProps, children, errorText, helperText, groupLabel, name, onValueChange, value, ...rest } = props;
8
+ const hasHeader = !!groupLabel || !!helperText;
8
9
  return /* @__PURE__ */ jsxs(Fieldset.Root, {
9
10
  ref,
10
11
  ...rest,
11
12
  invalid: rest.invalid || !!errorText,
12
13
  children: [
13
- /* @__PURE__ */ jsx(Fieldset.Legend, { children: label }),
14
+ groupLabel && /* @__PURE__ */ jsx(Fieldset.Legend, { children: groupLabel }),
14
15
  !!helperText && /* @__PURE__ */ jsx(Fieldset.HelperText, { children: helperText }),
15
16
  /* @__PURE__ */ jsx(Fieldset.Content, {
16
17
  display: "flex",
17
18
  flexDirection: "column",
18
19
  gap: "12",
19
- marginBlockStart: "12",
20
+ marginBlockStart: hasHeader ? "12" : void 0,
20
21
  asChild: true,
21
22
  children: /* @__PURE__ */ jsx(CheckboxGroup, {
22
23
  name,
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitCheckboxGroup.js","names":[],"sources":["../../../lib/components/BitkitCheckboxGroup/BitkitCheckboxGroup.tsx"],"sourcesContent":["import { CheckboxGroup, type CheckboxGroupProps } from '@chakra-ui/react/checkbox';\nimport { Fieldset } from '@chakra-ui/react/fieldset';\nimport { forwardRef, type ReactNode } from 'react';\n\nexport interface BitkitCheckboxGroupProps extends Fieldset.RootProps {\n checkboxGroupProps?: CheckboxGroupProps;\n children: ReactNode;\n errorText?: string;\n helperText?: string;\n label: string;\n name?: CheckboxGroupProps['name'];\n onValueChange: CheckboxGroupProps['onValueChange'];\n value: CheckboxGroupProps['value'];\n}\n\nconst BitkitCheckboxGroup = forwardRef<HTMLFieldSetElement, BitkitCheckboxGroupProps>((props, ref) => {\n const { checkboxGroupProps, children, errorText, helperText, label, name, onValueChange, value, ...rest } = props;\n return (\n <Fieldset.Root ref={ref} {...rest} invalid={rest.invalid || !!errorText}>\n <Fieldset.Legend>{label}</Fieldset.Legend>\n {!!helperText && <Fieldset.HelperText>{helperText}</Fieldset.HelperText>}\n <Fieldset.Content display=\"flex\" flexDirection=\"column\" gap=\"12\" marginBlockStart=\"12\" asChild>\n <CheckboxGroup name={name} onValueChange={onValueChange} value={value} {...checkboxGroupProps}>\n {children}\n </CheckboxGroup>\n </Fieldset.Content>\n {!!errorText && <Fieldset.ErrorText>{errorText}</Fieldset.ErrorText>}\n </Fieldset.Root>\n );\n});\n\nBitkitCheckboxGroup.displayName = 'BitkitCheckboxGroup';\n\nexport default BitkitCheckboxGroup;\n"],"mappings":";;;;;AAeA,IAAM,sBAAsB,YAA2D,OAAO,QAAQ;CACpG,MAAM,EAAE,oBAAoB,UAAU,WAAW,YAAY,OAAO,MAAM,eAAe,OAAO,GAAG,SAAS;CAC5G,OACE,qBAAC,SAAS,MAAV;EAAoB;EAAK,GAAI;EAAM,SAAS,KAAK,WAAW,CAAC,CAAC;YAA9D;GACE,oBAAC,SAAS,QAAV,EAAA,UAAkB,MAAuB,CAAA;GACxC,CAAC,CAAC,cAAc,oBAAC,SAAS,YAAV,EAAA,UAAsB,WAAgC,CAAA;GACvE,oBAAC,SAAS,SAAV;IAAkB,SAAQ;IAAO,eAAc;IAAS,KAAI;IAAK,kBAAiB;IAAK,SAAA;cACrF,oBAAC,eAAD;KAAqB;KAAqB;KAAsB;KAAO,GAAI;KACxE;IACY,CAAA;GACC,CAAA;GACjB,CAAC,CAAC,aAAa,oBAAC,SAAS,WAAV,EAAA,UAAqB,UAA8B,CAAA;EACtD;;AAEnB,CAAC;AAED,oBAAoB,cAAc"}
1
+ {"version":3,"file":"BitkitCheckboxGroup.js","names":[],"sources":["../../../lib/components/BitkitCheckboxGroup/BitkitCheckboxGroup.tsx"],"sourcesContent":["import { CheckboxGroup, type CheckboxGroupProps } from '@chakra-ui/react/checkbox';\nimport { Fieldset } from '@chakra-ui/react/fieldset';\nimport { forwardRef, type ReactNode } from 'react';\n\nexport interface BitkitCheckboxGroupProps extends Fieldset.RootProps {\n checkboxGroupProps?: CheckboxGroupProps;\n children: ReactNode;\n errorText?: string;\n /**\n * Visible legend rendered above the group. Optional — if you omit it, pass `aria-label` or\n * `aria-labelledby` instead so the fieldset still has an accessible name.\n */\n groupLabel?: string;\n helperText?: string;\n name?: CheckboxGroupProps['name'];\n onValueChange: CheckboxGroupProps['onValueChange'];\n value: CheckboxGroupProps['value'];\n}\n\nconst BitkitCheckboxGroup = forwardRef<HTMLFieldSetElement, BitkitCheckboxGroupProps>((props, ref) => {\n const { checkboxGroupProps, children, errorText, helperText, groupLabel, name, onValueChange, value, ...rest } =\n props;\n const hasHeader = !!groupLabel || !!helperText;\n return (\n <Fieldset.Root ref={ref} {...rest} invalid={rest.invalid || !!errorText}>\n {groupLabel && <Fieldset.Legend>{groupLabel}</Fieldset.Legend>}\n {!!helperText && <Fieldset.HelperText>{helperText}</Fieldset.HelperText>}\n <Fieldset.Content\n display=\"flex\"\n flexDirection=\"column\"\n gap=\"12\"\n marginBlockStart={hasHeader ? '12' : undefined}\n asChild\n >\n <CheckboxGroup name={name} onValueChange={onValueChange} value={value} {...checkboxGroupProps}>\n {children}\n </CheckboxGroup>\n </Fieldset.Content>\n {!!errorText && <Fieldset.ErrorText>{errorText}</Fieldset.ErrorText>}\n </Fieldset.Root>\n );\n});\n\nBitkitCheckboxGroup.displayName = 'BitkitCheckboxGroup';\n\nexport default BitkitCheckboxGroup;\n"],"mappings":";;;;;AAmBA,IAAM,sBAAsB,YAA2D,OAAO,QAAQ;CACpG,MAAM,EAAE,oBAAoB,UAAU,WAAW,YAAY,YAAY,MAAM,eAAe,OAAO,GAAG,SACtG;CACF,MAAM,YAAY,CAAC,CAAC,cAAc,CAAC,CAAC;CACpC,OACE,qBAAC,SAAS,MAAV;EAAoB;EAAK,GAAI;EAAM,SAAS,KAAK,WAAW,CAAC,CAAC;YAA9D;GACG,cAAc,oBAAC,SAAS,QAAV,EAAA,UAAkB,WAA4B,CAAA;GAC5D,CAAC,CAAC,cAAc,oBAAC,SAAS,YAAV,EAAA,UAAsB,WAAgC,CAAA;GACvE,oBAAC,SAAS,SAAV;IACE,SAAQ;IACR,eAAc;IACd,KAAI;IACJ,kBAAkB,YAAY,OAAO,KAAA;IACrC,SAAA;cAEA,oBAAC,eAAD;KAAqB;KAAqB;KAAsB;KAAO,GAAI;KACxE;IACY,CAAA;GACC,CAAA;GACjB,CAAC,CAAC,aAAa,oBAAC,SAAS,WAAV,EAAA,UAAqB,UAA8B,CAAA;EACtD;;AAEnB,CAAC;AAED,oBAAoB,cAAc"}
@@ -2,7 +2,7 @@ import { HTMLChakraProps } from '@chakra-ui/react/styled-system';
2
2
  import { BitkitIconComponent } from '../../icons';
3
3
  import { BitkitLabelTooltipProps } from '../BitkitLabelTooltip/BitkitLabelTooltip';
4
4
  type ControlButtonSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg';
5
- export interface BitkitControlButtonProps extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled' | 'size'> {
5
+ interface BitkitControlButtonCommonProps {
6
6
  icon: BitkitIconComponent;
7
7
  isDanger?: boolean;
8
8
  label: string;
@@ -10,5 +10,14 @@ export interface BitkitControlButtonProps extends Omit<HTMLChakraProps<'button'>
10
10
  state?: 'disabled' | 'skeleton';
11
11
  tooltipProps?: Partial<Omit<BitkitLabelTooltipProps, 'children' | 'text'>>;
12
12
  }
13
- declare const BitkitControlButton: import('react').ForwardRefExoticComponent<BitkitControlButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
13
+ interface BitkitControlButtonAsButtonProps extends BitkitControlButtonCommonProps, Omit<HTMLChakraProps<'button'>, 'children' | 'disabled' | 'size'> {
14
+ href?: undefined;
15
+ isExternal?: undefined;
16
+ }
17
+ interface BitkitControlButtonAsAnchorProps extends BitkitControlButtonCommonProps, Omit<HTMLChakraProps<'a'>, 'children' | 'size'> {
18
+ href: string;
19
+ isExternal?: boolean;
20
+ }
21
+ export type BitkitControlButtonProps = BitkitControlButtonAsButtonProps | BitkitControlButtonAsAnchorProps;
22
+ declare const BitkitControlButton: import('react').ForwardRefExoticComponent<BitkitControlButtonProps & import('react').RefAttributes<HTMLButtonElement | HTMLAnchorElement>>;
14
23
  export default BitkitControlButton;
@@ -5,9 +5,52 @@ import { jsx } from "react/jsx-runtime";
5
5
  import { Skeleton } from "@chakra-ui/react/skeleton";
6
6
  //#region lib/components/BitkitControlButton/BitkitControlButton.tsx
7
7
  var BitkitControlButton = forwardRef((props, ref) => {
8
- const { icon: Icon, isDanger, label, size = "sm", state, tooltipProps, ...rest } = props;
8
+ const Icon = props.icon;
9
+ const size = props.size ?? "sm";
9
10
  const recipe = useRecipe({ key: "controlButton" });
10
11
  const iconSize = size === "xxs" || size === "xs" ? "16" : "24";
12
+ const isDisabled = props.state === "disabled";
13
+ const isSkeleton = props.state === "skeleton";
14
+ const inertOnClick = isDisabled || isSkeleton;
15
+ if (props.href !== void 0) {
16
+ const { href, icon: _icon, isDanger, isExternal, label, onClick, onKeyDown, rel, size: _size, state: _state, target, tooltipProps, ...anchorRest } = props;
17
+ const effectiveTarget = isExternal ? "_blank" : target;
18
+ const effectiveRel = isExternal ? rel ? `${rel} noreferrer noopener` : "noreferrer noopener" : rel;
19
+ const handleClick = inertOnClick ? (e) => {
20
+ e.preventDefault();
21
+ e.stopPropagation();
22
+ } : onClick;
23
+ const handleKeyDown = inertOnClick ? (e) => {
24
+ if (e.key === "Enter" || e.key === " ") {
25
+ e.preventDefault();
26
+ e.stopPropagation();
27
+ }
28
+ } : onKeyDown;
29
+ return /* @__PURE__ */ jsx(BitkitLabelTooltip, {
30
+ text: label,
31
+ ...tooltipProps,
32
+ children: /* @__PURE__ */ jsx(chakra.a, {
33
+ ref,
34
+ "aria-disabled": inertOnClick || void 0,
35
+ "aria-label": label,
36
+ ...anchorRest,
37
+ css: recipe({
38
+ isDanger,
39
+ size
40
+ }),
41
+ href: inertOnClick ? void 0 : href,
42
+ onClick: handleClick,
43
+ onKeyDown: handleKeyDown,
44
+ rel: effectiveRel,
45
+ target: effectiveTarget,
46
+ children: /* @__PURE__ */ jsx(Skeleton, {
47
+ loading: isSkeleton,
48
+ children: /* @__PURE__ */ jsx(Icon, { size: iconSize })
49
+ })
50
+ })
51
+ });
52
+ }
53
+ const { icon: _icon, isDanger, label, size: _size, state, tooltipProps, ...buttonRest } = props;
11
54
  return /* @__PURE__ */ jsx(BitkitLabelTooltip, {
12
55
  text: label,
13
56
  ...tooltipProps,
@@ -15,13 +58,13 @@ var BitkitControlButton = forwardRef((props, ref) => {
15
58
  ref,
16
59
  "aria-label": label,
17
60
  disabled: state === "disabled" || state === "skeleton",
18
- ...rest,
61
+ ...buttonRest,
19
62
  css: recipe({
20
63
  isDanger,
21
64
  size
22
65
  }),
23
66
  children: /* @__PURE__ */ jsx(Skeleton, {
24
- loading: state === "skeleton",
67
+ loading: isSkeleton,
25
68
  children: /* @__PURE__ */ jsx(Icon, { size: iconSize })
26
69
  })
27
70
  })
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitControlButton.js","names":[],"sources":["../../../lib/components/BitkitControlButton/BitkitControlButton.tsx"],"sourcesContent":["import { Skeleton } from '@chakra-ui/react/skeleton';\nimport { chakra, type HTMLChakraProps, useRecipe } from '@chakra-ui/react/styled-system';\nimport { forwardRef } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport BitkitLabelTooltip, { type BitkitLabelTooltipProps } from '../BitkitLabelTooltip/BitkitLabelTooltip';\n\ntype ControlButtonSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg';\n\nexport interface BitkitControlButtonProps extends Omit<HTMLChakraProps<'button'>, 'children' | 'disabled' | 'size'> {\n icon: BitkitIconComponent;\n isDanger?: boolean;\n label: string;\n size?: ControlButtonSize;\n state?: 'disabled' | 'skeleton';\n tooltipProps?: Partial<Omit<BitkitLabelTooltipProps, 'children' | 'text'>>;\n}\n\nconst BitkitControlButton = forwardRef<HTMLButtonElement, BitkitControlButtonProps>((props, ref) => {\n const { icon: Icon, isDanger, label, size = 'sm', state, tooltipProps, ...rest } = props;\n\n const recipe = useRecipe({ key: 'controlButton' });\n const iconSize = size === 'xxs' || size === 'xs' ? '16' : '24';\n\n return (\n <BitkitLabelTooltip text={label} {...tooltipProps}>\n <chakra.button\n ref={ref}\n aria-label={label}\n disabled={state === 'disabled' || state === 'skeleton'}\n {...rest}\n css={recipe({ isDanger, size })}\n >\n <Skeleton loading={state === 'skeleton'}>\n <Icon size={iconSize} />\n </Skeleton>\n </chakra.button>\n </BitkitLabelTooltip>\n );\n});\n\nBitkitControlButton.displayName = 'BitkitControlButton';\n\nexport default BitkitControlButton;\n"],"mappings":";;;;;;AAkBA,IAAM,sBAAsB,YAAyD,OAAO,QAAQ;CAClG,MAAM,EAAE,MAAM,MAAM,UAAU,OAAO,OAAO,MAAM,OAAO,cAAc,GAAG,SAAS;CAEnF,MAAM,SAAS,UAAU,EAAE,KAAK,gBAAgB,CAAC;CACjD,MAAM,WAAW,SAAS,SAAS,SAAS,OAAO,OAAO;CAE1D,OACE,oBAAC,oBAAD;EAAoB,MAAM;EAAO,GAAI;YACnC,oBAAC,OAAO,QAAR;GACO;GACL,cAAY;GACZ,UAAU,UAAU,cAAc,UAAU;GAC5C,GAAI;GACJ,KAAK,OAAO;IAAE;IAAU;GAAK,CAAC;aAE9B,oBAAC,UAAD;IAAU,SAAS,UAAU;cAC3B,oBAAC,MAAD,EAAM,MAAM,SAAW,CAAA;GACf,CAAA;EACG,CAAA;CACG,CAAA;AAExB,CAAC;AAED,oBAAoB,cAAc"}
1
+ {"version":3,"file":"BitkitControlButton.js","names":[],"sources":["../../../lib/components/BitkitControlButton/BitkitControlButton.tsx"],"sourcesContent":["import { Skeleton } from '@chakra-ui/react/skeleton';\nimport { chakra, type HTMLChakraProps, useRecipe } from '@chakra-ui/react/styled-system';\nimport { forwardRef, type KeyboardEvent, type MouseEvent, type Ref } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport BitkitLabelTooltip, { type BitkitLabelTooltipProps } from '../BitkitLabelTooltip/BitkitLabelTooltip';\n\ntype ControlButtonSize = 'xxs' | 'xs' | 'sm' | 'md' | 'lg';\n\ninterface BitkitControlButtonCommonProps {\n icon: BitkitIconComponent;\n isDanger?: boolean;\n label: string;\n size?: ControlButtonSize;\n state?: 'disabled' | 'skeleton';\n tooltipProps?: Partial<Omit<BitkitLabelTooltipProps, 'children' | 'text'>>;\n}\n\ninterface BitkitControlButtonAsButtonProps\n extends BitkitControlButtonCommonProps, Omit<HTMLChakraProps<'button'>, 'children' | 'disabled' | 'size'> {\n href?: undefined;\n isExternal?: undefined;\n}\n\ninterface BitkitControlButtonAsAnchorProps\n extends BitkitControlButtonCommonProps, Omit<HTMLChakraProps<'a'>, 'children' | 'size'> {\n href: string;\n isExternal?: boolean;\n}\n\nexport type BitkitControlButtonProps = BitkitControlButtonAsButtonProps | BitkitControlButtonAsAnchorProps;\n\nconst BitkitControlButton = forwardRef<HTMLButtonElement | HTMLAnchorElement, BitkitControlButtonProps>(\n (props, ref) => {\n const Icon = props.icon;\n const size = props.size ?? 'sm';\n const recipe = useRecipe({ key: 'controlButton' });\n const iconSize = size === 'xxs' || size === 'xs' ? '16' : '24';\n const isDisabled = props.state === 'disabled';\n const isSkeleton = props.state === 'skeleton';\n const inertOnClick = isDisabled || isSkeleton;\n\n // --- Anchor mode (href) ---\n if (props.href !== undefined) {\n const {\n href,\n icon: _icon,\n isDanger,\n isExternal,\n label,\n onClick,\n onKeyDown,\n rel,\n size: _size,\n state: _state,\n target,\n tooltipProps,\n ...anchorRest\n } = props;\n const effectiveTarget = isExternal ? '_blank' : target;\n const effectiveRel = isExternal ? (rel ? `${rel} noreferrer noopener` : 'noreferrer noopener') : rel;\n const handleClick = inertOnClick\n ? (e: MouseEvent<HTMLAnchorElement>) => {\n e.preventDefault();\n e.stopPropagation();\n }\n : onClick;\n const handleKeyDown = inertOnClick\n ? (e: KeyboardEvent<HTMLAnchorElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n : onKeyDown;\n return (\n <BitkitLabelTooltip text={label} {...tooltipProps}>\n <chakra.a\n ref={ref as Ref<HTMLAnchorElement>}\n aria-disabled={inertOnClick || undefined}\n aria-label={label}\n {...anchorRest}\n css={recipe({ isDanger, size })}\n href={inertOnClick ? undefined : href}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n rel={effectiveRel}\n target={effectiveTarget}\n >\n <Skeleton loading={isSkeleton}>\n <Icon size={iconSize} />\n </Skeleton>\n </chakra.a>\n </BitkitLabelTooltip>\n );\n }\n\n // --- Button mode (default) ---\n const { icon: _icon, isDanger, label, size: _size, state, tooltipProps, ...buttonRest } = props;\n return (\n <BitkitLabelTooltip text={label} {...tooltipProps}>\n <chakra.button\n ref={ref as Ref<HTMLButtonElement>}\n aria-label={label}\n disabled={state === 'disabled' || state === 'skeleton'}\n {...buttonRest}\n css={recipe({ isDanger, size })}\n >\n <Skeleton loading={isSkeleton}>\n <Icon size={iconSize} />\n </Skeleton>\n </chakra.button>\n </BitkitLabelTooltip>\n );\n },\n);\n\nBitkitControlButton.displayName = 'BitkitControlButton';\n\nexport default BitkitControlButton;\n"],"mappings":";;;;;;AAgCA,IAAM,sBAAsB,YACzB,OAAO,QAAQ;CACd,MAAM,OAAO,MAAM;CACnB,MAAM,OAAO,MAAM,QAAQ;CAC3B,MAAM,SAAS,UAAU,EAAE,KAAK,gBAAgB,CAAC;CACjD,MAAM,WAAW,SAAS,SAAS,SAAS,OAAO,OAAO;CAC1D,MAAM,aAAa,MAAM,UAAU;CACnC,MAAM,aAAa,MAAM,UAAU;CACnC,MAAM,eAAe,cAAc;CAGnC,IAAI,MAAM,SAAS,KAAA,GAAW;EAC5B,MAAM,EACJ,MACA,MAAM,OACN,UACA,YACA,OACA,SACA,WACA,KACA,MAAM,OACN,OAAO,QACP,QACA,cACA,GAAG,eACD;EACJ,MAAM,kBAAkB,aAAa,WAAW;EAChD,MAAM,eAAe,aAAc,MAAM,GAAG,IAAI,wBAAwB,wBAAyB;EACjG,MAAM,cAAc,gBACf,MAAqC;GACpC,EAAE,eAAe;GACjB,EAAE,gBAAgB;EACpB,IACA;EACJ,MAAM,gBAAgB,gBACjB,MAAwC;GACvC,IAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;IACtC,EAAE,eAAe;IACjB,EAAE,gBAAgB;GACpB;EACF,IACA;EACJ,OACE,oBAAC,oBAAD;GAAoB,MAAM;GAAO,GAAI;aACnC,oBAAC,OAAO,GAAR;IACO;IACL,iBAAe,gBAAgB,KAAA;IAC/B,cAAY;IACZ,GAAI;IACJ,KAAK,OAAO;KAAE;KAAU;IAAK,CAAC;IAC9B,MAAM,eAAe,KAAA,IAAY;IACjC,SAAS;IACT,WAAW;IACX,KAAK;IACL,QAAQ;cAER,oBAAC,UAAD;KAAU,SAAS;eACjB,oBAAC,MAAD,EAAM,MAAM,SAAW,CAAA;IACf,CAAA;GACF,CAAA;EACQ,CAAA;CAExB;CAGA,MAAM,EAAE,MAAM,OAAO,UAAU,OAAO,MAAM,OAAO,OAAO,cAAc,GAAG,eAAe;CAC1F,OACE,oBAAC,oBAAD;EAAoB,MAAM;EAAO,GAAI;YACnC,oBAAC,OAAO,QAAR;GACO;GACL,cAAY;GACZ,UAAU,UAAU,cAAc,UAAU;GAC5C,GAAI;GACJ,KAAK,OAAO;IAAE;IAAU;GAAK,CAAC;aAE9B,oBAAC,UAAD;IAAU,SAAS;cACjB,oBAAC,MAAD,EAAM,MAAM,SAAW,CAAA;GACf,CAAA;EACG,CAAA;CACG,CAAA;AAExB,CACF;AAEA,oBAAoB,cAAc"}
@@ -1,11 +1,33 @@
1
1
  import { IconButtonProps } from '@chakra-ui/react/button';
2
+ import { HTMLChakraProps, RecipeProps } from '@chakra-ui/react/styled-system';
3
+ import { ReactElement } from 'react';
2
4
  import { BitkitIconComponent } from '../../icons';
3
5
  import { BitkitLabelTooltipProps } from '../BitkitLabelTooltip/BitkitLabelTooltip';
4
- export interface BitkitIconButtonProps extends Omit<IconButtonProps, 'aria-label' | 'children' | 'colorPalette' | 'disabled' | 'loading' | 'loadingText' | 'spinner' | 'spinnerPlacement'> {
6
+ type BitkitIconButtonOmittedFromButton = 'aria-label' | 'asChild' | 'children' | 'colorPalette' | 'disabled' | 'loading' | 'loadingText' | 'spinner' | 'spinnerPlacement';
7
+ interface BitkitIconButtonCommonProps {
5
8
  icon: BitkitIconComponent;
6
9
  label: string;
7
- state?: 'disabled' | 'loading' | 'skeleton';
8
10
  tooltipProps?: Partial<Omit<BitkitLabelTooltipProps, 'children' | 'text'>>;
9
11
  }
10
- declare const BitkitIconButton: import('react').ForwardRefExoticComponent<BitkitIconButtonProps & import('react').RefAttributes<HTMLButtonElement>>;
12
+ interface BitkitIconButtonAsButtonProps extends BitkitIconButtonCommonProps, Omit<IconButtonProps, BitkitIconButtonOmittedFromButton> {
13
+ asChild?: false;
14
+ href?: undefined;
15
+ isExternal?: undefined;
16
+ state?: 'disabled' | 'loading' | 'skeleton';
17
+ }
18
+ interface BitkitIconButtonAsAnchorProps extends BitkitIconButtonCommonProps, Omit<HTMLChakraProps<'a'>, 'aria-label' | 'children' | 'colorPalette'>, RecipeProps<'button'> {
19
+ asChild?: false;
20
+ href: string;
21
+ isExternal?: boolean;
22
+ state?: 'disabled' | 'skeleton';
23
+ }
24
+ interface BitkitIconButtonAsChildProps extends BitkitIconButtonCommonProps, Omit<IconButtonProps, BitkitIconButtonOmittedFromButton> {
25
+ asChild: true;
26
+ children: ReactElement;
27
+ href?: undefined;
28
+ isExternal?: undefined;
29
+ state?: 'disabled' | 'loading' | 'skeleton';
30
+ }
31
+ export type BitkitIconButtonProps = BitkitIconButtonAsButtonProps | BitkitIconButtonAsAnchorProps | BitkitIconButtonAsChildProps;
32
+ declare const BitkitIconButton: import('react').ForwardRefExoticComponent<BitkitIconButtonProps & import('react').RefAttributes<HTMLElement>>;
11
33
  export default BitkitIconButton;
@@ -1,25 +1,98 @@
1
1
  import BitkitLabelTooltip from "../BitkitLabelTooltip/BitkitLabelTooltip.js";
2
- import { forwardRef } from "react";
2
+ import { chakra, useRecipe } from "@chakra-ui/react/styled-system";
3
+ import { Children, cloneElement, forwardRef } from "react";
3
4
  import { jsx } from "react/jsx-runtime";
4
5
  import { Skeleton } from "@chakra-ui/react/skeleton";
5
6
  import { IconButton } from "@chakra-ui/react/button";
6
7
  //#region lib/components/BitkitIconButton/BitkitIconButton.tsx
7
8
  var BitkitIconButton = forwardRef((props, ref) => {
8
- const { icon: Icon, label, size, state, tooltipProps, ...rest } = props;
9
- const iconSize = size === "lg" ? "24" : "16";
9
+ const buttonRecipe = useRecipe({ key: "button" });
10
+ const Icon = props.icon;
11
+ const iconSize = props.size === "lg" ? "24" : "16";
12
+ const isDisabled = props.state === "disabled";
13
+ const isSkeleton = props.state === "skeleton";
14
+ if (props.asChild) {
15
+ const { asChild: _asChild, children, icon: _icon, label, state, tooltipProps, ...buttonRest } = props;
16
+ const onlyChild = Children.only(children);
17
+ const iconButtonElement = /* @__PURE__ */ jsx(IconButton, {
18
+ asChild: true,
19
+ "aria-label": label,
20
+ disabled: isDisabled,
21
+ loading: state === "loading",
22
+ ref,
23
+ ...buttonRest,
24
+ children: cloneElement(onlyChild, { "aria-label": onlyChild.props["aria-label"] ?? label }, /* @__PURE__ */ jsx(Icon, { size: iconSize }))
25
+ });
26
+ return /* @__PURE__ */ jsx(BitkitLabelTooltip, {
27
+ text: label,
28
+ ...tooltipProps,
29
+ children: isSkeleton ? /* @__PURE__ */ jsx(Skeleton, {
30
+ asChild: true,
31
+ loading: true,
32
+ children: iconButtonElement
33
+ }) : iconButtonElement
34
+ });
35
+ }
36
+ if (props.href !== void 0) {
37
+ const { css, href, icon: _icon, isExternal, label, onClick, onKeyDown, rel, size, state: _state, target, tooltipProps, variant, ...anchorRest } = props;
38
+ const effectiveTarget = isExternal ? "_blank" : target;
39
+ const effectiveRel = isExternal ? rel ? `${rel} noreferrer noopener` : "noreferrer noopener" : rel;
40
+ const handleClick = isDisabled ? (e) => {
41
+ e.preventDefault();
42
+ e.stopPropagation();
43
+ } : onClick;
44
+ const handleKeyDown = isDisabled ? (e) => {
45
+ if (e.key === "Enter" || e.key === " ") {
46
+ e.preventDefault();
47
+ e.stopPropagation();
48
+ }
49
+ } : onKeyDown;
50
+ const anchorElement = /* @__PURE__ */ jsx(chakra.a, {
51
+ ref,
52
+ ...anchorRest,
53
+ "aria-disabled": isDisabled || void 0,
54
+ "aria-label": label,
55
+ css: [
56
+ buttonRecipe({
57
+ size,
58
+ variant
59
+ }),
60
+ {
61
+ paddingBlock: 0,
62
+ paddingInline: 0
63
+ },
64
+ css
65
+ ],
66
+ href: isDisabled ? void 0 : href,
67
+ onClick: handleClick,
68
+ onKeyDown: handleKeyDown,
69
+ rel: effectiveRel,
70
+ target: effectiveTarget,
71
+ children: /* @__PURE__ */ jsx(Icon, { size: iconSize })
72
+ });
73
+ return /* @__PURE__ */ jsx(BitkitLabelTooltip, {
74
+ text: label,
75
+ ...tooltipProps,
76
+ children: isSkeleton ? /* @__PURE__ */ jsx(Skeleton, {
77
+ asChild: true,
78
+ loading: true,
79
+ children: anchorElement
80
+ }) : anchorElement
81
+ });
82
+ }
83
+ const { icon: _icon, label, state, tooltipProps, ...buttonRest } = props;
10
84
  return /* @__PURE__ */ jsx(BitkitLabelTooltip, {
11
85
  text: label,
12
86
  ...tooltipProps,
13
87
  children: /* @__PURE__ */ jsx(Skeleton, {
14
88
  asChild: true,
15
- loading: state === "skeleton",
89
+ loading: isSkeleton,
16
90
  children: /* @__PURE__ */ jsx(IconButton, {
17
91
  "aria-label": label,
18
- disabled: state === "disabled",
92
+ disabled: isDisabled,
19
93
  loading: state === "loading",
20
94
  ref,
21
- size,
22
- ...rest,
95
+ ...buttonRest,
23
96
  children: /* @__PURE__ */ jsx(Icon, { size: iconSize })
24
97
  })
25
98
  })
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitIconButton.js","names":[],"sources":["../../../lib/components/BitkitIconButton/BitkitIconButton.tsx"],"sourcesContent":["import { IconButton, type IconButtonProps } from '@chakra-ui/react/button';\nimport { Skeleton } from '@chakra-ui/react/skeleton';\nimport { forwardRef } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport BitkitLabelTooltip, { type BitkitLabelTooltipProps } from '../BitkitLabelTooltip/BitkitLabelTooltip';\n\nexport interface BitkitIconButtonProps extends Omit<\n IconButtonProps,\n 'aria-label' | 'children' | 'colorPalette' | 'disabled' | 'loading' | 'loadingText' | 'spinner' | 'spinnerPlacement'\n> {\n icon: BitkitIconComponent;\n label: string;\n state?: 'disabled' | 'loading' | 'skeleton';\n tooltipProps?: Partial<Omit<BitkitLabelTooltipProps, 'children' | 'text'>>;\n}\n\nconst BitkitIconButton = forwardRef<HTMLButtonElement, BitkitIconButtonProps>((props, ref) => {\n const { icon: Icon, label, size, state, tooltipProps, ...rest } = props;\n const iconSize = size === 'lg' ? '24' : '16';\n\n return (\n <BitkitLabelTooltip text={label} {...tooltipProps}>\n <Skeleton asChild loading={state === 'skeleton'}>\n <IconButton\n aria-label={label}\n disabled={state === 'disabled'}\n loading={state === 'loading'}\n ref={ref}\n size={size}\n {...rest}\n >\n <Icon size={iconSize} />\n </IconButton>\n </Skeleton>\n </BitkitLabelTooltip>\n );\n});\n\nBitkitIconButton.displayName = 'BitkitIconButton';\n\nexport default BitkitIconButton;\n"],"mappings":";;;;;;AAiBA,IAAM,mBAAmB,YAAsD,OAAO,QAAQ;CAC5F,MAAM,EAAE,MAAM,MAAM,OAAO,MAAM,OAAO,cAAc,GAAG,SAAS;CAClE,MAAM,WAAW,SAAS,OAAO,OAAO;CAExC,OACE,oBAAC,oBAAD;EAAoB,MAAM;EAAO,GAAI;YACnC,oBAAC,UAAD;GAAU,SAAA;GAAQ,SAAS,UAAU;aACnC,oBAAC,YAAD;IACE,cAAY;IACZ,UAAU,UAAU;IACpB,SAAS,UAAU;IACd;IACC;IACN,GAAI;cAEJ,oBAAC,MAAD,EAAM,MAAM,SAAW,CAAA;GACb,CAAA;EACJ,CAAA;CACQ,CAAA;AAExB,CAAC;AAED,iBAAiB,cAAc"}
1
+ {"version":3,"file":"BitkitIconButton.js","names":[],"sources":["../../../lib/components/BitkitIconButton/BitkitIconButton.tsx"],"sourcesContent":["import { IconButton, type IconButtonProps } from '@chakra-ui/react/button';\nimport { Skeleton } from '@chakra-ui/react/skeleton';\nimport { chakra, type HTMLChakraProps, type RecipeProps, useRecipe } from '@chakra-ui/react/styled-system';\nimport {\n Children,\n cloneElement,\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type ReactElement,\n type Ref,\n} from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\nimport BitkitLabelTooltip, { type BitkitLabelTooltipProps } from '../BitkitLabelTooltip/BitkitLabelTooltip';\n\ntype BitkitIconButtonOmittedFromButton =\n | 'aria-label'\n | 'asChild'\n | 'children'\n | 'colorPalette'\n | 'disabled'\n | 'loading'\n | 'loadingText'\n | 'spinner'\n | 'spinnerPlacement';\n\ninterface BitkitIconButtonCommonProps {\n icon: BitkitIconComponent;\n label: string;\n tooltipProps?: Partial<Omit<BitkitLabelTooltipProps, 'children' | 'text'>>;\n}\n\ninterface BitkitIconButtonAsButtonProps\n extends BitkitIconButtonCommonProps, Omit<IconButtonProps, BitkitIconButtonOmittedFromButton> {\n asChild?: false;\n href?: undefined;\n isExternal?: undefined;\n state?: 'disabled' | 'loading' | 'skeleton';\n}\n\ninterface BitkitIconButtonAsAnchorProps\n extends\n BitkitIconButtonCommonProps,\n Omit<HTMLChakraProps<'a'>, 'aria-label' | 'children' | 'colorPalette'>,\n RecipeProps<'button'> {\n asChild?: false;\n href: string;\n isExternal?: boolean;\n state?: 'disabled' | 'skeleton';\n}\n\ninterface BitkitIconButtonAsChildProps\n extends BitkitIconButtonCommonProps, Omit<IconButtonProps, BitkitIconButtonOmittedFromButton> {\n asChild: true;\n children: ReactElement;\n href?: undefined;\n isExternal?: undefined;\n state?: 'disabled' | 'loading' | 'skeleton';\n}\n\nexport type BitkitIconButtonProps =\n | BitkitIconButtonAsButtonProps\n | BitkitIconButtonAsAnchorProps\n | BitkitIconButtonAsChildProps;\n\n// The forwarded ref is typed as HTMLElement to cover all three modes (button, anchor, slot/asChild),\n// since asChild can render any element (router Link, custom wrappers, etc.). Inner narrow casts\n// satisfy the wrapped Chakra components without affecting the consumer-visible ref shape.\nconst BitkitIconButton = forwardRef<HTMLElement, BitkitIconButtonProps>((props, ref) => {\n const buttonRecipe = useRecipe({ key: 'button' });\n const Icon = props.icon;\n const iconSize = props.size === 'lg' ? '24' : '16';\n const isDisabled = props.state === 'disabled';\n const isSkeleton = props.state === 'skeleton';\n\n // --- Slot mode (asChild) ---\n if (props.asChild) {\n const { asChild: _asChild, children, icon: _icon, label, state, tooltipProps, ...buttonRest } = props;\n const onlyChild = Children.only(children) as ReactElement<{ 'aria-label'?: string }>;\n const iconButtonElement = (\n <IconButton\n asChild\n aria-label={label}\n disabled={isDisabled}\n loading={state === 'loading'}\n ref={ref as Ref<HTMLButtonElement>}\n {...buttonRest}\n >\n {cloneElement(onlyChild, { 'aria-label': onlyChild.props['aria-label'] ?? label }, <Icon size={iconSize} />)}\n </IconButton>\n );\n return (\n <BitkitLabelTooltip text={label} {...tooltipProps}>\n {isSkeleton ? (\n <Skeleton asChild loading>\n {iconButtonElement}\n </Skeleton>\n ) : (\n iconButtonElement\n )}\n </BitkitLabelTooltip>\n );\n }\n\n // --- Anchor mode (href) ---\n if (props.href !== undefined) {\n const {\n css,\n href,\n icon: _icon,\n isExternal,\n label,\n onClick,\n onKeyDown,\n rel,\n size,\n state: _state,\n target,\n tooltipProps,\n variant,\n ...anchorRest\n } = props;\n const effectiveTarget = isExternal ? '_blank' : target;\n const effectiveRel = isExternal ? (rel ? `${rel} noreferrer noopener` : 'noreferrer noopener') : rel;\n const handleClick = isDisabled\n ? (e: MouseEvent<HTMLAnchorElement>) => {\n e.preventDefault();\n e.stopPropagation();\n }\n : onClick;\n const handleKeyDown = isDisabled\n ? (e: KeyboardEvent<HTMLAnchorElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n : onKeyDown;\n const anchorElement = (\n <chakra.a\n ref={ref as Ref<HTMLAnchorElement>}\n {...anchorRest}\n aria-disabled={isDisabled || undefined}\n aria-label={label}\n css={[buttonRecipe({ size, variant }), { paddingBlock: 0, paddingInline: 0 }, css]}\n href={isDisabled ? undefined : href}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n rel={effectiveRel}\n target={effectiveTarget}\n >\n <Icon size={iconSize} />\n </chakra.a>\n );\n return (\n <BitkitLabelTooltip text={label} {...tooltipProps}>\n {isSkeleton ? (\n <Skeleton asChild loading>\n {anchorElement}\n </Skeleton>\n ) : (\n anchorElement\n )}\n </BitkitLabelTooltip>\n );\n }\n\n // --- Button mode (default) ---\n const { icon: _icon, label, state, tooltipProps, ...buttonRest } = props;\n return (\n <BitkitLabelTooltip text={label} {...tooltipProps}>\n <Skeleton asChild loading={isSkeleton}>\n <IconButton\n aria-label={label}\n disabled={isDisabled}\n loading={state === 'loading'}\n ref={ref as Ref<HTMLButtonElement>}\n {...buttonRest}\n >\n <Icon size={iconSize} />\n </IconButton>\n </Skeleton>\n </BitkitLabelTooltip>\n );\n});\n\nBitkitIconButton.displayName = 'BitkitIconButton';\n\nexport default BitkitIconButton;\n"],"mappings":";;;;;;;AAqEA,IAAM,mBAAmB,YAAgD,OAAO,QAAQ;CACtF,MAAM,eAAe,UAAU,EAAE,KAAK,SAAS,CAAC;CAChD,MAAM,OAAO,MAAM;CACnB,MAAM,WAAW,MAAM,SAAS,OAAO,OAAO;CAC9C,MAAM,aAAa,MAAM,UAAU;CACnC,MAAM,aAAa,MAAM,UAAU;CAGnC,IAAI,MAAM,SAAS;EACjB,MAAM,EAAE,SAAS,UAAU,UAAU,MAAM,OAAO,OAAO,OAAO,cAAc,GAAG,eAAe;EAChG,MAAM,YAAY,SAAS,KAAK,QAAQ;EACxC,MAAM,oBACJ,oBAAC,YAAD;GACE,SAAA;GACA,cAAY;GACZ,UAAU;GACV,SAAS,UAAU;GACd;GACL,GAAI;aAEH,aAAa,WAAW,EAAE,cAAc,UAAU,MAAM,iBAAiB,MAAM,GAAG,oBAAC,MAAD,EAAM,MAAM,SAAW,CAAA,CAAC;EACjG,CAAA;EAEd,OACE,oBAAC,oBAAD;GAAoB,MAAM;GAAO,GAAI;aAClC,aACC,oBAAC,UAAD;IAAU,SAAA;IAAQ,SAAA;cACf;GACO,CAAA,IAEV;EAEgB,CAAA;CAExB;CAGA,IAAI,MAAM,SAAS,KAAA,GAAW;EAC5B,MAAM,EACJ,KACA,MACA,MAAM,OACN,YACA,OACA,SACA,WACA,KACA,MACA,OAAO,QACP,QACA,cACA,SACA,GAAG,eACD;EACJ,MAAM,kBAAkB,aAAa,WAAW;EAChD,MAAM,eAAe,aAAc,MAAM,GAAG,IAAI,wBAAwB,wBAAyB;EACjG,MAAM,cAAc,cACf,MAAqC;GACpC,EAAE,eAAe;GACjB,EAAE,gBAAgB;EACpB,IACA;EACJ,MAAM,gBAAgB,cACjB,MAAwC;GACvC,IAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;IACtC,EAAE,eAAe;IACjB,EAAE,gBAAgB;GACpB;EACF,IACA;EACJ,MAAM,gBACJ,oBAAC,OAAO,GAAR;GACO;GACL,GAAI;GACJ,iBAAe,cAAc,KAAA;GAC7B,cAAY;GACZ,KAAK;IAAC,aAAa;KAAE;KAAM;IAAQ,CAAC;IAAG;KAAE,cAAc;KAAG,eAAe;IAAE;IAAG;GAAG;GACjF,MAAM,aAAa,KAAA,IAAY;GAC/B,SAAS;GACT,WAAW;GACX,KAAK;GACL,QAAQ;aAER,oBAAC,MAAD,EAAM,MAAM,SAAW,CAAA;EACf,CAAA;EAEZ,OACE,oBAAC,oBAAD;GAAoB,MAAM;GAAO,GAAI;aAClC,aACC,oBAAC,UAAD;IAAU,SAAA;IAAQ,SAAA;cACf;GACO,CAAA,IAEV;EAEgB,CAAA;CAExB;CAGA,MAAM,EAAE,MAAM,OAAO,OAAO,OAAO,cAAc,GAAG,eAAe;CACnE,OACE,oBAAC,oBAAD;EAAoB,MAAM;EAAO,GAAI;YACnC,oBAAC,UAAD;GAAU,SAAA;GAAQ,SAAS;aACzB,oBAAC,YAAD;IACE,cAAY;IACZ,UAAU;IACV,SAAS,UAAU;IACd;IACL,GAAI;cAEJ,oBAAC,MAAD,EAAM,MAAM,SAAW,CAAA;GACb,CAAA;EACJ,CAAA;CACQ,CAAA;AAExB,CAAC;AAED,iBAAiB,cAAc"}
@@ -2,6 +2,7 @@ import { LinkProps } from '@chakra-ui/react/link';
2
2
  import { ComponentPropsWithoutRef } from 'react';
3
3
  import { BitkitIconComponent } from '../../icons';
4
4
  export interface BitkitLinkProps extends LinkProps {
5
+ isExternal?: boolean;
5
6
  suffixIcon?: BitkitIconComponent;
6
7
  suffixIconSize?: ComponentPropsWithoutRef<BitkitIconComponent>['size'];
7
8
  state?: 'disabled';
@@ -3,11 +3,26 @@ import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { Link } from "@chakra-ui/react/link";
4
4
  //#region lib/components/BitkitLink/BitkitLink.tsx
5
5
  var BitkitLink = forwardRef((props, ref) => {
6
- const { children, href, suffixIcon: SuffixIcon, suffixIconSize, state, ...rest } = props;
6
+ const { children, href, isExternal, onClick, onKeyDown, rel, suffixIcon: SuffixIcon, suffixIconSize, state, target, ...rest } = props;
7
+ const isDisabled = state === "disabled";
8
+ const effectiveTarget = isExternal ? "_blank" : target;
9
+ const effectiveRel = isExternal ? rel ? `${rel} noreferrer noopener` : "noreferrer noopener" : rel;
7
10
  return /* @__PURE__ */ jsxs(Link, {
8
- "aria-disabled": state === "disabled" ? true : void 0,
9
- href: state === "disabled" ? void 0 : href,
11
+ "aria-disabled": isDisabled || void 0,
12
+ href: isDisabled ? void 0 : href,
13
+ onClick: isDisabled ? (e) => {
14
+ e.preventDefault();
15
+ e.stopPropagation();
16
+ } : onClick,
17
+ onKeyDown: isDisabled ? (e) => {
18
+ if (e.key === "Enter" || e.key === " ") {
19
+ e.preventDefault();
20
+ e.stopPropagation();
21
+ }
22
+ } : onKeyDown,
10
23
  ref,
24
+ rel: effectiveRel,
25
+ target: effectiveTarget,
11
26
  ...rest,
12
27
  children: [children, SuffixIcon && (suffixIconSize ? /* @__PURE__ */ jsx(SuffixIcon, { size: suffixIconSize }) : /* @__PURE__ */ jsx(SuffixIcon, { css: {
13
28
  height: "1lh",
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitLink.js","names":[],"sources":["../../../lib/components/BitkitLink/BitkitLink.tsx"],"sourcesContent":["import { Link, type LinkProps } from '@chakra-ui/react/link';\nimport { type ComponentPropsWithoutRef, forwardRef } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\n\nexport interface BitkitLinkProps extends LinkProps {\n suffixIcon?: BitkitIconComponent;\n suffixIconSize?: ComponentPropsWithoutRef<BitkitIconComponent>['size'];\n state?: 'disabled';\n}\n\nconst BitkitLink = forwardRef<HTMLAnchorElement, BitkitLinkProps>((props, ref) => {\n const { children, href, suffixIcon: SuffixIcon, suffixIconSize, state, ...rest } = props;\n\n return (\n <Link\n aria-disabled={state === 'disabled' ? true : undefined}\n href={state === 'disabled' ? undefined : href}\n ref={ref}\n {...rest}\n >\n {children}\n {SuffixIcon &&\n (suffixIconSize ? <SuffixIcon size={suffixIconSize} /> : <SuffixIcon css={{ height: '1lh', width: '1lh' }} />)}\n </Link>\n );\n});\n\nBitkitLink.displayName = 'BitkitLink';\n\nexport default BitkitLink;\n"],"mappings":";;;;AAWA,IAAM,aAAa,YAAgD,OAAO,QAAQ;CAChF,MAAM,EAAE,UAAU,MAAM,YAAY,YAAY,gBAAgB,OAAO,GAAG,SAAS;CAEnF,OACE,qBAAC,MAAD;EACE,iBAAe,UAAU,aAAa,OAAO,KAAA;EAC7C,MAAM,UAAU,aAAa,KAAA,IAAY;EACpC;EACL,GAAI;YAJN,CAMG,UACA,eACE,iBAAiB,oBAAC,YAAD,EAAY,MAAM,eAAiB,CAAA,IAAI,oBAAC,YAAD,EAAY,KAAK;GAAE,QAAQ;GAAO,OAAO;EAAM,EAAI,CAAA,EAC1G;;AAEV,CAAC;AAED,WAAW,cAAc"}
1
+ {"version":3,"file":"BitkitLink.js","names":[],"sources":["../../../lib/components/BitkitLink/BitkitLink.tsx"],"sourcesContent":["import { Link, type LinkProps } from '@chakra-ui/react/link';\nimport { type ComponentPropsWithoutRef, forwardRef, type KeyboardEvent, type MouseEvent } from 'react';\n\nimport { type BitkitIconComponent } from '../../icons';\n\nexport interface BitkitLinkProps extends LinkProps {\n isExternal?: boolean;\n suffixIcon?: BitkitIconComponent;\n suffixIconSize?: ComponentPropsWithoutRef<BitkitIconComponent>['size'];\n state?: 'disabled';\n}\n\nconst BitkitLink = forwardRef<HTMLAnchorElement, BitkitLinkProps>((props, ref) => {\n const {\n children,\n href,\n isExternal,\n onClick,\n onKeyDown,\n rel,\n suffixIcon: SuffixIcon,\n suffixIconSize,\n state,\n target,\n ...rest\n } = props;\n const isDisabled = state === 'disabled';\n const effectiveTarget = isExternal ? '_blank' : target;\n const effectiveRel = isExternal ? (rel ? `${rel} noreferrer noopener` : 'noreferrer noopener') : rel;\n const handleClick = isDisabled\n ? (e: MouseEvent<HTMLAnchorElement>) => {\n e.preventDefault();\n e.stopPropagation();\n }\n : onClick;\n const handleKeyDown = isDisabled\n ? (e: KeyboardEvent<HTMLAnchorElement>) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n e.stopPropagation();\n }\n }\n : onKeyDown;\n\n return (\n <Link\n aria-disabled={isDisabled || undefined}\n href={isDisabled ? undefined : href}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n ref={ref}\n rel={effectiveRel}\n target={effectiveTarget}\n {...rest}\n >\n {children}\n {SuffixIcon &&\n (suffixIconSize ? <SuffixIcon size={suffixIconSize} /> : <SuffixIcon css={{ height: '1lh', width: '1lh' }} />)}\n </Link>\n );\n});\n\nBitkitLink.displayName = 'BitkitLink';\n\nexport default BitkitLink;\n"],"mappings":";;;;AAYA,IAAM,aAAa,YAAgD,OAAO,QAAQ;CAChF,MAAM,EACJ,UACA,MACA,YACA,SACA,WACA,KACA,YAAY,YACZ,gBACA,OACA,QACA,GAAG,SACD;CACJ,MAAM,aAAa,UAAU;CAC7B,MAAM,kBAAkB,aAAa,WAAW;CAChD,MAAM,eAAe,aAAc,MAAM,GAAG,IAAI,wBAAwB,wBAAyB;CAgBjG,OACE,qBAAC,MAAD;EACE,iBAAe,cAAc,KAAA;EAC7B,MAAM,aAAa,KAAA,IAAY;EAC/B,SAnBgB,cACf,MAAqC;GACpC,EAAE,eAAe;GACjB,EAAE,gBAAgB;EACpB,IACA;EAeA,WAdkB,cACjB,MAAwC;GACvC,IAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;IACtC,EAAE,eAAe;IACjB,EAAE,gBAAgB;GACpB;EACF,IACA;EAQK;EACL,KAAK;EACL,QAAQ;EACR,GAAI;YARN,CAUG,UACA,eACE,iBAAiB,oBAAC,YAAD,EAAY,MAAM,eAAiB,CAAA,IAAI,oBAAC,YAAD,EAAY,KAAK;GAAE,QAAQ;GAAO,OAAO;EAAM,EAAI,CAAA,EAC1G;;AAEV,CAAC;AAED,WAAW,cAAc"}
@@ -32,19 +32,22 @@ var BitkitNoteCard = forwardRef((props, ref) => {
32
32
  css: title ? styles.message : styles.messageSolo,
33
33
  children: message
34
34
  })]
35
- }), action && /* @__PURE__ */ jsx(BitkitButton, {
35
+ }), action && (action.href !== void 0 ? /* @__PURE__ */ jsx(BitkitButton, {
36
36
  css: styles.actionArea,
37
+ href: action.href,
38
+ onClick: action.onClick,
39
+ rel: action.target === "_blank" ? "noopener noreferrer" : void 0,
37
40
  size: "sm",
41
+ target: action.target,
38
42
  variant: "tertiary",
39
- ...action.href && {
40
- as: "a",
41
- href: action.href,
42
- rel: action.target === "_blank" ? "noopener noreferrer" : void 0,
43
- target: action.target
44
- },
43
+ children: action.label
44
+ }) : /* @__PURE__ */ jsx(BitkitButton, {
45
+ css: styles.actionArea,
45
46
  onClick: action.onClick,
47
+ size: "sm",
48
+ variant: "tertiary",
46
49
  children: action.label
47
- })]
50
+ }))]
48
51
  })]
49
52
  });
50
53
  });
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitNoteCard.js","names":[],"sources":["../../../lib/components/BitkitNoteCard/BitkitNoteCard.tsx"],"sourcesContent":["import { Box, type BoxProps } from '@chakra-ui/react/box';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { type ElementType, forwardRef, type ReactNode } from 'react';\n\nimport { type NotificationVariant } from '../../theme/common/AlertAndToast.common';\nimport BitkitButton from '../BitkitButton/BitkitButton';\nimport { ICON_COMPONENTS_MAP, type NotificationAction } from '../common/notificationMaps';\n\n// ----- Props -----\n\nexport type BitkitNoteCardProps = Omit<BoxProps, 'children' | 'title'> & {\n action?: NotificationAction;\n message: ReactNode;\n status?: NotificationVariant;\n title?: string;\n};\n\n// ----- Component -----\n\nconst BitkitNoteCard = forwardRef<HTMLDivElement, BitkitNoteCardProps>((props, ref) => {\n const { action, message, status = 'info', title, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'noteCard' });\n const styles = recipe({ status });\n\n const IconComponent: ElementType = ICON_COMPONENTS_MAP[status];\n const isProgress = status === 'progress';\n\n return (\n <Box ref={ref} css={styles.root} {...rest}>\n <Box css={styles.iconBar}>\n <Box css={styles.iconWrapper}>{isProgress ? <IconComponent size=\"lg\" /> : <IconComponent size=\"24\" />}</Box>\n </Box>\n <Box css={styles.content}>\n <Box css={styles.messageBlock}>\n {title && <Text css={styles.title}>{title}</Text>}\n <Text css={title ? styles.message : styles.messageSolo}>{message}</Text>\n </Box>\n {action && (\n <BitkitButton\n css={styles.actionArea}\n size=\"sm\"\n variant=\"tertiary\"\n {...(action.href && {\n as: 'a' as const,\n href: action.href,\n rel: action.target === '_blank' ? 'noopener noreferrer' : undefined,\n target: action.target,\n })}\n onClick={action.onClick}\n >\n {action.label}\n </BitkitButton>\n )}\n </Box>\n </Box>\n );\n});\n\nBitkitNoteCard.displayName = 'BitkitNoteCard';\n\nexport default BitkitNoteCard;\n"],"mappings":";;;;;;;;AAoBA,IAAM,iBAAiB,YAAiD,OAAO,QAAQ;CACrF,MAAM,EAAE,QAAQ,SAAS,SAAS,QAAQ,OAAO,GAAG,SAAS;CAG7D,MAAM,SADS,cAAc,EAAE,KAAK,WAAW,CAChC,EAAO,EAAE,OAAO,CAAC;CAEhC,MAAM,gBAA6B,oBAAoB;CACvD,MAAM,aAAa,WAAW;CAE9B,OACE,qBAAC,KAAD;EAAU;EAAK,KAAK,OAAO;EAAM,GAAI;YAArC,CACE,oBAAC,KAAD;GAAK,KAAK,OAAO;aACf,oBAAC,KAAD;IAAK,KAAK,OAAO;cAAc,aAAa,oBAAC,eAAD,EAAe,MAAK,KAAM,CAAA,IAAI,oBAAC,eAAD,EAAe,MAAK,KAAM,CAAA;GAAO,CAAA;EACxG,CAAA,GACL,qBAAC,KAAD;GAAK,KAAK,OAAO;aAAjB,CACE,qBAAC,KAAD;IAAK,KAAK,OAAO;cAAjB,CACG,SAAS,oBAAC,MAAD;KAAM,KAAK,OAAO;eAAQ;IAAY,CAAA,GAChD,oBAAC,MAAD;KAAM,KAAK,QAAQ,OAAO,UAAU,OAAO;eAAc;IAAc,CAAA,CACpE;OACJ,UACC,oBAAC,cAAD;IACE,KAAK,OAAO;IACZ,MAAK;IACL,SAAQ;IACR,GAAK,OAAO,QAAQ;KAClB,IAAI;KACJ,MAAM,OAAO;KACb,KAAK,OAAO,WAAW,WAAW,wBAAwB,KAAA;KAC1D,QAAQ,OAAO;IACjB;IACA,SAAS,OAAO;cAEf,OAAO;GACI,CAAA,CAEb;IACF;;AAET,CAAC;AAED,eAAe,cAAc"}
1
+ {"version":3,"file":"BitkitNoteCard.js","names":[],"sources":["../../../lib/components/BitkitNoteCard/BitkitNoteCard.tsx"],"sourcesContent":["import { Box, type BoxProps } from '@chakra-ui/react/box';\nimport { useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Text } from '@chakra-ui/react/text';\nimport { type ElementType, forwardRef, type ReactNode } from 'react';\n\nimport { type NotificationVariant } from '../../theme/common/AlertAndToast.common';\nimport BitkitButton from '../BitkitButton/BitkitButton';\nimport { ICON_COMPONENTS_MAP, type NotificationAction } from '../common/notificationMaps';\n\n// ----- Props -----\n\nexport type BitkitNoteCardProps = Omit<BoxProps, 'children' | 'title'> & {\n action?: NotificationAction;\n message: ReactNode;\n status?: NotificationVariant;\n title?: string;\n};\n\n// ----- Component -----\n\nconst BitkitNoteCard = forwardRef<HTMLDivElement, BitkitNoteCardProps>((props, ref) => {\n const { action, message, status = 'info', title, ...rest } = props;\n\n const recipe = useSlotRecipe({ key: 'noteCard' });\n const styles = recipe({ status });\n\n const IconComponent: ElementType = ICON_COMPONENTS_MAP[status];\n const isProgress = status === 'progress';\n\n return (\n <Box ref={ref} css={styles.root} {...rest}>\n <Box css={styles.iconBar}>\n <Box css={styles.iconWrapper}>{isProgress ? <IconComponent size=\"lg\" /> : <IconComponent size=\"24\" />}</Box>\n </Box>\n <Box css={styles.content}>\n <Box css={styles.messageBlock}>\n {title && <Text css={styles.title}>{title}</Text>}\n <Text css={title ? styles.message : styles.messageSolo}>{message}</Text>\n </Box>\n {action &&\n (action.href !== undefined ? (\n <BitkitButton\n css={styles.actionArea}\n href={action.href}\n onClick={action.onClick}\n rel={action.target === '_blank' ? 'noopener noreferrer' : undefined}\n size=\"sm\"\n target={action.target}\n variant=\"tertiary\"\n >\n {action.label}\n </BitkitButton>\n ) : (\n <BitkitButton css={styles.actionArea} onClick={action.onClick} size=\"sm\" variant=\"tertiary\">\n {action.label}\n </BitkitButton>\n ))}\n </Box>\n </Box>\n );\n});\n\nBitkitNoteCard.displayName = 'BitkitNoteCard';\n\nexport default BitkitNoteCard;\n"],"mappings":";;;;;;;;AAoBA,IAAM,iBAAiB,YAAiD,OAAO,QAAQ;CACrF,MAAM,EAAE,QAAQ,SAAS,SAAS,QAAQ,OAAO,GAAG,SAAS;CAG7D,MAAM,SADS,cAAc,EAAE,KAAK,WAAW,CAChC,EAAO,EAAE,OAAO,CAAC;CAEhC,MAAM,gBAA6B,oBAAoB;CACvD,MAAM,aAAa,WAAW;CAE9B,OACE,qBAAC,KAAD;EAAU;EAAK,KAAK,OAAO;EAAM,GAAI;YAArC,CACE,oBAAC,KAAD;GAAK,KAAK,OAAO;aACf,oBAAC,KAAD;IAAK,KAAK,OAAO;cAAc,aAAa,oBAAC,eAAD,EAAe,MAAK,KAAM,CAAA,IAAI,oBAAC,eAAD,EAAe,MAAK,KAAM,CAAA;GAAO,CAAA;EACxG,CAAA,GACL,qBAAC,KAAD;GAAK,KAAK,OAAO;aAAjB,CACE,qBAAC,KAAD;IAAK,KAAK,OAAO;cAAjB,CACG,SAAS,oBAAC,MAAD;KAAM,KAAK,OAAO;eAAQ;IAAY,CAAA,GAChD,oBAAC,MAAD;KAAM,KAAK,QAAQ,OAAO,UAAU,OAAO;eAAc;IAAc,CAAA,CACpE;OACJ,WACE,OAAO,SAAS,KAAA,IACf,oBAAC,cAAD;IACE,KAAK,OAAO;IACZ,MAAM,OAAO;IACb,SAAS,OAAO;IAChB,KAAK,OAAO,WAAW,WAAW,wBAAwB,KAAA;IAC1D,MAAK;IACL,QAAQ,OAAO;IACf,SAAQ;cAEP,OAAO;GACI,CAAA,IAEd,oBAAC,cAAD;IAAc,KAAK,OAAO;IAAY,SAAS,OAAO;IAAS,MAAK;IAAK,SAAQ;cAC9E,OAAO;GACI,CAAA,EAEf;IACF;;AAET,CAAC;AAED,eAAe,cAAc"}
@@ -4,8 +4,12 @@ import { ReactNode } from 'react';
4
4
  export interface BitkitRadioGroupProps extends Fieldset.RootProps {
5
5
  children: ReactNode;
6
6
  errorText?: string;
7
+ /**
8
+ * Visible legend rendered above the group. Optional — if you omit it, pass `aria-label` or
9
+ * `aria-labelledby` instead so the fieldset still has an accessible name.
10
+ */
11
+ groupLabel?: string;
7
12
  helperText?: string;
8
- label: string;
9
13
  layout?: RadioGroupRootProps['orientation'];
10
14
  name?: RadioGroupRootProps['name'];
11
15
  onValueChange: RadioGroupRootProps['onValueChange'];
@@ -4,16 +4,17 @@ import { Fieldset } from "@chakra-ui/react/fieldset";
4
4
  import { RadioGroup } from "@chakra-ui/react/radio-group";
5
5
  //#region lib/components/BitkitRadioGroup/BitkitRadioGroup.tsx
6
6
  var BitkitRadioGroup = forwardRef((props, ref) => {
7
- const { children, errorText, helperText, label, layout, name, onValueChange, radioGroupRootProps, size, value, ...rest } = props;
7
+ const { children, errorText, helperText, groupLabel, layout, name, onValueChange, radioGroupRootProps, size, value, ...rest } = props;
8
+ const hasHeader = !!groupLabel || !!helperText;
8
9
  return /* @__PURE__ */ jsxs(Fieldset.Root, {
9
10
  ref,
10
11
  ...rest,
11
12
  invalid: rest.invalid || !!errorText,
12
13
  children: [
13
- /* @__PURE__ */ jsx(Fieldset.Legend, { children: label }),
14
+ groupLabel && /* @__PURE__ */ jsx(Fieldset.Legend, { children: groupLabel }),
14
15
  !!helperText && /* @__PURE__ */ jsx(Fieldset.HelperText, { children: helperText }),
15
16
  /* @__PURE__ */ jsx(Fieldset.Content, {
16
- marginBlockStart: "12",
17
+ marginBlockStart: hasHeader ? "12" : void 0,
17
18
  asChild: true,
18
19
  children: /* @__PURE__ */ jsx(RadioGroup.Root, {
19
20
  name,
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitRadioGroup.js","names":[],"sources":["../../../lib/components/BitkitRadioGroup/BitkitRadioGroup.tsx"],"sourcesContent":["import { Fieldset } from '@chakra-ui/react/fieldset';\nimport { RadioGroup, type RadioGroupRootProps } from '@chakra-ui/react/radio-group';\nimport { forwardRef, type ReactNode } from 'react';\n\nexport interface BitkitRadioGroupProps extends Fieldset.RootProps {\n children: ReactNode;\n errorText?: string;\n helperText?: string;\n label: string;\n layout?: RadioGroupRootProps['orientation'];\n name?: RadioGroupRootProps['name'];\n onValueChange: RadioGroupRootProps['onValueChange'];\n radioGroupRootProps?: RadioGroupRootProps;\n size?: RadioGroupRootProps['size'];\n value: RadioGroupRootProps['value'];\n}\n\nconst BitkitRadioGroup = forwardRef<HTMLFieldSetElement, BitkitRadioGroupProps>((props, ref) => {\n const {\n children,\n errorText,\n helperText,\n label,\n layout,\n name,\n onValueChange,\n radioGroupRootProps,\n size,\n value,\n ...rest\n } = props;\n return (\n <Fieldset.Root ref={ref} {...rest} invalid={rest.invalid || !!errorText}>\n <Fieldset.Legend>{label}</Fieldset.Legend>\n {!!helperText && <Fieldset.HelperText>{helperText}</Fieldset.HelperText>}\n <Fieldset.Content marginBlockStart=\"12\" asChild>\n <RadioGroup.Root\n name={name}\n size={size}\n orientation={layout}\n onValueChange={onValueChange}\n value={value}\n {...radioGroupRootProps}\n >\n {children}\n </RadioGroup.Root>\n </Fieldset.Content>\n {!!errorText && <Fieldset.ErrorText>{errorText}</Fieldset.ErrorText>}\n </Fieldset.Root>\n );\n});\n\nBitkitRadioGroup.displayName = 'BitkitRadioGroup';\n\nexport default BitkitRadioGroup;\n"],"mappings":";;;;;AAiBA,IAAM,mBAAmB,YAAwD,OAAO,QAAQ;CAC9F,MAAM,EACJ,UACA,WACA,YACA,OACA,QACA,MACA,eACA,qBACA,MACA,OACA,GAAG,SACD;CACJ,OACE,qBAAC,SAAS,MAAV;EAAoB;EAAK,GAAI;EAAM,SAAS,KAAK,WAAW,CAAC,CAAC;YAA9D;GACE,oBAAC,SAAS,QAAV,EAAA,UAAkB,MAAuB,CAAA;GACxC,CAAC,CAAC,cAAc,oBAAC,SAAS,YAAV,EAAA,UAAsB,WAAgC,CAAA;GACvE,oBAAC,SAAS,SAAV;IAAkB,kBAAiB;IAAK,SAAA;cACtC,oBAAC,WAAW,MAAZ;KACQ;KACA;KACN,aAAa;KACE;KACR;KACP,GAAI;KAEH;IACc,CAAA;GACD,CAAA;GACjB,CAAC,CAAC,aAAa,oBAAC,SAAS,WAAV,EAAA,UAAqB,UAA8B,CAAA;EACtD;;AAEnB,CAAC;AAED,iBAAiB,cAAc"}
1
+ {"version":3,"file":"BitkitRadioGroup.js","names":[],"sources":["../../../lib/components/BitkitRadioGroup/BitkitRadioGroup.tsx"],"sourcesContent":["import { Fieldset } from '@chakra-ui/react/fieldset';\nimport { RadioGroup, type RadioGroupRootProps } from '@chakra-ui/react/radio-group';\nimport { forwardRef, type ReactNode } from 'react';\n\nexport interface BitkitRadioGroupProps extends Fieldset.RootProps {\n children: ReactNode;\n errorText?: string;\n /**\n * Visible legend rendered above the group. Optional — if you omit it, pass `aria-label` or\n * `aria-labelledby` instead so the fieldset still has an accessible name.\n */\n groupLabel?: string;\n helperText?: string;\n layout?: RadioGroupRootProps['orientation'];\n name?: RadioGroupRootProps['name'];\n onValueChange: RadioGroupRootProps['onValueChange'];\n radioGroupRootProps?: RadioGroupRootProps;\n size?: RadioGroupRootProps['size'];\n value: RadioGroupRootProps['value'];\n}\n\nconst BitkitRadioGroup = forwardRef<HTMLFieldSetElement, BitkitRadioGroupProps>((props, ref) => {\n const {\n children,\n errorText,\n helperText,\n groupLabel,\n layout,\n name,\n onValueChange,\n radioGroupRootProps,\n size,\n value,\n ...rest\n } = props;\n const hasHeader = !!groupLabel || !!helperText;\n return (\n <Fieldset.Root ref={ref} {...rest} invalid={rest.invalid || !!errorText}>\n {groupLabel && <Fieldset.Legend>{groupLabel}</Fieldset.Legend>}\n {!!helperText && <Fieldset.HelperText>{helperText}</Fieldset.HelperText>}\n <Fieldset.Content marginBlockStart={hasHeader ? '12' : undefined} asChild>\n <RadioGroup.Root\n name={name}\n size={size}\n orientation={layout}\n onValueChange={onValueChange}\n value={value}\n {...radioGroupRootProps}\n >\n {children}\n </RadioGroup.Root>\n </Fieldset.Content>\n {!!errorText && <Fieldset.ErrorText>{errorText}</Fieldset.ErrorText>}\n </Fieldset.Root>\n );\n});\n\nBitkitRadioGroup.displayName = 'BitkitRadioGroup';\n\nexport default BitkitRadioGroup;\n"],"mappings":";;;;;AAqBA,IAAM,mBAAmB,YAAwD,OAAO,QAAQ;CAC9F,MAAM,EACJ,UACA,WACA,YACA,YACA,QACA,MACA,eACA,qBACA,MACA,OACA,GAAG,SACD;CACJ,MAAM,YAAY,CAAC,CAAC,cAAc,CAAC,CAAC;CACpC,OACE,qBAAC,SAAS,MAAV;EAAoB;EAAK,GAAI;EAAM,SAAS,KAAK,WAAW,CAAC,CAAC;YAA9D;GACG,cAAc,oBAAC,SAAS,QAAV,EAAA,UAAkB,WAA4B,CAAA;GAC5D,CAAC,CAAC,cAAc,oBAAC,SAAS,YAAV,EAAA,UAAsB,WAAgC,CAAA;GACvE,oBAAC,SAAS,SAAV;IAAkB,kBAAkB,YAAY,OAAO,KAAA;IAAW,SAAA;cAChE,oBAAC,WAAW,MAAZ;KACQ;KACA;KACN,aAAa;KACE;KACR;KACP,GAAI;KAEH;IACc,CAAA;GACD,CAAA;GACjB,CAAC,CAAC,aAAa,oBAAC,SAAS,WAAV,EAAA,UAAqB,UAA8B,CAAA;EACtD;;AAEnB,CAAC;AAED,iBAAiB,cAAc"}
@@ -1,10 +1,10 @@
1
1
  import { GroupProps } from '@chakra-ui/react/group';
2
2
  import { PropsWithChildren, ReactNode } from 'react';
3
- import { BitkitButtonProps } from '../BitkitButton/BitkitButton';
3
+ import { BitkitButtonAsAnchorProps, BitkitButtonAsButtonProps } from '../BitkitButton/BitkitButton';
4
4
  type Size = 'lg' | 'md' | 'sm';
5
5
  type Variant = 'primary' | 'secondary';
6
6
  type State = 'disabled' | 'loading' | 'skeleton';
7
- type BitkitSplitButtonActionProps = Omit<BitkitButtonProps, 'size' | 'variant' | 'state'>;
7
+ type BitkitSplitButtonActionProps = Omit<BitkitButtonAsButtonProps | BitkitButtonAsAnchorProps, 'size' | 'variant' | 'state'>;
8
8
  export type BitkitSplitButtonProps = PropsWithChildren<Omit<GroupProps, 'attached' | 'children' | 'display'> & {
9
9
  size?: Size;
10
10
  variant?: Variant;
@@ -17,9 +17,9 @@ declare const _default: import('react').ForwardRefExoticComponent<Omit<GroupProp
17
17
  } & {
18
18
  children?: ReactNode | undefined;
19
19
  } & import('react').RefAttributes<HTMLDivElement>> & {
20
- Action: import('react').ForwardRefExoticComponent<BitkitSplitButtonActionProps & import('react').RefAttributes<HTMLButtonElement>>;
20
+ Action: import('react').ForwardRefExoticComponent<BitkitSplitButtonActionProps & import('react').RefAttributes<HTMLElement>>;
21
21
  Group: import('react').ForwardRefExoticComponent<import('..').BitkitMenuGroupProps & import('react').RefAttributes<HTMLDivElement>>;
22
- Item: import('react').ForwardRefExoticComponent<import('..').BitkitMenuItemProps & import('react').RefAttributes<HTMLDivElement>>;
22
+ Item: import('react').ForwardRefExoticComponent<import('..').BitkitMenuItemProps & import('react').RefAttributes<HTMLElement>>;
23
23
  Separator: {
24
24
  (): import("react/jsx-runtime").JSX.Element;
25
25
  displayName: string;
@@ -22,13 +22,21 @@ var [SplitButtonProvider, useSplitButtonContext] = createContext$1({
22
22
  });
23
23
  var BitkitSplitButtonAction = forwardRef((props, ref) => {
24
24
  const { size, state, styles, variant } = useSplitButtonContext();
25
- return /* @__PURE__ */ jsx(BitkitButton, {
25
+ if (props.href !== void 0) return /* @__PURE__ */ jsx(BitkitButton, {
26
+ ...props,
27
+ css: styles.action,
26
28
  ref,
29
+ size,
30
+ state: state === "loading" ? "disabled" : state,
31
+ variant
32
+ });
33
+ return /* @__PURE__ */ jsx(BitkitButton, {
34
+ ...props,
27
35
  css: styles.action,
36
+ ref,
28
37
  size,
29
- variant,
30
38
  state,
31
- ...props
39
+ variant
32
40
  });
33
41
  });
34
42
  BitkitSplitButtonAction.displayName = "BitkitSplitButtonAction";
@@ -1 +1 @@
1
- {"version":3,"file":"BitkitSplitButton.js","names":[],"sources":["../../../lib/components/BitkitSplitButton/BitkitSplitButton.tsx"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport { createContext } from '@chakra-ui/react';\nimport { Group, type GroupProps } from '@chakra-ui/react/group';\nimport { Skeleton } from '@chakra-ui/react/skeleton';\nimport { type SystemStyleObject, useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Children, forwardRef, isValidElement, type PropsWithChildren, type ReactElement, type ReactNode } from 'react';\n\nimport { IconChevronDown } from '../../icons';\nimport BitkitActionMenu from '../BitkitActionMenu/BitkitActionMenu';\nimport BitkitButton, { type BitkitButtonProps } from '../BitkitButton/BitkitButton';\nimport BitkitIconButton from '../BitkitIconButton/BitkitIconButton';\n\ntype Size = 'lg' | 'md' | 'sm';\ntype Variant = 'primary' | 'secondary';\ntype State = 'disabled' | 'loading' | 'skeleton';\n\nconst isValidActionItem = (child: ReactNode): child is ReactElement => {\n return isValidElement(child) && child.type === BitkitSplitButtonAction;\n};\n\nconst isValidMenuItem = (child: ReactNode): child is ReactElement => {\n return (\n isValidElement(child) &&\n (child.type === BitkitActionMenu.Group ||\n child.type === BitkitActionMenu.Item ||\n child.type === BitkitActionMenu.Separator)\n );\n};\n\n// --- Context ---\ninterface SplitButtonContext {\n size: Size;\n variant: Variant;\n state: State | undefined;\n styles: Record<string, SystemStyleObject>;\n}\n\nconst [SplitButtonProvider, useSplitButtonContext] = createContext<SplitButtonContext>({\n name: 'SplitButtonContext',\n hookName: 'useSplitButtonContext',\n providerName: '<BitkitSplitButton />',\n});\n\n// --- Action ---\ntype BitkitSplitButtonActionProps = Omit<BitkitButtonProps, 'size' | 'variant' | 'state'>;\n\nconst BitkitSplitButtonAction = forwardRef<HTMLButtonElement, BitkitSplitButtonActionProps>((props, ref) => {\n const { size, state, styles, variant } = useSplitButtonContext();\n\n return <BitkitButton ref={ref} css={styles.action} size={size} variant={variant} state={state} {...props} />;\n});\n\nBitkitSplitButtonAction.displayName = 'BitkitSplitButtonAction';\n\n// --- Root ---\nexport type BitkitSplitButtonProps = PropsWithChildren<\n Omit<GroupProps, 'attached' | 'children' | 'display'> & {\n size?: Size;\n variant?: Variant;\n state?: State;\n }\n>;\n\nconst BitkitSplitButton = forwardRef<HTMLDivElement, BitkitSplitButtonProps>((props, ref) => {\n const { children, size = 'lg', state, variant = 'primary', ...rest } = props;\n\n const childArray = Children.toArray(children);\n const actionChild = childArray.find(isValidActionItem);\n const menuItems = childArray.filter(isValidMenuItem);\n\n const menuSize = size === 'lg' ? 'lg' : 'md';\n const recipe = useSlotRecipe({ key: 'splitButton' });\n const styles = recipe({ variant });\n\n return (\n <SplitButtonProvider value={{ size, state, styles, variant }}>\n <Skeleton asChild loading={state === 'skeleton'}>\n <Group ref={ref} {...rest} attached display=\"inline-flex\">\n {actionChild}\n <BitkitActionMenu.Root\n size={menuSize}\n trigger={\n <BitkitIconButton\n css={styles.trigger}\n icon={IconChevronDown}\n label=\"Toggle menu\"\n size={size}\n state={state === 'loading' ? 'disabled' : state}\n variant={variant}\n />\n }\n positioning={{ placement: 'bottom-end' }}\n >\n {menuItems}\n </BitkitActionMenu.Root>\n </Group>\n </Skeleton>\n </SplitButtonProvider>\n );\n});\nBitkitSplitButton.displayName = 'BitkitSplitButton';\n\nexport default Object.assign(BitkitSplitButton, {\n Action: BitkitSplitButtonAction,\n Group: BitkitActionMenu.Group,\n Item: BitkitActionMenu.Item,\n Separator: BitkitActionMenu.Separator,\n});\n"],"mappings":";;;;;;;;;;;AAgBA,IAAM,qBAAqB,UAA4C;CACrE,OAAO,eAAe,KAAK,KAAK,MAAM,SAAS;AACjD;AAEA,IAAM,mBAAmB,UAA4C;CACnE,OACE,eAAe,KAAK,MACnB,MAAM,SAAS,iBAAiB,SAC/B,MAAM,SAAS,iBAAiB,QAChC,MAAM,SAAS,iBAAiB;AAEtC;AAUA,IAAM,CAAC,qBAAqB,yBAAyB,gBAAkC;CACrF,MAAM;CACN,UAAU;CACV,cAAc;AAChB,CAAC;AAKD,IAAM,0BAA0B,YAA6D,OAAO,QAAQ;CAC1G,MAAM,EAAE,MAAM,OAAO,QAAQ,YAAY,sBAAsB;CAE/D,OAAO,oBAAC,cAAD;EAAmB;EAAK,KAAK,OAAO;EAAc;EAAe;EAAgB;EAAO,GAAI;CAAQ,CAAA;AAC7G,CAAC;AAED,wBAAwB,cAAc;AAWtC,IAAM,oBAAoB,YAAoD,OAAO,QAAQ;CAC3F,MAAM,EAAE,UAAU,OAAO,MAAM,OAAO,UAAU,WAAW,GAAG,SAAS;CAEvE,MAAM,aAAa,SAAS,QAAQ,QAAQ;CAC5C,MAAM,cAAc,WAAW,KAAK,iBAAiB;CACrD,MAAM,YAAY,WAAW,OAAO,eAAe;CAEnD,MAAM,WAAW,SAAS,OAAO,OAAO;CAExC,MAAM,SADS,cAAc,EAAE,KAAK,cAAc,CACnC,EAAO,EAAE,QAAQ,CAAC;CAEjC,OACE,oBAAC,qBAAD;EAAqB,OAAO;GAAE;GAAM;GAAO;GAAQ;EAAQ;YACzD,oBAAC,UAAD;GAAU,SAAA;GAAQ,SAAS,UAAU;aACnC,qBAAC,OAAD;IAAY;IAAK,GAAI;IAAM,UAAA;IAAS,SAAQ;cAA5C,CACG,aACD,oBAAC,iBAAiB,MAAlB;KACE,MAAM;KACN,SACE,oBAAC,kBAAD;MACE,KAAK,OAAO;MACZ,MAAM;MACN,OAAM;MACA;MACN,OAAO,UAAU,YAAY,aAAa;MACjC;KACV,CAAA;KAEH,aAAa,EAAE,WAAW,aAAa;eAEtC;IACoB,CAAA,CAClB;;EACC,CAAA;CACS,CAAA;AAEzB,CAAC;AACD,kBAAkB,cAAc;AAEhC,IAAA,4BAAe,OAAO,OAAO,mBAAmB;CAC9C,QAAQ;CACR,OAAO,iBAAiB;CACxB,MAAM,iBAAiB;CACvB,WAAW,iBAAiB;AAC9B,CAAC"}
1
+ {"version":3,"file":"BitkitSplitButton.js","names":[],"sources":["../../../lib/components/BitkitSplitButton/BitkitSplitButton.tsx"],"sourcesContent":["// eslint-disable-next-line no-restricted-imports\nimport { createContext } from '@chakra-ui/react';\nimport { Group, type GroupProps } from '@chakra-ui/react/group';\nimport { Skeleton } from '@chakra-ui/react/skeleton';\nimport { type SystemStyleObject, useSlotRecipe } from '@chakra-ui/react/styled-system';\nimport { Children, forwardRef, isValidElement, type PropsWithChildren, type ReactElement, type ReactNode } from 'react';\n\nimport { IconChevronDown } from '../../icons';\nimport BitkitActionMenu from '../BitkitActionMenu/BitkitActionMenu';\nimport BitkitButton, {\n type BitkitButtonAsAnchorProps,\n type BitkitButtonAsButtonProps,\n} from '../BitkitButton/BitkitButton';\nimport BitkitIconButton from '../BitkitIconButton/BitkitIconButton';\n\ntype Size = 'lg' | 'md' | 'sm';\ntype Variant = 'primary' | 'secondary';\ntype State = 'disabled' | 'loading' | 'skeleton';\n\nconst isValidActionItem = (child: ReactNode): child is ReactElement => {\n return isValidElement(child) && child.type === BitkitSplitButtonAction;\n};\n\nconst isValidMenuItem = (child: ReactNode): child is ReactElement => {\n return (\n isValidElement(child) &&\n (child.type === BitkitActionMenu.Group ||\n child.type === BitkitActionMenu.Item ||\n child.type === BitkitActionMenu.Separator)\n );\n};\n\n// --- Context ---\ninterface SplitButtonContext {\n size: Size;\n variant: Variant;\n state: State | undefined;\n styles: Record<string, SystemStyleObject>;\n}\n\nconst [SplitButtonProvider, useSplitButtonContext] = createContext<SplitButtonContext>({\n name: 'SplitButtonContext',\n hookName: 'useSplitButtonContext',\n providerName: '<BitkitSplitButton />',\n});\n\n// --- Action ---\n// Split-button action can be a button (default) or anchor (when href is set). asChild is intentionally\n// not part of the API — routing-library elements don't fit cleanly into the Group attached layout.\n// The forwarded ref is HTMLElement so it covers both <button> and <a>.\ntype BitkitSplitButtonActionProps = Omit<\n BitkitButtonAsButtonProps | BitkitButtonAsAnchorProps,\n 'size' | 'variant' | 'state'\n>;\n\nconst BitkitSplitButtonAction = forwardRef<HTMLElement, BitkitSplitButtonActionProps>((props, ref) => {\n const { size, state, styles, variant } = useSplitButtonContext();\n\n if (props.href !== undefined) {\n // Anchor branch: BitkitButton's anchor variant doesn't allow state=\"loading\". Coerce to \"disabled\"\n // so a SplitButton-wide loading state still surfaces visually on a link-mode action.\n return (\n <BitkitButton\n {...(props as BitkitButtonAsAnchorProps)}\n css={styles.action}\n ref={ref}\n size={size}\n state={state === 'loading' ? 'disabled' : state}\n variant={variant}\n />\n );\n }\n\n return (\n <BitkitButton\n {...(props as BitkitButtonAsButtonProps)}\n css={styles.action}\n ref={ref}\n size={size}\n state={state}\n variant={variant}\n />\n );\n});\n\nBitkitSplitButtonAction.displayName = 'BitkitSplitButtonAction';\n\n// --- Root ---\nexport type BitkitSplitButtonProps = PropsWithChildren<\n Omit<GroupProps, 'attached' | 'children' | 'display'> & {\n size?: Size;\n variant?: Variant;\n state?: State;\n }\n>;\n\nconst BitkitSplitButton = forwardRef<HTMLDivElement, BitkitSplitButtonProps>((props, ref) => {\n const { children, size = 'lg', state, variant = 'primary', ...rest } = props;\n\n const childArray = Children.toArray(children);\n const actionChild = childArray.find(isValidActionItem);\n const menuItems = childArray.filter(isValidMenuItem);\n\n const menuSize = size === 'lg' ? 'lg' : 'md';\n const recipe = useSlotRecipe({ key: 'splitButton' });\n const styles = recipe({ variant });\n\n return (\n <SplitButtonProvider value={{ size, state, styles, variant }}>\n <Skeleton asChild loading={state === 'skeleton'}>\n <Group ref={ref} {...rest} attached display=\"inline-flex\">\n {actionChild}\n <BitkitActionMenu.Root\n size={menuSize}\n trigger={\n <BitkitIconButton\n css={styles.trigger}\n icon={IconChevronDown}\n label=\"Toggle menu\"\n size={size}\n state={state === 'loading' ? 'disabled' : state}\n variant={variant}\n />\n }\n positioning={{ placement: 'bottom-end' }}\n >\n {menuItems}\n </BitkitActionMenu.Root>\n </Group>\n </Skeleton>\n </SplitButtonProvider>\n );\n});\nBitkitSplitButton.displayName = 'BitkitSplitButton';\n\nexport default Object.assign(BitkitSplitButton, {\n Action: BitkitSplitButtonAction,\n Group: BitkitActionMenu.Group,\n Item: BitkitActionMenu.Item,\n Separator: BitkitActionMenu.Separator,\n});\n"],"mappings":";;;;;;;;;;;AAmBA,IAAM,qBAAqB,UAA4C;CACrE,OAAO,eAAe,KAAK,KAAK,MAAM,SAAS;AACjD;AAEA,IAAM,mBAAmB,UAA4C;CACnE,OACE,eAAe,KAAK,MACnB,MAAM,SAAS,iBAAiB,SAC/B,MAAM,SAAS,iBAAiB,QAChC,MAAM,SAAS,iBAAiB;AAEtC;AAUA,IAAM,CAAC,qBAAqB,yBAAyB,gBAAkC;CACrF,MAAM;CACN,UAAU;CACV,cAAc;AAChB,CAAC;AAWD,IAAM,0BAA0B,YAAuD,OAAO,QAAQ;CACpG,MAAM,EAAE,MAAM,OAAO,QAAQ,YAAY,sBAAsB;CAE/D,IAAI,MAAM,SAAS,KAAA,GAGjB,OACE,oBAAC,cAAD;EACE,GAAK;EACL,KAAK,OAAO;EACP;EACC;EACN,OAAO,UAAU,YAAY,aAAa;EACjC;CACV,CAAA;CAIL,OACE,oBAAC,cAAD;EACE,GAAK;EACL,KAAK,OAAO;EACP;EACC;EACC;EACE;CACV,CAAA;AAEL,CAAC;AAED,wBAAwB,cAAc;AAWtC,IAAM,oBAAoB,YAAoD,OAAO,QAAQ;CAC3F,MAAM,EAAE,UAAU,OAAO,MAAM,OAAO,UAAU,WAAW,GAAG,SAAS;CAEvE,MAAM,aAAa,SAAS,QAAQ,QAAQ;CAC5C,MAAM,cAAc,WAAW,KAAK,iBAAiB;CACrD,MAAM,YAAY,WAAW,OAAO,eAAe;CAEnD,MAAM,WAAW,SAAS,OAAO,OAAO;CAExC,MAAM,SADS,cAAc,EAAE,KAAK,cAAc,CACnC,EAAO,EAAE,QAAQ,CAAC;CAEjC,OACE,oBAAC,qBAAD;EAAqB,OAAO;GAAE;GAAM;GAAO;GAAQ;EAAQ;YACzD,oBAAC,UAAD;GAAU,SAAA;GAAQ,SAAS,UAAU;aACnC,qBAAC,OAAD;IAAY;IAAK,GAAI;IAAM,UAAA;IAAS,SAAQ;cAA5C,CACG,aACD,oBAAC,iBAAiB,MAAlB;KACE,MAAM;KACN,SACE,oBAAC,kBAAD;MACE,KAAK,OAAO;MACZ,MAAM;MACN,OAAM;MACA;MACN,OAAO,UAAU,YAAY,aAAa;MACjC;KACV,CAAA;KAEH,aAAa,EAAE,WAAW,aAAa;eAEtC;IACoB,CAAA,CAClB;;EACC,CAAA;CACS,CAAA;AAEzB,CAAC;AACD,kBAAkB,cAAc;AAEhC,IAAA,4BAAe,OAAO,OAAO,mBAAmB;CAC9C,QAAQ;CACR,OAAO,iBAAiB;CACxB,MAAM,iBAAiB;CACvB,WAAW,iBAAiB;AAC9B,CAAC"}
@@ -63,11 +63,43 @@ Chakra v2 → v3 prop changes on primitives:
63
63
  |----|----|
64
64
  | `Button` | `BitkitButton` |
65
65
  | `IconButton` | `BitkitIconButton` |
66
+ | `ControlButton` | `BitkitControlButton` |
67
+ | `Button as="a" href="..."` | `BitkitButton href="..."` (renders `<a>`) |
68
+ | `IconButton as="a" href="..."` | `BitkitIconButton href="..."` |
69
+ | `<Link isExternal>` | `BitkitLink isExternal` |
66
70
  | `leftIconName` | `icon` |
67
71
  | `isDisabled` | `state="disabled"` |
68
72
  | `isLoading` | `state="loading"` |
69
73
 
70
- **Gotcha**: `BitkitButton` requires `children` to be a `string`. If a button contains complex layout (icon + text, conditional content, custom JSX), use `chakra.button` from `@chakra-ui/react/styled-system` instead of forcing it into `BitkitButton`.
74
+ **Polymorphism**: `BitkitButton`, `BitkitIconButton`, and `BitkitControlButton` all render as `<a>` when `href` is passed the button recipe styles apply to the anchor. The `state` prop's `'loading'` value is not valid in anchor mode (semantically a button thing).
75
+
76
+ ```tsx
77
+ // Renders <button>
78
+ <BitkitButton onClick={save}>Save</BitkitButton>
79
+
80
+ // Renders <a href="/details"> with the button visual style
81
+ <BitkitButton href="/details">View details</BitkitButton>
82
+
83
+ // External link — auto-adds target="_blank" rel="noreferrer noopener"
84
+ <BitkitButton href="https://example.com" isExternal>External</BitkitButton>
85
+ ```
86
+
87
+ **Routing library integration** — for routers that render their own `<a>` (Next.js Link, React Router Link), use `asChild`:
88
+
89
+ ```tsx
90
+ <BitkitButton asChild icon={IconCheck}>
91
+ <NextLink href="/route">Navigate</NextLink>
92
+ </BitkitButton>
93
+ ```
94
+
95
+ `BitkitLink` also supports `isExternal` for the same target+rel convenience. `BitkitActionMenu.Item` accepts `href` (with optional `target`, `rel`, and `isExternal`) for link-style menu items:
96
+
97
+ ```tsx
98
+ <BitkitActionMenu.Item href="/internal" value="v1">Go to settings</BitkitActionMenu.Item>
99
+ <BitkitActionMenu.Item href="https://example.com" isExternal value="v2">Open docs</BitkitActionMenu.Item>
100
+ ```
101
+
102
+ **Gotcha**: `BitkitButton` requires `children` to be a `string` in button/anchor modes. For complex layout (multiple text nodes, conditional JSX), use `asChild` mode with your own element, or compose with `chakra.button` from `@chakra-ui/react/styled-system` for full freedom.
71
103
 
72
104
  ### Badge / Tag
73
105
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@bitrise/bitkit-v2",
3
3
  "private": false,
4
- "version": "0.3.220",
4
+ "version": "0.3.222",
5
5
  "description": "Bitrise Design System Components built with Chakra UI V3",
6
6
  "keywords": [
7
7
  "react",