jattac.libs.web.zest-button 1.2.9 → 1.4.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.
package/dist/index.d.ts CHANGED
@@ -37,6 +37,21 @@ interface ConfirmOptions {
37
37
  displayLabel: string;
38
38
  timeoutSecs: number;
39
39
  }
40
+ /**
41
+ * A single secondary action in a ZestButton's dropdown menu. Runs through the
42
+ * same busy/confirm machinery as the main button, independently per item.
43
+ */
44
+ interface ZestDropdownOption {
45
+ key?: string;
46
+ label: React.ReactNode;
47
+ icon?: React.ReactNode;
48
+ disabled?: boolean;
49
+ semanticType?: SemanticType;
50
+ onClick?: (e: Event) => void | Promise<void>;
51
+ busyOptions?: BusyOptions;
52
+ successOptions?: SuccessOptions;
53
+ confirmOptions?: ConfirmOptions;
54
+ }
40
55
  interface ZestCustomProps {
41
56
  visualOptions?: VisualOptions;
42
57
  busyOptions?: BusyOptions;
@@ -46,6 +61,8 @@ interface ZestCustomProps {
46
61
  theme?: ZestTheme;
47
62
  buttonStyle?: ZestButtonStyle;
48
63
  semanticType?: SemanticType;
64
+ dropdownOptions?: ZestDropdownOption[];
65
+ dropdownAriaLabel?: string;
49
66
  }
50
67
  /**
51
68
  * All supported props
@@ -67,5 +84,5 @@ interface ZestButtonConfigProviderProps {
67
84
  }
68
85
  declare const ZestButtonConfigProvider: React.FC<ZestButtonConfigProviderProps>;
69
86
 
70
- export { ZestButton, ZestButtonConfigProvider, useZestButtonConfig };
71
- export type { ConfirmOptions, CustomZestSemanticTypes, SemanticType, ZestButtonProps, ZestButtonStyle, ZestCustomProps, ZestGlobalConfig, ZestSize, ZestTheme, ZestVariant };
87
+ export { ZestButtonConfigProvider, ZestButton as default, useZestButtonConfig };
88
+ export type { BusyOptions, ConfirmOptions, CustomZestSemanticTypes, SemanticType, SuccessOptions, ZestButtonProps, ZestButtonStyle, ZestCustomProps, ZestDropdownOption, ZestGlobalConfig, ZestSize, ZestTheme, ZestVariant };
package/dist/index.esm.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import require$$0, { useContext, useState, useRef, useEffect, useCallback } from 'react';
2
- import { FaSpinner } from 'react-icons/fa6';
2
+ import { FaSpinner, FaChevronDown } from 'react-icons/fa6';
3
3
  import { FaShareAlt, FaPrint, FaSyncAlt, FaUpload, FaDownload, FaArrowRight, FaTimes, FaTrash, FaEdit, FaSave, FaPlus } from 'react-icons/fa';
4
+ import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
4
5
 
5
6
  var jsxRuntime = {exports: {}};
6
7
 
@@ -1384,8 +1385,8 @@ function styleInject(css, ref) {
1384
1385
  }
1385
1386
  }
1386
1387
 
1387
- var css_248z = "/* Styles/ZestButton.module.css */\n\n/* Define base variables for light mode */\n:root {\n --zest-color-standard-bg: #1e40af;\n --zest-color-standard-bg-hover: #1a35a0;\n --zest-color-standard-text: white;\n --zest-color-standard-border: #1e40af;\n\n --zest-color-success-bg: #059669;\n --zest-color-success-bg-hover: #047857;\n --zest-color-success-text: white;\n --zest-color-success-border: #059669;\n\n --zest-color-danger-bg: #dc2626;\n --zest-color-danger-bg-hover: #b91c1c;\n --zest-color-danger-text: white;\n --zest-color-danger-border: #dc2626;\n\n --zest-color-disabled-bg: #cbd5e1;\n --zest-color-disabled-bg-hover: #aeb9c4;\n --zest-color-disabled-text: #6b7280;\n --zest-color-disabled-border: #cbd5e1;\n\n --zest-color-icon-success: #10b981;\n --zest-color-icon-fail: #ef4444;\n}\n\n/* Dark mode adjustments via system preference */\n@media (prefers-color-scheme: dark) {\n :root {\n --zest-color-standard-bg: #3b82f6;\n --zest-color-standard-bg-hover: #2563eb;\n --zest-color-standard-text: white;\n --zest-color-standard-border: #3b82f6;\n\n --zest-color-success-bg: #34d399;\n --zest-color-success-bg-hover: #10b981;\n --zest-color-success-text: white;\n --zest-color-success-border: #34d399;\n\n --zest-color-danger-bg: #ef4444;\n --zest-color-danger-bg-hover: #dc2626;\n --zest-color-danger-text: white;\n --zest-color-danger-border: #ef4444;\n\n --zest-color-disabled-bg: #4b5563;\n --zest-color-disabled-bg-hover: #6b7280;\n --zest-color-disabled-text: #9ca3af;\n --zest-color-disabled-border: #4b5563;\n\n --zest-color-icon-success: #34d399;\n --zest-color-icon-fail: #ef4444;\n }\n}\n\n/* Theme override classes */\n.ZestButton-module_force-light__zZTIZ {\n --zest-color-standard-bg: #1e40af;\n --zest-color-standard-bg-hover: #1a35a0;\n --zest-color-standard-text: white;\n --zest-color-standard-border: #1e40af;\n\n --zest-color-success-bg: #059669;\n --zest-color-success-bg-hover: #047857;\n --zest-color-success-text: white;\n --zest-color-success-border: #059669;\n\n --zest-color-danger-bg: #dc2626;\n --zest-color-danger-bg-hover: #b91c1c;\n --zest-color-danger-text: white;\n --zest-color-danger-border: #dc2626;\n\n --zest-color-disabled-bg: #cbd5e1;\n --zest-color-disabled-bg-hover: #aeb9c4;\n --zest-color-disabled-text: #6b7280;\n --zest-color-disabled-border: #cbd5e1;\n\n --zest-color-icon-success: #10b981;\n --zest-color-icon-fail: #ef4444;\n}\n\n.ZestButton-module_force-dark__cx74D {\n --zest-color-standard-bg: #3b82f6;\n --zest-color-standard-bg-hover: #2563eb;\n --zest-color-standard-text: white;\n --zest-color-standard-border: #3b82f6;\n\n --zest-color-success-bg: #34d399;\n --zest-color-success-bg-hover: #10b981;\n --zest-color-success-text: white;\n --zest-color-success-border: #34d399;\n\n --zest-color-danger-bg: #ef4444;\n --zest-color-danger-bg-hover: #dc2626;\n --zest-color-danger-text: white;\n --zest-color-danger-border: #ef4444;\n\n --zest-color-disabled-bg: #4b5563;\n --zest-color-disabled-bg-hover: #6b7280;\n --zest-color-disabled-text: #9ca3af;\n --zest-color-disabled-border: #4b5563;\n\n --zest-color-icon-success: #34d399;\n --zest-color-icon-fail: #ef4444;\n}\n\n\n.ZestButton-module_button__KDafc {\n font-family: \"Segoe UI\", Roboto, sans-serif;\n font-weight: 600;\n border-radius: 8px;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n transition: background-color 0.2s ease, box-shadow 0.2s ease, color 0.2s ease, border-color 0.2s ease;\n position: relative;\n padding: 0.6em 1.2em;\n overflow: hidden;\n border: none; /* Default to no border, overridden by outline/dashed */\n}\n\n/* Base styles for different button styles */\n.ZestButton-module_solid__cu4tr {\n background-color: var(--zest-color-standard-bg);\n color: var(--zest-color-standard-text);\n}\n.ZestButton-module_solid__cu4tr:hover:not(:disabled) {\n background-color: var(--zest-color-standard-bg-hover);\n}\n\n.ZestButton-module_outline__esgLq {\n background-color: transparent;\n border: 2px solid var(--zest-color-standard-border);\n color: var(--zest-color-standard-border);\n}\n.ZestButton-module_outline__esgLq:hover:not(:disabled) {\n background-color: var(--zest-color-standard-bg);\n color: var(--zest-color-standard-text);\n}\n\n.ZestButton-module_text__8X1xD {\n background-color: transparent;\n border: none;\n color: var(--zest-color-standard-bg);\n}\n.ZestButton-module_text__8X1xD:hover:not(:disabled) {\n background-color: rgba(var(--zest-color-standard-bg-rgb, 30, 64, 175), 0.1); /* Fallback RGB for text hover */\n}\n\n.ZestButton-module_dashed__ebKYF {\n background-color: transparent;\n border: 2px dashed var(--zest-color-standard-border);\n color: var(--zest-color-standard-border);\n}\n.ZestButton-module_dashed__ebKYF:hover:not(:disabled) {\n background-color: rgba(var(--zest-color-standard-bg-rgb, 30, 64, 175), 0.1); /* Fallback RGB for dashed hover */\n}\n\n\n/* Variant overrides for solid style */\n.ZestButton-module_solid__cu4tr.ZestButton-module_standard__T3EGM { /* Already handled by .solid base */ }\n.ZestButton-module_solid__cu4tr.ZestButton-module_success__XEptA {\n background-color: var(--zest-color-success-bg);\n color: var(--zest-color-success-text);\n}\n.ZestButton-module_solid__cu4tr.ZestButton-module_success__XEptA:hover:not(:disabled) {\n background-color: var(--zest-color-success-bg-hover);\n}\n.ZestButton-module_solid__cu4tr.ZestButton-module_danger__nJpJ- {\n background-color: var(--zest-color-danger-bg);\n color: var(--zest-color-danger-text);\n}\n.ZestButton-module_solid__cu4tr.ZestButton-module_danger__nJpJ-:hover:not(:disabled) {\n background-color: var(--zest-color-danger-bg-hover);\n}\n\n/* Variant overrides for outline style */\n.ZestButton-module_outline__esgLq.ZestButton-module_standard__T3EGM { /* Already handled by .outline base */ }\n.ZestButton-module_outline__esgLq.ZestButton-module_success__XEptA {\n border-color: var(--zest-color-success-border);\n color: var(--zest-color-success-border);\n}\n.ZestButton-module_outline__esgLq.ZestButton-module_success__XEptA:hover:not(:disabled) {\n background-color: var(--zest-color-success-bg);\n color: var(--zest-color-success-text);\n}\n.ZestButton-module_outline__esgLq.ZestButton-module_danger__nJpJ- {\n border-color: var(--zest-color-danger-border);\n color: var(--zest-color-danger-border);\n}\n.ZestButton-module_outline__esgLq.ZestButton-module_danger__nJpJ-:hover:not(:disabled) {\n background-color: var(--zest-color-danger-bg);\n color: var(--zest-color-danger-text);\n}\n\n/* Variant overrides for text style */\n.ZestButton-module_text__8X1xD.ZestButton-module_standard__T3EGM { /* Already handled by .text base */ }\n.ZestButton-module_text__8X1xD.ZestButton-module_success__XEptA {\n color: var(--zest-color-success-bg);\n}\n.ZestButton-module_text__8X1xD.ZestButton-module_success__XEptA:hover:not(:disabled) {\n background-color: rgba(var(--zest-color-success-bg-rgb, 5, 150, 105), 0.1);\n}\n.ZestButton-module_text__8X1xD.ZestButton-module_danger__nJpJ- {\n color: var(--zest-color-danger-bg);\n}\n.ZestButton-module_text__8X1xD.ZestButton-module_danger__nJpJ-:hover:not(:disabled) {\n background-color: rgba(var(--zest-color-danger-bg-rgb, 220, 38, 38), 0.1);\n}\n\n/* Variant overrides for dashed style */\n.ZestButton-module_dashed__ebKYF.ZestButton-module_standard__T3EGM { /* Already handled by .dashed base */ }\n.ZestButton-module_dashed__ebKYF.ZestButton-module_success__XEptA {\n border-color: var(--zest-color-success-border);\n color: var(--zest-color-success-border);\n}\n.ZestButton-module_dashed__ebKYF.ZestButton-module_success__XEptA:hover:not(:disabled) {\n background-color: rgba(var(--zest-color-success-bg-rgb, 5, 150, 105), 0.1);\n}\n.ZestButton-module_dashed__ebKYF.ZestButton-module_danger__nJpJ- {\n border-color: var(--zest-color-danger-border);\n color: var(--zest-color-danger-border);\n}\n.ZestButton-module_dashed__ebKYF.ZestButton-module_danger__nJpJ-:hover:not(:disabled) {\n background-color: rgba(var(--zest-color-danger-bg-rgb, 220, 38, 38), 0.1);\n}\n\n\n/* Disabled state overrides for different button styles */\n.ZestButton-module_solid__cu4tr:disabled, .ZestButton-module_solid__cu4tr.ZestButton-module_disabled__gw6y3 {\n background-color: var(--zest-color-disabled-bg);\n color: var(--zest-color-disabled-text);\n border-color: var(--zest-color-disabled-border);\n}\n.ZestButton-module_outline__esgLq:disabled, .ZestButton-module_outline__esgLq.ZestButton-module_disabled__gw6y3 {\n background-color: transparent;\n border-color: var(--zest-color-disabled-border);\n color: var(--zest-color-disabled-text);\n}\n.ZestButton-module_text__8X1xD:disabled, .ZestButton-module_text__8X1xD.ZestButton-module_disabled__gw6y3 {\n background-color: transparent;\n color: var(--zest-color-disabled-text);\n}\n.ZestButton-module_dashed__ebKYF:disabled, .ZestButton-module_dashed__ebKYF.ZestButton-module_disabled__gw6y3 {\n background-color: transparent;\n border-color: var(--zest-color-disabled-border);\n color: var(--zest-color-disabled-text);\n}\n\n\n/* Layout */\n.ZestButton-module_stretch__CTLNw {\n width: 100%;\n}\n\n.ZestButton-module_sm__G1vAP {\n font-size: 0.85rem;\n padding: 0.4em 0.8em;\n}\n\n.ZestButton-module_md__Y-PMO {\n font-size: 1rem;\n padding: 0.6em 1.2em;\n}\n\n.ZestButton-module_lg__AQgdf {\n font-size: 1.125rem;\n padding: 0.8em 1.6em;\n}\n\n.ZestButton-module_inner__1j2Fr {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n position: relative;\n}\n\n.ZestButton-module_spinner__l2hLe {\n position: absolute;\n width: 1em;\n height: 1em;\n animation: ZestButton-module_spin__4asdw 0.75s linear infinite;\n color: currentColor; /* Inherit color from button text */\n}\n\n.ZestButton-module_content__hlea3 {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5em;\n}\n\n.ZestButton-module_label__8x263 {\n display: inline-block;\n}\n\n.ZestButton-module_icon__B3DFi {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n}\n\n/* Success + Fail Icons */\n.ZestButton-module_animatedCheck__8K4K- {\n width: 1.25em;\n height: 1.25em;\n color: var(--zest-color-icon-success);\n animation: ZestButton-module_fadeIn__iEave 0.25s ease-out;\n}\n\n.ZestButton-module_animatedX__KQnt7 {\n width: 1.25em;\n height: 1.25em;\n color: var(--zest-color-icon-fail);\n animation: ZestButton-module_fadeIn__iEave 0.25s ease-out;\n}\n\n/* Stroke animations */\n.ZestButton-module_animatedCheck__8K4K- path {\n stroke-dasharray: 24;\n stroke-dashoffset: 24;\n animation: ZestButton-module_drawCheck__3DyjT 0.4s ease-out forwards;\n}\n\n.ZestButton-module_animatedX__KQnt7 line {\n stroke-dasharray: 24;\n stroke-dashoffset: 24;\n animation: ZestButton-module_drawCheck__3DyjT 0.4s ease-out forwards;\n}\n\n/* New: apply spacing between left icon and text */\n.ZestButton-module_icon__B3DFi:first-child {\n margin-right: 0.7em;\n}\n\n/* Optional override for iconRight if needed */\n.ZestButton-module_icon__B3DFi:last-child {\n margin-left: 0.7em;\n}\n\n/* Animations */\n@keyframes ZestButton-module_spin__4asdw {\n to {\n transform: rotate(360deg);\n }\n}\n\n@keyframes ZestButton-module_drawCheck__3DyjT {\n to {\n stroke-dashoffset: 0;\n }\n}\n\n@keyframes ZestButton-module_fadeIn__iEave {\n from {\n opacity: 0;\n transform: scale(0.8);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n@keyframes ZestButton-module_shakeIt__ox-R3 {\n 0%,\n 100% {\n transform: translateX(0);\n }\n 20%,\n 60% {\n transform: translateX(-4px);\n }\n 40%,\n 80% {\n transform: translateX(4px);\n }\n}\n\n.ZestButton-module_shake__NtIjf {\n animation: ZestButton-module_shakeIt__ox-R3 0.4s ease;\n box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.6);\n}\n\n/* Mobile-first adjustments for hit area */\n@media (max-width: 768px) {\n .ZestButton-module_button__KDafc {\n min-height: 44px; /* Ensure a minimum touch target size for accessibility */\n }\n\n .ZestButton-module_sm__G1vAP {\n padding: 0.6em 1em; /* Increase padding for small buttons on mobile */\n }\n\n .ZestButton-module_md__Y-PMO {\n padding: 0.8em 1.4em; /* Slightly increase padding for medium buttons on mobile */\n }\n}\n\n";
1388
- var styles = {"force-light":"ZestButton-module_force-light__zZTIZ","force-dark":"ZestButton-module_force-dark__cx74D","button":"ZestButton-module_button__KDafc","solid":"ZestButton-module_solid__cu4tr","outline":"ZestButton-module_outline__esgLq","text":"ZestButton-module_text__8X1xD","dashed":"ZestButton-module_dashed__ebKYF","standard":"ZestButton-module_standard__T3EGM","success":"ZestButton-module_success__XEptA","danger":"ZestButton-module_danger__nJpJ-","disabled":"ZestButton-module_disabled__gw6y3","stretch":"ZestButton-module_stretch__CTLNw","sm":"ZestButton-module_sm__G1vAP","md":"ZestButton-module_md__Y-PMO","lg":"ZestButton-module_lg__AQgdf","inner":"ZestButton-module_inner__1j2Fr","spinner":"ZestButton-module_spinner__l2hLe","spin":"ZestButton-module_spin__4asdw","content":"ZestButton-module_content__hlea3","label":"ZestButton-module_label__8x263","icon":"ZestButton-module_icon__B3DFi","animatedCheck":"ZestButton-module_animatedCheck__8K4K-","fadeIn":"ZestButton-module_fadeIn__iEave","animatedX":"ZestButton-module_animatedX__KQnt7","drawCheck":"ZestButton-module_drawCheck__3DyjT","shake":"ZestButton-module_shake__NtIjf","shakeIt":"ZestButton-module_shakeIt__ox-R3"};
1388
+ var css_248z = "/* Styles/ZestButton.module.css */\r\n\r\n/* Define base variables for light mode */\r\n:root {\r\n --zest-color-standard-bg: #1e40af;\r\n --zest-color-standard-bg-hover: #1a35a0;\r\n --zest-color-standard-text: white;\r\n --zest-color-standard-border: #1e40af;\r\n\r\n --zest-color-success-bg: #059669;\r\n --zest-color-success-bg-hover: #047857;\r\n --zest-color-success-text: white;\r\n --zest-color-success-border: #059669;\r\n\r\n --zest-color-danger-bg: #dc2626;\r\n --zest-color-danger-bg-hover: #b91c1c;\r\n --zest-color-danger-text: white;\r\n --zest-color-danger-border: #dc2626;\r\n\r\n --zest-color-disabled-bg: #cbd5e1;\r\n --zest-color-disabled-bg-hover: #aeb9c4;\r\n --zest-color-disabled-text: #6b7280;\r\n --zest-color-disabled-border: #cbd5e1;\r\n\r\n --zest-color-icon-success: #10b981;\r\n --zest-color-icon-fail: #ef4444;\r\n}\r\n\r\n/* Dark mode adjustments via system preference */\r\n@media (prefers-color-scheme: dark) {\r\n :root {\r\n --zest-color-standard-bg: #3b82f6;\r\n --zest-color-standard-bg-hover: #2563eb;\r\n --zest-color-standard-text: white;\r\n --zest-color-standard-border: #3b82f6;\r\n\r\n --zest-color-success-bg: #34d399;\r\n --zest-color-success-bg-hover: #10b981;\r\n --zest-color-success-text: white;\r\n --zest-color-success-border: #34d399;\r\n\r\n --zest-color-danger-bg: #ef4444;\r\n --zest-color-danger-bg-hover: #dc2626;\r\n --zest-color-danger-text: white;\r\n --zest-color-danger-border: #ef4444;\r\n\r\n --zest-color-disabled-bg: #4b5563;\r\n --zest-color-disabled-bg-hover: #6b7280;\r\n --zest-color-disabled-text: #9ca3af;\r\n --zest-color-disabled-border: #4b5563;\r\n\r\n --zest-color-icon-success: #34d399;\r\n --zest-color-icon-fail: #ef4444;\r\n }\r\n}\r\n\r\n/* Theme override classes */\r\n.ZestButton-module_force-light__zZTIZ {\r\n --zest-color-standard-bg: #1e40af;\r\n --zest-color-standard-bg-hover: #1a35a0;\r\n --zest-color-standard-text: white;\r\n --zest-color-standard-border: #1e40af;\r\n\r\n --zest-color-success-bg: #059669;\r\n --zest-color-success-bg-hover: #047857;\r\n --zest-color-success-text: white;\r\n --zest-color-success-border: #059669;\r\n\r\n --zest-color-danger-bg: #dc2626;\r\n --zest-color-danger-bg-hover: #b91c1c;\r\n --zest-color-danger-text: white;\r\n --zest-color-danger-border: #dc2626;\r\n\r\n --zest-color-disabled-bg: #cbd5e1;\r\n --zest-color-disabled-bg-hover: #aeb9c4;\r\n --zest-color-disabled-text: #6b7280;\r\n --zest-color-disabled-border: #cbd5e1;\r\n\r\n --zest-color-icon-success: #10b981;\r\n --zest-color-icon-fail: #ef4444;\r\n}\r\n\r\n.ZestButton-module_force-dark__cx74D {\r\n --zest-color-standard-bg: #3b82f6;\r\n --zest-color-standard-bg-hover: #2563eb;\r\n --zest-color-standard-text: white;\r\n --zest-color-standard-border: #3b82f6;\r\n\r\n --zest-color-success-bg: #34d399;\r\n --zest-color-success-bg-hover: #10b981;\r\n --zest-color-success-text: white;\r\n --zest-color-success-border: #34d399;\r\n\r\n --zest-color-danger-bg: #ef4444;\r\n --zest-color-danger-bg-hover: #dc2626;\r\n --zest-color-danger-text: white;\r\n --zest-color-danger-border: #ef4444;\r\n\r\n --zest-color-disabled-bg: #4b5563;\r\n --zest-color-disabled-bg-hover: #6b7280;\r\n --zest-color-disabled-text: #9ca3af;\r\n --zest-color-disabled-border: #4b5563;\r\n\r\n --zest-color-icon-success: #34d399;\r\n --zest-color-icon-fail: #ef4444;\r\n}\r\n\r\n\r\n.ZestButton-module_button__KDafc {\r\n font-family: \"Segoe UI\", Roboto, sans-serif;\r\n font-weight: 600;\r\n border-radius: 8px;\r\n cursor: pointer;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n transition: background-color 0.2s ease, box-shadow 0.2s ease, color 0.2s ease, border-color 0.2s ease;\r\n position: relative;\r\n padding: 0.6em 1.2em;\r\n overflow: hidden;\r\n border: none; /* Default to no border, overridden by outline/dashed */\r\n}\r\n\r\n/* Base styles for different button styles */\r\n.ZestButton-module_solid__cu4tr {\r\n background-color: var(--zest-color-standard-bg);\r\n color: var(--zest-color-standard-text);\r\n}\r\n.ZestButton-module_solid__cu4tr:hover:not(:disabled) {\r\n background-color: var(--zest-color-standard-bg-hover);\r\n}\r\n\r\n.ZestButton-module_outline__esgLq {\r\n background-color: transparent;\r\n border: 2px solid var(--zest-color-standard-border);\r\n color: var(--zest-color-standard-border);\r\n}\r\n.ZestButton-module_outline__esgLq:hover:not(:disabled) {\r\n background-color: var(--zest-color-standard-bg);\r\n color: var(--zest-color-standard-text);\r\n}\r\n\r\n.ZestButton-module_text__8X1xD {\r\n background-color: transparent;\r\n border: none;\r\n color: var(--zest-color-standard-bg);\r\n}\r\n.ZestButton-module_text__8X1xD:hover:not(:disabled) {\r\n background-color: rgba(var(--zest-color-standard-bg-rgb, 30, 64, 175), 0.1); /* Fallback RGB for text hover */\r\n}\r\n\r\n.ZestButton-module_dashed__ebKYF {\r\n background-color: transparent;\r\n border: 2px dashed var(--zest-color-standard-border);\r\n color: var(--zest-color-standard-border);\r\n}\r\n.ZestButton-module_dashed__ebKYF:hover:not(:disabled) {\r\n background-color: rgba(var(--zest-color-standard-bg-rgb, 30, 64, 175), 0.1); /* Fallback RGB for dashed hover */\r\n}\r\n\r\n\r\n/* Variant overrides for solid style */\r\n.ZestButton-module_solid__cu4tr.ZestButton-module_standard__T3EGM { /* Already handled by .solid base */ }\r\n.ZestButton-module_solid__cu4tr.ZestButton-module_success__XEptA {\r\n background-color: var(--zest-color-success-bg);\r\n color: var(--zest-color-success-text);\r\n}\r\n.ZestButton-module_solid__cu4tr.ZestButton-module_success__XEptA:hover:not(:disabled) {\r\n background-color: var(--zest-color-success-bg-hover);\r\n}\r\n.ZestButton-module_solid__cu4tr.ZestButton-module_danger__nJpJ- {\r\n background-color: var(--zest-color-danger-bg);\r\n color: var(--zest-color-danger-text);\r\n}\r\n.ZestButton-module_solid__cu4tr.ZestButton-module_danger__nJpJ-:hover:not(:disabled) {\r\n background-color: var(--zest-color-danger-bg-hover);\r\n}\r\n\r\n/* Variant overrides for outline style */\r\n.ZestButton-module_outline__esgLq.ZestButton-module_standard__T3EGM { /* Already handled by .outline base */ }\r\n.ZestButton-module_outline__esgLq.ZestButton-module_success__XEptA {\r\n border-color: var(--zest-color-success-border);\r\n color: var(--zest-color-success-border);\r\n}\r\n.ZestButton-module_outline__esgLq.ZestButton-module_success__XEptA:hover:not(:disabled) {\r\n background-color: var(--zest-color-success-bg);\r\n color: var(--zest-color-success-text);\r\n}\r\n.ZestButton-module_outline__esgLq.ZestButton-module_danger__nJpJ- {\r\n border-color: var(--zest-color-danger-border);\r\n color: var(--zest-color-danger-border);\r\n}\r\n.ZestButton-module_outline__esgLq.ZestButton-module_danger__nJpJ-:hover:not(:disabled) {\r\n background-color: var(--zest-color-danger-bg);\r\n color: var(--zest-color-danger-text);\r\n}\r\n\r\n/* Variant overrides for text style */\r\n.ZestButton-module_text__8X1xD.ZestButton-module_standard__T3EGM { /* Already handled by .text base */ }\r\n.ZestButton-module_text__8X1xD.ZestButton-module_success__XEptA {\r\n color: var(--zest-color-success-bg);\r\n}\r\n.ZestButton-module_text__8X1xD.ZestButton-module_success__XEptA:hover:not(:disabled) {\r\n background-color: rgba(var(--zest-color-success-bg-rgb, 5, 150, 105), 0.1);\r\n}\r\n.ZestButton-module_text__8X1xD.ZestButton-module_danger__nJpJ- {\r\n color: var(--zest-color-danger-bg);\r\n}\r\n.ZestButton-module_text__8X1xD.ZestButton-module_danger__nJpJ-:hover:not(:disabled) {\r\n background-color: rgba(var(--zest-color-danger-bg-rgb, 220, 38, 38), 0.1);\r\n}\r\n\r\n/* Variant overrides for dashed style */\r\n.ZestButton-module_dashed__ebKYF.ZestButton-module_standard__T3EGM { /* Already handled by .dashed base */ }\r\n.ZestButton-module_dashed__ebKYF.ZestButton-module_success__XEptA {\r\n border-color: var(--zest-color-success-border);\r\n color: var(--zest-color-success-border);\r\n}\r\n.ZestButton-module_dashed__ebKYF.ZestButton-module_success__XEptA:hover:not(:disabled) {\r\n background-color: rgba(var(--zest-color-success-bg-rgb, 5, 150, 105), 0.1);\r\n}\r\n.ZestButton-module_dashed__ebKYF.ZestButton-module_danger__nJpJ- {\r\n border-color: var(--zest-color-danger-border);\r\n color: var(--zest-color-danger-border);\r\n}\r\n.ZestButton-module_dashed__ebKYF.ZestButton-module_danger__nJpJ-:hover:not(:disabled) {\r\n background-color: rgba(var(--zest-color-danger-bg-rgb, 220, 38, 38), 0.1);\r\n}\r\n\r\n\r\n/* Disabled state overrides for different button styles */\r\n.ZestButton-module_solid__cu4tr:disabled, .ZestButton-module_solid__cu4tr.ZestButton-module_disabled__gw6y3 {\r\n background-color: var(--zest-color-disabled-bg);\r\n color: var(--zest-color-disabled-text);\r\n border-color: var(--zest-color-disabled-border);\r\n}\r\n.ZestButton-module_outline__esgLq:disabled, .ZestButton-module_outline__esgLq.ZestButton-module_disabled__gw6y3 {\r\n background-color: transparent;\r\n border-color: var(--zest-color-disabled-border);\r\n color: var(--zest-color-disabled-text);\r\n}\r\n.ZestButton-module_text__8X1xD:disabled, .ZestButton-module_text__8X1xD.ZestButton-module_disabled__gw6y3 {\r\n background-color: transparent;\r\n color: var(--zest-color-disabled-text);\r\n}\r\n.ZestButton-module_dashed__ebKYF:disabled, .ZestButton-module_dashed__ebKYF.ZestButton-module_disabled__gw6y3 {\r\n background-color: transparent;\r\n border-color: var(--zest-color-disabled-border);\r\n color: var(--zest-color-disabled-text);\r\n}\r\n\r\n\r\n/* Layout */\r\n.ZestButton-module_stretch__CTLNw {\r\n width: 100%;\r\n}\r\n\r\n.ZestButton-module_sm__G1vAP {\r\n font-size: 0.85rem;\r\n padding: 0.4em 0.8em;\r\n}\r\n\r\n.ZestButton-module_md__Y-PMO {\r\n font-size: 1rem;\r\n padding: 0.6em 1.2em;\r\n}\r\n\r\n.ZestButton-module_lg__AQgdf {\r\n font-size: 1.125rem;\r\n padding: 0.8em 1.6em;\r\n}\r\n\r\n.ZestButton-module_inner__1j2Fr {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n position: relative;\r\n}\r\n\r\n.ZestButton-module_spinner__l2hLe {\r\n position: absolute;\r\n width: 1em;\r\n height: 1em;\r\n animation: ZestButton-module_spin__4asdw 0.75s linear infinite;\r\n color: currentColor; /* Inherit color from button text */\r\n}\r\n\r\n.ZestButton-module_content__hlea3 {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n gap: 0.5em;\r\n}\r\n\r\n.ZestButton-module_label__8x263 {\r\n display: inline-block;\r\n}\r\n\r\n.ZestButton-module_icon__B3DFi {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n\r\n/* Success + Fail Icons */\r\n.ZestButton-module_animatedCheck__8K4K- {\r\n width: 1.25em;\r\n height: 1.25em;\r\n color: var(--zest-color-icon-success);\r\n animation: ZestButton-module_fadeIn__iEave 0.25s ease-out;\r\n}\r\n\r\n.ZestButton-module_animatedX__KQnt7 {\r\n width: 1.25em;\r\n height: 1.25em;\r\n color: var(--zest-color-icon-fail);\r\n animation: ZestButton-module_fadeIn__iEave 0.25s ease-out;\r\n}\r\n\r\n/* Stroke animations */\r\n.ZestButton-module_animatedCheck__8K4K- path {\r\n stroke-dasharray: 24;\r\n stroke-dashoffset: 24;\r\n animation: ZestButton-module_drawCheck__3DyjT 0.4s ease-out forwards;\r\n}\r\n\r\n.ZestButton-module_animatedX__KQnt7 line {\r\n stroke-dasharray: 24;\r\n stroke-dashoffset: 24;\r\n animation: ZestButton-module_drawCheck__3DyjT 0.4s ease-out forwards;\r\n}\r\n\r\n/* New: apply spacing between left icon and text */\r\n.ZestButton-module_icon__B3DFi:first-child {\r\n margin-right: 0.7em;\r\n}\r\n\r\n/* Optional override for iconRight if needed */\r\n.ZestButton-module_icon__B3DFi:last-child {\r\n margin-left: 0.7em;\r\n}\r\n\r\n/* Animations */\r\n@keyframes ZestButton-module_spin__4asdw {\r\n to {\r\n transform: rotate(360deg);\r\n }\r\n}\r\n\r\n@keyframes ZestButton-module_drawCheck__3DyjT {\r\n to {\r\n stroke-dashoffset: 0;\r\n }\r\n}\r\n\r\n@keyframes ZestButton-module_fadeIn__iEave {\r\n from {\r\n opacity: 0;\r\n transform: scale(0.8);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: scale(1);\r\n }\r\n}\r\n\r\n@keyframes ZestButton-module_shakeIt__ox-R3 {\r\n 0%,\r\n 100% {\r\n transform: translateX(0);\r\n }\r\n 20%,\r\n 60% {\r\n transform: translateX(-4px);\r\n }\r\n 40%,\r\n 80% {\r\n transform: translateX(4px);\r\n }\r\n}\r\n\r\n.ZestButton-module_shake__NtIjf {\r\n animation: ZestButton-module_shakeIt__ox-R3 0.4s ease;\r\n box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.6);\r\n}\r\n\r\n/* Mobile-first adjustments for hit area */\r\n@media (max-width: 768px) {\r\n .ZestButton-module_button__KDafc {\r\n min-height: 44px; /* Ensure a minimum touch target size for accessibility */\r\n }\r\n\r\n .ZestButton-module_sm__G1vAP {\r\n padding: 0.6em 1em; /* Increase padding for small buttons on mobile */\r\n }\r\n\r\n .ZestButton-module_md__Y-PMO {\r\n padding: 0.8em 1.4em; /* Slightly increase padding for medium buttons on mobile */\r\n }\r\n}\r\n\r\n/* ------------------------------------------------------------------ */\r\n/* Split button (zest.dropdownOptions) */\r\n/* ------------------------------------------------------------------ */\r\n\r\n.ZestButton-module_splitButtonContainer__UPOGd {\r\n display: inline-flex;\r\n align-items: stretch;\r\n}\r\n\r\n.ZestButton-module_splitButtonMain__F0cHX {\r\n border-top-right-radius: 0;\r\n border-bottom-right-radius: 0;\r\n border-right: none;\r\n}\r\n\r\n.ZestButton-module_dropdownTrigger__wqBMN {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n border-top-left-radius: 0;\r\n border-bottom-left-radius: 0;\r\n padding: 0 0.7em;\r\n min-width: 2.4em;\r\n}\r\n\r\n/* .solid/.text have no border of their own — add an explicit divider so the\r\n two segments still read as one control. .outline/.dashed already carry a\r\n full border via their own base rule, which already serves as the divider. */\r\n.ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_solid__cu4tr {\r\n border-left: 1px solid rgba(255, 255, 255, 0.3);\r\n}\r\n.ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_text__8X1xD {\r\n border-left: 1px solid rgba(0, 0, 0, 0.15);\r\n}\r\n\r\n.ZestButton-module_dropdownChevron__GMkdW {\r\n width: 0.85em;\r\n height: 0.85em;\r\n transition: transform 0.2s ease;\r\n}\r\n\r\n.ZestButton-module_dropdownChevronOpen__-2CEj {\r\n transform: rotate(180deg);\r\n}\r\n\r\n.ZestButton-module_dropdownMenuContent__wIHv- {\r\n min-width: 180px;\r\n width: max-content;\r\n max-width: 320px;\r\n padding: 0.4rem;\r\n border-radius: 8px;\r\n background: var(--zest-color-menu-bg, #ffffff);\r\n color: var(--zest-color-menu-text, #1f2937);\r\n box-shadow: 0 8px 24px rgba(0, 0, 0, 0.16);\r\n border: 1px solid rgba(0, 0, 0, 0.08);\r\n z-index: 1000;\r\n}\r\n\r\n.ZestButton-module_force-dark__cx74D.ZestButton-module_dropdownMenuContent__wIHv-,\r\n.ZestButton-module_dropdownMenuContent__wIHv-.ZestButton-module_force-dark__cx74D {\r\n background: #1f2937;\r\n color: #f3f4f6;\r\n border-color: rgba(255, 255, 255, 0.12);\r\n}\r\n\r\n.ZestButton-module_dropdownMenuItem__7vFFl {\r\n display: flex;\r\n align-items: center;\r\n gap: 0.5em;\r\n padding: 0.55em 0.75em;\r\n border-radius: 6px;\r\n cursor: pointer;\r\n outline: none;\r\n font-family: \"Segoe UI\", Roboto, sans-serif;\r\n font-size: 0.9rem;\r\n}\r\n\r\n.ZestButton-module_dropdownMenuItem__7vFFl:hover,\r\n.ZestButton-module_dropdownMenuItem__7vFFl[data-highlighted] {\r\n background: rgba(0, 0, 0, 0.06);\r\n}\r\n\r\n.ZestButton-module_force-dark__cx74D .ZestButton-module_dropdownMenuItem__7vFFl:hover,\r\n.ZestButton-module_force-dark__cx74D .ZestButton-module_dropdownMenuItem__7vFFl[data-highlighted] {\r\n background: rgba(255, 255, 255, 0.1);\r\n}\r\n\r\n.ZestButton-module_dropdownMenuItem__7vFFl.ZestButton-module_disabled__gw6y3,\r\n.ZestButton-module_dropdownMenuItem__7vFFl[data-disabled] {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n}\r\n\r\n.ZestButton-module_dropdownMenuItemLabel__ArKh6 {\r\n flex: 1;\r\n}\r\n\r\n/* Mobile-first: chevron segment always meets the 44px touch-target minimum,\r\n independent of `size`, since it's a narrow tap target next to another one. */\r\n.ZestButton-module_dropdownTrigger__wqBMN {\r\n min-height: 44px;\r\n}\r\n\r\n@media (min-width: 769px) {\r\n /* Desktop-aware: once mis-tapping a neighbouring segment isn't a concern,\r\n let the chevron shrink to match the main button's own sizing. */\r\n .ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_sm__G1vAP {\r\n min-height: 0;\r\n padding: 0.4em 0.6em;\r\n }\r\n .ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_md__Y-PMO {\r\n min-height: 0;\r\n padding: 0.6em 0.7em;\r\n }\r\n .ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_lg__AQgdf {\r\n min-height: 0;\r\n padding: 0.8em 0.9em;\r\n }\r\n}\r\n\r\n";
1389
+ var styles = {"force-light":"ZestButton-module_force-light__zZTIZ","force-dark":"ZestButton-module_force-dark__cx74D","button":"ZestButton-module_button__KDafc","solid":"ZestButton-module_solid__cu4tr","outline":"ZestButton-module_outline__esgLq","text":"ZestButton-module_text__8X1xD","dashed":"ZestButton-module_dashed__ebKYF","standard":"ZestButton-module_standard__T3EGM","success":"ZestButton-module_success__XEptA","danger":"ZestButton-module_danger__nJpJ-","disabled":"ZestButton-module_disabled__gw6y3","stretch":"ZestButton-module_stretch__CTLNw","sm":"ZestButton-module_sm__G1vAP","md":"ZestButton-module_md__Y-PMO","lg":"ZestButton-module_lg__AQgdf","inner":"ZestButton-module_inner__1j2Fr","spinner":"ZestButton-module_spinner__l2hLe","spin":"ZestButton-module_spin__4asdw","content":"ZestButton-module_content__hlea3","label":"ZestButton-module_label__8x263","icon":"ZestButton-module_icon__B3DFi","animatedCheck":"ZestButton-module_animatedCheck__8K4K-","fadeIn":"ZestButton-module_fadeIn__iEave","animatedX":"ZestButton-module_animatedX__KQnt7","drawCheck":"ZestButton-module_drawCheck__3DyjT","shake":"ZestButton-module_shake__NtIjf","shakeIt":"ZestButton-module_shakeIt__ox-R3","splitButtonContainer":"ZestButton-module_splitButtonContainer__UPOGd","splitButtonMain":"ZestButton-module_splitButtonMain__F0cHX","dropdownTrigger":"ZestButton-module_dropdownTrigger__wqBMN","dropdownChevron":"ZestButton-module_dropdownChevron__GMkdW","dropdownChevronOpen":"ZestButton-module_dropdownChevronOpen__-2CEj","dropdownMenuContent":"ZestButton-module_dropdownMenuContent__wIHv-","dropdownMenuItem":"ZestButton-module_dropdownMenuItem__7vFFl","dropdownMenuItemLabel":"ZestButton-module_dropdownMenuItemLabel__ArKh6"};
1389
1390
  styleInject(css_248z);
1390
1391
 
1391
1392
  // Create the Zest Context with a default empty configuration
@@ -1738,12 +1739,136 @@ const useThemeDetection = () => {
1738
1739
  return systemTheme;
1739
1740
  };
1740
1741
 
1742
+ const AnimatedCheckmark$1 = () => (jsxRuntimeExports.jsx("svg", { className: styles.animatedCheck, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M5 13l4 4L19 7" }) }));
1743
+ const AnimatedX$1 = () => (jsxRuntimeExports.jsxs("svg", { className: styles.animatedX, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M6 6L18 18" }), jsxRuntimeExports.jsx("path", { d: "M6 18L18 6" })] }));
1744
+ const ZestDropdownMenuItem = ({ option, disabled: externallyDisabled = false, onBusyChange, }) => {
1745
+ const { label, icon, disabled: optionDisabled = false, onClick, busyOptions = {}, successOptions = {}, confirmOptions, } = option;
1746
+ const { handleInternally, minBusyDurationMs, showCheckmark, showFailIcon, internalBusy, wasSuccessful, wasFailed, startBusy, endBusy, } = useBusyState({ busyOptions, successOptions });
1747
+ const { awaitingConfirm, currentChildren, startConfirmation, stopConfirmation } = useConfirmation({
1748
+ confirmOptions,
1749
+ originalChildren: label,
1750
+ onConfirmFail: () => endBusy(false),
1751
+ });
1752
+ useEffect(() => {
1753
+ onBusyChange?.(internalBusy);
1754
+ }, [internalBusy, onBusyChange]);
1755
+ const isDisabled = externallyDisabled || optionDisabled || internalBusy;
1756
+ const handleActivate = async (e) => {
1757
+ if (handleInternally && typeof onClick === "function") {
1758
+ try {
1759
+ startBusy();
1760
+ const startTime = Date.now();
1761
+ await onClick(e);
1762
+ const elapsed = Date.now() - startTime;
1763
+ const remaining = Math.max(minBusyDurationMs - elapsed, 0);
1764
+ if (remaining > 0) {
1765
+ await new Promise((resolve) => setTimeout(resolve, remaining));
1766
+ }
1767
+ endBusy(true);
1768
+ }
1769
+ catch (err) {
1770
+ console.error(err);
1771
+ endBusy(false);
1772
+ }
1773
+ }
1774
+ else if (onClick) {
1775
+ onClick(e);
1776
+ }
1777
+ };
1778
+ const handleSelect = (e) => {
1779
+ if (isDisabled) {
1780
+ e.preventDefault();
1781
+ return;
1782
+ }
1783
+ if (awaitingConfirm) {
1784
+ // Keep the menu open through the confirm step; only the real
1785
+ // activation (below) decides whether the menu is allowed to close.
1786
+ e.preventDefault();
1787
+ stopConfirmation();
1788
+ void handleActivate(e);
1789
+ return;
1790
+ }
1791
+ if (confirmOptions) {
1792
+ e.preventDefault();
1793
+ if (!onClick) {
1794
+ console.warn("ZestButton dropdown item: 'confirmOptions' provided but 'onClick' is missing.");
1795
+ }
1796
+ startConfirmation();
1797
+ return;
1798
+ }
1799
+ if (handleInternally) {
1800
+ // Busy items keep the row open to show progress; Radix's default
1801
+ // close-on-select would hide the spinner/checkmark/shake feedback.
1802
+ e.preventDefault();
1803
+ void handleActivate(e);
1804
+ return;
1805
+ }
1806
+ // Plain synchronous item: let Radix close the menu as it normally would.
1807
+ void handleActivate(e);
1808
+ };
1809
+ const renderIcon = () => {
1810
+ if (internalBusy) {
1811
+ return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(FaSpinner, { className: styles.spinner }) }));
1812
+ }
1813
+ if (wasSuccessful && showCheckmark) {
1814
+ return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(AnimatedCheckmark$1, {}) }));
1815
+ }
1816
+ if (wasFailed && showFailIcon) {
1817
+ return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(AnimatedX$1, {}) }));
1818
+ }
1819
+ if (icon) {
1820
+ return jsxRuntimeExports.jsx("span", { className: styles.icon, children: icon });
1821
+ }
1822
+ return null;
1823
+ };
1824
+ return (jsxRuntimeExports.jsxs(DropdownMenu.Item, { className: [
1825
+ styles.dropdownMenuItem,
1826
+ isDisabled ? styles.disabled : "",
1827
+ wasFailed ? styles.shake : "",
1828
+ ]
1829
+ .join(" ")
1830
+ .trim(), disabled: isDisabled, onSelect: handleSelect, children: [renderIcon(), jsxRuntimeExports.jsx("span", { className: styles.dropdownMenuItemLabel, children: currentChildren })] }));
1831
+ };
1832
+
1833
+ const ZestDropdownMenu = ({ options, ariaLabel, open, onOpenChange, disabled = false, onAnyItemBusyChange, variant, size, buttonStyle, effectiveTheme, }) => {
1834
+ const busyKeysRef = useRef(new Set());
1835
+ const handleItemBusyChange = useCallback((key, busy) => {
1836
+ const busyKeys = busyKeysRef.current;
1837
+ const wasAnyBusy = busyKeys.size > 0;
1838
+ if (busy) {
1839
+ busyKeys.add(key);
1840
+ }
1841
+ else {
1842
+ busyKeys.delete(key);
1843
+ }
1844
+ const isAnyBusy = busyKeys.size > 0;
1845
+ if (isAnyBusy !== wasAnyBusy) {
1846
+ onAnyItemBusyChange?.(isAnyBusy);
1847
+ }
1848
+ }, [onAnyItemBusyChange]);
1849
+ return (jsxRuntimeExports.jsxs(DropdownMenu.Root, { open: open, onOpenChange: onOpenChange, modal: false, children: [jsxRuntimeExports.jsx(DropdownMenu.Trigger, { asChild: true, disabled: disabled, children: jsxRuntimeExports.jsx("button", { type: "button", "aria-label": ariaLabel, disabled: disabled, className: [
1850
+ styles.dropdownTrigger,
1851
+ styles[buttonStyle],
1852
+ styles[variant],
1853
+ styles[size],
1854
+ disabled ? styles.disabled : "",
1855
+ effectiveTheme === "light" ? styles["force-light"] : styles["force-dark"],
1856
+ ]
1857
+ .join(" ")
1858
+ .trim(), children: jsxRuntimeExports.jsx(FaChevronDown, { className: [styles.dropdownChevron, open ? styles.dropdownChevronOpen : ""]
1859
+ .join(" ")
1860
+ .trim() }) }) }), jsxRuntimeExports.jsx(DropdownMenu.Portal, { children: jsxRuntimeExports.jsx(DropdownMenu.Content, { className: [
1861
+ styles.dropdownMenuContent,
1862
+ effectiveTheme === "light" ? styles["force-light"] : styles["force-dark"],
1863
+ ].join(" "), sideOffset: 4, align: "end", collisionPadding: 8, children: options.map((option, index) => (jsxRuntimeExports.jsx(ZestDropdownMenuItem, { option: option, disabled: disabled, onBusyChange: (busy) => handleItemBusyChange(option.key ?? index, busy) }, option.key ?? index))) }) })] }));
1864
+ };
1865
+
1741
1866
  // --- Components ---
