jattac.libs.web.zest-button 1.1.0 → 1.1.1
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 +66 -40
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +66 -40
- package/dist/index.esm.js.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var require$$0 = require('react');
|
|
4
|
-
var
|
|
4
|
+
var fa6 = require('react-icons/fa6');
|
|
5
5
|
|
|
6
6
|
var jsxRuntime = {exports: {}};
|
|
7
7
|
|
|
@@ -1396,10 +1396,22 @@ const ZestButton = ({ visualOptions = {}, busyOptions = {}, successOptions = {},
|
|
|
1396
1396
|
const { variant = "standard", size = "md", fullWidth = false, iconLeft, iconRight, } = visualOptions;
|
|
1397
1397
|
const { handleInternally = true, preventRageClick = true, minBusyDurationMs = 500, } = busyOptions;
|
|
1398
1398
|
const { showCheckmark = true, showFailIcon = true, autoResetAfterMs = 2000, } = successOptions;
|
|
1399
|
+
// Edge Case 4: Add warnings for very short durations in development
|
|
1400
|
+
require$$0.useEffect(() => {
|
|
1401
|
+
if (process.env.NODE_ENV === 'development') {
|
|
1402
|
+
if (minBusyDurationMs > 0 && minBusyDurationMs < 100) {
|
|
1403
|
+
console.warn(`ZestButton: 'minBusyDurationMs' is set to ${minBusyDurationMs}ms. Very short durations can lead to visual flickering and a poor user experience. Consider a value of 100ms or more.`);
|
|
1404
|
+
}
|
|
1405
|
+
if (autoResetAfterMs > 0 && autoResetAfterMs < 100) {
|
|
1406
|
+
console.warn(`ZestButton: 'autoResetAfterMs' is set to ${autoResetAfterMs}ms. Very short durations can make success/fail feedback hard to perceive. Consider a value of 100ms or more.`);
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
}, [minBusyDurationMs, autoResetAfterMs]);
|
|
1399
1410
|
const [internalBusy, setInternalBusy] = require$$0.useState(false);
|
|
1400
1411
|
const [wasSuccessful, setWasSuccessful] = require$$0.useState(false);
|
|
1401
1412
|
const [wasFailed, setWasFailed] = require$$0.useState(false);
|
|
1402
1413
|
const buttonRef = require$$0.useRef(null);
|
|
1414
|
+
const failTimeoutRef = require$$0.useRef(null); // Bug 1: Add useRef for failTimeout
|
|
1403
1415
|
const [currentChildren, setCurrentChildren] = require$$0.useState(children);
|
|
1404
1416
|
const [awaitingConfirm, setAwaitingConfirm] = require$$0.useState(false);
|
|
1405
1417
|
// ✅ interval ref for confirm countdown
|
|
@@ -1418,6 +1430,15 @@ const ZestButton = ({ visualOptions = {}, busyOptions = {}, successOptions = {},
|
|
|
1418
1430
|
const isDisabled = disabled ||
|
|
1419
1431
|
effectiveBusy ||
|
|
1420
1432
|
(preventRageClick && (wasSuccessful || wasFailed));
|
|
1433
|
+
// Move handleClick, stopWaiting, and handleConfirmClick declarations here
|
|
1434
|
+
const stopWaiting = () => {
|
|
1435
|
+
if (confirmIntervalRef.current) {
|
|
1436
|
+
clearInterval(confirmIntervalRef.current);
|
|
1437
|
+
confirmIntervalRef.current = null;
|
|
1438
|
+
}
|
|
1439
|
+
setCurrentChildren(children);
|
|
1440
|
+
setAwaitingConfirm(false);
|
|
1441
|
+
};
|
|
1421
1442
|
const handleClick = async (e) => {
|
|
1422
1443
|
if (preventRageClick && internalBusy)
|
|
1423
1444
|
return;
|
|
@@ -1449,45 +1470,14 @@ const ZestButton = ({ visualOptions = {}, busyOptions = {}, successOptions = {},
|
|
|
1449
1470
|
onClick(e);
|
|
1450
1471
|
}
|
|
1451
1472
|
};
|
|
1452
|
-
// auto-reset success/failure state
|
|
1453
|
-
require$$0.useEffect(() => {
|
|
1454
|
-
if ((wasSuccessful || wasFailed) && autoResetAfterMs) {
|
|
1455
|
-
const timeout = setTimeout(() => {
|
|
1456
|
-
setWasSuccessful(false);
|
|
1457
|
-
setWasFailed(false);
|
|
1458
|
-
}, autoResetAfterMs);
|
|
1459
|
-
return () => clearTimeout(timeout);
|
|
1460
|
-
}
|
|
1461
|
-
}, [wasSuccessful, wasFailed, autoResetAfterMs]);
|
|
1462
|
-
// Enter key handler if isDefault
|
|
1463
|
-
require$$0.useEffect(() => {
|
|
1464
|
-
if (!isDefault || isDisabled)
|
|
1465
|
-
return;
|
|
1466
|
-
const listener = (e) => {
|
|
1467
|
-
const target = e.target;
|
|
1468
|
-
if (e.key === "Enter" &&
|
|
1469
|
-
!e.repeat &&
|
|
1470
|
-
!e.defaultPrevented &&
|
|
1471
|
-
!(target instanceof HTMLTextAreaElement)) {
|
|
1472
|
-
e.preventDefault();
|
|
1473
|
-
buttonRef.current?.click();
|
|
1474
|
-
}
|
|
1475
|
-
};
|
|
1476
|
-
document.addEventListener("keydown", listener);
|
|
1477
|
-
return () => document.removeEventListener("keydown", listener);
|
|
1478
|
-
}, [isDefault, isDisabled]);
|
|
1479
|
-
const stopWaiting = () => {
|
|
1480
|
-
if (confirmIntervalRef.current) {
|
|
1481
|
-
clearInterval(confirmIntervalRef.current);
|
|
1482
|
-
confirmIntervalRef.current = null;
|
|
1483
|
-
}
|
|
1484
|
-
setCurrentChildren(children);
|
|
1485
|
-
setAwaitingConfirm(false);
|
|
1486
|
-
};
|
|
1487
1473
|
const handleConfirmClick = async (e) => {
|
|
1488
1474
|
if (!props.confirmOptions) {
|
|
1489
1475
|
return handleClick(e);
|
|
1490
1476
|
}
|
|
1477
|
+
// Edge Case 3: Add warning for missing onClick with confirmOptions
|
|
1478
|
+
if (props.confirmOptions && !onClick) { // Use destructured onClick
|
|
1479
|
+
console.warn("ZestButton: 'confirmOptions' are provided but 'onClick' handler is missing. The button will confirm but perform no action.");
|
|
1480
|
+
}
|
|
1491
1481
|
if (awaitingConfirm) {
|
|
1492
1482
|
stopWaiting();
|
|
1493
1483
|
return handleClick(e);
|
|
@@ -1502,33 +1492,69 @@ const ZestButton = ({ visualOptions = {}, busyOptions = {}, successOptions = {},
|
|
|
1502
1492
|
if (timeRemaining <= 0) {
|
|
1503
1493
|
stopWaiting();
|
|
1504
1494
|
setWasFailed(true); // Indicate failure for shake animation
|
|
1505
|
-
|
|
1495
|
+
// Bug 1: Clear any existing timeout before setting a new one
|
|
1496
|
+
if (failTimeoutRef.current) {
|
|
1497
|
+
clearTimeout(failTimeoutRef.current);
|
|
1498
|
+
}
|
|
1499
|
+
failTimeoutRef.current = setTimeout(() => {
|
|
1506
1500
|
setWasFailed(false);
|
|
1501
|
+
failTimeoutRef.current = null; // Clear ref after timeout fires
|
|
1507
1502
|
}, 400); // Shake animation duration
|
|
1508
|
-
// No need to return clearTimeout, as this timeout is for visual feedback only
|
|
1509
1503
|
}
|
|
1510
1504
|
else {
|
|
1511
1505
|
setCurrentChildren(`${displayLabel} (${timeRemaining}s)`);
|
|
1512
1506
|
}
|
|
1513
1507
|
}, 1000); // Update once per second
|
|
1514
1508
|
};
|
|
1509
|
+
// auto-reset success/failure state
|
|
1510
|
+
require$$0.useEffect(() => {
|
|
1511
|
+
if ((wasSuccessful || wasFailed) && autoResetAfterMs) {
|
|
1512
|
+
const timeout = setTimeout(() => {
|
|
1513
|
+
setWasSuccessful(false);
|
|
1514
|
+
setWasFailed(false);
|
|
1515
|
+
}, autoResetAfterMs);
|
|
1516
|
+
return () => clearTimeout(timeout);
|
|
1517
|
+
}
|
|
1518
|
+
}, [wasSuccessful, wasFailed, autoResetAfterMs]);
|
|
1519
|
+
// Enter key handler if isDefault
|
|
1520
|
+
require$$0.useEffect(() => {
|
|
1521
|
+
if (!isDefault || isDisabled)
|
|
1522
|
+
return;
|
|
1523
|
+
const listener = (e) => {
|
|
1524
|
+
const target = e.target;
|
|
1525
|
+
if (e.key === "Enter" &&
|
|
1526
|
+
!e.repeat &&
|
|
1527
|
+
!e.defaultPrevented &&
|
|
1528
|
+
!(target instanceof HTMLTextAreaElement)) {
|
|
1529
|
+
e.preventDefault();
|
|
1530
|
+
// Bug 2: Directly call handleConfirmClick to respect confirmation logic
|
|
1531
|
+
handleConfirmClick(e);
|
|
1532
|
+
}
|
|
1533
|
+
};
|
|
1534
|
+
document.addEventListener("keydown", listener);
|
|
1535
|
+
return () => document.removeEventListener("keydown", listener);
|
|
1536
|
+
}, [isDefault, isDisabled, handleConfirmClick]); // Bug 2: Add handleConfirmClick to dependencies
|
|
1515
1537
|
// cleanup on unmount
|
|
1516
1538
|
require$$0.useEffect(() => {
|
|
1517
1539
|
return () => {
|
|
1518
1540
|
if (confirmIntervalRef.current) {
|
|
1519
1541
|
clearInterval(confirmIntervalRef.current);
|
|
1520
1542
|
}
|
|
1543
|
+
// Bug 1: Add cleanup for failTimeoutRef
|
|
1544
|
+
if (failTimeoutRef.current) {
|
|
1545
|
+
clearTimeout(failTimeoutRef.current);
|
|
1546
|
+
}
|
|
1521
1547
|
};
|
|
1522
1548
|
}, []);
|
|
1523
1549
|
const renderLeftIcon = () => {
|
|
1524
1550
|
if (effectiveBusy) {
|
|
1525
|
-
return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(
|
|
1551
|
+
return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(fa6.FaSpinner, { className: styles.spinner }) }));
|
|
1526
1552
|
}
|
|
1527
1553
|
else if (wasSuccessful && showCheckmark) {
|
|
1528
1554
|
return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(AnimatedCheckmark, {}) }));
|
|
1529
1555
|
}
|
|
1530
1556
|
else if (wasFailed && showFailIcon) {
|
|
1531
|
-
return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}
|
|
1557
|
+
return (jsxRuntimeExports.jsx("span", { className: `${styles.icon} ${styles.fadeIn}`, children: jsxRuntimeExports.jsx(AnimatedX, {}) }));
|
|
1532
1558
|
}
|
|
1533
1559
|
else if (iconLeft) {
|
|
1534
1560
|
return jsxRuntimeExports.jsx("span", { className: styles.icon, children: iconLeft });
|