@cimpress-ui/react 1.33.1 → 1.34.1

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 (43) hide show
  1. package/dist/commonjs/components/button/button.d.ts +12 -1
  2. package/dist/commonjs/components/button/button.d.ts.map +1 -1
  3. package/dist/commonjs/components/button/button.js +6 -2
  4. package/dist/commonjs/components/button/button.js.map +1 -1
  5. package/dist/commonjs/components/button/disabled-with-reason.d.ts +2 -0
  6. package/dist/commonjs/components/button/disabled-with-reason.d.ts.map +1 -0
  7. package/dist/commonjs/components/button/disabled-with-reason.js +43 -0
  8. package/dist/commonjs/components/button/disabled-with-reason.js.map +1 -0
  9. package/dist/commonjs/components/button/icon-button.d.ts +12 -1
  10. package/dist/commonjs/components/button/icon-button.d.ts.map +1 -1
  11. package/dist/commonjs/components/button/icon-button.js +6 -2
  12. package/dist/commonjs/components/button/icon-button.js.map +1 -1
  13. package/dist/commonjs/components/button/icon-link-button.d.ts +12 -1
  14. package/dist/commonjs/components/button/icon-link-button.d.ts.map +1 -1
  15. package/dist/commonjs/components/button/icon-link-button.js +8 -1
  16. package/dist/commonjs/components/button/icon-link-button.js.map +1 -1
  17. package/dist/commonjs/components/button/link-button.d.ts +12 -1
  18. package/dist/commonjs/components/button/link-button.d.ts.map +1 -1
  19. package/dist/commonjs/components/button/link-button.js +8 -1
  20. package/dist/commonjs/components/button/link-button.js.map +1 -1
  21. package/dist/esm/components/button/button.d.ts +12 -1
  22. package/dist/esm/components/button/button.d.ts.map +1 -1
  23. package/dist/esm/components/button/button.js +6 -2
  24. package/dist/esm/components/button/button.js.map +1 -1
  25. package/dist/esm/components/button/disabled-with-reason.d.ts +2 -0
  26. package/dist/esm/components/button/disabled-with-reason.d.ts.map +1 -0
  27. package/dist/esm/components/button/disabled-with-reason.js +39 -0
  28. package/dist/esm/components/button/disabled-with-reason.js.map +1 -0
  29. package/dist/esm/components/button/icon-button.d.ts +12 -1
  30. package/dist/esm/components/button/icon-button.d.ts.map +1 -1
  31. package/dist/esm/components/button/icon-button.js +6 -2
  32. package/dist/esm/components/button/icon-button.js.map +1 -1
  33. package/dist/esm/components/button/icon-link-button.d.ts +12 -1
  34. package/dist/esm/components/button/icon-link-button.d.ts.map +1 -1
  35. package/dist/esm/components/button/icon-link-button.js +8 -1
  36. package/dist/esm/components/button/icon-link-button.js.map +1 -1
  37. package/dist/esm/components/button/link-button.d.ts +12 -1
  38. package/dist/esm/components/button/link-button.d.ts.map +1 -1
  39. package/dist/esm/components/button/link-button.js +8 -1
  40. package/dist/esm/components/button/link-button.js.map +1 -1
  41. package/dist-styles/core.css +1 -1
  42. package/dist-styles/styles.css +1 -1
  43. package/package.json +1 -1
@@ -1,5 +1,16 @@
1
1
  import type { ActionButtonProps, BaseButtonProps, TextButtonProps } from './types.js';
