jattac.libs.web.zest-button 1.3.0 → 1.5.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/LICENSE +21 -0
- package/README.md +10 -9
- package/dist/ZestButton.d.ts +23 -2
- package/dist/ZestDropdownMenu.d.ts +20 -0
- package/dist/ZestDropdownMenuItem.d.ts +9 -0
- package/dist/index.cjs.js +192 -7
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.esm.js +175 -9
- package/dist/index.esm.js.map +1 -1
- package/{docs → documentation}/api.md +25 -0
- package/{docs → documentation}/examples.md +62 -0
- package/{docs → documentation}/features.md +24 -0
- package/package.json +79 -69
- package/dist/ZestContext.d.ts +0 -9
- package/dist/ZestProvider.d.ts +0 -8
- package/dist/semanticTypeDefaults.d.ts +0 -4
- /package/{docs → documentation}/breaking-changes.md +0 -0
- /package/{docs → documentation}/configuration.md +0 -0
- /package/{docs → documentation}/development.md +0 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jattac
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -8,13 +8,14 @@ A highly customizable and interactive React button component designed for modern
|
|
|
8
8
|
* **Success & Failure Feedback**: Provide instant visual feedback with animated checkmarks for success or an animated 'X' with a shake for failures and timeouts.
|
|
9
9
|
* **Built-in Confirmation Flow**: Protect critical actions with a configurable "click-to-confirm" mechanism, complete with a countdown timer.
|
|
10
10
|
* **Richly Styleable**: Comes with `solid`, `outline`, `text`, and `dashed` styles, multiple color variants, and automatic light/dark mode support.
|
|
11
|
+
* **Split Buttons & Overflow Menus**: Attach a set of secondary actions to a button's default action via `dropdownOptions` — a discoverable chevron opens a themeable, independently-sized menu, with each item running through the same busy/confirm feedback as the main button.
|
|
11
12
|
|
|
12
13
|
### Installation
|
|
13
14
|
|
|
14
15
|
```bash
|
|
15
|
-
npm install jattac.libs.web.zest-button react-icons
|
|
16
|
+
npm install jattac.libs.web.zest-button react-icons @radix-ui/react-dropdown-menu
|
|
16
17
|
```
|
|
17
|
-
*Note: `react`, `react-dom`, and
|
|
18
|
+
*Note: `react`, `react-dom`, `react-icons`, and `@radix-ui/react-dropdown-menu` are peer dependencies and must be installed in your project.*
|
|
18
19
|
|
|
19
20
|
### Basic Usage (The "Hello World")
|
|
20
21
|
|
|
@@ -41,12 +42,12 @@ To get started, check out our **Cookbook** of practical recipes.
|
|
|
41
42
|
|
|
42
43
|
| Topic | Description |
|
|
43
44
|
| :--- | :--- |
|
|
44
|
-
| **[The Cookbook](./
|
|
45
|
-
| **[Features Showcase](./
|
|
46
|
-
| **[API Reference](./
|
|
47
|
-
| **[Configuration Guide](./
|
|
48
|
-
| **[Development Guide](./
|
|
49
|
-
| **[Breaking Changes](./
|
|
45
|
+
| **[The Cookbook](./documentation/examples.md)** | **(Start Here)** A collection of practical, real-world recipes to master `ZestButton`. |
|
|
46
|
+
| **[Features Showcase](./documentation/features.md)** | A high-level visual tour of what's possible. |
|
|
47
|
+
| **[API Reference](./documentation/api.md)** | An exhaustive technical reference for all props and types. |
|
|
48
|
+
| **[Configuration Guide](./documentation/configuration.md)**| A deep dive into global configuration using the `ZestProvider`. |
|
|
49
|
+
| **[Development Guide](./documentation/development.md)** | Information for contributors on the project's architecture and setup. |
|
|
50
|
+
| **[Breaking Changes](./documentation/breaking-changes.md)** | A log of breaking changes to assist with version upgrades. |
|
|
50
51
|
|
|
51
52
|
### License
|
|
52
53
|
|
|
@@ -54,4 +55,4 @@ Licensed under [MIT](./LICENSE).
|
|
|
54
55
|
|
|
55
56
|
---
|
|
56
57
|
|
|
57
|
-
[Next: The Cookbook (Examples) ➡️](./
|
|
58
|
+
[Next: The Cookbook (Examples) ➡️](./documentation/examples.md)
|
package/dist/ZestButton.d.ts
CHANGED
|
@@ -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,12 @@ export interface ZestCustomProps {
|
|
|
45
60
|
theme?: ZestTheme;
|
|
46
61
|
buttonStyle?: ZestButtonStyle;
|
|
47
62
|
semanticType?: SemanticType;
|
|
63
|
+
dropdownOptions?: ZestDropdownOption[];
|
|
64
|
+
dropdownAriaLabel?: string;
|
|
65
|
+
/** Theme for the dropdown menu panel; inherits the button's own `theme` when unset. */
|
|
66
|
+
dropdownTheme?: ZestTheme;
|
|
67
|
+
/** Minimum width for the dropdown menu panel (px number or CSS length string); defaults to the split control's own rendered width. */
|
|
68
|
+
dropdownWidth?: number | string;
|
|
48
69
|
}
|
|
49
70
|
/**
|
|
50
71
|
* All supported props
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
/** Theme for the menu panel; falls back to `effectiveTheme` when unset. */
|
|
15
|
+
effectiveMenuTheme?: "light" | "dark";
|
|
16
|
+
/** Minimum width for the menu panel (px number or CSS length string). */
|
|
17
|
+
menuMinWidth?: number | string;
|
|
18
|
+
}
|
|
19
|
+
declare const ZestDropdownMenu: React.FC<ZestDropdownMenuProps>;
|
|
20
|
+
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/* Shape/elevation/motion tokens (additive; no existing --zest-color-* renamed) */\r\n:root {\r\n --zest-radius-sm: 6px; /* menu items */\r\n --zest-radius-md: 8px; /* buttons, menu panel */\r\n --zest-shadow-resting: 0 1px 2px rgba(0, 0, 0, 0.08), 0 1px 1px rgba(0, 0, 0, 0.04);\r\n --zest-shadow-hover: 0 4px 10px rgba(0, 0, 0, 0.12), 0 2px 4px rgba(0, 0, 0, 0.06);\r\n --zest-shadow-menu: 0 8px 24px rgba(0, 0, 0, 0.16);\r\n --zest-focus-ring-color: #2563eb;\r\n --zest-focus-ring: 0 0 0 3px rgba(37, 99, 235, 0.45);\r\n --zest-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);\r\n --zest-ease-standard: cubic-bezier(0.2, 0, 0, 1);\r\n --zest-motion-fast: 0.15s;\r\n --zest-motion-base: 0.2s;\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 --zest-shadow-resting: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 1px rgba(0, 0, 0, 0.2);\r\n --zest-shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.25);\r\n --zest-focus-ring-color: #60a5fa;\r\n --zest-focus-ring: 0 0 0 3px rgba(96, 165, 250, 0.5);\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 --zest-shadow-resting: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 1px rgba(0, 0, 0, 0.2);\r\n --zest-shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.25);\r\n --zest-focus-ring-color: #60a5fa;\r\n --zest-focus-ring: 0 0 0 3px rgba(96, 165, 250, 0.5);\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: var(--zest-radius-md);\r\n cursor: pointer;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n appearance: none;\r\n -webkit-appearance: none;\r\n -moz-appearance: none;\r\n transition:\r\n background-color var(--zest-motion-base) ease,\r\n box-shadow var(--zest-motion-base) ease,\r\n color var(--zest-motion-base) ease,\r\n border-color var(--zest-motion-base) ease,\r\n transform var(--zest-motion-fast) var(--zest-ease-standard);\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 box-shadow: var(--zest-shadow-resting);\r\n}\r\n\r\n.ZestButton-module_button__KDafc::-moz-focus-inner {\r\n border: 0;\r\n padding: 0;\r\n}\r\n\r\n.ZestButton-module_button__KDafc:hover:not(:disabled) {\r\n box-shadow: var(--zest-shadow-hover);\r\n transform: translateY(-1px);\r\n}\r\n\r\n.ZestButton-module_button__KDafc:active:not(:disabled) {\r\n transform: translateY(0) scale(0.97);\r\n transition-duration: 0.08s;\r\n}\r\n\r\n.ZestButton-module_button__KDafc:disabled {\r\n box-shadow: none;\r\n cursor: not-allowed;\r\n transform: none;\r\n}\r\n\r\n.ZestButton-module_button__KDafc:focus-visible {\r\n outline: none;\r\n box-shadow: var(--zest-shadow-resting), var(--zest-focus-ring);\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 box-shadow: none; /* transparent background has nothing for a shadow to sit under */\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 box-shadow: none;\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/* Divider between the two split-button segments, defined for all four\r\n buttonStyles (not just solid/text) so the seam is always visible at rest.\r\n Each dropdownTrigger also gets a persistent (not just on-hover) background\r\n tint so the chevron reads as its own distinct, separately-clickable\r\n region — this is the primary fix for the two segments blending together. */\r\n.ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_solid__cu4tr {\r\n border-left: 1px solid rgba(255, 255, 255, 0.35);\r\n background-color: rgba(0, 0, 0, 0.06);\r\n}\r\n.ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_solid__cu4tr:hover:not(:disabled) {\r\n background-color: rgba(0, 0, 0, 0.12);\r\n}\r\n.ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_text__8X1xD {\r\n border-left: 1px solid rgba(0, 0, 0, 0.18);\r\n background-color: rgba(0, 0, 0, 0.035);\r\n}\r\n.ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_outline__esgLq,\r\n.ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_dashed__ebKYF {\r\n /* outline/dashed already draw their own full border; splitButtonMain\r\n removes its own right border below so only this left border remains\r\n as the seam, keeping its weight consistent with solid/text. */\r\n border-left-width: 2px;\r\n background-color: rgba(0, 0, 0, 0.035);\r\n}\r\n\r\n.ZestButton-module_splitButtonMain__F0cHX.ZestButton-module_outline__esgLq,\r\n.ZestButton-module_splitButtonMain__F0cHX.ZestButton-module_dashed__ebKYF {\r\n border-right: none;\r\n}\r\n\r\n.ZestButton-module_force-dark__cx74D .ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_solid__cu4tr {\r\n background-color: rgba(255, 255, 255, 0.1);\r\n}\r\n.ZestButton-module_force-dark__cx74D .ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_solid__cu4tr:hover:not(:disabled) {\r\n background-color: rgba(255, 255, 255, 0.18);\r\n}\r\n.ZestButton-module_force-dark__cx74D .ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_text__8X1xD,\r\n.ZestButton-module_force-dark__cx74D .ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_outline__esgLq,\r\n.ZestButton-module_force-dark__cx74D .ZestButton-module_dropdownTrigger__wqBMN.ZestButton-module_dashed__ebKYF {\r\n background-color: rgba(255, 255, 255, 0.06);\r\n}\r\n\r\n.ZestButton-module_dropdownChevron__GMkdW {\r\n width: 0.85em;\r\n height: 0.85em;\r\n transition: transform var(--zest-motion-base) var(--zest-ease-spring);\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: var(--zest-radius-md);\r\n background: var(--zest-color-menu-bg, #ffffff);\r\n color: var(--zest-color-menu-text, #1f2937);\r\n box-shadow: var(--zest-shadow-menu);\r\n border: 1px solid rgba(0, 0, 0, 0.08);\r\n z-index: 1000;\r\n transform-origin: var(--radix-dropdown-menu-content-transform-origin);\r\n}\r\n\r\n.ZestButton-module_dropdownMenuContent__wIHv-[data-state=\"open\"] {\r\n animation: ZestButton-module_dropdownMenuIn__st1Yy var(--zest-motion-base) var(--zest-ease-standard);\r\n}\r\n/* Radix unmounts Content immediately on close (no forceMount is used here),\r\n so this closing keyframe may not get a chance to visibly play in every\r\n browser — treat it as a graceful enhancement, not a guarantee. */\r\n.ZestButton-module_dropdownMenuContent__wIHv-[data-state=\"closed\"] {\r\n animation: ZestButton-module_dropdownMenuOut__o45vS var(--zest-motion-fast) var(--zest-ease-standard);\r\n}\r\n\r\n@keyframes ZestButton-module_dropdownMenuIn__st1Yy {\r\n from { opacity: 0; transform: scale(0.96); }\r\n to { opacity: 1; transform: scale(1); }\r\n}\r\n@keyframes ZestButton-module_dropdownMenuOut__o45vS {\r\n from { opacity: 1; transform: scale(1); }\r\n to { opacity: 0; transform: scale(0.96); }\r\n}\r\n\r\n@media (prefers-reduced-motion: reduce) {\r\n .ZestButton-module_dropdownMenuContent__wIHv-[data-state=\"open\"],\r\n .ZestButton-module_dropdownMenuContent__wIHv-[data-state=\"closed\"] {\r\n animation: none;\r\n }\r\n .ZestButton-module_dropdownChevron__GMkdW {\r\n transition: none;\r\n }\r\n .ZestButton-module_button__KDafc {\r\n transition: background-color var(--zest-motion-base) ease,\r\n box-shadow var(--zest-motion-base) ease,\r\n color var(--zest-motion-base) ease,\r\n border-color var(--zest-motion-base) ease;\r\n }\r\n .ZestButton-module_button__KDafc:hover:not(:disabled),\r\n .ZestButton-module_button__KDafc:active:not(:disabled) {\r\n transform: none;\r\n }\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: var(--zest-radius-sm);\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-","dropdownMenuIn":"ZestButton-module_dropdownMenuIn__st1Yy","dropdownMenuOut":"ZestButton-module_dropdownMenuOut__o45vS","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,139 @@ 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, effectiveMenuTheme, menuMinWidth, }) => {
|
|
1857
|
+
const resolvedMenuTheme = effectiveMenuTheme ?? effectiveTheme;
|
|
1858
|
+
const busyKeysRef = require$$0.useRef(new Set());
|
|
1859
|
+
const handleItemBusyChange = require$$0.useCallback((key, busy) => {
|
|
1860
|
+
const busyKeys = busyKeysRef.current;
|
|
1861
|
+
const wasAnyBusy = busyKeys.size > 0;
|
|
1862
|
+
if (busy) {
|
|
1863
|
+
busyKeys.add(key);
|
|
1864
|
+
}
|
|
1865
|
+
else {
|
|
1866
|
+
busyKeys.delete(key);
|
|
1867
|
+
}
|
|
1868
|
+
const isAnyBusy = busyKeys.size > 0;
|
|
1869
|
+
if (isAnyBusy !== wasAnyBusy) {
|
|
1870
|
+
onAnyItemBusyChange?.(isAnyBusy);
|
|
1871
|
+
}
|
|
1872
|
+
}, [onAnyItemBusyChange]);
|
|
1873
|
+
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: [
|
|
1874
|
+
styles.dropdownTrigger,
|
|
1875
|
+
styles[buttonStyle],
|
|
1876
|
+
styles[variant],
|
|
1877
|
+
styles[size],
|
|
1878
|
+
disabled ? styles.disabled : "",
|
|
1879
|
+
effectiveTheme === "light" ? styles["force-light"] : styles["force-dark"],
|
|
1880
|
+
]
|
|
1881
|
+
.join(" ")
|
|
1882
|
+
.trim(), children: jsxRuntimeExports.jsx(fa6.FaChevronDown, { className: [styles.dropdownChevron, open ? styles.dropdownChevronOpen : ""]
|
|
1883
|
+
.join(" ")
|
|
1884
|
+
.trim() }) }) }), jsxRuntimeExports.jsx(DropdownMenu__namespace.Portal, { children: jsxRuntimeExports.jsx(DropdownMenu__namespace.Content, { className: [
|
|
1885
|
+
styles.dropdownMenuContent,
|
|
1886
|
+
resolvedMenuTheme === "light" ? styles["force-light"] : styles["force-dark"],
|
|
1887
|
+
].join(" "), style: menuMinWidth !== undefined
|
|
1888
|
+
? { minWidth: typeof menuMinWidth === "number" ? `${menuMinWidth}px` : menuMinWidth }
|
|
1889
|
+
: undefined, 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))) }) })] }));
|
|
1890
|
+
};
|
|
1891
|
+
|
|
1745
1892
|
// --- Components ---
|
|
1746
1893
|
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
1894
|
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
1895
|
const ZestButton = ({ className = "", disabled, children, onClick, zest: localZestProps, ...props }) => {
|
|
1749
1896
|
const effectiveZestConfig = useZestConfig(localZestProps);
|
|
1750
|
-
const { visualOptions = {}, busyOptions = {}, successOptions = {}, confirmOptions, isDefault = false, theme = 'system', buttonStyle = 'solid', } = effectiveZestConfig;
|
|
1897
|
+
const { visualOptions = {}, busyOptions = {}, successOptions = {}, confirmOptions, isDefault = false, theme = 'system', buttonStyle = 'solid', dropdownOptions, dropdownAriaLabel = "More options", dropdownTheme, dropdownWidth, } = effectiveZestConfig;
|
|
1751
1898
|
const { variant = "standard", size = "md", stretch = false, iconLeft, iconRight, } = visualOptions;
|
|
1752
1899
|
const { handleInternally, minBusyDurationMs, preventRageClick, showCheckmark, showFailIcon, internalBusy, wasSuccessful, wasFailed, startBusy, endBusy, } = useBusyState({ busyOptions, successOptions });
|
|
1753
1900
|
const { awaitingConfirm, currentChildren, startConfirmation, stopConfirmation, } = useConfirmation({
|
|
@@ -1758,6 +1905,38 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
|
|
|
1758
1905
|
const buttonRef = require$$0.useRef(null);
|
|
1759
1906
|
const systemTheme = useThemeDetection();
|
|
1760
1907
|
const effectiveTheme = theme === 'system' ? systemTheme : theme;
|
|
1908
|
+
// Dropdown menus default to light regardless of the button's own theme
|
|
1909
|
+
// (product preference) — dropdownTheme only kicks in once set explicitly.
|
|
1910
|
+
const effectiveDropdownTheme = dropdownTheme
|
|
1911
|
+
? dropdownTheme === 'system'
|
|
1912
|
+
? systemTheme
|
|
1913
|
+
: dropdownTheme
|
|
1914
|
+
: 'light';
|
|
1915
|
+
const hasDropdown = Boolean(dropdownOptions && dropdownOptions.length > 0);
|
|
1916
|
+
const [dropdownOpen, setDropdownOpen] = require$$0.useState(false);
|
|
1917
|
+
const [anyDropdownItemBusy, setAnyDropdownItemBusy] = require$$0.useState(false);
|
|
1918
|
+
const splitContainerRef = require$$0.useRef(null);
|
|
1919
|
+
const [measuredControlWidth, setMeasuredControlWidth] = require$$0.useState(undefined);
|
|
1920
|
+
require$$0.useLayoutEffect(() => {
|
|
1921
|
+
if (!hasDropdown || !splitContainerRef.current)
|
|
1922
|
+
return;
|
|
1923
|
+
const el = splitContainerRef.current;
|
|
1924
|
+
// A width of 0 means "not actually laid out yet" (e.g. jsdom, or a
|
|
1925
|
+
// display:none ancestor) rather than a real zero-width control — treat
|
|
1926
|
+
// it as unavailable so the menu falls back to its own CSS default
|
|
1927
|
+
// instead of being forced to a bogus 0px minimum.
|
|
1928
|
+
const initialWidth = el.getBoundingClientRect().width;
|
|
1929
|
+
if (initialWidth > 0)
|
|
1930
|
+
setMeasuredControlWidth(initialWidth);
|
|
1931
|
+
const observer = new ResizeObserver((entries) => {
|
|
1932
|
+
const width = entries[0]?.contentRect.width ?? 0;
|
|
1933
|
+
if (width > 0)
|
|
1934
|
+
setMeasuredControlWidth(width);
|
|
1935
|
+
});
|
|
1936
|
+
observer.observe(el);
|
|
1937
|
+
return () => observer.disconnect();
|
|
1938
|
+
}, [hasDropdown]);
|
|
1939
|
+
const resolvedMenuMinWidth = dropdownWidth ?? measuredControlWidth;
|
|
1761
1940
|
const effectiveBusy = typeof props["aria-busy"] === "boolean"
|
|
1762
1941
|
? Boolean(props["aria-busy"])
|
|
1763
1942
|
: handleInternally
|
|
@@ -1765,7 +1944,8 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
|
|
|
1765
1944
|
: false;
|
|
1766
1945
|
const isDisabled = disabled ||
|
|
1767
1946
|
effectiveBusy ||
|
|
1768
|
-
(preventRageClick && (wasSuccessful || wasFailed))
|
|
1947
|
+
(preventRageClick && (wasSuccessful || wasFailed)) ||
|
|
1948
|
+
anyDropdownItemBusy;
|
|
1769
1949
|
const handleClick = async (e) => {
|
|
1770
1950
|
if (preventRageClick && internalBusy)
|
|
1771
1951
|
return;
|
|
@@ -1807,7 +1987,7 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
|
|
|
1807
1987
|
}
|
|
1808
1988
|
};
|
|
1809
1989
|
require$$0.useEffect(() => {
|
|
1810
|
-
if (!isDefault || isDisabled)
|
|
1990
|
+
if (!isDefault || isDisabled || dropdownOpen)
|
|
1811
1991
|
return;
|
|
1812
1992
|
const listener = (e) => {
|
|
1813
1993
|
const target = e.target;
|
|
@@ -1824,7 +2004,7 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
|
|
|
1824
2004
|
};
|
|
1825
2005
|
document.addEventListener("keydown", listener);
|
|
1826
2006
|
return () => document.removeEventListener("keydown", listener);
|
|
1827
|
-
}, [isDefault, isDisabled]);
|
|
2007
|
+
}, [isDefault, isDisabled, dropdownOpen]);
|
|
1828
2008
|
const renderLeftIcon = () => {
|
|
1829
2009
|
if (effectiveBusy) {
|
|
1830
2010
|
return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(fa6.FaSpinner, { className: styles.spinner }) }));
|
|
@@ -1840,7 +2020,7 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
|
|
|
1840
2020
|
}
|
|
1841
2021
|
return null;
|
|
1842
2022
|
};
|
|
1843
|
-
|
|
2023
|
+
const buttonElement = (jsxRuntimeExports.jsx("button", { ref: buttonRef, className: [
|
|
1844
2024
|
styles.button,
|
|
1845
2025
|
styles[buttonStyle],
|
|
1846
2026
|
styles[variant],
|
|
@@ -1849,8 +2029,13 @@ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZe
|
|
|
1849
2029
|
isDisabled ? styles.disabled : "",
|
|
1850
2030
|
wasFailed ? styles.shake : "",
|
|
1851
2031
|
effectiveTheme === 'light' ? styles['force-light'] : styles['force-dark'],
|
|
2032
|
+
hasDropdown ? styles.splitButtonMain : "",
|
|
1852
2033
|
className,
|
|
1853
2034
|
].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 })] })] }) }));
|
|
2035
|
+
if (!hasDropdown) {
|
|
2036
|
+
return buttonElement;
|
|
2037
|
+
}
|
|
2038
|
+
return (jsxRuntimeExports.jsxs("div", { className: styles.splitButtonContainer, ref: splitContainerRef, 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, effectiveMenuTheme: effectiveDropdownTheme, menuMinWidth: resolvedMenuMinWidth })] }));
|
|
1854
2039
|
};
|
|
1855
2040
|
|
|
1856
2041
|
const ZestButtonConfigProvider = ({ config, children }) => {
|