@pk-design/react-tailwind 1.8.1 → 1.10.0

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 (63) hide show
  1. package/dist/cjs/components/Banner/Banner.js +1 -1
  2. package/dist/cjs/components/Banner/Banner.js.map +1 -1
  3. package/dist/cjs/components/BottomNavigation/BottomNavigation.js +14 -5
  4. package/dist/cjs/components/BottomNavigation/BottomNavigation.js.map +1 -1
  5. package/dist/cjs/components/Button/Button.js +88 -60
  6. package/dist/cjs/components/Button/Button.js.map +1 -1
  7. package/dist/cjs/components/Drawer/Drawer.js +6 -2
  8. package/dist/cjs/components/Drawer/Drawer.js.map +1 -1
  9. package/dist/cjs/components/MobileHeader/MobileHeader.js +21 -3
  10. package/dist/cjs/components/MobileHeader/MobileHeader.js.map +1 -1
  11. package/dist/cjs/components/PullToRefresh/PullToRefresh.js +145 -57
  12. package/dist/cjs/components/PullToRefresh/PullToRefresh.js.map +1 -1
  13. package/dist/cjs/components/SelectBox/SelectBox.js +25 -4
  14. package/dist/cjs/components/SelectBox/SelectBox.js.map +1 -1
  15. package/dist/cjs/components/StickyActionBar/StickyActionBar.js +2 -2
  16. package/dist/cjs/components/StickyActionBar/StickyActionBar.js.map +1 -1
  17. package/dist/cjs/components/Toast/Toast.js +1 -1
  18. package/dist/cjs/components/Toast/Toast.js.map +1 -1
  19. package/dist/cjs/hooks/use-breakpoint.js +48 -0
  20. package/dist/cjs/hooks/use-breakpoint.js.map +1 -0
  21. package/dist/cjs/index.js +5 -0
  22. package/dist/cjs/index.js.map +1 -1
  23. package/dist/es/components/Banner/Banner.js +1 -1
  24. package/dist/es/components/Banner/Banner.js.map +1 -1
  25. package/dist/es/components/BottomNavigation/BottomNavigation.js +14 -5
  26. package/dist/es/components/BottomNavigation/BottomNavigation.js.map +1 -1
  27. package/dist/es/components/Button/Button.js +89 -61
  28. package/dist/es/components/Button/Button.js.map +1 -1
  29. package/dist/es/components/Drawer/Drawer.js +6 -2
  30. package/dist/es/components/Drawer/Drawer.js.map +1 -1
  31. package/dist/es/components/MobileHeader/MobileHeader.js +21 -3
  32. package/dist/es/components/MobileHeader/MobileHeader.js.map +1 -1
  33. package/dist/es/components/PullToRefresh/PullToRefresh.js +146 -58
  34. package/dist/es/components/PullToRefresh/PullToRefresh.js.map +1 -1
  35. package/dist/es/components/SelectBox/SelectBox.js +26 -5
  36. package/dist/es/components/SelectBox/SelectBox.js.map +1 -1
  37. package/dist/es/components/StickyActionBar/StickyActionBar.js +2 -2
  38. package/dist/es/components/StickyActionBar/StickyActionBar.js.map +1 -1
  39. package/dist/es/components/Toast/Toast.js +1 -1
  40. package/dist/es/components/Toast/Toast.js.map +1 -1
  41. package/dist/es/hooks/use-breakpoint.js +43 -0
  42. package/dist/es/hooks/use-breakpoint.js.map +1 -0
  43. package/dist/es/index.js +1 -0
  44. package/dist/es/index.js.map +1 -1
  45. package/dist/react-tailwind.cjs.js +344 -135
  46. package/dist/react-tailwind.cjs.js.map +1 -1
  47. package/dist/react-tailwind.es.js +342 -137
  48. package/dist/react-tailwind.es.js.map +1 -1
  49. package/dist/types/components/BottomNavigation/BottomNavigation.d.ts +1 -1
  50. package/dist/types/components/BottomNavigation/BottomNavigation.types.d.ts +28 -3
  51. package/dist/types/components/Button/Button.types.d.ts +12 -6
  52. package/dist/types/components/Drawer/Drawer.types.d.ts +8 -4
  53. package/dist/types/components/MobileHeader/MobileHeader.d.ts +1 -1
  54. package/dist/types/components/MobileHeader/MobileHeader.types.d.ts +13 -0
  55. package/dist/types/components/PullToRefresh/PullToRefresh.d.ts +1 -1
  56. package/dist/types/components/PullToRefresh/PullToRefresh.types.d.ts +45 -6
  57. package/dist/types/components/SelectBox/SelectBox.types.d.ts +18 -1
  58. package/dist/types/components/StickyActionBar/StickyActionBar.types.d.ts +12 -0
  59. package/dist/types/hooks/use-breakpoint.d.ts +27 -0
  60. package/dist/types/hooks/use-breakpoint.test.d.ts +1 -0
  61. package/dist/types/index.d.ts +1 -0
  62. package/dist/types/test-utils/mock-viewport.d.ts +7 -0
  63. package/package.json +1 -1
@@ -33,7 +33,7 @@ const Banner = React.forwardRef((props, ref) => {
33
33
  const { type = 'info', iconSize = 'sm', children, icon, removable = false, onRemove, className, ...restProps } = props;
34
34
  const DefaultIcon = IconMap[type];
35
35
  const iconNode = icon !== undefined ? (icon) : (jsxRuntime.jsx(DefaultIcon, { "data-testid": `banner-${type}-icon`, className: buildClassname.buildClassName('shrink-0', sizeMap[iconSize]) }));
36
- return (jsxRuntime.jsxs("div", { ref: ref, className: buildClassname.buildClassName('text-sm rounded-md flex w-full p-3 items-center gap-3 ring-1 ring-inset', TypeClassMap[type], className), "data-testid": `banner-${type}`, ...restProps, children: [iconNode, jsxRuntime.jsx("div", { className: "flex items-center w-full justify-between", children: children }), removable && (jsxRuntime.jsx(Button.Button, { iconOnly: true, "aria-label": "Dismiss banner", size: "xs", variant: "plain", theme: "secondary", className: "hover:bg-black/10 dark:hover:bg-white/10 shrink-0", onClick: () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(), "data-testid": "banner-remove-btn", children: jsxRuntime.jsx(X.default, { className: "size-4.5", "data-testid": "banner-remove-icon" }) }))] }));
36
+ return (jsxRuntime.jsxs("div", { ref: ref, className: buildClassname.buildClassName('text-sm rounded-md flex w-full p-3 items-center gap-3 ring-1 ring-inset', TypeClassMap[type], className), "data-testid": `banner-${type}`, ...restProps, children: [iconNode, jsxRuntime.jsx("div", { className: "flex items-center w-full justify-between", children: children }), removable && (jsxRuntime.jsx(Button.Button, { iconOnly: true, "aria-label": "Dismiss banner", size: "xs", variant: "plain", className: "text-current focus-visible:outline-current shrink-0", onClick: () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(), "data-testid": "banner-remove-btn", children: jsxRuntime.jsx(X.default, { className: "size-4.5", "data-testid": "banner-remove-icon" }) }))] }));
37
37
  });
38
38
  Banner.displayName = 'Banner';
39
39
 
