@pos-360/horizon 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-WLBF2GR6.mjs → chunk-3CJL52WY.mjs} +164 -34
- package/dist/chunk-3CJL52WY.mjs.map +1 -0
- package/dist/{chunk-T6DNK3SI.js → chunk-4UFEDQ7W.js} +141 -47
- package/dist/chunk-4UFEDQ7W.js.map +1 -0
- package/dist/{chunk-PEL2DCBC.mjs → chunk-IMKSKYMQ.mjs} +142 -48
- package/dist/chunk-IMKSKYMQ.mjs.map +1 -0
- package/dist/{chunk-4GEUF55E.js → chunk-LUUH457P.js} +162 -32
- package/dist/chunk-LUUH457P.js.map +1 -0
- package/dist/enhanced.d.mts +10 -1
- package/dist/enhanced.d.ts +10 -1
- package/dist/enhanced.js +27 -27
- package/dist/enhanced.mjs +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +112 -112
- package/dist/index.mjs +2 -2
- package/dist/primitives.d.mts +8 -2
- package/dist/primitives.d.ts +8 -2
- package/dist/primitives.js +85 -85
- package/dist/primitives.mjs +1 -1
- package/package.json +2 -1
- package/dist/chunk-4GEUF55E.js.map +0 -1
- package/dist/chunk-PEL2DCBC.mjs.map +0 -1
- package/dist/chunk-T6DNK3SI.js.map +0 -1
- package/dist/chunk-WLBF2GR6.mjs.map +0 -1
|
@@ -1257,6 +1257,7 @@ LargePanel.Stats = LargePanelStats;
|
|
|
1257
1257
|
LargePanel.Chart = LargePanelChart;
|
|
1258
1258
|
LargePanel.Content = LargePanelContent;
|
|
1259
1259
|
LargePanel.Table = LargePanelTable;
|
|
1260
|
+
var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1260
1261
|
var Input = React.forwardRef(
|
|
1261
1262
|
({
|
|
1262
1263
|
label,
|
|
@@ -1292,12 +1293,32 @@ var Input = React.forwardRef(
|
|
|
1292
1293
|
readOnly = false,
|
|
1293
1294
|
tabIndex = 0,
|
|
1294
1295
|
tooltip,
|
|
1296
|
+
passwordRules,
|
|
1297
|
+
onValidationChange,
|
|
1295
1298
|
...props
|
|
1296
1299
|
}, ref) => {
|
|
1297
1300
|
const [showTooltip, setShowTooltip] = React.useState(false);
|
|
1301
|
+
const [internalError, setInternalError] = React.useState("");
|
|
1302
|
+
const [hasBeenBlurred, setHasBeenBlurred] = React.useState(false);
|
|
1303
|
+
const [showPassword, setShowPassword] = React.useState(false);
|
|
1304
|
+
const inputInternalRef = React.useRef(null);
|
|
1305
|
+
const handleTogglePassword = () => {
|
|
1306
|
+
const input = inputInternalRef.current;
|
|
1307
|
+
const start = input?.selectionStart ?? null;
|
|
1308
|
+
const end = input?.selectionEnd ?? null;
|
|
1309
|
+
setShowPassword((v) => !v);
|
|
1310
|
+
requestAnimationFrame(() => {
|
|
1311
|
+
if (input && start !== null && end !== null) {
|
|
1312
|
+
input.focus();
|
|
1313
|
+
input.setSelectionRange(start, end);
|
|
1314
|
+
}
|
|
1315
|
+
});
|
|
1316
|
+
};
|
|
1298
1317
|
const isNumberType = type === "number";
|
|
1299
1318
|
const isSelectType = type === "select";
|
|
1300
1319
|
const isMobileType = type === "mobile";
|
|
1320
|
+
const isEmailType = type === "email";
|
|
1321
|
+
const isPasswordType = type === "password";
|
|
1301
1322
|
const [inputValue, setInputValue] = React.useState(
|
|
1302
1323
|
value !== void 0 ? value.toString() : ""
|
|
1303
1324
|
);
|
|
@@ -1306,6 +1327,28 @@ var Input = React.forwardRef(
|
|
|
1306
1327
|
setInputValue(value.toString());
|
|
1307
1328
|
}
|
|
1308
1329
|
}, [value]);
|
|
1330
|
+
const displayError = error || internalError;
|
|
1331
|
+
const currentPasswordValue = isPasswordType ? inputValue : "";
|
|
1332
|
+
const passwordRuleResults = passwordRules ? {
|
|
1333
|
+
minLength: passwordRules.minLength !== void 0 ? currentPasswordValue.length >= passwordRules.minLength : null,
|
|
1334
|
+
uppercase: passwordRules.requireUppercase ? /[A-Z]/.test(currentPasswordValue) : null,
|
|
1335
|
+
lowercase: passwordRules.requireLowercase ? /[a-z]/.test(currentPasswordValue) : null,
|
|
1336
|
+
number: passwordRules.requireNumber ? /[0-9]/.test(currentPasswordValue) : null,
|
|
1337
|
+
specialChar: passwordRules.requireSpecialChar ? /[^a-zA-Z0-9]/.test(currentPasswordValue) : null
|
|
1338
|
+
} : null;
|
|
1339
|
+
const isPasswordValid = passwordRuleResults ? Object.values(passwordRuleResults).every((v) => v === null || v === true) : true;
|
|
1340
|
+
React.useEffect(() => {
|
|
1341
|
+
if (isPasswordType && onValidationChange) {
|
|
1342
|
+
onValidationChange(isPasswordValid);
|
|
1343
|
+
}
|
|
1344
|
+
}, [isPasswordValid, isPasswordType, onValidationChange]);
|
|
1345
|
+
const passwordRuleLabels = {
|
|
1346
|
+
minLength: (r) => `At least ${r.minLength} characters`,
|
|
1347
|
+
uppercase: () => "One uppercase letter",
|
|
1348
|
+
lowercase: () => "One lowercase letter",
|
|
1349
|
+
number: () => "One number",
|
|
1350
|
+
specialChar: () => "One special character"
|
|
1351
|
+
};
|
|
1309
1352
|
const formatNumber = (num) => {
|
|
1310
1353
|
if (precision > 0) {
|
|
1311
1354
|
return parseFloat(num.toFixed(precision));
|
|
@@ -1321,6 +1364,29 @@ var Input = React.forwardRef(
|
|
|
1321
1364
|
if (max !== void 0 && num > max) return false;
|
|
1322
1365
|
return true;
|
|
1323
1366
|
};
|
|
1367
|
+
const handleKeyDown = (e) => {
|
|
1368
|
+
if (!isNumberType) return;
|
|
1369
|
+
const allowedKeys = [
|
|
1370
|
+
"Backspace",
|
|
1371
|
+
"Delete",
|
|
1372
|
+
"Tab",
|
|
1373
|
+
"Enter",
|
|
1374
|
+
"ArrowLeft",
|
|
1375
|
+
"ArrowRight",
|
|
1376
|
+
"ArrowUp",
|
|
1377
|
+
"ArrowDown",
|
|
1378
|
+
"Home",
|
|
1379
|
+
"End"
|
|
1380
|
+
];
|
|
1381
|
+
const isAllowedKey = allowedKeys.includes(e.key);
|
|
1382
|
+
const isDigit = /^[0-9]$/.test(e.key);
|
|
1383
|
+
const isDecimalPoint = e.key === "." && precision > 0 && !inputValue.includes(".");
|
|
1384
|
+
const isNegativeSign = e.key === "-" && allowNegative && inputValue === "";
|
|
1385
|
+
const isCtrlOrMeta = e.ctrlKey || e.metaKey;
|
|
1386
|
+
if (!isAllowedKey && !isDigit && !isDecimalPoint && !isNegativeSign && !isCtrlOrMeta) {
|
|
1387
|
+
e.preventDefault();
|
|
1388
|
+
}
|
|
1389
|
+
};
|
|
1324
1390
|
const handleInputChange = (e) => {
|
|
1325
1391
|
if (isMobileType) {
|
|
1326
1392
|
const digits = (e.target.value || "").replace(/\D/g, "").slice(0, 10);
|
|
@@ -1329,7 +1395,15 @@ var Input = React.forwardRef(
|
|
|
1329
1395
|
});
|
|
1330
1396
|
return;
|
|
1331
1397
|
}
|
|
1332
|
-
if (
|
|
1398
|
+
if (isPasswordType) {
|
|
1399
|
+
const filtered = e.target.value.replace(/\s/g, "");
|
|
1400
|
+
setInputValue(filtered);
|
|
1401
|
+
if (filtered !== e.target.value && onChange) {
|
|
1402
|
+
onChange({ ...e, target: { ...e.target, value: filtered } });
|
|
1403
|
+
} else {
|
|
1404
|
+
onChange?.(e);
|
|
1405
|
+
}
|
|
1406
|
+
} else if (isNumberType) {
|
|
1333
1407
|
const newValue = e.target.value;
|
|
1334
1408
|
if (newValue === "" || allowNegative && newValue === "-") {
|
|
1335
1409
|
setInputValue(newValue);
|
|
@@ -1339,13 +1413,51 @@ var Input = React.forwardRef(
|
|
|
1339
1413
|
setInputValue(newValue);
|
|
1340
1414
|
const numValue = parseFloat(newValue);
|
|
1341
1415
|
if (!isNaN(numValue)) {
|
|
1342
|
-
onNumberChange(formatNumber(numValue));
|
|
1416
|
+
onNumberChange?.(formatNumber(numValue));
|
|
1343
1417
|
}
|
|
1344
1418
|
}
|
|
1345
1419
|
} else {
|
|
1346
1420
|
onChange?.(e);
|
|
1347
1421
|
}
|
|
1348
1422
|
};
|
|
1423
|
+
const handleFocus = (e) => {
|
|
1424
|
+
if (isEmailType || isMobileType) {
|
|
1425
|
+
setInternalError("");
|
|
1426
|
+
}
|
|
1427
|
+
onFocus?.(e);
|
|
1428
|
+
};
|
|
1429
|
+
const handleBlur = (e) => {
|
|
1430
|
+
setHasBeenBlurred(true);
|
|
1431
|
+
if (isEmailType) {
|
|
1432
|
+
const val = (e.target.value || "").trim();
|
|
1433
|
+
if (val && !EMAIL_REGEX.test(val)) {
|
|
1434
|
+
setInternalError("Please enter a valid email address");
|
|
1435
|
+
} else {
|
|
1436
|
+
setInternalError("");
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
if (isMobileType) {
|
|
1440
|
+
const digits = (e.target.value || "").replace(/\D/g, "");
|
|
1441
|
+
if (digits && digits.length !== 10) {
|
|
1442
|
+
setInternalError("Please enter a valid 10-digit phone number");
|
|
1443
|
+
} else {
|
|
1444
|
+
setInternalError("");
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1447
|
+
if (isNumberType) {
|
|
1448
|
+
if (inputValue !== "" && inputValue !== "-") {
|
|
1449
|
+
const numValue = parseFloat(inputValue);
|
|
1450
|
+
if (!isNaN(numValue)) {
|
|
1451
|
+
const cleanValue = formatNumber(numValue);
|
|
1452
|
+
setInputValue(cleanValue.toString());
|
|
1453
|
+
onNumberChange?.(cleanValue);
|
|
1454
|
+
}
|
|
1455
|
+
} else if (inputValue === "" || inputValue === "-") {
|
|
1456
|
+
setInputValue("");
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
onBlur?.(e);
|
|
1460
|
+
};
|
|
1349
1461
|
const handleSelectChange = (e) => {
|
|
1350
1462
|
onSelectChange?.(e.target.value);
|
|
1351
1463
|
};
|
|
@@ -1367,22 +1479,7 @@ var Input = React.forwardRef(
|
|
|
1367
1479
|
setInputValue(finalValue.toString());
|
|
1368
1480
|
onNumberChange?.(finalValue);
|
|
1369
1481
|
};
|
|
1370
|
-
const
|
|
1371
|
-
if (isNumberType && onNumberChange) {
|
|
1372
|
-
if (inputValue !== "" && inputValue !== "-") {
|
|
1373
|
-
const numValue = parseFloat(inputValue);
|
|
1374
|
-
if (!isNaN(numValue)) {
|
|
1375
|
-
const cleanValue = formatNumber(numValue);
|
|
1376
|
-
setInputValue(cleanValue.toString());
|
|
1377
|
-
onNumberChange(cleanValue);
|
|
1378
|
-
}
|
|
1379
|
-
} else if (inputValue === "" || inputValue === "-") {
|
|
1380
|
-
setInputValue("");
|
|
1381
|
-
}
|
|
1382
|
-
}
|
|
1383
|
-
onBlur?.(e);
|
|
1384
|
-
};
|
|
1385
|
-
const baseInputStyles = "w-full transition-colors focus:outline-none min-h-[52px]";
|
|
1482
|
+
const baseInputStyles = "w-full transition-colors focus:outline-none";
|
|
1386
1483
|
const sizeStyles = {
|
|
1387
1484
|
sm: "px-3 py-2 text-sm",
|
|
1388
1485
|
md: "px-4 py-3 text-base",
|
|
@@ -1400,13 +1497,13 @@ var Input = React.forwardRef(
|
|
|
1400
1497
|
};
|
|
1401
1498
|
const variantStyles2 = {
|
|
1402
1499
|
default: "border bg-white/60 dark:bg-neutral-800/60 backdrop-blur-sm transition-colors duration-hz-slow ease-hz-default rounded-hz-md",
|
|
1403
|
-
filled: "border-
|
|
1500
|
+
filled: "border border-transparent bg-neutral-50/60 dark:bg-neutral-700/60 backdrop-blur-sm transition-colors duration-hz-slow ease-hz-default rounded-hz-md"
|
|
1404
1501
|
};
|
|
1405
|
-
const stateStyles =
|
|
1502
|
+
const stateStyles = displayError ? "border-rose-500/50 dark:border-rose-400/50 focus:border-rose-600/70 dark:focus:border-rose-500/70 focus:ring-1 focus:ring-rose-500/50 dark:focus:ring-rose-400/50" : "border-neutral-300/50 dark:border-neutral-600/50 focus:border-blue-500/70 dark:focus:border-blue-400/70 focus:ring-1 focus:ring-blue-500/50 dark:focus:ring-blue-400/50";
|
|
1406
1503
|
const disabledStyles = disabled ? "bg-neutral-100/60 dark:bg-neutral-700/60 text-neutral-500 dark:text-neutral-400 cursor-not-allowed" : "text-neutral-900 dark:text-neutral-100";
|
|
1407
1504
|
const hasControls = isNumberType && showControls;
|
|
1408
1505
|
const hasLeadingContent = leadingIcon || leadingDecorator;
|
|
1409
|
-
const hasTrailingContent = trailingIcon || trailingDecorator || hasControls;
|
|
1506
|
+
const hasTrailingContent = trailingIcon || trailingDecorator || hasControls || isPasswordType;
|
|
1410
1507
|
const inputClasses = `
|
|
1411
1508
|
${baseInputStyles}
|
|
1412
1509
|
${sizeStyles[size]}
|
|
@@ -1430,6 +1527,7 @@ var Input = React.forwardRef(
|
|
|
1430
1527
|
`.trim().replace(/\s+/g, " ");
|
|
1431
1528
|
const canDecrement = !disabled && (min === void 0 || (parseFloat(inputValue) || 0) > min);
|
|
1432
1529
|
const canIncrement = !disabled && (max === void 0 || (parseFloat(inputValue) || 0) < max);
|
|
1530
|
+
const showPasswordRules = isPasswordType && passwordRules && hasBeenBlurred;
|
|
1433
1531
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full", children: [
|
|
1434
1532
|
label && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative mb-2", children: [
|
|
1435
1533
|
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "text-sm font-medium text-neutral-700 dark:text-neutral-300 transition-colors duration-hz-slow ease-hz-default flex items-center", children: [
|
|
@@ -1488,13 +1586,18 @@ var Input = React.forwardRef(
|
|
|
1488
1586
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
1489
1587
|
"input",
|
|
1490
1588
|
{
|
|
1491
|
-
ref
|
|
1492
|
-
|
|
1589
|
+
ref: (node) => {
|
|
1590
|
+
inputInternalRef.current = node;
|
|
1591
|
+
if (typeof ref === "function") ref(node);
|
|
1592
|
+
else if (ref) ref.current = node;
|
|
1593
|
+
},
|
|
1594
|
+
type: isMobileType ? "tel" : isNumberType ? "text" : isPasswordType ? showPassword ? "text" : "password" : type,
|
|
1493
1595
|
inputMode: isMobileType ? "numeric" : isNumberType ? "numeric" : void 0,
|
|
1494
|
-
value: isNumberType
|
|
1596
|
+
value: isNumberType || isPasswordType ? inputValue : value,
|
|
1495
1597
|
onChange: handleInputChange,
|
|
1496
|
-
|
|
1497
|
-
|
|
1598
|
+
onKeyDown: isNumberType ? handleKeyDown : void 0,
|
|
1599
|
+
onFocus: handleFocus,
|
|
1600
|
+
onBlur: handleBlur,
|
|
1498
1601
|
placeholder,
|
|
1499
1602
|
disabled,
|
|
1500
1603
|
required,
|
|
@@ -1510,6 +1613,7 @@ var Input = React.forwardRef(
|
|
|
1510
1613
|
"button",
|
|
1511
1614
|
{
|
|
1512
1615
|
type: "button",
|
|
1616
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1513
1617
|
onClick: handleDecrement,
|
|
1514
1618
|
disabled: !canDecrement,
|
|
1515
1619
|
className: `
|
|
@@ -1527,6 +1631,7 @@ var Input = React.forwardRef(
|
|
|
1527
1631
|
"button",
|
|
1528
1632
|
{
|
|
1529
1633
|
type: "button",
|
|
1634
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1530
1635
|
onClick: handleIncrement,
|
|
1531
1636
|
disabled: !canIncrement,
|
|
1532
1637
|
className: `
|
|
@@ -1540,6 +1645,17 @@ var Input = React.forwardRef(
|
|
|
1540
1645
|
}
|
|
1541
1646
|
)
|
|
1542
1647
|
] }) }),
|
|
1648
|
+
isPasswordType && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1649
|
+
"button",
|
|
1650
|
+
{
|
|
1651
|
+
type: "button",
|
|
1652
|
+
tabIndex: -1,
|
|
1653
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1654
|
+
onClick: handleTogglePassword,
|
|
1655
|
+
className: "absolute inset-y-0 right-0 pr-3 flex items-center text-neutral-400 hover:text-neutral-600 dark:hover:text-neutral-300 transition-colors",
|
|
1656
|
+
children: showPassword ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeOff, { size: iconSizeStyles[size] }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Eye, { size: iconSizeStyles[size] })
|
|
1657
|
+
}
|
|
1658
|
+
),
|
|
1543
1659
|
isSelectType && !trailingIcon && !trailingDecorator && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1544
1660
|
lucideReact.ChevronDown,
|
|
1545
1661
|
{
|
|
@@ -1560,10 +1676,24 @@ var Input = React.forwardRef(
|
|
|
1560
1676
|
}
|
|
1561
1677
|
)
|
|
1562
1678
|
] }),
|
|
1563
|
-
(
|
|
1564
|
-
|
|
1565
|
-
helperText && !
|
|
1566
|
-
] })
|
|
1679
|
+
(displayError || helperText) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2", children: [
|
|
1680
|
+
displayError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-rose-600 dark:text-rose-400 transition-colors duration-hz-slow ease-hz-default", children: displayError }),
|
|
1681
|
+
helperText && !displayError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-neutral-500 dark:text-neutral-400 transition-colors duration-hz-slow ease-hz-default", children: helperText })
|
|
1682
|
+
] }),
|
|
1683
|
+
showPasswordRules && passwordRuleResults && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "mt-2 space-y-1", children: Object.keys(passwordRuleResults).filter((key) => passwordRuleResults[key] !== null).map((key) => {
|
|
1684
|
+
const passed = passwordRuleResults[key];
|
|
1685
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1686
|
+
"li",
|
|
1687
|
+
{
|
|
1688
|
+
className: `flex items-center gap-1.5 text-xs transition-colors ${passed ? "text-green-600 dark:text-green-400" : "text-rose-500 dark:text-rose-400"}`,
|
|
1689
|
+
children: [
|
|
1690
|
+
passed ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-3 h-3 shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-3 h-3 shrink-0" }),
|
|
1691
|
+
passwordRules && passwordRuleLabels[key](passwordRules)
|
|
1692
|
+
]
|
|
1693
|
+
},
|
|
1694
|
+
key
|
|
1695
|
+
);
|
|
1696
|
+
}) })
|
|
1567
1697
|
] });
|
|
1568
1698
|
}
|
|
1569
1699
|
);
|
|
@@ -2597,5 +2727,5 @@ exports.TextButton = TextButton;
|
|
|
2597
2727
|
exports.Toast = Toast;
|
|
2598
2728
|
exports.useDashboardContext = useDashboardContext;
|
|
2599
2729
|
exports.useSideNavContext = useSideNavContext;
|
|
2600
|
-
//# sourceMappingURL=chunk-
|
|
2601
|
-
//# sourceMappingURL=chunk-
|
|
2730
|
+
//# sourceMappingURL=chunk-LUUH457P.js.map
|
|
2731
|
+
//# sourceMappingURL=chunk-LUUH457P.js.map
|