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/README.md +33 -33
- package/dist/index.cjs +232 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +39 -13
- package/dist/index.d.ts +39 -13
- package/dist/index.js +228 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -12,25 +12,25 @@ npm install hazo_ui
|
|
|
12
12
|
|
|
13
13
|
### Component Overview
|
|
14
14
|
|
|
15
|
-
- **[
|
|
15
|
+
- **[HazoUiMultiFilterDialog](#hazouimultifilterdialog)** - A powerful dialog component for multi-field filtering with support for text, number, combobox, boolean, and date fields. Includes operator support, validation, and visual feedback.
|
|
16
16
|
|
|
17
|
-
- **[
|
|
17
|
+
- **[HazoUiMultiSortDialog](#hazouimultisortdialog)** - A flexible dialog component for multi-field sorting with drag-and-drop reordering. Allows users to set sort priority and direction (ascending/descending) for multiple fields.
|
|
18
18
|
|
|
19
|
-
- **[
|
|
19
|
+
- **[HazoUiFlexRadio](#hazouiflexradio)** - A flexible radio button/icon selection component with support for single and multi-selection modes, customizable layouts, and react-icons integration. Perfect for settings panels, preference selection, and option groups.
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## HazoUiMultiFilterDialog
|
|
24
24
|
|
|
25
25
|
A powerful, flexible dialog component for multi-field filtering with support for various input types. Perfect for table headers, grid views, or any interface where users need to apply multiple filters simultaneously.
|
|
26
26
|
|
|
27
|
-

|
|
28
28
|
|
|
29
|
-

|
|
30
30
|
|
|
31
|
-

|
|
32
32
|
|
|
33
|
-

|
|
34
34
|
|
|
35
35
|
#### Features
|
|
36
36
|
|
|
@@ -71,7 +71,7 @@ A powerful, flexible dialog component for multi-field filtering with support for
|
|
|
71
71
|
#### Usage
|
|
72
72
|
|
|
73
73
|
```tsx
|
|
74
|
-
import {
|
|
74
|
+
import { HazoUiMultiFilterDialog, type FilterField, type FilterConfig } from 'hazo_ui';
|
|
75
75
|
import { useState } from 'react';
|
|
76
76
|
|
|
77
77
|
function DataTable() {
|
|
@@ -145,7 +145,7 @@ function DataTable() {
|
|
|
145
145
|
|
|
146
146
|
return (
|
|
147
147
|
<div>
|
|
148
|
-
<
|
|
148
|
+
<HazoUiMultiFilterDialog
|
|
149
149
|
availableFields={availableFields}
|
|
150
150
|
onFilterChange={handleFilterChange}
|
|
151
151
|
initialFilters={filters}
|
|
@@ -239,17 +239,17 @@ When users apply filters, the `onFilterChange` callback receives an array of `Fi
|
|
|
239
239
|
|
|
240
240
|
---
|
|
241
241
|
|
|
242
|
-
##
|
|
242
|
+
## HazoUiMultiSortDialog
|
|
243
243
|
|
|
244
244
|
A powerful dialog component for multi-field sorting with drag-and-drop reordering. Allows users to select multiple fields for sorting, reorder them by priority, and set ascending/descending direction for each field.
|
|
245
245
|
|
|
246
|
-

|
|
247
247
|
|
|
248
|
-

|
|
249
249
|
|
|
250
|
-

|
|
251
251
|
|
|
252
|
-

|
|
253
253
|
|
|
254
254
|
#### Features
|
|
255
255
|
|
|
@@ -278,7 +278,7 @@ The component returns an array of sort configurations in priority order, where t
|
|
|
278
278
|
#### Usage
|
|
279
279
|
|
|
280
280
|
```tsx
|
|
281
|
-
import {
|
|
281
|
+
import { HazoUiMultiSortDialog, type SortField, type SortConfig } from 'hazo_ui';
|
|
282
282
|
import { useState } from 'react';
|
|
283
283
|
|
|
284
284
|
function DataTable() {
|
|
@@ -319,7 +319,7 @@ function DataTable() {
|
|
|
319
319
|
|
|
320
320
|
return (
|
|
321
321
|
<div>
|
|
322
|
-
<
|
|
322
|
+
<HazoUiMultiSortDialog
|
|
323
323
|
availableFields={availableFields}
|
|
324
324
|
onSortChange={handleSortChange}
|
|
325
325
|
initialSortFields={sorts}
|
|
@@ -446,7 +446,7 @@ const sortedData = applySorts(originalData, sorts);
|
|
|
446
446
|
|
|
447
447
|
---
|
|
448
448
|
|
|
449
|
-
##
|
|
449
|
+
## HazoUiFlexRadio
|
|
450
450
|
|
|
451
451
|
A flexible radio button/icon selection component with support for single and multi-selection modes, customizable layouts, and react-icons integration. Perfect for settings panels, preference selection, and option groups.
|
|
452
452
|
|
|
@@ -466,19 +466,19 @@ A flexible radio button/icon selection component with support for single and mul
|
|
|
466
466
|
#### Props
|
|
467
467
|
|
|
468
468
|
```typescript
|
|
469
|
-
interface
|
|
469
|
+
interface HazoUiFlexRadioItem {
|
|
470
470
|
label: string; // Display label for the option
|
|
471
471
|
value: string; // Unique value identifier
|
|
472
472
|
icon_selected?: string; // Icon name when selected (e.g., "FaHome")
|
|
473
473
|
icon_unselected?: string; // Icon name when unselected (e.g., "FaRegHome")
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
-
interface
|
|
476
|
+
interface HazoUiFlexRadioProps {
|
|
477
477
|
layout?: 'horizontal' | 'vertical'; // Layout direction (default: 'horizontal')
|
|
478
478
|
style?: 'radio' | 'icons'; // Display style (default: 'radio')
|
|
479
479
|
display_label?: boolean; // Show/hide labels (default: true)
|
|
480
480
|
icon_set?: string; // Icon set package name (e.g., 'fa', 'md')
|
|
481
|
-
data:
|
|
481
|
+
data: HazoUiFlexRadioItem[]; // Array of options
|
|
482
482
|
selection: 'single' | 'multi'; // Selection mode
|
|
483
483
|
value: string | string[]; // Controlled value (string for single, array for multi)
|
|
484
484
|
onChange: (value: string | string[]) => void; // Change handler
|
|
@@ -491,13 +491,13 @@ interface MultiStateRadioProps {
|
|
|
491
491
|
**Basic Single Selection (Radio Style)**
|
|
492
492
|
|
|
493
493
|
```tsx
|
|
494
|
-
import {
|
|
494
|
+
import { HazoUiFlexRadio, type HazoUiFlexRadioItem } from 'hazo_ui';
|
|
495
495
|
import { useState } from 'react';
|
|
496
496
|
|
|
497
497
|
function SettingsPanel() {
|
|
498
498
|
const [selectedOption, setSelectedOption] = useState<string>('option1');
|
|
499
499
|
|
|
500
|
-
const options:
|
|
500
|
+
const options: HazoUiFlexRadioItem[] = [
|
|
501
501
|
{ label: 'Option 1', value: 'option1' },
|
|
502
502
|
{ label: 'Option 2', value: 'option2' },
|
|
503
503
|
{ label: 'Option 3', value: 'option3' },
|
|
@@ -505,7 +505,7 @@ function SettingsPanel() {
|
|
|
505
505
|
];
|
|
506
506
|
|
|
507
507
|
return (
|
|
508
|
-
<
|
|
508
|
+
<HazoUiFlexRadio
|
|
509
509
|
data={options}
|
|
510
510
|
value={selectedOption}
|
|
511
511
|
onChange={setSelectedOption}
|
|
@@ -521,13 +521,13 @@ function SettingsPanel() {
|
|
|
521
521
|
**Icon Style with React Icons**
|
|
522
522
|
|
|
523
523
|
```tsx
|
|
524
|
-
import {
|
|
524
|
+
import { HazoUiFlexRadio, type HazoUiFlexRadioItem } from 'hazo_ui';
|
|
525
525
|
import { useState } from 'react';
|
|
526
526
|
|
|
527
527
|
function IconSelector() {
|
|
528
528
|
const [selectedIcon, setSelectedIcon] = useState<string>('home');
|
|
529
529
|
|
|
530
|
-
const iconOptions:
|
|
530
|
+
const iconOptions: HazoUiFlexRadioItem[] = [
|
|
531
531
|
{
|
|
532
532
|
label: 'Home',
|
|
533
533
|
value: 'home',
|
|
@@ -549,7 +549,7 @@ function IconSelector() {
|
|
|
549
549
|
];
|
|
550
550
|
|
|
551
551
|
return (
|
|
552
|
-
<
|
|
552
|
+
<HazoUiFlexRadio
|
|
553
553
|
data={iconOptions}
|
|
554
554
|
value={selectedIcon}
|
|
555
555
|
onChange={setSelectedIcon}
|
|
@@ -566,13 +566,13 @@ function IconSelector() {
|
|
|
566
566
|
**Multi-Selection Mode**
|
|
567
567
|
|
|
568
568
|
```tsx
|
|
569
|
-
import {
|
|
569
|
+
import { HazoUiFlexRadio, type HazoUiFlexRadioItem } from 'hazo_ui';
|
|
570
570
|
import { useState } from 'react';
|
|
571
571
|
|
|
572
572
|
function MultiSelectExample() {
|
|
573
573
|
const [selectedOptions, setSelectedOptions] = useState<string[]>(['option1', 'option3']);
|
|
574
574
|
|
|
575
|
-
const options:
|
|
575
|
+
const options: HazoUiFlexRadioItem[] = [
|
|
576
576
|
{ label: 'Option 1', value: 'option1' },
|
|
577
577
|
{ label: 'Option 2', value: 'option2' },
|
|
578
578
|
{ label: 'Option 3', value: 'option3' },
|
|
@@ -580,7 +580,7 @@ function MultiSelectExample() {
|
|
|
580
580
|
];
|
|
581
581
|
|
|
582
582
|
return (
|
|
583
|
-
<
|
|
583
|
+
<HazoUiFlexRadio
|
|
584
584
|
data={options}
|
|
585
585
|
value={selectedOptions}
|
|
586
586
|
onChange={setSelectedOptions}
|
|
@@ -596,13 +596,13 @@ function MultiSelectExample() {
|
|
|
596
596
|
**Vertical Layout with Icons Only (No Labels)**
|
|
597
597
|
|
|
598
598
|
```tsx
|
|
599
|
-
import {
|
|
599
|
+
import { HazoUiFlexRadio, type HazoUiFlexRadioItem } from 'hazo_ui';
|
|
600
600
|
import { useState } from 'react';
|
|
601
601
|
|
|
602
602
|
function VerticalIconSelector() {
|
|
603
603
|
const [selected, setSelected] = useState<string>('favorite');
|
|
604
604
|
|
|
605
|
-
const options:
|
|
605
|
+
const options: HazoUiFlexRadioItem[] = [
|
|
606
606
|
{
|
|
607
607
|
label: 'Favorite',
|
|
608
608
|
value: 'favorite',
|
|
@@ -618,7 +618,7 @@ function VerticalIconSelector() {
|
|
|
618
618
|
];
|
|
619
619
|
|
|
620
620
|
return (
|
|
621
|
-
<
|
|
621
|
+
<HazoUiFlexRadio
|
|
622
622
|
data={options}
|
|
623
623
|
value={selected}
|
|
624
624
|
onChange={setSelected}
|
package/dist/index.cjs
CHANGED
|
@@ -28,6 +28,7 @@ var FiIcons = require('react-icons/fi');
|
|
|
28
28
|
var IoIcons = require('react-icons/io5');
|
|
29
29
|
var RiIcons = require('react-icons/ri');
|
|
30
30
|
var TbIcons = require('react-icons/tb');
|
|
31
|
+
var CiIcons = require('react-icons/ci');
|
|
31
32
|
|
|
32
33
|
function _interopNamespace(e) {
|
|
33
34
|
if (e && e.__esModule) return e;
|
|
@@ -64,6 +65,7 @@ var FiIcons__namespace = /*#__PURE__*/_interopNamespace(FiIcons);
|
|
|
64
65
|
var IoIcons__namespace = /*#__PURE__*/_interopNamespace(IoIcons);
|
|
65
66
|
var RiIcons__namespace = /*#__PURE__*/_interopNamespace(RiIcons);
|
|
66
67
|
var TbIcons__namespace = /*#__PURE__*/_interopNamespace(TbIcons);
|
|
68
|
+
var CiIcons__namespace = /*#__PURE__*/_interopNamespace(CiIcons);
|
|
67
69
|
|
|
68
70
|
var ExampleComponent = ({ children, className = "" }) => {
|
|
69
71
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `cls_example_component ${className}`, children });
|
|
@@ -660,7 +662,7 @@ function FilterFieldItem({
|
|
|
660
662
|
)
|
|
661
663
|
] });
|
|
662
664
|
}
|
|
663
|
-
function
|
|
665
|
+
function HazoUiMultiFilterDialog({
|
|
664
666
|
availableFields,
|
|
665
667
|
onFilterChange,
|
|
666
668
|
initialFilters = []
|
|
@@ -980,7 +982,7 @@ function SortableSortFieldItem({
|
|
|
980
982
|
}
|
|
981
983
|
);
|
|
982
984
|
}
|
|
983
|
-
function
|
|
985
|
+
function HazoUiMultiSortDialog({
|
|
984
986
|
availableFields,
|
|
985
987
|
onSortChange,
|
|
986
988
|
initialSortFields = []
|
|
@@ -1230,7 +1232,8 @@ var iconSetMap = {
|
|
|
1230
1232
|
io: IoIcons__namespace,
|
|
1231
1233
|
io5: IoIcons__namespace,
|
|
1232
1234
|
ri: RiIcons__namespace,
|
|
1233
|
-
tb: TbIcons__namespace
|
|
1235
|
+
tb: TbIcons__namespace,
|
|
1236
|
+
ci: CiIcons__namespace
|
|
1234
1237
|
};
|
|
1235
1238
|
function getIconLibrary(iconSet) {
|
|
1236
1239
|
if (!iconSet) return null;
|
|
@@ -1244,7 +1247,7 @@ function getIconComponent(iconSet, iconName) {
|
|
|
1244
1247
|
const IconComponent = iconLibrary[iconName];
|
|
1245
1248
|
return IconComponent || null;
|
|
1246
1249
|
}
|
|
1247
|
-
function
|
|
1250
|
+
function HazoUiFlexRadio({
|
|
1248
1251
|
layout = "horizontal",
|
|
1249
1252
|
style = "radio",
|
|
1250
1253
|
display_label = true,
|
|
@@ -1376,6 +1379,10 @@ function MultiStateRadio({
|
|
|
1376
1379
|
const SelectedIcon = icon_set && item.icon_selected ? getIconComponent(icon_set, item.icon_selected) : null;
|
|
1377
1380
|
const UnselectedIcon = icon_set && item.icon_unselected ? getIconComponent(icon_set, item.icon_unselected) : null;
|
|
1378
1381
|
const IconComponent = selected && SelectedIcon ? SelectedIcon : UnselectedIcon || SelectedIcon;
|
|
1382
|
+
const buttonStyles = {};
|
|
1383
|
+
if (item.bgcolor) {
|
|
1384
|
+
buttonStyles.backgroundColor = item.bgcolor;
|
|
1385
|
+
}
|
|
1379
1386
|
const buttonContent = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1380
1387
|
Button,
|
|
1381
1388
|
{
|
|
@@ -1386,9 +1393,11 @@ function MultiStateRadio({
|
|
|
1386
1393
|
layout === "horizontal" ? "flex-row" : "flex-col",
|
|
1387
1394
|
"gap-2 h-auto",
|
|
1388
1395
|
compressed ? "py-0 px-0" : "py-2 px-3 sm:py-3 sm:px-4",
|
|
1389
|
-
|
|
1390
|
-
!selected && "
|
|
1396
|
+
// Only apply default colors if custom colors are not provided
|
|
1397
|
+
!item.bgcolor && selected && "bg-primary text-primary-foreground",
|
|
1398
|
+
!item.bgcolor && !selected && "hover:bg-accent"
|
|
1391
1399
|
),
|
|
1400
|
+
style: Object.keys(buttonStyles).length > 0 ? buttonStyles : void 0,
|
|
1392
1401
|
onClick: () => {
|
|
1393
1402
|
if (selection === "single") {
|
|
1394
1403
|
handleSingleSelection(item.value);
|
|
@@ -1399,8 +1408,21 @@ function MultiStateRadio({
|
|
|
1399
1408
|
"aria-label": item.label,
|
|
1400
1409
|
"aria-pressed": selected,
|
|
1401
1410
|
children: [
|
|
1402
|
-
IconComponent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1403
|
-
|
|
1411
|
+
IconComponent && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1412
|
+
IconComponent,
|
|
1413
|
+
{
|
|
1414
|
+
className: "cls_icon h-4 w-4 sm:h-5 sm:w-5",
|
|
1415
|
+
style: item.fgcolor ? { color: item.fgcolor } : void 0
|
|
1416
|
+
}
|
|
1417
|
+
),
|
|
1418
|
+
display_label && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1419
|
+
"span",
|
|
1420
|
+
{
|
|
1421
|
+
className: "cls_icon_label text-sm font-medium",
|
|
1422
|
+
style: item.fgcolor ? { color: item.fgcolor } : void 0,
|
|
1423
|
+
children: item.label
|
|
1424
|
+
}
|
|
1425
|
+
)
|
|
1404
1426
|
]
|
|
1405
1427
|
}
|
|
1406
1428
|
);
|
|
@@ -1410,7 +1432,7 @@ function MultiStateRadio({
|
|
|
1410
1432
|
] }, item.value);
|
|
1411
1433
|
};
|
|
1412
1434
|
const containerClasses = cn(
|
|
1413
|
-
"
|
|
1435
|
+
"cls_hazo_ui_flex_radio border border-input rounded-md",
|
|
1414
1436
|
compressed ? "" : "p-2 sm:p-3",
|
|
1415
1437
|
layout === "horizontal" ? cn(
|
|
1416
1438
|
"flex flex-row flex-wrap",
|
|
@@ -1444,10 +1466,208 @@ function MultiStateRadio({
|
|
|
1444
1466
|
}
|
|
1445
1467
|
}
|
|
1446
1468
|
}
|
|
1469
|
+
function validateInput(value, input_type, text_len_min, text_len_max, num_min, num_max, regex, num_decimals) {
|
|
1470
|
+
if (value === "") {
|
|
1471
|
+
return { isValid: true };
|
|
1472
|
+
}
|
|
1473
|
+
switch (input_type) {
|
|
1474
|
+
case "numeric": {
|
|
1475
|
+
const numValue = parseFloat(value);
|
|
1476
|
+
if (isNaN(numValue)) {
|
|
1477
|
+
return { isValid: false, errorMessage: "Must be a valid number" };
|
|
1478
|
+
}
|
|
1479
|
+
if (num_decimals !== void 0) {
|
|
1480
|
+
const decimalPlaces = value.split(".")[1]?.length || 0;
|
|
1481
|
+
if (decimalPlaces > num_decimals) {
|
|
1482
|
+
return {
|
|
1483
|
+
isValid: false,
|
|
1484
|
+
errorMessage: `Maximum ${num_decimals} decimal place${num_decimals !== 1 ? "s" : ""} allowed`
|
|
1485
|
+
};
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
if (num_min !== void 0 && numValue < num_min) {
|
|
1489
|
+
return { isValid: false, errorMessage: `Must be at least ${num_min}` };
|
|
1490
|
+
}
|
|
1491
|
+
if (num_max !== void 0 && numValue > num_max) {
|
|
1492
|
+
return { isValid: false, errorMessage: `Must be at most ${num_max}` };
|
|
1493
|
+
}
|
|
1494
|
+
break;
|
|
1495
|
+
}
|
|
1496
|
+
case "alpha": {
|
|
1497
|
+
const alphaRegex = /^[A-Za-z\s]*$/;
|
|
1498
|
+
if (!alphaRegex.test(value)) {
|
|
1499
|
+
return { isValid: false, errorMessage: "Only letters are allowed" };
|
|
1500
|
+
}
|
|
1501
|
+
break;
|
|
1502
|
+
}
|
|
1503
|
+
case "email": {
|
|
1504
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1505
|
+
if (!emailRegex.test(value)) {
|
|
1506
|
+
return { isValid: false, errorMessage: "Must be a valid email address" };
|
|
1507
|
+
}
|
|
1508
|
+
break;
|
|
1509
|
+
}
|
|
1510
|
+
case "mixed": {
|
|
1511
|
+
if (text_len_min !== void 0 && value.length < text_len_min) {
|
|
1512
|
+
return {
|
|
1513
|
+
isValid: false,
|
|
1514
|
+
errorMessage: `Must be at least ${text_len_min} character${text_len_min !== 1 ? "s" : ""}`
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
if (text_len_max !== void 0 && value.length > text_len_max) {
|
|
1518
|
+
return {
|
|
1519
|
+
isValid: false,
|
|
1520
|
+
errorMessage: `Must be at most ${text_len_max} character${text_len_max !== 1 ? "s" : ""}`
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
break;
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
if (regex) {
|
|
1527
|
+
const regexPattern = typeof regex === "string" ? new RegExp(regex) : regex;
|
|
1528
|
+
if (!regexPattern.test(value)) {
|
|
1529
|
+
return { isValid: false, errorMessage: "Invalid format" };
|
|
1530
|
+
}
|
|
1531
|
+
}
|
|
1532
|
+
return { isValid: true };
|
|
1533
|
+
}
|
|
1534
|
+
function filterInputValue(value, input_type, num_decimals) {
|
|
1535
|
+
switch (input_type) {
|
|
1536
|
+
case "numeric": {
|
|
1537
|
+
let filtered = value.replace(/[^\d.-]/g, "");
|
|
1538
|
+
const parts = filtered.split(".");
|
|
1539
|
+
if (parts.length > 2) {
|
|
1540
|
+
filtered = parts[0] + "." + parts.slice(1).join("");
|
|
1541
|
+
}
|
|
1542
|
+
if (num_decimals === 0 && filtered.includes(".")) {
|
|
1543
|
+
filtered = filtered.replace(".", "");
|
|
1544
|
+
}
|
|
1545
|
+
if (num_decimals !== void 0 && num_decimals > 0) {
|
|
1546
|
+
const parts2 = filtered.split(".");
|
|
1547
|
+
if (parts2.length === 2 && parts2[1].length > num_decimals) {
|
|
1548
|
+
filtered = parts2[0] + "." + parts2[1].substring(0, num_decimals);
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
return filtered;
|
|
1552
|
+
}
|
|
1553
|
+
case "alpha": {
|
|
1554
|
+
return value.replace(/[^A-Za-z\s]/g, "");
|
|
1555
|
+
}
|
|
1556
|
+
case "email":
|
|
1557
|
+
case "mixed":
|
|
1558
|
+
default: {
|
|
1559
|
+
return value;
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
var HazoUiFlexInput = React6__namespace.forwardRef(
|
|
1564
|
+
({
|
|
1565
|
+
className,
|
|
1566
|
+
input_type = "mixed",
|
|
1567
|
+
text_len_min,
|
|
1568
|
+
text_len_max,
|
|
1569
|
+
num_min,
|
|
1570
|
+
num_max,
|
|
1571
|
+
regex,
|
|
1572
|
+
num_decimals,
|
|
1573
|
+
format_guide,
|
|
1574
|
+
format_guide_info = false,
|
|
1575
|
+
value: controlledValue,
|
|
1576
|
+
onChange,
|
|
1577
|
+
onBlur,
|
|
1578
|
+
...props
|
|
1579
|
+
}, ref) => {
|
|
1580
|
+
const [internalValue, setInternalValue] = React6__namespace.useState(
|
|
1581
|
+
typeof controlledValue === "string" ? controlledValue : typeof controlledValue === "number" ? String(controlledValue) : ""
|
|
1582
|
+
);
|
|
1583
|
+
const [errorMessage, setErrorMessage] = React6__namespace.useState();
|
|
1584
|
+
const isControlled = controlledValue !== void 0;
|
|
1585
|
+
const currentValue = isControlled ? typeof controlledValue === "string" ? controlledValue : String(controlledValue || "") : internalValue;
|
|
1586
|
+
React6__namespace.useEffect(() => {
|
|
1587
|
+
if (isControlled) {
|
|
1588
|
+
const newValue = typeof controlledValue === "string" ? controlledValue : String(controlledValue || "");
|
|
1589
|
+
if (newValue !== internalValue) {
|
|
1590
|
+
setInternalValue(newValue);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
}, [controlledValue, isControlled]);
|
|
1594
|
+
const handleChange = (e) => {
|
|
1595
|
+
let newValue = e.target.value;
|
|
1596
|
+
if (input_type === "numeric" || input_type === "alpha") {
|
|
1597
|
+
newValue = filterInputValue(newValue, input_type, num_decimals);
|
|
1598
|
+
}
|
|
1599
|
+
if (!isControlled) {
|
|
1600
|
+
setInternalValue(newValue);
|
|
1601
|
+
}
|
|
1602
|
+
if (errorMessage) {
|
|
1603
|
+
setErrorMessage(void 0);
|
|
1604
|
+
}
|
|
1605
|
+
if (onChange) {
|
|
1606
|
+
const syntheticEvent = {
|
|
1607
|
+
...e,
|
|
1608
|
+
target: { ...e.target, value: newValue }
|
|
1609
|
+
};
|
|
1610
|
+
onChange(syntheticEvent);
|
|
1611
|
+
}
|
|
1612
|
+
};
|
|
1613
|
+
const handleBlur = (e) => {
|
|
1614
|
+
const validation = validateInput(
|
|
1615
|
+
currentValue,
|
|
1616
|
+
input_type,
|
|
1617
|
+
text_len_min,
|
|
1618
|
+
text_len_max,
|
|
1619
|
+
num_min,
|
|
1620
|
+
num_max,
|
|
1621
|
+
regex,
|
|
1622
|
+
num_decimals
|
|
1623
|
+
);
|
|
1624
|
+
if (!validation.isValid) {
|
|
1625
|
+
setErrorMessage(validation.errorMessage || format_guide || "Invalid input");
|
|
1626
|
+
} else {
|
|
1627
|
+
setErrorMessage(void 0);
|
|
1628
|
+
}
|
|
1629
|
+
if (onBlur) {
|
|
1630
|
+
onBlur(e);
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
const htmlInputType = input_type === "email" ? "email" : input_type === "numeric" ? "text" : "text";
|
|
1634
|
+
const hasError = errorMessage !== void 0;
|
|
1635
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "cls_hazo_ui_flex_input_container w-full", children: [
|
|
1636
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1637
|
+
Input,
|
|
1638
|
+
{
|
|
1639
|
+
ref,
|
|
1640
|
+
type: htmlInputType,
|
|
1641
|
+
value: currentValue,
|
|
1642
|
+
onChange: handleChange,
|
|
1643
|
+
onBlur: handleBlur,
|
|
1644
|
+
className: cn(
|
|
1645
|
+
hasError && "border-destructive focus-visible:ring-destructive",
|
|
1646
|
+
className
|
|
1647
|
+
),
|
|
1648
|
+
...props
|
|
1649
|
+
}
|
|
1650
|
+
),
|
|
1651
|
+
hasError && errorMessage && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "cls_error_message mt-1 text-sm text-destructive", children: errorMessage }),
|
|
1652
|
+
format_guide_info && format_guide && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1653
|
+
"p",
|
|
1654
|
+
{
|
|
1655
|
+
className: cn(
|
|
1656
|
+
"cls_format_guide_info mt-1 text-xs italic text-muted-foreground",
|
|
1657
|
+
hasError && "mt-0"
|
|
1658
|
+
),
|
|
1659
|
+
children: format_guide
|
|
1660
|
+
}
|
|
1661
|
+
)
|
|
1662
|
+
] });
|
|
1663
|
+
}
|
|
1664
|
+
);
|
|
1665
|
+
HazoUiFlexInput.displayName = "HazoUiFlexInput";
|
|
1447
1666
|
|
|
1448
1667
|
exports.ExampleComponent = ExampleComponent;
|
|
1449
|
-
exports.
|
|
1450
|
-
exports.
|
|
1451
|
-
exports.
|
|
1668
|
+
exports.HazoUiFlexInput = HazoUiFlexInput;
|
|
1669
|
+
exports.HazoUiFlexRadio = HazoUiFlexRadio;
|
|
1670
|
+
exports.HazoUiMultiFilterDialog = HazoUiMultiFilterDialog;
|
|
1671
|
+
exports.HazoUiMultiSortDialog = HazoUiMultiSortDialog;
|
|
1452
1672
|
//# sourceMappingURL=index.cjs.map
|
|
1453
1673
|
//# sourceMappingURL=index.cjs.map
|