@@ -1 +1 @@
1
- {"version":3,"file":"Banner.js","sources":["../../../../../src/components/Banner/Banner.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport TriangleAlertIcon from '../Icons/TriangleAlert.svg'\nimport CircleXIcon from '../Icons/CircleX.svg'\nimport CircleCheckIcon from '../Icons/CircleCheck.svg'\nimport InfoIcon from '../Icons/Info.svg'\nimport XIcon from '../Icons/X.svg'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Button } from '../Button'\nimport { BannerProps } from './Banner.types'\n\nconst sizeMap = {\n xs: 'size-4',\n sm: 'size-5',\n md: 'size-6',\n lg: 'size-8',\n xl: 'size-10',\n}\n\nconst IconMap = {\n info: InfoIcon,\n error: CircleXIcon,\n success: CircleCheckIcon,\n warning: TriangleAlertIcon,\n}\n\nconst TypeClassMap = {\n info: 'bg-[var(--ui-info-light)] ring-[var(--ui-info-ring-subtle)] text-[var(--ui-info-text)]',\n error:\n 'bg-[var(--ui-danger-light)] ring-[var(--ui-danger-ring-subtle)] text-[var(--ui-danger-text)]',\n success:\n 'bg-[var(--ui-success-light)] ring-[var(--ui-success-ring-subtle)] text-[var(--ui-success-text)]',\n warning:\n 'bg-[var(--ui-warning-light)] ring-[var(--ui-warning-ring-subtle)] text-[var(--ui-warning-text)]',\n}\n\nexport const Banner = forwardRef<HTMLDivElement, BannerProps>((props, ref) => {\n const {\n type = 'info',\n iconSize = 'sm',\n children,\n icon,\n removable = false,\n onRemove,\n className,\n ...restProps\n } = props\n\n const DefaultIcon = IconMap[type]\n const iconNode =\n icon !== undefined ? (\n icon\n ) : (\n <DefaultIcon\n data-testid={`banner-${type}-icon`}\n className={buildClassName('shrink-0', sizeMap[iconSize])}\n />\n )\n\n return (\n <div\n ref={ref}\n className={buildClassName(\n 'text-sm rounded-md flex w-full p-3 items-center gap-3 ring-1 ring-inset',\n TypeClassMap[type],\n className,\n )}\n data-testid={`banner-${type}`}\n {...restProps}\n >\n {iconNode}\n <div className=\"flex items-center w-full justify-between\">{children}</div>\n {removable && (\n <Button\n iconOnly\n aria-label=\"Dismiss banner\"\n size=\"xs\"\n variant=\"plain\"\n theme=\"secondary\"\n className=\"hover:bg-black/10 dark:hover:bg-white/10 shrink-0\"\n onClick={() => onRemove?.()}\n data-testid=\"banner-remove-btn\"\n >\n <XIcon className=\"size-4.5\" data-testid=\"banner-remove-icon\" />\n </Button>\n )}\n </div>\n )\n})\n\nBanner.displayName = 'Banner'\n"],"names":["InfoIcon","CircleXIcon","CircleCheckIcon","TriangleAlertIcon","forwardRef","_jsx","buildClassName","_jsxs","Button","XIcon"],"mappings":";;;;;;;;;;;;AAUA,MAAM,OAAO,GAAG;AACd,IAAA,EAAE,EAAE,QAAQ;AACZ,IAAA,EAAE,EAAE,QAAQ;AACZ,IAAA,EAAE,EAAE,QAAQ;AACZ,IAAA,EAAE,EAAE,QAAQ;AACZ,IAAA,EAAE,EAAE,SAAS;CACd;AAED,MAAM,OAAO,GAAG;AACd,IAAA,IAAI,EAAEA,YAAQ;AACd,IAAA,KAAK,EAAEC,eAAW;AAClB,IAAA,OAAO,EAAEC,mBAAe;AACxB,IAAA,OAAO,EAAEC,qBAAiB;CAC3B;AAED,MAAM,YAAY,GAAG;AACnB,IAAA,IAAI,EAAE,wFAAwF;AAC9F,IAAA,KAAK,EACH,8FAA8F;AAChG,IAAA,OAAO,EACL,iGAAiG;AACnG,IAAA,OAAO,EACL,iGAAiG;CACpG;AAEM,MAAM,MAAM,GAAGC,gBAAU,CAA8B,CAAC,KAAK,EAAE,GAAG,KAAI;IAC3E,MAAM,EACJ,IAAI,GAAG,MAAM,EACb,QAAQ,GAAG,IAAI,EACf,QAAQ,EACR,IAAI,EACJ,SAAS,GAAG,KAAK,EACjB,QAAQ,EACR,SAAS,EACT,GAAG,SAAS,EACb,GAAG,KAAK;AAET,IAAA,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;AACjC,IAAA,MAAM,QAAQ,GACZ,IAAI,KAAK,SAAS,IAChB,IAAI,KAEJC,cAAA,CAAC,WAAW,EAAA,EAAA,aAAA,EACG,CAAA,OAAA,EAAU,IAAI,CAAA,KAAA,CAAO,EAClC,SAAS,EAAEC,6BAAc,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAA,CACxD,CACH;AAEH,IAAA,QACEC,eAAA,CAAA,KAAA,EAAA,EACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAED,6BAAc,CACvB,yEAAyE,EACzE,YAAY,CAAC,IAAI,CAAC,EAClB,SAAS,CACV,EAAA,aAAA,EACY,CAAA,OAAA,EAAU,IAAI,CAAA,CAAE,KACzB,SAAS,EAAA,QAAA,EAAA,CAEZ,QAAQ,EACTD,cAAA,CAAA,KAAA,EAAA,EAAK,SAAS,EAAC,0CAA0C,YAAE,QAAQ,EAAA,CAAO,EACzE,SAAS,KACRA,cAAA,CAACG,aAAM,IACL,QAAQ,EAAA,IAAA,EAAA,YAAA,EACG,gBAAgB,EAC3B,IAAI,EAAC,IAAI,EACT,OAAO,EAAC,OAAO,EACf,KAAK,EAAC,WAAW,EACjB,SAAS,EAAC,mDAAmD,EAC7D,OAAO,EAAE,MAAM,QAAQ,KAAA,IAAA,IAAR,QAAQ,uBAAR,QAAQ,EAAI,iBACf,mBAAmB,EAAA,QAAA,EAE/BH,eAACI,SAAK,EAAA,EAAC,SAAS,EAAC,UAAU,iBAAa,oBAAoB,EAAA,CAAG,GACxD,CACV,CAAA,EAAA,CACG;AAEV,CAAC;AAED,MAAM,CAAC,WAAW,GAAG,QAAQ;;;;"}
1
+ {"version":3,"file":"Banner.js","sources":["../../../../../src/components/Banner/Banner.tsx"],"sourcesContent":["import React, { forwardRef } from 'react'\nimport TriangleAlertIcon from '../Icons/TriangleAlert.svg'\nimport CircleXIcon from '../Icons/CircleX.svg'\nimport CircleCheckIcon from '../Icons/CircleCheck.svg'\nimport InfoIcon from '../Icons/Info.svg'\nimport XIcon from '../Icons/X.svg'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Button } from '../Button'\nimport { BannerProps } from './Banner.types'\n\nconst sizeMap = {\n xs: 'size-4',\n sm: 'size-5',\n md: 'size-6',\n lg: 'size-8',\n xl: 'size-10',\n}\n\nconst IconMap = {\n info: InfoIcon,\n error: CircleXIcon,\n success: CircleCheckIcon,\n warning: TriangleAlertIcon,\n}\n\nconst TypeClassMap = {\n info: 'bg-[var(--ui-info-light)] ring-[var(--ui-info-ring-subtle)] text-[var(--ui-info-text)]',\n error:\n 'bg-[var(--ui-danger-light)] ring-[var(--ui-danger-ring-subtle)] text-[var(--ui-danger-text)]',\n success:\n 'bg-[var(--ui-success-light)] ring-[var(--ui-success-ring-subtle)] text-[var(--ui-success-text)]',\n warning:\n 'bg-[var(--ui-warning-light)] ring-[var(--ui-warning-ring-subtle)] text-[var(--ui-warning-text)]',\n}\n\nexport const Banner = forwardRef<HTMLDivElement, BannerProps>((props, ref) => {\n const {\n type = 'info',\n iconSize = 'sm',\n children,\n icon,\n removable = false,\n onRemove,\n className,\n ...restProps\n } = props\n\n const DefaultIcon = IconMap[type]\n const iconNode =\n icon !== undefined ? (\n icon\n ) : (\n <DefaultIcon\n data-testid={`banner-${type}-icon`}\n className={buildClassName('shrink-0', sizeMap[iconSize])}\n />\n )\n\n return (\n <div\n ref={ref}\n className={buildClassName(\n 'text-sm rounded-md flex w-full p-3 items-center gap-3 ring-1 ring-inset',\n TypeClassMap[type],\n className,\n )}\n data-testid={`banner-${type}`}\n {...restProps}\n >\n {iconNode}\n <div className=\"flex items-center w-full justify-between\">{children}</div>\n {removable && (\n <Button\n iconOnly\n aria-label=\"Dismiss banner\"\n size=\"xs\"\n variant=\"plain\"\n className=\"text-current focus-visible:outline-current shrink-0\"\n onClick={() => onRemove?.()}\n data-testid=\"banner-remove-btn\"\n >\n <XIcon className=\"size-4.5\" data-testid=\"banner-remove-icon\" />\n </Button>\n )}\n </div>\n )\n})\n\nBanner.displayName = 'Banner'\n"],"names":["InfoIcon","CircleXIcon","CircleCheckIcon","TriangleAlertIcon","forwardRef","_jsx","buildClassName","_jsxs","Button","XIcon"],"mappings":";;;;;;;;;;;;AAUA,MAAM,OAAO,GAAG;AACd,IAAA,EAAE,EAAE,QAAQ;AACZ,IAAA,EAAE,EAAE,QAAQ;AACZ,IAAA,EAAE,EAAE,QAAQ;AACZ,IAAA,EAAE,EAAE,QAAQ;AACZ,IAAA,EAAE,EAAE,SAAS;CACd;AAED,MAAM,OAAO,GAAG;AACd,IAAA,IAAI,EAAEA,YAAQ;AACd,IAAA,KAAK,EAAEC,eAAW;AAClB,IAAA,OAAO,EAAEC,mBAAe;AACxB,IAAA,OAAO,EAAEC,qBAAiB;CAC3B;AAED,MAAM,YAAY,GAAG;AACnB,IAAA,IAAI,EAAE,wFAAwF;AAC9F,IAAA,KAAK,EACH,8FAA8F;AAChG,IAAA,OAAO,EACL,iGAAiG;AACnG,IAAA,OAAO,EACL,iGAAiG;CACpG;AAEM,MAAM,MAAM,GAAGC,gBAAU,CAA8B,CAAC,KAAK,EAAE,GAAG,KAAI;IAC3E,MAAM,EACJ,IAAI,GAAG,MAAM,EACb,QAAQ,GAAG,IAAI,EACf,QAAQ,EACR,IAAI,EACJ,SAAS,GAAG,KAAK,EACjB,QAAQ,EACR,SAAS,EACT,GAAG,SAAS,EACb,GAAG,KAAK;AAET,IAAA,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;AACjC,IAAA,MAAM,QAAQ,GACZ,IAAI,KAAK,SAAS,IAChB,IAAI,KAEJC,cAAA,CAAC,WAAW,EAAA,EAAA,aAAA,EACG,CAAA,OAAA,EAAU,IAAI,CAAA,KAAA,CAAO,EAClC,SAAS,EAAEC,6BAAc,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAA,CACxD,CACH;AAEH,IAAA,QACEC,eAAA,CAAA,KAAA,EAAA,EACE,GAAG,EAAE,GAAG,EACR,SAAS,EAAED,6BAAc,CACvB,yEAAyE,EACzE,YAAY,CAAC,IAAI,CAAC,EAClB,SAAS,CACV,EAAA,aAAA,EACY,CAAA,OAAA,EAAU,IAAI,EAAE,EAAA,GACzB,SAAS,aAEZ,QAAQ,EACTD,wBAAK,SAAS,EAAC,0CAA0C,EAAA,QAAA,EAAE,QAAQ,EAAA,CAAO,EACzE,SAAS,KACRA,eAACG,aAAM,EAAA,EACL,QAAQ,EAAA,IAAA,EAAA,YAAA,EACG,gBAAgB,EAC3B,IAAI,EAAC,IAAI,EACT,OAAO,EAAC,OAAO,EACf,SAAS,EAAC,qDAAqD,EAC/D,OAAO,EAAE,MAAM,QAAQ,KAAA,IAAA,IAAR,QAAQ,uBAAR,QAAQ,EAAI,iBACf,mBAAmB,EAAA,QAAA,EAE/BH,eAACI,SAAK,EAAA,EAAC,SAAS,EAAC,UAAU,iBAAa,oBAAoB,EAAA,CAAG,GACxD,CACV,CAAA,EAAA,CACG;AAEV,CAAC;AAED,MAAM,CAAC,WAAW,GAAG,QAAQ;;;;"}
@@ -3,20 +3,23 @@
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var buildClassname = require('../../utils/build-classname.js');
5
5
 
