jattac.libs.web.zest-button 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  var require$$0 = require('react');
4
4
  var fa6 = require('react-icons/fa6');
5
+ var fa = require('react-icons/fa');
5
6
 
6
7
  var jsxRuntime = {exports: {}};
7
8
 
@@ -1389,18 +1390,218 @@ var css_248z = "/* Styles/ZestButton.module.css */\n\n/* Define base variables f
1389
1390
  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","fullWidth":"ZestButton-module_fullWidth__2ziwk","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"};
1390
1391
  styleInject(css_248z);
1391
1392
 
1392
- // --- Components ---
1393
- 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" }) }));
1394
- 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" })] }));
1395
- const ZestButton = ({ className = "", disabled, children, onClick, // Destructure onClick here
1396
- zest, // New parent prop
1397
- ...props }) => {
1398
- // Destructure custom props from 'zest' with defaults
1399
- const { visualOptions = {}, busyOptions = {}, successOptions = {}, confirmOptions, // confirmOptions can be undefined
1400
- isDefault = false, theme = 'system', buttonStyle = 'solid', } = zest || {}; // Provide empty object as default for zest
1401
- const { variant = "standard", size = "md", fullWidth = false, iconLeft, iconRight, } = visualOptions;
1402
- const { handleInternally = true, preventRageClick = true, minBusyDurationMs = 500, } = busyOptions;
1403
- const { showCheckmark = true, showFailIcon = true, autoResetAfterMs = 2000, } = successOptions;
1393
+ // Create the Zest Context with a default empty configuration
1394
+ const ZestContext = require$$0.createContext(undefined);
1395
+ // Custom hook to use the Zest Context
1396
+ const useZest = () => {
1397
+ const context = require$$0.useContext(ZestContext);
1398
+ // Optional: Add a check here if context is undefined, meaning provider is not used
1399
+ // if (context === undefined) {
1400
+ // console.warn("useZest must be used within a ZestProvider. Falling back to default ZestButton props.");
1401
+ // }
1402
+ return context;
1403
+ };
1404
+
1405
+ const semanticTypeDefaults = {
1406
+ // Creation / Add
1407
+ 'add': {
1408
+ visualOptions: {
1409
+ variant: 'standard',
1410
+ iconLeft: jsxRuntimeExports.jsx(fa.FaPlus, {}),
1411
+ },
1412
+ },
1413
+ 'new': {
1414
+ visualOptions: {
1415
+ variant: 'standard',
1416
+ iconLeft: jsxRuntimeExports.jsx(fa.FaPlus, {}),
1417
+ },
1418
+ },
1419
+ // Save / Submit
1420
+ 'save': {
1421
+ visualOptions: {
1422
+ variant: 'success',
1423
+ iconLeft: jsxRuntimeExports.jsx(fa.FaSave, {}),
1424
+ },
1425
+ busyOptions: { minBusyDurationMs: 500 }, // Default busy duration for saves
1426
+ successOptions: { showCheckmark: true },
1427
+ },
1428
+ 'submit': {
1429
+ visualOptions: {
1430
+ variant: 'success',
1431
+ iconLeft: jsxRuntimeExports.jsx(fa.FaSave, {}),
1432
+ },
1433
+ busyOptions: { minBusyDurationMs: 500 },
1434
+ successOptions: { showCheckmark: true },
1435
+ },
1436
+ // Edit / Update
1437
+ 'edit': {
1438
+ visualOptions: {
1439
+ variant: 'standard',
1440
+ iconLeft: jsxRuntimeExports.jsx(fa.FaEdit, {}),
1441
+ },
1442
+ },
1443
+ 'update': {
1444
+ visualOptions: {
1445
+ variant: 'standard',
1446
+ iconLeft: jsxRuntimeExports.jsx(fa.FaEdit, {}),
1447
+ },
1448
+ },
1449
+ // Delete / Remove
1450
+ 'delete': {
1451
+ visualOptions: {
1452
+ variant: 'danger',
1453
+ iconLeft: jsxRuntimeExports.jsx(fa.FaTrash, {}),
1454
+ },
1455
+ confirmOptions: {
1456
+ displayLabel: 'Confirm Delete',
1457
+ timeoutSecs: 5,
1458
+ },
1459
+ successOptions: { showFailIcon: true, autoResetAfterMs: 400 }, // Shake for fail
1460
+ },
1461
+ 'remove': {
1462
+ visualOptions: {
1463
+ variant: 'danger',
1464
+ iconLeft: jsxRuntimeExports.jsx(fa.FaTrash, {}),
1465
+ },
1466
+ confirmOptions: {
1467
+ displayLabel: 'Confirm Remove',
1468
+ timeoutSecs: 5,
1469
+ },
1470
+ successOptions: { showFailIcon: true, autoResetAfterMs: 400 },
1471
+ },
1472
+ // Cancel / Close
1473
+ 'cancel': {
1474
+ buttonStyle: 'outline', // Moved here
1475
+ visualOptions: {
1476
+ variant: 'standard',
1477
+ iconLeft: jsxRuntimeExports.jsx(fa.FaTimes, {}),
1478
+ },
1479
+ },
1480
+ 'close': {
1481
+ buttonStyle: 'outline', // Moved here
1482
+ visualOptions: {
1483
+ variant: 'standard',
1484
+ iconLeft: jsxRuntimeExports.jsx(fa.FaTimes, {}),
1485
+ },
1486
+ },
1487
+ // View / Details
1488
+ 'view': {
1489
+ buttonStyle: 'text', // Moved here
1490
+ visualOptions: {
1491
+ variant: 'standard',
1492
+ iconRight: jsxRuntimeExports.jsx(fa.FaArrowRight, {}),
1493
+ },
1494
+ },
1495
+ 'details': {
1496
+ buttonStyle: 'text', // Moved here
1497
+ visualOptions: {
1498
+ variant: 'standard',
1499
+ iconRight: jsxRuntimeExports.jsx(fa.FaArrowRight, {}),
1500
+ },
1501
+ },
1502
+ // Download
1503
+ 'download': {
1504
+ visualOptions: {
1505
+ variant: 'standard',
1506
+ iconLeft: jsxRuntimeExports.jsx(fa.FaDownload, {}),
1507
+ },
1508
+ },
1509
+ // Upload
1510
+ 'upload': {
1511
+ visualOptions: {
1512
+ variant: 'standard',
1513
+ iconLeft: jsxRuntimeExports.jsx(fa.FaUpload, {}),
1514
+ },
1515
+ },
1516
+ // Refresh / Reload
1517
+ 'refresh': {
1518
+ visualOptions: {
1519
+ variant: 'standard',
1520
+ iconLeft: jsxRuntimeExports.jsx(fa.FaSyncAlt, {}),
1521
+ },
1522
+ busyOptions: { minBusyDurationMs: 500 },
1523
+ },
1524
+ 'reload': {
1525
+ visualOptions: {
1526
+ variant: 'standard',
1527
+ iconLeft: jsxRuntimeExports.jsx(fa.FaSyncAlt, {}),
1528
+ },
1529
+ busyOptions: { minBusyDurationMs: 500 },
1530
+ },
1531
+ // Print
1532
+ 'print': {
1533
+ visualOptions: {
1534
+ variant: 'standard',
1535
+ iconLeft: jsxRuntimeExports.jsx(fa.FaPrint, {}),
1536
+ },
1537
+ },
1538
+ // Share
1539
+ 'share': {
1540
+ visualOptions: {
1541
+ variant: 'standard',
1542
+ iconLeft: jsxRuntimeExports.jsx(fa.FaShareAlt, {}),
1543
+ },
1544
+ },
1545
+ // Confirm (generic)
1546
+ 'confirm': {
1547
+ visualOptions: {
1548
+ variant: 'success', // Could be standard or success
1549
+ },
1550
+ confirmOptions: {
1551
+ displayLabel: 'Are you sure?',
1552
+ timeoutSecs: 5,
1553
+ },
1554
+ },
1555
+ };
1556
+
1557
+ // Define a deep merge utility function
1558
+ const deepMerge = (target, source) => {
1559
+ const output = { ...target };
1560
+ if (target && typeof target === 'object' && source && typeof source === 'object') {
1561
+ Object.keys(source).forEach(key => {
1562
+ if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
1563
+ if (!(key in target))
1564
+ Object.assign(output, { [key]: source[key] });
1565
+ else
1566
+ output[key] = deepMerge(target[key], source[key]);
1567
+ }
1568
+ else {
1569
+ Object.assign(output, { [key]: source[key] });
1570
+ }
1571
+ });
1572
+ }
1573
+ return output;
1574
+ };
1575
+ const useZestConfig = (localZestProps) => {
1576
+ const globalConfig = useZest();
1577
+ const globalDefaultProps = globalConfig?.defaultProps;
1578
+ const customSemanticDefaults = globalConfig?.semanticTypeDefaults;
1579
+ // 1. Start with global defaults (lowest precedence)
1580
+ let effectiveZestConfig = deepMerge({}, globalDefaultProps || {});
1581
+ // Determine the semanticType from either local props or the already-merged global props
1582
+ const semanticType = localZestProps?.semanticType || effectiveZestConfig.semanticType;
1583
+ if (semanticType) {
1584
+ // 2. Apply built-in semantic defaults
1585
+ if (semanticTypeDefaults[semanticType]) {
1586
+ effectiveZestConfig = deepMerge(effectiveZestConfig, semanticTypeDefaults[semanticType]);
1587
+ }
1588
+ // 3. Apply custom semantic defaults from provider (overrides built-in ones)
1589
+ if (customSemanticDefaults && customSemanticDefaults[semanticType]) {
1590
+ effectiveZestConfig = deepMerge(effectiveZestConfig, customSemanticDefaults[semanticType]);
1591
+ }
1592
+ }
1593
+ // 4. Apply local props (highest precedence)
1594
+ effectiveZestConfig = deepMerge(effectiveZestConfig, localZestProps || {});
1595
+ return effectiveZestConfig;
1596
+ };
1597
+
1598
+ const useBusyState = ({ busyOptions, successOptions }) => {
1599
+ const [internalBusy, setInternalBusy] = require$$0.useState(false);
1600
+ const [wasSuccessful, setWasSuccessful] = require$$0.useState(false);
1601
+ const [wasFailed, setWasFailed] = require$$0.useState(false);
1602
+ const failTimeoutRef = require$$0.useRef(null);
1603
+ const { handleInternally = true, preventRageClick = true, minBusyDurationMs = 500, } = busyOptions || {};
1604
+ const { showCheckmark = true, showFailIcon = true, autoResetAfterMs = 2000, } = successOptions || {};
1404
1605
  // Edge Case 4: Add warnings for very short durations in development
1405
1606
  require$$0.useEffect(() => {
1406
1607
  if (process.env.NODE_ENV === 'development') {
@@ -1412,16 +1613,120 @@ zest, // New parent prop
1412
1613
  }
1413
1614
  }
1414
1615
  }, [minBusyDurationMs, autoResetAfterMs]);