1742
1867
  const AnimatedCheckmark = () => (jsxRuntimeExports.jsx("svg", { className: styles.animatedCheck, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: jsxRuntimeExports.jsx("path", { d: "M5 13l4 4L19 7" }) }));
1743
1868
  const AnimatedX = () => (jsxRuntimeExports.jsxs("svg", { className: styles.animatedX, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M6 6L18 18" }), jsxRuntimeExports.jsx("path", { d: "M6 18L18 6" })] }));
1744
1869
  const ZestButton = ({ className = "", disabled, children, onClick, zest: localZestProps, ...props }) => {
1745
1870
  const effectiveZestConfig = useZestConfig(localZestProps);
1746
- const { visualOptions = {}, busyOptions = {}, successOptions = {}, confirmOptions, isDefault = false, theme = 'system', buttonStyle = 'solid', } = effectiveZestConfig;
1871
+ const { visualOptions = {}, busyOptions = {}, successOptions = {}, confirmOptions, isDefault = false, theme = 'system', buttonStyle = 'solid', dropdownOptions, dropdownAriaLabel = "More options", } = effectiveZestConfig;
1747
1872
  const { variant = "standard", size = "md", stretch = false, iconLeft, iconRight, } = visualOptions;
1748
1873
  const { handleInternally, minBusyDurationMs, preventRageClick, showCheckmark, showFailIcon, internalBusy, wasSuccessful, wasFailed, startBusy, endBusy, } = useBusyState({ busyOptions, successOptions });
1749
1874
  const { awaitingConfirm, currentChildren, startConfirmation, stopConfirmation, } = useConfirmation({
@@ -1754,6 +1879,9 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1754
1879
  const buttonRef = useRef(null);
1755
1880
  const systemTheme = useThemeDetection();
1756
1881
  const effectiveTheme = theme === 'system' ? systemTheme : theme;
1882
+ const hasDropdown = Boolean(dropdownOptions && dropdownOptions.length > 0);
1883
+ const [dropdownOpen, setDropdownOpen] = useState(false);
1884
+ const [anyDropdownItemBusy, setAnyDropdownItemBusy] = useState(false);
1757
1885
  const effectiveBusy = typeof props["aria-busy"] === "boolean"
1758
1886
  ? Boolean(props["aria-busy"])
1759
1887
  : handleInternally
@@ -1761,7 +1889,8 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1761
1889
  : false;
1762
1890
  const isDisabled = disabled ||
1763
1891
  effectiveBusy ||
1764
- (preventRageClick && (wasSuccessful || wasFailed));
1892
+ (preventRageClick && (wasSuccessful || wasFailed)) ||
1893
+ anyDropdownItemBusy;
1765
1894
  const handleClick = async (e) => {
1766
1895
  if (preventRageClick && internalBusy)
1767
1896
  return;
@@ -1803,7 +1932,7 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1803
1932
  }
1804
1933
  };
1805
1934
  useEffect(() => {
1806
- if (!isDefault || isDisabled)
1935
+ if (!isDefault || isDisabled || dropdownOpen)
1807
1936
  return;
1808
1937
  const listener = (e) => {
1809
1938
  const target = e.target;
@@ -1820,7 +1949,7 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1820
1949
  };
1821
1950
  document.addEventListener("keydown", listener);
1822
1951
  return () => document.removeEventListener("keydown", listener);
1823
- }, [isDefault, isDisabled]);
1952
+ }, [isDefault, isDisabled, dropdownOpen]);
1824
1953
  const renderLeftIcon = () => {
1825
1954
  if (effectiveBusy) {
1826
1955
  return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(FaSpinner, { className: styles.spinner }) }));
@@ -1836,7 +1965,7 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1836
1965
  }
1837
1966
  return null;
1838
1967
  };
