jattac.libs.web.zest-button 1.3.0 → 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.
@@ -19,7 +19,7 @@ interface VisualOptions {
19
19
  /**
20
20
  * Behavior during async operations
21
21
  */
22
- interface BusyOptions {
22
+ export interface BusyOptions {
23
23
  handleInternally?: boolean;
24
24
  preventRageClick?: boolean;
25
25
  minBusyDurationMs?: number;
@@ -27,7 +27,7 @@ interface BusyOptions {
27
27
  /**
28
28
  * Behavior after a successful or failed click
29
29
  */
30
- interface SuccessOptions {
30
+ export interface SuccessOptions {
31
31
  showCheckmark?: boolean;
32
32
  showFailIcon?: boolean;
33
33
  autoResetAfterMs?: number;
@@ -36,6 +36,21 @@ export interface ConfirmOptions {
36
36
  displayLabel: string;
37
37
  timeoutSecs: number;
38
38
  }
39
+ /**
40
+ * A single secondary action in a ZestButton's dropdown menu. Runs through the
41
+ * same busy/confirm machinery as the main button, independently per item.
42
+ */
43
+ export interface ZestDropdownOption {
44
+ key?: string;
45
+ label: React.ReactNode;
46
+ icon?: React.ReactNode;
47
+ disabled?: boolean;
48
+ semanticType?: SemanticType;
49
+ onClick?: (e: Event) => void | Promise<void>;
50
+ busyOptions?: BusyOptions;
51
+ successOptions?: SuccessOptions;
52
+ confirmOptions?: ConfirmOptions;
53
+ }
39
54
  export interface ZestCustomProps {
40
55
  visualOptions?: VisualOptions;
41
56
  busyOptions?: BusyOptions;
@@ -45,6 +60,8 @@ export interface ZestCustomProps {
45
60
  theme?: ZestTheme;
46
61
  buttonStyle?: ZestButtonStyle;
47
62
  semanticType?: SemanticType;
63
+ dropdownOptions?: ZestDropdownOption[];
64
+ dropdownAriaLabel?: string;
48
65
  }
49
66
  /**
50
67
  * All supported props
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+ import { ZestDropdownOption, ZestVariant, ZestSize, ZestButtonStyle } from "./ZestButton";
3
+ export interface ZestDropdownMenuProps {
4
+ options: ZestDropdownOption[];
5
+ ariaLabel: string;
6
+ open: boolean;
7
+ onOpenChange: (open: boolean) => void;
8
+ disabled?: boolean;
9
+ onAnyItemBusyChange?: (busy: boolean) => void;
10
+ variant: ZestVariant;
11
+ size: ZestSize;
12
+ buttonStyle: ZestButtonStyle;
13
+ effectiveTheme: "light" | "dark";
14
+ }
15
+ declare const ZestDropdownMenu: React.FC<ZestDropdownMenuProps>;
16
+ export default ZestDropdownMenu;
@@ -0,0 +1,9 @@
1
+ import React from "react";
2
+ import { ZestDropdownOption } from "./ZestButton";
3
+ export interface ZestDropdownMenuItemProps {
4
+ option: ZestDropdownOption;
5
+ disabled?: boolean;
6
+ onBusyChange?: (busy: boolean) => void;
7
+ }
8
+ declare const ZestDropdownMenuItem: React.FC<ZestDropdownMenuItemProps>;
9
+ export default ZestDropdownMenuItem;
package/dist/index.cjs.js CHANGED
@@ -5,6 +5,26 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var require$$0 = require('react');
6
6
  var fa6 = require('react-icons/fa6');
7
7
  var fa = require('react-icons/fa');
8
+ var DropdownMenu = require('@radix-ui/react-dropdown-menu');
9
+
10
+ function _interopNamespaceDefault(e) {
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var DropdownMenu__namespace = /*#__PURE__*/_interopNamespaceDefault(DropdownMenu);
8
28
 
9
29
  var jsxRuntime = {exports: {}};
10
30
 
@@ -1388,8 +1408,8 @@ function styleInject(css, ref) {
1388
1408
  }
1389
1409
  }
1390
1410
 
1391
- 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";
1392
- 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"};
1411
+ 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";
1412
+ 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"};
1393
1413
  styleInject(css_248z);
1394
1414
 
1395
1415
  // Create the Zest Context with a default empty configuration
@@ -1742,12 +1762,136 @@ const useThemeDetection = () => {
1742
1762
  return systemTheme;
1743
1763
  };
1744
1764
 
1765
+ 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" }) }));
1766
+ 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" })] }));
1767
+ const ZestDropdownMenuItem = ({ option, disabled: externallyDisabled = false, onBusyChange, }) => {
1768
+ const { label, icon, disabled: optionDisabled = false, onClick, busyOptions = {}, successOptions = {}, confirmOptions, } = option;
1769
+ const { handleInternally, minBusyDurationMs, showCheckmark, showFailIcon, internalBusy, wasSuccessful, wasFailed, startBusy, endBusy, } = useBusyState({ busyOptions, successOptions });
1770
+ const { awaitingConfirm, currentChildren, startConfirmation, stopConfirmation } = useConfirmation({
1771
+ confirmOptions,
1772
+ originalChildren: label,
1773
+ onConfirmFail: () => endBusy(false),
1774
+ });
1775
+ require$$0.useEffect(() => {
1776
+ onBusyChange?.(internalBusy);
1777
+ }, [internalBusy, onBusyChange]);
1778
+ const isDisabled = externallyDisabled || optionDisabled || internalBusy;
1779
+ const handleActivate = async (e) => {
1780
+ if (handleInternally && typeof onClick === "function") {
1781
+ try {
1782
+ startBusy();
1783
+ const startTime = Date.now();
1784
+ await onClick(e);
1785
+ const elapsed = Date.now() - startTime;
1786
+ const remaining = Math.max(minBusyDurationMs - elapsed, 0);
1787
+ if (remaining > 0) {
1788
+ await new Promise((resolve) => setTimeout(resolve, remaining));
1789
+ }
1790
+ endBusy(true);
1791
+ }
1792
+ catch (err) {
1793
+ console.error(err);
1794
+ endBusy(false);
1795
+ }
1796
+ }
1797
+ else if (onClick) {
1798
+ onClick(e);
1799
+ }
1800
+ };
1801
+ const handleSelect = (e) => {
1802
+ if (isDisabled) {
1803
+ e.preventDefault();
1804
+ return;
1805
+ }
1806
+ if (awaitingConfirm) {
1807
+ // Keep the menu open through the confirm step; only the real
1808
+ // activation (below) decides whether the menu is allowed to close.
1809
+ e.preventDefault();
1810
+ stopConfirmation();
1811
+ void handleActivate(e);
1812
+ return;
1813
+ }
1814
+ if (confirmOptions) {
1815
+ e.preventDefault();
1816
+ if (!onClick) {
1817
+ console.warn("ZestButton dropdown item: 'confirmOptions' provided but 'onClick' is missing.");
1818
+ }
1819
+ startConfirmation();
1820
+ return;
1821
+ }
1822
+ if (handleInternally) {
1823
+ // Busy items keep the row open to show progress; Radix's default
1824
+ // close-on-select would hide the spinner/checkmark/shake feedback.
1825
+ e.preventDefault();
1826
+ void handleActivate(e);
1827
+ return;
1828
+ }
1829
+ // Plain synchronous item: let Radix close the menu as it normally would.
1830
+ void handleActivate(e);
1831
+ };
1832
+ const renderIcon = () => {
1833
+ if (internalBusy) {
1834
+ return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(fa6.FaSpinner, { className: styles.spinner }) }));
1835
+ }
1836
+ if (wasSuccessful && showCheckmark) {
1837
+ return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(AnimatedCheckmark$1, {}) }));
1838
+ }
1839
+ if (wasFailed && showFailIcon) {
1840
+ return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(AnimatedX$1, {}) }));
1841
+ }
1842
+ if (icon) {
1843
+ return jsxRuntimeExports.jsx("span", { className: styles.icon, children: icon });
1844
+ }
1845
+ return null;
1846
+ };
1847
+ return (jsxRuntimeExports.jsxs(DropdownMenu__namespace.Item, { className: [
1848
+ styles.dropdownMenuItem,
1849
+ isDisabled ? styles.disabled : "",
1850
+ wasFailed ? styles.shake : "",
1851
+ ]
1852
+ .join(" ")
1853
+ .trim(), disabled: isDisabled, onSelect: handleSelect, children: [renderIcon(), jsxRuntimeExports.jsx("span", { className: styles.dropdownMenuItemLabel, children: currentChildren })] }));
1854
+ };
1855
+
1856
+ const ZestDropdownMenu = ({ options, ariaLabel, open, onOpenChange, disabled = false, onAnyItemBusyChange, variant, size, buttonStyle, effectiveTheme, }) => {
1857
+ const busyKeysRef = require$$0.useRef(new Set());
1858
+ const handleItemBusyChange = require$$0.useCallback((key, busy) => {
1859
+ const busyKeys = busyKeysRef.current;
1860
+ const wasAnyBusy = busyKeys.size > 0;
1861
+ if (busy) {
1862
+ busyKeys.add(key);
1863
+ }
1864
+ else {
1865
+ busyKeys.delete(key);
1866
+ }
1867
+ const isAnyBusy = busyKeys.size > 0;
1868
+ if (isAnyBusy !== wasAnyBusy) {
1869
+ onAnyItemBusyChange?.(isAnyBusy);
1870
+ }
1871
+ }, [onAnyItemBusyChange]);
1872
+ return (jsxRuntimeExports.jsxs(DropdownMenu__namespace.Root, { open: open, onOpenChange: onOpenChange, modal: false, children: [jsxRuntimeExports.jsx(DropdownMenu__namespace.Trigger, { asChild: true, disabled: disabled, children: jsxRuntimeExports.jsx("button", { type: "button", "aria-label": ariaLabel, disabled: disabled, className: [
1873
+ styles.dropdownTrigger,
1874
+ styles[buttonStyle],
1875
+ styles[variant],
1876
+ styles[size],
1877
+ disabled ? styles.disabled : "",
1878
+ effectiveTheme === "light" ? styles["force-light"] : styles["force-dark"],
1879
+ ]
1880
+ .join(" ")
1881
+ .trim(), children: jsxRuntimeExports.jsx(fa6.FaChevronDown, { className: [styles.dropdownChevron, open ? styles.dropdownChevronOpen : ""]
1882
+ .join(" ")
1883
+ .trim() }) }) }), jsxRuntimeExports.jsx(DropdownMenu__namespace.Portal, { children: jsxRuntimeExports.jsx(DropdownMenu__namespace.Content, { className: [
1884
+ styles.dropdownMenuContent,
1885
+ effectiveTheme === "light" ? styles["force-light"] : styles["force-dark"],
1886
+ ].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))) }) })] }));
1887
+ };
1888
+
1745
1889
  // --- Components ---
