@carbon/react 1.113.0 → 1.114.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +962 -962
- package/es/components/Card/Card.d.ts +48 -0
- package/es/components/Card/Card.js +148 -0
- package/es/components/Card/Card.types.d.ts +88 -0
- package/es/components/Card/CardAction.d.ts +37 -0
- package/es/components/Card/CardAction.js +32 -0
- package/es/components/Card/CardActions.d.ts +30 -0
- package/es/components/Card/CardActions.js +93 -0
- package/es/components/Card/CardBody.d.ts +11 -0
- package/es/components/Card/CardBody.js +34 -0
- package/es/components/Card/CardContext.d.ts +17 -0
- package/es/components/Card/CardContext.js +31 -0
- package/es/components/Card/CardFooter.d.ts +11 -0
- package/es/components/Card/CardFooter.js +34 -0
- package/es/components/Card/CardHeader.d.ts +11 -0
- package/es/components/Card/CardHeader.js +44 -0
- package/es/components/Card/CardHeaderMedia.d.ts +21 -0
- package/es/components/Card/CardHeaderMedia.js +24 -0
- package/es/components/Card/CardMedia.d.ts +35 -0
- package/es/components/Card/CardMedia.js +42 -0
- package/es/components/Card/CardTitle.d.ts +72 -0
- package/es/components/Card/CardTitle.js +86 -0
- package/es/components/Card/CardTitleMedia.d.ts +23 -0
- package/es/components/Card/CardTitleMedia.js +36 -0
- package/es/components/Card/_story-assets/data.d.ts +6 -0
- package/es/components/Card/_story-assets/options.d.ts +47 -0
- package/es/components/Card/index.d.ts +8 -0
- package/es/components/Card/index.js +33 -0
- package/es/components/Checkbox/Checkbox.js +1 -1
- package/es/components/CheckboxGroup/CheckboxGroup.js +1 -1
- package/es/components/ComboBox/ComboBox.js +2 -2
- package/es/components/ComboButton/index.js +1 -1
- package/es/components/ComposedModal/ComposedModal.js +1 -1
- package/es/components/DatePicker/DatePicker.d.ts +10 -0
- package/es/components/DatePicker/DatePicker.js +7 -6
- package/es/components/DatePicker/next/components/Calendar.d.ts +40 -0
- package/es/components/DatePicker/next/components/Calendar.js +181 -0
- package/es/components/DatePicker/next/components/DatePicker.d.ts +86 -0
- package/es/components/DatePicker/next/components/DatePicker.js +147 -0
- package/es/components/DatePicker/next/components/DatePickerInput.d.ts +143 -0
- package/es/components/DatePicker/next/components/DatePickerInput.js +124 -0
- package/es/components/DatePicker/next/components/DatePickerSkeleton.d.ts +22 -0
- package/es/components/DatePicker/next/components/DatePickerSkeleton.js +32 -0
- package/es/components/DatePicker/next/hooks/useDatePicker.d.ts +144 -0
- package/es/components/DatePicker/next/hooks/useDatePicker.js +286 -0
- package/es/components/DatePicker/next/index.d.ts +12 -0
- package/es/components/DatePicker/next/index.js +19 -0
- package/es/components/DatePickerInput/DatePickerInput.js +1 -1
- package/es/components/Dropdown/Dropdown.js +2 -2
- package/es/components/ExpandableSearch/ExpandableSearch.js +1 -1
- package/es/components/MenuButton/index.js +1 -1
- package/es/components/MultiSelect/FilterableMultiSelect.js +2 -2
- package/es/components/MultiSelect/MultiSelect.js +2 -2
- package/es/components/NumberInput/NumberInput.js +2 -2
- package/es/components/OverflowMenu/next/index.js +1 -1
- package/es/components/RadioButton/RadioButton.js +1 -1
- package/es/components/RadioButtonGroup/RadioButtonGroup.js +1 -1
- package/es/components/Select/Select.js +1 -1
- package/es/components/Tag/SelectableTag.js +1 -1
- package/es/components/TextArea/TextArea.js +1 -1
- package/es/components/TextInput/TextInput.js +1 -1
- package/es/index.d.ts +2 -0
- package/es/index.js +7 -5
- package/es/internal/checkForOverflow.d.ts +5 -0
- package/es/internal/useFocus.d.ts +23 -0
- package/es/internal/usePrefersReducedMotion.d.ts +11 -0
- package/es/internal/useSidePanelPresence.d.ts +21 -0
- package/lib/components/Card/Card.d.ts +48 -0
- package/lib/components/Card/Card.js +161 -0
- package/lib/components/Card/Card.types.d.ts +88 -0
- package/lib/components/Card/CardAction.d.ts +37 -0
- package/lib/components/Card/CardAction.js +41 -0
- package/lib/components/Card/CardActions.d.ts +30 -0
- package/lib/components/Card/CardActions.js +96 -0
- package/lib/components/Card/CardBody.d.ts +11 -0
- package/lib/components/Card/CardBody.js +37 -0
- package/lib/components/Card/CardContext.d.ts +17 -0
- package/lib/components/Card/CardContext.js +32 -0
- package/lib/components/Card/CardFooter.d.ts +11 -0
- package/lib/components/Card/CardFooter.js +37 -0
- package/lib/components/Card/CardHeader.d.ts +11 -0
- package/lib/components/Card/CardHeader.js +47 -0
- package/lib/components/Card/CardHeaderMedia.d.ts +21 -0
- package/lib/components/Card/CardHeaderMedia.js +33 -0
- package/lib/components/Card/CardMedia.d.ts +35 -0
- package/lib/components/Card/CardMedia.js +51 -0
- package/lib/components/Card/CardTitle.d.ts +72 -0
- package/lib/components/Card/CardTitle.js +89 -0
- package/lib/components/Card/CardTitleMedia.d.ts +23 -0
- package/lib/components/Card/CardTitleMedia.js +39 -0
- package/lib/components/Card/_story-assets/data.d.ts +6 -0
- package/lib/components/Card/_story-assets/options.d.ts +47 -0
- package/lib/components/Card/index.d.ts +8 -0
- package/lib/components/Card/index.js +48 -0
- package/lib/components/Checkbox/Checkbox.js +1 -1
- package/lib/components/CheckboxGroup/CheckboxGroup.js +1 -1
- package/lib/components/ComboBox/ComboBox.js +2 -2
- package/lib/components/ComboButton/index.js +1 -1
- package/lib/components/ComposedModal/ComposedModal.js +1 -1
- package/lib/components/DatePicker/DatePicker.d.ts +10 -0
- package/lib/components/DatePicker/DatePicker.js +7 -6
- package/lib/components/DatePicker/next/components/Calendar.d.ts +40 -0
- package/lib/components/DatePicker/next/components/Calendar.js +184 -0
- package/lib/components/DatePicker/next/components/DatePicker.d.ts +86 -0
- package/lib/components/DatePicker/next/components/DatePicker.js +150 -0
- package/lib/components/DatePicker/next/components/DatePickerInput.d.ts +143 -0
- package/lib/components/DatePicker/next/components/DatePickerInput.js +127 -0
- package/lib/components/DatePicker/next/components/DatePickerSkeleton.d.ts +22 -0
- package/lib/components/DatePicker/next/components/DatePickerSkeleton.js +41 -0
- package/lib/components/DatePicker/next/hooks/useDatePicker.d.ts +144 -0
- package/lib/components/DatePicker/next/hooks/useDatePicker.js +286 -0
- package/lib/components/DatePicker/next/index.d.ts +12 -0
- package/lib/components/DatePicker/next/index.js +27 -0
- package/lib/components/DatePickerInput/DatePickerInput.js +1 -1
- package/lib/components/Dropdown/Dropdown.js +2 -2
- package/lib/components/ExpandableSearch/ExpandableSearch.js +1 -1
- package/lib/components/MenuButton/index.js +1 -1
- package/lib/components/MultiSelect/FilterableMultiSelect.js +2 -2
- package/lib/components/MultiSelect/MultiSelect.js +2 -2
- package/lib/components/NumberInput/NumberInput.js +2 -2
- package/lib/components/OverflowMenu/next/index.js +1 -1
- package/lib/components/RadioButton/RadioButton.js +1 -1
- package/lib/components/RadioButtonGroup/RadioButtonGroup.js +1 -1
- package/lib/components/Select/Select.js +1 -1
- package/lib/components/Tag/SelectableTag.js +1 -1
- package/lib/components/TextArea/TextArea.js +1 -1
- package/lib/components/TextInput/TextInput.js +1 -1
- package/lib/index.d.ts +2 -0
- package/lib/index.js +59 -45
- package/lib/internal/checkForOverflow.d.ts +5 -0
- package/lib/internal/useFocus.d.ts +23 -0
- package/lib/internal/usePrefersReducedMotion.d.ts +11 -0
- package/lib/internal/useSidePanelPresence.d.ts +21 -0
- package/package.json +11 -11
- package/scss/components/action-set/_action-set.scss +9 -0
- package/scss/components/action-set/_index.scss +9 -0
- package/scss/components/resizer/_index.scss +9 -0
- package/scss/components/resizer/_resizer.scss +9 -0
- package/scss/components/side-panel/_index.scss +9 -0
- package/scss/components/side-panel/_side-panel.scss +9 -0
- package/scss/components/truncated-text/_index.scss +9 -0
- package/scss/components/truncated-text/_truncated-text.scss +9 -0
- package/telemetry.yml +57 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2026
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { usePrefix } from "../../../../internal/usePrefix.js";
|
|
9
|
+
import { useCallback, useMemo, useState } from "react";
|
|
10
|
+
import cx from "classnames";
|
|
11
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
import { generateCalendarGrid, getFullDateLabel, getMonthYearLabel, getWeekdayLabels } from "@carbon/utilities/date-picker";
|
|
13
|
+
//#region src/components/DatePicker/next/components/Calendar.tsx
|
|
14
|
+
/**
|
|
15
|
+
* Copyright IBM Corp. 2026
|
|
16
|
+
*
|
|
17
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
18
|
+
* LICENSE file in the root directory of this source tree.
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Calendar component
|
|
22
|
+
* Renders a calendar grid for date selection
|
|
23
|
+
*/
|
|
24
|
+
function Calendar({ context, onDateSelect, onNavigate, className, locale = "en" }) {
|
|
25
|
+
const prefix = usePrefix();
|
|
26
|
+
const { viewDate, startDate, endDate, minDate, maxDate, focusedDate, mode } = context;
|
|
27
|
+
const [hoveredDate, setHoveredDate] = useState(null);
|
|
28
|
+
const calendarGrid = useMemo(() => {
|
|
29
|
+
if (!viewDate) return [];
|
|
30
|
+
return generateCalendarGrid(viewDate, minDate, maxDate);
|
|
31
|
+
}, [
|
|
32
|
+
viewDate,
|
|
33
|
+
minDate,
|
|
34
|
+
maxDate
|
|
35
|
+
]);
|
|
36
|
+
const handlePrevMonth = useCallback(() => {
|
|
37
|
+
onNavigate("PREV_MONTH");
|
|
38
|
+
}, [onNavigate]);
|
|
39
|
+
const handleNextMonth = useCallback(() => {
|
|
40
|
+
onNavigate("NEXT_MONTH");
|
|
41
|
+
}, [onNavigate]);
|
|
42
|
+
const handleDateClick = useCallback((date, isDisabled) => {
|
|
43
|
+
if (!isDisabled) onDateSelect(date);
|
|
44
|
+
}, [onDateSelect]);
|
|
45
|
+
const isDateSelected = useCallback((date) => {
|
|
46
|
+
if (!startDate) return false;
|
|
47
|
+
if (Temporal.PlainDate.compare(date, startDate) === 0) return true;
|
|
48
|
+
if (endDate && Temporal.PlainDate.compare(date, endDate) === 0) return true;
|
|
49
|
+
return false;
|
|
50
|
+
}, [startDate, endDate]);
|
|
51
|
+
const isDateInRange = useCallback((date) => {
|
|
52
|
+
if (mode !== "range" || !startDate) return false;
|
|
53
|
+
if (endDate) return Temporal.PlainDate.compare(date, startDate) > 0 && Temporal.PlainDate.compare(date, endDate) < 0;
|
|
54
|
+
const previewDate = hoveredDate || focusedDate;
|
|
55
|
+
if (previewDate) {
|
|
56
|
+
if (minDate && Temporal.PlainDate.compare(previewDate, minDate) < 0 || maxDate && Temporal.PlainDate.compare(previewDate, maxDate) > 0) return false;
|
|
57
|
+
const earlierDate = Temporal.PlainDate.compare(startDate, previewDate) < 0 ? startDate : previewDate;
|
|
58
|
+
const laterDate = Temporal.PlainDate.compare(startDate, previewDate) < 0 ? previewDate : startDate;
|
|
59
|
+
return Temporal.PlainDate.compare(date, earlierDate) > 0 && Temporal.PlainDate.compare(date, laterDate) < 0;
|
|
60
|
+
}
|
|
61
|
+
return false;
|
|
62
|
+
}, [
|
|
63
|
+
mode,
|
|
64
|
+
startDate,
|
|
65
|
+
endDate,
|
|
66
|
+
hoveredDate,
|
|
67
|
+
focusedDate,
|
|
68
|
+
minDate,
|
|
69
|
+
maxDate
|
|
70
|
+
]);
|
|
71
|
+
const isDateFocused = useCallback((date) => {
|
|
72
|
+
if (!focusedDate) return false;
|
|
73
|
+
return Temporal.PlainDate.compare(date, focusedDate) === 0;
|
|
74
|
+
}, [focusedDate]);
|
|
75
|
+
if (!viewDate) return null;
|
|
76
|
+
const calendarClasses = cx(`${prefix}--date-picker__calendar`, className);
|
|
77
|
+
const monthYear = getMonthYearLabel(viewDate, locale);
|
|
78
|
+
const weekdayLabels = getWeekdayLabels(locale);
|
|
79
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
80
|
+
className: calendarClasses,
|
|
81
|
+
role: "grid",
|
|
82
|
+
"aria-label": "Calendar",
|
|
83
|
+
tabIndex: 0,
|
|
84
|
+
children: [
|
|
85
|
+
/* @__PURE__ */ jsxs("div", {
|
|
86
|
+
className: `${prefix}--date-picker__month`,
|
|
87
|
+
children: [
|
|
88
|
+
/* @__PURE__ */ jsx("button", {
|
|
89
|
+
type: "button",
|
|
90
|
+
className: `${prefix}--date-picker__month-nav`,
|
|
91
|
+
onClick: handlePrevMonth,
|
|
92
|
+
"aria-label": "Previous month",
|
|
93
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
94
|
+
focusable: "false",
|
|
95
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
96
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
97
|
+
fill: "currentColor",
|
|
98
|
+
width: "16",
|
|
99
|
+
height: "16",
|
|
100
|
+
viewBox: "0 0 16 16",
|
|
101
|
+
"aria-hidden": "true",
|
|
102
|
+
children: /* @__PURE__ */ jsx("path", {
|
|
103
|
+
d: "M11 8l-5 5-.7-.7L9.6 8 5.3 3.7 6 3z",
|
|
104
|
+
transform: "rotate(180 8 8)"
|
|
105
|
+
})
|
|
106
|
+
})
|
|
107
|
+
}),
|
|
108
|
+
/* @__PURE__ */ jsx("div", {
|
|
109
|
+
className: `${prefix}--date-picker__current-month`,
|
|
110
|
+
children: monthYear
|
|
111
|
+
}),
|
|
112
|
+
/* @__PURE__ */ jsx("button", {
|
|
113
|
+
type: "button",
|
|
114
|
+
className: `${prefix}--date-picker__month-nav`,
|
|
115
|
+
onClick: handleNextMonth,
|
|
116
|
+
"aria-label": "Next month",
|
|
117
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
118
|
+
focusable: "false",
|
|
119
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
120
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
121
|
+
fill: "currentColor",
|
|
122
|
+
width: "16",
|
|
123
|
+
height: "16",
|
|
124
|
+
viewBox: "0 0 16 16",
|
|
125
|
+
"aria-hidden": "true",
|
|
126
|
+
children: /* @__PURE__ */ jsx("path", { d: "M11 8l-5 5-.7-.7L9.6 8 5.3 3.7 6 3z" })
|
|
127
|
+
})
|
|
128
|
+
})
|
|
129
|
+
]
|
|
130
|
+
}),
|
|
131
|
+
/* @__PURE__ */ jsx("div", {
|
|
132
|
+
className: `${prefix}--date-picker__weekdays`,
|
|
133
|
+
children: weekdayLabels.map((day, index) => /* @__PURE__ */ jsx("div", {
|
|
134
|
+
className: `${prefix}--date-picker__weekday`,
|
|
135
|
+
title: day,
|
|
136
|
+
children: day
|
|
137
|
+
}, index))
|
|
138
|
+
}),
|
|
139
|
+
/* @__PURE__ */ jsx("div", {
|
|
140
|
+
className: `${prefix}--date-picker__days`,
|
|
141
|
+
children: calendarGrid.flat().map((dayCell, index) => {
|
|
142
|
+
const { date, isCurrentMonth, isDisabled, isToday } = dayCell;
|
|
143
|
+
const selected = isDateSelected(date);
|
|
144
|
+
const inRange = isDateInRange(date);
|
|
145
|
+
const focused = isDateFocused(date);
|
|
146
|
+
return /* @__PURE__ */ jsx("button", {
|
|
147
|
+
type: "button",
|
|
148
|
+
className: cx(`${prefix}--date-picker__day`, {
|
|
149
|
+
today: isToday,
|
|
150
|
+
selected,
|
|
151
|
+
inRange,
|
|
152
|
+
prevMonthDay: !isCurrentMonth && date.month < viewDate.month,
|
|
153
|
+
nextMonthDay: !isCurrentMonth && date.month > viewDate.month,
|
|
154
|
+
disabled: isDisabled,
|
|
155
|
+
focused
|
|
156
|
+
}),
|
|
157
|
+
onMouseDown: (event) => {
|
|
158
|
+
event.preventDefault();
|
|
159
|
+
},
|
|
160
|
+
onMouseEnter: () => {
|
|
161
|
+
if (mode === "range" && startDate && !endDate) setHoveredDate(date);
|
|
162
|
+
},
|
|
163
|
+
onMouseLeave: () => {
|
|
164
|
+
setHoveredDate(null);
|
|
165
|
+
},
|
|
166
|
+
onClick: () => handleDateClick(date, isDisabled),
|
|
167
|
+
disabled: isDisabled,
|
|
168
|
+
"aria-label": getFullDateLabel(date, locale),
|
|
169
|
+
"aria-pressed": selected || void 0,
|
|
170
|
+
"aria-current": isToday ? "date" : void 0,
|
|
171
|
+
tabIndex: focused ? 0 : -1,
|
|
172
|
+
children: date.day
|
|
173
|
+
}, index);
|
|
174
|
+
})
|
|
175
|
+
})
|
|
176
|
+
]
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
Calendar.displayName = "Calendar";
|
|
180
|
+
//#endregion
|
|
181
|
+
export { Calendar };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2026
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
/**
|
|
9
|
+
* DatePicker component props
|
|
10
|
+
* Maintains 100% backwards compatibility with Carbon React v11 API
|
|
11
|
+
*/
|
|
12
|
+
export interface DatePickerProps {
|
|
13
|
+
/**
|
|
14
|
+
* The type of date picker
|
|
15
|
+
*/
|
|
16
|
+
datePickerType?: 'simple' | 'single' | 'range';
|
|
17
|
+
/**
|
|
18
|
+
* The date format string
|
|
19
|
+
*/
|
|
20
|
+
dateFormat?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Minimum selectable date (mm/dd/yyyy format)
|
|
23
|
+
*/
|
|
24
|
+
minDate?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Maximum selectable date (mm/dd/yyyy format)
|
|
27
|
+
*/
|
|
28
|
+
maxDate?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Locale for date formatting
|
|
31
|
+
*/
|
|
32
|
+
locale?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Whether the picker is read-only
|
|
35
|
+
*/
|
|
36
|
+
readOnly?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Whether to use the light variant
|
|
39
|
+
*/
|
|
40
|
+
light?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether to use the short variant
|
|
43
|
+
*/
|
|
44
|
+
short?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Whether to allow manual input
|
|
47
|
+
*/
|
|
48
|
+
allowInput?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Whether to close calendar on date selection
|
|
51
|
+
*/
|
|
52
|
+
closeOnSelect?: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Change handler - receives array of Date objects
|
|
55
|
+
*/
|
|
56
|
+
onChange?: (dates: Date[]) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Close handler
|
|
59
|
+
*/
|
|
60
|
+
onClose?: () => void;
|
|
61
|
+
/**
|
|
62
|
+
* Open handler
|
|
63
|
+
*/
|
|
64
|
+
onOpen?: () => void;
|
|
65
|
+
/**
|
|
66
|
+
* Additional CSS class names
|
|
67
|
+
*/
|
|
68
|
+
className?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Children (DatePickerInput components)
|
|
71
|
+
*/
|
|
72
|
+
children?: React.ReactNode;
|
|
73
|
+
/**
|
|
74
|
+
* Initial value
|
|
75
|
+
*/
|
|
76
|
+
value?: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* DatePicker component
|
|
80
|
+
* Main wrapper component that orchestrates date picker functionality
|
|
81
|
+
* Maintains 100% backwards compatibility with Carbon React v11
|
|
82
|
+
*/
|
|
83
|
+
export declare function DatePicker({ datePickerType, dateFormat, minDate, maxDate, locale, readOnly, light, short, allowInput, closeOnSelect, onChange, onClose, onOpen, className, children, value, }: DatePickerProps): import("react/jsx-runtime").JSX.Element;
|
|
84
|
+
export declare namespace DatePicker {
|
|
85
|
+
var displayName: string;
|
|
86
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2026
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { usePrefix } from "../../../../internal/usePrefix.js";
|
|
9
|
+
import { useDatePicker } from "../hooks/useDatePicker.js";
|
|
10
|
+
import { Calendar } from "./Calendar.js";
|
|
11
|
+
import React, { Children, isValidElement, useRef } from "react";
|
|
12
|
+
import cx from "classnames";
|
|
13
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
14
|
+
import { formatPlainDate } from "@carbon/utilities/date-picker";
|
|
15
|
+
//#region src/components/DatePicker/next/components/DatePicker.tsx
|
|
16
|
+
/**
|
|
17
|
+
* Copyright IBM Corp. 2026
|
|
18
|
+
*
|
|
19
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
20
|
+
* LICENSE file in the root directory of this source tree.
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* DatePicker component
|
|
24
|
+
* Main wrapper component that orchestrates date picker functionality
|
|
25
|
+
* Maintains 100% backwards compatibility with Carbon React v11
|
|
26
|
+
*/
|
|
27
|
+
function DatePicker({ datePickerType = "single", dateFormat = "m/d/Y", minDate, maxDate, locale = "en", readOnly = false, light = false, short = false, allowInput = true, closeOnSelect = true, onChange, onClose, onOpen, className, children, value }) {
|
|
28
|
+
const containerRef = useRef(null);
|
|
29
|
+
const prefix = usePrefix();
|
|
30
|
+
const { context, isOpen, selectDate, openCalendar, closeCalendar, handleInputFocus, handleInputBlur, handleInputChange, send, startInputRef, endInputRef, calendarRef, exitSentinelRef, handleExitSentinelFocus } = useDatePicker({
|
|
31
|
+
datePickerType,
|
|
32
|
+
value,
|
|
33
|
+
minDate,
|
|
34
|
+
maxDate,
|
|
35
|
+
dateFormat,
|
|
36
|
+
allowInput,
|
|
37
|
+
closeOnSelect,
|
|
38
|
+
readOnly,
|
|
39
|
+
locale,
|
|
40
|
+
onChange,
|
|
41
|
+
onOpen,
|
|
42
|
+
onClose
|
|
43
|
+
});
|
|
44
|
+
const handleNavigate = (eventType) => {
|
|
45
|
+
send(eventType);
|
|
46
|
+
};
|
|
47
|
+
const handleIconClick = () => {
|
|
48
|
+
if (isOpen) closeCalendar();
|
|
49
|
+
else openCalendar();
|
|
50
|
+
};
|
|
51
|
+
const enhancedChildren = Children.toArray(children).map((child, index) => {
|
|
52
|
+
if (!isValidElement(child)) return child;
|
|
53
|
+
const isStartInput = index === 0;
|
|
54
|
+
const isEndInput = index === 1 && datePickerType === "range";
|
|
55
|
+
const inputRef = isStartInput ? startInputRef : isEndInput ? endInputRef : void 0;
|
|
56
|
+
let inputValue = child.props.value ?? "";
|
|
57
|
+
if (inputValue === "") {
|
|
58
|
+
if (isStartInput && context.startDate) inputValue = formatPlainDate(context.startDate, context.dateFormat);
|
|
59
|
+
else if (isEndInput && context.endDate) inputValue = formatPlainDate(context.endDate, context.dateFormat);
|
|
60
|
+
}
|
|
61
|
+
const enhancedProps = {
|
|
62
|
+
...child.props,
|
|
63
|
+
value: inputValue,
|
|
64
|
+
disabled: child.props.disabled || context.isDisabled,
|
|
65
|
+
readOnly: child.props.readOnly || readOnly,
|
|
66
|
+
onFocus: (e) => {
|
|
67
|
+
child.props.onFocus?.(e);
|
|
68
|
+
handleInputFocus(isEndInput ? "to" : "from");
|
|
69
|
+
},
|
|
70
|
+
onBlur: (e) => {
|
|
71
|
+
child.props.onBlur?.(e);
|
|
72
|
+
handleInputBlur();
|
|
73
|
+
},
|
|
74
|
+
onChange: (e) => {
|
|
75
|
+
child.props.onChange?.(e);
|
|
76
|
+
handleInputChange(e.target.value, isEndInput ? "to" : "from");
|
|
77
|
+
},
|
|
78
|
+
onClick: (e) => {
|
|
79
|
+
child.props.onClick?.(e);
|
|
80
|
+
if (!isOpen) openCalendar();
|
|
81
|
+
},
|
|
82
|
+
onKeyDown: (e) => {
|
|
83
|
+
child.props.onKeyDown?.(e);
|
|
84
|
+
if (!e.defaultPrevented && e.key === "Tab" && !e.shiftKey && !isOpen) {
|
|
85
|
+
e.preventDefault();
|
|
86
|
+
openCalendar();
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
onIconClick: () => {
|
|
90
|
+
child.props.onIconClick?.();
|
|
91
|
+
handleIconClick();
|
|
92
|
+
},
|
|
93
|
+
hideIcon: datePickerType === "simple" || child.props.hideIcon
|
|
94
|
+
};
|
|
95
|
+
return /* @__PURE__ */ jsx("div", {
|
|
96
|
+
className: cx(`${prefix}--date-picker-container`, {
|
|
97
|
+
[`${prefix}--date-picker-container--single`]: datePickerType === "single",
|
|
98
|
+
[`${prefix}--date-picker-container--from`]: isStartInput && datePickerType === "range",
|
|
99
|
+
[`${prefix}--date-picker-container--to`]: isEndInput && datePickerType === "range"
|
|
100
|
+
}),
|
|
101
|
+
children: React.createElement(child.type, {
|
|
102
|
+
...child.props,
|
|
103
|
+
...enhancedProps,
|
|
104
|
+
ref: inputRef
|
|
105
|
+
})
|
|
106
|
+
}, child.props.id);
|
|
107
|
+
});
|
|
108
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
109
|
+
ref: containerRef,
|
|
110
|
+
className: cx(`${prefix}--date-picker`, `${prefix}--date-picker--next`, {
|
|
111
|
+
[`${prefix}--date-picker--simple`]: datePickerType === "simple",
|
|
112
|
+
[`${prefix}--date-picker--single`]: datePickerType === "single",
|
|
113
|
+
[`${prefix}--date-picker--range`]: datePickerType === "range",
|
|
114
|
+
[`${prefix}--date-picker--light`]: light,
|
|
115
|
+
[`${prefix}--date-picker--short`]: short,
|
|
116
|
+
[`${prefix}--date-picker--open`]: isOpen
|
|
117
|
+
}, className),
|
|
118
|
+
children: [
|
|
119
|
+
enhancedChildren,
|
|
120
|
+
datePickerType !== "simple" && isOpen && /* @__PURE__ */ jsx("div", {
|
|
121
|
+
ref: calendarRef,
|
|
122
|
+
className: `${prefix}--date-picker__calendar-container`,
|
|
123
|
+
children: /* @__PURE__ */ jsx(Calendar, {
|
|
124
|
+
context,
|
|
125
|
+
onDateSelect: selectDate,
|
|
126
|
+
onNavigate: handleNavigate,
|
|
127
|
+
locale
|
|
128
|
+
})
|
|
129
|
+
}),
|
|
130
|
+
/* @__PURE__ */ jsx("span", {
|
|
131
|
+
ref: exitSentinelRef,
|
|
132
|
+
tabIndex: -1,
|
|
133
|
+
"aria-hidden": true,
|
|
134
|
+
onFocus: handleExitSentinelFocus,
|
|
135
|
+
style: {
|
|
136
|
+
position: "absolute",
|
|
137
|
+
width: 0,
|
|
138
|
+
height: 0,
|
|
139
|
+
overflow: "hidden"
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
]
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
DatePicker.displayName = "DatePicker";
|
|
146
|
+
//#endregion
|
|
147
|
+
export { DatePicker };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2026
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
/**
|
|
9
|
+
* DatePickerInput component props
|
|
10
|
+
* Maintains 100% backwards compatibility with Carbon React v11 API
|
|
11
|
+
*/
|
|
12
|
+
export interface DatePickerInputProps {
|
|
13
|
+
/**
|
|
14
|
+
* The unique identifier for the input (required)
|
|
15
|
+
*/
|
|
16
|
+
id: string;
|
|
17
|
+
/**
|
|
18
|
+
* The label text
|
|
19
|
+
*/
|
|
20
|
+
labelText?: React.ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* The placeholder text
|
|
23
|
+
*/
|
|
24
|
+
placeholder?: string;
|
|
25
|
+
/**
|
|
26
|
+
* The input size
|
|
27
|
+
*/
|
|
28
|
+
size?: 'sm' | 'md' | 'lg';
|
|
29
|
+
/**
|
|
30
|
+
* Whether the input is disabled
|
|
31
|
+
*/
|
|
32
|
+
disabled?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Whether the input is invalid
|
|
35
|
+
*/
|
|
36
|
+
invalid?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* The invalid text to display
|
|
39
|
+
*/
|
|
40
|
+
invalidText?: React.ReactNode;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the input has a warning
|
|
43
|
+
*/
|
|
44
|
+
warn?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* The warning text to display
|
|
47
|
+
*/
|
|
48
|
+
warnText?: React.ReactNode;
|
|
49
|
+
/**
|
|
50
|
+
* Helper text to display below the input
|
|
51
|
+
*/
|
|
52
|
+
helperText?: React.ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* Whether to hide the label visually (still accessible)
|
|
55
|
+
*/
|
|
56
|
+
hideLabel?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Additional CSS class names
|
|
59
|
+
*/
|
|
60
|
+
className?: string;
|
|
61
|
+
/**
|
|
62
|
+
* The input value
|
|
63
|
+
*/
|
|
64
|
+
value?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Default value for uncontrolled component
|
|
67
|
+
*/
|
|
68
|
+
defaultValue?: string;
|
|
69
|
+
/**
|
|
70
|
+
* Change handler
|
|
71
|
+
*/
|
|
72
|
+
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
73
|
+
/**
|
|
74
|
+
* Focus handler
|
|
75
|
+
*/
|
|
76
|
+
onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
|
|
77
|
+
/**
|
|
78
|
+
* Blur handler
|
|
79
|
+
*/
|
|
80
|
+
onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Keydown handler
|
|
83
|
+
*/
|
|
84
|
+
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
|
|
85
|
+
/**
|
|
86
|
+
* Click handler
|
|
87
|
+
*/
|
|
88
|
+
onClick?: (event: React.MouseEvent<HTMLInputElement>) => void;
|
|
89
|
+
/**
|
|
90
|
+
* Icon description for accessibility
|
|
91
|
+
*/
|
|
92
|
+
iconDescription?: string;
|
|
93
|
+
/**
|
|
94
|
+
* Calendar icon click handler
|
|
95
|
+
*/
|
|
96
|
+
onIconClick?: () => void;
|
|
97
|
+
/**
|
|
98
|
+
* Whether to show the calendar icon
|
|
99
|
+
*/
|
|
100
|
+
hideIcon?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Pattern for input validation
|
|
103
|
+
*/
|
|
104
|
+
pattern?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Type of input
|
|
107
|
+
*/
|
|
108
|
+
type?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Whether the input is read-only
|
|
111
|
+
*/
|
|
112
|
+
readOnly?: boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Autocomplete attribute
|
|
115
|
+
*/
|
|
116
|
+
autoComplete?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Name attribute
|
|
119
|
+
*/
|
|
120
|
+
name?: string;
|
|
121
|
+
/**
|
|
122
|
+
* Whether the field is required
|
|
123
|
+
*/
|
|
124
|
+
required?: boolean;
|
|
125
|
+
/**
|
|
126
|
+
* Callback when calendar opens (for internal use)
|
|
127
|
+
*/
|
|
128
|
+
onOpen?: () => void;
|
|
129
|
+
/**
|
|
130
|
+
* Decorator component (e.g., AI Label)
|
|
131
|
+
*/
|
|
132
|
+
decorator?: React.ReactNode;
|
|
133
|
+
/**
|
|
134
|
+
* @deprecated Use `decorator` instead. Will be removed in next major version.
|
|
135
|
+
*/
|
|
136
|
+
slug?: React.ReactNode;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* DatePickerInput component
|
|
140
|
+
* Input field for date picker with Carbon Design System styling
|
|
141
|
+
* Maintains 100% backwards compatibility with Carbon React v11
|
|
142
|
+
*/
|
|
143
|
+
export declare const DatePickerInput: React.ForwardRefExoticComponent<DatePickerInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2026
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { usePrefix } from "../../../../internal/usePrefix.js";
|
|
9
|
+
import { cloneElement, forwardRef, isValidElement } from "react";
|
|
10
|
+
import cx from "classnames";
|
|
11
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
+
//#region src/components/DatePicker/next/components/DatePickerInput.tsx
|
|
13
|
+
/**
|
|
14
|
+
* Copyright IBM Corp. 2026
|
|
15
|
+
*
|
|
16
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
17
|
+
* LICENSE file in the root directory of this source tree.
|
|
18
|
+
*/
|
|
19
|
+
/**
|
|
20
|
+
* DatePickerInput component
|
|
21
|
+
* Input field for date picker with Carbon Design System styling
|
|
22
|
+
* Maintains 100% backwards compatibility with Carbon React v11
|
|
23
|
+
*/
|
|
24
|
+
const DatePickerInput = forwardRef(function DatePickerInput({ id, labelText, placeholder = "mm/dd/yyyy", size = "md", disabled = false, invalid = false, invalidText, warn = false, warnText, helperText, hideLabel = false, className, value, defaultValue, onChange, onFocus, onBlur, onKeyDown, onClick, iconDescription = "Open calendar", onIconClick, hideIcon = false, pattern, type = "text", readOnly = false, autoComplete = "off", name, required = false, onOpen: _onOpen, decorator, slug, ...rest }, ref) {
|
|
25
|
+
const prefix = usePrefix();
|
|
26
|
+
const candidate = decorator || slug;
|
|
27
|
+
const normalizedDecorator = candidate && isValidElement(candidate) && candidate.type?.displayName === "AILabel" && isValidElement(candidate) ? cloneElement(candidate, { size: "mini" }) : candidate;
|
|
28
|
+
const wrapperClasses = cx(`${prefix}--date-picker-input__wrapper`, className, {
|
|
29
|
+
[`${prefix}--date-picker-input__wrapper--slug`]: slug,
|
|
30
|
+
[`${prefix}--date-picker-input__wrapper--decorator`]: decorator
|
|
31
|
+
});
|
|
32
|
+
const inputClasses = cx(`${prefix}--date-picker__input`, {
|
|
33
|
+
[`${prefix}--date-picker__input--sm`]: size === "sm",
|
|
34
|
+
[`${prefix}--date-picker__input--lg`]: size === "lg",
|
|
35
|
+
[`${prefix}--date-picker__input--invalid`]: invalid,
|
|
36
|
+
[`${prefix}--date-picker__input--warn`]: warn && !invalid
|
|
37
|
+
});
|
|
38
|
+
const labelClasses = cx(`${prefix}--label`, {
|
|
39
|
+
[`${prefix}--visually-hidden`]: hideLabel,
|
|
40
|
+
[`${prefix}--label--disabled`]: disabled
|
|
41
|
+
});
|
|
42
|
+
const showInvalidText = invalid && invalidText;
|
|
43
|
+
const showWarnText = !invalid && warn && warnText;
|
|
44
|
+
const showHelperText = !invalid && !warn && helperText;
|
|
45
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
46
|
+
labelText && /* @__PURE__ */ jsxs("label", {
|
|
47
|
+
htmlFor: id,
|
|
48
|
+
className: labelClasses,
|
|
49
|
+
children: [labelText, required && /* @__PURE__ */ jsx("span", {
|
|
50
|
+
className: `${prefix}--label__required`,
|
|
51
|
+
children: "*"
|
|
52
|
+
})]
|
|
53
|
+
}),
|
|
54
|
+
/* @__PURE__ */ jsx("div", {
|
|
55
|
+
className: wrapperClasses,
|
|
56
|
+
children: /* @__PURE__ */ jsxs("span", { children: [
|
|
57
|
+
/* @__PURE__ */ jsx("input", {
|
|
58
|
+
...rest,
|
|
59
|
+
ref,
|
|
60
|
+
id,
|
|
61
|
+
name,
|
|
62
|
+
type,
|
|
63
|
+
className: inputClasses,
|
|
64
|
+
placeholder,
|
|
65
|
+
value,
|
|
66
|
+
defaultValue,
|
|
67
|
+
disabled,
|
|
68
|
+
readOnly,
|
|
69
|
+
pattern,
|
|
70
|
+
autoComplete,
|
|
71
|
+
required,
|
|
72
|
+
onChange,
|
|
73
|
+
onFocus,
|
|
74
|
+
onBlur,
|
|
75
|
+
onKeyDown,
|
|
76
|
+
onClick,
|
|
77
|
+
"aria-invalid": invalid || void 0,
|
|
78
|
+
"aria-describedby": showInvalidText ? `${id}-error` : showWarnText ? `${id}-warn` : showHelperText ? `${id}-helper` : void 0
|
|
79
|
+
}),
|
|
80
|
+
slug ? normalizedDecorator : decorator ? /* @__PURE__ */ jsx("div", {
|
|
81
|
+
className: `${prefix}--date-picker-input-inner-wrapper--decorator`,
|
|
82
|
+
children: normalizedDecorator
|
|
83
|
+
}) : null,
|
|
84
|
+
!hideIcon && /* @__PURE__ */ jsx("button", {
|
|
85
|
+
type: "button",
|
|
86
|
+
className: `${prefix}--date-picker__icon`,
|
|
87
|
+
onClick: onIconClick,
|
|
88
|
+
disabled: disabled || readOnly,
|
|
89
|
+
"aria-label": iconDescription,
|
|
90
|
+
tabIndex: -1,
|
|
91
|
+
children: /* @__PURE__ */ jsx("svg", {
|
|
92
|
+
focusable: "false",
|
|
93
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
94
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
95
|
+
fill: "currentColor",
|
|
96
|
+
width: "16",
|
|
97
|
+
height: "16",
|
|
98
|
+
viewBox: "0 0 32 32",
|
|
99
|
+
"aria-hidden": "true",
|
|
100
|
+
children: /* @__PURE__ */ jsx("path", { d: "M26,4h-4V2h-2v2h-8V2h-2v2H6C4.9,4,4,4.9,4,6v20c0,1.1,0.9,2,2,2h20c1.1,0,2-0.9,2-2V6C28,4.9,27.1,4,26,4z M26,26H6V12h20 V26z M26,10H6V6h4v2h2V6h8v2h2V6h4V10z" })
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
] })
|
|
104
|
+
}),
|
|
105
|
+
showInvalidText && /* @__PURE__ */ jsx("div", {
|
|
106
|
+
id: `${id}-error`,
|
|
107
|
+
className: `${prefix}--form-requirement`,
|
|
108
|
+
children: invalidText
|
|
109
|
+
}),
|
|
110
|
+
showWarnText && /* @__PURE__ */ jsx("div", {
|
|
111
|
+
id: `${id}-warn`,
|
|
112
|
+
className: `${prefix}--form-requirement`,
|
|
113
|
+
children: warnText
|
|
114
|
+
}),
|
|
115
|
+
showHelperText && /* @__PURE__ */ jsx("div", {
|
|
116
|
+
id: `${id}-helper`,
|
|
117
|
+
className: `${prefix}--form__helper-text`,
|
|
118
|
+
children: helperText
|
|
119
|
+
})
|
|
120
|
+
] });
|
|
121
|
+
});
|
|
122
|
+
DatePickerInput.displayName = "DatePickerInput";
|
|
123
|
+
//#endregion
|
|
124
|
+
export { DatePickerInput };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2026
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
export interface DatePickerSkeletonProps {
|
|
9
|
+
/**
|
|
10
|
+
* Specify whether the skeleton should be a range date picker
|
|
11
|
+
*/
|
|
12
|
+
range?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Additional CSS class names
|
|
15
|
+
*/
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* DatePickerSkeleton component for loading states
|
|
20
|
+
*/
|
|
21
|
+
export declare const DatePickerSkeleton: React.FC<DatePickerSkeletonProps>;
|
|
22
|
+
export default DatePickerSkeleton;
|