1839
- return (jsxRuntimeExports.jsx("button", { ref: buttonRef, className: [
1968
+ const buttonElement = (jsxRuntimeExports.jsx("button", { ref: buttonRef, className: [
1840
1969
  styles.button,
1841
1970
  styles[buttonStyle],
1842
1971
  styles[variant],
@@ -1845,13 +1974,18 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1845
1974
  isDisabled ? styles.disabled : "",
1846
1975
  wasFailed ? styles.shake : "",
1847
1976
  effectiveTheme === 'light' ? styles['force-light'] : styles['force-dark'],
1977
+ hasDropdown ? styles.splitButtonMain : "",
1848
1978
  className,
1849
1979
  ].join(" "), disabled: isDisabled, "aria-busy": effectiveBusy, onClick: handleConfirmClick, ...props, children: jsxRuntimeExports.jsxs("span", { className: styles.inner, children: [renderLeftIcon(), jsxRuntimeExports.jsxs("span", { className: styles.content, children: [currentChildren, iconRight && jsxRuntimeExports.jsx("span", { className: styles.icon, children: iconRight })] })] }) }));
1980
+ if (!hasDropdown) {
1981
+ return buttonElement;
1982
+ }
1983
+ return (jsxRuntimeExports.jsxs("div", { className: styles.splitButtonContainer, children: [buttonElement, jsxRuntimeExports.jsx(ZestDropdownMenu, { options: dropdownOptions, ariaLabel: dropdownAriaLabel, open: dropdownOpen, onOpenChange: setDropdownOpen, disabled: isDisabled, onAnyItemBusyChange: setAnyDropdownItemBusy, variant: variant, size: size, buttonStyle: buttonStyle, effectiveTheme: effectiveTheme })] }));
1850
1984
  };
1851
1985
 
1852
1986
  const ZestButtonConfigProvider = ({ config, children }) => {
1853
1987
  return (jsxRuntimeExports.jsx(ZestButtonConfigContext.Provider, { value: config, children: children }));
1854
1988
  };
1855
1989
 
1856
- export { ZestButton, ZestButtonConfigProvider, useZestButtonConfig };
1990
+ export { ZestButtonConfigProvider, ZestButton as default, useZestButtonConfig };
1857
1991
  //# sourceMappingURL=index.esm.js.map