1746
1890
  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" }) }));
1747
1891
  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" })] }));
1748
1892
  const ZestButton = ({ className = "", disabled, children, onClick, zest: localZestProps, ...props }) => {
1749
1893
  const effectiveZestConfig = useZestConfig(localZestProps);
1750
- const { visualOptions = {}, busyOptions = {}, successOptions = {}, confirmOptions, isDefault = false, theme = 'system', buttonStyle = 'solid', } = effectiveZestConfig;
1894
+ const { visualOptions = {}, busyOptions = {}, successOptions = {}, confirmOptions, isDefault = false, theme = 'system', buttonStyle = 'solid', dropdownOptions, dropdownAriaLabel = "More options", } = effectiveZestConfig;
1751
1895
  const { variant = "standard", size = "md", stretch = false, iconLeft, iconRight, } = visualOptions;
1752
1896
  const { handleInternally, minBusyDurationMs, preventRageClick, showCheckmark, showFailIcon, internalBusy, wasSuccessful, wasFailed, startBusy, endBusy, } = useBusyState({ busyOptions, successOptions });
1753
1897
  const { awaitingConfirm, currentChildren, startConfirmation, stopConfirmation, } = useConfirmation({
@@ -1758,6 +1902,9 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1758
1902
  const buttonRef = require$$0.useRef(null);
1759
1903
  const systemTheme = useThemeDetection();
1760
1904
  const effectiveTheme = theme === 'system' ? systemTheme : theme;
1905
+ const hasDropdown = Boolean(dropdownOptions && dropdownOptions.length > 0);
1906
+ const [dropdownOpen, setDropdownOpen] = require$$0.useState(false);
1907
+ const [anyDropdownItemBusy, setAnyDropdownItemBusy] = require$$0.useState(false);
1761
1908
  const effectiveBusy = typeof props["aria-busy"] === "boolean"
1762
1909
  ? Boolean(props["aria-busy"])
1763
1910
  : handleInternally
@@ -1765,7 +1912,8 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1765
1912
  : false;
1766
1913
  const isDisabled = disabled ||
1767
1914
  effectiveBusy ||
1768
- (preventRageClick && (wasSuccessful || wasFailed));
1915
+ (preventRageClick && (wasSuccessful || wasFailed)) ||
1916
+ anyDropdownItemBusy;
1769
1917
  const handleClick = async (e) => {
1770
1918
  if (preventRageClick && internalBusy)
1771
1919
  return;
@@ -1807,7 +1955,7 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1807
1955
  }
1808
1956
  };
1809
1957
  require$$0.useEffect(() => {
1810
- if (!isDefault || isDisabled)
1958
+ if (!isDefault || isDisabled || dropdownOpen)
1811
1959
  return;
1812
1960
  const listener = (e) => {
1813
1961
  const target = e.target;
@@ -1824,7 +1972,7 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1824
1972
  };
1825
1973
  document.addEventListener("keydown", listener);
1826
1974
  return () => document.removeEventListener("keydown", listener);
1827
- }, [isDefault, isDisabled]);
1975
+ }, [isDefault, isDisabled, dropdownOpen]);
1828
1976
  const renderLeftIcon = () => {
1829
1977
  if (effectiveBusy) {
1830
1978
  return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(fa6.FaSpinner, { className: styles.spinner }) }));
@@ -1840,7 +1988,7 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1840
1988
  }
1841
1989
  return null;
1842
1990
  };
1843
- return (jsxRuntimeExports.jsx("button", { ref: buttonRef, className: [
1991
+ const buttonElement = (jsxRuntimeExports.jsx("button", { ref: buttonRef, className: [
1844
1992
  styles.button,
1845
1993
  styles[buttonStyle],
1846
1994
  styles[variant],
@@ -1849,8 +1997,13 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
1849
1997
  isDisabled ? styles.disabled : "",
1850
1998
  wasFailed ? styles.shake : "",
1851
1999
  effectiveTheme === 'light' ? styles['force-light'] : styles['force-dark'],
2000
+ hasDropdown ? styles.splitButtonMain : "",
1852
2001
  className,
1853
2002
  ].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 })] })] }) }));
2003
+ if (!hasDropdown) {
2004
+ return buttonElement;
2005
+ }
2006
+ 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 })] }));
1854
2007
  };
1855
2008
 
1856
2009
  const ZestButtonConfigProvider = ({ config, children }) => {