@carbon-labs/react-date-picker 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +35 -0
- package/es/_virtual/_rollupPluginBabelHelpers.js +18 -0
- package/es/components/Calendar.d.ts +37 -0
- package/es/components/Calendar.js +267 -0
- package/es/components/DatePicker.d.ts +90 -0
- package/es/components/DatePicker.js +182 -0
- package/es/components/DatePickerInput.d.ts +139 -0
- package/es/components/DatePickerInput.js +149 -0
- package/es/components/DatePickerSkeleton.d.ts +22 -0
- package/es/components/DatePickerSkeleton.js +39 -0
- package/es/hooks/useDatePicker.d.ts +130 -0
- package/es/hooks/useDatePicker.js +364 -0
- package/es/index.d.ts +18 -0
- package/es/index.js +13 -0
- package/lib/_virtual/_rollupPluginBabelHelpers.js +20 -0
- package/lib/components/Calendar.d.ts +37 -0
- package/lib/components/Calendar.js +269 -0
- package/lib/components/DatePicker.d.ts +90 -0
- package/lib/components/DatePicker.js +184 -0
- package/lib/components/DatePickerInput.d.ts +139 -0
- package/lib/components/DatePickerInput.js +151 -0
- package/lib/components/DatePickerSkeleton.d.ts +22 -0
- package/lib/components/DatePickerSkeleton.js +41 -0
- package/lib/hooks/useDatePicker.d.ts +130 -0
- package/lib/hooks/useDatePicker.js +366 -0
- package/lib/index.d.ts +18 -0
- package/lib/index.js +31 -0
- package/package.json +51 -0
- package/scss/date-picker.scss +20 -0
- package/telemetry.yml +6 -0
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2024
|
|
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 React, { useRef, Children, isValidElement, cloneElement } from 'react';
|
|
9
|
+
import classNames from 'classnames';
|
|
10
|
+
import { useDatePicker } from '../hooks/useDatePicker.js';
|
|
11
|
+
import { Calendar } from './Calendar.js';
|
|
12
|
+
import { formatPlainDate } from '@carbon-labs/primitives/date-picker';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* DatePicker component props
|
|
16
|
+
* Maintains 100% backwards compatibility with Carbon React v11 API
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* DatePicker component
|
|
21
|
+
* Main wrapper component that orchestrates date picker functionality
|
|
22
|
+
* Maintains 100% backwards compatibility with Carbon React v11
|
|
23
|
+
*/
|
|
24
|
+
function DatePicker({
|
|
25
|
+
datePickerType = 'single',
|
|
26
|
+
dateFormat = 'm/d/Y',
|
|
27
|
+
minDate,
|
|
28
|
+
maxDate,
|
|
29
|
+
locale = 'en',
|
|
30
|
+
readOnly = false,
|
|
31
|
+
light = false,
|
|
32
|
+
short = false,
|
|
33
|
+
allowInput = true,
|
|
34
|
+
closeOnSelect = true,
|
|
35
|
+
onChange,
|
|
36
|
+
onClose,
|
|
37
|
+
onOpen,
|
|
38
|
+
className,
|
|
39
|
+
children,
|
|
40
|
+
value
|
|
41
|
+
}) {
|
|
42
|
+
const containerRef = useRef(null);
|
|
43
|
+
|
|
44
|
+
// Use Carbon's standard 'cds' prefix to match Carbon's date-picker styles
|
|
45
|
+
const prefix = 'cds';
|
|
46
|
+
|
|
47
|
+
// Use the date picker hook
|
|
48
|
+
const {
|
|
49
|
+
context,
|
|
50
|
+
isOpen,
|
|
51
|
+
selectDate,
|
|
52
|
+
openCalendar,
|
|
53
|
+
closeCalendar,
|
|
54
|
+
handleInputFocus,
|
|
55
|
+
handleInputBlur,
|
|
56
|
+
handleInputChange,
|
|
57
|
+
send,
|
|
58
|
+
startInputRef,
|
|
59
|
+
endInputRef,
|
|
60
|
+
calendarRef
|
|
61
|
+
} = useDatePicker({
|
|
62
|
+
datePickerType,
|
|
63
|
+
value,
|
|
64
|
+
minDate,
|
|
65
|
+
maxDate,
|
|
66
|
+
dateFormat,
|
|
67
|
+
closeOnSelect,
|
|
68
|
+
readOnly,
|
|
69
|
+
onChange,
|
|
70
|
+
onOpen,
|
|
71
|
+
onClose
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Handle calendar navigation
|
|
75
|
+
const handleNavigate = eventType => {
|
|
76
|
+
send(eventType);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Handle calendar icon click - toggle calendar open/close
|
|
80
|
+
const handleIconClick = () => {
|
|
81
|
+
if (isOpen) {
|
|
82
|
+
closeCalendar();
|
|
83
|
+
} else {
|
|
84
|
+
openCalendar();
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// Clone children and inject props
|
|
89
|
+
const childArray = Children.toArray(children);
|
|
90
|
+
const enhancedChildren = childArray.map((child, index) => {
|
|
91
|
+
if (! /*#__PURE__*/isValidElement(child)) {
|
|
92
|
+
return child;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Determine which input this is (start or end for range mode)
|
|
96
|
+
const isStartInput = index === 0;
|
|
97
|
+
const isEndInput = index === 1 && datePickerType === 'range';
|
|
98
|
+
|
|
99
|
+
// Get the appropriate ref
|
|
100
|
+
const inputRef = isStartInput ? startInputRef : isEndInput ? endInputRef : undefined;
|
|
101
|
+
|
|
102
|
+
// Get the appropriate value - always use a string to keep input controlled
|
|
103
|
+
let inputValue = child.props.value ?? '';
|
|
104
|
+
if (inputValue === '') {
|
|
105
|
+
if (isStartInput && context.startDate) {
|
|
106
|
+
inputValue = formatPlainDate(context.startDate, context.dateFormat);
|
|
107
|
+
} else if (isEndInput && context.endDate) {
|
|
108
|
+
inputValue = formatPlainDate(context.endDate, context.dateFormat);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Clone the child with enhanced props
|
|
113
|
+
const enhancedProps = {
|
|
114
|
+
...child.props,
|
|
115
|
+
value: inputValue,
|
|
116
|
+
// Always a string, never undefined
|
|
117
|
+
disabled: child.props.disabled || context.isDisabled,
|
|
118
|
+
readOnly: child.props.readOnly || readOnly,
|
|
119
|
+
onFocus: e => {
|
|
120
|
+
child.props.onFocus?.(e);
|
|
121
|
+
handleInputFocus(isEndInput ? 'to' : 'from');
|
|
122
|
+
},
|
|
123
|
+
onBlur: e => {
|
|
124
|
+
child.props.onBlur?.(e);
|
|
125
|
+
handleInputBlur();
|
|
126
|
+
},
|
|
127
|
+
onChange: e => {
|
|
128
|
+
child.props.onChange?.(e);
|
|
129
|
+
handleInputChange(e.target.value, isEndInput ? 'to' : 'from');
|
|
130
|
+
},
|
|
131
|
+
onIconClick: () => {
|
|
132
|
+
child.props.onIconClick?.();
|
|
133
|
+
handleIconClick();
|
|
134
|
+
},
|
|
135
|
+
hideIcon: datePickerType === 'simple' || child.props.hideIcon
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Wrap each input in a container div with proper Carbon classes
|
|
139
|
+
const containerClasses = classNames(`${prefix}--date-picker-container`, {
|
|
140
|
+
[`${prefix}--date-picker-container--single`]: datePickerType === 'single',
|
|
141
|
+
[`${prefix}--date-picker-container--from`]: isStartInput && datePickerType === 'range',
|
|
142
|
+
[`${prefix}--date-picker-container--to`]: isEndInput && datePickerType === 'range'
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
// Use cloneElement with ref separately to avoid TypeScript issues
|
|
146
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
147
|
+
key: child.props.id,
|
|
148
|
+
className: containerClasses
|
|
149
|
+
}, /*#__PURE__*/cloneElement(child, {
|
|
150
|
+
...enhancedProps,
|
|
151
|
+
// @ts-expect-error - ref is valid but TypeScript doesn't recognize it in cloneElement
|
|
152
|
+
ref: inputRef
|
|
153
|
+
}));
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Generate class names
|
|
157
|
+
const wrapperClasses = classNames(`${prefix}--date-picker`, {
|
|
158
|
+
[`${prefix}--date-picker--simple`]: datePickerType === 'simple',
|
|
159
|
+
[`${prefix}--date-picker--single`]: datePickerType === 'single',
|
|
160
|
+
[`${prefix}--date-picker--range`]: datePickerType === 'range',
|
|
161
|
+
[`${prefix}--date-picker--light`]: light,
|
|
162
|
+
[`${prefix}--date-picker--short`]: short,
|
|
163
|
+
[`${prefix}--date-picker--open`]: isOpen
|
|
164
|
+
}, className);
|
|
165
|
+
|
|
166
|
+
// Don't render calendar for simple mode
|
|
167
|
+
const shouldRenderCalendar = datePickerType !== 'simple' && isOpen;
|
|
168
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
169
|
+
ref: containerRef,
|
|
170
|
+
className: wrapperClasses
|
|
171
|
+
}, enhancedChildren, shouldRenderCalendar && /*#__PURE__*/React.createElement("div", {
|
|
172
|
+
ref: calendarRef,
|
|
173
|
+
className: `${prefix}--date-picker__calendar-container`
|
|
174
|
+
}, /*#__PURE__*/React.createElement(Calendar, {
|
|
175
|
+
context: context,
|
|
176
|
+
onDateSelect: selectDate,
|
|
177
|
+
onNavigate: handleNavigate
|
|
178
|
+
})));
|
|
179
|
+
}
|
|
180
|
+
DatePicker.displayName = 'DatePicker';
|
|
181
|
+
|
|
182
|
+
export { DatePicker };
|
|
@@ -0,0 +1,139 @@
|
|
|
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
|
+
* Icon description for accessibility
|
|
87
|
+
*/
|
|
88
|
+
iconDescription?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Calendar icon click handler
|
|
91
|
+
*/
|
|
92
|
+
onIconClick?: () => void;
|
|
93
|
+
/**
|
|
94
|
+
* Whether to show the calendar icon
|
|
95
|
+
*/
|
|
96
|
+
hideIcon?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* Pattern for input validation
|
|
99
|
+
*/
|
|
100
|
+
pattern?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Type of input
|
|
103
|
+
*/
|
|
104
|
+
type?: string;
|
|
105
|
+
/**
|
|
106
|
+
* Whether the input is read-only
|
|
107
|
+
*/
|
|
108
|
+
readOnly?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* Autocomplete attribute
|
|
111
|
+
*/
|
|
112
|
+
autoComplete?: string;
|
|
113
|
+
/**
|
|
114
|
+
* Name attribute
|
|
115
|
+
*/
|
|
116
|
+
name?: string;
|
|
117
|
+
/**
|
|
118
|
+
* Whether the field is required
|
|
119
|
+
*/
|
|
120
|
+
required?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Callback when calendar opens (for internal use)
|
|
123
|
+
*/
|
|
124
|
+
onOpen?: () => void;
|
|
125
|
+
/**
|
|
126
|
+
* Decorator component (e.g., AI Label)
|
|
127
|
+
*/
|
|
128
|
+
decorator?: React.ReactNode;
|
|
129
|
+
/**
|
|
130
|
+
* @deprecated Use `decorator` instead. Will be removed in next major version.
|
|
131
|
+
*/
|
|
132
|
+
slug?: React.ReactNode;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* DatePickerInput component
|
|
136
|
+
* Input field for date picker with Carbon Design System styling
|
|
137
|
+
* Maintains 100% backwards compatibility with Carbon React v11
|
|
138
|
+
*/
|
|
139
|
+
export declare const DatePickerInput: React.ForwardRefExoticComponent<DatePickerInputProps & React.RefAttributes<HTMLInputElement>>;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2024
|
|
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 { extends as _extends } from '../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
+
import React, { forwardRef, isValidElement, cloneElement } from 'react';
|
|
10
|
+
import classNames from 'classnames';
|
|
11
|
+
|
|
12
|
+
var _span, _svg;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* DatePickerInput component props
|
|
16
|
+
* Maintains 100% backwards compatibility with Carbon React v11 API
|
|
17
|
+
*/
|
|
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 = /*#__PURE__*/forwardRef(function DatePickerInput({
|
|
25
|
+
id,
|
|
26
|
+
labelText,
|
|
27
|
+
placeholder = 'mm/dd/yyyy',
|
|
28
|
+
size = 'md',
|
|
29
|
+
disabled = false,
|
|
30
|
+
invalid = false,
|
|
31
|
+
invalidText,
|
|
32
|
+
warn = false,
|
|
33
|
+
warnText,
|
|
34
|
+
helperText,
|
|
35
|
+
hideLabel = false,
|
|
36
|
+
className,
|
|
37
|
+
value,
|
|
38
|
+
defaultValue,
|
|
39
|
+
onChange,
|
|
40
|
+
onFocus,
|
|
41
|
+
onBlur,
|
|
42
|
+
onKeyDown,
|
|
43
|
+
iconDescription = 'Open calendar',
|
|
44
|
+
onIconClick,
|
|
45
|
+
hideIcon = false,
|
|
46
|
+
pattern,
|
|
47
|
+
type = 'text',
|
|
48
|
+
readOnly = false,
|
|
49
|
+
autoComplete = 'off',
|
|
50
|
+
name,
|
|
51
|
+
required = false,
|
|
52
|
+
onOpen: _onOpen,
|
|
53
|
+
decorator,
|
|
54
|
+
slug,
|
|
55
|
+
...rest
|
|
56
|
+
}, ref) {
|
|
57
|
+
// Use Carbon's standard 'cds' prefix to match Carbon's date-picker styles
|
|
58
|
+
const prefix = 'cds';
|
|
59
|
+
|
|
60
|
+
// Check if decorator/slug is an AILabel component
|
|
61
|
+
const candidate = decorator || slug;
|
|
62
|
+
const isAILabel = candidate && /*#__PURE__*/isValidElement(candidate) && candidate.type?.displayName === 'AILabel';
|
|
63
|
+
|
|
64
|
+
// Clone AILabel with size='mini' if it's an AILabel
|
|
65
|
+
const normalizedDecorator = isAILabel && /*#__PURE__*/isValidElement(candidate) ? /*#__PURE__*/cloneElement(candidate, {
|
|
66
|
+
size: 'mini'
|
|
67
|
+
}) : candidate;
|
|
68
|
+
|
|
69
|
+
// Generate class names following Carbon Design System patterns
|
|
70
|
+
const wrapperClasses = classNames(`${prefix}--date-picker-input__wrapper`, className, {
|
|
71
|
+
[`${prefix}--date-picker-input__wrapper--slug`]: slug,
|
|
72
|
+
[`${prefix}--date-picker-input__wrapper--decorator`]: decorator
|
|
73
|
+
});
|
|
74
|
+
const inputClasses = classNames(`${prefix}--date-picker__input`, {
|
|
75
|
+
[`${prefix}--date-picker__input--sm`]: size === 'sm',
|
|
76
|
+
[`${prefix}--date-picker__input--lg`]: size === 'lg',
|
|
77
|
+
[`${prefix}--date-picker__input--invalid`]: invalid,
|
|
78
|
+
[`${prefix}--date-picker__input--warn`]: warn && !invalid
|
|
79
|
+
});
|
|
80
|
+
const labelClasses = classNames(`${prefix}--label`, {
|
|
81
|
+
[`${prefix}--visually-hidden`]: hideLabel,
|
|
82
|
+
[`${prefix}--label--disabled`]: disabled
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
// Determine which validation message to show
|
|
86
|
+
const showInvalidText = invalid && invalidText;
|
|
87
|
+
const showWarnText = !invalid && warn && warnText;
|
|
88
|
+
const showHelperText = !invalid && !warn && helperText;
|
|
89
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, labelText && /*#__PURE__*/React.createElement("label", {
|
|
90
|
+
htmlFor: id,
|
|
91
|
+
className: labelClasses
|
|
92
|
+
}, labelText, required && (_span || (_span = /*#__PURE__*/React.createElement("span", {
|
|
93
|
+
className: `${prefix}--label__required`
|
|
94
|
+
}, "*")))), /*#__PURE__*/React.createElement("div", {
|
|
95
|
+
className: wrapperClasses
|
|
96
|
+
}, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement("input", _extends({}, rest, {
|
|
97
|
+
ref: ref,
|
|
98
|
+
id: id,
|
|
99
|
+
name: name,
|
|
100
|
+
type: type,
|
|
101
|
+
className: inputClasses,
|
|
102
|
+
placeholder: placeholder,
|
|
103
|
+
value: value,
|
|
104
|
+
defaultValue: defaultValue,
|
|
105
|
+
disabled: disabled,
|
|
106
|
+
readOnly: readOnly,
|
|
107
|
+
pattern: pattern,
|
|
108
|
+
autoComplete: autoComplete,
|
|
109
|
+
required: required,
|
|
110
|
+
onChange: onChange,
|
|
111
|
+
onFocus: onFocus,
|
|
112
|
+
onBlur: onBlur,
|
|
113
|
+
onKeyDown: onKeyDown,
|
|
114
|
+
"aria-invalid": invalid || undefined,
|
|
115
|
+
"aria-describedby": showInvalidText ? `${id}-error` : showWarnText ? `${id}-warn` : showHelperText ? `${id}-helper` : undefined
|
|
116
|
+
})), slug ? normalizedDecorator : decorator ? /*#__PURE__*/React.createElement("div", {
|
|
117
|
+
className: `${prefix}--date-picker-input-inner-wrapper--decorator`
|
|
118
|
+
}, normalizedDecorator) : null, !hideIcon && /*#__PURE__*/React.createElement("button", {
|
|
119
|
+
type: "button",
|
|
120
|
+
className: `${prefix}--date-picker__icon`,
|
|
121
|
+
onClick: onIconClick,
|
|
122
|
+
disabled: disabled || readOnly,
|
|
123
|
+
"aria-label": iconDescription,
|
|
124
|
+
tabIndex: -1
|
|
125
|
+
}, _svg || (_svg = /*#__PURE__*/React.createElement("svg", {
|
|
126
|
+
focusable: "false",
|
|
127
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
128
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
129
|
+
fill: "currentColor",
|
|
130
|
+
width: "16",
|
|
131
|
+
height: "16",
|
|
132
|
+
viewBox: "0 0 32 32",
|
|
133
|
+
"aria-hidden": "true"
|
|
134
|
+
}, /*#__PURE__*/React.createElement("path", {
|
|
135
|
+
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"
|
|
136
|
+
})))))), showInvalidText && /*#__PURE__*/React.createElement("div", {
|
|
137
|
+
id: `${id}-error`,
|
|
138
|
+
className: `${prefix}--form-requirement`
|
|
139
|
+
}, invalidText), showWarnText && /*#__PURE__*/React.createElement("div", {
|
|
140
|
+
id: `${id}-warn`,
|
|
141
|
+
className: `${prefix}--form-requirement`
|
|
142
|
+
}, warnText), showHelperText && /*#__PURE__*/React.createElement("div", {
|
|
143
|
+
id: `${id}-helper`,
|
|
144
|
+
className: `${prefix}--form__helper-text`
|
|
145
|
+
}, helperText));
|
|
146
|
+
});
|
|
147
|
+
DatePickerInput.displayName = 'DatePickerInput';
|
|
148
|
+
|
|
149
|
+
export { DatePickerInput };
|
|
@@ -0,0 +1,22 @@
|
|
|
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
|
+
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;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2024
|
|
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 React from 'react';
|
|
9
|
+
|
|
10
|
+
var _div, _div2;
|
|
11
|
+
/**
|
|
12
|
+
* DatePickerSkeleton component for loading states
|
|
13
|
+
*/
|
|
14
|
+
const DatePickerSkeleton = ({
|
|
15
|
+
range = false,
|
|
16
|
+
className
|
|
17
|
+
}) => {
|
|
18
|
+
// Use 'cds' prefix to match Carbon's skeleton styles
|
|
19
|
+
const prefix = 'cds';
|
|
20
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
21
|
+
className: `${prefix}--form-item`
|
|
22
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
23
|
+
className: `${prefix}--date-picker ${prefix}--date-picker--${range ? 'range' : 'single'} ${prefix}--skeleton ${className || ''}`
|
|
24
|
+
}, _div || (_div = /*#__PURE__*/React.createElement("div", {
|
|
25
|
+
className: `${prefix}--date-picker-container`
|
|
26
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
27
|
+
className: `${prefix}--label ${prefix}--skeleton`
|
|
28
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
29
|
+
className: `${prefix}--date-picker__input ${prefix}--skeleton`
|
|
30
|
+
}))), range && (_div2 || (_div2 = /*#__PURE__*/React.createElement("div", {
|
|
31
|
+
className: `${prefix}--date-picker-container`
|
|
32
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
33
|
+
className: `${prefix}--label ${prefix}--skeleton`
|
|
34
|
+
}), /*#__PURE__*/React.createElement("div", {
|
|
35
|
+
className: `${prefix}--date-picker__input ${prefix}--skeleton`
|
|
36
|
+
}))))));
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export { DatePickerSkeleton };
|
|
@@ -0,0 +1,130 @@
|
|
|
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 { DatePickerState, type DatePickerContext } from '@carbon-labs/primitives/date-picker';
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for the useDatePicker hook
|
|
10
|
+
* Maintains 100% backwards compatibility with Carbon React v11 API
|
|
11
|
+
*/
|
|
12
|
+
export interface UseDatePickerConfig {
|
|
13
|
+
/**
|
|
14
|
+
* The type of date picker (Carbon API uses datePickerType, not mode)
|
|
15
|
+
*/
|
|
16
|
+
datePickerType?: 'simple' | 'single' | 'range';
|
|
17
|
+
/**
|
|
18
|
+
* Initial value as ISO date string
|
|
19
|
+
*/
|
|
20
|
+
value?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Minimum selectable date (mm/dd/yyyy format - Carbon API)
|
|
23
|
+
*/
|
|
24
|
+
minDate?: string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Maximum selectable date (mm/dd/yyyy format - Carbon API)
|
|
27
|
+
*/
|
|
28
|
+
maxDate?: string | null;
|
|
29
|
+
/**
|
|
30
|
+
* Date format string (Flatpickr-compatible format)
|
|
31
|
+
*/
|
|
32
|
+
dateFormat?: string;
|
|
33
|
+
/**
|
|
34
|
+
* Whether to allow manual input
|
|
35
|
+
*/
|
|
36
|
+
allowInput?: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Whether to close calendar on date selection
|
|
39
|
+
*/
|
|
40
|
+
closeOnSelect?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether the picker is disabled
|
|
43
|
+
*/
|
|
44
|
+
disabled?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Whether the picker is read-only (Carbon uses readOnly, not readonly)
|
|
47
|
+
*/
|
|
48
|
+
readOnly?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Locale for date formatting
|
|
51
|
+
*/
|
|
52
|
+
locale?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Change handler - receives array of Date objects (Carbon API)
|
|
55
|
+
*/
|
|
56
|
+
onChange?: (dates: Date[]) => void;
|
|
57
|
+
/**
|
|
58
|
+
* Open handler
|
|
59
|
+
*/
|
|
60
|
+
onOpen?: () => void;
|
|
61
|
+
/**
|
|
62
|
+
* Close handler
|
|
63
|
+
*/
|
|
64
|
+
onClose?: () => void;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Return type for the useDatePicker hook
|
|
68
|
+
*/
|
|
69
|
+
export interface UseDatePickerReturn {
|
|
70
|
+
/**
|
|
71
|
+
* Current state machine context
|
|
72
|
+
*/
|
|
73
|
+
context: DatePickerContext;
|
|
74
|
+
/**
|
|
75
|
+
* Current state
|
|
76
|
+
*/
|
|
77
|
+
state: DatePickerState;
|
|
78
|
+
/**
|
|
79
|
+
* Whether the calendar is open
|
|
80
|
+
*/
|
|
81
|
+
isOpen: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Send an event to the state machine
|
|
84
|
+
*/
|
|
85
|
+
send: (eventType: string, payload?: any) => void;
|
|
86
|
+
/**
|
|
87
|
+
* Open the calendar
|
|
88
|
+
*/
|
|
89
|
+
openCalendar: () => void;
|
|
90
|
+
/**
|
|
91
|
+
* Close the calendar
|
|
92
|
+
*/
|
|
93
|
+
closeCalendar: () => void;
|
|
94
|
+
/**
|
|
95
|
+
* Select a date
|
|
96
|
+
*/
|
|
97
|
+
selectDate: (date: Temporal.PlainDate) => void;
|
|
98
|
+
/**
|
|
99
|
+
* Handle input focus
|
|
100
|
+
*/
|
|
101
|
+
handleInputFocus: (inputType?: 'from' | 'to') => void;
|
|
102
|
+
/**
|
|
103
|
+
* Handle input blur
|
|
104
|
+
*/
|
|
105
|
+
handleInputBlur: () => void;
|
|
106
|
+
/**
|
|
107
|
+
* Handle input value change
|
|
108
|
+
*/
|
|
109
|
+
handleInputChange: (value: string, inputType?: 'from' | 'to') => void;
|
|
110
|
+
/**
|
|
111
|
+
* Ref for the start input
|
|
112
|
+
*/
|
|
113
|
+
startInputRef: React.RefObject<HTMLInputElement>;
|
|
114
|
+
/**
|
|
115
|
+
* Ref for the end input (range mode)
|
|
116
|
+
*/
|
|
117
|
+
endInputRef: React.RefObject<HTMLInputElement>;
|
|
118
|
+
/**
|
|
119
|
+
* Ref for the calendar container
|
|
120
|
+
*/
|
|
121
|
+
calendarRef: React.RefObject<HTMLDivElement>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* React hook for managing date picker state using the shared state machine
|
|
125
|
+
* Maintains 100% backwards compatibility with Carbon React v11 API
|
|
126
|
+
*
|
|
127
|
+
* @param {UseDatePickerConfig} config - Configuration options
|
|
128
|
+
* @returns {UseDatePickerReturn} Hook return object with state and handlers
|
|
129
|
+
*/
|
|
130
|
+
export declare function useDatePicker(config?: UseDatePickerConfig): UseDatePickerReturn;
|