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/ZestButton.d.ts +19 -2
- package/dist/ZestDropdownMenu.d.ts +16 -0
- package/dist/ZestDropdownMenuItem.d.ts +9 -0
- package/dist/index.cjs.js +163 -8
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +19 -2
- package/dist/index.esm.js +143 -9
- package/dist/index.esm.js.map +1 -1
- package/docs/e2e/critical-paths.md +75 -0
- package/docs/features/zest-button-dropdown-options/BRS.md +213 -0
- package/docs/guidelines/AI_ARCHITECTURE.md +455 -0
- package/docs/guidelines/AI_BRS.md +435 -0
- package/docs/guidelines/AI_CODE_REVIEW.md +198 -0
- package/docs/guidelines/AI_E2E_TESTING.md +227 -0
- package/docs/guidelines/AI_GIT_WORKFLOW.md +595 -0
- package/docs/guidelines/AI_KNOWLEDGE.md +213 -0
- package/docs/guidelines/AI_PITFALLS.md +245 -0
- package/docs/guidelines/AI_STYLE_GUIDE.md +162 -0
- package/docs/guidelines/AI_TESTING.md +275 -0
- package/docs/guidelines/AI_TEST_CONFIGURATION.md +529 -0
- package/docs/guidelines/AI_WORKFLOW.md +442 -0
- package/docs/guidelines/AI_WORKFLOW_TRIGGERS.md +222 -0
- package/docs/guidelines/ai-knowledge.md +154 -0
- package/docs/guidelines/decision-log.md +149 -0
- package/package.json +78 -69
- package/dist/ZestContext.d.ts +0 -9
- package/dist/ZestProvider.d.ts +0 -8
- package/dist/semanticTypeDefaults.d.ts +0 -4
- package/docs/api.md +0 -140
- package/docs/breaking-changes.md +0 -143
- package/docs/configuration.md +0 -214
- package/docs/development.md +0 -93
- package/docs/examples.md +0 -227
- package/docs/features.md +0 -126
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 {
|
|
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
|
-
|
|
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 {
|
|
1990
|
+
export { ZestButtonConfigProvider, ZestButton as default, useZestButtonConfig };
|
|
1857
1991
|
//# sourceMappingURL=index.esm.js.map
|