@lerianstudio/sindarian-ui 1.4.0-beta.4 → 1.4.0-beta.6
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/form/date-picker-field/index.d.ts +12 -2
- package/dist/components/form/date-picker-field/index.d.ts.map +1 -1
- package/dist/components/form/date-picker-field/index.js +7 -2
- package/dist/components/form/date-range-field/index.d.ts +12 -2
- package/dist/components/form/date-range-field/index.d.ts.map +1 -1
- package/dist/components/form/date-range-field/index.js +3 -2
- package/dist/components/form/date-time-picker-field/index.d.ts +12 -2
- package/dist/components/form/date-time-picker-field/index.d.ts.map +1 -1
- package/dist/components/form/date-time-picker-field/index.js +3 -2
- package/dist/components/page-header/index.d.ts +13 -0
- package/dist/components/page-header/index.d.ts.map +1 -1
- package/dist/components/page-header/index.js +32 -1
- package/dist/components/ui/calendar/index.d.ts.map +1 -1
- package/dist/components/ui/calendar/index.js +1 -4
- package/dist/enterprise/data-table/index.d.ts +36 -3
- package/dist/enterprise/data-table/index.d.ts.map +1 -1
- package/dist/enterprise/data-table/index.js +34 -3
- package/dist/enterprise/date-range-picker/index.d.ts +19 -1
- package/dist/enterprise/date-range-picker/index.d.ts.map +1 -1
- package/dist/enterprise/date-range-picker/index.js +28 -4
- package/dist/esm/components/form/date-picker-field/index.d.ts +12 -2
- package/dist/esm/components/form/date-picker-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/date-picker-field/index.js +7 -2
- package/dist/esm/components/form/date-range-field/index.d.ts +12 -2
- package/dist/esm/components/form/date-range-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/date-range-field/index.js +3 -2
- package/dist/esm/components/form/date-time-picker-field/index.d.ts +12 -2
- package/dist/esm/components/form/date-time-picker-field/index.d.ts.map +1 -1
- package/dist/esm/components/form/date-time-picker-field/index.js +3 -2
- package/dist/esm/components/page-header/index.d.ts +13 -0
- package/dist/esm/components/page-header/index.d.ts.map +1 -1
- package/dist/esm/components/page-header/index.js +33 -2
- package/dist/esm/components/ui/calendar/index.d.ts.map +1 -1
- package/dist/esm/components/ui/calendar/index.js +1 -4
- package/dist/esm/enterprise/data-table/index.d.ts +36 -3
- package/dist/esm/enterprise/data-table/index.d.ts.map +1 -1
- package/dist/esm/enterprise/data-table/index.js +34 -3
- package/dist/esm/enterprise/date-range-picker/index.d.ts +19 -1
- package/dist/esm/enterprise/date-range-picker/index.d.ts.map +1 -1
- package/dist/esm/enterprise/date-range-picker/index.js +29 -5
- package/package.json +1 -1
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { Calendar } from '../../../components/ui/calendar';
|
|
1
2
|
import * as React from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
3
4
|
import { Control, FieldValues } from 'react-hook-form';
|
|
5
|
+
/**
|
|
6
|
+
* The calendar's locale type, taken straight off the Calendar props so the
|
|
7
|
+
* public signature stays the react-day-picker/date-fns `Locale` without this
|
|
8
|
+
* package taking a direct date-fns dependency.
|
|
9
|
+
*/
|
|
10
|
+
type CalendarLocale = ComponentProps<typeof Calendar>['locale'];
|
|
4
11
|
export type DatePickerFieldProps<T extends FieldValues = FieldValues> = {
|
|
5
12
|
name: string;
|
|
6
13
|
label?: ReactNode;
|
|
@@ -16,6 +23,9 @@ export type DatePickerFieldProps<T extends FieldValues = FieldValues> = {
|
|
|
16
23
|
align?: 'start' | 'center' | 'end';
|
|
17
24
|
'data-testid'?: string;
|
|
18
25
|
valueAsString?: boolean;
|
|
26
|
+
/** date-fns locale for the calendar. Defaults to en-US. */
|
|
27
|
+
locale?: CalendarLocale;
|
|
19
28
|
};
|
|
20
|
-
export declare const DatePickerField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat, align, valueAsString, ...others }: DatePickerFieldProps<T>) => React.JSX.Element;
|
|
29
|
+
export declare const DatePickerField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat, align, valueAsString, locale, ...others }: DatePickerFieldProps<T>) => React.JSX.Element;
|
|
30
|
+
export {};
|
|
21
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/form/date-picker-field/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/form/date-picker-field/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAkBnD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAQ,MAAM,iBAAiB,CAAA;AAE5D;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IACtE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,4JAgBlE,oBAAoB,CAAC,CAAC,CAAC,sBAiGzB,CAAA"}
|
|
@@ -47,7 +47,8 @@ const utils_1 = require("../../../lib/utils");
|
|
|
47
47
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
48
48
|
const lucide_react_1 = require("lucide-react");
|
|
49
49
|
const React = __importStar(require("react"));
|
|
50
|
-
const
|
|
50
|
+
const locale_1 = require("react-day-picker/locale");
|
|
51
|
+
const DatePickerField = ({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat = 'MMM DD, YYYY', align = 'start', valueAsString, locale = locale_1.enUS, ...others }) => {
|
|
51
52
|
const [open, setOpen] = React.useState(false);
|
|
52
53
|
return ((0, jsx_runtime_1.jsx)(form_1.FormField, { name: name, control: control, render: ({ field }) => {
|
|
53
54
|
const convertFieldValueToDate = (fieldValue) => {
|
|
@@ -72,7 +73,11 @@ const DatePickerField = ({ name, label, tooltip, labelExtra, description, placeh
|
|
|
72
73
|
const handleSelect = (date) => {
|
|
73
74
|
field.onChange(convertDateToOutputFormat(date));
|
|
74
75
|
};
|
|
75
|
-
return ((0, jsx_runtime_1.jsxs)(form_1.FormItem, { required: required, children: [label && ((0, jsx_runtime_1.jsx)(form_1.FormLabel, { extra: tooltip ? (0, jsx_runtime_1.jsx)(form_1.FormTooltip, { children: tooltip }) : labelExtra, children: label })), (0, jsx_runtime_1.jsxs)(popover_1.Popover, { open: open, onOpenChange: setOpen, children: [(0, jsx_runtime_1.jsx)(popover_1.PopoverTrigger, { asChild: true, children: (0, jsx_runtime_1.jsx)(form_1.FormControl, { children: (0, jsx_runtime_1.jsx)(button_1.Button, { variant: "outline", disabled: disabled, className: (0, utils_1.cn)('bg-input hover:bg-input border-shadcn-400 text-foreground h-10 w-full justify-start rounded-md px-2.5 font-normal', readOnly && 'pointer-events-none', open && 'ring-ring ring-2 ring-offset-0'), "data-testid": others['data-testid'], icon: (0, jsx_runtime_1.jsx)(lucide_react_1.CalendarIcon, { className: "size-4" }), children: value ? ((0, jsx_runtime_1.jsx)("span", { className: "text-foreground flex-1 text-left font-bold", children: (0, dayjs_1.default)(value).format(dateFormat) })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground flex-1 text-left", children: placeholder })) }) }) }), (0, jsx_runtime_1.jsx)(popover_1.PopoverContent, { className: "w-auto p-0", align: align, children: (0, jsx_runtime_1.jsx)(calendar_1.Calendar, { mode: "single",
|
|
76
|
+
return ((0, jsx_runtime_1.jsxs)(form_1.FormItem, { required: required, children: [label && ((0, jsx_runtime_1.jsx)(form_1.FormLabel, { extra: tooltip ? (0, jsx_runtime_1.jsx)(form_1.FormTooltip, { children: tooltip }) : labelExtra, children: label })), (0, jsx_runtime_1.jsxs)(popover_1.Popover, { open: open, onOpenChange: setOpen, children: [(0, jsx_runtime_1.jsx)(popover_1.PopoverTrigger, { asChild: true, children: (0, jsx_runtime_1.jsx)(form_1.FormControl, { children: (0, jsx_runtime_1.jsx)(button_1.Button, { variant: "outline", disabled: disabled, className: (0, utils_1.cn)('bg-input hover:bg-input border-shadcn-400 text-foreground h-10 w-full justify-start rounded-md px-2.5 font-normal', readOnly && 'pointer-events-none', open && 'ring-ring ring-2 ring-offset-0'), "data-testid": others['data-testid'], icon: (0, jsx_runtime_1.jsx)(lucide_react_1.CalendarIcon, { className: "size-4" }), children: value ? ((0, jsx_runtime_1.jsx)("span", { className: "text-foreground flex-1 text-left font-bold", children: (0, dayjs_1.default)(value).format(dateFormat) })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground flex-1 text-left", children: placeholder })) }) }) }), (0, jsx_runtime_1.jsx)(popover_1.PopoverContent, { className: "w-auto p-0", align: align, children: (0, jsx_runtime_1.jsx)(calendar_1.Calendar, { mode: "single",
|
|
77
|
+
// `required` mirrors the field's own required: a required
|
|
78
|
+
// field is not emptied by a re-click; an optional one keeps
|
|
79
|
+
// react-day-picker's clear gesture.
|
|
80
|
+
required: required, defaultMonth: value, selected: value, onSelect: handleSelect, disabled: disabled || readOnly, locale: locale }) })] }), (0, jsx_runtime_1.jsx)(form_1.FormMessage, {}), description && (0, jsx_runtime_1.jsx)(form_1.FormDescription, { children: description })] }));
|
|
76
81
|
} }));
|
|
77
82
|
};
|
|
78
83
|
exports.DatePickerField = DatePickerField;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { Calendar } from '../../../components/ui/calendar';
|
|
1
2
|
import * as React from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
+
import { type ComponentProps, ReactNode } from 'react';
|
|
3
4
|
import { Control, FieldValues } from 'react-hook-form';
|
|
5
|
+
/**
|
|
6
|
+
* The calendar's locale type, taken straight off the Calendar props so the
|
|
7
|
+
* public signature stays the react-day-picker/date-fns `Locale` without this
|
|
8
|
+
* package taking a direct date-fns dependency.
|
|
9
|
+
*/
|
|
10
|
+
type CalendarLocale = ComponentProps<typeof Calendar>['locale'];
|
|
4
11
|
export type DateRangeFieldProps<T extends FieldValues = FieldValues> = {
|
|
5
12
|
name: string;
|
|
6
13
|
label?: ReactNode;
|
|
@@ -15,7 +22,10 @@ export type DateRangeFieldProps<T extends FieldValues = FieldValues> = {
|
|
|
15
22
|
numberOfMonths?: number;
|
|
16
23
|
dateFormat?: string;
|
|
17
24
|
align?: 'start' | 'center' | 'end';
|
|
25
|
+
/** date-fns locale for the calendar. Defaults to en-US. */
|
|
26
|
+
locale?: CalendarLocale;
|
|
18
27
|
'data-testid'?: string;
|
|
19
28
|
};
|
|
20
|
-
export declare const DateRangeField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, numberOfMonths, dateFormat, align, ...others }: DateRangeFieldProps<T>) => React.JSX.Element;
|
|
29
|
+
export declare const DateRangeField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, numberOfMonths, dateFormat, align, locale, ...others }: DateRangeFieldProps<T>) => React.JSX.Element;
|
|
30
|
+
export {};
|
|
21
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/form/date-range-field/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/form/date-range-field/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAkBnD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,KAAK,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAQ,MAAM,iBAAiB,CAAA;AAE5D;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IACrE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,6JAgBjE,mBAAmB,CAAC,CAAC,CAAC,sBA2ExB,CAAA"}
|
|
@@ -47,11 +47,12 @@ const utils_1 = require("../../../lib/utils");
|
|
|
47
47
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
48
48
|
const lucide_react_1 = require("lucide-react");
|
|
49
49
|
const React = __importStar(require("react"));
|
|
50
|
-
const
|
|
50
|
+
const locale_1 = require("react-day-picker/locale");
|
|
51
|
+
const DateRangeField = ({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, numberOfMonths = 2, dateFormat = 'MMM DD, YYYY', align = 'start', locale = locale_1.enUS, ...others }) => {
|
|
51
52
|
const [open, setOpen] = React.useState(false);
|
|
52
53
|
return ((0, jsx_runtime_1.jsx)(form_1.FormField, { name: name, control: control, render: ({ field }) => {
|
|
53
54
|
const value = field.value;
|
|
54
|
-
return ((0, jsx_runtime_1.jsxs)(form_1.FormItem, { required: required, children: [label && ((0, jsx_runtime_1.jsx)(form_1.FormLabel, { extra: tooltip ? (0, jsx_runtime_1.jsx)(form_1.FormTooltip, { children: tooltip }) : labelExtra, children: label })), (0, jsx_runtime_1.jsxs)(popover_1.Popover, { open: open, onOpenChange: setOpen, children: [(0, jsx_runtime_1.jsx)(popover_1.PopoverTrigger, { asChild: true, children: (0, jsx_runtime_1.jsx)(form_1.FormControl, { children: (0, jsx_runtime_1.jsx)(button_1.Button, { variant: "outline", disabled: disabled, className: (0, utils_1.cn)('bg-input hover:bg-input border-shadcn-400 text-foreground h-10 w-full justify-start rounded-md px-2.5 font-normal', readOnly && 'pointer-events-none', open && 'ring-ring ring-2 ring-offset-0'), "data-testid": others['data-testid'], icon: (0, jsx_runtime_1.jsx)(lucide_react_1.CalendarIcon, { className: "size-4" }), children: value?.from ? ((0, jsx_runtime_1.jsx)("span", { className: "text-foreground flex-1 text-left font-bold", children: value.to ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, dayjs_1.default)(value.from).format(dateFormat), " -", ' ', (0, dayjs_1.default)(value.to).format(dateFormat)] })) : ((0, dayjs_1.default)(value.from).format(dateFormat)) })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground flex-1 text-left", children: placeholder })) }) }) }), (0, jsx_runtime_1.jsx)(popover_1.PopoverContent, { className: "w-auto p-0", align: align, children: (0, jsx_runtime_1.jsx)(calendar_1.Calendar, { mode: "range", defaultMonth: value?.from, selected: value, onSelect: field.onChange, numberOfMonths: numberOfMonths, disabled: disabled || readOnly }) })] }), (0, jsx_runtime_1.jsx)(form_1.FormMessage, {}), description && (0, jsx_runtime_1.jsx)(form_1.FormDescription, { children: description })] }));
|
|
55
|
+
return ((0, jsx_runtime_1.jsxs)(form_1.FormItem, { required: required, children: [label && ((0, jsx_runtime_1.jsx)(form_1.FormLabel, { extra: tooltip ? (0, jsx_runtime_1.jsx)(form_1.FormTooltip, { children: tooltip }) : labelExtra, children: label })), (0, jsx_runtime_1.jsxs)(popover_1.Popover, { open: open, onOpenChange: setOpen, children: [(0, jsx_runtime_1.jsx)(popover_1.PopoverTrigger, { asChild: true, children: (0, jsx_runtime_1.jsx)(form_1.FormControl, { children: (0, jsx_runtime_1.jsx)(button_1.Button, { variant: "outline", disabled: disabled, className: (0, utils_1.cn)('bg-input hover:bg-input border-shadcn-400 text-foreground h-10 w-full justify-start rounded-md px-2.5 font-normal', readOnly && 'pointer-events-none', open && 'ring-ring ring-2 ring-offset-0'), "data-testid": others['data-testid'], icon: (0, jsx_runtime_1.jsx)(lucide_react_1.CalendarIcon, { className: "size-4" }), children: value?.from ? ((0, jsx_runtime_1.jsx)("span", { className: "text-foreground flex-1 text-left font-bold", children: value.to ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, dayjs_1.default)(value.from).format(dateFormat), " -", ' ', (0, dayjs_1.default)(value.to).format(dateFormat)] })) : ((0, dayjs_1.default)(value.from).format(dateFormat)) })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground flex-1 text-left", children: placeholder })) }) }) }), (0, jsx_runtime_1.jsx)(popover_1.PopoverContent, { className: "w-auto p-0", align: align, children: (0, jsx_runtime_1.jsx)(calendar_1.Calendar, { mode: "range", defaultMonth: value?.from, selected: value, onSelect: field.onChange, numberOfMonths: numberOfMonths, disabled: disabled || readOnly, locale: locale }) })] }), (0, jsx_runtime_1.jsx)(form_1.FormMessage, {}), description && (0, jsx_runtime_1.jsx)(form_1.FormDescription, { children: description })] }));
|
|
55
56
|
} }));
|
|
56
57
|
};
|
|
57
58
|
exports.DateRangeField = DateRangeField;
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { Calendar } from '../../../components/ui/calendar';
|
|
1
2
|
import * as React from 'react';
|
|
2
|
-
import { type ReactNode } from 'react';
|
|
3
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
3
4
|
import { Control, FieldValues } from 'react-hook-form';
|
|
5
|
+
/**
|
|
6
|
+
* The calendar's locale type, taken straight off the Calendar props so the
|
|
7
|
+
* public signature stays the react-day-picker/date-fns `Locale` without this
|
|
8
|
+
* package taking a direct date-fns dependency.
|
|
9
|
+
*/
|
|
10
|
+
type CalendarLocale = ComponentProps<typeof Calendar>['locale'];
|
|
4
11
|
export type DateTimePickerFieldProps<T extends FieldValues = FieldValues> = {
|
|
5
12
|
name: string;
|
|
6
13
|
label?: ReactNode;
|
|
@@ -14,10 +21,13 @@ export type DateTimePickerFieldProps<T extends FieldValues = FieldValues> = {
|
|
|
14
21
|
required?: boolean;
|
|
15
22
|
dateFormat?: string;
|
|
16
23
|
align?: 'start' | 'center' | 'end';
|
|
24
|
+
/** date-fns locale for the calendar. Defaults to en-US. */
|
|
25
|
+
locale?: CalendarLocale;
|
|
17
26
|
'data-testid'?: string;
|
|
18
27
|
minDate?: Date;
|
|
19
28
|
maxDate?: Date;
|
|
20
29
|
defaultTime?: string;
|
|
21
30
|
};
|
|
22
|
-
export declare const DateTimePickerField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat, align, minDate, maxDate, defaultTime, ...others }: DateTimePickerFieldProps<T>) => React.JSX.Element;
|
|
31
|
+
export declare const DateTimePickerField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat, align, locale, minDate, maxDate, defaultTime, ...others }: DateTimePickerFieldProps<T>) => React.JSX.Element;
|
|
32
|
+
export {};
|
|
23
33
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/form/date-time-picker-field/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/form/date-time-picker-field/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAmBnD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAQ,MAAM,iBAAiB,CAAA;AAE5D;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IAC1E,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,4KAkBtE,wBAAwB,CAAC,CAAC,CAAC,sBAiK7B,CAAA"}
|
|
@@ -48,7 +48,8 @@ const utils_1 = require("../../../lib/utils");
|
|
|
48
48
|
const dayjs_1 = __importDefault(require("dayjs"));
|
|
49
49
|
const lucide_react_1 = require("lucide-react");
|
|
50
50
|
const React = __importStar(require("react"));
|
|
51
|
-
const
|
|
51
|
+
const locale_1 = require("react-day-picker/locale");
|
|
52
|
+
const DateTimePickerField = ({ name, label, tooltip, labelExtra, description, placeholder = 'Select date and time...', disabled, readOnly, control, required, dateFormat = 'MMM DD, YYYY HH:mm', align = 'start', locale = locale_1.enUS, minDate, maxDate, defaultTime = '00:00', ...others }) => {
|
|
52
53
|
const [open, setOpen] = React.useState(false);
|
|
53
54
|
const parseDefaultTime = (time) => {
|
|
54
55
|
const [h, m] = time.split(':').map(Number);
|
|
@@ -97,7 +98,7 @@ const DateTimePickerField = ({ name, label, tooltip, labelExtra, description, pl
|
|
|
97
98
|
e.preventDefault();
|
|
98
99
|
handleClear(e);
|
|
99
100
|
}
|
|
100
|
-
}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.XIcon, { className: "size-4" }) }))] }), (0, jsx_runtime_1.jsx)(popover_1.PopoverContent, { className: "w-auto p-0", align: align, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col sm:flex-row sm:items-stretch", children: [(0, jsx_runtime_1.jsx)(calendar_1.Calendar, { mode: "single", defaultMonth: validCurrent ? validCurrent.toDate() : undefined, selected: validCurrent ? validCurrent.toDate() : undefined, onSelect: handleDateSelect, disabled: (date) => {
|
|
101
|
+
}, children: (0, jsx_runtime_1.jsx)(lucide_react_1.XIcon, { className: "size-4" }) }))] }), (0, jsx_runtime_1.jsx)(popover_1.PopoverContent, { className: "w-auto p-0", align: align, children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col sm:flex-row sm:items-stretch", children: [(0, jsx_runtime_1.jsx)(calendar_1.Calendar, { mode: "single", defaultMonth: validCurrent ? validCurrent.toDate() : undefined, selected: validCurrent ? validCurrent.toDate() : undefined, onSelect: handleDateSelect, locale: locale, disabled: (date) => {
|
|
101
102
|
if (disabled || readOnly)
|
|
102
103
|
return true;
|
|
103
104
|
if (minDate &&
|
|
@@ -27,8 +27,21 @@ export type PageHeaderInfoTitleProps = {
|
|
|
27
27
|
/**
|
|
28
28
|
* Seam for the wrapper element's own margins. Merged AFTER the hard-coded
|
|
29
29
|
* `mb-12` so a consumer utility (e.g. `mb-0`) wins via tailwind-merge.
|
|
30
|
+
*
|
|
31
|
+
* It is also the way back to the old shrink-to-zero title box:
|
|
32
|
+
* `containerClassName="min-w-0"` simply lands, because the base string
|
|
33
|
+
* declares no `min-w-*` for tailwind-merge to weigh it against. Pass it only
|
|
34
|
+
* if a title box that a wide action slot can squeeze past its longest word
|
|
35
|
+
* is what the surface actually wants.
|
|
30
36
|
*/
|
|
31
37
|
containerClassName?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Rendered as their own row under the subtitle, wrapping, so a long identity
|
|
40
|
+
* tape never competes with the subtitle for the same line. This is the slot
|
|
41
|
+
* for things that IDENTIFY the record (short id, status, severity, counts),
|
|
42
|
+
* not for controls: buttons belong in the header's action slot, where the
|
|
43
|
+
* wrapper's `justify-between` keeps them right-aligned.
|
|
44
|
+
*/
|
|
32
45
|
children?: ReactNode;
|
|
33
46
|
};
|
|
34
47
|
export declare function PageHeaderInfoTitle({ title, subtitle, className, containerClassName, children, as: Heading }: PageHeaderInfoTitleProps): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/page-header/index.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/page-header/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAA2B,SAAS,EAAwB,MAAM,OAAO,CAAA;AAmBhF,wBAAgB,uBAAuB,CAAC,EACtC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAQ7B;AAED,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAc7B;AAED,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,SAAS,CAAA;IACnB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,aAAa,EACd,EAAE,eAAe,+BAmBjB;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IAC5C;;;;;;;;;OASG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB,CAAA;AAED,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,QAAQ,EACR,SAAS,EACT,kBAAkB,EAClB,QAAQ,EACR,EAAE,EAAE,OAAc,EACnB,EAAE,wBAAwB,+BA2D1B;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACT,EAAE,0BAA0B,+BAqC5B;AAED,MAAM,MAAM,qCAAqC,GAAG;IAClD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,wBAAgB,gCAAgC,CAAC,EAC/C,QAAQ,EACT,EAAE,qCAAqC,+BAavC;AAED,MAAM,MAAM,8BAA8B,GAAG;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,MAAM,EACN,OAAO,EACP,IAAI,EACL,EAAE,8BAA8B,+BA+ChC"}
|
|
@@ -29,7 +29,38 @@ function PageHeader({ children, className, rootClassName }) {
|
|
|
29
29
|
return ((0, jsx_runtime_1.jsx)(PageHeaderContext.Provider, { value: { isOpen }, children: (0, jsx_runtime_1.jsx)("div", { "data-slot": "page-header", className: (0, utils_1.cn)('mt-12', isOpen && 'mb-12', rootClassName), children: (0, jsx_runtime_1.jsx)(collapsible_1.Collapsible, { open: isOpen, onOpenChange: setIsOpen, className: className, children: children }) }) }));
|
|
30
30
|
}
|
|
31
31
|
function PageHeaderInfoTitle({ title, subtitle, className, containerClassName, children, as: Heading = 'h1' }) {
|
|
32
|
-
return ((0, jsx_runtime_1.jsxs)("div", { "data-slot": "page-header-info-title",
|
|
32
|
+
return ((0, jsx_runtime_1.jsxs)("div", { "data-slot": "page-header-info-title",
|
|
33
|
+
/*
|
|
34
|
+
Two utilities and one deliberate absence.
|
|
35
|
+
|
|
36
|
+
`flex-1` (basis 0) is #170: flex shrinking is shared in proportion to
|
|
37
|
+
flex-basis, so a title box at basis auto (its max-content width, which
|
|
38
|
+
a long subtitle inflates) absorbed almost none of the overflow and
|
|
39
|
+
starved the action row into one button per line. At basis 0 the line's
|
|
40
|
+
hypothetical size is the action row alone, so the row keeps its natural
|
|
41
|
+
width and the title grows into what is left, wrapping at spaces.
|
|
42
|
+
|
|
43
|
+
NO `min-w-0` is #174, and the absence is the fix. A flex item's
|
|
44
|
+
automatic minimum size is its own min-content, so left alone the box
|
|
45
|
+
cannot be squeezed below its longest word (of the title, the subtitle,
|
|
46
|
+
or a child chip) and nothing can overflow horizontally at any width.
|
|
47
|
+
beta.5 carried `min-w-0`, which waives that minimum: on Matcher's
|
|
48
|
+
exception-detail masthead the box collapsed to 68px and the `h1`
|
|
49
|
+
painted straight out of it and across the action row. That is gone.
|
|
50
|
+
|
|
51
|
+
A fixed floor was the other candidate and is wrong: any `sm:` gate keys
|
|
52
|
+
on the VIEWPORT while the overflow condition is the MASTHEAD width, so
|
|
53
|
+
a 1024px viewport with a 320px side panel open (a ~332px masthead)
|
|
54
|
+
would keep a 320px floor and scroll the body sideways.
|
|
55
|
+
|
|
56
|
+
The measured trade: on a masthead carrying a 520px action row the title
|
|
57
|
+
box shrinks to its longest word and the subtitle wraps to about three
|
|
58
|
+
lines. The remedy there is fewer controls in the action slot, not a
|
|
59
|
+
wider floor. A consumer that wants the collapse back passes
|
|
60
|
+
`containerClassName="min-w-0"`. jsdom does not lay out, so the geometry
|
|
61
|
+
is verified downstream.
|
|
62
|
+
*/
|
|
63
|
+
className: (0, utils_1.cn)('mb-12 flex flex-1 flex-col gap-4', containerClassName), children: [(0, jsx_runtime_1.jsx)(Heading, { className: (0, utils_1.cn)('text-foreground text-4xl font-bold', className), "data-testid": "title", children: title }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center gap-2", children: (0, jsx_runtime_1.jsx)("p", { className: "text-muted-foreground text-sm font-medium", children: subtitle }) }), react_1.Children.toArray(children).length > 0 ? ((0, jsx_runtime_1.jsx)("div", { className: "flex flex-wrap items-center gap-2", children: children })) : null] }));
|
|
33
64
|
}
|
|
34
65
|
function PageHeaderInfoTooltip({ subtitle }) {
|
|
35
66
|
const { toast } = (0, use_toast_1.useToast)();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/calendar/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EACL,SAAS,EAET,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,MAAM,EAAkB,MAAM,wBAAwB,CAAA;AAO/D,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,UAAU,EACV,eAAsB,EACtB,aAAuB,EACvB,aAAuB,EACvB,UAAU,EACV,UAAU,EACV,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,GAAG;IAC1C,aAAa,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAA;CAC/D,qBA0JA;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,EACH,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/calendar/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EACL,SAAS,EAET,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,MAAM,EAAkB,MAAM,wBAAwB,CAAA;AAO/D,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,UAAU,EACV,eAAsB,EACtB,aAAuB,EACvB,aAAuB,EACvB,UAAU,EACV,UAAU,EACV,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,GAAG;IAC1C,aAAa,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAA;CAC/D,qBA0JA;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,EACH,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,qBAqCxC;AAED,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAA"}
|
|
@@ -105,11 +105,8 @@ function CalendarDayButton({ className, day, modifiers, ...props }) {
|
|
|
105
105
|
if (modifiers.focused)
|
|
106
106
|
ref.current?.focus();
|
|
107
107
|
}, [modifiers.focused]);
|
|
108
|
-
const dayNumber = day.date.getDate();
|
|
109
|
-
const monthName = day.date.toLocaleDateString('en', { month: 'long' });
|
|
110
|
-
const year = day.date.getFullYear();
|
|
111
108
|
return ((0, jsx_runtime_1.jsx)(button_1.Button, { ref: ref, variant: "plain", size: "small", "data-day": day.date.toLocaleDateString(), "data-selected-single": modifiers.selected &&
|
|
112
109
|
!modifiers.range_start &&
|
|
113
110
|
!modifiers.range_end &&
|
|
114
|
-
!modifiers.range_middle, "data-range-start": modifiers.range_start, "data-range-end": modifiers.range_end, "data-range-middle": modifiers.range_middle, "data-today": modifiers.today && !modifiers.range_middle, "aria-
|
|
111
|
+
!modifiers.range_middle, "data-range-start": modifiers.range_start, "data-range-end": modifiers.range_end, "data-range-middle": modifiers.range_middle, "data-today": modifiers.today && !modifiers.range_middle, "aria-current": modifiers.today ? 'date' : undefined, className: (0, utils_1.cn)('data-[today=true]:bg-accent data-[today=true]:text-accent-foreground data-[selected-single=true]:bg-accent data-[selected-single=true]:text-accent-foreground data-[range-middle=true]:bg-accent-mute data-[range-middle=true]:text-foreground data-[range-start=true]:bg-accent data-[range-start=true]:text-accent-foreground data-[range-end=true]:bg-accent data-[range-end=true]:text-accent-foreground focus-visible:border-accent focus-visible:ring-accent/50 relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal focus-visible:ring-[3px] focus-visible:outline-none data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-end=true]:font-bold data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) data-[range-start=true]:font-bold data-[selected-single=true]:font-bold data-[today=true]:font-bold [&>span]:text-xs [&>span]:opacity-70', defaultClassNames.day, className), ...props }));
|
|
115
112
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ColumnDef, type OnChangeFn, type RowData, type RowSelectionState } from '@tanstack/react-table';
|
|
1
|
+
import { type ColumnDef, type OnChangeFn, type RowData, type RowSelectionState, type SortingState } from '@tanstack/react-table';
|
|
2
2
|
import { type EmptyStateProps } from '../empty-state';
|
|
3
3
|
/**
|
|
4
4
|
* Per-column opt-in for ledger numeric alignment. Set `meta: { numeric: true }`
|
|
@@ -38,6 +38,39 @@ type RowSelectionProps<TData> = {
|
|
|
38
38
|
*/
|
|
39
39
|
getRowSelectionLabel?: (row: TData) => string;
|
|
40
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Sorting is CONTROLLED-ONLY and OPT-IN, mirroring the row-selection contract
|
|
43
|
+
* above: the table sets `manualSorting` and adds no sorted row model, so it
|
|
44
|
+
* never reorders rows. The consumer owns the order (it usually comes back
|
|
45
|
+
* sorted from the server); what the table owns is announcing the state in the
|
|
46
|
+
* one place ARIA defines for it, `aria-sort` on the `th`. Header content is
|
|
47
|
+
* typically a `<button>`, and `aria-sort` is not allowed on a button, so a
|
|
48
|
+
* consumer cannot put it there without failing axe `aria-allowed-attr`.
|
|
49
|
+
*
|
|
50
|
+
* GOTCHA, TanStack's own rule, not a new one: `getCanSort()` is
|
|
51
|
+
* `(columnDef.enableSorting ?? true) && (options.enableSorting ?? true) &&
|
|
52
|
+
* !!column.accessorFn`. A display column (an `id` plus a `cell`, no
|
|
53
|
+
* `accessorKey` or `accessorFn`) has no accessor, so it can never sort and
|
|
54
|
+
* gets no `aria-sort`. That is right for an actions column and surprising for
|
|
55
|
+
* a computed column: give a column you want announced an accessor, and give a
|
|
56
|
+
* column you want excluded `enableSorting: false`.
|
|
57
|
+
*/
|
|
58
|
+
type SortingProps = {
|
|
59
|
+
enableSorting?: false;
|
|
60
|
+
sorting?: never;
|
|
61
|
+
onSortingChange?: never;
|
|
62
|
+
} | {
|
|
63
|
+
enableSorting: true;
|
|
64
|
+
/**
|
|
65
|
+
* Controlled sort state (TanStack `SortingState`). Single-entry:
|
|
66
|
+
* `aria-sort` is defined for one sorted header at a time, so a
|
|
67
|
+
* multi-entry `SortingState` is the consumer's responsibility and yields
|
|
68
|
+
* several non-`none` values.
|
|
69
|
+
*/
|
|
70
|
+
sorting: SortingState;
|
|
71
|
+
/** Controlled sort updater (TanStack `OnChangeFn`). */
|
|
72
|
+
onSortingChange: OnChangeFn<SortingState>;
|
|
73
|
+
};
|
|
41
74
|
type DataTableBaseProps<TData> = {
|
|
42
75
|
columns: ColumnDef<TData, unknown>[];
|
|
43
76
|
data: TData[];
|
|
@@ -94,7 +127,7 @@ type DataTableBaseProps<TData> = {
|
|
|
94
127
|
*/
|
|
95
128
|
footer?: React.ReactNode;
|
|
96
129
|
};
|
|
97
|
-
export type DataTableProps<TData> = DataTableBaseProps<TData> & RowSelectionProps<TData
|
|
98
|
-
export declare function DataTable<TData>({ columns, data, loading, skeletonRows, loadingLabel, empty, getRowId, flush, density, enableRowSelection, rowSelection, onRowSelectionChange, getRowSelectionLabel, onRowActivate, rowHref, className, headClassName, footer }: DataTableProps<TData>): import("react").JSX.Element;
|
|
130
|
+
export type DataTableProps<TData> = DataTableBaseProps<TData> & RowSelectionProps<TData> & SortingProps;
|
|
131
|
+
export declare function DataTable<TData>({ columns, data, loading, skeletonRows, loadingLabel, empty, getRowId, flush, density, enableRowSelection, rowSelection, onRowSelectionChange, getRowSelectionLabel, enableSorting, sorting, onSortingChange, onRowActivate, rowHref, className, headClassName, footer }: DataTableProps<TData>): import("react").JSX.Element;
|
|
99
132
|
export {};
|
|
100
133
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enterprise/data-table/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enterprise/data-table/index.tsx"],"names":[],"mappings":"AAuDA,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,UAAU,EAEf,KAAK,OAAO,EACZ,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAElB,MAAM,uBAAuB,CAAA;AAc9B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAGjE;;;;GAIG;AACH,OAAO,QAAQ,uBAAuB,CAAC;IAIrC,UAAU,UAAU,CAAC,KAAK,SAAS,OAAO,EAAE,MAAM;QAChD,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB;CACF;AAED;;;;;;;;GAQG;AACH,KAAK,iBAAiB,CAAC,KAAK,IACxB;IACE,kBAAkB,CAAC,EAAE,KAAK,CAAA;IAC1B,YAAY,CAAC,EAAE,KAAK,CAAA;IACpB,oBAAoB,CAAC,EAAE,KAAK,CAAA;IAC5B,oBAAoB,CAAC,EAAE,KAAK,CAAA;CAC7B,GACD;IACE,kBAAkB,EAAE,IAAI,CAAA;IACxB,kFAAkF;IAClF,YAAY,EAAE,iBAAiB,CAAA;IAC/B,4DAA4D;IAC5D,oBAAoB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACnD;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAA;CAC9C,CAAA;AAEL;;;;;;;;;;;;;;;;GAgBG;AACH,KAAK,YAAY,GACb;IACE,aAAa,CAAC,EAAE,KAAK,CAAA;IACrB,OAAO,CAAC,EAAE,KAAK,CAAA;IACf,eAAe,CAAC,EAAE,KAAK,CAAA;CACxB,GACD;IACE,aAAa,EAAE,IAAI,CAAA;IACnB;;;;;OAKG;IACH,OAAO,EAAE,YAAY,CAAA;IACrB,uDAAuD;IACvD,eAAe,EAAE,UAAU,CAAC,YAAY,CAAC,CAAA;CAC1C,CAAA;AAEL,KAAK,kBAAkB,CAAC,KAAK,IAAI;IAC/B,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAA;IACpC,IAAI,EAAE,KAAK,EAAE,CAAA;IACb,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAChD;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAA;IACnC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IACpC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,KAAK,IAAI,kBAAkB,CAAC,KAAK,CAAC,GAC3D,iBAAiB,CAAC,KAAK,CAAC,GACxB,YAAY,CAAA;AA8Fd,wBAAgB,SAAS,CAAC,KAAK,EAAE,EAC/B,OAAO,EACP,IAAI,EACJ,OAAe,EACf,YAAgB,EAChB,YAAmC,EACnC,KAAK,EACL,QAAQ,EACR,KAAa,EACb,OAAuB,EACvB,kBAA0B,EAC1B,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,aAAqB,EACrB,OAAO,EACP,eAAe,EACf,aAAa,EACb,OAAO,EACP,SAAS,EACT,aAAa,EACb,MAAM,EACP,EAAE,cAAc,CAAC,KAAK,CAAC,+BAyTvB"}
|
|
@@ -38,6 +38,11 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
38
38
|
* page (indeterminate for partial), checkbox-cell clicks never bubble to
|
|
39
39
|
* row-level handlers. With the flag off (the default), nothing changes.
|
|
40
40
|
*
|
|
41
|
+
* Sorting is opt-in and controlled too: pass `enableSorting` plus `sorting` /
|
|
42
|
+
* `onSortingChange`. Rows are never reordered client-side (`manualSorting`, no
|
|
43
|
+
* sorted row model); what the flag buys is `aria-sort` on each sortable `th`.
|
|
44
|
+
* With the flag off (the default), no header carries the attribute.
|
|
45
|
+
*
|
|
41
46
|
* Keyboard navigation is opt-in via `onRowActivate`: when present, rows get
|
|
42
47
|
* a roving tabindex (Tab enters the table once at the anchor row; the next
|
|
43
48
|
* Tab moves to the row's first tabbable child if it has one, otherwise out
|
|
@@ -77,6 +82,22 @@ const ROW_FOCUS_CLASS = 'focus-visible:outline focus-visible:outline-2 focus-vis
|
|
|
77
82
|
function stopPropagation(event) {
|
|
78
83
|
event.stopPropagation();
|
|
79
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* ARIA sort state for one header cell. `undefined` (attribute omitted) on a
|
|
87
|
+
* column that cannot sort, which covers both sorting-off tables and columns
|
|
88
|
+
* that opted out, so the attribute never claims a control the user does not
|
|
89
|
+
* have.
|
|
90
|
+
*/
|
|
91
|
+
function ariaSortFor(column) {
|
|
92
|
+
if (!column.getCanSort())
|
|
93
|
+
return undefined;
|
|
94
|
+
const sorted = column.getIsSorted();
|
|
95
|
+
if (sorted === 'asc')
|
|
96
|
+
return 'ascending';
|
|
97
|
+
if (sorted === 'desc')
|
|
98
|
+
return 'descending';
|
|
99
|
+
return 'none';
|
|
100
|
+
}
|
|
80
101
|
function SelectAllCheckbox({ table }) {
|
|
81
102
|
const allSelected = table.getIsAllPageRowsSelected();
|
|
82
103
|
const someSelected = table.getIsSomePageRowsSelected();
|
|
@@ -95,7 +116,7 @@ function createSelectionColumn(getLabel) {
|
|
|
95
116
|
cell: ({ row }) => (0, jsx_runtime_1.jsx)(RowSelectionCheckbox, { row: row, getLabel: getLabel })
|
|
96
117
|
};
|
|
97
118
|
}
|
|
98
|
-
function DataTable({ columns, data, loading = false, skeletonRows = 8, loadingLabel = 'Loading table rows', empty, getRowId, flush = false, density = 'comfortable', enableRowSelection = false, rowSelection, onRowSelectionChange, getRowSelectionLabel, onRowActivate, rowHref, className, headClassName, footer }) {
|
|
119
|
+
function DataTable({ columns, data, loading = false, skeletonRows = 8, loadingLabel = 'Loading table rows', empty, getRowId, flush = false, density = 'comfortable', enableRowSelection = false, rowSelection, onRowSelectionChange, getRowSelectionLabel, enableSorting = false, sorting, onSortingChange, onRowActivate, rowHref, className, headClassName, footer }) {
|
|
99
120
|
const tableColumns = (0, react_1.useMemo)(() => enableRowSelection
|
|
100
121
|
? [createSelectionColumn(getRowSelectionLabel), ...columns]
|
|
101
122
|
: columns, [columns, enableRowSelection, getRowSelectionLabel]);
|
|
@@ -114,8 +135,16 @@ function DataTable({ columns, data, loading = false, skeletonRows = 8, loadingLa
|
|
|
114
135
|
// types make the TS path require the controlled pair whenever selection is
|
|
115
136
|
// enabled, so the dead-checkbox configuration is now unrepresentable.
|
|
116
137
|
onRowSelectionChange: enableRowSelection ? onRowSelectionChange : undefined,
|
|
138
|
+
// Controlled-only as well, and deliberately without `getSortedRowModel`:
|
|
139
|
+
// `manualSorting` tells TanStack the rows arrive in the order the consumer
|
|
140
|
+
// already chose, so enabling sorting changes what the header ANNOUNCES,
|
|
141
|
+
// never what the body shows.
|
|
142
|
+
manualSorting: true,
|
|
143
|
+
enableSorting,
|
|
144
|
+
onSortingChange: enableSorting ? onSortingChange : undefined,
|
|
117
145
|
state: {
|
|
118
|
-
rowSelection: enableRowSelection ? (rowSelection ?? {}) : undefined
|
|
146
|
+
rowSelection: enableRowSelection ? (rowSelection ?? {}) : undefined,
|
|
147
|
+
sorting: enableSorting ? (sorting ?? []) : undefined
|
|
119
148
|
}
|
|
120
149
|
});
|
|
121
150
|
const colCount = tableColumns.length;
|
|
@@ -237,7 +266,9 @@ function DataTable({ columns, data, loading = false, skeletonRows = 8, loadingLa
|
|
|
237
266
|
? 'No rows'
|
|
238
267
|
: `${rowCount} rows` }), (0, jsx_runtime_1.jsxs)(table_1.Table, { "aria-busy": loading ? 'true' : undefined, children: [(0, jsx_runtime_1.jsx)(table_1.TableHeader, { children: table.getHeaderGroups().map((headerGroup) => ((0, jsx_runtime_1.jsx)(table_1.TableRow, { className: "hover:bg-transparent", children: headerGroup.headers.map((header) => {
|
|
239
268
|
const numeric = header.column.columnDef.meta?.numeric;
|
|
240
|
-
return ((0, jsx_runtime_1.jsx)(table_1.TableHead, { align: numeric ? 'right' : undefined,
|
|
269
|
+
return ((0, jsx_runtime_1.jsx)(table_1.TableHead, { align: numeric ? 'right' : undefined, "aria-sort": header.isPlaceholder
|
|
270
|
+
? undefined
|
|
271
|
+
: ariaSortFor(header.column),
|
|
241
272
|
// Only a column that DECLARED sizing gets an inline width;
|
|
242
273
|
// everything else keeps the auto table layout it has today.
|
|
243
274
|
style: (0, column_size_1.readPreferredColumnSize)(header.column), className: (0, utils_1.cn)(typography_1.LABEL_VOICE_CLASS, headDensityClass, header.column.id === SELECTION_COLUMN_ID && 'w-10', headClassName), children: header.isPlaceholder
|
|
@@ -21,6 +21,13 @@ export type DateRangePickerProps = {
|
|
|
21
21
|
fromLabel: ReactNode;
|
|
22
22
|
toLabel: ReactNode;
|
|
23
23
|
invalid?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Marks the range as mandatory. Renders the library's required marker: the
|
|
26
|
+
* literal ' *' appended to both labels, exactly as `FormLabel` does. It is
|
|
27
|
+
* deliberately NOT mirrored as `aria-required` on the triggers: ARIA does not
|
|
28
|
+
* allow that attribute on `role="button"`.
|
|
29
|
+
*/
|
|
30
|
+
required?: boolean;
|
|
24
31
|
/** Wired as aria-describedby on both triggers while `invalid` is set. */
|
|
25
32
|
errorId?: string;
|
|
26
33
|
/** Trigger placeholder when unset. */
|
|
@@ -31,7 +38,18 @@ export type DateRangePickerProps = {
|
|
|
31
38
|
clearLabel?: string;
|
|
32
39
|
/** date-fns locale for the calendar. Defaults to en-US. */
|
|
33
40
|
locale?: CalendarLocale;
|
|
41
|
+
/**
|
|
42
|
+
* Suspends the control. Both segments get the NATIVE `disabled` attribute,
|
|
43
|
+
* not an `aria-disabled` substitute: a trigger whose only job is to open a
|
|
44
|
+
* popover has no state worth keeping focusable, and native `disabled` is
|
|
45
|
+
* what takes it out of the tab order AND keeps the popover shut. That last
|
|
46
|
+
* part matters more than it looks: `PopoverContent` is portaled to
|
|
47
|
+
* `document.body`, so the calendar's Clear button is outside any wrapper a
|
|
48
|
+
* consumer could disable, and the closed popover is the only thing keeping
|
|
49
|
+
* it out of reach.
|
|
50
|
+
*/
|
|
51
|
+
disabled?: boolean;
|
|
34
52
|
};
|
|
35
|
-
export declare function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabel, invalid, errorId, placeholder, ariaLabel, clearLabel, locale }: DateRangePickerProps): import("react").JSX.Element;
|
|
53
|
+
export declare function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabel, invalid, required, errorId, placeholder, ariaLabel, clearLabel, locale, disabled }: DateRangePickerProps): import("react").JSX.Element;
|
|
36
54
|
export {};
|
|
37
55
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enterprise/date-range-picker/index.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AASnD;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,cAAc,GAAG;IAC3B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,cAAc,CAAA;IACrB,aAAa,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,SAAS,CAAA;IACpB,OAAO,EAAE,SAAS,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/enterprise/date-range-picker/index.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AASnD;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,cAAc,GAAG;IAC3B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,cAAc,CAAA;IACrB,aAAa,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,SAAS,CAAA;IACpB,OAAO,EAAE,SAAS,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAkCD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,aAAa,EACb,MAAM,EACN,IAAI,EACJ,SAAS,EACT,OAAO,EACP,OAAe,EACf,QAAgB,EAChB,OAAO,EACP,WAAwB,EACxB,SAA+B,EAC/B,UAAoB,EACpB,MAAa,EACb,QAAgB,EACjB,EAAE,oBAAoB,+BAgJtB"}
|
|
@@ -6,7 +6,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
6
6
|
/**
|
|
7
7
|
* DateRangePicker — a two-segment popover range control.
|
|
8
8
|
*
|
|
9
|
-
* Two labelled
|
|
9
|
+
* Two labelled trigger segments (from / to) each open the SAME two-month
|
|
10
10
|
* react-day-picker range calendar over the same range selection. The external
|
|
11
11
|
* contract is plain YYYY-MM-DD strings (empty string = unset) so state shapes
|
|
12
12
|
* that speak `date_from`/`date_to` stay untouched. The picker guarantees
|
|
@@ -62,12 +62,22 @@ function toDayString(value) {
|
|
|
62
62
|
const day = String(value.getDate()).padStart(2, '0');
|
|
63
63
|
return `${year}-${month}-${day}`;
|
|
64
64
|
}
|
|
65
|
-
function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabel, invalid = false, errorId, placeholder = 'Any date', ariaLabel = 'Select date range', clearLabel = 'Clear', locale = locale_1.enUS }) {
|
|
65
|
+
function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabel, invalid = false, required = false, errorId, placeholder = 'Any date', ariaLabel = 'Select date range', clearLabel = 'Clear', locale = locale_1.enUS, disabled = false }) {
|
|
66
66
|
// Which segment's popover is open, if any. One root per segment means one open
|
|
67
67
|
// state per segment; holding the identity of the open one here keeps them
|
|
68
68
|
// mutually exclusive, so clicking "to" while "from" is open swaps the anchor
|
|
69
69
|
// instead of stacking two calendars.
|
|
70
70
|
const [openSegment, setOpenSegment] = (0, react_1.useState)(null);
|
|
71
|
+
// Suspending the control must FORGET which segment was open, not just hide
|
|
72
|
+
// it. The `open` prop below already shuts the popover in the same frame
|
|
73
|
+
// `disabled` flips, but a controlled Radix root never calls `onOpenChange`
|
|
74
|
+
// for a prop-driven close, so the identity survived: lifting `disabled`
|
|
75
|
+
// re-satisfied the same condition and the portaled calendar reopened with no
|
|
76
|
+
// user gesture, pulling focus into it.
|
|
77
|
+
(0, react_1.useEffect)(() => {
|
|
78
|
+
if (disabled)
|
|
79
|
+
setOpenSegment(null);
|
|
80
|
+
}, [disabled]);
|
|
71
81
|
const fromDate = parseDay(value.from);
|
|
72
82
|
const toDate = parseDay(value.to);
|
|
73
83
|
const selected = fromDate || toDate ? { from: fromDate, to: toDate } : undefined;
|
|
@@ -81,11 +91,25 @@ function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabe
|
|
|
81
91
|
to: toDayString(range?.to)
|
|
82
92
|
});
|
|
83
93
|
};
|
|
84
|
-
const triggerClass = (0, utils_1.cn)(
|
|
94
|
+
const triggerClass = (0, utils_1.cn)(
|
|
95
|
+
// border-shadcn-400, not border-input: `--input` is a SURFACE token and is
|
|
96
|
+
// white in the light theme, so the trigger had no visible edge next to the
|
|
97
|
+
// Input and Select it sits with. font-sans, not font-mono: the dates are
|
|
98
|
+
// figures in the body face with tabular figures, like every other figure in
|
|
99
|
+
// the console.
|
|
100
|
+
'border-shadcn-400 bg-card hover:bg-secondary focus-visible:ring-ring flex h-9 items-center gap-2 rounded-md border px-3 text-left font-sans text-sm tabular-nums transition-colors duration-150 ease-out focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none sm:w-40', invalid && 'border-destructive',
|
|
101
|
+
// Conditional rather than `disabled:` variants, matching how this file
|
|
102
|
+
// already applies `border-destructive`: with the prop absent the class
|
|
103
|
+
// string stays byte-identical to what consumers render today.
|
|
104
|
+
disabled && 'cursor-not-allowed opacity-50');
|
|
85
105
|
// The one calendar, rendered inside whichever segment's popover is open. Both
|
|
86
106
|
// segments read and write the SAME range selection, so which one you opened
|
|
87
107
|
// changes only the anchor, never the state.
|
|
88
108
|
const calendar = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(calendar_1.Calendar, { mode: "range", numberOfMonths: 2, defaultMonth: fromDate ?? toDate ?? new Date(), selected: selected, onSelect: onSelect, locale: locale }), (0, jsx_runtime_1.jsx)("div", { className: "border-border flex items-center justify-end border-t px-3 py-2", children: (0, jsx_runtime_1.jsx)(button_1.Button, { type: "button", variant: "plain", size: "small", disabled: !hasValue, onClick: () => onValueChange({ from: '', to: '' }), children: clearLabel }) })] }));
|
|
89
|
-
const renderSegment = (segment, id, label, dateValue) => ((0, jsx_runtime_1.jsxs)(popover_1.Popover, {
|
|
109
|
+
const renderSegment = (segment, id, label, dateValue) => ((0, jsx_runtime_1.jsxs)(popover_1.Popover, {
|
|
110
|
+
// A disabled trigger cannot open a popover, but a surface that suspends
|
|
111
|
+
// itself WHILE one is open (a filter bar flipping to "show all") would
|
|
112
|
+
// otherwise leave the portaled calendar on screen with no way back to it.
|
|
113
|
+
open: !disabled && openSegment === segment, onOpenChange: (next) => setOpenSegment(next ? segment : null), children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-1.5", children: [(0, jsx_runtime_1.jsxs)(label_1.Label, { htmlFor: id, children: [label, required ? ' *' : ''] }), (0, jsx_runtime_1.jsxs)(popover_1.PopoverTrigger, { type: "button", id: id, className: triggerClass, disabled: disabled, "aria-invalid": invalid || undefined, "aria-describedby": invalid ? errorId : undefined, children: [(0, jsx_runtime_1.jsx)(lucide_react_1.CalendarDays, { className: "text-muted-foreground size-4 shrink-0", "aria-hidden": true }), dateValue ? ((0, jsx_runtime_1.jsx)("span", { children: dateValue })) : ((0, jsx_runtime_1.jsx)("span", { className: "text-muted-foreground", children: placeholder }))] })] }), (0, jsx_runtime_1.jsx)(popover_1.PopoverContent, { align: "start", className: "w-auto p-0", "aria-label": ariaLabel, children: calendar })] }, segment));
|
|
90
114
|
return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-end", children: [renderSegment('from', fromId, fromLabel, value.from), renderSegment('to', toId, toLabel, value.to)] }));
|
|
91
115
|
}
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { Calendar } from '../../../components/ui/calendar/index.js';
|
|
1
2
|
import * as React from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
+
import { ComponentProps, ReactNode } from 'react';
|
|
3
4
|
import { Control, FieldValues } from 'react-hook-form';
|
|
5
|
+
/**
|
|
6
|
+
* The calendar's locale type, taken straight off the Calendar props so the
|
|
7
|
+
* public signature stays the react-day-picker/date-fns `Locale` without this
|
|
8
|
+
* package taking a direct date-fns dependency.
|
|
9
|
+
*/
|
|
10
|
+
type CalendarLocale = ComponentProps<typeof Calendar>['locale'];
|
|
4
11
|
export type DatePickerFieldProps<T extends FieldValues = FieldValues> = {
|
|
5
12
|
name: string;
|
|
6
13
|
label?: ReactNode;
|
|
@@ -16,6 +23,9 @@ export type DatePickerFieldProps<T extends FieldValues = FieldValues> = {
|
|
|
16
23
|
align?: 'start' | 'center' | 'end';
|
|
17
24
|
'data-testid'?: string;
|
|
18
25
|
valueAsString?: boolean;
|
|
26
|
+
/** date-fns locale for the calendar. Defaults to en-US. */
|
|
27
|
+
locale?: CalendarLocale;
|
|
19
28
|
};
|
|
20
|
-
export declare const DatePickerField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat, align, valueAsString, ...others }: DatePickerFieldProps<T>) => React.JSX.Element;
|
|
29
|
+
export declare const DatePickerField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat, align, valueAsString, locale, ...others }: DatePickerFieldProps<T>) => React.JSX.Element;
|
|
30
|
+
export {};
|
|
21
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/date-picker-field/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/date-picker-field/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAkBnD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAQ,MAAM,iBAAiB,CAAA;AAE5D;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IACtE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;CACxB,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,4JAgBlE,oBAAoB,CAAC,CAAC,CAAC,sBAiGzB,CAAA"}
|
|
@@ -8,7 +8,8 @@ import { cn } from '../../../lib/utils.js';
|
|
|
8
8
|
import dayjs from 'dayjs';
|
|
9
9
|
import { CalendarIcon } from 'lucide-react';
|
|
10
10
|
import * as React from 'react';
|
|
11
|
-
|
|
11
|
+
import { enUS } from 'react-day-picker/locale';
|
|
12
|
+
export const DatePickerField = ({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat = 'MMM DD, YYYY', align = 'start', valueAsString, locale = enUS, ...others }) => {
|
|
12
13
|
const [open, setOpen] = React.useState(false);
|
|
13
14
|
return (_jsx(FormField, { name: name, control: control, render: ({ field }) => {
|
|
14
15
|
const convertFieldValueToDate = (fieldValue) => {
|
|
@@ -33,6 +34,10 @@ export const DatePickerField = ({ name, label, tooltip, labelExtra, description,
|
|
|
33
34
|
const handleSelect = (date) => {
|
|
34
35
|
field.onChange(convertDateToOutputFormat(date));
|
|
35
36
|
};
|
|
36
|
-
return (_jsxs(FormItem, { required: required, children: [label && (_jsx(FormLabel, { extra: tooltip ? _jsx(FormTooltip, { children: tooltip }) : labelExtra, children: label })), _jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(FormControl, { children: _jsx(Button, { variant: "outline", disabled: disabled, className: cn('bg-input hover:bg-input border-shadcn-400 text-foreground h-10 w-full justify-start rounded-md px-2.5 font-normal', readOnly && 'pointer-events-none', open && 'ring-ring ring-2 ring-offset-0'), "data-testid": others['data-testid'], icon: _jsx(CalendarIcon, { className: "size-4" }), children: value ? (_jsx("span", { className: "text-foreground flex-1 text-left font-bold", children: dayjs(value).format(dateFormat) })) : (_jsx("span", { className: "text-muted-foreground flex-1 text-left", children: placeholder })) }) }) }), _jsx(PopoverContent, { className: "w-auto p-0", align: align, children: _jsx(Calendar, { mode: "single",
|
|
37
|
+
return (_jsxs(FormItem, { required: required, children: [label && (_jsx(FormLabel, { extra: tooltip ? _jsx(FormTooltip, { children: tooltip }) : labelExtra, children: label })), _jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(FormControl, { children: _jsx(Button, { variant: "outline", disabled: disabled, className: cn('bg-input hover:bg-input border-shadcn-400 text-foreground h-10 w-full justify-start rounded-md px-2.5 font-normal', readOnly && 'pointer-events-none', open && 'ring-ring ring-2 ring-offset-0'), "data-testid": others['data-testid'], icon: _jsx(CalendarIcon, { className: "size-4" }), children: value ? (_jsx("span", { className: "text-foreground flex-1 text-left font-bold", children: dayjs(value).format(dateFormat) })) : (_jsx("span", { className: "text-muted-foreground flex-1 text-left", children: placeholder })) }) }) }), _jsx(PopoverContent, { className: "w-auto p-0", align: align, children: _jsx(Calendar, { mode: "single",
|
|
38
|
+
// `required` mirrors the field's own required: a required
|
|
39
|
+
// field is not emptied by a re-click; an optional one keeps
|
|
40
|
+
// react-day-picker's clear gesture.
|
|
41
|
+
required: required, defaultMonth: value, selected: value, onSelect: handleSelect, disabled: disabled || readOnly, locale: locale }) })] }), _jsx(FormMessage, {}), description && _jsx(FormDescription, { children: description })] }));
|
|
37
42
|
} }));
|
|
38
43
|
};
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { Calendar } from '../../../components/ui/calendar/index.js';
|
|
1
2
|
import * as React from 'react';
|
|
2
|
-
import { ReactNode } from 'react';
|
|
3
|
+
import { type ComponentProps, ReactNode } from 'react';
|
|
3
4
|
import { Control, FieldValues } from 'react-hook-form';
|
|
5
|
+
/**
|
|
6
|
+
* The calendar's locale type, taken straight off the Calendar props so the
|
|
7
|
+
* public signature stays the react-day-picker/date-fns `Locale` without this
|
|
8
|
+
* package taking a direct date-fns dependency.
|
|
9
|
+
*/
|
|
10
|
+
type CalendarLocale = ComponentProps<typeof Calendar>['locale'];
|
|
4
11
|
export type DateRangeFieldProps<T extends FieldValues = FieldValues> = {
|
|
5
12
|
name: string;
|
|
6
13
|
label?: ReactNode;
|
|
@@ -15,7 +22,10 @@ export type DateRangeFieldProps<T extends FieldValues = FieldValues> = {
|
|
|
15
22
|
numberOfMonths?: number;
|
|
16
23
|
dateFormat?: string;
|
|
17
24
|
align?: 'start' | 'center' | 'end';
|
|
25
|
+
/** date-fns locale for the calendar. Defaults to en-US. */
|
|
26
|
+
locale?: CalendarLocale;
|
|
18
27
|
'data-testid'?: string;
|
|
19
28
|
};
|
|
20
|
-
export declare const DateRangeField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, numberOfMonths, dateFormat, align, ...others }: DateRangeFieldProps<T>) => React.JSX.Element;
|
|
29
|
+
export declare const DateRangeField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, numberOfMonths, dateFormat, align, locale, ...others }: DateRangeFieldProps<T>) => React.JSX.Element;
|
|
30
|
+
export {};
|
|
21
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/date-range-field/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/date-range-field/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAkBnD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,KAAK,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAGtD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAQ,MAAM,iBAAiB,CAAA;AAE5D;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IACrE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,6JAgBjE,mBAAmB,CAAC,CAAC,CAAC,sBA2ExB,CAAA"}
|
|
@@ -8,10 +8,11 @@ import { cn } from '../../../lib/utils.js';
|
|
|
8
8
|
import dayjs from 'dayjs';
|
|
9
9
|
import { CalendarIcon } from 'lucide-react';
|
|
10
10
|
import * as React from 'react';
|
|
11
|
-
|
|
11
|
+
import { enUS } from 'react-day-picker/locale';
|
|
12
|
+
export const DateRangeField = ({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, numberOfMonths = 2, dateFormat = 'MMM DD, YYYY', align = 'start', locale = enUS, ...others }) => {
|
|
12
13
|
const [open, setOpen] = React.useState(false);
|
|
13
14
|
return (_jsx(FormField, { name: name, control: control, render: ({ field }) => {
|
|
14
15
|
const value = field.value;
|
|
15
|
-
return (_jsxs(FormItem, { required: required, children: [label && (_jsx(FormLabel, { extra: tooltip ? _jsx(FormTooltip, { children: tooltip }) : labelExtra, children: label })), _jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(FormControl, { children: _jsx(Button, { variant: "outline", disabled: disabled, className: cn('bg-input hover:bg-input border-shadcn-400 text-foreground h-10 w-full justify-start rounded-md px-2.5 font-normal', readOnly && 'pointer-events-none', open && 'ring-ring ring-2 ring-offset-0'), "data-testid": others['data-testid'], icon: _jsx(CalendarIcon, { className: "size-4" }), children: value?.from ? (_jsx("span", { className: "text-foreground flex-1 text-left font-bold", children: value.to ? (_jsxs(_Fragment, { children: [dayjs(value.from).format(dateFormat), " -", ' ', dayjs(value.to).format(dateFormat)] })) : (dayjs(value.from).format(dateFormat)) })) : (_jsx("span", { className: "text-muted-foreground flex-1 text-left", children: placeholder })) }) }) }), _jsx(PopoverContent, { className: "w-auto p-0", align: align, children: _jsx(Calendar, { mode: "range", defaultMonth: value?.from, selected: value, onSelect: field.onChange, numberOfMonths: numberOfMonths, disabled: disabled || readOnly }) })] }), _jsx(FormMessage, {}), description && _jsx(FormDescription, { children: description })] }));
|
|
16
|
+
return (_jsxs(FormItem, { required: required, children: [label && (_jsx(FormLabel, { extra: tooltip ? _jsx(FormTooltip, { children: tooltip }) : labelExtra, children: label })), _jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(FormControl, { children: _jsx(Button, { variant: "outline", disabled: disabled, className: cn('bg-input hover:bg-input border-shadcn-400 text-foreground h-10 w-full justify-start rounded-md px-2.5 font-normal', readOnly && 'pointer-events-none', open && 'ring-ring ring-2 ring-offset-0'), "data-testid": others['data-testid'], icon: _jsx(CalendarIcon, { className: "size-4" }), children: value?.from ? (_jsx("span", { className: "text-foreground flex-1 text-left font-bold", children: value.to ? (_jsxs(_Fragment, { children: [dayjs(value.from).format(dateFormat), " -", ' ', dayjs(value.to).format(dateFormat)] })) : (dayjs(value.from).format(dateFormat)) })) : (_jsx("span", { className: "text-muted-foreground flex-1 text-left", children: placeholder })) }) }) }), _jsx(PopoverContent, { className: "w-auto p-0", align: align, children: _jsx(Calendar, { mode: "range", defaultMonth: value?.from, selected: value, onSelect: field.onChange, numberOfMonths: numberOfMonths, disabled: disabled || readOnly, locale: locale }) })] }), _jsx(FormMessage, {}), description && _jsx(FormDescription, { children: description })] }));
|
|
16
17
|
} }));
|
|
17
18
|
};
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { Calendar } from '../../../components/ui/calendar/index.js';
|
|
1
2
|
import * as React from 'react';
|
|
2
|
-
import { type ReactNode } from 'react';
|
|
3
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
3
4
|
import { Control, FieldValues } from 'react-hook-form';
|
|
5
|
+
/**
|
|
6
|
+
* The calendar's locale type, taken straight off the Calendar props so the
|
|
7
|
+
* public signature stays the react-day-picker/date-fns `Locale` without this
|
|
8
|
+
* package taking a direct date-fns dependency.
|
|
9
|
+
*/
|
|
10
|
+
type CalendarLocale = ComponentProps<typeof Calendar>['locale'];
|
|
4
11
|
export type DateTimePickerFieldProps<T extends FieldValues = FieldValues> = {
|
|
5
12
|
name: string;
|
|
6
13
|
label?: ReactNode;
|
|
@@ -14,10 +21,13 @@ export type DateTimePickerFieldProps<T extends FieldValues = FieldValues> = {
|
|
|
14
21
|
required?: boolean;
|
|
15
22
|
dateFormat?: string;
|
|
16
23
|
align?: 'start' | 'center' | 'end';
|
|
24
|
+
/** date-fns locale for the calendar. Defaults to en-US. */
|
|
25
|
+
locale?: CalendarLocale;
|
|
17
26
|
'data-testid'?: string;
|
|
18
27
|
minDate?: Date;
|
|
19
28
|
maxDate?: Date;
|
|
20
29
|
defaultTime?: string;
|
|
21
30
|
};
|
|
22
|
-
export declare const DateTimePickerField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat, align, minDate, maxDate, defaultTime, ...others }: DateTimePickerFieldProps<T>) => React.JSX.Element;
|
|
31
|
+
export declare const DateTimePickerField: <T extends FieldValues = FieldValues>({ name, label, tooltip, labelExtra, description, placeholder, disabled, readOnly, control, required, dateFormat, align, locale, minDate, maxDate, defaultTime, ...others }: DateTimePickerFieldProps<T>) => React.JSX.Element;
|
|
32
|
+
export {};
|
|
23
33
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/date-time-picker-field/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/date-time-picker-field/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AAmBnD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAE3D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAQ,MAAM,iBAAiB,CAAA;AAE5D;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,WAAW,GAAG,WAAW,IAAI;IAC1E,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;IAClC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,OAAO,CAAC,EAAE,IAAI,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,CAAC,SAAS,WAAW,GAAG,WAAW,EAAE,4KAkBtE,wBAAwB,CAAC,CAAC,CAAC,sBAiK7B,CAAA"}
|
|
@@ -9,7 +9,8 @@ import { cn } from '../../../lib/utils.js';
|
|
|
9
9
|
import dayjs from 'dayjs';
|
|
10
10
|
import { CalendarIcon, XIcon } from 'lucide-react';
|
|
11
11
|
import * as React from 'react';
|
|
12
|
-
|
|
12
|
+
import { enUS } from 'react-day-picker/locale';
|
|
13
|
+
export const DateTimePickerField = ({ name, label, tooltip, labelExtra, description, placeholder = 'Select date and time...', disabled, readOnly, control, required, dateFormat = 'MMM DD, YYYY HH:mm', align = 'start', locale = enUS, minDate, maxDate, defaultTime = '00:00', ...others }) => {
|
|
13
14
|
const [open, setOpen] = React.useState(false);
|
|
14
15
|
const parseDefaultTime = (time) => {
|
|
15
16
|
const [h, m] = time.split(':').map(Number);
|
|
@@ -58,7 +59,7 @@ export const DateTimePickerField = ({ name, label, tooltip, labelExtra, descript
|
|
|
58
59
|
e.preventDefault();
|
|
59
60
|
handleClear(e);
|
|
60
61
|
}
|
|
61
|
-
}, children: _jsx(XIcon, { className: "size-4" }) }))] }), _jsx(PopoverContent, { className: "w-auto p-0", align: align, children: _jsxs("div", { className: "flex flex-col sm:flex-row sm:items-stretch", children: [_jsx(Calendar, { mode: "single", defaultMonth: validCurrent ? validCurrent.toDate() : undefined, selected: validCurrent ? validCurrent.toDate() : undefined, onSelect: handleDateSelect, disabled: (date) => {
|
|
62
|
+
}, children: _jsx(XIcon, { className: "size-4" }) }))] }), _jsx(PopoverContent, { className: "w-auto p-0", align: align, children: _jsxs("div", { className: "flex flex-col sm:flex-row sm:items-stretch", children: [_jsx(Calendar, { mode: "single", defaultMonth: validCurrent ? validCurrent.toDate() : undefined, selected: validCurrent ? validCurrent.toDate() : undefined, onSelect: handleDateSelect, locale: locale, disabled: (date) => {
|
|
62
63
|
if (disabled || readOnly)
|
|
63
64
|
return true;
|
|
64
65
|
if (minDate &&
|
|
@@ -27,8 +27,21 @@ export type PageHeaderInfoTitleProps = {
|
|
|
27
27
|
/**
|
|
28
28
|
* Seam for the wrapper element's own margins. Merged AFTER the hard-coded
|
|
29
29
|
* `mb-12` so a consumer utility (e.g. `mb-0`) wins via tailwind-merge.
|
|
30
|
+
*
|
|
31
|
+
* It is also the way back to the old shrink-to-zero title box:
|
|
32
|
+
* `containerClassName="min-w-0"` simply lands, because the base string
|
|
33
|
+
* declares no `min-w-*` for tailwind-merge to weigh it against. Pass it only
|
|
34
|
+
* if a title box that a wide action slot can squeeze past its longest word
|
|
35
|
+
* is what the surface actually wants.
|
|
30
36
|
*/
|
|
31
37
|
containerClassName?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Rendered as their own row under the subtitle, wrapping, so a long identity
|
|
40
|
+
* tape never competes with the subtitle for the same line. This is the slot
|
|
41
|
+
* for things that IDENTIFY the record (short id, status, severity, counts),
|
|
42
|
+
* not for controls: buttons belong in the header's action slot, where the
|
|
43
|
+
* wrapper's `justify-between` keeps them right-aligned.
|
|
44
|
+
*/
|
|
32
45
|
children?: ReactNode;
|
|
33
46
|
};
|
|
34
47
|
export declare function PageHeaderInfoTitle({ title, subtitle, className, containerClassName, children, as: Heading }: PageHeaderInfoTitleProps): import("react").JSX.Element;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/page-header/index.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/components/page-header/index.tsx"],"names":[],"mappings":"AACA,OAAO,EAA2B,SAAS,EAAwB,MAAM,OAAO,CAAA;AAmBhF,wBAAgB,uBAAuB,CAAC,EACtC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAQ7B;AAED,wBAAgB,iBAAiB,CAAC,EAChC,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,+BAc7B;AAED,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,SAAS,CAAA;IACnB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAS,EACT,aAAa,EACd,EAAE,eAAe,+BAmBjB;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,oDAAoD;IACpD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,EAAE,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAA;IAC5C;;;;;;;;;OASG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB,CAAA;AAED,wBAAgB,mBAAmB,CAAC,EAClC,KAAK,EACL,QAAQ,EACR,SAAS,EACT,kBAAkB,EAClB,QAAQ,EACR,EAAE,EAAE,OAAc,EACnB,EAAE,wBAAwB,+BA2D1B;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACT,EAAE,0BAA0B,+BAqC5B;AAED,MAAM,MAAM,qCAAqC,GAAG;IAClD,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,wBAAgB,gCAAgC,CAAC,EAC/C,QAAQ,EACT,EAAE,qCAAqC,+BAavC;AAED,MAAM,MAAM,8BAA8B,GAAG;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,wBAAgB,yBAAyB,CAAC,EACxC,QAAQ,EACR,MAAM,EACN,OAAO,EACP,IAAI,EACL,EAAE,8BAA8B,+BA+ChC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from '../../lib/utils.js';
|
|
3
|
-
import { createContext, useContext, useState } from 'react';
|
|
3
|
+
import { Children, createContext, useContext, useState } from 'react';
|
|
4
4
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../../components/ui/collapsible/index.js';
|
|
5
5
|
import { Button } from '../ui/button/index.js';
|
|
6
6
|
import { HelpCircle, ChevronUp, ExternalLink, Copy } from 'lucide-react';
|
|
@@ -20,7 +20,38 @@ export function PageHeader({ children, className, rootClassName }) {
|
|
|
20
20
|
return (_jsx(PageHeaderContext.Provider, { value: { isOpen }, children: _jsx("div", { "data-slot": "page-header", className: cn('mt-12', isOpen && 'mb-12', rootClassName), children: _jsx(Collapsible, { open: isOpen, onOpenChange: setIsOpen, className: className, children: children }) }) }));
|
|
21
21
|
}
|
|
22
22
|
export function PageHeaderInfoTitle({ title, subtitle, className, containerClassName, children, as: Heading = 'h1' }) {
|
|
23
|
-
return (_jsxs("div", { "data-slot": "page-header-info-title",
|
|
23
|
+
return (_jsxs("div", { "data-slot": "page-header-info-title",
|
|
24
|
+
/*
|
|
25
|
+
Two utilities and one deliberate absence.
|
|
26
|
+
|
|
27
|
+
`flex-1` (basis 0) is #170: flex shrinking is shared in proportion to
|
|
28
|
+
flex-basis, so a title box at basis auto (its max-content width, which
|
|
29
|
+
a long subtitle inflates) absorbed almost none of the overflow and
|
|
30
|
+
starved the action row into one button per line. At basis 0 the line's
|
|
31
|
+
hypothetical size is the action row alone, so the row keeps its natural
|
|
32
|
+
width and the title grows into what is left, wrapping at spaces.
|
|
33
|
+
|
|
34
|
+
NO `min-w-0` is #174, and the absence is the fix. A flex item's
|
|
35
|
+
automatic minimum size is its own min-content, so left alone the box
|
|
36
|
+
cannot be squeezed below its longest word (of the title, the subtitle,
|
|
37
|
+
or a child chip) and nothing can overflow horizontally at any width.
|
|
38
|
+
beta.5 carried `min-w-0`, which waives that minimum: on Matcher's
|
|
39
|
+
exception-detail masthead the box collapsed to 68px and the `h1`
|
|
40
|
+
painted straight out of it and across the action row. That is gone.
|
|
41
|
+
|
|
42
|
+
A fixed floor was the other candidate and is wrong: any `sm:` gate keys
|
|
43
|
+
on the VIEWPORT while the overflow condition is the MASTHEAD width, so
|
|
44
|
+
a 1024px viewport with a 320px side panel open (a ~332px masthead)
|
|
45
|
+
would keep a 320px floor and scroll the body sideways.
|
|
46
|
+
|
|
47
|
+
The measured trade: on a masthead carrying a 520px action row the title
|
|
48
|
+
box shrinks to its longest word and the subtitle wraps to about three
|
|
49
|
+
lines. The remedy there is fewer controls in the action slot, not a
|
|
50
|
+
wider floor. A consumer that wants the collapse back passes
|
|
51
|
+
`containerClassName="min-w-0"`. jsdom does not lay out, so the geometry
|
|
52
|
+
is verified downstream.
|
|
53
|
+
*/
|
|
54
|
+
className: cn('mb-12 flex flex-1 flex-col gap-4', containerClassName), children: [_jsx(Heading, { className: cn('text-foreground text-4xl font-bold', className), "data-testid": "title", children: title }), _jsx("div", { className: "flex items-center gap-2", children: _jsx("p", { className: "text-muted-foreground text-sm font-medium", children: subtitle }) }), Children.toArray(children).length > 0 ? (_jsx("div", { className: "flex flex-wrap items-center gap-2", children: children })) : null] }));
|
|
24
55
|
}
|
|
25
56
|
export function PageHeaderInfoTooltip({ subtitle }) {
|
|
26
57
|
const { toast } = useToast();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/calendar/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EACL,SAAS,EAET,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,MAAM,EAAkB,MAAM,wBAAwB,CAAA;AAO/D,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,UAAU,EACV,eAAsB,EACtB,aAAuB,EACvB,aAAuB,EACvB,UAAU,EACV,UAAU,EACV,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,GAAG;IAC1C,aAAa,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAA;CAC/D,qBA0JA;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,EACH,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/components/ui/calendar/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EACL,SAAS,EAET,KAAK,SAAS,EACf,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,MAAM,EAAkB,MAAM,wBAAwB,CAAA;AAO/D,iBAAS,QAAQ,CAAC,EAChB,SAAS,EACT,UAAU,EACV,eAAsB,EACtB,aAAuB,EACvB,aAAuB,EACvB,UAAU,EACV,UAAU,EACV,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,GAAG;IAC1C,aAAa,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,CAAC,SAAS,CAAC,CAAA;CAC/D,qBA0JA;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,EACH,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,SAAS,CAAC,qBAqCxC;AAED,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,CAAA"}
|
|
@@ -68,12 +68,9 @@ function CalendarDayButton({ className, day, modifiers, ...props }) {
|
|
|
68
68
|
if (modifiers.focused)
|
|
69
69
|
ref.current?.focus();
|
|
70
70
|
}, [modifiers.focused]);
|
|
71
|
-
const dayNumber = day.date.getDate();
|
|
72
|
-
const monthName = day.date.toLocaleDateString('en', { month: 'long' });
|
|
73
|
-
const year = day.date.getFullYear();
|
|
74
71
|
return (_jsx(Button, { ref: ref, variant: "plain", size: "small", "data-day": day.date.toLocaleDateString(), "data-selected-single": modifiers.selected &&
|
|
75
72
|
!modifiers.range_start &&
|
|
76
73
|
!modifiers.range_end &&
|
|
77
|
-
!modifiers.range_middle, "data-range-start": modifiers.range_start, "data-range-end": modifiers.range_end, "data-range-middle": modifiers.range_middle, "data-today": modifiers.today && !modifiers.range_middle, "aria-
|
|
74
|
+
!modifiers.range_middle, "data-range-start": modifiers.range_start, "data-range-end": modifiers.range_end, "data-range-middle": modifiers.range_middle, "data-today": modifiers.today && !modifiers.range_middle, "aria-current": modifiers.today ? 'date' : undefined, className: cn('data-[today=true]:bg-accent data-[today=true]:text-accent-foreground data-[selected-single=true]:bg-accent data-[selected-single=true]:text-accent-foreground data-[range-middle=true]:bg-accent-mute data-[range-middle=true]:text-foreground data-[range-start=true]:bg-accent data-[range-start=true]:text-accent-foreground data-[range-end=true]:bg-accent data-[range-end=true]:text-accent-foreground focus-visible:border-accent focus-visible:ring-accent/50 relative isolate z-10 flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 border-0 leading-none font-normal focus-visible:ring-[3px] focus-visible:outline-none data-[range-end=true]:rounded-(--cell-radius) data-[range-end=true]:rounded-r-(--cell-radius) data-[range-end=true]:font-bold data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-(--cell-radius) data-[range-start=true]:rounded-l-(--cell-radius) data-[range-start=true]:font-bold data-[selected-single=true]:font-bold data-[today=true]:font-bold [&>span]:text-xs [&>span]:opacity-70', defaultClassNames.day, className), ...props }));
|
|
78
75
|
}
|
|
79
76
|
export { Calendar, CalendarDayButton };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ColumnDef, type OnChangeFn, type RowData, type RowSelectionState } from '@tanstack/react-table';
|
|
1
|
+
import { type ColumnDef, type OnChangeFn, type RowData, type RowSelectionState, type SortingState } from '@tanstack/react-table';
|
|
2
2
|
import { type EmptyStateProps } from '../empty-state/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* Per-column opt-in for ledger numeric alignment. Set `meta: { numeric: true }`
|
|
@@ -38,6 +38,39 @@ type RowSelectionProps<TData> = {
|
|
|
38
38
|
*/
|
|
39
39
|
getRowSelectionLabel?: (row: TData) => string;
|
|
40
40
|
};
|
|
41
|
+
/**
|
|
42
|
+
* Sorting is CONTROLLED-ONLY and OPT-IN, mirroring the row-selection contract
|
|
43
|
+
* above: the table sets `manualSorting` and adds no sorted row model, so it
|
|
44
|
+
* never reorders rows. The consumer owns the order (it usually comes back
|
|
45
|
+
* sorted from the server); what the table owns is announcing the state in the
|
|
46
|
+
* one place ARIA defines for it, `aria-sort` on the `th`. Header content is
|
|
47
|
+
* typically a `<button>`, and `aria-sort` is not allowed on a button, so a
|
|
48
|
+
* consumer cannot put it there without failing axe `aria-allowed-attr`.
|
|
49
|
+
*
|
|
50
|
+
* GOTCHA, TanStack's own rule, not a new one: `getCanSort()` is
|
|
51
|
+
* `(columnDef.enableSorting ?? true) && (options.enableSorting ?? true) &&
|
|
52
|
+
* !!column.accessorFn`. A display column (an `id` plus a `cell`, no
|
|
53
|
+
* `accessorKey` or `accessorFn`) has no accessor, so it can never sort and
|
|
54
|
+
* gets no `aria-sort`. That is right for an actions column and surprising for
|
|
55
|
+
* a computed column: give a column you want announced an accessor, and give a
|
|
56
|
+
* column you want excluded `enableSorting: false`.
|
|
57
|
+
*/
|
|
58
|
+
type SortingProps = {
|
|
59
|
+
enableSorting?: false;
|
|
60
|
+
sorting?: never;
|
|
61
|
+
onSortingChange?: never;
|
|
62
|
+
} | {
|
|
63
|
+
enableSorting: true;
|
|
64
|
+
/**
|
|
65
|
+
* Controlled sort state (TanStack `SortingState`). Single-entry:
|
|
66
|
+
* `aria-sort` is defined for one sorted header at a time, so a
|
|
67
|
+
* multi-entry `SortingState` is the consumer's responsibility and yields
|
|
68
|
+
* several non-`none` values.
|
|
69
|
+
*/
|
|
70
|
+
sorting: SortingState;
|
|
71
|
+
/** Controlled sort updater (TanStack `OnChangeFn`). */
|
|
72
|
+
onSortingChange: OnChangeFn<SortingState>;
|
|
73
|
+
};
|
|
41
74
|
type DataTableBaseProps<TData> = {
|
|
42
75
|
columns: ColumnDef<TData, unknown>[];
|
|
43
76
|
data: TData[];
|
|
@@ -94,7 +127,7 @@ type DataTableBaseProps<TData> = {
|
|
|
94
127
|
*/
|
|
95
128
|
footer?: React.ReactNode;
|
|
96
129
|
};
|
|
97
|
-
export type DataTableProps<TData> = DataTableBaseProps<TData> & RowSelectionProps<TData
|
|
98
|
-
export declare function DataTable<TData>({ columns, data, loading, skeletonRows, loadingLabel, empty, getRowId, flush, density, enableRowSelection, rowSelection, onRowSelectionChange, getRowSelectionLabel, onRowActivate, rowHref, className, headClassName, footer }: DataTableProps<TData>): import("react").JSX.Element;
|
|
130
|
+
export type DataTableProps<TData> = DataTableBaseProps<TData> & RowSelectionProps<TData> & SortingProps;
|
|
131
|
+
export declare function DataTable<TData>({ columns, data, loading, skeletonRows, loadingLabel, empty, getRowId, flush, density, enableRowSelection, rowSelection, onRowSelectionChange, getRowSelectionLabel, enableSorting, sorting, onSortingChange, onRowActivate, rowHref, className, headClassName, footer }: DataTableProps<TData>): import("react").JSX.Element;
|
|
99
132
|
export {};
|
|
100
133
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/data-table/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/data-table/index.tsx"],"names":[],"mappings":"AAuDA,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,UAAU,EAEf,KAAK,OAAO,EACZ,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAElB,MAAM,uBAAuB,CAAA;AAc9B,OAAO,EAAc,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAGjE;;;;GAIG;AACH,OAAO,QAAQ,uBAAuB,CAAC;IAIrC,UAAU,UAAU,CAAC,KAAK,SAAS,OAAO,EAAE,MAAM;QAChD,OAAO,CAAC,EAAE,OAAO,CAAA;KAClB;CACF;AAED;;;;;;;;GAQG;AACH,KAAK,iBAAiB,CAAC,KAAK,IACxB;IACE,kBAAkB,CAAC,EAAE,KAAK,CAAA;IAC1B,YAAY,CAAC,EAAE,KAAK,CAAA;IACpB,oBAAoB,CAAC,EAAE,KAAK,CAAA;IAC5B,oBAAoB,CAAC,EAAE,KAAK,CAAA;CAC7B,GACD;IACE,kBAAkB,EAAE,IAAI,CAAA;IACxB,kFAAkF;IAClF,YAAY,EAAE,iBAAiB,CAAA;IAC/B,4DAA4D;IAC5D,oBAAoB,EAAE,UAAU,CAAC,iBAAiB,CAAC,CAAA;IACnD;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAA;CAC9C,CAAA;AAEL;;;;;;;;;;;;;;;;GAgBG;AACH,KAAK,YAAY,GACb;IACE,aAAa,CAAC,EAAE,KAAK,CAAA;IACrB,OAAO,CAAC,EAAE,KAAK,CAAA;IACf,eAAe,CAAC,EAAE,KAAK,CAAA;CACxB,GACD;IACE,aAAa,EAAE,IAAI,CAAA;IACnB;;;;;OAKG;IACH,OAAO,EAAE,YAAY,CAAA;IACrB,uDAAuD;IACvD,eAAe,EAAE,UAAU,CAAC,YAAY,CAAC,CAAA;CAC1C,CAAA;AAEL,KAAK,kBAAkB,CAAC,KAAK,IAAI;IAC/B,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAA;IACpC,IAAI,EAAE,KAAK,EAAE,CAAA;IACb,sDAAsD;IACtD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,iGAAiG;IACjG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,qEAAqE;IACrE,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IAChD;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAA;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,aAAa,GAAG,SAAS,CAAA;IACnC;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IACpC;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,MAAM,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,KAAK,IAAI,kBAAkB,CAAC,KAAK,CAAC,GAC3D,iBAAiB,CAAC,KAAK,CAAC,GACxB,YAAY,CAAA;AA8Fd,wBAAgB,SAAS,CAAC,KAAK,EAAE,EAC/B,OAAO,EACP,IAAI,EACJ,OAAe,EACf,YAAgB,EAChB,YAAmC,EACnC,KAAK,EACL,QAAQ,EACR,KAAa,EACb,OAAuB,EACvB,kBAA0B,EAC1B,YAAY,EACZ,oBAAoB,EACpB,oBAAoB,EACpB,aAAqB,EACrB,OAAO,EACP,eAAe,EACf,aAAa,EACb,OAAO,EACP,SAAS,EACT,aAAa,EACb,MAAM,EACP,EAAE,cAAc,CAAC,KAAK,CAAC,+BAyTvB"}
|
|
@@ -35,6 +35,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
35
35
|
* page (indeterminate for partial), checkbox-cell clicks never bubble to
|
|
36
36
|
* row-level handlers. With the flag off (the default), nothing changes.
|
|
37
37
|
*
|
|
38
|
+
* Sorting is opt-in and controlled too: pass `enableSorting` plus `sorting` /
|
|
39
|
+
* `onSortingChange`. Rows are never reordered client-side (`manualSorting`, no
|
|
40
|
+
* sorted row model); what the flag buys is `aria-sort` on each sortable `th`.
|
|
41
|
+
* With the flag off (the default), no header carries the attribute.
|
|
42
|
+
*
|
|
38
43
|
* Keyboard navigation is opt-in via `onRowActivate`: when present, rows get
|
|
39
44
|
* a roving tabindex (Tab enters the table once at the anchor row; the next
|
|
40
45
|
* Tab moves to the row's first tabbable child if it has one, otherwise out
|
|
@@ -74,6 +79,22 @@ const ROW_FOCUS_CLASS = 'focus-visible:outline focus-visible:outline-2 focus-vis
|
|
|
74
79
|
function stopPropagation(event) {
|
|
75
80
|
event.stopPropagation();
|
|
76
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* ARIA sort state for one header cell. `undefined` (attribute omitted) on a
|
|
84
|
+
* column that cannot sort, which covers both sorting-off tables and columns
|
|
85
|
+
* that opted out, so the attribute never claims a control the user does not
|
|
86
|
+
* have.
|
|
87
|
+
*/
|
|
88
|
+
function ariaSortFor(column) {
|
|
89
|
+
if (!column.getCanSort())
|
|
90
|
+
return undefined;
|
|
91
|
+
const sorted = column.getIsSorted();
|
|
92
|
+
if (sorted === 'asc')
|
|
93
|
+
return 'ascending';
|
|
94
|
+
if (sorted === 'desc')
|
|
95
|
+
return 'descending';
|
|
96
|
+
return 'none';
|
|
97
|
+
}
|
|
77
98
|
function SelectAllCheckbox({ table }) {
|
|
78
99
|
const allSelected = table.getIsAllPageRowsSelected();
|
|
79
100
|
const someSelected = table.getIsSomePageRowsSelected();
|
|
@@ -92,7 +113,7 @@ function createSelectionColumn(getLabel) {
|
|
|
92
113
|
cell: ({ row }) => _jsx(RowSelectionCheckbox, { row: row, getLabel: getLabel })
|
|
93
114
|
};
|
|
94
115
|
}
|
|
95
|
-
export function DataTable({ columns, data, loading = false, skeletonRows = 8, loadingLabel = 'Loading table rows', empty, getRowId, flush = false, density = 'comfortable', enableRowSelection = false, rowSelection, onRowSelectionChange, getRowSelectionLabel, onRowActivate, rowHref, className, headClassName, footer }) {
|
|
116
|
+
export function DataTable({ columns, data, loading = false, skeletonRows = 8, loadingLabel = 'Loading table rows', empty, getRowId, flush = false, density = 'comfortable', enableRowSelection = false, rowSelection, onRowSelectionChange, getRowSelectionLabel, enableSorting = false, sorting, onSortingChange, onRowActivate, rowHref, className, headClassName, footer }) {
|
|
96
117
|
const tableColumns = useMemo(() => enableRowSelection
|
|
97
118
|
? [createSelectionColumn(getRowSelectionLabel), ...columns]
|
|
98
119
|
: columns, [columns, enableRowSelection, getRowSelectionLabel]);
|
|
@@ -111,8 +132,16 @@ export function DataTable({ columns, data, loading = false, skeletonRows = 8, lo
|
|
|
111
132
|
// types make the TS path require the controlled pair whenever selection is
|
|
112
133
|
// enabled, so the dead-checkbox configuration is now unrepresentable.
|
|
113
134
|
onRowSelectionChange: enableRowSelection ? onRowSelectionChange : undefined,
|
|
135
|
+
// Controlled-only as well, and deliberately without `getSortedRowModel`:
|
|
136
|
+
// `manualSorting` tells TanStack the rows arrive in the order the consumer
|
|
137
|
+
// already chose, so enabling sorting changes what the header ANNOUNCES,
|
|
138
|
+
// never what the body shows.
|
|
139
|
+
manualSorting: true,
|
|
140
|
+
enableSorting,
|
|
141
|
+
onSortingChange: enableSorting ? onSortingChange : undefined,
|
|
114
142
|
state: {
|
|
115
|
-
rowSelection: enableRowSelection ? (rowSelection ?? {}) : undefined
|
|
143
|
+
rowSelection: enableRowSelection ? (rowSelection ?? {}) : undefined,
|
|
144
|
+
sorting: enableSorting ? (sorting ?? []) : undefined
|
|
116
145
|
}
|
|
117
146
|
});
|
|
118
147
|
const colCount = tableColumns.length;
|
|
@@ -234,7 +263,9 @@ export function DataTable({ columns, data, loading = false, skeletonRows = 8, lo
|
|
|
234
263
|
? 'No rows'
|
|
235
264
|
: `${rowCount} rows` }), _jsxs(Table, { "aria-busy": loading ? 'true' : undefined, children: [_jsx(TableHeader, { children: table.getHeaderGroups().map((headerGroup) => (_jsx(TableRow, { className: "hover:bg-transparent", children: headerGroup.headers.map((header) => {
|
|
236
265
|
const numeric = header.column.columnDef.meta?.numeric;
|
|
237
|
-
return (_jsx(TableHead, { align: numeric ? 'right' : undefined,
|
|
266
|
+
return (_jsx(TableHead, { align: numeric ? 'right' : undefined, "aria-sort": header.isPlaceholder
|
|
267
|
+
? undefined
|
|
268
|
+
: ariaSortFor(header.column),
|
|
238
269
|
// Only a column that DECLARED sizing gets an inline width;
|
|
239
270
|
// everything else keeps the auto table layout it has today.
|
|
240
271
|
style: readPreferredColumnSize(header.column), className: cn(LABEL_VOICE_CLASS, headDensityClass, header.column.id === SELECTION_COLUMN_ID && 'w-10', headClassName), children: header.isPlaceholder
|
|
@@ -21,6 +21,13 @@ export type DateRangePickerProps = {
|
|
|
21
21
|
fromLabel: ReactNode;
|
|
22
22
|
toLabel: ReactNode;
|
|
23
23
|
invalid?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Marks the range as mandatory. Renders the library's required marker: the
|
|
26
|
+
* literal ' *' appended to both labels, exactly as `FormLabel` does. It is
|
|
27
|
+
* deliberately NOT mirrored as `aria-required` on the triggers: ARIA does not
|
|
28
|
+
* allow that attribute on `role="button"`.
|
|
29
|
+
*/
|
|
30
|
+
required?: boolean;
|
|
24
31
|
/** Wired as aria-describedby on both triggers while `invalid` is set. */
|
|
25
32
|
errorId?: string;
|
|
26
33
|
/** Trigger placeholder when unset. */
|
|
@@ -31,7 +38,18 @@ export type DateRangePickerProps = {
|
|
|
31
38
|
clearLabel?: string;
|
|
32
39
|
/** date-fns locale for the calendar. Defaults to en-US. */
|
|
33
40
|
locale?: CalendarLocale;
|
|
41
|
+
/**
|
|
42
|
+
* Suspends the control. Both segments get the NATIVE `disabled` attribute,
|
|
43
|
+
* not an `aria-disabled` substitute: a trigger whose only job is to open a
|
|
44
|
+
* popover has no state worth keeping focusable, and native `disabled` is
|
|
45
|
+
* what takes it out of the tab order AND keeps the popover shut. That last
|
|
46
|
+
* part matters more than it looks: `PopoverContent` is portaled to
|
|
47
|
+
* `document.body`, so the calendar's Clear button is outside any wrapper a
|
|
48
|
+
* consumer could disable, and the closed popover is the only thing keeping
|
|
49
|
+
* it out of reach.
|
|
50
|
+
*/
|
|
51
|
+
disabled?: boolean;
|
|
34
52
|
};
|
|
35
|
-
export declare function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabel, invalid, errorId, placeholder, ariaLabel, clearLabel, locale }: DateRangePickerProps): import("react").JSX.Element;
|
|
53
|
+
export declare function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabel, invalid, required, errorId, placeholder, ariaLabel, clearLabel, locale, disabled }: DateRangePickerProps): import("react").JSX.Element;
|
|
36
54
|
export {};
|
|
37
55
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/date-range-picker/index.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AASnD;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,cAAc,GAAG;IAC3B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,cAAc,CAAA;IACrB,aAAa,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,SAAS,CAAA;IACpB,OAAO,EAAE,SAAS,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/date-range-picker/index.tsx"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtD,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAA;AASnD;;;;GAIG;AACH,KAAK,cAAc,GAAG,cAAc,CAAC,OAAO,QAAQ,CAAC,CAAC,QAAQ,CAAC,CAAA;AAE/D,MAAM,MAAM,cAAc,GAAG;IAC3B,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAA;IACZ,mCAAmC;IACnC,EAAE,EAAE,MAAM,CAAA;CACX,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,cAAc,CAAA;IACrB,aAAa,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC7C,8EAA8E;IAC9E,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,SAAS,CAAA;IACpB,OAAO,EAAE,SAAS,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,sCAAsC;IACtC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iDAAiD;IACjD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,cAAc,CAAA;IACvB;;;;;;;;;OASG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAkCD,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,aAAa,EACb,MAAM,EACN,IAAI,EACJ,SAAS,EACT,OAAO,EACP,OAAe,EACf,QAAgB,EAChB,OAAO,EACP,WAAwB,EACxB,SAA+B,EAC/B,UAAoB,EACpB,MAAa,EACb,QAAgB,EACjB,EAAE,oBAAoB,+BAgJtB"}
|
|
@@ -3,7 +3,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
3
3
|
/**
|
|
4
4
|
* DateRangePicker — a two-segment popover range control.
|
|
5
5
|
*
|
|
6
|
-
* Two labelled
|
|
6
|
+
* Two labelled trigger segments (from / to) each open the SAME two-month
|
|
7
7
|
* react-day-picker range calendar over the same range selection. The external
|
|
8
8
|
* contract is plain YYYY-MM-DD strings (empty string = unset) so state shapes
|
|
9
9
|
* that speak `date_from`/`date_to` stay untouched. The picker guarantees
|
|
@@ -20,7 +20,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
|
|
|
20
20
|
* popover closed. Each segment is now a real `PopoverTrigger` button: focusable,
|
|
21
21
|
* correctly named, and the element Radix returns focus to on dismissal.
|
|
22
22
|
*/
|
|
23
|
-
import { useState } from 'react';
|
|
23
|
+
import { useEffect, useState } from 'react';
|
|
24
24
|
import { CalendarDays } from 'lucide-react';
|
|
25
25
|
import { enUS } from 'react-day-picker/locale';
|
|
26
26
|
import { Button } from '../../components/ui/button/index.js';
|
|
@@ -59,12 +59,22 @@ function toDayString(value) {
|
|
|
59
59
|
const day = String(value.getDate()).padStart(2, '0');
|
|
60
60
|
return `${year}-${month}-${day}`;
|
|
61
61
|
}
|
|
62
|
-
export function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabel, invalid = false, errorId, placeholder = 'Any date', ariaLabel = 'Select date range', clearLabel = 'Clear', locale = enUS }) {
|
|
62
|
+
export function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel, toLabel, invalid = false, required = false, errorId, placeholder = 'Any date', ariaLabel = 'Select date range', clearLabel = 'Clear', locale = enUS, disabled = false }) {
|
|
63
63
|
// Which segment's popover is open, if any. One root per segment means one open
|
|
64
64
|
// state per segment; holding the identity of the open one here keeps them
|
|
65
65
|
// mutually exclusive, so clicking "to" while "from" is open swaps the anchor
|
|
66
66
|
// instead of stacking two calendars.
|
|
67
67
|
const [openSegment, setOpenSegment] = useState(null);
|
|
68
|
+
// Suspending the control must FORGET which segment was open, not just hide
|
|
69
|
+
// it. The `open` prop below already shuts the popover in the same frame
|
|
70
|
+
// `disabled` flips, but a controlled Radix root never calls `onOpenChange`
|
|
71
|
+
// for a prop-driven close, so the identity survived: lifting `disabled`
|
|
72
|
+
// re-satisfied the same condition and the portaled calendar reopened with no
|
|
73
|
+
// user gesture, pulling focus into it.
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (disabled)
|
|
76
|
+
setOpenSegment(null);
|
|
77
|
+
}, [disabled]);
|
|
68
78
|
const fromDate = parseDay(value.from);
|
|
69
79
|
const toDate = parseDay(value.to);
|
|
70
80
|
const selected = fromDate || toDate ? { from: fromDate, to: toDate } : undefined;
|
|
@@ -78,11 +88,25 @@ export function DateRangePicker({ value, onValueChange, fromId, toId, fromLabel,
|
|
|
78
88
|
to: toDayString(range?.to)
|
|
79
89
|
});
|
|
80
90
|
};
|
|
81
|
-
const triggerClass = cn(
|
|
91
|
+
const triggerClass = cn(
|
|
92
|
+
// border-shadcn-400, not border-input: `--input` is a SURFACE token and is
|
|
93
|
+
// white in the light theme, so the trigger had no visible edge next to the
|
|
94
|
+
// Input and Select it sits with. font-sans, not font-mono: the dates are
|
|
95
|
+
// figures in the body face with tabular figures, like every other figure in
|
|
96
|
+
// the console.
|
|
97
|
+
'border-shadcn-400 bg-card hover:bg-secondary focus-visible:ring-ring flex h-9 items-center gap-2 rounded-md border px-3 text-left font-sans text-sm tabular-nums transition-colors duration-150 ease-out focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none sm:w-40', invalid && 'border-destructive',
|
|
98
|
+
// Conditional rather than `disabled:` variants, matching how this file
|
|
99
|
+
// already applies `border-destructive`: with the prop absent the class
|
|
100
|
+
// string stays byte-identical to what consumers render today.
|
|
101
|
+
disabled && 'cursor-not-allowed opacity-50');
|
|
82
102
|
// The one calendar, rendered inside whichever segment's popover is open. Both
|
|
83
103
|
// segments read and write the SAME range selection, so which one you opened
|
|
84
104
|
// changes only the anchor, never the state.
|
|
85
105
|
const calendar = (_jsxs(_Fragment, { children: [_jsx(Calendar, { mode: "range", numberOfMonths: 2, defaultMonth: fromDate ?? toDate ?? new Date(), selected: selected, onSelect: onSelect, locale: locale }), _jsx("div", { className: "border-border flex items-center justify-end border-t px-3 py-2", children: _jsx(Button, { type: "button", variant: "plain", size: "small", disabled: !hasValue, onClick: () => onValueChange({ from: '', to: '' }), children: clearLabel }) })] }));
|
|
86
|
-
const renderSegment = (segment, id, label, dateValue) => (_jsxs(Popover, {
|
|
106
|
+
const renderSegment = (segment, id, label, dateValue) => (_jsxs(Popover, {
|
|
107
|
+
// A disabled trigger cannot open a popover, but a surface that suspends
|
|
108
|
+
// itself WHILE one is open (a filter bar flipping to "show all") would
|
|
109
|
+
// otherwise leave the portaled calendar on screen with no way back to it.
|
|
110
|
+
open: !disabled && openSegment === segment, onOpenChange: (next) => setOpenSegment(next ? segment : null), children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsxs(Label, { htmlFor: id, children: [label, required ? ' *' : ''] }), _jsxs(PopoverTrigger, { type: "button", id: id, className: triggerClass, disabled: disabled, "aria-invalid": invalid || undefined, "aria-describedby": invalid ? errorId : undefined, children: [_jsx(CalendarDays, { className: "text-muted-foreground size-4 shrink-0", "aria-hidden": true }), dateValue ? (_jsx("span", { children: dateValue })) : (_jsx("span", { className: "text-muted-foreground", children: placeholder }))] })] }), _jsx(PopoverContent, { align: "start", className: "w-auto p-0", "aria-label": ariaLabel, children: calendar })] }, segment));
|
|
87
111
|
return (_jsxs("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-end", children: [renderSegment('from', fromId, fromLabel, value.from), renderSegment('to', toId, toLabel, value.to)] }));
|
|
88
112
|
}
|