1415
- const [internalBusy, setInternalBusy] = require$$0.useState(false);
1416
- const [wasSuccessful, setWasSuccessful] = require$$0.useState(false);
1417
- const [wasFailed, setWasFailed] = require$$0.useState(false);
1418
- const buttonRef = require$$0.useRef(null);
1419
- const failTimeoutRef = require$$0.useRef(null); // Bug 1: Add useRef for failTimeout
1420
- const [currentChildren, setCurrentChildren] = require$$0.useState(children);
1616
+ // auto-reset success/failure state
1617
+ require$$0.useEffect(() => {
1618
+ if ((wasSuccessful || wasFailed) && autoResetAfterMs) {
1619
+ const timeout = setTimeout(() => {
1620
+ setWasSuccessful(false);
1621
+ setWasFailed(false);
1622
+ if (failTimeoutRef.current) { // Clear fail timeout if still active
1623
+ clearTimeout(failTimeoutRef.current);
1624
+ failTimeoutRef.current = null;
1625
+ }
1626
+ }, autoResetAfterMs);
1627
+ return () => clearTimeout(timeout);
1628
+ }
1629
+ }, [wasSuccessful, wasFailed, autoResetAfterMs]);
1630
+ // Cleanup for failTimeoutRef on unmount
1631
+ require$$0.useEffect(() => {
1632
+ return () => {
1633
+ if (failTimeoutRef.current) {
1634
+ clearTimeout(failTimeoutRef.current);
1635
+ }
1636
+ };
1637
+ }, []);
1638
+ const startBusy = () => {
1639
+ setWasSuccessful(false);
1640
+ setWasFailed(false);
1641
+ setInternalBusy(true);
1642
+ };
1643
+ const endBusy = (isSuccess) => {
1644
+ setInternalBusy(false);
1645
+ if (isSuccess) {
1646
+ if (showCheckmark)
1647
+ setWasSuccessful(true);
1648
+ }
1649
+ else {
1650
+ if (showFailIcon)
1651
+ setWasFailed(true);
1652
+ // Bug 1: Clear any existing timeout before setting a new one
1653
+ if (failTimeoutRef.current) {
1654
+ clearTimeout(failTimeoutRef.current);
1655
+ }
1656
+ failTimeoutRef.current = setTimeout(() => {
1657
+ setWasFailed(false);
1658
+ failTimeoutRef.current = null; // Clear ref after timeout fires
1659
+ }, 400); // Shake animation duration
1660
+ }
1661
+ };
1662
+ return {
1663
+ internalBusy,
1664
+ wasSuccessful,
1665
+ wasFailed,
1666
+ startBusy,
1667
+ endBusy,
1668
+ handleInternally,
1669
+ preventRageClick,
1670
+ minBusyDurationMs,
1671
+ showCheckmark,
1672
+ showFailIcon,
1673
+ autoResetAfterMs,
1674
+ failTimeoutRef // Expose this for ZestButton to clear if needed (e.g., confirmation failure)
1675
+ };
1676
+ };
1677
+
1678
+ const useConfirmation = ({ confirmOptions, originalChildren, onConfirmFail }) => {
1421
1679
  const [awaitingConfirm, setAwaitingConfirm] = require$$0.useState(false);
1422
- // interval ref for confirm countdown
1680
+ const [currentChildren, setCurrentChildren] = require$$0.useState(originalChildren);
1423
1681
  const confirmIntervalRef = require$$0.useRef(null);
1424
- // Theme state and detection
1682
+ require$$0.useEffect(() => {
1683
+ if (!awaitingConfirm) {
1684
+ setCurrentChildren(originalChildren);
1685
+ }
1686
+ }, [originalChildren, awaitingConfirm]);
1687
+ const stopConfirmation = require$$0.useCallback(() => {
1688
+ if (confirmIntervalRef.current) {
1689
+ clearInterval(confirmIntervalRef.current);
1690
+ confirmIntervalRef.current = null;
1691
+ }
1692
+ setCurrentChildren(originalChildren);
1693
+ setAwaitingConfirm(false);
1694
+ }, [originalChildren]);
1695
+ const startConfirmation = require$$0.useCallback(() => {
1696
+ if (!confirmOptions)
1697
+ return;
1698
+ setAwaitingConfirm(true);
1699
+ const { displayLabel, timeoutSecs } = confirmOptions;
1700
+ setCurrentChildren(`${displayLabel} (${timeoutSecs}s)`);
1701
+ const startTime = Date.now();
1702
+ confirmIntervalRef.current = setInterval(() => {
1703
+ const elapsed = Date.now() - startTime;
1704
+ const timeRemaining = timeoutSecs - Math.floor(elapsed / 1000);
1705
+ if (timeRemaining <= 0) {
1706
+ stopConfirmation();
1707
+ onConfirmFail?.();
1708
+ }
1709
+ else {
1710
+ setCurrentChildren(`${displayLabel} (${timeRemaining}s)`);
1711
+ }
1712
+ }, 1000);
1713
+ }, [confirmOptions, onConfirmFail, stopConfirmation]);
1714
+ require$$0.useEffect(() => {
1715
+ return () => {
1716
+ if (confirmIntervalRef.current) {
1717
+ clearInterval(confirmIntervalRef.current);
1718
+ }
1719
+ };
1720
+ }, []);
1721
+ return {
1722
+ awaitingConfirm,
1723
+ currentChildren,
1724
+ startConfirmation,
1725
+ stopConfirmation,
1726
+ };
1727
+ };
1728
+
1729
+ const useThemeDetection = () => {
1425
1730
  const [systemTheme, setSystemTheme] = require$$0.useState('light');
1426
1731
  require$$0.useEffect(() => {
1427
1732
  const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
@@ -1432,13 +1737,25 @@ zest, // New parent prop
1432
1737
  mediaQuery.addEventListener('change', handleChange);
1433
1738
  return () => mediaQuery.removeEventListener('change', handleChange);
1434
1739
  }, []);
1740
+ return systemTheme;
1741
+ };
1742
+
1743
+ // --- Components ---
1744
+ 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" }) }));
1745
+ 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" })] }));
1746
+ const ZestButton = ({ className = "", disabled, children, onClick, zest: localZestProps, ...props }) => {
1747
+ const effectiveZestConfig = useZestConfig(localZestProps);
1748
+ const { visualOptions = {}, busyOptions = {}, successOptions = {}, confirmOptions, isDefault = false, theme = 'system', buttonStyle = 'solid', } = effectiveZestConfig;
1749
+ const { variant = "standard", size = "md", fullWidth = false, iconLeft, iconRight, } = visualOptions;
1750
+ const { handleInternally, minBusyDurationMs, preventRageClick, showCheckmark, showFailIcon, internalBusy, wasSuccessful, wasFailed, startBusy, endBusy, } = useBusyState({ busyOptions, successOptions });
1751
+ const { awaitingConfirm, currentChildren, startConfirmation, stopConfirmation, } = useConfirmation({
1752
+ confirmOptions,
1753
+ originalChildren: children,
1754
+ onConfirmFail: () => endBusy(false),
1755
+ });
1756
+ const buttonRef = require$$0.useRef(null);
1757
+ const systemTheme = useThemeDetection();
1435
1758
  const effectiveTheme = theme === 'system' ? systemTheme : theme;
1436
- // keep children in sync when not in confirm mode
1437
- require$$0.useEffect(() => {
1438
- if (!awaitingConfirm) {
1439
- setCurrentChildren(children);
1440
- }
1441
- }, [children, awaitingConfirm]);
1442
1759
  const effectiveBusy = typeof props["aria-busy"] === "boolean"
1443
1760
  ? Boolean(props["aria-busy"])
1444
1761
  : handleInternally
@@ -1447,23 +1764,12 @@ zest, // New parent prop
1447
1764
  const isDisabled = disabled ||
1448
1765
  effectiveBusy ||
1449
1766
  (preventRageClick && (wasSuccessful || wasFailed));
1450
- // Move handleClick, stopWaiting, and handleConfirmClick declarations here
1451
- const stopWaiting = () => {
1452
- if (confirmIntervalRef.current) {
1453
- clearInterval(confirmIntervalRef.current);
1454
- confirmIntervalRef.current = null;
1455
- }
1456
- setCurrentChildren(children);
1457
- setAwaitingConfirm(false);
1458
- };
1459
1767
  const handleClick = async (e) => {
1460
1768
  if (preventRageClick && internalBusy)
1461
1769
  return;
1462
1770
  if (handleInternally && typeof onClick === "function") {
1463
1771
  try {
1464
- setWasSuccessful(false);
1465
- setWasFailed(false);
1466
- setInternalBusy(true);
1772
+ startBusy();
1467
1773
  const startTime = Date.now();
1468
1774
  await onClick(e);
1469
1775
  const elapsed = Date.now() - startTime;
@@ -1471,69 +1777,33 @@ zest, // New parent prop
1471
1777
  if (remaining > 0) {
1472
1778
  await new Promise((resolve) => setTimeout(resolve, remaining));
1473
1779
  }
1474
- if (showCheckmark)
1475
- setWasSuccessful(true);
1780
+ endBusy(true);
1476
1781
  }
1477
1782
  catch (err) {
1478
1783
  console.error(err);
1479
- if (showFailIcon)
1480
- setWasFailed(true);
1481
- }
1482
- finally {
1483
- setInternalBusy(false);
1784
+ endBusy(false);
1484
1785
  }
1485
1786
  }
1486
1787
  else if (onClick) {
1487
1788
  onClick(e);
1488
1789
  }
1489
1790
  };
1490
- const handleConfirmClick = async (e) => {
1491
- if (!confirmOptions) { // Use destructured confirmOptions
1492
- return handleClick(e);
1493
- }
1494
- // Edge Case 3: Add warning for missing onClick with confirmOptions
1495
- if (confirmOptions && !onClick) { // Use destructured confirmOptions and onClick
1496
- console.warn("ZestButton: 'confirmOptions' are provided but 'onClick' handler is missing. The button will confirm but perform no action.");
1497
- }
1791
+ const handleConfirmClick = (e) => {
1498
1792
  if (awaitingConfirm) {
1499
- stopWaiting();
1500
- return handleClick(e);
1793
+ stopConfirmation();
1794
+ handleClick(e);
1795
+ return;
1501
1796
  }
1502
- const { displayLabel, timeoutSecs } = confirmOptions; // Use destructured confirmOptions
1503
- const startTime = Date.now();
1504
- setAwaitingConfirm(true);
1505
- setCurrentChildren(`${displayLabel} (${timeoutSecs}s)`); // Initial display
1506
- confirmIntervalRef.current = setInterval(() => {
1507
- const elapsed = Date.now() - startTime;
1508
- const timeRemaining = timeoutSecs - Math.floor(elapsed / 1000);
1509
- if (timeRemaining <= 0) {
1510
- stopWaiting();
1511
- setWasFailed(true); // Indicate failure for shake animation
1512
- // Bug 1: Clear any existing timeout before setting a new one
1513
- if (failTimeoutRef.current) {
1514
- clearTimeout(failTimeoutRef.current);
1515
- }
1516
- failTimeoutRef.current = setTimeout(() => {
1517
- setWasFailed(false);
1518
- failTimeoutRef.current = null; // Clear ref after timeout fires
1519
- }, 400); // Shake animation duration
1520
- }
1521
- else {
1522
- setCurrentChildren(`${displayLabel} (${timeRemaining}s)`);
1797
+ if (confirmOptions) {
1798
+ if (!onClick) {
1799
+ console.warn("ZestButton: 'confirmOptions' are provided but 'onClick' handler is missing.");
1523
1800
  }
1524
- }, 1000); // Update once per second
1525
- };
1526
- // auto-reset success/failure state
1527
- require$$0.useEffect(() => {
1528
- if ((wasSuccessful || wasFailed) && autoResetAfterMs) {
1529
- const timeout = setTimeout(() => {
1530
- setWasSuccessful(false);
1531
- setWasFailed(false);
1532
- }, autoResetAfterMs);
1533
- return () => clearTimeout(timeout);
1801
+ startConfirmation();
1534
1802
  }
1535
- }, [wasSuccessful, wasFailed, autoResetAfterMs]);
1536
- // Enter key handler if isDefault
1803
+ else {
1804
+ handleClick(e);
1805
+ }
1806
+ };
1537
1807
  require$$0.useEffect(() => {
1538
1808
  if (!isDefault || isDisabled)
1539
1809
  return;
@@ -1542,54 +1812,50 @@ zest, // New parent prop
1542
1812
  if (e.key === "Enter" &&
1543
1813
  !e.repeat &&
1544
1814
  !e.defaultPrevented &&
1545
- !(target instanceof HTMLTextAreaElement)) {
1815
+ !(target instanceof HTMLTextAreaElement) &&
1816
+ buttonRef.current &&
1817
+ document.activeElement !== buttonRef.current // Optional: prevent double-action if button is focused
1818
+ ) {
1546
1819
  e.preventDefault();
1547
- // Bug 2: Directly call handleConfirmClick to respect confirmation logic
1548
- handleConfirmClick(e);
1820
+ buttonRef.current.click();
1549
1821
  }
1550
1822
  };
1551
1823
  document.addEventListener("keydown", listener);
1552
1824
  return () => document.removeEventListener("keydown", listener);
1553
- }, [isDefault, isDisabled, handleConfirmClick]); // Bug 2: Add handleConfirmClick to dependencies
1554
- // cleanup on unmount
1555
- require$$0.useEffect(() => {
1556
- return () => {
1557
- if (confirmIntervalRef.current) {
1558
- clearInterval(confirmIntervalRef.current);
1559
- }
1560
- // Bug 1: Add cleanup for failTimeoutRef
1561
- if (failTimeoutRef.current) {
1562
- clearTimeout(failTimeoutRef.current);
1563
- }
1564
- };
1565
- }, []);
1825
+ }, [isDefault, isDisabled]);
1566
1826
  const renderLeftIcon = () => {
1567
1827
  if (effectiveBusy) {
1568
1828
  return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(fa6.FaSpinner, { className: styles.spinner }) }));
