@pos-360/horizon 0.7.1 → 0.9.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-TK3Z2O2A.js → chunk-JQJP5M4C.js} +137 -36
- package/dist/chunk-JQJP5M4C.js.map +1 -0
- package/dist/{chunk-4GEUF55E.js → chunk-LUUH457P.js} +162 -32
- package/dist/chunk-LUUH457P.js.map +1 -0
- package/dist/{chunk-4ODZYEVR.mjs → chunk-XRB5L6TH.mjs} +137 -38
- package/dist/chunk-XRB5L6TH.mjs.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 +120 -112
- package/dist/index.mjs +2 -2
- package/dist/primitives.d.mts +16 -2
- package/dist/primitives.d.ts +16 -2
- package/dist/primitives.js +93 -85
- package/dist/primitives.mjs +1 -1
- package/package.json +2 -1
- package/dist/chunk-4GEUF55E.js.map +0 -1
- package/dist/chunk-4ODZYEVR.mjs.map +0 -1
- package/dist/chunk-TK3Z2O2A.js.map +0 -1
- package/dist/chunk-WLBF2GR6.mjs.map +0 -1
|
@@ -2,8 +2,8 @@ import { cn, Text, Badge } from './chunk-E3UN74IA.mjs';
|
|
|
2
2
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
3
3
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import { createContext, forwardRef, useId, useMemo, useState,
|
|
6
|
-
import { ChevronLeft, ChevronRight, Info, ChevronDown, ChevronUp, TrendingUp, TrendingDown, Minus, LayoutGrid, List,
|
|
5
|
+
import { createContext, forwardRef, useId, useMemo, useState, useRef, useEffect, useCallback, useContext } from 'react';
|
|
6
|
+
import { ChevronLeft, ChevronRight, Info, ChevronDown, ChevronUp, EyeOff, Eye, Check, X, TrendingUp, TrendingDown, Minus, LayoutGrid, List, ExternalLink, Moon, Rocket, Star, Globe, Orbit, Sparkles, AlertTriangle } from 'lucide-react';
|
|
7
7
|
export { Globe, Moon, Orbit, Rocket, Sparkles, Star } from 'lucide-react';
|
|
8
8
|
import { Bar, AreaClosed, LinePath, Pie } from '@visx/shape';
|
|
9
9
|
import { Group } from '@visx/group';
|
|
@@ -1236,6 +1236,7 @@ LargePanel.Stats = LargePanelStats;
|
|
|
1236
1236
|
LargePanel.Chart = LargePanelChart;
|
|
1237
1237
|
LargePanel.Content = LargePanelContent;
|
|
1238
1238
|
LargePanel.Table = LargePanelTable;
|
|
1239
|
+
var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1239
1240
|
var Input = forwardRef(
|
|
1240
1241
|
({
|
|
1241
1242
|
label,
|
|
@@ -1271,12 +1272,32 @@ var Input = forwardRef(
|
|
|
1271
1272
|
readOnly = false,
|
|
1272
1273
|
tabIndex = 0,
|
|
1273
1274
|
tooltip,
|
|
1275
|
+
passwordRules,
|
|
1276
|
+
onValidationChange,
|
|
1274
1277
|
...props
|
|
1275
1278
|
}, ref) => {
|
|
1276
1279
|
const [showTooltip, setShowTooltip] = useState(false);
|
|
1280
|
+
const [internalError, setInternalError] = useState("");
|
|
1281
|
+
const [hasBeenBlurred, setHasBeenBlurred] = useState(false);
|
|
1282
|
+
const [showPassword, setShowPassword] = useState(false);
|
|
1283
|
+
const inputInternalRef = useRef(null);
|
|
1284
|
+
const handleTogglePassword = () => {
|
|
1285
|
+
const input = inputInternalRef.current;
|
|
1286
|
+
const start = input?.selectionStart ?? null;
|
|
1287
|
+
const end = input?.selectionEnd ?? null;
|
|
1288
|
+
setShowPassword((v) => !v);
|
|
1289
|
+
requestAnimationFrame(() => {
|
|
1290
|
+
if (input && start !== null && end !== null) {
|
|
1291
|
+
input.focus();
|
|
1292
|
+
input.setSelectionRange(start, end);
|
|
1293
|
+
}
|
|
1294
|
+
});
|
|
1295
|
+
};
|
|
1277
1296
|
const isNumberType = type === "number";
|
|
1278
1297
|
const isSelectType = type === "select";
|
|
1279
1298
|
const isMobileType = type === "mobile";
|
|
1299
|
+
const isEmailType = type === "email";
|
|
1300
|
+
const isPasswordType = type === "password";
|
|
1280
1301
|
const [inputValue, setInputValue] = useState(
|
|
1281
1302
|
value !== void 0 ? value.toString() : ""
|
|
1282
1303
|
);
|
|
@@ -1285,6 +1306,28 @@ var Input = forwardRef(
|
|
|
1285
1306
|
setInputValue(value.toString());
|
|
1286
1307
|
}
|
|
1287
1308
|
}, [value]);
|
|
1309
|
+
const displayError = error || internalError;
|
|
1310
|
+
const currentPasswordValue = isPasswordType ? inputValue : "";
|
|
1311
|
+
const passwordRuleResults = passwordRules ? {
|
|
1312
|
+
minLength: passwordRules.minLength !== void 0 ? currentPasswordValue.length >= passwordRules.minLength : null,
|
|
1313
|
+
uppercase: passwordRules.requireUppercase ? /[A-Z]/.test(currentPasswordValue) : null,
|
|
1314
|
+
lowercase: passwordRules.requireLowercase ? /[a-z]/.test(currentPasswordValue) : null,
|
|
1315
|
+
number: passwordRules.requireNumber ? /[0-9]/.test(currentPasswordValue) : null,
|
|
1316
|
+
specialChar: passwordRules.requireSpecialChar ? /[^a-zA-Z0-9]/.test(currentPasswordValue) : null
|
|
1317
|
+
} : null;
|
|
1318
|
+
const isPasswordValid = passwordRuleResults ? Object.values(passwordRuleResults).every((v) => v === null || v === true) : true;
|
|
1319
|
+
useEffect(() => {
|
|
1320
|
+
if (isPasswordType && onValidationChange) {
|
|
1321
|
+
onValidationChange(isPasswordValid);
|
|
1322
|
+
}
|
|
1323
|
+
}, [isPasswordValid, isPasswordType, onValidationChange]);
|
|
1324
|
+
const passwordRuleLabels = {
|
|
1325
|
+
minLength: (r) => `At least ${r.minLength} characters`,
|
|
1326
|
+
uppercase: () => "One uppercase letter",
|
|
1327
|
+
lowercase: () => "One lowercase letter",
|
|
1328
|
+
number: () => "One number",
|
|
1329
|
+
specialChar: () => "One special character"
|
|
1330
|
+
};
|
|
1288
1331
|
const formatNumber = (num) => {
|
|
1289
1332
|
if (precision > 0) {
|
|
1290
1333
|
return parseFloat(num.toFixed(precision));
|
|
@@ -1300,6 +1343,29 @@ var Input = forwardRef(
|
|
|
1300
1343
|
if (max !== void 0 && num > max) return false;
|
|
1301
1344
|
return true;
|
|
1302
1345
|
};
|
|
1346
|
+
const handleKeyDown = (e) => {
|
|
1347
|
+
if (!isNumberType) return;
|
|
1348
|
+
const allowedKeys = [
|
|
1349
|
+
"Backspace",
|
|
1350
|
+
"Delete",
|
|
1351
|
+
"Tab",
|
|
1352
|
+
"Enter",
|
|
1353
|
+
"ArrowLeft",
|
|
1354
|
+
"ArrowRight",
|
|
1355
|
+
"ArrowUp",
|
|
1356
|
+
"ArrowDown",
|
|
1357
|
+
"Home",
|
|
1358
|
+
"End"
|
|
1359
|
+
];
|
|
1360
|
+
const isAllowedKey = allowedKeys.includes(e.key);
|
|
1361
|
+
const isDigit = /^[0-9]$/.test(e.key);
|
|
1362
|
+
const isDecimalPoint = e.key === "." && precision > 0 && !inputValue.includes(".");
|
|
1363
|
+
const isNegativeSign = e.key === "-" && allowNegative && inputValue === "";
|
|
1364
|
+
const isCtrlOrMeta = e.ctrlKey || e.metaKey;
|
|
1365
|
+
if (!isAllowedKey && !isDigit && !isDecimalPoint && !isNegativeSign && !isCtrlOrMeta) {
|
|
1366
|
+
e.preventDefault();
|
|
1367
|
+
}
|
|
1368
|
+
};
|
|
1303
1369
|
const handleInputChange = (e) => {
|
|
1304
1370
|
if (isMobileType) {
|
|
1305
1371
|
const digits = (e.target.value || "").replace(/\D/g, "").slice(0, 10);
|
|
@@ -1308,7 +1374,15 @@ var Input = forwardRef(
|
|
|
1308
1374
|
});
|
|
1309
1375
|
return;
|
|
1310
1376
|
}
|
|
1311
|
-
if (
|
|
1377
|
+
if (isPasswordType) {
|
|
1378
|
+
const filtered = e.target.value.replace(/\s/g, "");
|
|
1379
|
+
setInputValue(filtered);
|
|
1380
|
+
if (filtered !== e.target.value && onChange) {
|
|
1381
|
+
onChange({ ...e, target: { ...e.target, value: filtered } });
|
|
1382
|
+
} else {
|
|
1383
|
+
onChange?.(e);
|
|
1384
|
+
}
|
|
1385
|
+
} else if (isNumberType) {
|
|
1312
1386
|
const newValue = e.target.value;
|
|
1313
1387
|
if (newValue === "" || allowNegative && newValue === "-") {
|
|
1314
1388
|
setInputValue(newValue);
|
|
@@ -1318,13 +1392,51 @@ var Input = forwardRef(
|
|
|
1318
1392
|
setInputValue(newValue);
|
|
1319
1393
|
const numValue = parseFloat(newValue);
|
|
1320
1394
|
if (!isNaN(numValue)) {
|
|
1321
|
-
onNumberChange(formatNumber(numValue));
|
|
1395
|
+
onNumberChange?.(formatNumber(numValue));
|
|
1322
1396
|
}
|
|
1323
1397
|
}
|
|
1324
1398
|
} else {
|
|
1325
1399
|
onChange?.(e);
|
|
1326
1400
|
}
|
|
1327
1401
|
};
|
|
1402
|
+
const handleFocus = (e) => {
|
|
1403
|
+
if (isEmailType || isMobileType) {
|
|
1404
|
+
setInternalError("");
|
|
1405
|
+
}
|
|
1406
|
+
onFocus?.(e);
|
|
1407
|
+
};
|
|
1408
|
+
const handleBlur = (e) => {
|
|
1409
|
+
setHasBeenBlurred(true);
|
|
1410
|
+
if (isEmailType) {
|
|
1411
|
+
const val = (e.target.value || "").trim();
|
|
1412
|
+
if (val && !EMAIL_REGEX.test(val)) {
|
|
1413
|
+
setInternalError("Please enter a valid email address");
|
|
1414
|
+
} else {
|
|
1415
|
+
setInternalError("");
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
if (isMobileType) {
|
|
1419
|
+
const digits = (e.target.value || "").replace(/\D/g, "");
|
|
1420
|
+
if (digits && digits.length !== 10) {
|
|
1421
|
+
setInternalError("Please enter a valid 10-digit phone number");
|
|
1422
|
+
} else {
|
|
1423
|
+
setInternalError("");
|
|
1424
|
+
}
|
|
1425
|
+
}
|
|
1426
|
+
if (isNumberType) {
|
|
1427
|
+
if (inputValue !== "" && inputValue !== "-") {
|
|
1428
|
+
const numValue = parseFloat(inputValue);
|
|
1429
|
+
if (!isNaN(numValue)) {
|
|
1430
|
+
const cleanValue = formatNumber(numValue);
|
|
1431
|
+
setInputValue(cleanValue.toString());
|
|
1432
|
+
onNumberChange?.(cleanValue);
|
|
1433
|
+
}
|
|
1434
|
+
} else if (inputValue === "" || inputValue === "-") {
|
|
1435
|
+
setInputValue("");
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
onBlur?.(e);
|
|
1439
|
+
};
|
|
1328
1440
|
const handleSelectChange = (e) => {
|
|
1329
1441
|
onSelectChange?.(e.target.value);
|
|
1330
1442
|
};
|
|
@@ -1346,22 +1458,7 @@ var Input = forwardRef(
|
|
|
1346
1458
|
setInputValue(finalValue.toString());
|
|
1347
1459
|
onNumberChange?.(finalValue);
|
|
1348
1460
|
};
|
|
1349
|
-
const
|
|
1350
|
-
if (isNumberType && onNumberChange) {
|
|
1351
|
-
if (inputValue !== "" && inputValue !== "-") {
|
|
1352
|
-
const numValue = parseFloat(inputValue);
|
|
1353
|
-
if (!isNaN(numValue)) {
|
|
1354
|
-
const cleanValue = formatNumber(numValue);
|
|
1355
|
-
setInputValue(cleanValue.toString());
|
|
1356
|
-
onNumberChange(cleanValue);
|
|
1357
|
-
}
|
|
1358
|
-
} else if (inputValue === "" || inputValue === "-") {
|
|
1359
|
-
setInputValue("");
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
onBlur?.(e);
|
|
1363
|
-
};
|
|
1364
|
-
const baseInputStyles = "w-full transition-colors focus:outline-none min-h-[52px]";
|
|
1461
|
+
const baseInputStyles = "w-full transition-colors focus:outline-none";
|
|
1365
1462
|
const sizeStyles = {
|
|
1366
1463
|
sm: "px-3 py-2 text-sm",
|
|
1367
1464
|
md: "px-4 py-3 text-base",
|
|
@@ -1379,13 +1476,13 @@ var Input = forwardRef(
|
|
|
1379
1476
|
};
|
|
1380
1477
|
const variantStyles2 = {
|
|
1381
1478
|
default: "border bg-white/60 dark:bg-neutral-800/60 backdrop-blur-sm transition-colors duration-hz-slow ease-hz-default rounded-hz-md",
|
|
1382
|
-
filled: "border-
|
|
1479
|
+
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"
|
|
1383
1480
|
};
|
|
1384
|
-
const stateStyles =
|
|
1481
|
+
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";
|
|
1385
1482
|
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";
|
|
1386
1483
|
const hasControls = isNumberType && showControls;
|
|
1387
1484
|
const hasLeadingContent = leadingIcon || leadingDecorator;
|
|
1388
|
-
const hasTrailingContent = trailingIcon || trailingDecorator || hasControls;
|
|
1485
|
+
const hasTrailingContent = trailingIcon || trailingDecorator || hasControls || isPasswordType;
|
|
1389
1486
|
const inputClasses = `
|
|
1390
1487
|
${baseInputStyles}
|
|
1391
1488
|
${sizeStyles[size]}
|
|
@@ -1409,6 +1506,7 @@ var Input = forwardRef(
|
|
|
1409
1506
|
`.trim().replace(/\s+/g, " ");
|
|
1410
1507
|
const canDecrement = !disabled && (min === void 0 || (parseFloat(inputValue) || 0) > min);
|
|
1411
1508
|
const canIncrement = !disabled && (max === void 0 || (parseFloat(inputValue) || 0) < max);
|
|
1509
|
+
const showPasswordRules = isPasswordType && passwordRules && hasBeenBlurred;
|
|
1412
1510
|
return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
|
|
1413
1511
|
label && /* @__PURE__ */ jsxs("div", { className: "relative mb-2", children: [
|
|
1414
1512
|
/* @__PURE__ */ 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: [
|
|
@@ -1467,13 +1565,18 @@ var Input = forwardRef(
|
|
|
1467
1565
|
) : /* @__PURE__ */ jsx(
|
|
1468
1566
|
"input",
|
|
1469
1567
|
{
|
|
1470
|
-
ref
|
|
1471
|
-
|
|
1568
|
+
ref: (node) => {
|
|
1569
|
+
inputInternalRef.current = node;
|
|
1570
|
+
if (typeof ref === "function") ref(node);
|
|
1571
|
+
else if (ref) ref.current = node;
|
|
1572
|
+
},
|
|
1573
|
+
type: isMobileType ? "tel" : isNumberType ? "text" : isPasswordType ? showPassword ? "text" : "password" : type,
|
|
1472
1574
|
inputMode: isMobileType ? "numeric" : isNumberType ? "numeric" : void 0,
|
|
1473
|
-
value: isNumberType
|
|
1575
|
+
value: isNumberType || isPasswordType ? inputValue : value,
|
|
1474
1576
|
onChange: handleInputChange,
|
|
1475
|
-
|
|
1476
|
-
|
|
1577
|
+
onKeyDown: isNumberType ? handleKeyDown : void 0,
|
|
1578
|
+
onFocus: handleFocus,
|
|
1579
|
+
onBlur: handleBlur,
|
|
1477
1580
|
placeholder,
|
|
1478
1581
|
disabled,
|
|
1479
1582
|
required,
|
|
@@ -1489,6 +1592,7 @@ var Input = forwardRef(
|
|
|
1489
1592
|
"button",
|
|
1490
1593
|
{
|
|
1491
1594
|
type: "button",
|
|
1595
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1492
1596
|
onClick: handleDecrement,
|
|
1493
1597
|
disabled: !canDecrement,
|
|
1494
1598
|
className: `
|
|
@@ -1506,6 +1610,7 @@ var Input = forwardRef(
|
|
|
1506
1610
|
"button",
|
|
1507
1611
|
{
|
|
1508
1612
|
type: "button",
|
|
1613
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1509
1614
|
onClick: handleIncrement,
|
|
1510
1615
|
disabled: !canIncrement,
|
|
1511
1616
|
className: `
|
|
@@ -1519,6 +1624,17 @@ var Input = forwardRef(
|
|
|
1519
1624
|
}
|
|
1520
1625
|
)
|
|
1521
1626
|
] }) }),
|
|
1627
|
+
isPasswordType && /* @__PURE__ */ jsx(
|
|
1628
|
+
"button",
|
|
1629
|
+
{
|
|
1630
|
+
type: "button",
|
|
1631
|
+
tabIndex: -1,
|
|
1632
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
1633
|
+
onClick: handleTogglePassword,
|
|
1634
|
+
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",
|
|
1635
|
+
children: showPassword ? /* @__PURE__ */ jsx(EyeOff, { size: iconSizeStyles[size] }) : /* @__PURE__ */ jsx(Eye, { size: iconSizeStyles[size] })
|
|
1636
|
+
}
|
|
1637
|
+
),
|
|
1522
1638
|
isSelectType && !trailingIcon && !trailingDecorator && /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none", children: /* @__PURE__ */ jsx(
|
|
1523
1639
|
ChevronDown,
|
|
1524
1640
|
{
|
|
@@ -1539,10 +1655,24 @@ var Input = forwardRef(
|
|
|
1539
1655
|
}
|
|
1540
1656
|
)
|
|
1541
1657
|
] }),
|
|
1542
|
-
(
|
|
1543
|
-
|
|
1544
|
-
helperText && !
|
|
1545
|
-
] })
|
|
1658
|
+
(displayError || helperText) && /* @__PURE__ */ jsxs("div", { className: "mt-2", children: [
|
|
1659
|
+
displayError && /* @__PURE__ */ jsx("p", { className: "text-sm text-rose-600 dark:text-rose-400 transition-colors duration-hz-slow ease-hz-default", children: displayError }),
|
|
1660
|
+
helperText && !displayError && /* @__PURE__ */ jsx("p", { className: "text-sm text-neutral-500 dark:text-neutral-400 transition-colors duration-hz-slow ease-hz-default", children: helperText })
|
|
1661
|
+
] }),
|
|
1662
|
+
showPasswordRules && passwordRuleResults && /* @__PURE__ */ jsx("ul", { className: "mt-2 space-y-1", children: Object.keys(passwordRuleResults).filter((key) => passwordRuleResults[key] !== null).map((key) => {
|
|
1663
|
+
const passed = passwordRuleResults[key];
|
|
1664
|
+
return /* @__PURE__ */ jsxs(
|
|
1665
|
+
"li",
|
|
1666
|
+
{
|
|
1667
|
+
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"}`,
|
|
1668
|
+
children: [
|
|
1669
|
+
passed ? /* @__PURE__ */ jsx(Check, { className: "w-3 h-3 shrink-0" }) : /* @__PURE__ */ jsx(X, { className: "w-3 h-3 shrink-0" }),
|
|
1670
|
+
passwordRules && passwordRuleLabels[key](passwordRules)
|
|
1671
|
+
]
|
|
1672
|
+
},
|
|
1673
|
+
key
|
|
1674
|
+
);
|
|
1675
|
+
}) })
|
|
1546
1676
|
] });
|
|
1547
1677
|
}
|
|
1548
1678
|
);
|
|
@@ -2533,5 +2663,5 @@ var SideNavFooter = forwardRef(
|
|
|
2533
2663
|
SideNavFooter.displayName = "SideNavFooter";
|
|
2534
2664
|
|
|
2535
2665
|
export { AnimatedButton, ChartRenderer, CompactPanel, Dashboard, DashboardPanel, Input, LargePanel, MediumPanel, SideNav, SideNavFooter, SideNavHeader, SideNavItem, SideNavSection, StatDisplay, TableRenderer, TemplateSelector, TextButton, Toast, useDashboardContext, useSideNavContext };
|
|
2536
|
-
//# sourceMappingURL=chunk-
|
|
2537
|
-
//# sourceMappingURL=chunk-
|
|
2666
|
+
//# sourceMappingURL=chunk-3CJL52WY.mjs.map
|
|
2667
|
+
//# sourceMappingURL=chunk-3CJL52WY.mjs.map
|