2
- export interface ButtonProps extends BaseButtonProps, TextButtonProps, ActionButtonProps {
2
+ export interface ButtonProps extends BaseButtonProps, TextButtonProps, Omit<ActionButtonProps, 'isDisabled'> {
3
+ /**
4
+ * Whether the button is disabled.
5
+ *
6
+ * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.
7
+ * This information will be shown to end-users as a tooltip or a popover.
8
+ *
9
+ * @default false
10
+ */
11
+ isDisabled?: boolean | {
12
+ reason: string;
13
+ };
3
14
  }
4
15
  /**
5
16
  * Displays a labelled button that allows users to perform an action.
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/button.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEtF,MAAM,WAAW,WAAY,SAAQ,eAAe,EAAE,eAAe,EAAE,iBAAiB;CAAG;AAmD3F;;;;GAIG;AACH,QAAA,MAAM,OAAO,gKAA+C,CAAC;AAE7D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/button.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEtF,MAAM,WAAW,WAAY,SAAQ,eAAe,EAAE,eAAe,EAAE,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC;IAC1G;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAyDD;;;;GAIG;AACH,QAAA,MAAM,OAAO,gKAA+C,CAAC;AAE7D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC"}
@@ -13,13 +13,17 @@ const use_production_warning_js_1 = require("../../utils/use-production-warning.
13
13
  const with_style_props_js_1 = require("../../with-style-props.js");
14
14
  const spinner_js_1 = require("../internal/spinner/spinner.js");
15
15
  const constants_js_1 = require("./constants.js");
16
- function Button({ children, variant = 'secondary', tone = 'base', size = 'medium', iconStart, iconEnd, isLoading, loadingLabel, isDisabled, fullWidth, UNSAFE_className, UNSAFE_style, ...props }, ref) {
16
+ const disabled_with_reason_js_1 = require("./disabled-with-reason.js");
17
+ function Button({ children, variant = 'secondary', tone = 'base', size = 'medium', iconStart, iconEnd, isLoading, loadingLabel, isDisabled, fullWidth, UNSAFE_className, UNSAFE_style, slot, ...props }, ref) {
17
18
  (0, use_production_warning_js_1.useProductionWarning)(() => {
18
19
  if (isLoading && !loadingLabel) {
19
20
  console.warn('Button requires loadingLabel when isLoading is true for accessibility');
20
21
  }
21
22
  }, [isLoading, loadingLabel]);
22
- return ((0, jsx_runtime_1.jsx)(react_aria_components_1.Button, { ...props, ref: ref, className: (0, clsx_1.default)('cim-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isDisabled: isDisabled, isPending: isLoading, children: ({ isPending }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [iconStart, (0, jsx_runtime_1.jsx)("span", { className: "cim-button-text", children: children }), iconEnd, isPending && (0, jsx_runtime_1.jsx)(spinner_js_1.InternalSpinner, { size: constants_js_1.SPINNER_SIZES[size], "aria-label": loadingLabel })] })) }));
23
+ const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';
24
+ props = (0, disabled_with_reason_js_1.useDisableInteractions)(props, isDisabled ?? false);
25
+ const button = ((0, jsx_runtime_1.jsx)(react_aria_components_1.Button, { ...props, ref: ref, slot: slot, className: (0, clsx_1.default)('cim-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isPending: isLoading, children: ({ isPending }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [iconStart, (0, jsx_runtime_1.jsx)("span", { className: "cim-button-text", children: children }), iconEnd, isPending && (0, jsx_runtime_1.jsx)(spinner_js_1.InternalSpinner, { size: constants_js_1.SPINNER_SIZES[size], "aria-label": loadingLabel })] })) }));
26
+ return hasDisabledReason ? (0, jsx_runtime_1.jsx)(disabled_with_reason_js_1.DisabledWithReason, { reason: isDisabled.reason, children: button }) : button;
23
27
  }
24
28
  /**
25
29
  * Displays a labelled button that allows users to perform an action.
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../src/components/button/button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;AAEb,gDAAwB;AAExB,iEAA4D;AAC5D,yDAAkD;AAClD,qFAA6E;AAC7E,mEAA2D;AAC3D,+DAAiE;AACjE,iDAA+C;AAK/C,SAAS,MAAM,CACb,EACE,QAAQ,EACR,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,OAAO,EACP,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,GAAG,KAAK,EACI,EACd,GAAoC;IAEpC,IAAA,gDAAoB,EAAC,GAAG,EAAE;QACxB,IAAI,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IAE9B,OAAO,CACL,uBAAC,8BAAS,OACJ,KAAK,EACT,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAA,cAAI,EAAC,YAAY,EAAE,gBAAgB,CAAC,EAC/C,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,YAEnB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAClB,6DACG,SAAS,EACV,iCAAM,SAAS,EAAC,iBAAiB,YAAE,QAAQ,GAAQ,EAClD,OAAO,EACP,SAAS,IAAI,uBAAC,4BAAe,IAAC,IAAI,EAAE,4BAAa,CAAC,IAAI,CAAC,gBAAc,YAAY,GAAI,IACrF,CACJ,GACS,CACb,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,GAAG,IAAA,oCAAc,EAAC,IAAA,2BAAU,EAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;AAEzC,yBAAM","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Button as RACButton } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { useProductionWarning } from '../../utils/use-production-warning.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport { InternalSpinner } from '../internal/spinner/spinner.js';\nimport { SPINNER_SIZES } from './constants.js';\nimport type { ActionButtonProps, BaseButtonProps, TextButtonProps } from './types.js';\n\nexport interface ButtonProps extends BaseButtonProps, TextButtonProps, ActionButtonProps {}\n\nfunction Button(\n {\n children,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n iconStart,\n iconEnd,\n isLoading,\n loadingLabel,\n isDisabled,\n fullWidth,\n UNSAFE_className,\n UNSAFE_style,\n ...props\n }: ButtonProps,\n ref: ForwardedRef<HTMLButtonElement>,\n) {\n useProductionWarning(() => {\n if (isLoading && !loadingLabel) {\n console.warn('Button requires loadingLabel when isLoading is true for accessibility');\n }\n }, [isLoading, loadingLabel]);\n\n return (\n <RACButton\n {...props}\n ref={ref}\n className={clsx('cim-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isDisabled={isDisabled}\n isPending={isLoading}\n >\n {({ isPending }) => (\n <>\n {iconStart}\n <span className=\"cim-button-text\">{children}</span>\n {iconEnd}\n {isPending && <InternalSpinner size={SPINNER_SIZES[size]} aria-label={loadingLabel} />}\n </>\n )}\n </RACButton>\n );\n}\n\n/**\n * Displays a labelled button that allows users to perform an action.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _Button = withStyleProps(forwardRef(Button), 'Button');\n\nexport { _Button as Button };\n"]}
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../src/components/button/button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;AAEb,gDAAwB;AAExB,iEAA4D;AAC5D,yDAAkD;AAClD,qFAA6E;AAC7E,mEAA2D;AAC3D,+DAAiE;AACjE,iDAA+C;AAC/C,uEAAuF;AAevF,SAAS,MAAM,CACb,EACE,QAAQ,EACR,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,OAAO,EACP,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,IAAI,EACJ,GAAG,KAAK,EACI,EACd,GAAoC;IAEpC,IAAA,gDAAoB,EAAC,GAAG,EAAE;QACxB,IAAI,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IAE9B,MAAM,iBAAiB,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE,CAAC;IACrF,KAAK,GAAG,IAAA,gDAAsB,EAAC,KAAK,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC;IAE3D,MAAM,MAAM,GAAG,CACb,uBAAC,8BAAS,OACJ,KAAK,EACT,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,IAAA,cAAI,EAAC,YAAY,EAAE,gBAAgB,CAAC,EAC/C,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,SAAS,EAAE,SAAS,YAEnB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAClB,6DACG,SAAS,EACV,iCAAM,SAAS,EAAC,iBAAiB,YAAE,QAAQ,GAAQ,EAClD,OAAO,EACP,SAAS,IAAI,uBAAC,4BAAe,IAAC,IAAI,EAAE,4BAAa,CAAC,IAAI,CAAC,gBAAc,YAAY,GAAI,IACrF,CACJ,GACS,CACb,CAAC;IAEF,OAAO,iBAAiB,CAAC,CAAC,CAAC,uBAAC,4CAAkB,IAAC,MAAM,EAAE,UAAU,CAAC,MAAM,YAAG,MAAM,GAAsB,CAAC,CAAC,CAAC,MAAM,CAAC;AACnH,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,GAAG,IAAA,oCAAc,EAAC,IAAA,2BAAU,EAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;AAEzC,yBAAM","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Button as RACButton } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { useProductionWarning } from '../../utils/use-production-warning.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport { InternalSpinner } from '../internal/spinner/spinner.js';\nimport { SPINNER_SIZES } from './constants.js';\nimport { DisabledWithReason, useDisableInteractions } from './disabled-with-reason.js';\nimport type { ActionButtonProps, BaseButtonProps, TextButtonProps } from './types.js';\n\nexport interface ButtonProps extends BaseButtonProps, TextButtonProps, Omit<ActionButtonProps, 'isDisabled'> {\n /**\n * Whether the button is disabled.\n *\n * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.\n * This information will be shown to end-users as a tooltip or a popover.\n *\n * @default false\n */\n isDisabled?: boolean | { reason: string };\n}\n\nfunction Button(\n {\n children,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n iconStart,\n iconEnd,\n isLoading,\n loadingLabel,\n isDisabled,\n fullWidth,\n UNSAFE_className,\n UNSAFE_style,\n slot,\n ...props\n }: ButtonProps,\n ref: ForwardedRef<HTMLButtonElement>,\n) {\n useProductionWarning(() => {\n if (isLoading && !loadingLabel) {\n console.warn('Button requires loadingLabel when isLoading is true for accessibility');\n }\n }, [isLoading, loadingLabel]);\n\n const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';\n props = useDisableInteractions(props, isDisabled ?? false);\n\n const button = (\n <RACButton\n {...props}\n ref={ref}\n slot={slot}\n className={clsx('cim-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isPending={isLoading}\n >\n {({ isPending }) => (\n <>\n {iconStart}\n <span className=\"cim-button-text\">{children}</span>\n {iconEnd}\n {isPending && <InternalSpinner size={SPINNER_SIZES[size]} aria-label={loadingLabel} />}\n </>\n )}\n </RACButton>\n );\n\n return hasDisabledReason ? <DisabledWithReason reason={isDisabled.reason}>{button}</DisabledWithReason> : button;\n}\n\n/**\n * Displays a labelled button that allows users to perform an action.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _Button = withStyleProps(forwardRef(Button), 'Button');\n\nexport { _Button as Button };\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=disabled-with-reason.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disabled-with-reason.d.ts","sourceRoot":"","sources":["../../../../src/components/button/disabled-with-reason.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DisabledWithReason = DisabledWithReason;
4
+ exports.useDisableInteractions = useDisableInteractions;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const use_media_query_js_1 = require("../../utils/use-media-query.js");
7
+ const popover_js_1 = require("../popover/popover.js");
8
+ const tooltip_js_1 = require("../tooltip/tooltip.js");
9
+ /** @internal */
10
+ function DisabledWithReason({ children, reason }) {
11
+ const hasHover = (0, use_media_query_js_1.useMediaQuery)('(hover: hover)', { defaultValue: true, initializeWithValue: true });
12
+ if (hasHover) {
13
+ return (0, jsx_runtime_1.jsx)(tooltip_js_1.Tooltip, { label: reason, children: children });
14
+ }
15
+ else {
16
+ return ((0, jsx_runtime_1.jsxs)(popover_js_1.PopoverRoot, { children: [children, (0, jsx_runtime_1.jsx)(popover_js_1.Popover, { children: reason })] }));
17
+ }
18
+ }
19
+ // Events to preserve when `isDisabled` is true (for tooltips and other overlays)
20
+ const PRESERVED_EVENT_PATTERN = /Focus|Blur|Hover|Pointer(Enter|Leave|Over|Out)|Mouse(Enter|Leave|Over|Out)/;
21
+ /** @internal */
22
+ // eslint-disable-next-line react-refresh/only-export-components
23
+ function useDisableInteractions(props, isDisabled) {
24
+ if (isDisabled !== false) {
25
+ for (const key in props) {
26
+ if (key.startsWith('on') && !PRESERVED_EVENT_PATTERN.test(key)) {
27
+ delete props[key];
28
+ }
29
+ }
30
+ }
31
+ if (typeof isDisabled === 'object' && isDisabled.reason) {
32
+ // Use `aria-disabled` instead of `disabled`
33
+ props['aria-disabled'] = true;
34
+ // Prevent form submission
35
+ props.type = props.type === 'submit' ? 'button' : props.type;
36
+ }
37
+ else if (isDisabled !== false) {
38
+ // Make the button actually disabled
39
+ props.isDisabled = true;
40
+ }
41
+ return props;
42
+ }
43
+ //# sourceMappingURL=disabled-with-reason.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disabled-with-reason.js","sourceRoot":"","sources":["../../../../src/components/button/disabled-with-reason.tsx"],"names":[],"mappings":";;AAOA,gDAcC;AAOD,wDAuBC;;AAjDD,uEAA+D;AAC/D,sDAA6D;AAC7D,sDAAgD;AAEhD,gBAAgB;AAChB,SAAgB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,MAAM,EAA2C;IAC9F,MAAM,QAAQ,GAAG,IAAA,kCAAa,EAAC,gBAAgB,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpG,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,uBAAC,oBAAO,IAAC,KAAK,EAAE,MAAM,YAAG,QAAQ,GAAW,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,OAAO,CACL,wBAAC,wBAAW,eACT,QAAQ,EAET,uBAAC,oBAAO,cAAE,MAAM,GAAW,IACf,CACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED,iFAAiF;AACjF,MAAM,uBAAuB,GAAG,4EAA4E,CAAC;AAE7G,gBAAgB;AAChB,gEAAgE;AAChE,SAAgB,sBAAsB,CACpC,KAAQ,EACR,UAAwC;IAExC,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/D,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACxD,4CAA4C;QAC5C,KAAK,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;QAC9B,0BAA0B;QAC1B,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;IAC/D,CAAC;SAAM,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QAChC,oCAAoC;QACpC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react';\nimport type { ButtonProps as RACButtonProps } from 'react-aria-components';\nimport { useMediaQuery } from '../../utils/use-media-query.js';\nimport { Popover, PopoverRoot } from '../popover/popover.js';\nimport { Tooltip } from '../tooltip/tooltip.js';\n\n/** @internal */\nexport function DisabledWithReason({ children, reason }: { children: ReactNode; reason: string }) {\n const hasHover = useMediaQuery('(hover: hover)', { defaultValue: true, initializeWithValue: true });\n\n if (hasHover) {\n return <Tooltip label={reason}>{children}</Tooltip>;\n } else {\n return (\n <PopoverRoot>\n {children}\n {/* TODO: add aria-label */}\n <Popover>{reason}</Popover>\n </PopoverRoot>\n );\n }\n}\n\n// Events to preserve when `isDisabled` is true (for tooltips and other overlays)\nconst PRESERVED_EVENT_PATTERN = /Focus|Blur|Hover|Pointer(Enter|Leave|Over|Out)|Mouse(Enter|Leave|Over|Out)/;\n\n/** @internal */\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useDisableInteractions<T extends Partial<RACButtonProps & HTMLAttributes<HTMLButtonElement>>>(\n props: T,\n isDisabled: boolean | { reason: string },\n): T {\n if (isDisabled !== false) {\n for (const key in props) {\n if (key.startsWith('on') && !PRESERVED_EVENT_PATTERN.test(key)) {\n delete props[key];\n }\n }\n }\n\n if (typeof isDisabled === 'object' && isDisabled.reason) {\n // Use `aria-disabled` instead of `disabled`\n props['aria-disabled'] = true;\n // Prevent form submission\n props.type = props.type === 'submit' ? 'button' : props.type;\n } else if (isDisabled !== false) {\n // Make the button actually disabled\n props.isDisabled = true;\n }\n\n return props;\n}\n"]}
@@ -1,5 +1,16 @@
1
1
  import type { ActionButtonProps, BaseButtonProps, SingleIconButtonProps } from './types.js';
2
- export interface IconButtonProps extends BaseButtonProps, SingleIconButtonProps, ActionButtonProps {
2
+ export interface IconButtonProps extends BaseButtonProps, SingleIconButtonProps, Omit<ActionButtonProps, 'isDisabled'> {
3
+ /**
4
+ * Whether the button is disabled.
5
+ *
6
+ * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.
7
+ * This information will be shown to the end-users as a tooltip or a popover.
8
+ *
9
+ * @default false
10
+ */
11
+ isDisabled?: boolean | {
12
+ reason: string;
13
+ };
3
14
  }
4
15
  /**
5
16
  * Displays an icon-only button that allows users to perform an action.
@@ -1 +1 @@
1
- {"version":3,"file":"icon-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/icon-button.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE5F,MAAM,WAAW,eAAgB,SAAQ,eAAe,EAAE,qBAAqB,EAAE,iBAAiB;CAAG;AA+CrG;;;;GAIG;AACH,QAAA,MAAM,WAAW,oKAAuD,CAAC;AAEzE,OAAO,EAAE,WAAW,IAAI,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"icon-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/icon-button.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE5F,MAAM,WAAW,eAAgB,SAAQ,eAAe,EAAE,qBAAqB,EAAE,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC;IACpH;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAqDD;;;;GAIG;AACH,QAAA,MAAM,WAAW,oKAAuD,CAAC;AAEzE,OAAO,EAAE,WAAW,IAAI,UAAU,EAAE,CAAC"}
@@ -13,13 +13,17 @@ const use_production_warning_js_1 = require("../../utils/use-production-warning.
13
13
  const with_style_props_js_1 = require("../../with-style-props.js");
14
14
  const spinner_js_1 = require("../internal/spinner/spinner.js");
15
15
  const constants_js_1 = require("./constants.js");
16
- function IconButton({ icon, variant = 'secondary', tone = 'base', size = 'medium', isLoading, loadingLabel, isDisabled, fullWidth, UNSAFE_className, UNSAFE_style, ...props }, ref) {
16
+ const disabled_with_reason_js_1 = require("./disabled-with-reason.js");
17
+ function IconButton({ icon, variant = 'secondary', tone = 'base', size = 'medium', isLoading, loadingLabel, isDisabled, fullWidth, UNSAFE_className, UNSAFE_style, slot, ...props }, ref) {
17
18
  (0, use_production_warning_js_1.useProductionWarning)(() => {
18
19
  if (isLoading && !loadingLabel) {
19
20
  console.warn('IconButton requires loadingLabel when isLoading is true for accessibility');
20
21
  }
21
22
  }, [isLoading, loadingLabel]);
22
- return ((0, jsx_runtime_1.jsx)(react_aria_components_1.Button, { ...props, ref: ref, className: (0, clsx_1.default)('cim-icon-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isDisabled: isDisabled, isPending: isLoading, children: ({ isPending }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon, isPending && (0, jsx_runtime_1.jsx)(spinner_js_1.InternalSpinner, { size: constants_js_1.SPINNER_SIZES[size], "aria-label": loadingLabel })] })) }));
23
+ const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';
24
+ props = (0, disabled_with_reason_js_1.useDisableInteractions)(props, isDisabled ?? false);
25
+ const button = ((0, jsx_runtime_1.jsx)(react_aria_components_1.Button, { ...props, ref: ref, slot: slot, className: (0, clsx_1.default)('cim-icon-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isPending: isLoading, children: ({ isPending }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [icon, isPending && (0, jsx_runtime_1.jsx)(spinner_js_1.InternalSpinner, { size: constants_js_1.SPINNER_SIZES[size], "aria-label": loadingLabel })] })) }));
26
+ return hasDisabledReason ? (0, jsx_runtime_1.jsx)(disabled_with_reason_js_1.DisabledWithReason, { reason: isDisabled.reason, children: button }) : button;
23
27
  }
24
28
  /**
25
29
  * Displays an icon-only button that allows users to perform an action.
@@ -1 +1 @@
1
- {"version":3,"file":"icon-button.js","sourceRoot":"","sources":["../../../../src/components/button/icon-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;AAEb,gDAAwB;AAExB,iEAA4D;AAC5D,yDAAkD;AAClD,qFAA6E;AAC7E,mEAA2D;AAC3D,+DAAiE;AACjE,iDAA+C;AAK/C,SAAS,UAAU,CACjB,EACE,IAAI,EACJ,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,GAAG,KAAK,EACQ,EAClB,GAAoC;IAEpC,IAAA,gDAAoB,EAAC,GAAG,EAAE;QACxB,IAAI,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IAE9B,OAAO,CACL,uBAAC,8BAAS,OACJ,KAAK,EACT,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAA,cAAI,EAAC,iBAAiB,EAAE,gBAAgB,CAAC,EACpD,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,YAEnB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAClB,6DACG,IAAI,EACJ,SAAS,IAAI,uBAAC,4BAAe,IAAC,IAAI,EAAE,4BAAa,CAAC,IAAI,CAAC,gBAAc,YAAY,GAAI,IACrF,CACJ,GACS,CACb,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,IAAA,oCAAc,EAAC,IAAA,2BAAU,EAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;AAEjD,iCAAU","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Button as RACButton } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { useProductionWarning } from '../../utils/use-production-warning.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport { InternalSpinner } from '../internal/spinner/spinner.js';\nimport { SPINNER_SIZES } from './constants.js';\nimport type { ActionButtonProps, BaseButtonProps, SingleIconButtonProps } from './types.js';\n\nexport interface IconButtonProps extends BaseButtonProps, SingleIconButtonProps, ActionButtonProps {}\n\nfunction IconButton(\n {\n icon,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n isLoading,\n loadingLabel,\n isDisabled,\n fullWidth,\n UNSAFE_className,\n UNSAFE_style,\n ...props\n }: IconButtonProps,\n ref: ForwardedRef<HTMLButtonElement>,\n) {\n useProductionWarning(() => {\n if (isLoading && !loadingLabel) {\n console.warn('IconButton requires loadingLabel when isLoading is true for accessibility');\n }\n }, [isLoading, loadingLabel]);\n\n return (\n <RACButton\n {...props}\n ref={ref}\n className={clsx('cim-icon-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isDisabled={isDisabled}\n isPending={isLoading}\n >\n {({ isPending }) => (\n <>\n {icon}\n {isPending && <InternalSpinner size={SPINNER_SIZES[size]} aria-label={loadingLabel} />}\n </>\n )}\n </RACButton>\n );\n}\n\n/**\n * Displays an icon-only button that allows users to perform an action.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _IconButton = withStyleProps(forwardRef(IconButton), 'IconButton');\n\nexport { _IconButton as IconButton };\n"]}
1
+ {"version":3,"file":"icon-button.js","sourceRoot":"","sources":["../../../../src/components/button/icon-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;AAEb,gDAAwB;AAExB,iEAA4D;AAC5D,yDAAkD;AAClD,qFAA6E;AAC7E,mEAA2D;AAC3D,+DAAiE;AACjE,iDAA+C;AAC/C,uEAAuF;AAevF,SAAS,UAAU,CACjB,EACE,IAAI,EACJ,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,IAAI,EACJ,GAAG,KAAK,EACQ,EAClB,GAAoC;IAEpC,IAAA,gDAAoB,EAAC,GAAG,EAAE;QACxB,IAAI,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IAE9B,MAAM,iBAAiB,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE,CAAC;IACrF,KAAK,GAAG,IAAA,gDAAsB,EAAC,KAAK,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC;IAE3D,MAAM,MAAM,GAAG,CACb,uBAAC,8BAAS,OACJ,KAAK,EACT,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,IAAA,cAAI,EAAC,iBAAiB,EAAE,gBAAgB,CAAC,EACpD,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,SAAS,EAAE,SAAS,YAEnB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAClB,6DACG,IAAI,EACJ,SAAS,IAAI,uBAAC,4BAAe,IAAC,IAAI,EAAE,4BAAa,CAAC,IAAI,CAAC,gBAAc,YAAY,GAAI,IACrF,CACJ,GACS,CACb,CAAC;IAEF,OAAO,iBAAiB,CAAC,CAAC,CAAC,uBAAC,4CAAkB,IAAC,MAAM,EAAE,UAAU,CAAC,MAAM,YAAG,MAAM,GAAsB,CAAC,CAAC,CAAC,MAAM,CAAC;AACnH,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,IAAA,oCAAc,EAAC,IAAA,2BAAU,EAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;AAEjD,iCAAU","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Button as RACButton } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { useProductionWarning } from '../../utils/use-production-warning.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport { InternalSpinner } from '../internal/spinner/spinner.js';\nimport { SPINNER_SIZES } from './constants.js';\nimport { DisabledWithReason, useDisableInteractions } from './disabled-with-reason.js';\nimport type { ActionButtonProps, BaseButtonProps, SingleIconButtonProps } from './types.js';\n\nexport interface IconButtonProps extends BaseButtonProps, SingleIconButtonProps, Omit<ActionButtonProps, 'isDisabled'> {\n /**\n * Whether the button is disabled.\n *\n * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.\n * This information will be shown to the end-users as a tooltip or a popover.\n *\n * @default false\n */\n isDisabled?: boolean | { reason: string };\n}\n\nfunction IconButton(\n {\n icon,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n isLoading,\n loadingLabel,\n isDisabled,\n fullWidth,\n UNSAFE_className,\n UNSAFE_style,\n slot,\n ...props\n }: IconButtonProps,\n ref: ForwardedRef<HTMLButtonElement>,\n) {\n useProductionWarning(() => {\n if (isLoading && !loadingLabel) {\n console.warn('IconButton requires loadingLabel when isLoading is true for accessibility');\n }\n }, [isLoading, loadingLabel]);\n\n const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';\n props = useDisableInteractions(props, isDisabled ?? false);\n\n const button = (\n <RACButton\n {...props}\n ref={ref}\n slot={slot}\n className={clsx('cim-icon-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isPending={isLoading}\n >\n {({ isPending }) => (\n <>\n {icon}\n {isPending && <InternalSpinner size={SPINNER_SIZES[size]} aria-label={loadingLabel} />}\n </>\n )}\n </RACButton>\n );\n\n return hasDisabledReason ? <DisabledWithReason reason={isDisabled.reason}>{button}</DisabledWithReason> : button;\n}\n\n/**\n * Displays an icon-only button that allows users to perform an action.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _IconButton = withStyleProps(forwardRef(IconButton), 'IconButton');\n\nexport { _IconButton as IconButton };\n"]}
@@ -1,7 +1,18 @@
1
1
  import { type LinkProps as RACLinkProps } from 'react-aria-components';
2
2
  import type { NavigationProps, WithRequired } from '../types.js';
3
3
  import type { BaseButtonProps, SingleIconButtonProps } from './types.js';
4
- export interface IconLinkButtonProps extends Omit<BaseButtonProps, 'id'>, SingleIconButtonProps, WithRequired<NavigationProps, 'href'>, Pick<RACLinkProps, 'isDisabled' | 'onHoverStart' | 'onHoverEnd'> {
4
+ export interface IconLinkButtonProps extends Omit<BaseButtonProps, 'id'>, SingleIconButtonProps, WithRequired<NavigationProps, 'href'>, Pick<RACLinkProps, 'onHoverStart' | 'onHoverEnd'> {
5
+ /**
6
+ * Whether the button is disabled.
7
+ *
8
+ * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.
9
+ * This information will be shown to the end-users as a tooltip or a popover.
10
+ *
11
+ * @default false
12
+ */
13
+ isDisabled?: boolean | {
14
+ reason: string;
15
+ };
5
16
  }
6
17
  /**
7
18
  * Displays an icon-only button that allows users to navigate to another page or resource.
@@ -1 +1 @@
1
- {"version":3,"file":"icon-link-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/icon-link-button.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,SAAS,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGxF,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,mBACf,SACE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAC3B,qBAAqB,EACrB,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,EACrC,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,cAAc,GAAG,YAAY,CAAC;CAAG;AAiCvE;;;;GAIG;AACH,QAAA,MAAM,eAAe,wKAA+D,CAAC;AAErF,OAAO,EAAE,eAAe,IAAI,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"icon-link-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/icon-link-button.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,SAAS,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGxF,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,mBACf,SACE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAC3B,qBAAqB,EACrB,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,EACrC,IAAI,CAAC,YAAY,EAAE,cAAc,GAAG,YAAY,CAAC;IACnD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAsDD;;;;GAIG;AACH,QAAA,MAAM,eAAe,wKAA+D,CAAC;AAErF,OAAO,EAAE,eAAe,IAAI,cAAc,EAAE,CAAC"}
@@ -10,8 +10,15 @@ const clsx_1 = __importDefault(require("clsx"));
10
10
  const react_aria_components_1 = require("react-aria-components");
11
11
  const forward_ref_js_1 = require("../../forward-ref.js");
12
12
  const with_style_props_js_1 = require("../../with-style-props.js");
13
+ const icon_button_js_1 = require("./icon-button.js");
13
14
  function IconLinkButton({ icon, variant = 'secondary', tone = 'base', size = 'medium', isDisabled = false, fullWidth = false, UNSAFE_className, UNSAFE_style, ...props }, ref) {
14
- return ((0, jsx_runtime_1.jsx)(react_aria_components_1.Link, { ...props, ref: ref, className: (0, clsx_1.default)('cim-icon-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isDisabled: isDisabled, children: icon }));
15
+ const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';
16
+ if (hasDisabledReason) {
17
+ // `RACLink` doesn't support aria-disabled while keeping interactivity, so we render an `IconButton` instead
18
+ const { href, target, hrefLang, download, ping, referrerPolicy, rel, routerOptions, ...buttonProps } = props;
19
+ return ((0, jsx_runtime_1.jsx)(icon_button_js_1.IconButton, { ...buttonProps, icon: icon, variant: variant, tone: tone, size: size, isDisabled: isDisabled, fullWidth: fullWidth, UNSAFE_className: UNSAFE_className, UNSAFE_style: UNSAFE_style }));
20
+ }
21
+ return ((0, jsx_runtime_1.jsx)(react_aria_components_1.Link, { ...props, ref: ref, className: (0, clsx_1.default)('cim-icon-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isDisabled: !!isDisabled, children: icon }));
15
22
  }
16
23
  /**
17
24
  * Displays an icon-only button that allows users to navigate to another page or resource.
@@ -1 +1 @@
1
- {"version":3,"file":"icon-link-button.js","sourceRoot":"","sources":["../../../../src/components/button/icon-link-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;AAEb,gDAAwB;AAExB,iEAAwF;AACxF,yDAAkD;AAClD,mEAA2D;AAW3D,SAAS,cAAc,CACrB,EACE,IAAI,EACJ,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,UAAU,GAAG,KAAK,EAClB,SAAS,GAAG,KAAK,EACjB,gBAAgB,EAChB,YAAY,EACZ,GAAG,KAAK,EACY,EACtB,GAAoC;IAEpC,OAAO,CACL,uBAAC,4BAAO,OACF,KAAK,EACT,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAA,cAAI,EAAC,iBAAiB,EAAE,gBAAgB,CAAC,EACpD,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,UAAU,EAAE,UAAU,YAErB,IAAI,GACG,CACX,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,eAAe,GAAG,IAAA,oCAAc,EAAC,IAAA,2BAAU,EAAC,cAAc,CAAC,EAAE,gBAAgB,CAAC,CAAC;AAEzD,yCAAc","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Link as RACLink, type LinkProps as RACLinkProps } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport type { NavigationProps, WithRequired } from '../types.js';\nimport type { BaseButtonProps, SingleIconButtonProps } from './types.js';\n\nexport interface IconLinkButtonProps\n extends\n Omit<BaseButtonProps, 'id'>,\n SingleIconButtonProps,\n WithRequired<NavigationProps, 'href'>,\n Pick<RACLinkProps, 'isDisabled' | 'onHoverStart' | 'onHoverEnd'> {}\n\nfunction IconLinkButton(\n {\n icon,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n isDisabled = false,\n fullWidth = false,\n UNSAFE_className,\n UNSAFE_style,\n ...props\n }: IconLinkButtonProps,\n ref: ForwardedRef<HTMLAnchorElement>,\n) {\n return (\n <RACLink\n {...props}\n ref={ref}\n className={clsx('cim-icon-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isDisabled={isDisabled}\n >\n {icon}\n </RACLink>\n );\n}\n\n/**\n * Displays an icon-only button that allows users to navigate to another page or resource.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _IconLinkButton = withStyleProps(forwardRef(IconLinkButton), 'IconLinkButton');\n\nexport { _IconLinkButton as IconLinkButton };\n"]}
1
+ {"version":3,"file":"icon-link-button.js","sourceRoot":"","sources":["../../../../src/components/button/icon-link-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;AAEb,gDAAwB;AAExB,iEAAwF;AACxF,yDAAkD;AAClD,mEAA2D;AAE3D,qDAA8C;AAoB9C,SAAS,cAAc,CACrB,EACE,IAAI,EACJ,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,UAAU,GAAG,KAAK,EAClB,SAAS,GAAG,KAAK,EACjB,gBAAgB,EAChB,YAAY,EACZ,GAAG,KAAK,EACY,EACtB,GAAoC;IAEpC,MAAM,iBAAiB,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE,CAAC;IAErF,IAAI,iBAAiB,EAAE,CAAC;QACtB,4GAA4G;QAC5G,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,WAAW,EAAE,GAAG,KAAK,CAAC;QAE7G,OAAO,CACL,uBAAC,2BAAU,OACL,WAAW,EACf,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,EAAE,YAAY,GAC1B,CACH,CAAC;IACJ,CAAC;IAED,OAAO,CACL,uBAAC,4BAAO,OACF,KAAK,EACT,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAA,cAAI,EAAC,iBAAiB,EAAE,gBAAgB,CAAC,EACpD,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,UAAU,EAAE,CAAC,CAAC,UAAU,YAEvB,IAAI,GACG,CACX,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,eAAe,GAAG,IAAA,oCAAc,EAAC,IAAA,2BAAU,EAAC,cAAc,CAAC,EAAE,gBAAgB,CAAC,CAAC;AAEzD,yCAAc","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Link as RACLink, type LinkProps as RACLinkProps } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport type { NavigationProps, WithRequired } from '../types.js';\nimport { IconButton } from './icon-button.js';\nimport type { BaseButtonProps, SingleIconButtonProps } from './types.js';\n\nexport interface IconLinkButtonProps\n extends\n Omit<BaseButtonProps, 'id'>,\n SingleIconButtonProps,\n WithRequired<NavigationProps, 'href'>,\n Pick<RACLinkProps, 'onHoverStart' | 'onHoverEnd'> {\n /**\n * Whether the button is disabled.\n *\n * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.\n * This information will be shown to the end-users as a tooltip or a popover.\n *\n * @default false\n */\n isDisabled?: boolean | { reason: string };\n}\n\nfunction IconLinkButton(\n {\n icon,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n isDisabled = false,\n fullWidth = false,\n UNSAFE_className,\n UNSAFE_style,\n ...props\n }: IconLinkButtonProps,\n ref: ForwardedRef<HTMLAnchorElement>,\n) {\n const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';\n\n if (hasDisabledReason) {\n // `RACLink` doesn't support aria-disabled while keeping interactivity, so we render an `IconButton` instead\n const { href, target, hrefLang, download, ping, referrerPolicy, rel, routerOptions, ...buttonProps } = props;\n\n return (\n <IconButton\n {...buttonProps}\n icon={icon}\n variant={variant}\n tone={tone}\n size={size}\n isDisabled={isDisabled}\n fullWidth={fullWidth}\n UNSAFE_className={UNSAFE_className}\n UNSAFE_style={UNSAFE_style}\n />\n );\n }\n\n return (\n <RACLink\n {...props}\n ref={ref}\n className={clsx('cim-icon-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isDisabled={!!isDisabled}\n >\n {icon}\n </RACLink>\n );\n}\n\n/**\n * Displays an icon-only button that allows users to navigate to another page or resource.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _IconLinkButton = withStyleProps(forwardRef(IconLinkButton), 'IconLinkButton');\n\nexport { _IconLinkButton as IconLinkButton };\n"]}
@@ -1,7 +1,18 @@
1
1
  import { type LinkProps as RACLinkProps } from 'react-aria-components';
2
2
  import type { NavigationProps, WithRequired } from '../types.js';
3
3
  import type { BaseButtonProps, TextButtonProps } from './types.js';
4
- export interface LinkButtonProps extends Omit<BaseButtonProps, 'id'>, TextButtonProps, WithRequired<NavigationProps, 'href'>, Pick<RACLinkProps, 'isDisabled' | 'onHoverStart' | 'onHoverEnd'> {
4
+ export interface LinkButtonProps extends Omit<BaseButtonProps, 'id'>, TextButtonProps, WithRequired<NavigationProps, 'href'>, Pick<RACLinkProps, 'onHoverStart' | 'onHoverEnd'> {
5
+ /**
6
+ * Whether the button is disabled.
7
+ *
8
+ * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.
9
+ * This information will be shown to the end-users as a tooltip or a popover.
10
+ *
11
+ * @default false
12
+ */
13
+ isDisabled?: boolean | {
14
+ reason: string;
15
+ };
5
16
  }
6
17
  /**
7
18
  * Displays a labelled button that allows users to navigate to another page or resource.
@@ -1 +1 @@
1
- {"version":3,"file":"link-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/link-button.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,SAAS,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGxF,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,eACf,SACE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAC3B,eAAe,EACf,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,EACrC,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,cAAc,GAAG,YAAY,CAAC;CAAG;AAqCvE;;;;GAIG;AACH,QAAA,MAAM,WAAW,oKAAuD,CAAC;AAEzE,OAAO,EAAE,WAAW,IAAI,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"link-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/link-button.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,SAAS,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGxF,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,eACf,SACE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAC3B,eAAe,EACf,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,EACrC,IAAI,CAAC,YAAY,EAAE,cAAc,GAAG,YAAY,CAAC;IACnD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AA6DD;;;;GAIG;AACH,QAAA,MAAM,WAAW,oKAAuD,CAAC;AAEzE,OAAO,EAAE,WAAW,IAAI,UAAU,EAAE,CAAC"}
@@ -10,8 +10,15 @@ const clsx_1 = __importDefault(require("clsx"));
10
10
  const react_aria_components_1 = require("react-aria-components");
11
11
  const forward_ref_js_1 = require("../../forward-ref.js");
12
12
  const with_style_props_js_1 = require("../../with-style-props.js");
13
+ const button_js_1 = require("./button.js");
13
14
  function LinkButton({ children, variant = 'secondary', tone = 'base', size = 'medium', iconStart, iconEnd, isDisabled = false, fullWidth = false, UNSAFE_className, UNSAFE_style, ...props }, ref) {
14
- return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Link, { ...props, ref: ref, className: (0, clsx_1.default)('cim-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isDisabled: isDisabled, children: [iconStart, (0, jsx_runtime_1.jsx)("span", { className: "cim-button-text", children: children }), iconEnd] }));
15
+ const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';
16
+ if (hasDisabledReason) {
17
+ // `RACLink` doesn't support aria-disabled while keeping interactivity, so we render a `Button` instead
18
+ const { href, target, hrefLang, download, ping, referrerPolicy, rel, routerOptions, ...buttonProps } = props;
19
+ return ((0, jsx_runtime_1.jsx)(button_js_1.Button, { ...buttonProps, variant: variant, tone: tone, size: size, iconStart: iconStart, iconEnd: iconEnd, isDisabled: isDisabled, fullWidth: fullWidth, UNSAFE_className: UNSAFE_className, UNSAFE_style: UNSAFE_style, children: children }));
20
+ }
21
+ return ((0, jsx_runtime_1.jsxs)(react_aria_components_1.Link, { ...props, ref: ref, className: (0, clsx_1.default)('cim-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isDisabled: !!isDisabled, children: [iconStart, (0, jsx_runtime_1.jsx)("span", { className: "cim-button-text", children: children }), iconEnd] }));
15
22
  }
16
23
  /**
17
24
  * Displays a labelled button that allows users to navigate to another page or resource.
@@ -1 +1 @@
1
- {"version":3,"file":"link-button.js","sourceRoot":"","sources":["../../../../src/components/button/link-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;AAEb,gDAAwB;AAExB,iEAAwF;AACxF,yDAAkD;AAClD,mEAA2D;AAW3D,SAAS,UAAU,CACjB,EACE,QAAQ,EACR,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,OAAO,EACP,UAAU,GAAG,KAAK,EAClB,SAAS,GAAG,KAAK,EACjB,gBAAgB,EAChB,YAAY,EACZ,GAAG,KAAK,EACQ,EAClB,GAAoC;IAEpC,OAAO,CACL,wBAAC,4BAAO,OACF,KAAK,EACT,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAA,cAAI,EAAC,YAAY,EAAE,gBAAgB,CAAC,EAC/C,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,UAAU,EAAE,UAAU,aAErB,SAAS,EACV,iCAAM,SAAS,EAAC,iBAAiB,YAAE,QAAQ,GAAQ,EAClD,OAAO,IACA,CACX,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,IAAA,oCAAc,EAAC,IAAA,2BAAU,EAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;AAEjD,iCAAU","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Link as RACLink, type LinkProps as RACLinkProps } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport type { NavigationProps, WithRequired } from '../types.js';\nimport type { BaseButtonProps, TextButtonProps } from './types.js';\n\nexport interface LinkButtonProps\n extends\n Omit<BaseButtonProps, 'id'>,\n TextButtonProps,\n WithRequired<NavigationProps, 'href'>,\n Pick<RACLinkProps, 'isDisabled' | 'onHoverStart' | 'onHoverEnd'> {}\n\nfunction LinkButton(\n {\n children,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n iconStart,\n iconEnd,\n isDisabled = false,\n fullWidth = false,\n UNSAFE_className,\n UNSAFE_style,\n ...props\n }: LinkButtonProps,\n ref: ForwardedRef<HTMLAnchorElement>,\n) {\n return (\n <RACLink\n {...props}\n ref={ref}\n className={clsx('cim-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isDisabled={isDisabled}\n >\n {iconStart}\n <span className=\"cim-button-text\">{children}</span>\n {iconEnd}\n </RACLink>\n );\n}\n\n/**\n * Displays a labelled button that allows users to navigate to another page or resource.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _LinkButton = withStyleProps(forwardRef(LinkButton), 'LinkButton');\n\nexport { _LinkButton as LinkButton };\n"]}
1
+ {"version":3,"file":"link-button.js","sourceRoot":"","sources":["../../../../src/components/button/link-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;;;;;;;AAEb,gDAAwB;AAExB,iEAAwF;AACxF,yDAAkD;AAClD,mEAA2D;AAE3D,2CAAqC;AAoBrC,SAAS,UAAU,CACjB,EACE,QAAQ,EACR,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,OAAO,EACP,UAAU,GAAG,KAAK,EAClB,SAAS,GAAG,KAAK,EACjB,gBAAgB,EAChB,YAAY,EACZ,GAAG,KAAK,EACQ,EAClB,GAAoC;IAEpC,MAAM,iBAAiB,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE,CAAC;IAErF,IAAI,iBAAiB,EAAE,CAAC;QACtB,uGAAuG;QACvG,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,aAAa,EAAE,GAAG,WAAW,EAAE,GAAG,KAAK,CAAC;QAE7G,OAAO,CACL,uBAAC,kBAAM,OACD,WAAW,EACf,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,EACpB,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,gBAAgB,EAAE,gBAAgB,EAClC,YAAY,EAAE,YAAY,YAEzB,QAAQ,GACF,CACV,CAAC;IACJ,CAAC;IAED,OAAO,CACL,wBAAC,4BAAO,OACF,KAAK,EACT,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAA,cAAI,EAAC,YAAY,EAAE,gBAAgB,CAAC,EAC/C,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,UAAU,EAAE,CAAC,CAAC,UAAU,aAEvB,SAAS,EACV,iCAAM,SAAS,EAAC,iBAAiB,YAAE,QAAQ,GAAQ,EAClD,OAAO,IACA,CACX,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,IAAA,oCAAc,EAAC,IAAA,2BAAU,EAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;AAEjD,iCAAU","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Link as RACLink, type LinkProps as RACLinkProps } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport type { NavigationProps, WithRequired } from '../types.js';\nimport { Button } from './button.js';\nimport type { BaseButtonProps, TextButtonProps } from './types.js';\n\nexport interface LinkButtonProps\n extends\n Omit<BaseButtonProps, 'id'>,\n TextButtonProps,\n WithRequired<NavigationProps, 'href'>,\n Pick<RACLinkProps, 'onHoverStart' | 'onHoverEnd'> {\n /**\n * Whether the button is disabled.\n *\n * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.\n * This information will be shown to the end-users as a tooltip or a popover.\n *\n * @default false\n */\n isDisabled?: boolean | { reason: string };\n}\n\nfunction LinkButton(\n {\n children,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n iconStart,\n iconEnd,\n isDisabled = false,\n fullWidth = false,\n UNSAFE_className,\n UNSAFE_style,\n ...props\n }: LinkButtonProps,\n ref: ForwardedRef<HTMLAnchorElement>,\n) {\n const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';\n\n if (hasDisabledReason) {\n // `RACLink` doesn't support aria-disabled while keeping interactivity, so we render a `Button` instead\n const { href, target, hrefLang, download, ping, referrerPolicy, rel, routerOptions, ...buttonProps } = props;\n\n return (\n <Button\n {...buttonProps}\n variant={variant}\n tone={tone}\n size={size}\n iconStart={iconStart}\n iconEnd={iconEnd}\n isDisabled={isDisabled}\n fullWidth={fullWidth}\n UNSAFE_className={UNSAFE_className}\n UNSAFE_style={UNSAFE_style}\n >\n {children}\n </Button>\n );\n }\n\n return (\n <RACLink\n {...props}\n ref={ref}\n className={clsx('cim-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isDisabled={!!isDisabled}\n >\n {iconStart}\n <span className=\"cim-button-text\">{children}</span>\n {iconEnd}\n </RACLink>\n );\n}\n\n/**\n * Displays a labelled button that allows users to navigate to another page or resource.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _LinkButton = withStyleProps(forwardRef(LinkButton), 'LinkButton');\n\nexport { _LinkButton as LinkButton };\n"]}
@@ -1,5 +1,16 @@
1
1
  import type { ActionButtonProps, BaseButtonProps, TextButtonProps } from './types.js';
2
- export interface ButtonProps extends BaseButtonProps, TextButtonProps, ActionButtonProps {
2
+ export interface ButtonProps extends BaseButtonProps, TextButtonProps, Omit<ActionButtonProps, 'isDisabled'> {
3
+ /**
4
+ * Whether the button is disabled.
5
+ *
6
+ * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.
7
+ * This information will be shown to end-users as a tooltip or a popover.
8
+ *
9
+ * @default false
10
+ */
11
+ isDisabled?: boolean | {
12
+ reason: string;
13
+ };
3
14
  }
4
15
  /**
5
16
  * Displays a labelled button that allows users to perform an action.
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/button.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEtF,MAAM,WAAW,WAAY,SAAQ,eAAe,EAAE,eAAe,EAAE,iBAAiB;CAAG;AAmD3F;;;;GAIG;AACH,QAAA,MAAM,OAAO,gKAA+C,CAAC;AAE7D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/button.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAEtF,MAAM,WAAW,WAAY,SAAQ,eAAe,EAAE,eAAe,EAAE,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC;IAC1G;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAyDD;;;;GAIG;AACH,QAAA,MAAM,OAAO,gKAA+C,CAAC;AAE7D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC"}
@@ -7,13 +7,17 @@ import { useProductionWarning } from '../../utils/use-production-warning.js';
7
7
  import { withStyleProps } from '../../with-style-props.js';
8
8
  import { InternalSpinner } from '../internal/spinner/spinner.js';
9
9
  import { SPINNER_SIZES } from './constants.js';
10
- function Button({ children, variant = 'secondary', tone = 'base', size = 'medium', iconStart, iconEnd, isLoading, loadingLabel, isDisabled, fullWidth, UNSAFE_className, UNSAFE_style, ...props }, ref) {
10
+ import { DisabledWithReason, useDisableInteractions } from './disabled-with-reason.js';
11
+ function Button({ children, variant = 'secondary', tone = 'base', size = 'medium', iconStart, iconEnd, isLoading, loadingLabel, isDisabled, fullWidth, UNSAFE_className, UNSAFE_style, slot, ...props }, ref) {
11
12
  useProductionWarning(() => {
12
13
  if (isLoading && !loadingLabel) {
13
14
  console.warn('Button requires loadingLabel when isLoading is true for accessibility');
14
15
  }
15
16
  }, [isLoading, loadingLabel]);
16
- return (_jsx(RACButton, { ...props, ref: ref, className: clsx('cim-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isDisabled: isDisabled, isPending: isLoading, children: ({ isPending }) => (_jsxs(_Fragment, { children: [iconStart, _jsx("span", { className: "cim-button-text", children: children }), iconEnd, isPending && _jsx(InternalSpinner, { size: SPINNER_SIZES[size], "aria-label": loadingLabel })] })) }));
17
+ const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';
18
+ props = useDisableInteractions(props, isDisabled ?? false);
19
+ const button = (_jsx(RACButton, { ...props, ref: ref, slot: slot, className: clsx('cim-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isPending: isLoading, children: ({ isPending }) => (_jsxs(_Fragment, { children: [iconStart, _jsx("span", { className: "cim-button-text", children: children }), iconEnd, isPending && _jsx(InternalSpinner, { size: SPINNER_SIZES[size], "aria-label": loadingLabel })] })) }));
20
+ return hasDisabledReason ? _jsx(DisabledWithReason, { reason: isDisabled.reason, children: button }) : button;
17
21
  }
18
22
  /**
19
23
  * Displays a labelled button that allows users to perform an action.
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../src/components/button/button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAK/C,SAAS,MAAM,CACb,EACE,QAAQ,EACR,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,OAAO,EACP,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,GAAG,KAAK,EACI,EACd,GAAoC;IAEpC,oBAAoB,CAAC,GAAG,EAAE;QACxB,IAAI,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IAE9B,OAAO,CACL,KAAC,SAAS,OACJ,KAAK,EACT,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,gBAAgB,CAAC,EAC/C,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,YAEnB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAClB,8BACG,SAAS,EACV,eAAM,SAAS,EAAC,iBAAiB,YAAE,QAAQ,GAAQ,EAClD,OAAO,EACP,SAAS,IAAI,KAAC,eAAe,IAAC,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,gBAAc,YAAY,GAAI,IACrF,CACJ,GACS,CACb,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;AAE7D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Button as RACButton } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { useProductionWarning } from '../../utils/use-production-warning.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport { InternalSpinner } from '../internal/spinner/spinner.js';\nimport { SPINNER_SIZES } from './constants.js';\nimport type { ActionButtonProps, BaseButtonProps, TextButtonProps } from './types.js';\n\nexport interface ButtonProps extends BaseButtonProps, TextButtonProps, ActionButtonProps {}\n\nfunction Button(\n {\n children,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n iconStart,\n iconEnd,\n isLoading,\n loadingLabel,\n isDisabled,\n fullWidth,\n UNSAFE_className,\n UNSAFE_style,\n ...props\n }: ButtonProps,\n ref: ForwardedRef<HTMLButtonElement>,\n) {\n useProductionWarning(() => {\n if (isLoading && !loadingLabel) {\n console.warn('Button requires loadingLabel when isLoading is true for accessibility');\n }\n }, [isLoading, loadingLabel]);\n\n return (\n <RACButton\n {...props}\n ref={ref}\n className={clsx('cim-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isDisabled={isDisabled}\n isPending={isLoading}\n >\n {({ isPending }) => (\n <>\n {iconStart}\n <span className=\"cim-button-text\">{children}</span>\n {iconEnd}\n {isPending && <InternalSpinner size={SPINNER_SIZES[size]} aria-label={loadingLabel} />}\n </>\n )}\n </RACButton>\n );\n}\n\n/**\n * Displays a labelled button that allows users to perform an action.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _Button = withStyleProps(forwardRef(Button), 'Button');\n\nexport { _Button as Button };\n"]}
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../src/components/button/button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAevF,SAAS,MAAM,CACb,EACE,QAAQ,EACR,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,OAAO,EACP,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,IAAI,EACJ,GAAG,KAAK,EACI,EACd,GAAoC;IAEpC,oBAAoB,CAAC,GAAG,EAAE;QACxB,IAAI,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,uEAAuE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IAE9B,MAAM,iBAAiB,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE,CAAC;IACrF,KAAK,GAAG,sBAAsB,CAAC,KAAK,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC;IAE3D,MAAM,MAAM,GAAG,CACb,KAAC,SAAS,OACJ,KAAK,EACT,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,gBAAgB,CAAC,EAC/C,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,SAAS,EAAE,SAAS,YAEnB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAClB,8BACG,SAAS,EACV,eAAM,SAAS,EAAC,iBAAiB,YAAE,QAAQ,GAAQ,EAClD,OAAO,EACP,SAAS,IAAI,KAAC,eAAe,IAAC,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,gBAAc,YAAY,GAAI,IACrF,CACJ,GACS,CACb,CAAC;IAEF,OAAO,iBAAiB,CAAC,CAAC,CAAC,KAAC,kBAAkB,IAAC,MAAM,EAAE,UAAU,CAAC,MAAM,YAAG,MAAM,GAAsB,CAAC,CAAC,CAAC,MAAM,CAAC;AACnH,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC;AAE7D,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,CAAC","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Button as RACButton } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { useProductionWarning } from '../../utils/use-production-warning.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport { InternalSpinner } from '../internal/spinner/spinner.js';\nimport { SPINNER_SIZES } from './constants.js';\nimport { DisabledWithReason, useDisableInteractions } from './disabled-with-reason.js';\nimport type { ActionButtonProps, BaseButtonProps, TextButtonProps } from './types.js';\n\nexport interface ButtonProps extends BaseButtonProps, TextButtonProps, Omit<ActionButtonProps, 'isDisabled'> {\n /**\n * Whether the button is disabled.\n *\n * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.\n * This information will be shown to end-users as a tooltip or a popover.\n *\n * @default false\n */\n isDisabled?: boolean | { reason: string };\n}\n\nfunction Button(\n {\n children,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n iconStart,\n iconEnd,\n isLoading,\n loadingLabel,\n isDisabled,\n fullWidth,\n UNSAFE_className,\n UNSAFE_style,\n slot,\n ...props\n }: ButtonProps,\n ref: ForwardedRef<HTMLButtonElement>,\n) {\n useProductionWarning(() => {\n if (isLoading && !loadingLabel) {\n console.warn('Button requires loadingLabel when isLoading is true for accessibility');\n }\n }, [isLoading, loadingLabel]);\n\n const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';\n props = useDisableInteractions(props, isDisabled ?? false);\n\n const button = (\n <RACButton\n {...props}\n ref={ref}\n slot={slot}\n className={clsx('cim-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isPending={isLoading}\n >\n {({ isPending }) => (\n <>\n {iconStart}\n <span className=\"cim-button-text\">{children}</span>\n {iconEnd}\n {isPending && <InternalSpinner size={SPINNER_SIZES[size]} aria-label={loadingLabel} />}\n </>\n )}\n </RACButton>\n );\n\n return hasDisabledReason ? <DisabledWithReason reason={isDisabled.reason}>{button}</DisabledWithReason> : button;\n}\n\n/**\n * Displays a labelled button that allows users to perform an action.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _Button = withStyleProps(forwardRef(Button), 'Button');\n\nexport { _Button as Button };\n"]}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=disabled-with-reason.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disabled-with-reason.d.ts","sourceRoot":"","sources":["../../../../src/components/button/disabled-with-reason.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,39 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useMediaQuery } from '../../utils/use-media-query.js';
3
+ import { Popover, PopoverRoot } from '../popover/popover.js';
4
+ import { Tooltip } from '../tooltip/tooltip.js';
5
+ /** @internal */
6
+ export function DisabledWithReason({ children, reason }) {
7
+ const hasHover = useMediaQuery('(hover: hover)', { defaultValue: true, initializeWithValue: true });
8
+ if (hasHover) {
9
+ return _jsx(Tooltip, { label: reason, children: children });
10
+ }
11
+ else {
12
+ return (_jsxs(PopoverRoot, { children: [children, _jsx(Popover, { children: reason })] }));
13
+ }
14
+ }
15
+ // Events to preserve when `isDisabled` is true (for tooltips and other overlays)
16
+ const PRESERVED_EVENT_PATTERN = /Focus|Blur|Hover|Pointer(Enter|Leave|Over|Out)|Mouse(Enter|Leave|Over|Out)/;
17
+ /** @internal */
18
+ // eslint-disable-next-line react-refresh/only-export-components
19
+ export function useDisableInteractions(props, isDisabled) {
20
+ if (isDisabled !== false) {
21
+ for (const key in props) {
22
+ if (key.startsWith('on') && !PRESERVED_EVENT_PATTERN.test(key)) {
23
+ delete props[key];
24
+ }
25
+ }
26
+ }
27
+ if (typeof isDisabled === 'object' && isDisabled.reason) {
28
+ // Use `aria-disabled` instead of `disabled`
29
+ props['aria-disabled'] = true;
30
+ // Prevent form submission
31
+ props.type = props.type === 'submit' ? 'button' : props.type;
32
+ }
33
+ else if (isDisabled !== false) {
34
+ // Make the button actually disabled
35
+ props.isDisabled = true;
36
+ }
37
+ return props;
38
+ }
39
+ //# sourceMappingURL=disabled-with-reason.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"disabled-with-reason.js","sourceRoot":"","sources":["../../../../src/components/button/disabled-with-reason.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAEhD,gBAAgB;AAChB,MAAM,UAAU,kBAAkB,CAAC,EAAE,QAAQ,EAAE,MAAM,EAA2C;IAC9F,MAAM,QAAQ,GAAG,aAAa,CAAC,gBAAgB,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAC;IAEpG,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,KAAC,OAAO,IAAC,KAAK,EAAE,MAAM,YAAG,QAAQ,GAAW,CAAC;IACtD,CAAC;SAAM,CAAC;QACN,OAAO,CACL,MAAC,WAAW,eACT,QAAQ,EAET,KAAC,OAAO,cAAE,MAAM,GAAW,IACf,CACf,CAAC;IACJ,CAAC;AACH,CAAC;AAED,iFAAiF;AACjF,MAAM,uBAAuB,GAAG,4EAA4E,CAAC;AAE7G,gBAAgB;AAChB,gEAAgE;AAChE,MAAM,UAAU,sBAAsB,CACpC,KAAQ,EACR,UAAwC;IAExC,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QACzB,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/D,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC;YACpB,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;QACxD,4CAA4C;QAC5C,KAAK,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC;QAC9B,0BAA0B;QAC1B,KAAK,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;IAC/D,CAAC;SAAM,IAAI,UAAU,KAAK,KAAK,EAAE,CAAC;QAChC,oCAAoC;QACpC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import type { HTMLAttributes, ReactNode } from 'react';\nimport type { ButtonProps as RACButtonProps } from 'react-aria-components';\nimport { useMediaQuery } from '../../utils/use-media-query.js';\nimport { Popover, PopoverRoot } from '../popover/popover.js';\nimport { Tooltip } from '../tooltip/tooltip.js';\n\n/** @internal */\nexport function DisabledWithReason({ children, reason }: { children: ReactNode; reason: string }) {\n const hasHover = useMediaQuery('(hover: hover)', { defaultValue: true, initializeWithValue: true });\n\n if (hasHover) {\n return <Tooltip label={reason}>{children}</Tooltip>;\n } else {\n return (\n <PopoverRoot>\n {children}\n {/* TODO: add aria-label */}\n <Popover>{reason}</Popover>\n </PopoverRoot>\n );\n }\n}\n\n// Events to preserve when `isDisabled` is true (for tooltips and other overlays)\nconst PRESERVED_EVENT_PATTERN = /Focus|Blur|Hover|Pointer(Enter|Leave|Over|Out)|Mouse(Enter|Leave|Over|Out)/;\n\n/** @internal */\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useDisableInteractions<T extends Partial<RACButtonProps & HTMLAttributes<HTMLButtonElement>>>(\n props: T,\n isDisabled: boolean | { reason: string },\n): T {\n if (isDisabled !== false) {\n for (const key in props) {\n if (key.startsWith('on') && !PRESERVED_EVENT_PATTERN.test(key)) {\n delete props[key];\n }\n }\n }\n\n if (typeof isDisabled === 'object' && isDisabled.reason) {\n // Use `aria-disabled` instead of `disabled`\n props['aria-disabled'] = true;\n // Prevent form submission\n props.type = props.type === 'submit' ? 'button' : props.type;\n } else if (isDisabled !== false) {\n // Make the button actually disabled\n props.isDisabled = true;\n }\n\n return props;\n}\n"]}
@@ -1,5 +1,16 @@
1
1
  import type { ActionButtonProps, BaseButtonProps, SingleIconButtonProps } from './types.js';
2
- export interface IconButtonProps extends BaseButtonProps, SingleIconButtonProps, ActionButtonProps {
2
+ export interface IconButtonProps extends BaseButtonProps, SingleIconButtonProps, Omit<ActionButtonProps, 'isDisabled'> {
3
+ /**
4
+ * Whether the button is disabled.
5
+ *
6
+ * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.
7
+ * This information will be shown to the end-users as a tooltip or a popover.
8
+ *
9
+ * @default false
10
+ */
11
+ isDisabled?: boolean | {
12
+ reason: string;
13
+ };
3
14
  }
4
15
  /**
5
16
  * Displays an icon-only button that allows users to perform an action.
@@ -1 +1 @@
1
- {"version":3,"file":"icon-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/icon-button.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE5F,MAAM,WAAW,eAAgB,SAAQ,eAAe,EAAE,qBAAqB,EAAE,iBAAiB;CAAG;AA+CrG;;;;GAIG;AACH,QAAA,MAAM,WAAW,oKAAuD,CAAC;AAEzE,OAAO,EAAE,WAAW,IAAI,UAAU,EAAE,CAAC"}
1
+ {"version":3,"file":"icon-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/icon-button.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE5F,MAAM,WAAW,eAAgB,SAAQ,eAAe,EAAE,qBAAqB,EAAE,IAAI,CAAC,iBAAiB,EAAE,YAAY,CAAC;IACpH;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAqDD;;;;GAIG;AACH,QAAA,MAAM,WAAW,oKAAuD,CAAC;AAEzE,OAAO,EAAE,WAAW,IAAI,UAAU,EAAE,CAAC"}
@@ -7,13 +7,17 @@ import { useProductionWarning } from '../../utils/use-production-warning.js';
7
7
  import { withStyleProps } from '../../with-style-props.js';
8
8
  import { InternalSpinner } from '../internal/spinner/spinner.js';
9
9
  import { SPINNER_SIZES } from './constants.js';
10
- function IconButton({ icon, variant = 'secondary', tone = 'base', size = 'medium', isLoading, loadingLabel, isDisabled, fullWidth, UNSAFE_className, UNSAFE_style, ...props }, ref) {
10
+ import { DisabledWithReason, useDisableInteractions } from './disabled-with-reason.js';
11
+ function IconButton({ icon, variant = 'secondary', tone = 'base', size = 'medium', isLoading, loadingLabel, isDisabled, fullWidth, UNSAFE_className, UNSAFE_style, slot, ...props }, ref) {
11
12
  useProductionWarning(() => {
12
13
  if (isLoading && !loadingLabel) {
13
14
  console.warn('IconButton requires loadingLabel when isLoading is true for accessibility');
14
15
  }
15
16
  }, [isLoading, loadingLabel]);
16
- return (_jsx(RACButton, { ...props, ref: ref, className: clsx('cim-icon-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isDisabled: isDisabled, isPending: isLoading, children: ({ isPending }) => (_jsxs(_Fragment, { children: [icon, isPending && _jsx(InternalSpinner, { size: SPINNER_SIZES[size], "aria-label": loadingLabel })] })) }));
17
+ const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';
18
+ props = useDisableInteractions(props, isDisabled ?? false);
19
+ const button = (_jsx(RACButton, { ...props, ref: ref, slot: slot, className: clsx('cim-icon-button', UNSAFE_className), style: UNSAFE_style, "data-variant": variant, "data-tone": tone, "data-size": size, "data-full-width": fullWidth || undefined, isPending: isLoading, children: ({ isPending }) => (_jsxs(_Fragment, { children: [icon, isPending && _jsx(InternalSpinner, { size: SPINNER_SIZES[size], "aria-label": loadingLabel })] })) }));
20
+ return hasDisabledReason ? _jsx(DisabledWithReason, { reason: isDisabled.reason, children: button }) : button;
17
21
  }
18
22
  /**
19
23
  * Displays an icon-only button that allows users to perform an action.
@@ -1 +1 @@
1
- {"version":3,"file":"icon-button.js","sourceRoot":"","sources":["../../../../src/components/button/icon-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAK/C,SAAS,UAAU,CACjB,EACE,IAAI,EACJ,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,GAAG,KAAK,EACQ,EAClB,GAAoC;IAEpC,oBAAoB,CAAC,GAAG,EAAE;QACxB,IAAI,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IAE9B,OAAO,CACL,KAAC,SAAS,OACJ,KAAK,EACT,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,EACpD,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,YAEnB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAClB,8BACG,IAAI,EACJ,SAAS,IAAI,KAAC,eAAe,IAAC,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,gBAAc,YAAY,GAAI,IACrF,CACJ,GACS,CACb,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;AAEzE,OAAO,EAAE,WAAW,IAAI,UAAU,EAAE,CAAC","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Button as RACButton } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { useProductionWarning } from '../../utils/use-production-warning.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport { InternalSpinner } from '../internal/spinner/spinner.js';\nimport { SPINNER_SIZES } from './constants.js';\nimport type { ActionButtonProps, BaseButtonProps, SingleIconButtonProps } from './types.js';\n\nexport interface IconButtonProps extends BaseButtonProps, SingleIconButtonProps, ActionButtonProps {}\n\nfunction IconButton(\n {\n icon,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n isLoading,\n loadingLabel,\n isDisabled,\n fullWidth,\n UNSAFE_className,\n UNSAFE_style,\n ...props\n }: IconButtonProps,\n ref: ForwardedRef<HTMLButtonElement>,\n) {\n useProductionWarning(() => {\n if (isLoading && !loadingLabel) {\n console.warn('IconButton requires loadingLabel when isLoading is true for accessibility');\n }\n }, [isLoading, loadingLabel]);\n\n return (\n <RACButton\n {...props}\n ref={ref}\n className={clsx('cim-icon-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isDisabled={isDisabled}\n isPending={isLoading}\n >\n {({ isPending }) => (\n <>\n {icon}\n {isPending && <InternalSpinner size={SPINNER_SIZES[size]} aria-label={loadingLabel} />}\n </>\n )}\n </RACButton>\n );\n}\n\n/**\n * Displays an icon-only button that allows users to perform an action.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _IconButton = withStyleProps(forwardRef(IconButton), 'IconButton');\n\nexport { _IconButton as IconButton };\n"]}
1
+ {"version":3,"file":"icon-button.js","sourceRoot":"","sources":["../../../../src/components/button/icon-button.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AACjE,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAevF,SAAS,UAAU,CACjB,EACE,IAAI,EACJ,OAAO,GAAG,WAAW,EACrB,IAAI,GAAG,MAAM,EACb,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,IAAI,EACJ,GAAG,KAAK,EACQ,EAClB,GAAoC;IAEpC,oBAAoB,CAAC,GAAG,EAAE;QACxB,IAAI,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,2EAA2E,CAAC,CAAC;QAC5F,CAAC;IACH,CAAC,EAAE,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC;IAE9B,MAAM,iBAAiB,GAAG,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,KAAK,EAAE,CAAC;IACrF,KAAK,GAAG,sBAAsB,CAAC,KAAK,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC;IAE3D,MAAM,MAAM,GAAG,CACb,KAAC,SAAS,OACJ,KAAK,EACT,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE,gBAAgB,CAAC,EACpD,KAAK,EAAE,YAAY,kBACL,OAAO,eACV,IAAI,eACJ,IAAI,qBACE,SAAS,IAAI,SAAS,EACvC,SAAS,EAAE,SAAS,YAEnB,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAClB,8BACG,IAAI,EACJ,SAAS,IAAI,KAAC,eAAe,IAAC,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,gBAAc,YAAY,GAAI,IACrF,CACJ,GACS,CACb,CAAC;IAEF,OAAO,iBAAiB,CAAC,CAAC,CAAC,KAAC,kBAAkB,IAAC,MAAM,EAAE,UAAU,CAAC,MAAM,YAAG,MAAM,GAAsB,CAAC,CAAC,CAAC,MAAM,CAAC;AACnH,CAAC;AAED;;;;GAIG;AACH,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;AAEzE,OAAO,EAAE,WAAW,IAAI,UAAU,EAAE,CAAC","sourcesContent":["'use client';\n\nimport clsx from 'clsx';\nimport type { ForwardedRef } from 'react';\nimport { Button as RACButton } from 'react-aria-components';\nimport { forwardRef } from '../../forward-ref.js';\nimport { useProductionWarning } from '../../utils/use-production-warning.js';\nimport { withStyleProps } from '../../with-style-props.js';\nimport { InternalSpinner } from '../internal/spinner/spinner.js';\nimport { SPINNER_SIZES } from './constants.js';\nimport { DisabledWithReason, useDisableInteractions } from './disabled-with-reason.js';\nimport type { ActionButtonProps, BaseButtonProps, SingleIconButtonProps } from './types.js';\n\nexport interface IconButtonProps extends BaseButtonProps, SingleIconButtonProps, Omit<ActionButtonProps, 'isDisabled'> {\n /**\n * Whether the button is disabled.\n *\n * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.\n * This information will be shown to the end-users as a tooltip or a popover.\n *\n * @default false\n */\n isDisabled?: boolean | { reason: string };\n}\n\nfunction IconButton(\n {\n icon,\n variant = 'secondary',\n tone = 'base',\n size = 'medium',\n isLoading,\n loadingLabel,\n isDisabled,\n fullWidth,\n UNSAFE_className,\n UNSAFE_style,\n slot,\n ...props\n }: IconButtonProps,\n ref: ForwardedRef<HTMLButtonElement>,\n) {\n useProductionWarning(() => {\n if (isLoading && !loadingLabel) {\n console.warn('IconButton requires loadingLabel when isLoading is true for accessibility');\n }\n }, [isLoading, loadingLabel]);\n\n const hasDisabledReason = typeof isDisabled === 'object' && isDisabled.reason !== '';\n props = useDisableInteractions(props, isDisabled ?? false);\n\n const button = (\n <RACButton\n {...props}\n ref={ref}\n slot={slot}\n className={clsx('cim-icon-button', UNSAFE_className)}\n style={UNSAFE_style}\n data-variant={variant}\n data-tone={tone}\n data-size={size}\n data-full-width={fullWidth || undefined}\n isPending={isLoading}\n >\n {({ isPending }) => (\n <>\n {icon}\n {isPending && <InternalSpinner size={SPINNER_SIZES[size]} aria-label={loadingLabel} />}\n </>\n )}\n </RACButton>\n );\n\n return hasDisabledReason ? <DisabledWithReason reason={isDisabled.reason}>{button}</DisabledWithReason> : button;\n}\n\n/**\n * Displays an icon-only button that allows users to perform an action.\n *\n * See [button usage guidelines](https://ui.cimpress.io/components/button/).\n */\nconst _IconButton = withStyleProps(forwardRef(IconButton), 'IconButton');\n\nexport { _IconButton as IconButton };\n"]}
@@ -1,7 +1,18 @@
1
1
  import { type LinkProps as RACLinkProps } from 'react-aria-components';
2
2
  import type { NavigationProps, WithRequired } from '../types.js';
3
3
  import type { BaseButtonProps, SingleIconButtonProps } from './types.js';
4
- export interface IconLinkButtonProps extends Omit<BaseButtonProps, 'id'>, SingleIconButtonProps, WithRequired<NavigationProps, 'href'>, Pick<RACLinkProps, 'isDisabled' | 'onHoverStart' | 'onHoverEnd'> {
4
+ export interface IconLinkButtonProps extends Omit<BaseButtonProps, 'id'>, SingleIconButtonProps, WithRequired<NavigationProps, 'href'>, Pick<RACLinkProps, 'onHoverStart' | 'onHoverEnd'> {
5
+ /**
6
+ * Whether the button is disabled.
7
+ *
8
+ * Optionally, you can provide an object with the `reason` property explaining why the button is disabled.
9
+ * This information will be shown to the end-users as a tooltip or a popover.
10
+ *
11
+ * @default false
12
+ */
13
+ isDisabled?: boolean | {
14
+ reason: string;
15
+ };
5
16
  }
6
17
  /**
7
18
  * Displays an icon-only button that allows users to navigate to another page or resource.
@@ -1 +1 @@
1
- {"version":3,"file":"icon-link-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/icon-link-button.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,SAAS,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGxF,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,mBACf,SACE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAC3B,qBAAqB,EACrB,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,EACrC,IAAI,CAAC,YAAY,EAAE,YAAY,GAAG,cAAc,GAAG,YAAY,CAAC;CAAG;AAiCvE;;;;GAIG;AACH,QAAA,MAAM,eAAe,wKAA+D,CAAC;AAErF,OAAO,EAAE,eAAe,IAAI,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"icon-link-button.d.ts","sourceRoot":"","sources":["../../../../src/components/button/icon-link-button.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,SAAS,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGxF,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,KAAK,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,mBACf,SACE,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,EAC3B,qBAAqB,EACrB,YAAY,CAAC,eAAe,EAAE,MAAM,CAAC,EACrC,IAAI,CAAC,YAAY,EAAE,cAAc,GAAG,YAAY,CAAC;IACnD;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3C;AAsDD;;;;GAIG;AACH,QAAA,MAAM,eAAe,wKAA+D,CAAC;AAErF,OAAO,EAAE,eAAe,IAAI,cAAc,EAAE,CAAC"}