1569
1829
  }
1570
- else if (wasSuccessful && showCheckmark) {
1830
+ if (wasSuccessful && showCheckmark) {
1571
1831
  return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(AnimatedCheckmark, {}) }));
1572
1832
  }
1573
- else if (wasFailed && showFailIcon) {
1833
+ if (wasFailed && showFailIcon) {
1574
1834
  return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(AnimatedX, {}) }));
1575
1835
  }
1576
- else if (iconLeft) {
1836
+ if (iconLeft) {
1577
1837
  return jsxRuntimeExports.jsx("span", { className: styles.icon, children: iconLeft });
1578
1838
  }
1579
1839
  return null;
1580
1840
  };
1581
1841
  return (jsxRuntimeExports.jsx("button", { ref: buttonRef, className: [
1582
1842
  styles.button,
1583
- styles[buttonStyle], // Apply buttonStyle class
1843
+ styles[buttonStyle],
1584
1844
  styles[variant],
1585
1845
  styles[size],
1586
1846
  fullWidth ? styles.fullWidth : "",
1587
1847
  isDisabled ? styles.disabled : "",
1588
1848
  wasFailed ? styles.shake : "",
1589
- effectiveTheme === 'light' ? styles['force-light'] : styles['force-dark'], // Apply theme override class
1849
+ effectiveTheme === 'light' ? styles['force-light'] : styles['force-dark'],
1590
1850
  className,
1591
1851
  ].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 })] })] }) }));
1592
1852
  };
1593
1853
 
1594
- module.exports = ZestButton;
1854
+ const ZestProvider = ({ config, children }) => {
1855
+ return (jsxRuntimeExports.jsx(ZestContext.Provider, { value: config, children: children }));
1856
+ };
1857
+
1858
+ exports.ZestButton = ZestButton;
1859
+ exports.ZestProvider = ZestProvider;
1860
+ exports.useZest = useZest;
1595
1861
  //# sourceMappingURL=index.cjs.js.map