periplo-ui 4.4.2 → 4.6.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/components/Checkbox/Checkbox.d.ts +4 -4
- package/dist/components/Checkbox/Checkbox.js +3 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/DataTable/DataTable.d.ts +1 -1
- package/dist/components/DataTable/DataTable.js +49 -18
- package/dist/components/DataTable/DataTable.js.map +1 -1
- package/dist/components/DataTable/components/DataTableBody.d.ts +12 -3
- package/dist/components/DataTable/components/DataTableBody.js +43 -8
- package/dist/components/DataTable/components/DataTableBody.js.map +1 -1
- package/dist/components/DataTable/components/DataTableGroupRow.d.ts +10 -0
- package/dist/components/DataTable/components/DataTableGroupRow.js +25 -0
- package/dist/components/DataTable/components/DataTableGroupRow.js.map +1 -0
- package/dist/components/DataTable/components/DataTableGroupRowSelector.d.ts +9 -0
- package/dist/components/DataTable/components/DataTableGroupRowSelector.js +32 -0
- package/dist/components/DataTable/components/DataTableGroupRowSelector.js.map +1 -0
- package/dist/components/DataTable/components/DataTableSelectHeader.js +16 -10
- package/dist/components/DataTable/components/DataTableSelectHeader.js.map +1 -1
- package/dist/components/DataTable/hooks/useGroupExpansion.d.ts +19 -0
- package/dist/components/DataTable/hooks/useGroupExpansion.js +34 -0
- package/dist/components/DataTable/hooks/useGroupExpansion.js.map +1 -0
- package/dist/components/DataTable/types.d.ts +27 -6
- package/dist/components/DataTable/utils.d.ts +6 -0
- package/dist/components/DataTable/utils.js +15 -0
- package/dist/components/DataTable/utils.js.map +1 -0
- package/dist/components/InputDate/InputDate.d.ts +9 -11
- package/dist/components/InputDate/InputDate.js +91 -113
- package/dist/components/InputDate/InputDate.js.map +1 -1
- package/package.json +6 -3
- package/dist/components/InputDate/MaskedInput.d.ts +0 -18
- package/dist/components/InputDate/MaskedInput.js +0 -227
- package/dist/components/InputDate/MaskedInput.js.map +0 -1
- package/dist/components/InputDate/manualDateFormat.d.ts +0 -11
- package/dist/components/InputDate/manualDateFormat.js +0 -60
- package/dist/components/InputDate/manualDateFormat.js.map +0 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
function useGroupExpansion({
|
|
4
|
+
grouping,
|
|
5
|
+
data,
|
|
6
|
+
getRowId
|
|
7
|
+
}) {
|
|
8
|
+
const [internalExpanded, setInternalExpanded] = React.useState(grouping?.defaultOpen ? true : {});
|
|
9
|
+
const expandedState = grouping?.open ?? internalExpanded;
|
|
10
|
+
const setExpandedState = grouping?.onOpenChange ?? setInternalExpanded;
|
|
11
|
+
const isGroupOpen = React.useCallback(
|
|
12
|
+
(groupId) => expandedState === true || typeof expandedState === "object" && expandedState[groupId] === true,
|
|
13
|
+
[expandedState]
|
|
14
|
+
);
|
|
15
|
+
const groupIds = React.useMemo(
|
|
16
|
+
() => grouping ? data.filter((item) => (grouping.getSubRows(item)?.length ?? 0) > 0).map(getRowId) : [],
|
|
17
|
+
[grouping, data, getRowId]
|
|
18
|
+
);
|
|
19
|
+
const toggleGroup = React.useCallback(
|
|
20
|
+
(groupId) => {
|
|
21
|
+
const updater = (prev) => {
|
|
22
|
+
const current = prev === true ? Object.fromEntries(groupIds.map((id) => [id, true])) : { ...prev };
|
|
23
|
+
current[groupId] = !current[groupId];
|
|
24
|
+
return current;
|
|
25
|
+
};
|
|
26
|
+
setExpandedState(updater);
|
|
27
|
+
},
|
|
28
|
+
[setExpandedState, groupIds]
|
|
29
|
+
);
|
|
30
|
+
return { isGroupOpen, toggleGroup };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { useGroupExpansion };
|
|
34
|
+
//# sourceMappingURL=useGroupExpansion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useGroupExpansion.js","sources":["../../../../src/components/DataTable/hooks/useGroupExpansion.ts"],"sourcesContent":["import { ExpandedState, Updater } from '@tanstack/react-table'\nimport * as React from 'react'\n\nimport { GroupingConfig, RowIdentifierFn } from '../types'\n\ntype UseGroupExpansionParams<TData> = {\n grouping?: GroupingConfig<TData>\n data: Array<TData>\n getRowId: RowIdentifierFn<TData>\n}\n\ntype UseGroupExpansionResult = {\n /** Whether the group identified by `groupId` is currently expanded. */\n isGroupOpen: (groupId: string) => boolean\n /** Toggles the expanded state of the group identified by `groupId`. */\n toggleGroup: (groupId: string) => void\n}\n\n/**\n * Encapsulates the expanded-state bookkeeping for grouped tables: tracks which\n * groups are open (supporting both controlled and uncontrolled modes) and\n * exposes helpers to query and toggle individual groups.\n */\nexport function useGroupExpansion<TData>({\n grouping,\n data,\n getRowId,\n}: UseGroupExpansionParams<TData>): UseGroupExpansionResult {\n const [internalExpanded, setInternalExpanded] = React.useState<ExpandedState>(grouping?.defaultOpen ? true : {})\n\n const expandedState = grouping?.open ?? internalExpanded\n const setExpandedState = grouping?.onOpenChange ?? setInternalExpanded\n\n const isGroupOpen = React.useCallback(\n (groupId: string) =>\n expandedState === true || (typeof expandedState === 'object' && expandedState[groupId] === true),\n [expandedState],\n )\n\n const groupIds = React.useMemo(\n () => (grouping ? data.filter((item) => (grouping.getSubRows(item)?.length ?? 0) > 0).map(getRowId) : []),\n [grouping, data, getRowId],\n )\n\n const toggleGroup = React.useCallback(\n (groupId: string) => {\n const updater = (prev: ExpandedState): ExpandedState => {\n const current = prev === true ? Object.fromEntries(groupIds.map((id) => [id, true])) : { ...prev }\n current[groupId] = !current[groupId]\n return current\n }\n ;(setExpandedState as (u: Updater<ExpandedState>) => void)(updater)\n },\n [setExpandedState, groupIds],\n )\n\n return { isGroupOpen, toggleGroup }\n}\n"],"names":[],"mappings":";;AAuBO,SAAS,iBAAA,CAAyB;AAAA,EACvC,QAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAAA,EAA4D;AAC1D,EAAA,MAAM,CAAC,gBAAA,EAAkB,mBAAmB,CAAA,GAAI,KAAA,CAAM,SAAwB,QAAA,EAAU,WAAA,GAAc,IAAA,GAAO,EAAE,CAAA;AAE/G,EAAA,MAAM,aAAA,GAAgB,UAAU,IAAA,IAAQ,gBAAA;AACxC,EAAA,MAAM,gBAAA,GAAmB,UAAU,YAAA,IAAgB,mBAAA;AAEnD,EAAA,MAAM,cAAc,KAAA,CAAM,WAAA;AAAA,IACxB,CAAC,YACC,aAAA,KAAkB,IAAA,IAAS,OAAO,aAAA,KAAkB,QAAA,IAAY,aAAA,CAAc,OAAO,CAAA,KAAM,IAAA;AAAA,IAC7F,CAAC,aAAa;AAAA,GAChB;AAEA,EAAA,MAAM,WAAW,KAAA,CAAM,OAAA;AAAA,IACrB,MAAO,QAAA,GAAW,IAAA,CAAK,MAAA,CAAO,CAAC,UAAU,QAAA,CAAS,UAAA,CAAW,IAAI,CAAA,EAAG,UAAU,CAAA,IAAK,CAAC,EAAE,GAAA,CAAI,QAAQ,IAAI,EAAC;AAAA,IACvG,CAAC,QAAA,EAAU,IAAA,EAAM,QAAQ;AAAA,GAC3B;AAEA,EAAA,MAAM,cAAc,KAAA,CAAM,WAAA;AAAA,IACxB,CAAC,OAAA,KAAoB;AACnB,MAAA,MAAM,OAAA,GAAU,CAAC,IAAA,KAAuC;AACtD,QAAA,MAAM,UAAU,IAAA,KAAS,IAAA,GAAO,MAAA,CAAO,WAAA,CAAY,SAAS,GAAA,CAAI,CAAC,EAAA,KAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAA,GAAI,EAAE,GAAG,IAAA,EAAK;AACjG,QAAA,OAAA,CAAQ,OAAO,CAAA,GAAI,CAAC,OAAA,CAAQ,OAAO,CAAA;AACnC,QAAA,OAAO,OAAA;AAAA,MACT,CAAA;AACC,MAAC,iBAAyD,OAAO,CAAA;AAAA,IACpE,CAAA;AAAA,IACA,CAAC,kBAAkB,QAAQ;AAAA,GAC7B;AAEA,EAAA,OAAO,EAAE,aAAa,WAAA,EAAY;AACpC;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ColumnDef, OnChangeFn, VisibilityState } from '@tanstack/react-table';
|
|
1
|
+
import { ColumnDef, ExpandedState, OnChangeFn, Row, VisibilityState } from '@tanstack/react-table';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
export type User = {
|
|
4
4
|
id: string;
|
|
@@ -107,7 +107,19 @@ export type BackendPaginationProps = {
|
|
|
107
107
|
/** Callback when page changes */
|
|
108
108
|
readonly onPageChange: (page: number) => void;
|
|
109
109
|
} & BasePaginationProps;
|
|
110
|
-
export type
|
|
110
|
+
export type GroupingConfig<TData> = {
|
|
111
|
+
/** Returns the children for a row. Return `undefined`/empty for leaf rows (no group). */
|
|
112
|
+
readonly getSubRows: (row: TData) => Array<TData> | undefined;
|
|
113
|
+
/** Whether all groups are expanded on first render (default: `false`, all collapsed). */
|
|
114
|
+
readonly defaultOpen?: boolean;
|
|
115
|
+
/** Controlled expanded state. When provided, you must manage it via `onOpenChange`. */
|
|
116
|
+
readonly open?: ExpandedState;
|
|
117
|
+
/** Callback when the expanded state changes (controlled mode). */
|
|
118
|
+
readonly onOpenChange?: OnChangeFn<ExpandedState>;
|
|
119
|
+
/** Renders the content of a group row (label, count, etc.). Defaults to an item count. */
|
|
120
|
+
readonly renderGroupRow?: (row: Row<TData>) => ReactNode;
|
|
121
|
+
};
|
|
122
|
+
type DataTableBaseProps<TData> = {
|
|
111
123
|
/** Array of column definitions that describe the table structure */
|
|
112
124
|
readonly columns: Array<ColumnDef<TData>>;
|
|
113
125
|
/** Array of data items to be displayed in the table */
|
|
@@ -116,8 +128,6 @@ export type DataTableProps<TData> = {
|
|
|
116
128
|
readonly columnVisibility?: ColumnVisibilityConfig;
|
|
117
129
|
/** Whether the table is in a loading state */
|
|
118
130
|
readonly isLoading?: boolean;
|
|
119
|
-
/** Pagination configuration. If not provided, pagination is disabled */
|
|
120
|
-
readonly pagination?: BasePaginationProps | BackendPaginationProps;
|
|
121
131
|
/** Primary filters that appear directly above the table */
|
|
122
132
|
readonly primaryFilters?: ReactNode;
|
|
123
133
|
/** Secondary filters that appear in the filters dropdown */
|
|
@@ -154,13 +164,23 @@ export type DataTableProps<TData> = {
|
|
|
154
164
|
readonly className?: string;
|
|
155
165
|
/** Optional className for the table */
|
|
156
166
|
readonly tableClassName?: string;
|
|
157
|
-
}
|
|
167
|
+
};
|
|
168
|
+
type IdProps<TData> = HasId<TData> extends true ? {
|
|
158
169
|
/** Function to get unique identifier from a row. Not needed when data has 'id' property */
|
|
159
170
|
readonly getRowId?: RowIdentifierFn<TData>;
|
|
160
171
|
} : {
|
|
161
172
|
/** Function to get unique identifier from a row. Required when data doesn't have 'id' property */
|
|
162
173
|
readonly getRowId: RowIdentifierFn<TData>;
|
|
163
|
-
}
|
|
174
|
+
};
|
|
175
|
+
type PaginatedVariant = {
|
|
176
|
+
readonly pagination?: BasePaginationProps | BackendPaginationProps;
|
|
177
|
+
readonly grouping?: never;
|
|
178
|
+
};
|
|
179
|
+
type GroupedVariant<TData> = {
|
|
180
|
+
readonly grouping: GroupingConfig<TData>;
|
|
181
|
+
readonly pagination?: never;
|
|
182
|
+
};
|
|
183
|
+
export type DataTableProps<TData> = DataTableBaseProps<TData> & IdProps<TData> & (PaginatedVariant | GroupedVariant<TData>);
|
|
164
184
|
/**
|
|
165
185
|
* Type helper to check if a type has an 'id' property
|
|
166
186
|
*/
|
|
@@ -171,3 +191,4 @@ export type HasId<T> = T extends {
|
|
|
171
191
|
* Function to get a unique identifier from a row
|
|
172
192
|
*/
|
|
173
193
|
export type RowIdentifierFn<T> = (row: T) => string;
|
|
194
|
+
export {};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively flattens a sub-row tree into its leaf items, discarding group
|
|
3
|
+
* nodes. Used so selection (counts, select-all, ids) operates over the actual
|
|
4
|
+
* selectable leaf rows rather than the group containers.
|
|
5
|
+
*/
|
|
6
|
+
export declare function flattenLeaves<TData>(data: Array<TData>, getSubRows: (row: TData) => Array<TData> | undefined): Array<TData>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function flattenLeaves(data, getSubRows) {
|
|
2
|
+
const leaves = [];
|
|
3
|
+
for (const item of data) {
|
|
4
|
+
const children = getSubRows(item);
|
|
5
|
+
if (children && children.length > 0) {
|
|
6
|
+
leaves.push(...flattenLeaves(children, getSubRows));
|
|
7
|
+
} else {
|
|
8
|
+
leaves.push(item);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return leaves;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export { flattenLeaves };
|
|
15
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../../../src/components/DataTable/utils.ts"],"sourcesContent":["/**\n * Recursively flattens a sub-row tree into its leaf items, discarding group\n * nodes. Used so selection (counts, select-all, ids) operates over the actual\n * selectable leaf rows rather than the group containers.\n */\nexport function flattenLeaves<TData>(\n data: Array<TData>,\n getSubRows: (row: TData) => Array<TData> | undefined,\n): Array<TData> {\n const leaves: Array<TData> = []\n for (const item of data) {\n const children = getSubRows(item)\n if (children && children.length > 0) {\n leaves.push(...flattenLeaves(children, getSubRows))\n } else {\n leaves.push(item)\n }\n }\n return leaves\n}\n"],"names":[],"mappings":"AAKO,SAAS,aAAA,CACd,MACA,UAAA,EACc;AACd,EAAA,MAAM,SAAuB,EAAC;AAC9B,EAAA,KAAA,MAAW,QAAQ,IAAA,EAAM;AACvB,IAAA,MAAM,QAAA,GAAW,WAAW,IAAI,CAAA;AAChC,IAAA,IAAI,QAAA,IAAY,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AACnC,MAAA,MAAA,CAAO,IAAA,CAAK,GAAG,aAAA,CAAc,QAAA,EAAU,UAAU,CAAC,CAAA;AAAA,IACpD,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,IAClB;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;;;;"}
|
|
@@ -1,27 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DateField, DateValue } from 'react-aria-components';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
export type InputDateProps = {
|
|
4
4
|
className?: string;
|
|
5
|
-
endContent?: React.ReactElement;
|
|
6
5
|
disabled?: boolean;
|
|
7
6
|
error?: boolean | string;
|
|
8
7
|
errorMessage?: string;
|
|
9
8
|
inputClassName?: string;
|
|
10
|
-
|
|
9
|
+
locale?: string;
|
|
11
10
|
onClear?: boolean | (() => void);
|
|
12
|
-
value?:
|
|
13
|
-
onChange?: (
|
|
14
|
-
} & Omit<React.
|
|
11
|
+
value?: DateValue | null;
|
|
12
|
+
onChange?: (date: DateValue | null) => void;
|
|
13
|
+
} & Omit<React.ComponentPropsWithoutRef<typeof DateField<DateValue>>, 'value' | 'onChange'>;
|
|
15
14
|
declare const InputDate: React.ForwardRefExoticComponent<{
|
|
16
15
|
className?: string;
|
|
17
|
-
endContent?: React.ReactElement;
|
|
18
16
|
disabled?: boolean;
|
|
19
17
|
error?: boolean | string;
|
|
20
18
|
errorMessage?: string;
|
|
21
19
|
inputClassName?: string;
|
|
22
|
-
|
|
20
|
+
locale?: string;
|
|
23
21
|
onClear?: boolean | (() => void);
|
|
24
|
-
value?:
|
|
25
|
-
onChange?: (
|
|
26
|
-
} & Omit<React.
|
|
22
|
+
value?: DateValue | null;
|
|
23
|
+
onChange?: (date: DateValue | null) => void;
|
|
24
|
+
} & Omit<Omit<import('react-aria-components').DateFieldProps<DateValue> & React.RefAttributes<HTMLDivElement>, "ref">, "onChange" | "value"> & React.RefAttributes<HTMLDivElement>>;
|
|
27
25
|
export { InputDate };
|
|
@@ -2,25 +2,14 @@ import { jsxs, jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import { CalendarBlank } from '@phosphor-icons/react/dist/ssr/CalendarBlank';
|
|
3
3
|
import { WarningCircle } from '@phosphor-icons/react/dist/ssr/WarningCircle';
|
|
4
4
|
import { X } from '@phosphor-icons/react/dist/ssr/X';
|
|
5
|
+
import { I18nProvider } from 'react-aria';
|
|
5
6
|
import * as React from 'react';
|
|
6
|
-
import {
|
|
7
|
+
import { DateField, Group, DateInput, DateSegment } from 'react-aria-components';
|
|
7
8
|
import { cn } from '../../lib/utils.js';
|
|
8
9
|
|
|
9
|
-
const emit = (onChange, value) => {
|
|
10
|
-
onChange?.({ target: { value } });
|
|
11
|
-
};
|
|
12
|
-
const toInternalValue = (external, format) => {
|
|
13
|
-
const isoMatch = /^(\d{4})-(\d{2})-(\d{2})$/.exec(external.trim());
|
|
14
|
-
if (!isoMatch) return external;
|
|
15
|
-
const [, year, month, day] = isoMatch;
|
|
16
|
-
if (format === "DD/MM/YYYY") return `${day}/${month}/${year}`;
|
|
17
|
-
if (format === "MM/DD/YYYY") return `${month}/${day}/${year}`;
|
|
18
|
-
return `${year}/${month}/${day}`;
|
|
19
|
-
};
|
|
20
10
|
const InputDate = React.forwardRef(
|
|
21
11
|
({
|
|
22
12
|
className,
|
|
23
|
-
endContent,
|
|
24
13
|
disabled,
|
|
25
14
|
error,
|
|
26
15
|
errorMessage,
|
|
@@ -28,129 +17,118 @@ const InputDate = React.forwardRef(
|
|
|
28
17
|
onChange: controlledOnChange,
|
|
29
18
|
inputClassName,
|
|
30
19
|
onClear = true,
|
|
31
|
-
|
|
32
|
-
"aria-invalid": ariaInvalid,
|
|
20
|
+
locale,
|
|
33
21
|
...props
|
|
34
22
|
}, ref) => {
|
|
35
|
-
const [
|
|
23
|
+
const [dateValue, setDateValue] = React.useState(() => controlledValue ?? null);
|
|
36
24
|
const [isHovered, setIsHovered] = React.useState(false);
|
|
25
|
+
const internalChange = React.useRef(false);
|
|
37
26
|
React.useEffect(() => {
|
|
38
|
-
if (
|
|
39
|
-
|
|
27
|
+
if (internalChange.current) {
|
|
28
|
+
internalChange.current = false;
|
|
40
29
|
return;
|
|
41
30
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
if (!controlledOnChange) return;
|
|
49
|
-
if (!newValue.trim()) {
|
|
50
|
-
emit(controlledOnChange, "");
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
const formatConfigs = {
|
|
54
|
-
"DD/MM/YYYY": { regex: /^(\d{2})\/(\d{2})\/(\d{4})$/, d: 1, m: 2, y: 3 },
|
|
55
|
-
"MM/DD/YYYY": { regex: /^(\d{2})\/(\d{2})\/(\d{4})$/, d: 2, m: 1, y: 3 },
|
|
56
|
-
"YYYY/MM/DD": { regex: /^(\d{4})\/(\d{2})\/(\d{2})$/, d: 3, m: 2, y: 1 }
|
|
57
|
-
};
|
|
58
|
-
const config = formatConfigs[inputFormat];
|
|
59
|
-
const match = config.regex.exec(newValue);
|
|
60
|
-
if (match) {
|
|
61
|
-
const year = match[config.y];
|
|
62
|
-
const month = match[config.m];
|
|
63
|
-
const day = match[config.d];
|
|
64
|
-
emit(controlledOnChange, `${year}-${month}-${day}`);
|
|
65
|
-
}
|
|
31
|
+
setDateValue(controlledValue ?? null);
|
|
32
|
+
}, [controlledValue]);
|
|
33
|
+
const handleRacChange = (date) => {
|
|
34
|
+
internalChange.current = true;
|
|
35
|
+
setDateValue(date);
|
|
36
|
+
controlledOnChange?.(date);
|
|
66
37
|
};
|
|
67
38
|
const handleClear = () => {
|
|
68
|
-
|
|
69
|
-
|
|
39
|
+
internalChange.current = true;
|
|
40
|
+
setDateValue(null);
|
|
41
|
+
controlledOnChange?.(null);
|
|
70
42
|
if (typeof onClear === "function") onClear();
|
|
71
43
|
};
|
|
72
|
-
const hasValue =
|
|
44
|
+
const hasValue = dateValue !== null;
|
|
73
45
|
const showClearIcon = Boolean(onClear && hasValue && isHovered && !disabled);
|
|
74
46
|
const resolvedErrorMessage = typeof error === "string" ? error : errorMessage;
|
|
75
47
|
const hasError = Boolean(error ?? resolvedErrorMessage);
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
return /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
|
|
80
|
-
WarningCircle,
|
|
81
|
-
{
|
|
82
|
-
"data-testid": "exclaim-icon",
|
|
83
|
-
className: cn(
|
|
84
|
-
"text-error-500 transition-opacity duration-150",
|
|
85
|
-
showClearIcon ? "opacity-0" : "opacity-100"
|
|
86
|
-
),
|
|
87
|
-
size: 18
|
|
88
|
-
}
|
|
89
|
-
) });
|
|
90
|
-
};
|
|
91
|
-
const renderClearIcon = () => {
|
|
92
|
-
if (disabled || !onClear) return null;
|
|
93
|
-
return /* @__PURE__ */ jsx(
|
|
94
|
-
"div",
|
|
48
|
+
const inner = /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-1", children: [
|
|
49
|
+
/* @__PURE__ */ jsx("div", { className: "flex w-full items-center", children: /* @__PURE__ */ jsx(
|
|
50
|
+
DateField,
|
|
95
51
|
{
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
52
|
+
ref,
|
|
53
|
+
value: dateValue,
|
|
54
|
+
onChange: handleRacChange,
|
|
55
|
+
isDisabled: disabled,
|
|
56
|
+
isInvalid: hasError,
|
|
57
|
+
granularity: "day",
|
|
58
|
+
className: "w-full",
|
|
59
|
+
...props,
|
|
60
|
+
children: /* @__PURE__ */ jsxs(
|
|
61
|
+
Group,
|
|
103
62
|
{
|
|
104
|
-
"data-testid": "
|
|
63
|
+
"data-testid": "input-date-mask-control",
|
|
105
64
|
className: cn(
|
|
106
|
-
"h-
|
|
107
|
-
|
|
65
|
+
"relative flex h-12 w-full items-center rounded-lg border border-neutral-200 bg-white px-3 transition-colors focus-within:border-neutral-950",
|
|
66
|
+
disabled && "bg-neutral-50",
|
|
67
|
+
hasError && "border-error-400 focus-within:border-error-700",
|
|
68
|
+
className
|
|
108
69
|
),
|
|
109
|
-
|
|
70
|
+
onMouseEnter: () => setIsHovered(true),
|
|
71
|
+
onMouseLeave: () => setIsHovered(false),
|
|
72
|
+
children: [
|
|
73
|
+
/* @__PURE__ */ jsx(CalendarBlank, { size: 20 }),
|
|
74
|
+
/* @__PURE__ */ jsx(DateInput, { className: cn("flex flex-1 items-center justify-center px-2", inputClassName), children: (segment) => /* @__PURE__ */ jsx(
|
|
75
|
+
DateSegment,
|
|
76
|
+
{
|
|
77
|
+
segment,
|
|
78
|
+
className: cn(
|
|
79
|
+
segment.type === "literal" ? "select-none text-neutral-400" : cn(
|
|
80
|
+
"min-w-[1ch] rounded-sm bg-transparent px-0.5 py-px text-center outline-0 transition-colors",
|
|
81
|
+
"caret-neutral-900",
|
|
82
|
+
"placeholder:text-neutral-300",
|
|
83
|
+
"data-focused:bg-neutral-100 data-focused:text-neutral-900",
|
|
84
|
+
"data-disabled:cursor-not-allowed data-disabled:opacity-50"
|
|
85
|
+
)
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
) }),
|
|
89
|
+
hasError && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
|
|
90
|
+
WarningCircle,
|
|
91
|
+
{
|
|
92
|
+
"data-testid": "exclaim-icon",
|
|
93
|
+
className: cn(
|
|
94
|
+
"text-error-500 transition-opacity duration-150",
|
|
95
|
+
showClearIcon ? "opacity-0" : "opacity-100"
|
|
96
|
+
),
|
|
97
|
+
size: 18
|
|
98
|
+
}
|
|
99
|
+
) }),
|
|
100
|
+
onClear && !disabled && /* @__PURE__ */ jsx(
|
|
101
|
+
"div",
|
|
102
|
+
{
|
|
103
|
+
className: cn(
|
|
104
|
+
"absolute right-3 z-10 flex h-full w-10 items-center justify-end rounded-r-lg",
|
|
105
|
+
hasError ? "bg-transparent" : "bg-linear-to-l from-white from-60% via-white/80 via-80% to-transparent transition-opacity duration-150",
|
|
106
|
+
showClearIcon ? "opacity-100" : "opacity-0"
|
|
107
|
+
),
|
|
108
|
+
children: /* @__PURE__ */ jsx(
|
|
109
|
+
X,
|
|
110
|
+
{
|
|
111
|
+
"data-testid": "clear-button",
|
|
112
|
+
className: cn(
|
|
113
|
+
"h-4 w-4 shrink-0 cursor-pointer transition-opacity duration-150",
|
|
114
|
+
showClearIcon ? "opacity-100 hover:opacity-70" : "opacity-0"
|
|
115
|
+
),
|
|
116
|
+
onClick: (e) => {
|
|
117
|
+
e.stopPropagation();
|
|
118
|
+
handleClear();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
]
|
|
110
125
|
}
|
|
111
126
|
)
|
|
112
127
|
}
|
|
113
|
-
);
|
|
114
|
-
};
|
|
115
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-1", children: [
|
|
116
|
-
/* @__PURE__ */ jsx("div", { className: "flex w-full items-center", children: /* @__PURE__ */ jsxs(
|
|
117
|
-
"label",
|
|
118
|
-
{
|
|
119
|
-
"data-testid": "input-date-mask-control",
|
|
120
|
-
className: cn(
|
|
121
|
-
"relative flex h-12 w-full items-center rounded-lg border border-neutral-200 bg-white px-3 transition-colors focus-within:border-neutral-950",
|
|
122
|
-
disabled && "bg-neutral-50",
|
|
123
|
-
hasError && "border-error-400 focus-within:border-error-700",
|
|
124
|
-
className
|
|
125
|
-
),
|
|
126
|
-
onMouseEnter: () => setIsHovered(true),
|
|
127
|
-
onMouseLeave: () => setIsHovered(false),
|
|
128
|
-
children: [
|
|
129
|
-
renderCalendarIcon(),
|
|
130
|
-
/* @__PURE__ */ jsx(
|
|
131
|
-
MaskedInput,
|
|
132
|
-
{
|
|
133
|
-
ref,
|
|
134
|
-
inputFormat,
|
|
135
|
-
placeholder: inputFormat,
|
|
136
|
-
"aria-invalid": ariaInvalid ?? hasError,
|
|
137
|
-
disabled,
|
|
138
|
-
value: internalValue,
|
|
139
|
-
onChange: handleMaskedChange,
|
|
140
|
-
className: cn(
|
|
141
|
-
"w-full bg-transparent px-2 outline-0 transition-colors placeholder:text-neutral-300 disabled:cursor-not-allowed disabled:opacity-50",
|
|
142
|
-
inputClassName
|
|
143
|
-
),
|
|
144
|
-
...props
|
|
145
|
-
}
|
|
146
|
-
),
|
|
147
|
-
renderErrorIcon(),
|
|
148
|
-
renderClearIcon()
|
|
149
|
-
]
|
|
150
|
-
}
|
|
151
128
|
) }),
|
|
152
129
|
resolvedErrorMessage && /* @__PURE__ */ jsx("span", { className: "text-error-500 text-sm", children: resolvedErrorMessage })
|
|
153
130
|
] });
|
|
131
|
+
return locale ? /* @__PURE__ */ jsx(I18nProvider, { locale, children: inner }) : inner;
|
|
154
132
|
}
|
|
155
133
|
);
|
|
156
134
|
InputDate.displayName = "InputDate";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InputDate.js","sources":["../../../src/components/InputDate/InputDate.tsx"],"sourcesContent":["import { CalendarBlank } from '@phosphor-icons/react/dist/ssr/CalendarBlank'\nimport { WarningCircle } from '@phosphor-icons/react/dist/ssr/WarningCircle'\nimport { X } from '@phosphor-icons/react/dist/ssr/X'\nimport * as React from 'react'\n\nimport { type DateInputFormat } from './manualDateFormat'\nimport { MaskedInput } from './MaskedInput'\n\nimport { cn } from '@/lib/utils'\n\nexport type InputDateProps = {\n className?: string\n endContent?: React.ReactElement\n disabled?: boolean\n error?: boolean | string\n errorMessage?: string\n inputClassName?: string\n inputFormat?: DateInputFormat\n onClear?: boolean | (() => void)\n value?: string\n onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void\n} & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'value' | 'onChange' | 'type'>\n\nconst emit = (onChange: ((e: React.ChangeEvent<HTMLInputElement>) => void) | undefined, value: string) => {\n onChange?.({ target: { value } } as React.ChangeEvent<HTMLInputElement>)\n}\n\nconst toInternalValue = (external: string, format: DateInputFormat): string => {\n const isoMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(external.trim())\n if (!isoMatch) return external\n\n const [, year, month, day] = isoMatch\n if (format === 'DD/MM/YYYY') return `${day}/${month}/${year}`\n if (format === 'MM/DD/YYYY') return `${month}/${day}/${year}`\n return `${year}/${month}/${day}`\n}\n\nconst InputDate = React.forwardRef<HTMLInputElement, InputDateProps>(\n (\n {\n className,\n endContent,\n disabled,\n error,\n errorMessage,\n value: controlledValue,\n onChange: controlledOnChange,\n inputClassName,\n onClear = true,\n inputFormat = 'DD/MM/YYYY',\n 'aria-invalid': ariaInvalid,\n ...props\n },\n ref,\n ) => {\n const [internalValue, setInternalValue] = React.useState(() => toInternalValue(controlledValue ?? '', inputFormat))\n const [isHovered, setIsHovered] = React.useState(false)\n\n React.useEffect(() => {\n if (!controlledValue) {\n setInternalValue('')\n return\n }\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(controlledValue.trim())) {\n setInternalValue(toInternalValue(controlledValue, inputFormat))\n }\n }, [controlledValue, inputFormat])\n\n const handleMaskedChange = (newValue: string) => {\n setInternalValue(newValue)\n\n if (!controlledOnChange) return\n\n if (!newValue.trim()) {\n emit(controlledOnChange, '')\n return\n }\n\n const formatConfigs: Record<DateInputFormat, { regex: RegExp; d: number; m: number; y: number }> = {\n 'DD/MM/YYYY': { regex: /^(\\d{2})\\/(\\d{2})\\/(\\d{4})$/, d: 1, m: 2, y: 3 },\n 'MM/DD/YYYY': { regex: /^(\\d{2})\\/(\\d{2})\\/(\\d{4})$/, d: 2, m: 1, y: 3 },\n 'YYYY/MM/DD': { regex: /^(\\d{4})\\/(\\d{2})\\/(\\d{2})$/, d: 3, m: 2, y: 1 },\n }\n\n const config = formatConfigs[inputFormat]\n const match = config.regex.exec(newValue)\n\n if (match) {\n const year = match[config.y]\n const month = match[config.m]\n const day = match[config.d]\n\n emit(controlledOnChange, `${year}-${month}-${day}`)\n }\n }\n\n const handleClear = () => {\n setInternalValue('')\n emit(controlledOnChange, '')\n if (typeof onClear === 'function') onClear()\n }\n\n const hasValue = Boolean(internalValue && internalValue.trim() !== '')\n const showClearIcon = Boolean(onClear && hasValue && isHovered && !disabled)\n const resolvedErrorMessage = typeof error === 'string' ? error : errorMessage\n const hasError = Boolean(error ?? resolvedErrorMessage)\n\n const renderCalendarIcon = () => <CalendarBlank size={20} />\n\n const renderErrorIcon = () => {\n if (!hasError) return null\n return (\n <div>\n <WarningCircle\n data-testid=\"exclaim-icon\"\n className={cn(\n 'text-error-500 transition-opacity duration-150',\n showClearIcon ? 'opacity-0' : 'opacity-100',\n )}\n size={18}\n />\n </div>\n )\n }\n\n const renderClearIcon = () => {\n if (disabled || !onClear) return null\n return (\n <div\n className={cn(\n 'absolute right-3 z-10 flex h-full w-10 items-center justify-end rounded-r-lg',\n endContent || error\n ? 'bg-transparent'\n : 'bg-gradient-to-l from-white from-60% via-white/80 via-80% to-transparent transition-opacity duration-150',\n showClearIcon ? 'opacity-100' : 'opacity-0',\n )}\n >\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'h-4 w-4 shrink-0 cursor-pointer transition-opacity duration-150',\n showClearIcon ? 'opacity-100 hover:opacity-70' : 'opacity-0',\n )}\n onClick={handleClear}\n />\n </div>\n )\n }\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <div className=\"flex w-full items-center\">\n <label\n data-testid=\"input-date-mask-control\"\n className={cn(\n 'relative flex h-12 w-full items-center rounded-lg border border-neutral-200 bg-white px-3 transition-colors focus-within:border-neutral-950',\n disabled && 'bg-neutral-50',\n hasError && 'border-error-400 focus-within:border-error-700',\n className,\n )}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n {renderCalendarIcon()}\n <MaskedInput\n ref={ref}\n inputFormat={inputFormat}\n placeholder={inputFormat}\n aria-invalid={ariaInvalid ?? hasError}\n disabled={disabled}\n value={internalValue}\n onChange={handleMaskedChange}\n className={cn(\n 'w-full bg-transparent px-2 outline-0 transition-colors placeholder:text-neutral-300 disabled:cursor-not-allowed disabled:opacity-50',\n inputClassName,\n )}\n {...props}\n />\n {renderErrorIcon()}\n {renderClearIcon()}\n </label>\n </div>\n {resolvedErrorMessage && <span className=\"text-error-500 text-sm\">{resolvedErrorMessage}</span>}\n </div>\n )\n },\n)\n\nInputDate.displayName = 'InputDate'\n\nexport { InputDate }\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InputDate.js","sources":["../../../src/components/InputDate/InputDate.tsx"],"sourcesContent":["import { CalendarBlank } from '@phosphor-icons/react/dist/ssr/CalendarBlank'\nimport { WarningCircle } from '@phosphor-icons/react/dist/ssr/WarningCircle'\nimport { X } from '@phosphor-icons/react/dist/ssr/X'\nimport { I18nProvider } from 'react-aria'\nimport * as React from 'react'\nimport {\n DateField,\n DateInput,\n DateSegment,\n Group,\n type DateValue,\n} from 'react-aria-components'\nimport { cn } from '@/lib/utils'\n\nexport type InputDateProps = {\n className?: string\n disabled?: boolean\n error?: boolean | string\n errorMessage?: string\n inputClassName?: string\n locale?: string\n onClear?: boolean | (() => void)\n value?: DateValue | null\n onChange?: (date: DateValue | null) => void\n} & Omit<React.ComponentPropsWithoutRef<typeof DateField<DateValue>>, 'value' | 'onChange'>\n\nconst InputDate = React.forwardRef<HTMLDivElement, InputDateProps>(\n (\n {\n className,\n disabled,\n error,\n errorMessage,\n value: controlledValue,\n onChange: controlledOnChange,\n inputClassName,\n onClear = true,\n locale,\n ...props\n },\n ref,\n ) => {\n const [dateValue, setDateValue] = React.useState<DateValue | null>(() => controlledValue ?? null)\n const [isHovered, setIsHovered] = React.useState(false)\n const internalChange = React.useRef(false)\n\n React.useEffect(() => {\n if (internalChange.current) {\n internalChange.current = false\n return\n }\n setDateValue(controlledValue ?? null)\n }, [controlledValue])\n\n const handleRacChange = (date: DateValue | null) => {\n internalChange.current = true\n setDateValue(date)\n controlledOnChange?.(date)\n }\n\n const handleClear = () => {\n internalChange.current = true\n setDateValue(null)\n controlledOnChange?.(null)\n if (typeof onClear === 'function') onClear()\n }\n\n const hasValue = dateValue !== null\n const showClearIcon = Boolean(onClear && hasValue && isHovered && !disabled)\n const resolvedErrorMessage = typeof error === 'string' ? error : errorMessage\n const hasError = Boolean(error ?? resolvedErrorMessage)\n\n const inner = (\n <div className=\"flex w-full flex-col gap-1\">\n <div className=\"flex w-full items-center\">\n <DateField\n ref={ref}\n value={dateValue}\n onChange={handleRacChange}\n isDisabled={disabled}\n isInvalid={hasError}\n granularity=\"day\"\n className=\"w-full\"\n {...props}\n >\n <Group\n data-testid=\"input-date-mask-control\"\n className={cn(\n 'relative flex h-12 w-full items-center rounded-lg border border-neutral-200 bg-white px-3 transition-colors focus-within:border-neutral-950',\n disabled && 'bg-neutral-50',\n hasError && 'border-error-400 focus-within:border-error-700',\n className,\n )}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <CalendarBlank size={20} />\n <DateInput className={cn('flex flex-1 items-center justify-center px-2', inputClassName)}>\n {(segment) => (\n <DateSegment\n segment={segment}\n className={cn(\n segment.type === 'literal'\n ? 'select-none text-neutral-400'\n : cn(\n 'min-w-[1ch] rounded-sm bg-transparent px-0.5 py-px text-center outline-0 transition-colors',\n 'caret-neutral-900',\n 'placeholder:text-neutral-300',\n 'data-focused:bg-neutral-100 data-focused:text-neutral-900',\n 'data-disabled:cursor-not-allowed data-disabled:opacity-50',\n ),\n )}\n />\n )}\n </DateInput>\n {hasError && (\n <div>\n <WarningCircle\n data-testid=\"exclaim-icon\"\n className={cn(\n 'text-error-500 transition-opacity duration-150',\n showClearIcon ? 'opacity-0' : 'opacity-100',\n )}\n size={18}\n />\n </div>\n )}\n {onClear && !disabled && (\n <div\n className={cn(\n 'absolute right-3 z-10 flex h-full w-10 items-center justify-end rounded-r-lg',\n hasError\n ? 'bg-transparent'\n : 'bg-linear-to-l from-white from-60% via-white/80 via-80% to-transparent transition-opacity duration-150',\n showClearIcon ? 'opacity-100' : 'opacity-0',\n )}\n >\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'h-4 w-4 shrink-0 cursor-pointer transition-opacity duration-150',\n showClearIcon ? 'opacity-100 hover:opacity-70' : 'opacity-0',\n )}\n onClick={(e) => {\n e.stopPropagation()\n handleClear()\n }}\n />\n </div>\n )}\n </Group>\n </DateField>\n </div>\n {resolvedErrorMessage && <span className=\"text-error-500 text-sm\">{resolvedErrorMessage}</span>}\n </div>\n )\n\n return locale ? <I18nProvider locale={locale}>{inner}</I18nProvider> : inner\n },\n)\n\nInputDate.displayName = 'InputDate'\n\nexport { InputDate }\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "periplo-ui",
|
|
3
3
|
"description": "IATI UI library",
|
|
4
4
|
"private": false,
|
|
5
|
-
"version": "4.
|
|
5
|
+
"version": "4.6.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
@@ -335,6 +335,7 @@
|
|
|
335
335
|
"dist"
|
|
336
336
|
],
|
|
337
337
|
"dependencies": {
|
|
338
|
+
"@internationalized/date": "^3.12.2",
|
|
338
339
|
"@radix-ui/react-accordion": "^1.2.11",
|
|
339
340
|
"@radix-ui/react-avatar": "^1.1.10",
|
|
340
341
|
"@radix-ui/react-checkbox": "^1.3.2",
|
|
@@ -352,14 +353,16 @@
|
|
|
352
353
|
"@radix-ui/react-toggle": "^1.1.9",
|
|
353
354
|
"@radix-ui/react-toggle-group": "^1.1.10",
|
|
354
355
|
"@radix-ui/react-tooltip": "^1.2.7",
|
|
356
|
+
"@tanstack/react-virtual": "^3.13.18",
|
|
355
357
|
"class-variance-authority": "0.7.1",
|
|
356
358
|
"clsx": "2.1.1",
|
|
357
359
|
"cmdk": "^1.1.1",
|
|
358
360
|
"date-fns": "^4.1.0",
|
|
359
361
|
"embla-carousel-react": "^8.6.0",
|
|
362
|
+
"react-aria": "^3.50.0",
|
|
363
|
+
"react-aria-components": "^1.19.0",
|
|
360
364
|
"react-day-picker": "^9.7.0",
|
|
361
365
|
"sonner": "^2.0.5",
|
|
362
|
-
"tailwind-merge": "3.3.1"
|
|
363
|
-
"@tanstack/react-virtual": "^3.13.18"
|
|
366
|
+
"tailwind-merge": "3.3.1"
|
|
364
367
|
}
|
|
365
368
|
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { default as React } from 'react';
|
|
2
|
-
export type DateInputFormat = 'DD/MM/YYYY' | 'MM/DD/YYYY' | 'YYYY/MM/DD';
|
|
3
|
-
type Props = {
|
|
4
|
-
value: string;
|
|
5
|
-
onChange: (value: string) => void;
|
|
6
|
-
onBlur?: React.FocusEventHandler<HTMLInputElement>;
|
|
7
|
-
onFocus?: React.FocusEventHandler<HTMLInputElement>;
|
|
8
|
-
onKeyDown?: React.KeyboardEventHandler<HTMLInputElement>;
|
|
9
|
-
placeholder?: string;
|
|
10
|
-
disabled?: boolean;
|
|
11
|
-
id?: string;
|
|
12
|
-
name?: string;
|
|
13
|
-
className?: string;
|
|
14
|
-
'aria-invalid'?: React.InputHTMLAttributes<HTMLInputElement>['aria-invalid'];
|
|
15
|
-
inputFormat?: DateInputFormat;
|
|
16
|
-
};
|
|
17
|
-
export declare const MaskedInput: React.ForwardRefExoticComponent<Props & React.RefAttributes<HTMLInputElement>>;
|
|
18
|
-
export {};
|