@sustaina/shared-ui 1.24.0 → 1.25.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.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +121 -59
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +121 -59
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,6 @@ import { twMerge } from 'tailwind-merge';
|
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import * as React4 from 'react';
|
|
6
6
|
import React4__default, { forwardRef, useRef, useMemo, useCallback, isValidElement, useState, useEffect, useLayoutEffect, createElement } from 'react';
|
|
7
|
-
import { format, isValid, parseISO, isAfter, compareAsc, parse } from 'date-fns';
|
|
8
7
|
import { CircleX, CircleHelp, Undo, Redo, Bold, Italic, Underline, Strikethrough, Code, Pilcrow, Heading1, Heading2, Heading3, List as List$1, ListOrdered, Quote, CodeSquare, Link, Link2Off, Image as Image$1, AlignLeft, AlignCenter, AlignRight, XIcon, ChevronRight, CheckIcon, Triangle, CalendarIcon, X, Search, ChevronUp, ChevronDown, Minimize2, Maximize2, Plus, ChevronLeft, CircleUserRound, PanelLeftIcon, Bug, GripVertical, Info, CircleMinus, Minus } from 'lucide-react';
|
|
9
8
|
import { createPortal } from 'react-dom';
|
|
10
9
|
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
@@ -12,6 +11,7 @@ import { useForm, FormProvider, Controller, useFormContext, useFormState, useFie
|
|
|
12
11
|
import { Slot } from '@radix-ui/react-slot';
|
|
13
12
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
14
13
|
import { cva } from 'class-variance-authority';
|
|
14
|
+
import { format, isValid, parseISO, isAfter, compareAsc, parse } from 'date-fns';
|
|
15
15
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
16
16
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
17
17
|
import * as CollapsiblePrimitive from '@radix-ui/react-collapsible';
|
|
@@ -3421,6 +3421,66 @@ function getBuilder(fieldType) {
|
|
|
3421
3421
|
return new JSONBuilder();
|
|
3422
3422
|
}
|
|
3423
3423
|
}
|
|
3424
|
+
var FILTER_FIELD_MAP = {
|
|
3425
|
+
timezone: "timezoneId",
|
|
3426
|
+
decimalSeparator: "decimalSeparatorId",
|
|
3427
|
+
country: "countryId",
|
|
3428
|
+
currency: "currencyId"
|
|
3429
|
+
};
|
|
3430
|
+
function transformFilterKeys(obj, fieldMap = FILTER_FIELD_MAP) {
|
|
3431
|
+
if (Array.isArray(obj)) {
|
|
3432
|
+
return obj.map((item) => transformFilterKeys(item, fieldMap));
|
|
3433
|
+
}
|
|
3434
|
+
if (obj && typeof obj === "object") {
|
|
3435
|
+
const newObj = {};
|
|
3436
|
+
for (const key in obj) {
|
|
3437
|
+
const mappedKey = fieldMap[key] ?? key;
|
|
3438
|
+
newObj[mappedKey] = transformFilterKeys(obj[key], fieldMap);
|
|
3439
|
+
}
|
|
3440
|
+
return newObj;
|
|
3441
|
+
}
|
|
3442
|
+
return obj;
|
|
3443
|
+
}
|
|
3444
|
+
var sanitizeInput = (val) => {
|
|
3445
|
+
if (!val) return val;
|
|
3446
|
+
if (typeof val !== "string") return "__INVALID_TYPE__";
|
|
3447
|
+
if (val.includes("\n") || val.includes("\r") || /[\u2028\u2029]/u.test(val))
|
|
3448
|
+
return "__INVALID_NEWLINE__";
|
|
3449
|
+
if (/\\\\/.test(val)) return "__INVALID_ESCAPE__";
|
|
3450
|
+
if (/\\(n|t|r|b|f|u[0-9a-fA-F]{4})/.test(val)) return "__INVALID_ESCAPE__";
|
|
3451
|
+
if (/\p{Cf}/u.test(val)) return "__INVALID_UNICODE_WHITESPACE__";
|
|
3452
|
+
if (/[\u00A0\u1680\u180E\u202F\u205F\u3000]/u.test(val)) return "__INVALID_UNICODE_WHITESPACE__";
|
|
3453
|
+
const trimmed = val.trim();
|
|
3454
|
+
if (/^\{.*\}$/s.test(trimmed) || /^\[.*\]$/s.test(trimmed)) return "__INVALID_JSON_LITERAL__";
|
|
3455
|
+
if (/\\\{/.test(val) || /\\\}/.test(val)) return "__INVALID_JSON_ESCAPE__";
|
|
3456
|
+
if (/[%_*~^]/.test(trimmed)) return "__INVALID_WILDCARD__";
|
|
3457
|
+
if (/[%><={}\\[\]"']/u.test(trimmed)) return "__INVALID_CHAR__";
|
|
3458
|
+
if (/\p{Cc}/u.test(val)) return "__INVALID_CONTROL_CHAR__";
|
|
3459
|
+
return trimmed.replace(/\s+/g, " ");
|
|
3460
|
+
};
|
|
3461
|
+
var numericTypes = ["number", "integer", "decimal"];
|
|
3462
|
+
var dateTypes = ["date", "datemonth"];
|
|
3463
|
+
var validateByFieldType = (value, fieldType) => {
|
|
3464
|
+
if (!value) return { valid: true };
|
|
3465
|
+
if (numericTypes.includes(fieldType)) {
|
|
3466
|
+
if (!/^\d+(\.\d+)?$/.test(value)) {
|
|
3467
|
+
return { valid: false, message: "Please enter a valid number." };
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
if (fieldType === "boolean") {
|
|
3471
|
+
if (!["true", "false"].includes(value.toLowerCase())) {
|
|
3472
|
+
return { valid: false, message: "Please enter a boolean value (true/false)." };
|
|
3473
|
+
}
|
|
3474
|
+
}
|
|
3475
|
+
if (dateTypes.includes(fieldType)) {
|
|
3476
|
+
const normalized = fieldType === "datemonth" ? `${value}-01` : value;
|
|
3477
|
+
const parsed = parseISO(normalized);
|
|
3478
|
+
if (!isValid(parsed)) {
|
|
3479
|
+
return { valid: false, message: "Invalid date format." };
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
return { valid: true };
|
|
3483
|
+
};
|
|
3424
3484
|
var AdvanceSearch = ({
|
|
3425
3485
|
fields,
|
|
3426
3486
|
portalId,
|
|
@@ -3428,7 +3488,8 @@ var AdvanceSearch = ({
|
|
|
3428
3488
|
limitRows = 4,
|
|
3429
3489
|
onSearch,
|
|
3430
3490
|
onClear,
|
|
3431
|
-
shortDateFormat
|
|
3491
|
+
shortDateFormat,
|
|
3492
|
+
filterFieldMap = FILTER_FIELD_MAP
|
|
3432
3493
|
}) => {
|
|
3433
3494
|
const fieldsData = useMemo(() => {
|
|
3434
3495
|
if (fields.length === 0) throw new Error("fields cannot be an empty array");
|
|
@@ -3480,72 +3541,75 @@ var AdvanceSearch = ({
|
|
|
3480
3541
|
const onSubmit = useCallback(() => {
|
|
3481
3542
|
const operatorValidation = {};
|
|
3482
3543
|
rows.forEach((r) => {
|
|
3483
|
-
const
|
|
3484
|
-
if (!
|
|
3544
|
+
const ops = operatorsForField(r.fieldName);
|
|
3545
|
+
if (!ops.length || !ops.includes(r.operator))
|
|
3485
3546
|
operatorValidation[r.id] = "Please select an operator.";
|
|
3486
|
-
}
|
|
3487
3547
|
});
|
|
3488
3548
|
setOperatorErrors(operatorValidation);
|
|
3489
|
-
if (Object.keys(operatorValidation).length > 0)
|
|
3490
|
-
return;
|
|
3491
|
-
}
|
|
3549
|
+
if (Object.keys(operatorValidation).length > 0) return;
|
|
3492
3550
|
const currentValues = getValues();
|
|
3493
|
-
let
|
|
3494
|
-
const
|
|
3495
|
-
const
|
|
3496
|
-
const
|
|
3551
|
+
let hasError = false;
|
|
3552
|
+
const processedRows = rows.map((r) => {
|
|
3553
|
+
const startField = `value_${r.id}`;
|
|
3554
|
+
const endField = `value2_${r.id}`;
|
|
3555
|
+
let v1 = currentValues[startField] ?? "";
|
|
3556
|
+
let v2 = currentValues[endField] ?? "";
|
|
3557
|
+
const s1 = sanitizeInput(v1);
|
|
3558
|
+
if (s1?.startsWith("__INVALID")) {
|
|
3559
|
+
hasError = true;
|
|
3560
|
+
setError(startField, { type: "validate", message: "Invalid input." });
|
|
3561
|
+
return null;
|
|
3562
|
+
}
|
|
3563
|
+
v1 = s1 || "";
|
|
3564
|
+
const valid1 = validateByFieldType(v1, r.fieldType);
|
|
3565
|
+
if (!valid1.valid) {
|
|
3566
|
+
hasError = true;
|
|
3567
|
+
setError(startField, { type: "validate", message: valid1.message });
|
|
3568
|
+
return null;
|
|
3569
|
+
}
|
|
3497
3570
|
if (r.operator === "between") {
|
|
3498
|
-
const
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
|
|
3503
|
-
|
|
3504
|
-
|
|
3505
|
-
|
|
3506
|
-
|
|
3507
|
-
|
|
3508
|
-
|
|
3509
|
-
|
|
3510
|
-
|
|
3511
|
-
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3571
|
+
const s2 = sanitizeInput(v2);
|
|
3572
|
+
if (s2?.startsWith("__INVALID")) {
|
|
3573
|
+
hasError = true;
|
|
3574
|
+
setError(endField, { type: "validate", message: "Invalid input." });
|
|
3575
|
+
return null;
|
|
3576
|
+
}
|
|
3577
|
+
v2 = s2 || "";
|
|
3578
|
+
const valid2 = validateByFieldType(v2, r.fieldType);
|
|
3579
|
+
if (!valid2.valid) {
|
|
3580
|
+
hasError = true;
|
|
3581
|
+
setError(endField, { type: "validate", message: valid2.message });
|
|
3582
|
+
return null;
|
|
3583
|
+
}
|
|
3584
|
+
if (v1 && v2 && ["date", "datemonth"].includes(r.fieldType)) {
|
|
3585
|
+
const d1 = parseRangeValue(v1, r.fieldType);
|
|
3586
|
+
const d2 = parseRangeValue(v2, r.fieldType);
|
|
3587
|
+
if (d1 && d2 && isAfter(d1, d2)) {
|
|
3588
|
+
hasError = true;
|
|
3589
|
+
setError(startField, { type: "validate", message: "Start value must be before end value." });
|
|
3590
|
+
setError(endField, { type: "validate", message: "End value must be after start value." });
|
|
3591
|
+
return null;
|
|
3515
3592
|
}
|
|
3516
3593
|
}
|
|
3517
|
-
return {
|
|
3518
|
-
...r,
|
|
3519
|
-
value: startValue ?? "",
|
|
3520
|
-
value2: endValue ?? ""
|
|
3521
|
-
};
|
|
3594
|
+
return { ...r, value: v1, value2: v2 };
|
|
3522
3595
|
}
|
|
3523
|
-
return {
|
|
3524
|
-
...r,
|
|
3525
|
-
value: startValue ?? ""
|
|
3526
|
-
};
|
|
3596
|
+
return { ...r, value: v1 };
|
|
3527
3597
|
});
|
|
3528
|
-
if (
|
|
3529
|
-
|
|
3530
|
-
}
|
|
3598
|
+
if (hasError) return;
|
|
3599
|
+
const cleanedRows = processedRows.filter(Boolean);
|
|
3531
3600
|
const param = {
|
|
3532
|
-
AND:
|
|
3533
|
-
const builder = getBuilder(r.fieldType);
|
|
3534
|
-
return builder.build(r);
|
|
3535
|
-
}).filter(Boolean)
|
|
3601
|
+
AND: cleanedRows.map((r) => getBuilder(r.fieldType).build(r)).filter(Boolean)
|
|
3536
3602
|
};
|
|
3537
|
-
if (onSearch)
|
|
3538
|
-
onSearch(param);
|
|
3539
|
-
}
|
|
3603
|
+
if (onSearch) onSearch(transformFilterKeys(param, filterFieldMap));
|
|
3540
3604
|
}, [
|
|
3541
|
-
|
|
3542
|
-
getValues,
|
|
3543
|
-
onSearch,
|
|
3605
|
+
rows,
|
|
3544
3606
|
operatorsForField,
|
|
3607
|
+
getValues,
|
|
3545
3608
|
parseRangeValue,
|
|
3546
|
-
rows,
|
|
3547
3609
|
setError,
|
|
3548
|
-
setOperatorErrors
|
|
3610
|
+
setOperatorErrors,
|
|
3611
|
+
filterFieldMap,
|
|
3612
|
+
onSearch
|
|
3549
3613
|
]);
|
|
3550
3614
|
return /* @__PURE__ */ jsx(
|
|
3551
3615
|
ExpandCollapse_default,
|
|
@@ -3583,9 +3647,7 @@ var AdvanceSearch = ({
|
|
|
3583
3647
|
unregister(`value_${row.id}`);
|
|
3584
3648
|
unregister(`value2_${row.id}`);
|
|
3585
3649
|
},
|
|
3586
|
-
onClearValue: (which) =>
|
|
3587
|
-
clearValue(row.id, which);
|
|
3588
|
-
},
|
|
3650
|
+
onClearValue: (which) => clearValue(row.id, which),
|
|
3589
3651
|
disableAdd: limitRows !== void 0 && rows.length >= limitRows
|
|
3590
3652
|
},
|
|
3591
3653
|
row.id
|
|
@@ -3610,7 +3672,7 @@ var AdvanceSearch = ({
|
|
|
3610
3672
|
Button,
|
|
3611
3673
|
{
|
|
3612
3674
|
type: "submit",
|
|
3613
|
-
className: "w-full bg-
|
|
3675
|
+
className: "w-full bg-sus-green-2 text-white hover:bg-[#2f7c21] md:w-auto md:min-w-[120px]",
|
|
3614
3676
|
"data-testid": "advsearch-btn-search",
|
|
3615
3677
|
children: "Search"
|
|
3616
3678
|
}
|
|
@@ -6547,8 +6609,8 @@ var GridSettingsModal = ({
|
|
|
6547
6609
|
}
|
|
6548
6610
|
}, [isOpen, currentColumns, form]);
|
|
6549
6611
|
const addColumn = async () => {
|
|
6550
|
-
const
|
|
6551
|
-
if (
|
|
6612
|
+
const isValid6 = await trigger("columns");
|
|
6613
|
+
if (isValid6) {
|
|
6552
6614
|
append({ id: "" });
|
|
6553
6615
|
requestAnimationFrame(() => {
|
|
6554
6616
|
const container = scrollRef.current;
|