hazo_ui 2.1.1 → 2.2.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/index.d.cts CHANGED
@@ -1,4 +1,5 @@
1
- import React from 'react';
1
+ import * as React from 'react';
2
+ import React__default from 'react';
2
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
4
5
  /**
@@ -6,8 +7,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
6
7
  * @param props - Component props
7
8
  * @returns React component
8
9
  */
9
- declare const ExampleComponent: React.FC<{
10
- children?: React.ReactNode;
10
+ declare const ExampleComponent: React__default.FC<{
11
+ children?: React__default.ReactNode;
11
12
  className?: string;
12
13
  }>;
13
14
 
@@ -39,12 +40,12 @@ interface FilterConfig {
39
40
  operator?: string;
40
41
  value: any;
41
42
  }
42
- interface MultiFilterDialogProps {
43
+ interface HazoUiMultiFilterDialogProps {
43
44
  availableFields: FilterField[];
44
45
  onFilterChange: (filterConfig: FilterConfig[]) => void;
45
46
  initialFilters?: FilterConfig[];
46
47
  }
47
- declare function MultiFilterDialog({ availableFields, onFilterChange, initialFilters, }: MultiFilterDialogProps): react_jsx_runtime.JSX.Element;
48
+ declare function HazoUiMultiFilterDialog({ availableFields, onFilterChange, initialFilters, }: HazoUiMultiFilterDialogProps): react_jsx_runtime.JSX.Element;
48
49
 
49
50
  interface SortField {
50
51
  value: string;
@@ -54,25 +55,27 @@ interface SortConfig {
54
55
  field: string;
55
56
  direction: 'asc' | 'desc';
56
57
  }
57
- interface MultiSortDialogProps {
58
+ interface HazoUiMultiSortDialogProps {
58
59
  availableFields: SortField[];
59
60
  onSortChange: (sortConfig: SortConfig[]) => void;
60
61
  initialSortFields?: SortConfig[];
61
62
  }
62
- declare function MultiSortDialog({ availableFields, onSortChange, initialSortFields, }: MultiSortDialogProps): react_jsx_runtime.JSX.Element;
63
+ declare function HazoUiMultiSortDialog({ availableFields, onSortChange, initialSortFields, }: HazoUiMultiSortDialogProps): react_jsx_runtime.JSX.Element;
63
64
 
64
- interface MultiStateRadioItem {
65
+ interface HazoUiFlexRadioItem {
65
66
  label: string;
66
67
  value: string;
67
68
  icon_selected?: string;
68
69
  icon_unselected?: string;
70
+ fgcolor?: string;
71
+ bgcolor?: string;
69
72
  }
70
- interface MultiStateRadioProps {
73
+ interface HazoUiFlexRadioProps {
71
74
  layout?: "horizontal" | "vertical";
72
75
  style?: "radio" | "icons";
73
76
  display_label?: boolean;
74
77
  icon_set?: string;
75
- data: MultiStateRadioItem[];
78
+ data: HazoUiFlexRadioItem[];
76
79
  selection: "single" | "multi";
77
80
  value: string | string[];
78
81
  onChange: (value: string | string[]) => void;
@@ -80,9 +83,32 @@ interface MultiStateRadioProps {
80
83
  compressed?: boolean;
81
84
  }
82
85
  /**
83
- * Multi State Radio Component
86
+ * Hazo UI Flex Radio Component
84
87
  * Supports single and multi-selection with radio buttons or icons
85
88
  */
86
- declare function MultiStateRadio({ layout, style, display_label, icon_set, data, selection, value, onChange, className, compressed, }: MultiStateRadioProps): react_jsx_runtime.JSX.Element;
89
+ declare function HazoUiFlexRadio({ layout, style, display_label, icon_set, data, selection, value, onChange, className, compressed, }: HazoUiFlexRadioProps): react_jsx_runtime.JSX.Element;
87
90
 
88
- export { ExampleComponent, type FilterConfig, type FilterField, MultiFilterDialog, MultiSortDialog, MultiStateRadio, type MultiStateRadioItem, type MultiStateRadioProps, type SortConfig, type SortField };
91
+ interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
92
+ }
93
+
94
+ /**
95
+ * Hazo UI Flex Input Component
96
+ *
97
+ * Enhanced input component with type validation, character restrictions, and error messaging.
98
+ * Extends shadcn Input component with additional validation props.
99
+ */
100
+
101
+ interface HazoUiFlexInputProps extends Omit<InputProps, "type"> {
102
+ input_type?: "mixed" | "numeric" | "email" | "alpha";
103
+ text_len_min?: number;
104
+ text_len_max?: number;
105
+ num_min?: number;
106
+ num_max?: number;
107
+ regex?: string | RegExp;
108
+ num_decimals?: number;
109
+ format_guide?: string;
110
+ format_guide_info?: boolean;
111
+ }
112
+ declare const HazoUiFlexInput: React.ForwardRefExoticComponent<HazoUiFlexInputProps & React.RefAttributes<HTMLInputElement>>;
113
+
114
+ export { ExampleComponent, type FilterConfig, type FilterField, HazoUiFlexInput, type HazoUiFlexInputProps, HazoUiFlexRadio, type HazoUiFlexRadioItem, type HazoUiFlexRadioProps, HazoUiMultiFilterDialog, HazoUiMultiSortDialog, type SortConfig, type SortField };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import React from 'react';
1
+ import * as React from 'react';
2
+ import React__default from 'react';
2
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
4
 
4
5
  /**
@@ -6,8 +7,8 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
6
7
  * @param props - Component props
7
8
  * @returns React component
8
9
  */
9
- declare const ExampleComponent: React.FC<{
10
- children?: React.ReactNode;
10
+ declare const ExampleComponent: React__default.FC<{
11
+ children?: React__default.ReactNode;
11
12
  className?: string;
12
13
  }>;
13
14
 
@@ -39,12 +40,12 @@ interface FilterConfig {
39
40
  operator?: string;
40
41
  value: any;
41
42
  }
42
- interface MultiFilterDialogProps {
43
+ interface HazoUiMultiFilterDialogProps {
43
44
  availableFields: FilterField[];
44
45
  onFilterChange: (filterConfig: FilterConfig[]) => void;
45
46
  initialFilters?: FilterConfig[];
46
47
  }
47
- declare function MultiFilterDialog({ availableFields, onFilterChange, initialFilters, }: MultiFilterDialogProps): react_jsx_runtime.JSX.Element;
48
+ declare function HazoUiMultiFilterDialog({ availableFields, onFilterChange, initialFilters, }: HazoUiMultiFilterDialogProps): react_jsx_runtime.JSX.Element;
48
49
 
49
50
  interface SortField {
50
51
  value: string;
@@ -54,25 +55,27 @@ interface SortConfig {
54
55
  field: string;
55
56
  direction: 'asc' | 'desc';
56
57
  }
57
- interface MultiSortDialogProps {
58
+ interface HazoUiMultiSortDialogProps {
58
59
  availableFields: SortField[];
59
60
  onSortChange: (sortConfig: SortConfig[]) => void;
60
61
  initialSortFields?: SortConfig[];
61
62
  }
62
- declare function MultiSortDialog({ availableFields, onSortChange, initialSortFields, }: MultiSortDialogProps): react_jsx_runtime.JSX.Element;
63
+ declare function HazoUiMultiSortDialog({ availableFields, onSortChange, initialSortFields, }: HazoUiMultiSortDialogProps): react_jsx_runtime.JSX.Element;
63
64
 
64
- interface MultiStateRadioItem {
65
+ interface HazoUiFlexRadioItem {
65
66
  label: string;
66
67
  value: string;
67
68
  icon_selected?: string;
68
69
  icon_unselected?: string;
70
+ fgcolor?: string;
71
+ bgcolor?: string;
69
72
  }
70
- interface MultiStateRadioProps {
73
+ interface HazoUiFlexRadioProps {
71
74
  layout?: "horizontal" | "vertical";
72
75
  style?: "radio" | "icons";
73
76
  display_label?: boolean;
74
77
  icon_set?: string;
75
- data: MultiStateRadioItem[];
78
+ data: HazoUiFlexRadioItem[];
76
79
  selection: "single" | "multi";
77
80
  value: string | string[];
78
81
  onChange: (value: string | string[]) => void;
@@ -80,9 +83,32 @@ interface MultiStateRadioProps {
80
83
  compressed?: boolean;
81
84
  }
82
85
  /**
83
- * Multi State Radio Component
86
+ * Hazo UI Flex Radio Component
84
87
  * Supports single and multi-selection with radio buttons or icons
85
88
  */
86
- declare function MultiStateRadio({ layout, style, display_label, icon_set, data, selection, value, onChange, className, compressed, }: MultiStateRadioProps): react_jsx_runtime.JSX.Element;
89
+ declare function HazoUiFlexRadio({ layout, style, display_label, icon_set, data, selection, value, onChange, className, compressed, }: HazoUiFlexRadioProps): react_jsx_runtime.JSX.Element;
87
90
 
88
- export { ExampleComponent, type FilterConfig, type FilterField, MultiFilterDialog, MultiSortDialog, MultiStateRadio, type MultiStateRadioItem, type MultiStateRadioProps, type SortConfig, type SortField };
91
+ interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
92
+ }
93
+
94
+ /**
95
+ * Hazo UI Flex Input Component
96
+ *
97
+ * Enhanced input component with type validation, character restrictions, and error messaging.
98
+ * Extends shadcn Input component with additional validation props.
99
+ */
100
+
101
+ interface HazoUiFlexInputProps extends Omit<InputProps, "type"> {
102
+ input_type?: "mixed" | "numeric" | "email" | "alpha";
103
+ text_len_min?: number;
104
+ text_len_max?: number;
105
+ num_min?: number;
106
+ num_max?: number;
107
+ regex?: string | RegExp;
108
+ num_decimals?: number;
109
+ format_guide?: string;
110
+ format_guide_info?: boolean;
111
+ }
112
+ declare const HazoUiFlexInput: React.ForwardRefExoticComponent<HazoUiFlexInputProps & React.RefAttributes<HTMLInputElement>>;
113
+
114
+ export { ExampleComponent, type FilterConfig, type FilterField, HazoUiFlexInput, type HazoUiFlexInputProps, HazoUiFlexRadio, type HazoUiFlexRadioItem, type HazoUiFlexRadioProps, HazoUiMultiFilterDialog, HazoUiMultiSortDialog, type SortConfig, type SortField };
package/dist/index.js CHANGED
@@ -27,6 +27,7 @@ import * as FiIcons from 'react-icons/fi';
27
27
  import * as IoIcons from 'react-icons/io5';
28
28
  import * as RiIcons from 'react-icons/ri';
29
29
  import * as TbIcons from 'react-icons/tb';
30
+ import * as CiIcons from 'react-icons/ci';
30
31
 
31
32
  var ExampleComponent = ({ children, className = "" }) => {
32
33
  return /* @__PURE__ */ jsx("div", { className: `cls_example_component ${className}`, children });
@@ -623,7 +624,7 @@ function FilterFieldItem({
623
624
  )
624
625
  ] });
625
626
  }
626
- function MultiFilterDialog({
627
+ function HazoUiMultiFilterDialog({
627
628
  availableFields,
628
629
  onFilterChange,
629
630
  initialFilters = []
@@ -943,7 +944,7 @@ function SortableSortFieldItem({
943
944
  }
944
945
  );
945
946
  }
946
- function MultiSortDialog({
947
+ function HazoUiMultiSortDialog({
947
948
  availableFields,
948
949
  onSortChange,
949
950
  initialSortFields = []
@@ -1193,7 +1194,8 @@ var iconSetMap = {
1193
1194
  io: IoIcons,
1194
1195
  io5: IoIcons,
1195
1196
  ri: RiIcons,
1196
- tb: TbIcons
1197
+ tb: TbIcons,
1198
+ ci: CiIcons
1197
1199
  };
1198
1200
  function getIconLibrary(iconSet) {
1199
1201
  if (!iconSet) return null;
@@ -1207,7 +1209,7 @@ function getIconComponent(iconSet, iconName) {
1207
1209
  const IconComponent = iconLibrary[iconName];
1208
1210
  return IconComponent || null;
1209
1211
  }
1210
- function MultiStateRadio({
1212
+ function HazoUiFlexRadio({
1211
1213
  layout = "horizontal",
1212
1214
  style = "radio",
1213
1215
  display_label = true,
@@ -1339,6 +1341,10 @@ function MultiStateRadio({
1339
1341
  const SelectedIcon = icon_set && item.icon_selected ? getIconComponent(icon_set, item.icon_selected) : null;
1340
1342
  const UnselectedIcon = icon_set && item.icon_unselected ? getIconComponent(icon_set, item.icon_unselected) : null;
1341
1343
  const IconComponent = selected && SelectedIcon ? SelectedIcon : UnselectedIcon || SelectedIcon;
1344
+ const buttonStyles = {};
1345
+ if (item.bgcolor) {
1346
+ buttonStyles.backgroundColor = item.bgcolor;
1347
+ }
1342
1348
  const buttonContent = /* @__PURE__ */ jsxs(
1343
1349
  Button,
1344
1350
  {
@@ -1349,9 +1355,11 @@ function MultiStateRadio({
1349
1355
  layout === "horizontal" ? "flex-row" : "flex-col",
1350
1356
  "gap-2 h-auto",
1351
1357
  compressed ? "py-0 px-0" : "py-2 px-3 sm:py-3 sm:px-4",
1352
- selected && "bg-primary text-primary-foreground",
1353
- !selected && "hover:bg-accent"
1358
+ // Only apply default colors if custom colors are not provided
1359
+ !item.bgcolor && selected && "bg-primary text-primary-foreground",
1360
+ !item.bgcolor && !selected && "hover:bg-accent"
1354
1361
  ),
1362
+ style: Object.keys(buttonStyles).length > 0 ? buttonStyles : void 0,
1355
1363
  onClick: () => {
1356
1364
  if (selection === "single") {
1357
1365
  handleSingleSelection(item.value);
@@ -1362,8 +1370,21 @@ function MultiStateRadio({
1362
1370
  "aria-label": item.label,
1363
1371
  "aria-pressed": selected,
1364
1372
  children: [
1365
- IconComponent && /* @__PURE__ */ jsx(IconComponent, { className: "cls_icon h-4 w-4 sm:h-5 sm:w-5" }),
1366
- display_label && /* @__PURE__ */ jsx("span", { className: "cls_icon_label text-sm font-medium", children: item.label })
1373
+ IconComponent && /* @__PURE__ */ jsx(
1374
+ IconComponent,
1375
+ {
1376
+ className: "cls_icon h-4 w-4 sm:h-5 sm:w-5",
1377
+ style: item.fgcolor ? { color: item.fgcolor } : void 0
1378
+ }
1379
+ ),
1380
+ display_label && /* @__PURE__ */ jsx(
1381
+ "span",
1382
+ {
1383
+ className: "cls_icon_label text-sm font-medium",
1384
+ style: item.fgcolor ? { color: item.fgcolor } : void 0,
1385
+ children: item.label
1386
+ }
1387
+ )
1367
1388
  ]
1368
1389
  }
1369
1390
  );
@@ -1373,7 +1394,7 @@ function MultiStateRadio({
1373
1394
  ] }, item.value);
1374
1395
  };
1375
1396
  const containerClasses = cn(
1376
- "cls_multi_state_radio border border-input rounded-md",
1397
+ "cls_hazo_ui_flex_radio border border-input rounded-md",
1377
1398
  compressed ? "" : "p-2 sm:p-3",
1378
1399
  layout === "horizontal" ? cn(
1379
1400
  "flex flex-row flex-wrap",
@@ -1407,7 +1428,204 @@ function MultiStateRadio({
1407
1428
  }
1408
1429
  }
1409
1430
  }
1431
+ function validateInput(value, input_type, text_len_min, text_len_max, num_min, num_max, regex, num_decimals) {
1432
+ if (value === "") {
1433
+ return { isValid: true };
1434
+ }
1435
+ switch (input_type) {
1436
+ case "numeric": {
1437
+ const numValue = parseFloat(value);
1438
+ if (isNaN(numValue)) {
1439
+ return { isValid: false, errorMessage: "Must be a valid number" };
1440
+ }
1441
+ if (num_decimals !== void 0) {
1442
+ const decimalPlaces = value.split(".")[1]?.length || 0;
1443
+ if (decimalPlaces > num_decimals) {
1444
+ return {
1445
+ isValid: false,
1446
+ errorMessage: `Maximum ${num_decimals} decimal place${num_decimals !== 1 ? "s" : ""} allowed`
1447
+ };
1448
+ }
1449
+ }
1450
+ if (num_min !== void 0 && numValue < num_min) {
1451
+ return { isValid: false, errorMessage: `Must be at least ${num_min}` };
1452
+ }
1453
+ if (num_max !== void 0 && numValue > num_max) {
1454
+ return { isValid: false, errorMessage: `Must be at most ${num_max}` };
1455
+ }
1456
+ break;
1457
+ }
1458
+ case "alpha": {
1459
+ const alphaRegex = /^[A-Za-z\s]*$/;
1460
+ if (!alphaRegex.test(value)) {
1461
+ return { isValid: false, errorMessage: "Only letters are allowed" };
1462
+ }
1463
+ break;
1464
+ }
1465
+ case "email": {
1466
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
1467
+ if (!emailRegex.test(value)) {
1468
+ return { isValid: false, errorMessage: "Must be a valid email address" };
1469
+ }
1470
+ break;
1471
+ }
1472
+ case "mixed": {
1473
+ if (text_len_min !== void 0 && value.length < text_len_min) {
1474
+ return {
1475
+ isValid: false,
1476
+ errorMessage: `Must be at least ${text_len_min} character${text_len_min !== 1 ? "s" : ""}`
1477
+ };
1478
+ }
1479
+ if (text_len_max !== void 0 && value.length > text_len_max) {
1480
+ return {
1481
+ isValid: false,
1482
+ errorMessage: `Must be at most ${text_len_max} character${text_len_max !== 1 ? "s" : ""}`
1483
+ };
1484
+ }
1485
+ break;
1486
+ }
1487
+ }
1488
+ if (regex) {
1489
+ const regexPattern = typeof regex === "string" ? new RegExp(regex) : regex;
1490
+ if (!regexPattern.test(value)) {
1491
+ return { isValid: false, errorMessage: "Invalid format" };
1492
+ }
1493
+ }
1494
+ return { isValid: true };
1495
+ }
1496
+ function filterInputValue(value, input_type, num_decimals) {
1497
+ switch (input_type) {
1498
+ case "numeric": {
1499
+ let filtered = value.replace(/[^\d.-]/g, "");
1500
+ const parts = filtered.split(".");
1501
+ if (parts.length > 2) {
1502
+ filtered = parts[0] + "." + parts.slice(1).join("");
1503
+ }
1504
+ if (num_decimals === 0 && filtered.includes(".")) {
1505
+ filtered = filtered.replace(".", "");
1506
+ }
1507
+ if (num_decimals !== void 0 && num_decimals > 0) {
1508
+ const parts2 = filtered.split(".");
1509
+ if (parts2.length === 2 && parts2[1].length > num_decimals) {
1510
+ filtered = parts2[0] + "." + parts2[1].substring(0, num_decimals);
1511
+ }
1512
+ }
1513
+ return filtered;
1514
+ }
1515
+ case "alpha": {
1516
+ return value.replace(/[^A-Za-z\s]/g, "");
1517
+ }
1518
+ case "email":
1519
+ case "mixed":
1520
+ default: {
1521
+ return value;
1522
+ }
1523
+ }
1524
+ }
1525
+ var HazoUiFlexInput = React6.forwardRef(
1526
+ ({
1527
+ className,
1528
+ input_type = "mixed",
1529
+ text_len_min,
1530
+ text_len_max,
1531
+ num_min,
1532
+ num_max,
1533
+ regex,
1534
+ num_decimals,
1535
+ format_guide,
1536
+ format_guide_info = false,
1537
+ value: controlledValue,
1538
+ onChange,
1539
+ onBlur,
1540
+ ...props
1541
+ }, ref) => {
1542
+ const [internalValue, setInternalValue] = React6.useState(
1543
+ typeof controlledValue === "string" ? controlledValue : typeof controlledValue === "number" ? String(controlledValue) : ""
1544
+ );
1545
+ const [errorMessage, setErrorMessage] = React6.useState();
1546
+ const isControlled = controlledValue !== void 0;
1547
+ const currentValue = isControlled ? typeof controlledValue === "string" ? controlledValue : String(controlledValue || "") : internalValue;
1548
+ React6.useEffect(() => {
1549
+ if (isControlled) {
1550
+ const newValue = typeof controlledValue === "string" ? controlledValue : String(controlledValue || "");
1551
+ if (newValue !== internalValue) {
1552
+ setInternalValue(newValue);
1553
+ }
1554
+ }
1555
+ }, [controlledValue, isControlled]);
1556
+ const handleChange = (e) => {
1557
+ let newValue = e.target.value;
1558
+ if (input_type === "numeric" || input_type === "alpha") {
1559
+ newValue = filterInputValue(newValue, input_type, num_decimals);
1560
+ }
1561
+ if (!isControlled) {
1562
+ setInternalValue(newValue);
1563
+ }
1564
+ if (errorMessage) {
1565
+ setErrorMessage(void 0);
1566
+ }
1567
+ if (onChange) {
1568
+ const syntheticEvent = {
1569
+ ...e,
1570
+ target: { ...e.target, value: newValue }
1571
+ };
1572
+ onChange(syntheticEvent);
1573
+ }
1574
+ };
1575
+ const handleBlur = (e) => {
1576
+ const validation = validateInput(
1577
+ currentValue,
1578
+ input_type,
1579
+ text_len_min,
1580
+ text_len_max,
1581
+ num_min,
1582
+ num_max,
1583
+ regex,
1584
+ num_decimals
1585
+ );
1586
+ if (!validation.isValid) {
1587
+ setErrorMessage(validation.errorMessage || format_guide || "Invalid input");
1588
+ } else {
1589
+ setErrorMessage(void 0);
1590
+ }
1591
+ if (onBlur) {
1592
+ onBlur(e);
1593
+ }
1594
+ };
1595
+ const htmlInputType = input_type === "email" ? "email" : input_type === "numeric" ? "text" : "text";
1596
+ const hasError = errorMessage !== void 0;
1597
+ return /* @__PURE__ */ jsxs("div", { className: "cls_hazo_ui_flex_input_container w-full", children: [
1598
+ /* @__PURE__ */ jsx(
1599
+ Input,
1600
+ {
1601
+ ref,
1602
+ type: htmlInputType,
1603
+ value: currentValue,
1604
+ onChange: handleChange,
1605
+ onBlur: handleBlur,
1606
+ className: cn(
1607
+ hasError && "border-destructive focus-visible:ring-destructive",
1608
+ className
1609
+ ),
1610
+ ...props
1611
+ }
1612
+ ),
1613
+ hasError && errorMessage && /* @__PURE__ */ jsx("p", { className: "cls_error_message mt-1 text-sm text-destructive", children: errorMessage }),
1614
+ format_guide_info && format_guide && /* @__PURE__ */ jsx(
1615
+ "p",
1616
+ {
1617
+ className: cn(
1618
+ "cls_format_guide_info mt-1 text-xs italic text-muted-foreground",
1619
+ hasError && "mt-0"
1620
+ ),
1621
+ children: format_guide
1622
+ }
1623
+ )
1624
+ ] });
1625
+ }
1626
+ );
1627
+ HazoUiFlexInput.displayName = "HazoUiFlexInput";
1410
1628
 
1411
- export { ExampleComponent, MultiFilterDialog, MultiSortDialog, MultiStateRadio };
1629
+ export { ExampleComponent, HazoUiFlexInput, HazoUiFlexRadio, HazoUiMultiFilterDialog, HazoUiMultiSortDialog };
1412
1630
  //# sourceMappingURL=index.js.map
1413
1631
  //# sourceMappingURL=index.js.map