6
- function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels = 'always', theme = 'light', activeIndicatorStyle = 'line', containerClass = '', itemClass = '', }) {
6
+ function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels = 'always', theme = 'light', activeIndicatorStyle = 'line', containerClass = '', itemClass = '', linkAs = 'a', linkHrefProp = 'href', ariaLabel = 'Bottom Navigation', hidden = false, }) {
7
7
  const handleTabClick = (item) => {
8
8
  var _a;
9
9
  if (item.disabled)
10
10
  return;
11
11
  (_a = item.onClick) === null || _a === void 0 ? void 0 : _a.call(item);
12
- onChange(item.id);
12
+ onChange === null || onChange === void 0 ? void 0 : onChange(item.id);
13
13
  };
14
+ // Removed from the tree, not just covered, so hidden tabs can't take focus.
15
+ if (hidden)
16
+ return null;
14
17
  const themeStyles = {
15
18
  light: 'bg-white dark:bg-gray-900 border-t border-[var(--ui-border)] text-gray-600 dark:text-gray-400',
16
19
  dark: 'bg-gray-900 text-gray-400 border-t border-gray-800',
17
20
  primary: 'bg-blue-600 text-blue-100 border-t border-blue-700',
18
21
  }[theme];
19
- return (jsxRuntime.jsx("nav", { "aria-label": "Bottom Navigation", className: buildClassname.buildClassName('w-full flex items-center justify-around select-none shadow-lg transition-colors relative', fixed && 'fixed bottom-0 left-0 right-0 z-40', 'pb-[env(safe-area-inset-bottom,6px)] px-2', themeStyles, containerClass), "data-testid": "bottom-navigation", children: items.map((item) => {
22
+ return (jsxRuntime.jsx("nav", { "aria-label": ariaLabel, className: buildClassname.buildClassName('w-full flex items-center justify-around select-none shadow-lg transition-colors relative', fixed && 'fixed bottom-0 left-0 right-0 z-40', 'pb-[env(safe-area-inset-bottom,6px)] px-2', themeStyles, containerClass), "data-testid": "bottom-navigation", children: items.map((item) => {
20
23
  const isActive = item.id === activeId;
21
24
  const showLabelText = showLabels === 'always' || (showLabels === 'active' && isActive);
22
25
  const activeItemColor = {
@@ -39,11 +42,17 @@ function BottomNavigation({ items, activeId, onChange, fixed = true, showLabels
39
42
  info: 'bg-blue-500 text-white',
40
43
  success: 'bg-emerald-500 text-white',
41
44
  }[item.badgeVariant || 'danger'];
42
- return (jsxRuntime.jsxs("button", { type: "button", disabled: item.disabled, onClick: () => handleTabClick(item), className: buildClassname.buildClassName('flex-1 flex flex-col items-center justify-center pt-2 pb-1.5 px-1 transition-all duration-200 relative cursor-pointer group', item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none', isActive ? activeItemColor : inactiveItemColor, itemClass), "data-testid": `bottom-nav-item-${item.id}`, "aria-selected": isActive, children: [activeIndicatorStyle === 'line' && isActive && (jsxRuntime.jsx("span", { className: buildClassname.buildClassName('absolute -top-[1px] h-0.75 w-9 rounded-full transition-all duration-200 z-10', theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400') })), jsxRuntime.jsxs("div", { className: buildClassname.buildClassName('relative inline-flex items-center justify-center transition-all duration-200', activeIndicatorStyle === 'pill'
45
+ // A disabled item stays a button: a link can't be disabled.
46
+ const isLink = Boolean(item.href) && !item.disabled;
47
+ const ItemElement = isLink ? linkAs : 'button';
48
+ const elementProps = isLink
49
+ ? { [linkHrefProp]: item.href }
50
+ : { type: 'button', disabled: item.disabled };
51
+ return (jsxRuntime.jsxs(ItemElement, { ...elementProps, onClick: () => handleTabClick(item), className: buildClassname.buildClassName('flex-1 flex flex-col items-center justify-center pt-2 pb-1.5 px-1 transition-all duration-200 relative cursor-pointer group', item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none', isActive ? activeItemColor : inactiveItemColor, itemClass), "data-testid": `bottom-nav-item-${item.id}`, "aria-current": isActive ? 'page' : undefined, "aria-label": !showLabelText && typeof item.label === 'string' ? item.label : undefined, children: [activeIndicatorStyle === 'line' && isActive && (jsxRuntime.jsx("span", { className: buildClassname.buildClassName('absolute -top-[1px] h-0.75 w-9 rounded-full transition-all duration-200 z-10', theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400') })), jsxRuntime.jsxs("div", { className: buildClassname.buildClassName('relative inline-flex items-center justify-center transition-all duration-200', activeIndicatorStyle === 'pill'
43
52
  ? buildClassname.buildClassName('px-4 py-1 rounded-full', isActive
44
53
  ? pillActiveStyles
45
54
  : 'group-hover:bg-gray-100/50 dark:group-hover:bg-gray-800/40')
46
- : 'px-1 py-0.5'), children: [jsxRuntime.jsx("span", { className: "text-xl transition-transform duration-150 group-active:scale-95", children: isActive && item.activeIcon ? item.activeIcon : item.icon }), item.badge !== undefined && item.badge !== null && (jsxRuntime.jsx("span", { className: buildClassname.buildClassName('absolute -top-1 -right-1 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs z-10', badgeColor), "data-testid": `bottom-nav-badge-${item.id}`, children: item.badge }))] }), showLabelText && (jsxRuntime.jsx("span", { className: buildClassname.buildClassName('text-[11px] leading-tight mt-1 truncate max-w-full transition-colors duration-150', isActive ? 'font-bold' : 'font-medium opacity-90'), children: item.label })), activeIndicatorStyle === 'dot' && isActive && (jsxRuntime.jsx("span", { className: buildClassname.buildClassName('size-1.5 rounded-full mt-1 transition-all duration-200', theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400') }))] }, item.id));
55
+ : 'px-1 py-0.5'), children: [jsxRuntime.jsx("span", { className: "text-xl transition-transform duration-150 group-active:scale-95", "aria-hidden": "true", children: isActive && item.activeIcon ? item.activeIcon : item.icon }), item.badge !== undefined && item.badge !== null && (jsxRuntime.jsx("span", { className: buildClassname.buildClassName('absolute -top-1 -right-1 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs z-10', badgeColor), "data-testid": `bottom-nav-badge-${item.id}`, children: item.badge }))] }), showLabelText && (jsxRuntime.jsx("span", { className: buildClassname.buildClassName('text-[11px] leading-tight mt-1 truncate max-w-full transition-colors duration-150', isActive ? 'font-bold' : 'font-medium opacity-90'), children: item.label })), activeIndicatorStyle === 'dot' && isActive && (jsxRuntime.jsx("span", { className: buildClassname.buildClassName('size-1.5 rounded-full mt-1 transition-all duration-200', theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400') }))] }, item.id));
47
56
  }) }));
48
57
  }
49
58
  BottomNavigation.displayName = 'BottomNavigation';
@@ -1 +1 @@
1
- {"version":3,"file":"BottomNavigation.js","sources":["../../../../../src/components/BottomNavigation/BottomNavigation.tsx"],"sourcesContent":["import React from 'react'\nimport type { BottomNavigationProps, BottomNavigationItem } from './BottomNavigation.types'\nimport { buildClassName } from '../../utils/build-classname'\n\nexport function BottomNavigation({\n items,\n activeId,\n onChange,\n fixed = true,\n showLabels = 'always',\n theme = 'light',\n activeIndicatorStyle = 'line',\n containerClass = '',\n itemClass = '',\n}: BottomNavigationProps) {\n const handleTabClick = (item: BottomNavigationItem) => {\n if (item.disabled) return\n item.onClick?.()\n onChange(item.id)\n }\n\n const themeStyles = {\n light:\n 'bg-white dark:bg-gray-900 border-t border-[var(--ui-border)] text-gray-600 dark:text-gray-400',\n dark: 'bg-gray-900 text-gray-400 border-t border-gray-800',\n primary: 'bg-blue-600 text-blue-100 border-t border-blue-700',\n }[theme]\n\n return (\n <nav\n aria-label=\"Bottom Navigation\"\n className={buildClassName(\n 'w-full flex items-center justify-around select-none shadow-lg transition-colors relative',\n fixed && 'fixed bottom-0 left-0 right-0 z-40',\n 'pb-[env(safe-area-inset-bottom,6px)] px-2',\n themeStyles,\n containerClass,\n )}\n data-testid=\"bottom-navigation\"\n >\n {items.map((item) => {\n const isActive = item.id === activeId\n const showLabelText = showLabels === 'always' || (showLabels === 'active' && isActive)\n\n const activeItemColor = {\n light: 'text-blue-600 dark:text-blue-400 font-bold',\n dark: 'text-white font-bold',\n primary: 'text-white font-bold',\n }[theme]\n\n const inactiveItemColor = {\n light:\n 'text-gray-500 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 font-medium',\n dark: 'text-gray-400 hover:text-gray-200 font-medium',\n primary: 'text-blue-200 hover:text-white font-medium',\n }[theme]\n\n const pillActiveStyles = {\n light:\n 'bg-blue-100 dark:bg-blue-950/80 text-blue-600 dark:text-blue-400 shadow-xs scale-105',\n dark: 'bg-gray-800 text-white ring-1 ring-gray-700 shadow-xs scale-105',\n primary: 'bg-white/25 text-white shadow-xs scale-105',\n }[theme]\n\n const badgeColor = {\n danger: 'bg-red-500 text-white',\n info: 'bg-blue-500 text-white',\n success: 'bg-emerald-500 text-white',\n }[item.badgeVariant || 'danger']\n\n return (\n <button\n key={item.id}\n type=\"button\"\n disabled={item.disabled}\n onClick={() => handleTabClick(item)}\n className={buildClassName(\n 'flex-1 flex flex-col items-center justify-center pt-2 pb-1.5 px-1 transition-all duration-200 relative cursor-pointer group',\n item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none',\n isActive ? activeItemColor : inactiveItemColor,\n itemClass,\n )}\n data-testid={`bottom-nav-item-${item.id}`}\n aria-selected={isActive}\n >\n {/* Active Indicator Bar on Top Border */}\n {activeIndicatorStyle === 'line' && isActive && (\n <span\n className={buildClassName(\n 'absolute -top-[1px] h-0.75 w-9 rounded-full transition-all duration-200 z-10',\n theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400',\n )}\n />\n )}\n\n {/* Icon & Badge Container */}\n <div\n className={buildClassName(\n 'relative inline-flex items-center justify-center transition-all duration-200',\n activeIndicatorStyle === 'pill'\n ? buildClassName(\n 'px-4 py-1 rounded-full',\n isActive\n ? pillActiveStyles\n : 'group-hover:bg-gray-100/50 dark:group-hover:bg-gray-800/40',\n )\n : 'px-1 py-0.5',\n )}\n >\n <span className=\"text-xl transition-transform duration-150 group-active:scale-95\">\n {isActive && item.activeIcon ? item.activeIcon : item.icon}\n </span>\n\n {/* Notification Badge */}\n {item.badge !== undefined && item.badge !== null && (\n <span\n className={buildClassName(\n 'absolute -top-1 -right-1 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs z-10',\n badgeColor,\n )}\n data-testid={`bottom-nav-badge-${item.id}`}\n >\n {item.badge}\n </span>\n )}\n </div>\n\n {/* Label */}\n {showLabelText && (\n <span\n className={buildClassName(\n 'text-[11px] leading-tight mt-1 truncate max-w-full transition-colors duration-150',\n isActive ? 'font-bold' : 'font-medium opacity-90',\n )}\n >\n {item.label}\n </span>\n )}\n\n {/* Active Dot Indicator */}\n {activeIndicatorStyle === 'dot' && isActive && (\n <span\n className={buildClassName(\n 'size-1.5 rounded-full mt-1 transition-all duration-200',\n theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400',\n )}\n />\n )}\n </button>\n )\n })}\n </nav>\n )\n}\n\nBottomNavigation.displayName = 'BottomNavigation'\n"],"names":["_jsx","buildClassName","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"BottomNavigation.js","sources":["../../../../../src/components/BottomNavigation/BottomNavigation.tsx"],"sourcesContent":["import React, { type ElementType } from 'react'\nimport type { BottomNavigationProps, BottomNavigationItem } from './BottomNavigation.types'\nimport { buildClassName } from '../../utils/build-classname'\n\nexport function BottomNavigation({\n items,\n activeId,\n onChange,\n fixed = true,\n showLabels = 'always',\n theme = 'light',\n activeIndicatorStyle = 'line',\n containerClass = '',\n itemClass = '',\n linkAs = 'a',\n linkHrefProp = 'href',\n ariaLabel = 'Bottom Navigation',\n hidden = false,\n}: BottomNavigationProps) {\n const handleTabClick = (item: BottomNavigationItem) => {\n if (item.disabled) return\n item.onClick?.()\n onChange?.(item.id)\n }\n\n // Removed from the tree, not just covered, so hidden tabs can't take focus.\n if (hidden) return null\n\n const themeStyles = {\n light:\n 'bg-white dark:bg-gray-900 border-t border-[var(--ui-border)] text-gray-600 dark:text-gray-400',\n dark: 'bg-gray-900 text-gray-400 border-t border-gray-800',\n primary: 'bg-blue-600 text-blue-100 border-t border-blue-700',\n }[theme]\n\n return (\n <nav\n aria-label={ariaLabel}\n className={buildClassName(\n 'w-full flex items-center justify-around select-none shadow-lg transition-colors relative',\n fixed && 'fixed bottom-0 left-0 right-0 z-40',\n 'pb-[env(safe-area-inset-bottom,6px)] px-2',\n themeStyles,\n containerClass,\n )}\n data-testid=\"bottom-navigation\"\n >\n {items.map((item) => {\n const isActive = item.id === activeId\n const showLabelText = showLabels === 'always' || (showLabels === 'active' && isActive)\n\n const activeItemColor = {\n light: 'text-blue-600 dark:text-blue-400 font-bold',\n dark: 'text-white font-bold',\n primary: 'text-white font-bold',\n }[theme]\n\n const inactiveItemColor = {\n light:\n 'text-gray-500 dark:text-gray-400 hover:text-gray-800 dark:hover:text-gray-200 font-medium',\n dark: 'text-gray-400 hover:text-gray-200 font-medium',\n primary: 'text-blue-200 hover:text-white font-medium',\n }[theme]\n\n const pillActiveStyles = {\n light:\n 'bg-blue-100 dark:bg-blue-950/80 text-blue-600 dark:text-blue-400 shadow-xs scale-105',\n dark: 'bg-gray-800 text-white ring-1 ring-gray-700 shadow-xs scale-105',\n primary: 'bg-white/25 text-white shadow-xs scale-105',\n }[theme]\n\n const badgeColor = {\n danger: 'bg-red-500 text-white',\n info: 'bg-blue-500 text-white',\n success: 'bg-emerald-500 text-white',\n }[item.badgeVariant || 'danger']\n\n // A disabled item stays a button: a link can't be disabled.\n const isLink = Boolean(item.href) && !item.disabled\n const ItemElement: ElementType = isLink ? linkAs : 'button'\n const elementProps = isLink\n ? { [linkHrefProp]: item.href }\n : { type: 'button', disabled: item.disabled }\n\n return (\n <ItemElement\n key={item.id}\n {...elementProps}\n onClick={() => handleTabClick(item)}\n className={buildClassName(\n 'flex-1 flex flex-col items-center justify-center pt-2 pb-1.5 px-1 transition-all duration-200 relative cursor-pointer group',\n item.disabled && 'opacity-40 cursor-not-allowed pointer-events-none',\n isActive ? activeItemColor : inactiveItemColor,\n itemClass,\n )}\n data-testid={`bottom-nav-item-${item.id}`}\n aria-current={isActive ? 'page' : undefined}\n // With its label hidden, the item still needs a name; the icon is decorative.\n aria-label={!showLabelText && typeof item.label === 'string' ? item.label : undefined}\n >\n {/* Active Indicator Bar on Top Border */}\n {activeIndicatorStyle === 'line' && isActive && (\n <span\n className={buildClassName(\n 'absolute -top-[1px] h-0.75 w-9 rounded-full transition-all duration-200 z-10',\n theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400',\n )}\n />\n )}\n\n {/* Icon & Badge Container */}\n <div\n className={buildClassName(\n 'relative inline-flex items-center justify-center transition-all duration-200',\n activeIndicatorStyle === 'pill'\n ? buildClassName(\n 'px-4 py-1 rounded-full',\n isActive\n ? pillActiveStyles\n : 'group-hover:bg-gray-100/50 dark:group-hover:bg-gray-800/40',\n )\n : 'px-1 py-0.5',\n )}\n >\n <span\n className=\"text-xl transition-transform duration-150 group-active:scale-95\"\n aria-hidden=\"true\"\n >\n {isActive && item.activeIcon ? item.activeIcon : item.icon}\n </span>\n\n {/* Notification Badge */}\n {item.badge !== undefined && item.badge !== null && (\n <span\n className={buildClassName(\n 'absolute -top-1 -right-1 min-w-[16px] h-4 px-1 rounded-full text-[10px] font-bold flex items-center justify-center shadow-xs z-10',\n badgeColor,\n )}\n data-testid={`bottom-nav-badge-${item.id}`}\n >\n {item.badge}\n </span>\n )}\n </div>\n\n {/* Label */}\n {showLabelText && (\n <span\n className={buildClassName(\n 'text-[11px] leading-tight mt-1 truncate max-w-full transition-colors duration-150',\n isActive ? 'font-bold' : 'font-medium opacity-90',\n )}\n >\n {item.label}\n </span>\n )}\n\n {/* Active Dot Indicator */}\n {activeIndicatorStyle === 'dot' && isActive && (\n <span\n className={buildClassName(\n 'size-1.5 rounded-full mt-1 transition-all duration-200',\n theme === 'primary' ? 'bg-white' : 'bg-blue-600 dark:bg-blue-400',\n )}\n />\n )}\n </ItemElement>\n )\n })}\n </nav>\n )\n}\n\nBottomNavigation.displayName = 'BottomNavigation'\n"],"names":["_jsx","buildClassName","_jsxs"],"mappings":"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"}
@@ -8,59 +8,35 @@ var TextContent = require('../TextContent/TextContent.js');
8
8
 
9
9
  /**
10
10
  * Tailwind CSS classes for theme + variant combinations.
11
+ *
12
+ * Only colours live here. Focus outline width/offset and disabled styling are
13
+ * applied uniformly in the component so they can be toggled in one place.
11
14
  */
12
15
  const THEMED_BTN_CLASS = {
13
16
  primary: {
14
- default: 'text-white bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:bg-[var(--ui-primary-disabled)]',
15
- outlined: 'text-[var(--ui-primary-text)] hover:text-white border border-[var(--ui-primary)] hover:bg-[var(--ui-primary)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)] disabled:border-[var(--ui-primary-disabled)]',
16
- plain: 'text-[var(--ui-primary-text)] hover:bg-blue-50/80 dark:hover:bg-blue-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)]',
17
+ default: 'text-white bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] focus-visible:outline-[var(--ui-primary-ring)]',
18
+ outlined: 'text-[var(--ui-primary-text)] hover:text-white border border-[var(--ui-primary)] hover:bg-[var(--ui-primary)] focus-visible:outline-[var(--ui-primary-ring)]',
19
+ plain: 'text-[var(--ui-primary-text)] hover:bg-current/10 active:bg-current/15 focus-visible:outline-[var(--ui-primary-ring)]',
17
20
  },
18
21
  danger: {
19
- default: 'text-white bg-[var(--ui-danger)] hover:bg-[var(--ui-danger-hover)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:bg-[var(--ui-danger-disabled)]',
20
- outlined: 'text-[var(--ui-danger-text)] hover:text-white border border-[var(--ui-danger)] hover:bg-[var(--ui-danger)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)] disabled:border-[var(--ui-danger-disabled)]',
21
- plain: 'text-[var(--ui-danger-text)] hover:bg-red-50/80 dark:hover:bg-red-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)]',
22
+ default: 'text-white bg-[var(--ui-danger)] hover:bg-[var(--ui-danger-hover)] focus-visible:outline-[var(--ui-danger-ring)]',
23
+ outlined: 'text-[var(--ui-danger-text)] hover:text-white border border-[var(--ui-danger)] hover:bg-[var(--ui-danger)] focus-visible:outline-[var(--ui-danger-ring)]',
24
+ plain: 'text-[var(--ui-danger-text)] hover:bg-current/10 active:bg-current/15 focus-visible:outline-[var(--ui-danger-ring)]',
22
25
  },
23
26
  secondary: {
24
- default: 'text-gray-700 bg-white border border-[var(--ui-border)] hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:bg-gray-200 dark:disabled:bg-gray-700',
25
- outlined: 'text-gray-700 hover:text-white border border-[var(--ui-border)] hover:bg-gray-700 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:text-gray-400 disabled:border-[var(--ui-border-muted)]',
26
- plain: 'text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-800 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:text-gray-400',
27
+ default: 'text-gray-700 bg-white border border-[var(--ui-border)] hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700 focus-visible:outline-[var(--ui-focus-ring)]',
28
+ outlined: 'text-gray-700 hover:text-white border border-[var(--ui-border)] hover:bg-gray-700 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus-visible:outline-[var(--ui-focus-ring)]',
29
+ plain: 'text-gray-700 hover:bg-current/10 active:bg-current/15 dark:text-gray-200 focus-visible:outline-[var(--ui-focus-ring)]',
27
30
  },
28
31
  success: {
29
- default: 'text-white bg-emerald-600 hover:bg-emerald-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:bg-emerald-300 dark:disabled:bg-emerald-900',
30
- outlined: 'text-emerald-600 hover:text-white border border-emerald-600 hover:bg-emerald-600 dark:text-emerald-400 dark:border-emerald-500 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:opacity-50',
31
- plain: 'text-emerald-600 hover:bg-emerald-50 dark:text-emerald-400 dark:hover:bg-emerald-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:opacity-50',
32
+ default: 'text-white bg-emerald-600 hover:bg-emerald-700 focus-visible:outline-emerald-500',
33
+ outlined: 'text-emerald-700 hover:text-white border border-emerald-600 hover:bg-emerald-600 dark:text-emerald-400 dark:border-emerald-500 focus-visible:outline-emerald-500',
34
+ plain: 'text-emerald-700 hover:bg-current/10 active:bg-current/15 dark:text-emerald-400 focus-visible:outline-emerald-500',
32
35
  },
33
36
  warning: {
34
- default: 'text-white bg-amber-500 hover:bg-amber-600 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:bg-amber-300 dark:disabled:bg-amber-900',
35
- outlined: 'text-amber-600 hover:text-white border border-amber-500 hover:bg-amber-500 dark:text-amber-400 dark:border-amber-500 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:opacity-50',
36
- plain: 'text-amber-600 hover:bg-amber-50 dark:text-amber-400 dark:hover:bg-amber-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:opacity-50',
37
- },
38
- };
39
- const LOADER_TEXT_CLASS = {
40
- primary: {
41
- default: 'text-white',
42
- outlined: 'text-[var(--ui-primary-text)]',
43
- plain: 'text-[var(--ui-primary-text)]',
44
- },
45
- danger: {
46
- default: 'text-white',
47
- outlined: 'text-[var(--ui-danger-text)]',
48
- plain: 'text-[var(--ui-danger-text)]',
49
- },
50
- secondary: {
51
- default: 'text-gray-700 dark:text-white',
52
- outlined: 'text-gray-700 dark:text-gray-200',
53
- plain: 'text-gray-700 dark:text-gray-200',
54
- },
55
- success: {
56
- default: 'text-white',
57
- outlined: 'text-emerald-600 dark:text-emerald-400',
58
- plain: 'text-emerald-600 dark:text-emerald-400',
59
- },
60
- warning: {
61
- default: 'text-white',
62
- outlined: 'text-amber-600 dark:text-amber-400',
63
- plain: 'text-amber-600 dark:text-amber-400',
37
+ default: 'text-white bg-amber-500 hover:bg-amber-600 focus-visible:outline-amber-500',
38
+ outlined: 'text-amber-700 hover:text-white border border-amber-500 hover:bg-amber-500 dark:text-amber-400 dark:border-amber-500 focus-visible:outline-amber-500',
39
+ plain: 'text-amber-700 hover:bg-current/10 active:bg-current/15 dark:text-amber-400 focus-visible:outline-amber-500',
64
40
  },
65
41
  };
66
42
  const SIZE_CLASSES = {
@@ -80,22 +56,32 @@ const LOADER_SIZE = {
80
56
  };
81
57
  /**
82
58
  * Base shared tailwind classes.
59
+ *
60
+ * Disabled styling is keyed off both the native `disabled` attribute and
61
+ * `aria-disabled`, so non-button elements rendered via `as` look disabled too.
83
62
  */
84
63
  const BASE_BTN_CLASS = 'font-medium inline-flex items-center justify-center shrink-0 cursor-pointer select-none ' +
85
- 'disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-75 ' +
86
- 'active:scale-[0.98] transition-all duration-150 ease-out focus:outline-none';
64
+ 'transition-[color,background-color,border-color,box-shadow,opacity,transform] duration-150 ease-out ' +
65
+ 'active:scale-[0.98] focus:outline-none ' +
66
+ 'disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none ' +
67
+ 'aria-disabled:pointer-events-none aria-disabled:opacity-50 aria-disabled:shadow-none';
87
68
  const Button = React.forwardRef(({ as, type, ...props }, ref) => {
88
- var _a, _b, _c, _d;
89
69
  const { className = '', children, theme = 'primary', variant = 'default', size = 'md', leftIcon, rightIcon, fullWidth = false, loading = false, loadingText = '', rounded = false, disabled, iconOnly = false, noOutlineOnFocus = false, active, onClick, ...restProps } = props;
90
70
  const Component = as || 'button';
91
71
  const isNativeButton = Component === 'button';
72
+ // Clean invalid props when not rendering a real button
73
+ const { type: _ignoreType, disabled: _ignoreDisabled, role, tabIndex, onKeyDown, onKeyUp, ...domProps } = restProps;
74
+ const ariaLabel = domProps['aria-label'];
75
+ const ariaLabelledBy = domProps['aria-labelledby'];
92
76
  // Accessibility guard for icon-only buttons
93
- if (iconOnly && !restProps['aria-label']) {
94
- console.warn('[ui] <Button iconOnly> requires aria-label for accessibility.');
95
- }
77
+ React.useEffect(() => {
78
+ if (iconOnly && !ariaLabel && !ariaLabelledBy) {
79
+ console.warn('[ui] <Button iconOnly> requires aria-label or aria-labelledby for accessibility.');
80
+ }
81
+ }, [iconOnly, ariaLabel, ariaLabelledBy]);
96
82
  const resolvedDisabled = Boolean(disabled || loading);
97
- // Clean invalid props when not rendering a real button
98
- const { type: _ignoreType, disabled: _ignoreDisabled, ...cleanRest } = restProps;
83
+ // Links (`href`, or `to` for router Link components) keep their native semantics.
84
+ const isLink = !isNativeButton && (domProps.href != null || domProps.to != null);
99
85
  const handleClick = (e) => {
100
86
  if (resolvedDisabled) {
101
87
  e.preventDefault();
@@ -104,31 +90,73 @@ const Button = React.forwardRef(({ as, type, ...props }, ref) => {
104
90
  }
105
91
  onClick === null || onClick === void 0 ? void 0 : onClick(e);
106
92
  };
93
+ // Mirror native <button> keyboard activation for non-button elements:
94
+ // Enter activates on keydown, Space on keyup (and must not scroll the page).
95
+ const handleKeyDown = (e) => {
96
+ onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(e);
97
+ if (e.defaultPrevented || e.target !== e.currentTarget)
98
+ return;
99
+ if (e.key === 'Enter') {
100
+ e.preventDefault();
101
+ e.currentTarget.click();
102
+ }
103
+ else if (e.key === ' ') {
104
+ e.preventDefault();
105
+ }
106
+ };
107
+ const handleKeyUp = (e) => {
108
+ onKeyUp === null || onKeyUp === void 0 ? void 0 : onKeyUp(e);
109
+ if (e.defaultPrevented || e.target !== e.currentTarget)
110
+ return;
111
+ if (e.key === ' ') {
112
+ e.preventDefault();
113
+ e.currentTarget.click();
114
+ }
115
+ };
107
116
  const elementProps = isNativeButton
108
117
  ? {
109
118
  type: type !== null && type !== void 0 ? type : 'button',
110
119
  disabled: resolvedDisabled,
120
+ role,
121
+ tabIndex,
111
122
  onClick: handleClick,
123
+ onKeyDown,
124
+ onKeyUp,
112
125
  }
113
- : {
114
- role: (_a = cleanRest.role) !== null && _a !== void 0 ? _a : 'button',
115
- tabIndex: resolvedDisabled ? -1 : ((_b = cleanRest.tabIndex) !== null && _b !== void 0 ? _b : 0),
116
- 'aria-disabled': resolvedDisabled ? true : undefined,
117
- onClick: handleClick,
118
- };
126
+ : isLink
127
+ ? {
128
+ role,
129
+ tabIndex: resolvedDisabled ? -1 : tabIndex,
130
+ 'aria-disabled': resolvedDisabled ? true : undefined,
131
+ onClick: handleClick,
132
+ onKeyDown,
133
+ onKeyUp,
134
+ }
135
+ : {
136
+ role: role !== null && role !== void 0 ? role : 'button',
137
+ tabIndex: resolvedDisabled ? -1 : (tabIndex !== null && tabIndex !== void 0 ? tabIndex : 0),
138
+ 'aria-disabled': resolvedDisabled ? true : undefined,
139
+ onClick: handleClick,
140
+ onKeyDown: handleKeyDown,
141
+ onKeyUp: handleKeyUp,
142
+ };
119
143
  const sizeObj = SIZE_CLASSES[size] || SIZE_CLASSES.md;
120
144
  const classes = React.useMemo(() => {
121
145
  var _a;
122
- return buildClassname.buildClassName(BASE_BTN_CLASS, ((_a = THEMED_BTN_CLASS[theme]) === null || _a === void 0 ? void 0 : _a[variant]) || THEMED_BTN_CLASS.primary.default, iconOnly ? sizeObj.iconOnly : sizeObj.normal, !noOutlineOnFocus && 'focus-visible:ring-2 focus-visible:ring-offset-2', rounded && 'rounded-full', fullWidth && 'w-full', variant === 'default' && 'shadow-xs hover:shadow-none disabled:shadow-none', active && 'ring-2 ring-offset-2 ring-current', className);
146
+ return buildClassname.buildClassName(BASE_BTN_CLASS, ((_a = THEMED_BTN_CLASS[theme]) === null || _a === void 0 ? void 0 : _a[variant]) || THEMED_BTN_CLASS.primary.default, iconOnly ? sizeObj.iconOnly : sizeObj.normal,
147
+ // An outline (not a ring) so the offset gap stays transparent on any surface/mode.
148
+ !noOutlineOnFocus &&
149
+ 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid', rounded && 'rounded-full', fullWidth && 'w-full', variant === 'default' && 'shadow-xs hover:shadow-none', active && 'ring-2 ring-current', className);
123
150
  }, [theme, variant, sizeObj, iconOnly, noOutlineOnFocus, rounded, fullWidth, active, className]);
124
- const loaderIcon = (jsxRuntime.jsx(index.Loader, { "data-testid": "btn-loader-icon", size: LOADER_SIZE[size] || 'xs', className: buildClassname.buildClassName((_c = LOADER_TEXT_CLASS[theme]) === null || _c === void 0 ? void 0 : _c[variant]) }));
151
+ // The spinner and loading text inherit the button's text colour.
152
+ const loaderIcon = (jsxRuntime.jsx(index.Loader, { "data-testid": "btn-loader-icon", size: LOADER_SIZE[size] || 'xs', className: "text-current" }));
125
153
  /**
126
154
  * SPECIAL CASE: iconOnly + loading → show spinner only
127
155
  */
128
156
  if (loading && iconOnly) {
129
- return (jsxRuntime.jsx(Component, { ref: ref, className: classes, "aria-busy": "true", "aria-pressed": active !== undefined ? active : undefined, ...elementProps, ...cleanRest, children: loaderIcon }));
157
+ return (jsxRuntime.jsx(Component, { ref: ref, className: classes, "aria-busy": "true", "aria-pressed": active !== undefined ? active : undefined, ...domProps, ...elementProps, children: loaderIcon }));
130
158
  }
131
- return (jsxRuntime.jsx(Component, { ref: ref, className: classes, "aria-busy": loading ? 'true' : undefined, "aria-pressed": active !== undefined ? active : undefined, ...elementProps, ...cleanRest, children: loading ? (jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-2", "aria-live": "polite", children: [loaderIcon, loadingText ? (jsxRuntime.jsx(TextContent.TextContent, { className: buildClassname.buildClassName((_d = LOADER_TEXT_CLASS[theme]) === null || _d === void 0 ? void 0 : _d[variant]), children: loadingText })) : (children)] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [leftIcon && jsxRuntime.jsx("span", { className: "shrink-0 inline-flex items-center", children: leftIcon }), children, rightIcon && jsxRuntime.jsx("span", { className: "shrink-0 inline-flex items-center", children: rightIcon })] })) }));
159
+ return (jsxRuntime.jsx(Component, { ref: ref, className: classes, "aria-busy": loading ? 'true' : undefined, "aria-pressed": active !== undefined ? active : undefined, ...domProps, ...elementProps, children: loading ? (jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-2", "aria-live": "polite", children: [loaderIcon, loadingText ? (jsxRuntime.jsx(TextContent.TextContent, { className: "text-current", children: loadingText })) : (children)] })) : (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [leftIcon && jsxRuntime.jsx("span", { className: "shrink-0 inline-flex items-center", children: leftIcon }), children, rightIcon && jsxRuntime.jsx("span", { className: "shrink-0 inline-flex items-center", children: rightIcon })] })) }));
132
160
  });
133
161
  Button.displayName = 'Button';
134
162
 
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sources":["../../../../../src/components/Button/Button.tsx"],"sourcesContent":["import React, { ElementType, forwardRef, useMemo } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Loader } from '../Loader'\nimport { TextContent } from '../TextContent'\nimport type { ButtonComponent, ButtonProps, ButtonSize, ThemedButtonClass } from './Button.types'\nimport type { PolymorphicRef } from '../common-type'\n\n/**\n * Tailwind CSS classes for theme + variant combinations.\n */\nconst THEMED_BTN_CLASS: ThemedButtonClass = {\n primary: {\n default:\n 'text-white bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:bg-[var(--ui-primary-disabled)]',\n outlined:\n 'text-[var(--ui-primary-text)] hover:text-white border border-[var(--ui-primary)] hover:bg-[var(--ui-primary)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)] disabled:border-[var(--ui-primary-disabled)]',\n plain:\n 'text-[var(--ui-primary-text)] hover:bg-blue-50/80 dark:hover:bg-blue-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-primary-ring)] disabled:text-[var(--ui-primary-disabled)]',\n },\n danger: {\n default:\n 'text-white bg-[var(--ui-danger)] hover:bg-[var(--ui-danger-hover)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:bg-[var(--ui-danger-disabled)]',\n outlined:\n 'text-[var(--ui-danger-text)] hover:text-white border border-[var(--ui-danger)] hover:bg-[var(--ui-danger)] focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)] disabled:border-[var(--ui-danger-disabled)]',\n plain:\n 'text-[var(--ui-danger-text)] hover:bg-red-50/80 dark:hover:bg-red-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-danger-ring)] disabled:text-[var(--ui-danger-disabled)]',\n },\n secondary: {\n default:\n 'text-gray-700 bg-white border border-[var(--ui-border)] hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:bg-gray-200 dark:disabled:bg-gray-700',\n outlined:\n 'text-gray-700 hover:text-white border border-[var(--ui-border)] hover:bg-gray-700 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:text-gray-400 disabled:border-[var(--ui-border-muted)]',\n plain:\n 'text-gray-700 hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-800 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-[var(--ui-focus-ring)] disabled:text-gray-400',\n },\n success: {\n default:\n 'text-white bg-emerald-600 hover:bg-emerald-700 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:bg-emerald-300 dark:disabled:bg-emerald-900',\n outlined:\n 'text-emerald-600 hover:text-white border border-emerald-600 hover:bg-emerald-600 dark:text-emerald-400 dark:border-emerald-500 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:opacity-50',\n plain:\n 'text-emerald-600 hover:bg-emerald-50 dark:text-emerald-400 dark:hover:bg-emerald-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-emerald-500 disabled:opacity-50',\n },\n warning: {\n default:\n 'text-white bg-amber-500 hover:bg-amber-600 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:bg-amber-300 dark:disabled:bg-amber-900',\n outlined:\n 'text-amber-600 hover:text-white border border-amber-500 hover:bg-amber-500 dark:text-amber-400 dark:border-amber-500 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:opacity-50',\n plain:\n 'text-amber-600 hover:bg-amber-50 dark:text-amber-400 dark:hover:bg-amber-950/40 focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-amber-500 disabled:opacity-50',\n },\n}\n\nconst LOADER_TEXT_CLASS: ThemedButtonClass = {\n primary: {\n default: 'text-white',\n outlined: 'text-[var(--ui-primary-text)]',\n plain: 'text-[var(--ui-primary-text)]',\n },\n danger: {\n default: 'text-white',\n outlined: 'text-[var(--ui-danger-text)]',\n plain: 'text-[var(--ui-danger-text)]',\n },\n secondary: {\n default: 'text-gray-700 dark:text-white',\n outlined: 'text-gray-700 dark:text-gray-200',\n plain: 'text-gray-700 dark:text-gray-200',\n },\n success: {\n default: 'text-white',\n outlined: 'text-emerald-600 dark:text-emerald-400',\n plain: 'text-emerald-600 dark:text-emerald-400',\n },\n warning: {\n default: 'text-white',\n outlined: 'text-amber-600 dark:text-amber-400',\n plain: 'text-amber-600 dark:text-amber-400',\n },\n}\n\nconst SIZE_CLASSES: Record<ButtonSize, { normal: string; iconOnly: string }> = {\n xs: { normal: 'h-7 px-2.5 rounded-sm gap-1 text-xs', iconOnly: 'h-7 w-7 p-1 rounded-sm text-xs' },\n sm: { normal: 'h-8 px-3 rounded gap-1.5 text-sm', iconOnly: 'h-8 w-8 p-1.5 rounded text-sm' },\n md: { normal: 'h-9 px-4 rounded-md gap-2 text-sm', iconOnly: 'h-9 w-9 p-2 rounded-md text-sm' },\n lg: {\n normal: 'h-10 px-5 rounded-lg gap-2 text-base',\n iconOnly: 'h-10 w-10 p-2.5 rounded-lg text-base',\n },\n}\n\nconst LOADER_SIZE: Record<ButtonSize, 'xs' | 'sm'> = {\n xs: 'xs',\n sm: 'xs',\n md: 'sm',\n lg: 'sm',\n}\n\n/**\n * Base shared tailwind classes.\n */\nconst BASE_BTN_CLASS =\n 'font-medium inline-flex items-center justify-center shrink-0 cursor-pointer select-none ' +\n 'disabled:cursor-not-allowed disabled:pointer-events-none disabled:opacity-75 ' +\n 'active:scale-[0.98] transition-all duration-150 ease-out focus:outline-none'\n\nexport const Button = forwardRef(\n <C extends ElementType = 'button'>(\n { as, type, ...props }: ButtonProps<C>,\n ref: PolymorphicRef<C>,\n ) => {\n const {\n className = '',\n children,\n theme = 'primary',\n variant = 'default',\n size = 'md',\n leftIcon,\n rightIcon,\n fullWidth = false,\n loading = false,\n loadingText = '',\n rounded = false,\n disabled,\n iconOnly = false,\n noOutlineOnFocus = false,\n active,\n onClick,\n ...restProps\n } = props\n\n const Component = as || 'button'\n const isNativeButton = Component === 'button'\n\n // Accessibility guard for icon-only buttons\n if (iconOnly && !(restProps as Record<string, unknown>)['aria-label']) {\n console.warn('[ui] <Button iconOnly> requires aria-label for accessibility.')\n }\n\n const resolvedDisabled = Boolean(disabled || loading)\n\n // Clean invalid props when not rendering a real button\n const { type: _ignoreType, disabled: _ignoreDisabled, ...cleanRest } = restProps\n\n const handleClick = (e: React.MouseEvent<any>) => {\n if (resolvedDisabled) {\n e.preventDefault()\n e.stopPropagation()\n return\n }\n onClick?.(e)\n }\n\n const elementProps = isNativeButton\n ? {\n type: type ?? 'button',\n disabled: resolvedDisabled,\n onClick: handleClick,\n }\n : {\n role: cleanRest.role ?? 'button',\n tabIndex: resolvedDisabled ? -1 : (cleanRest.tabIndex ?? 0),\n 'aria-disabled': resolvedDisabled ? true : undefined,\n onClick: handleClick,\n }\n\n const sizeObj = SIZE_CLASSES[size] || SIZE_CLASSES.md\n\n const classes = useMemo(\n () =>\n buildClassName(\n BASE_BTN_CLASS,\n THEMED_BTN_CLASS[theme]?.[variant] || THEMED_BTN_CLASS.primary.default,\n iconOnly ? sizeObj.iconOnly : sizeObj.normal,\n !noOutlineOnFocus && 'focus-visible:ring-2 focus-visible:ring-offset-2',\n rounded && 'rounded-full',\n fullWidth && 'w-full',\n variant === 'default' && 'shadow-xs hover:shadow-none disabled:shadow-none',\n active && 'ring-2 ring-offset-2 ring-current',\n className,\n ),\n [theme, variant, sizeObj, iconOnly, noOutlineOnFocus, rounded, fullWidth, active, className],\n )\n\n const loaderIcon = (\n <Loader\n data-testid=\"btn-loader-icon\"\n size={LOADER_SIZE[size] || 'xs'}\n className={buildClassName(LOADER_TEXT_CLASS[theme]?.[variant])}\n />\n )\n\n /**\n * SPECIAL CASE: iconOnly + loading → show spinner only\n */\n if (loading && iconOnly) {\n return (\n <Component\n ref={ref}\n className={classes}\n aria-busy=\"true\"\n aria-pressed={active !== undefined ? active : undefined}\n {...elementProps}\n {...cleanRest}\n >\n {loaderIcon}\n </Component>\n )\n }\n\n return (\n <Component\n ref={ref}\n className={classes}\n aria-busy={loading ? 'true' : undefined}\n aria-pressed={active !== undefined ? active : undefined}\n {...elementProps}\n {...cleanRest}\n >\n {loading ? (\n <span className=\"inline-flex items-center gap-2\" aria-live=\"polite\">\n {loaderIcon}\n {loadingText ? (\n <TextContent className={buildClassName(LOADER_TEXT_CLASS[theme]?.[variant])}>\n {loadingText}\n </TextContent>\n ) : (\n children\n )}\n </span>\n ) : (\n <>\n {leftIcon && <span className=\"shrink-0 inline-flex items-center\">{leftIcon}</span>}\n {children}\n {rightIcon && <span className=\"shrink-0 inline-flex items-center\">{rightIcon}</span>}\n </>\n )}\n </Component>\n )\n },\n) as ButtonComponent\n\nButton.displayName = 'Button'\n"],"names":["forwardRef","useMemo","buildClassName","_jsx","Loader","_jsxs","TextContent","_Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"Button.js","sources":["../../../../../src/components/Button/Button.tsx"],"sourcesContent":["import React, { ElementType, forwardRef, useEffect, useMemo } from 'react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Loader } from '../Loader'\nimport { TextContent } from '../TextContent'\nimport type { ButtonComponent, ButtonProps, ButtonSize, ThemedButtonClass } from './Button.types'\nimport type { PolymorphicRef } from '../common-type'\n\n/**\n * Tailwind CSS classes for theme + variant combinations.\n *\n * Only colours live here. Focus outline width/offset and disabled styling are\n * applied uniformly in the component so they can be toggled in one place.\n */\nconst THEMED_BTN_CLASS: ThemedButtonClass = {\n primary: {\n default:\n 'text-white bg-[var(--ui-primary)] hover:bg-[var(--ui-primary-hover)] focus-visible:outline-[var(--ui-primary-ring)]',\n outlined:\n 'text-[var(--ui-primary-text)] hover:text-white border border-[var(--ui-primary)] hover:bg-[var(--ui-primary)] focus-visible:outline-[var(--ui-primary-ring)]',\n plain:\n 'text-[var(--ui-primary-text)] hover:bg-current/10 active:bg-current/15 focus-visible:outline-[var(--ui-primary-ring)]',\n },\n danger: {\n default:\n 'text-white bg-[var(--ui-danger)] hover:bg-[var(--ui-danger-hover)] focus-visible:outline-[var(--ui-danger-ring)]',\n outlined:\n 'text-[var(--ui-danger-text)] hover:text-white border border-[var(--ui-danger)] hover:bg-[var(--ui-danger)] focus-visible:outline-[var(--ui-danger-ring)]',\n plain:\n 'text-[var(--ui-danger-text)] hover:bg-current/10 active:bg-current/15 focus-visible:outline-[var(--ui-danger-ring)]',\n },\n secondary: {\n default:\n 'text-gray-700 bg-white border border-[var(--ui-border)] hover:bg-gray-100 dark:bg-gray-800 dark:text-white dark:hover:bg-gray-700 focus-visible:outline-[var(--ui-focus-ring)]',\n outlined:\n 'text-gray-700 hover:text-white border border-[var(--ui-border)] hover:bg-gray-700 dark:text-gray-200 dark:hover:text-white dark:hover:bg-gray-600 focus-visible:outline-[var(--ui-focus-ring)]',\n plain:\n 'text-gray-700 hover:bg-current/10 active:bg-current/15 dark:text-gray-200 focus-visible:outline-[var(--ui-focus-ring)]',\n },\n success: {\n default: 'text-white bg-emerald-600 hover:bg-emerald-700 focus-visible:outline-emerald-500',\n outlined:\n 'text-emerald-700 hover:text-white border border-emerald-600 hover:bg-emerald-600 dark:text-emerald-400 dark:border-emerald-500 focus-visible:outline-emerald-500',\n plain:\n 'text-emerald-700 hover:bg-current/10 active:bg-current/15 dark:text-emerald-400 focus-visible:outline-emerald-500',\n },\n warning: {\n default: 'text-white bg-amber-500 hover:bg-amber-600 focus-visible:outline-amber-500',\n outlined:\n 'text-amber-700 hover:text-white border border-amber-500 hover:bg-amber-500 dark:text-amber-400 dark:border-amber-500 focus-visible:outline-amber-500',\n plain:\n 'text-amber-700 hover:bg-current/10 active:bg-current/15 dark:text-amber-400 focus-visible:outline-amber-500',\n },\n}\n\nconst SIZE_CLASSES: Record<ButtonSize, { normal: string; iconOnly: string }> = {\n xs: { normal: 'h-7 px-2.5 rounded-sm gap-1 text-xs', iconOnly: 'h-7 w-7 p-1 rounded-sm text-xs' },\n sm: { normal: 'h-8 px-3 rounded gap-1.5 text-sm', iconOnly: 'h-8 w-8 p-1.5 rounded text-sm' },\n md: { normal: 'h-9 px-4 rounded-md gap-2 text-sm', iconOnly: 'h-9 w-9 p-2 rounded-md text-sm' },\n lg: {\n normal: 'h-10 px-5 rounded-lg gap-2 text-base',\n iconOnly: 'h-10 w-10 p-2.5 rounded-lg text-base',\n },\n}\n\nconst LOADER_SIZE: Record<ButtonSize, 'xs' | 'sm'> = {\n xs: 'xs',\n sm: 'xs',\n md: 'sm',\n lg: 'sm',\n}\n\n/**\n * Base shared tailwind classes.\n *\n * Disabled styling is keyed off both the native `disabled` attribute and\n * `aria-disabled`, so non-button elements rendered via `as` look disabled too.\n */\nconst BASE_BTN_CLASS =\n 'font-medium inline-flex items-center justify-center shrink-0 cursor-pointer select-none ' +\n 'transition-[color,background-color,border-color,box-shadow,opacity,transform] duration-150 ease-out ' +\n 'active:scale-[0.98] focus:outline-none ' +\n 'disabled:pointer-events-none disabled:opacity-50 disabled:shadow-none ' +\n 'aria-disabled:pointer-events-none aria-disabled:opacity-50 aria-disabled:shadow-none'\n\nexport const Button = forwardRef(\n <C extends ElementType = 'button'>(\n { as, type, ...props }: ButtonProps<C>,\n ref: PolymorphicRef<C>,\n ) => {\n const {\n className = '',\n children,\n theme = 'primary',\n variant = 'default',\n size = 'md',\n leftIcon,\n rightIcon,\n fullWidth = false,\n loading = false,\n loadingText = '',\n rounded = false,\n disabled,\n iconOnly = false,\n noOutlineOnFocus = false,\n active,\n onClick,\n ...restProps\n } = props\n\n const Component = as || 'button'\n const isNativeButton = Component === 'button'\n\n // Clean invalid props when not rendering a real button\n const {\n type: _ignoreType,\n disabled: _ignoreDisabled,\n role,\n tabIndex,\n onKeyDown,\n onKeyUp,\n ...domProps\n } = restProps as Record<string, any>\n\n const ariaLabel = domProps['aria-label']\n const ariaLabelledBy = domProps['aria-labelledby']\n\n // Accessibility guard for icon-only buttons\n useEffect(() => {\n if (iconOnly && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n '[ui] <Button iconOnly> requires aria-label or aria-labelledby for accessibility.',\n )\n }\n }, [iconOnly, ariaLabel, ariaLabelledBy])\n\n const resolvedDisabled = Boolean(disabled || loading)\n\n // Links (`href`, or `to` for router Link components) keep their native semantics.\n const isLink = !isNativeButton && (domProps.href != null || domProps.to != null)\n\n const handleClick = (e: React.MouseEvent<any>) => {\n if (resolvedDisabled) {\n e.preventDefault()\n e.stopPropagation()\n return\n }\n onClick?.(e)\n }\n\n // Mirror native <button> keyboard activation for non-button elements:\n // Enter activates on keydown, Space on keyup (and must not scroll the page).\n const handleKeyDown = (e: React.KeyboardEvent<any>) => {\n onKeyDown?.(e)\n if (e.defaultPrevented || e.target !== e.currentTarget) return\n if (e.key === 'Enter') {\n e.preventDefault()\n e.currentTarget.click()\n } else if (e.key === ' ') {\n e.preventDefault()\n }\n }\n\n const handleKeyUp = (e: React.KeyboardEvent<any>) => {\n onKeyUp?.(e)\n if (e.defaultPrevented || e.target !== e.currentTarget) return\n if (e.key === ' ') {\n e.preventDefault()\n e.currentTarget.click()\n }\n }\n\n const elementProps = isNativeButton\n ? {\n type: type ?? 'button',\n disabled: resolvedDisabled,\n role,\n tabIndex,\n onClick: handleClick,\n onKeyDown,\n onKeyUp,\n }\n : isLink\n ? {\n role,\n tabIndex: resolvedDisabled ? -1 : tabIndex,\n 'aria-disabled': resolvedDisabled ? true : undefined,\n onClick: handleClick,\n onKeyDown,\n onKeyUp,\n }\n : {\n role: role ?? 'button',\n tabIndex: resolvedDisabled ? -1 : (tabIndex ?? 0),\n 'aria-disabled': resolvedDisabled ? true : undefined,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n onKeyUp: handleKeyUp,\n }\n\n const sizeObj = SIZE_CLASSES[size] || SIZE_CLASSES.md\n\n const classes = useMemo(\n () =>\n buildClassName(\n BASE_BTN_CLASS,\n THEMED_BTN_CLASS[theme]?.[variant] || THEMED_BTN_CLASS.primary.default,\n iconOnly ? sizeObj.iconOnly : sizeObj.normal,\n // An outline (not a ring) so the offset gap stays transparent on any surface/mode.\n !noOutlineOnFocus &&\n 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-solid',\n rounded && 'rounded-full',\n fullWidth && 'w-full',\n variant === 'default' && 'shadow-xs hover:shadow-none',\n active && 'ring-2 ring-current',\n className,\n ),\n [theme, variant, sizeObj, iconOnly, noOutlineOnFocus, rounded, fullWidth, active, className],\n )\n\n // The spinner and loading text inherit the button's text colour.\n const loaderIcon = (\n <Loader\n data-testid=\"btn-loader-icon\"\n size={LOADER_SIZE[size] || 'xs'}\n className=\"text-current\"\n />\n )\n\n /**\n * SPECIAL CASE: iconOnly + loading → show spinner only\n */\n if (loading && iconOnly) {\n return (\n <Component\n ref={ref}\n className={classes}\n aria-busy=\"true\"\n aria-pressed={active !== undefined ? active : undefined}\n {...domProps}\n {...elementProps}\n >\n {loaderIcon}\n </Component>\n )\n }\n\n return (\n <Component\n ref={ref}\n className={classes}\n aria-busy={loading ? 'true' : undefined}\n aria-pressed={active !== undefined ? active : undefined}\n {...domProps}\n {...elementProps}\n >\n {loading ? (\n <span className=\"inline-flex items-center gap-2\" aria-live=\"polite\">\n {loaderIcon}\n {loadingText ? (\n <TextContent className=\"text-current\">{loadingText}</TextContent>\n ) : (\n children\n )}\n </span>\n ) : (\n <>\n {leftIcon && <span className=\"shrink-0 inline-flex items-center\">{leftIcon}</span>}\n {children}\n {rightIcon && <span className=\"shrink-0 inline-flex items-center\">{rightIcon}</span>}\n </>\n )}\n </Component>\n )\n },\n) as ButtonComponent\n\nButton.displayName = 'Button'\n"],"names":["forwardRef","useEffect","useMemo","buildClassName","_jsx","Loader","_jsxs","TextContent"],"mappings":"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"}
@@ -7,6 +7,7 @@ var buildClassname = require('../../utils/build-classname.js');
7
7
  var Button = require('../Button/Button.js');
8
8
  var ChevronLeft = require('../Icons/ChevronLeft.svg.js');
9
9
  var X = require('../Icons/X.svg.js');
10
+ var useBreakpoint = require('../../hooks/use-breakpoint.js');
10
11
 
11
12
  const alignmentMap = {
12
13
  center: 'items-center justify-center h-full',
@@ -20,7 +21,8 @@ const panelAlignmentMap = {
20
21
  start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',
21
22
  end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',
22
23
  top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',
23
- bottom: 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[88vh] max-h-[88dvh]',
24
+ // Bottom sheets clear the home indicator on notched phones (0 elsewhere).
25
+ bottom: 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[88vh] max-h-[88dvh] pb-[env(safe-area-inset-bottom,0px)]',
24
26
  };
25
27
  const panelSizeMap = {
26
28
  xs: 'max-w-xs',
@@ -31,7 +33,9 @@ const panelSizeMap = {
31
33
  '2xl': 'max-w-2xl',
32
34
  full: 'w-full',
33
35
  };
34
- const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align = 'end', size = 'md', backdrop = true, title, description, children, footer, footerSticky = false, panelClass = '', contentClass = '', titleClass = '', descriptionClass = '', titleSticky = false, showBackButton = false, showCloseButton = true, dragHandle, }) => {
36
+ const Drawer = ({ isOpen, onClose = () => { }, closeOnOutsideClick = true, align: alignProp = 'end', size: sizeProp = 'md', backdrop = true, title, description, children, footer, footerSticky = false, panelClass = '', contentClass = '', titleClass = '', descriptionClass = '', titleSticky = false, showBackButton = false, showCloseButton = true, dragHandle, }) => {
37
+ const align = useBreakpoint.useResponsiveValue(alignProp);
38
+ const size = useBreakpoint.useResponsiveValue(sizeProp);
35
39
  const showTitleSection = Boolean(title || description || showBackButton || showCloseButton);
36
40
  const shouldShowDragHandle = dragHandle !== null && dragHandle !== void 0 ? dragHandle : align === 'bottom';
37
41
  const [viewportHeight, setViewportHeight] = React.useState(null);
@@ -1 +1 @@
1
- {"version":3,"file":"Drawer.js","sources":["../../../../../src/components/Drawer/Drawer.tsx"],"sourcesContent":["import React from 'react'\nimport { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Button } from '../Button'\nimport ChevronLeftIcon from '../Icons/ChevronLeft.svg'\nimport XIcon from '../Icons/X.svg'\nimport type { AlignmentMap, DrawerProps, SizeMap } from './Drawer.types'\n\nconst alignmentMap: AlignmentMap = {\n center: 'items-center justify-center h-full',\n start: 'justify-start h-full',\n end: 'justify-end h-full',\n top: 'items-start justify-center w-full',\n bottom: 'items-end justify-center h-full',\n}\n\nconst panelAlignmentMap: AlignmentMap = {\n center: 'data-[closed]:scale-95 rounded-2xl',\n start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',\n end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',\n top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',\n bottom:\n 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[88vh] max-h-[88dvh]',\n}\n\nconst panelSizeMap: SizeMap = {\n xs: 'max-w-xs',\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n xl: 'max-w-xl',\n '2xl': 'max-w-2xl',\n full: 'w-full',\n}\n\nexport const Drawer: React.FC<DrawerProps> = ({\n isOpen,\n onClose = () => {},\n closeOnOutsideClick = true,\n align = 'end',\n size = 'md',\n backdrop = true,\n title,\n description,\n children,\n footer,\n footerSticky = false,\n panelClass = '',\n contentClass = '',\n titleClass = '',\n descriptionClass = '',\n titleSticky = false,\n showBackButton = false,\n showCloseButton = true,\n dragHandle,\n}) => {\n const showTitleSection = Boolean(title || description || showBackButton || showCloseButton)\n const shouldShowDragHandle = dragHandle ?? align === 'bottom'\n const [viewportHeight, setViewportHeight] = React.useState<number | null>(null)\n\n React.useEffect(() => {\n if (!isOpen) {\n setViewportHeight(null)\n return\n }\n\n const updateHeight = () => {\n if (typeof window !== 'undefined' && window.visualViewport) {\n setViewportHeight(window.visualViewport.height)\n }\n }\n\n updateHeight()\n const vv = typeof window !== 'undefined' ? window.visualViewport : null\n vv?.addEventListener('resize', updateHeight)\n vv?.addEventListener('scroll', updateHeight)\n\n return () => {\n vv?.removeEventListener('resize', updateHeight)\n vv?.removeEventListener('scroll', updateHeight)\n }\n }, [isOpen])\n\n const handleDialogClose = () => {\n if (closeOnOutsideClick) {\n onClose?.()\n }\n }\n\n return (\n <Dialog\n open={isOpen}\n as=\"div\"\n className=\"relative z-50 focus:outline-none\"\n onClose={handleDialogClose}\n transition\n >\n {backdrop && (\n <DialogBackdrop className=\"fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200\" />\n )}\n\n <div\n className=\"fixed left-0 top-0 w-full\"\n style={{ height: viewportHeight ? `${viewportHeight}px` : '100dvh' }}\n >\n <div className={buildClassName('flex', alignmentMap[align])}>\n <DialogPanel\n transition\n className={buildClassName(\n 'w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0',\n 'overflow-y-auto overflow-x-hidden overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] duration-200 ease-out data-[closed]:opacity-0',\n panelAlignmentMap[align],\n panelSizeMap[size],\n panelClass,\n )}\n >\n {/* Top drag handle indicator for mobile bottom sheet */}\n {shouldShowDragHandle && (\n <div\n className=\"w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab\"\n data-testid=\"drawer-drag-handle\"\n />\n )}\n\n {/* Header Section */}\n {showTitleSection && (\n <div\n className={buildClassName(\n 'space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0',\n titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10',\n )}\n >\n <div className=\"flex items-center justify-between gap-3 min-w-0\">\n <div className=\"flex items-center gap-2 min-w-0 flex-1\">\n {showBackButton && (\n <Button\n iconOnly\n aria-label=\"Back\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n >\n <ChevronLeftIcon className=\"size-4\" />\n </Button>\n )}\n {title && (\n <DialogTitle\n as=\"h3\"\n className={buildClassName(\n 'text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0',\n titleClass,\n )}\n >\n {title}\n </DialogTitle>\n )}\n </div>\n\n {showCloseButton && (\n <Button\n iconOnly\n aria-label=\"Close drawer\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n className=\"rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0\"\n >\n <XIcon className=\"size-4\" />\n </Button>\n )}\n </div>\n\n {description && (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400 font-normal truncate',\n descriptionClass,\n )}\n >\n {description}\n </p>\n )}\n </div>\n )}\n\n {/* Content Body */}\n <div className={buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass)}>\n {children}\n </div>\n\n {/* Footer Section */}\n {footer && (\n <div\n className={buildClassName(\n 'p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0',\n footerSticky && 'sticky bottom-0 z-10',\n )}\n >\n {footer}\n </div>\n )}\n </DialogPanel>\n </div>\n </div>\n </Dialog>\n )\n}\n\nDrawer.displayName = 'Drawer'\n"],"names":["_jsxs","Dialog","_jsx","DialogBackdrop","buildClassName","DialogPanel","Button","ChevronLeftIcon","DialogTitle","XIcon"],"mappings":"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"}
1
+ {"version":3,"file":"Drawer.js","sources":["../../../../../src/components/Drawer/Drawer.tsx"],"sourcesContent":["import React from 'react'\nimport { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react'\nimport { buildClassName } from '../../utils/build-classname'\nimport { Button } from '../Button'\nimport ChevronLeftIcon from '../Icons/ChevronLeft.svg'\nimport XIcon from '../Icons/X.svg'\nimport { useResponsiveValue } from '../../hooks/use-breakpoint'\nimport type { AlignmentMap, DrawerProps, SizeMap } from './Drawer.types'\n\nconst alignmentMap: AlignmentMap = {\n center: 'items-center justify-center h-full',\n start: 'justify-start h-full',\n end: 'justify-end h-full',\n top: 'items-start justify-center w-full',\n bottom: 'items-end justify-center h-full',\n}\n\nconst panelAlignmentMap: AlignmentMap = {\n center: 'data-[closed]:scale-95 rounded-2xl',\n start: 'data-[closed]:-translate-x-1/2 rounded-r-2xl',\n end: 'data-[closed]:translate-x-1/2 rounded-l-2xl',\n top: 'data-[closed]:-translate-y-1/2 rounded-b-2xl',\n // Bottom sheets clear the home indicator on notched phones (0 elsewhere).\n bottom:\n 'data-[closed]:translate-y-full rounded-t-2xl md:rounded-t-3xl max-h-[88vh] max-h-[88dvh] pb-[env(safe-area-inset-bottom,0px)]',\n}\n\nconst panelSizeMap: SizeMap = {\n xs: 'max-w-xs',\n sm: 'max-w-sm',\n md: 'max-w-md',\n lg: 'max-w-lg',\n xl: 'max-w-xl',\n '2xl': 'max-w-2xl',\n full: 'w-full',\n}\n\nexport const Drawer: React.FC<DrawerProps> = ({\n isOpen,\n onClose = () => {},\n closeOnOutsideClick = true,\n align: alignProp = 'end',\n size: sizeProp = 'md',\n backdrop = true,\n title,\n description,\n children,\n footer,\n footerSticky = false,\n panelClass = '',\n contentClass = '',\n titleClass = '',\n descriptionClass = '',\n titleSticky = false,\n showBackButton = false,\n showCloseButton = true,\n dragHandle,\n}) => {\n const align = useResponsiveValue(alignProp)\n const size = useResponsiveValue(sizeProp)\n const showTitleSection = Boolean(title || description || showBackButton || showCloseButton)\n const shouldShowDragHandle = dragHandle ?? align === 'bottom'\n const [viewportHeight, setViewportHeight] = React.useState<number | null>(null)\n\n React.useEffect(() => {\n if (!isOpen) {\n setViewportHeight(null)\n return\n }\n\n const updateHeight = () => {\n if (typeof window !== 'undefined' && window.visualViewport) {\n setViewportHeight(window.visualViewport.height)\n }\n }\n\n updateHeight()\n const vv = typeof window !== 'undefined' ? window.visualViewport : null\n vv?.addEventListener('resize', updateHeight)\n vv?.addEventListener('scroll', updateHeight)\n\n return () => {\n vv?.removeEventListener('resize', updateHeight)\n vv?.removeEventListener('scroll', updateHeight)\n }\n }, [isOpen])\n\n const handleDialogClose = () => {\n if (closeOnOutsideClick) {\n onClose?.()\n }\n }\n\n return (\n <Dialog\n open={isOpen}\n as=\"div\"\n className=\"relative z-50 focus:outline-none\"\n onClose={handleDialogClose}\n transition\n >\n {backdrop && (\n <DialogBackdrop className=\"fixed inset-0 bg-black/40 backdrop-blur-xs transition-opacity duration-200\" />\n )}\n\n <div\n className=\"fixed left-0 top-0 w-full\"\n style={{ height: viewportHeight ? `${viewportHeight}px` : '100dvh' }}\n >\n <div className={buildClassName('flex', alignmentMap[align])}>\n <DialogPanel\n transition\n className={buildClassName(\n 'w-full max-w-full bg-white dark:bg-gray-800 shadow-xl flex flex-col min-w-0',\n 'overflow-y-auto overflow-x-hidden overscroll-contain touch-pan-y [-webkit-overflow-scrolling:touch] duration-200 ease-out data-[closed]:opacity-0',\n panelAlignmentMap[align],\n panelSizeMap[size],\n panelClass,\n )}\n >\n {/* Top drag handle indicator for mobile bottom sheet */}\n {shouldShowDragHandle && (\n <div\n className=\"w-12 h-1.5 rounded-full bg-gray-300 dark:bg-gray-600 mx-auto my-2.5 shrink-0 cursor-grab\"\n data-testid=\"drawer-drag-handle\"\n />\n )}\n\n {/* Header Section */}\n {showTitleSection && (\n <div\n className={buildClassName(\n 'space-y-1 py-3 px-4 md:px-6 flex flex-col border-b border-[var(--ui-border)] shrink-0',\n titleSticky && 'sticky top-0 bg-white dark:bg-gray-800 z-10',\n )}\n >\n <div className=\"flex items-center justify-between gap-3 min-w-0\">\n <div className=\"flex items-center gap-2 min-w-0 flex-1\">\n {showBackButton && (\n <Button\n iconOnly\n aria-label=\"Back\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n >\n <ChevronLeftIcon className=\"size-4\" />\n </Button>\n )}\n {title && (\n <DialogTitle\n as=\"h3\"\n className={buildClassName(\n 'text-lg font-semibold text-gray-900 dark:text-white truncate tracking-tight min-w-0',\n titleClass,\n )}\n >\n {title}\n </DialogTitle>\n )}\n </div>\n\n {showCloseButton && (\n <Button\n iconOnly\n aria-label=\"Close drawer\"\n variant=\"plain\"\n theme=\"secondary\"\n size=\"xs\"\n onClick={onClose}\n className=\"rounded-full text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 shrink-0\"\n >\n <XIcon className=\"size-4\" />\n </Button>\n )}\n </div>\n\n {description && (\n <p\n className={buildClassName(\n 'text-sm text-gray-500 dark:text-gray-400 font-normal truncate',\n descriptionClass,\n )}\n >\n {description}\n </p>\n )}\n </div>\n )}\n\n {/* Content Body */}\n <div className={buildClassName('flex-1 p-4 md:p-6 space-y-4 min-w-0', contentClass)}>\n {children}\n </div>\n\n {/* Footer Section */}\n {footer && (\n <div\n className={buildClassName(\n 'p-4 border-t border-[var(--ui-border-muted)] bg-white dark:bg-gray-800 shrink-0 min-w-0',\n footerSticky && 'sticky bottom-0 z-10',\n )}\n >\n {footer}\n </div>\n )}\n </DialogPanel>\n </div>\n </div>\n </Dialog>\n )\n}\n\nDrawer.displayName = 'Drawer'\n"],"names":["useResponsiveValue","_jsxs","Dialog","_jsx","DialogBackdrop","buildClassName","DialogPanel","Button","ChevronLeftIcon","DialogTitle","XIcon"],"mappings":"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"}