mtrl 0.2.5 → 0.2.7
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/index.ts +18 -0
- package/package.json +1 -1
- package/src/components/badge/_styles.scss +123 -115
- package/src/components/badge/api.ts +57 -59
- package/src/components/badge/badge.ts +16 -2
- package/src/components/badge/config.ts +65 -11
- package/src/components/badge/constants.ts +22 -12
- package/src/components/badge/features.ts +44 -40
- package/src/components/badge/types.ts +42 -30
- package/src/components/bottom-app-bar/_styles.scss +103 -0
- package/src/components/bottom-app-bar/bottom-app-bar.ts +196 -0
- package/src/components/bottom-app-bar/config.ts +73 -0
- package/src/components/bottom-app-bar/index.ts +11 -0
- package/src/components/bottom-app-bar/types.ts +108 -0
- package/src/components/button/_styles.scss +0 -66
- package/src/components/button/api.ts +5 -0
- package/src/components/button/button.ts +0 -2
- package/src/components/button/config.ts +5 -0
- package/src/components/button/constants.ts +0 -6
- package/src/components/button/index.ts +2 -2
- package/src/components/button/types.ts +7 -7
- package/src/components/card/_styles.scss +67 -25
- package/src/components/card/api.ts +54 -3
- package/src/components/card/card.ts +25 -6
- package/src/components/card/config.ts +189 -22
- package/src/components/card/constants.ts +20 -19
- package/src/components/card/content.ts +299 -2
- package/src/components/card/features.ts +158 -4
- package/src/components/card/index.ts +31 -9
- package/src/components/card/types.ts +166 -15
- package/src/components/checkbox/_styles.scss +0 -2
- package/src/components/chip/chip.ts +1 -9
- package/src/components/chip/constants.ts +0 -10
- package/src/components/chip/index.ts +1 -1
- package/src/components/chip/types.ts +1 -4
- package/src/components/datepicker/_styles.scss +358 -0
- package/src/components/datepicker/api.ts +272 -0
- package/src/components/datepicker/config.ts +144 -0
- package/src/components/datepicker/constants.ts +98 -0
- package/src/components/datepicker/datepicker.ts +346 -0
- package/src/components/datepicker/index.ts +9 -0
- package/src/components/datepicker/render.ts +452 -0
- package/src/components/datepicker/types.ts +268 -0
- package/src/components/datepicker/utils.ts +290 -0
- package/src/components/dialog/_styles.scss +174 -128
- package/src/components/dialog/api.ts +48 -13
- package/src/components/dialog/config.ts +9 -5
- package/src/components/dialog/dialog.ts +6 -3
- package/src/components/dialog/features.ts +290 -130
- package/src/components/dialog/types.ts +7 -4
- package/src/components/divider/_styles.scss +57 -0
- package/src/components/divider/config.ts +81 -0
- package/src/components/divider/divider.ts +37 -0
- package/src/components/divider/features.ts +207 -0
- package/src/components/divider/index.ts +5 -0
- package/src/components/divider/types.ts +55 -0
- package/src/components/extended-fab/_styles.scss +267 -0
- package/src/components/extended-fab/api.ts +141 -0
- package/src/components/extended-fab/config.ts +108 -0
- package/src/components/extended-fab/constants.ts +36 -0
- package/src/components/extended-fab/extended-fab.ts +125 -0
- package/src/components/extended-fab/index.ts +4 -0
- package/src/components/extended-fab/types.ts +287 -0
- package/src/components/fab/_styles.scss +225 -0
- package/src/components/fab/api.ts +97 -0
- package/src/components/fab/config.ts +94 -0
- package/src/components/fab/constants.ts +41 -0
- package/src/components/fab/fab.ts +67 -0
- package/src/components/fab/index.ts +4 -0
- package/src/components/fab/types.ts +234 -0
- package/src/components/navigation/_styles.scss +1 -0
- package/src/components/navigation/api.ts +78 -50
- package/src/components/navigation/features/items.ts +280 -0
- package/src/components/navigation/nav-item.ts +72 -23
- package/src/components/navigation/navigation.ts +54 -2
- package/src/components/navigation/types.ts +210 -188
- package/src/components/progress/_styles.scss +0 -65
- package/src/components/progress/config.ts +1 -2
- package/src/components/progress/constants.ts +0 -14
- package/src/components/progress/index.ts +1 -1
- package/src/components/progress/progress.ts +1 -4
- package/src/components/progress/types.ts +1 -4
- package/src/components/radios/_styles.scss +0 -45
- package/src/components/radios/api.ts +85 -60
- package/src/components/radios/config.ts +1 -2
- package/src/components/radios/constants.ts +0 -9
- package/src/components/radios/index.ts +1 -1
- package/src/components/radios/radio.ts +34 -11
- package/src/components/radios/radios.ts +2 -1
- package/src/components/radios/types.ts +1 -7
- package/src/components/search/_styles.scss +306 -0
- package/src/components/search/api.ts +203 -0
- package/src/components/search/config.ts +87 -0
- package/src/components/search/constants.ts +21 -0
- package/src/components/search/features/index.ts +4 -0
- package/src/components/search/features/search.ts +718 -0
- package/src/components/search/features/states.ts +165 -0
- package/src/components/search/features/structure.ts +198 -0
- package/src/components/search/index.ts +10 -0
- package/src/components/search/search.ts +52 -0
- package/src/components/search/types.ts +163 -0
- package/src/components/segmented-button/_styles.scss +117 -0
- package/src/components/segmented-button/config.ts +67 -0
- package/src/components/segmented-button/constants.ts +42 -0
- package/src/components/segmented-button/index.ts +4 -0
- package/src/components/segmented-button/segment.ts +155 -0
- package/src/components/segmented-button/segmented-button.ts +250 -0
- package/src/components/segmented-button/types.ts +219 -0
- package/src/components/slider/_styles.scss +221 -168
- package/src/components/slider/accessibility.md +59 -0
- package/src/components/slider/api.ts +41 -120
- package/src/components/slider/config.ts +51 -49
- package/src/components/slider/features/handlers.ts +495 -0
- package/src/components/slider/features/index.ts +1 -2
- package/src/components/slider/features/slider.ts +66 -84
- package/src/components/slider/features/states.ts +195 -0
- package/src/components/slider/features/structure.ts +141 -184
- package/src/components/slider/features/ui.ts +150 -201
- package/src/components/slider/index.ts +2 -11
- package/src/components/slider/slider.ts +9 -12
- package/src/components/slider/types.ts +39 -24
- package/src/components/switch/_styles.scss +0 -2
- package/src/components/tabs/_styles.scss +346 -154
- package/src/components/tabs/api.ts +178 -400
- package/src/components/tabs/config.ts +46 -52
- package/src/components/tabs/constants.ts +85 -8
- package/src/components/tabs/features.ts +403 -0
- package/src/components/tabs/index.ts +60 -3
- package/src/components/tabs/indicator.ts +285 -0
- package/src/components/tabs/responsive.ts +144 -0
- package/src/components/tabs/scroll-indicators.ts +149 -0
- package/src/components/tabs/state.ts +186 -0
- package/src/components/tabs/tab-api.ts +258 -0
- package/src/components/tabs/tab.ts +255 -0
- package/src/components/tabs/tabs.ts +50 -31
- package/src/components/tabs/types.ts +332 -128
- package/src/components/tabs/utils.ts +107 -0
- package/src/components/textfield/_styles.scss +0 -98
- package/src/components/textfield/config.ts +2 -3
- package/src/components/textfield/constants.ts +0 -14
- package/src/components/textfield/index.ts +2 -2
- package/src/components/textfield/textfield.ts +0 -2
- package/src/components/textfield/types.ts +1 -4
- package/src/components/timepicker/README.md +277 -0
- package/src/components/timepicker/_styles.scss +451 -0
- package/src/components/timepicker/api.ts +632 -0
- package/src/components/timepicker/clockdial.ts +482 -0
- package/src/components/timepicker/config.ts +130 -0
- package/src/components/timepicker/constants.ts +138 -0
- package/src/components/timepicker/index.ts +8 -0
- package/src/components/timepicker/render.ts +613 -0
- package/src/components/timepicker/timepicker.ts +117 -0
- package/src/components/timepicker/types.ts +336 -0
- package/src/components/timepicker/utils.ts +241 -0
- package/src/components/top-app-bar/_styles.scss +225 -0
- package/src/components/top-app-bar/config.ts +83 -0
- package/src/components/top-app-bar/index.ts +11 -0
- package/src/components/top-app-bar/top-app-bar.ts +316 -0
- package/src/components/top-app-bar/types.ts +140 -0
- package/src/core/build/_ripple.scss +6 -6
- package/src/core/build/ripple.ts +72 -95
- package/src/core/compose/component.ts +1 -1
- package/src/core/compose/features/badge.ts +79 -0
- package/src/core/compose/features/icon.ts +3 -1
- package/src/core/compose/features/index.ts +3 -1
- package/src/core/compose/features/ripple.ts +4 -1
- package/src/core/compose/features/textlabel.ts +26 -2
- package/src/core/dom/create.ts +5 -0
- package/src/index.ts +9 -0
- package/src/styles/abstract/_theme.scss +115 -3
- package/src/styles/themes/_autumn.scss +21 -0
- package/src/styles/themes/_base-theme.scss +61 -0
- package/src/styles/themes/_baseline.scss +58 -0
- package/src/styles/themes/_bluekhaki.scss +125 -0
- package/src/styles/themes/_brownbeige.scss +125 -0
- package/src/styles/themes/_browngreen.scss +125 -0
- package/src/styles/themes/_forest.scss +6 -0
- package/src/styles/themes/_greenbeige.scss +125 -0
- package/src/styles/themes/_material.scss +125 -0
- package/src/styles/themes/_ocean.scss +6 -0
- package/src/styles/themes/_sageivory.scss +125 -0
- package/src/styles/themes/_spring.scss +6 -0
- package/src/styles/themes/_summer.scss +5 -0
- package/src/styles/themes/_sunset.scss +5 -0
- package/src/styles/themes/_tealcaramel.scss +125 -0
- package/src/styles/themes/_winter.scss +6 -0
- package/src/components/card/actions.ts +0 -48
- package/src/components/card/header.ts +0 -88
- package/src/components/card/media.ts +0 -52
- package/src/components/navigation/features/items.js +0 -192
- package/src/components/slider/features/appearance.ts +0 -94
- package/src/components/slider/features/disabled.ts +0 -43
- package/src/components/slider/features/events.ts +0 -164
- package/src/components/slider/features/interactions.ts +0 -261
- package/src/components/slider/features/keyboard.ts +0 -112
- package/src/core/collection/adapters/mongodb.js +0 -232
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// src/components/datepicker/config.ts
|
|
2
|
+
import {
|
|
3
|
+
createComponentConfig,
|
|
4
|
+
createElementConfig,
|
|
5
|
+
BaseComponentConfig
|
|
6
|
+
} from '../../core/config/component-config';
|
|
7
|
+
import { DatePickerConfig } from './types';
|
|
8
|
+
import {
|
|
9
|
+
DATEPICKER_VARIANTS,
|
|
10
|
+
DATEPICKER_VIEWS,
|
|
11
|
+
DATEPICKER_SELECTION_MODES,
|
|
12
|
+
DEFAULT_DATE_FORMAT
|
|
13
|
+
} from './constants';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Default configuration for the DatePicker component
|
|
17
|
+
*/
|
|
18
|
+
export const defaultConfig: DatePickerConfig = {
|
|
19
|
+
variant: DATEPICKER_VARIANTS.DOCKED,
|
|
20
|
+
initialView: DATEPICKER_VIEWS.DAY,
|
|
21
|
+
selectionMode: DATEPICKER_SELECTION_MODES.SINGLE,
|
|
22
|
+
dateFormat: DEFAULT_DATE_FORMAT,
|
|
23
|
+
animate: true
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Creates the base configuration for DatePicker component
|
|
28
|
+
* @param {DatePickerConfig} config - User provided configuration
|
|
29
|
+
* @returns {DatePickerConfig} Complete configuration with defaults applied
|
|
30
|
+
*/
|
|
31
|
+
export const createBaseConfig = (config: DatePickerConfig = {}): DatePickerConfig => {
|
|
32
|
+
const baseConfig = createComponentConfig(defaultConfig, config, 'datepicker') as DatePickerConfig;
|
|
33
|
+
|
|
34
|
+
// Set closeOnSelect default based on variant
|
|
35
|
+
if (baseConfig.closeOnSelect === undefined) {
|
|
36
|
+
baseConfig.closeOnSelect = baseConfig.variant !== DATEPICKER_VARIANTS.DOCKED;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return baseConfig;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Generates element configuration for the DatePicker container
|
|
44
|
+
* @param {DatePickerConfig} config - DatePicker configuration
|
|
45
|
+
* @returns {Object} Element configuration object for withElement
|
|
46
|
+
*/
|
|
47
|
+
export const getContainerConfig = (config: DatePickerConfig) => {
|
|
48
|
+
return createElementConfig(config, {
|
|
49
|
+
tag: 'div',
|
|
50
|
+
attrs: {
|
|
51
|
+
role: 'application',
|
|
52
|
+
'aria-label': 'Date Picker',
|
|
53
|
+
tabindex: '-1'
|
|
54
|
+
},
|
|
55
|
+
className: [
|
|
56
|
+
`${config.prefix}-datepicker-container`,
|
|
57
|
+
config.class
|
|
58
|
+
],
|
|
59
|
+
forwardEvents: {
|
|
60
|
+
keydown: true,
|
|
61
|
+
click: true
|
|
62
|
+
},
|
|
63
|
+
interactive: true
|
|
64
|
+
});
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Generates element configuration for the input field
|
|
69
|
+
* @param {DatePickerConfig} config - DatePicker configuration
|
|
70
|
+
* @returns {Object} Element configuration object for input field
|
|
71
|
+
*/
|
|
72
|
+
export const getInputConfig = (config: DatePickerConfig) => {
|
|
73
|
+
// Create the attributes object
|
|
74
|
+
const attrs: Record<string, any> = {
|
|
75
|
+
type: 'text',
|
|
76
|
+
placeholder: config.placeholder || config.dateFormat,
|
|
77
|
+
autocomplete: 'off',
|
|
78
|
+
readonly: true
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Only add disabled attribute if it's explicitly true
|
|
82
|
+
if (config.disabled === true) {
|
|
83
|
+
attrs.disabled = true;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return createElementConfig(config, {
|
|
87
|
+
tag: 'input',
|
|
88
|
+
attrs,
|
|
89
|
+
className: `${config.prefix}-datepicker-input`,
|
|
90
|
+
forwardEvents: {
|
|
91
|
+
focus: true,
|
|
92
|
+
blur: true,
|
|
93
|
+
click: true
|
|
94
|
+
},
|
|
95
|
+
interactive: true
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Generates element configuration for the calendar container
|
|
101
|
+
* @param {DatePickerConfig} config - DatePicker configuration
|
|
102
|
+
* @returns {Object} Element configuration object for calendar container
|
|
103
|
+
*/
|
|
104
|
+
export const getCalendarConfig = (config: DatePickerConfig) => {
|
|
105
|
+
return createElementConfig(config, {
|
|
106
|
+
tag: 'div',
|
|
107
|
+
attrs: {
|
|
108
|
+
role: 'dialog',
|
|
109
|
+
'aria-modal': config.variant !== DATEPICKER_VARIANTS.DOCKED ? 'true' : 'false'
|
|
110
|
+
},
|
|
111
|
+
className: [
|
|
112
|
+
`${config.prefix}-datepicker-calendar`,
|
|
113
|
+
`${config.prefix}-datepicker-${config.variant}`,
|
|
114
|
+
config.selectionMode === DATEPICKER_SELECTION_MODES.RANGE ?
|
|
115
|
+
`${config.prefix}-datepicker-range` : ''
|
|
116
|
+
],
|
|
117
|
+
forwardEvents: {
|
|
118
|
+
keydown: true,
|
|
119
|
+
click: true
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Creates API configuration for the DatePicker component
|
|
126
|
+
* @param {Object} comp - Component with features like disabled and lifecycle
|
|
127
|
+
* @returns {Object} API configuration object
|
|
128
|
+
*/
|
|
129
|
+
export const getApiConfig = (comp: any) => ({
|
|
130
|
+
disabled: {
|
|
131
|
+
enable: () => comp.disabled.enable(),
|
|
132
|
+
disable: () => comp.disabled.disable()
|
|
133
|
+
},
|
|
134
|
+
lifecycle: {
|
|
135
|
+
destroy: () => comp.lifecycle.destroy()
|
|
136
|
+
},
|
|
137
|
+
events: {
|
|
138
|
+
on: comp.on,
|
|
139
|
+
off: comp.off,
|
|
140
|
+
emit: comp.emit
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
export default defaultConfig;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// src/components/datepicker/constants.ts
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* DatePicker variant types
|
|
5
|
+
*/
|
|
6
|
+
export const DATEPICKER_VARIANTS = {
|
|
7
|
+
/** Displays inline with a text field above the calendar */
|
|
8
|
+
DOCKED: 'docked',
|
|
9
|
+
|
|
10
|
+
/** Displays as a modal dialog */
|
|
11
|
+
MODAL: 'modal',
|
|
12
|
+
|
|
13
|
+
/** Displays as a modal dialog with text input */
|
|
14
|
+
MODAL_INPUT: 'modal-input'
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* DatePicker view types
|
|
19
|
+
*/
|
|
20
|
+
export const DATEPICKER_VIEWS = {
|
|
21
|
+
/** Calendar day selection view */
|
|
22
|
+
DAY: 'day',
|
|
23
|
+
|
|
24
|
+
/** Month selection view */
|
|
25
|
+
MONTH: 'month',
|
|
26
|
+
|
|
27
|
+
/** Year selection view */
|
|
28
|
+
YEAR: 'year'
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* DatePicker selection modes
|
|
33
|
+
*/
|
|
34
|
+
export const DATEPICKER_SELECTION_MODES = {
|
|
35
|
+
/** Single date selection */
|
|
36
|
+
SINGLE: 'single',
|
|
37
|
+
|
|
38
|
+
/** Date range selection */
|
|
39
|
+
RANGE: 'range'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Day names for the calendar
|
|
44
|
+
*/
|
|
45
|
+
export const DAY_NAMES = ['S', 'M', 'T', 'W', 'T', 'F', 'S'];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Month names for the calendar
|
|
49
|
+
*/
|
|
50
|
+
export const MONTH_NAMES = [
|
|
51
|
+
'January', 'February', 'March', 'April',
|
|
52
|
+
'May', 'June', 'July', 'August',
|
|
53
|
+
'September', 'October', 'November', 'December'
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Month names abbreviated
|
|
58
|
+
*/
|
|
59
|
+
export const MONTH_NAMES_SHORT = [
|
|
60
|
+
'Jan', 'Feb', 'Mar', 'Apr',
|
|
61
|
+
'May', 'Jun', 'Jul', 'Aug',
|
|
62
|
+
'Sep', 'Oct', 'Nov', 'Dec'
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Default format for displaying dates
|
|
67
|
+
*/
|
|
68
|
+
export const DEFAULT_DATE_FORMAT = 'MM/DD/YYYY';
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* CSS class name for today's date
|
|
72
|
+
*/
|
|
73
|
+
export const TODAY_CLASS = 'today';
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* CSS class name for selected date
|
|
77
|
+
*/
|
|
78
|
+
export const SELECTED_CLASS = 'selected';
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* CSS class name for dates outside the current month
|
|
82
|
+
*/
|
|
83
|
+
export const OUTSIDE_MONTH_CLASS = 'outside-month';
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* CSS class for the first date in a range
|
|
87
|
+
*/
|
|
88
|
+
export const RANGE_START_CLASS = 'range-start';
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* CSS class for the last date in a range
|
|
92
|
+
*/
|
|
93
|
+
export const RANGE_END_CLASS = 'range-end';
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* CSS class for dates between start and end in a range
|
|
97
|
+
*/
|
|
98
|
+
export const RANGE_MIDDLE_CLASS = 'range-middle';
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
// src/components/datepicker/datepicker.ts
|
|
2
|
+
import { PREFIX } from '../../core/config';
|
|
3
|
+
import { pipe } from '../../core/compose';
|
|
4
|
+
import { createBase, withElement } from '../../core/compose/component';
|
|
5
|
+
import {
|
|
6
|
+
withEvents,
|
|
7
|
+
withDisabled,
|
|
8
|
+
withLifecycle
|
|
9
|
+
} from '../../core/compose/features';
|
|
10
|
+
|
|
11
|
+
import { withAPI } from './api';
|
|
12
|
+
import { DatePickerConfig } from './types';
|
|
13
|
+
import {
|
|
14
|
+
DATEPICKER_VARIANTS,
|
|
15
|
+
DATEPICKER_VIEWS,
|
|
16
|
+
DATEPICKER_SELECTION_MODES
|
|
17
|
+
} from './constants';
|
|
18
|
+
import {
|
|
19
|
+
createBaseConfig,
|
|
20
|
+
getContainerConfig,
|
|
21
|
+
getInputConfig,
|
|
22
|
+
getCalendarConfig,
|
|
23
|
+
getApiConfig
|
|
24
|
+
} from './config';
|
|
25
|
+
import {
|
|
26
|
+
formatDate,
|
|
27
|
+
parseDate,
|
|
28
|
+
isSameDay
|
|
29
|
+
} from './utils';
|
|
30
|
+
import {
|
|
31
|
+
renderCalendar
|
|
32
|
+
} from './render';
|
|
33
|
+
import { createElement } from '../../core/dom/create';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Creates a new DatePicker component
|
|
37
|
+
* @param {DatePickerConfig} config - DatePicker configuration object
|
|
38
|
+
* @returns {DatePickerComponent} DatePicker component instance
|
|
39
|
+
*/
|
|
40
|
+
const createDatePicker = (config: DatePickerConfig = {}) => {
|
|
41
|
+
const baseConfig = createBaseConfig(config);
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
// Initialize state
|
|
45
|
+
const state: any = {
|
|
46
|
+
isOpen: false,
|
|
47
|
+
selectedDate: null,
|
|
48
|
+
rangeEndDate: null,
|
|
49
|
+
currentView: baseConfig.initialView,
|
|
50
|
+
currentMonth: new Date().getMonth(),
|
|
51
|
+
currentYear: new Date().getFullYear(),
|
|
52
|
+
minDate: baseConfig.minDate ? parseDate(baseConfig.minDate) : null,
|
|
53
|
+
maxDate: baseConfig.maxDate ? parseDate(baseConfig.maxDate) : null,
|
|
54
|
+
dateFormat: baseConfig.dateFormat,
|
|
55
|
+
variant: baseConfig.variant,
|
|
56
|
+
selectionMode: baseConfig.selectionMode,
|
|
57
|
+
closeOnSelect: baseConfig.closeOnSelect,
|
|
58
|
+
prefix: baseConfig.prefix || PREFIX,
|
|
59
|
+
calendarElement: null,
|
|
60
|
+
input: null,
|
|
61
|
+
|
|
62
|
+
updateInputValue(): void {
|
|
63
|
+
if (!this.input) return;
|
|
64
|
+
|
|
65
|
+
if (!this.selectedDate) {
|
|
66
|
+
this.input.value = '';
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Format for range selection
|
|
71
|
+
if (this.selectionMode === DATEPICKER_SELECTION_MODES.RANGE && this.rangeEndDate) {
|
|
72
|
+
const startStr = formatDate(this.selectedDate, this.dateFormat);
|
|
73
|
+
const endStr = formatDate(this.rangeEndDate, this.dateFormat);
|
|
74
|
+
this.input.value = `${startStr} - ${endStr}`;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Format for single selection
|
|
79
|
+
this.input.value = formatDate(this.selectedDate, this.dateFormat);
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
updateCalendar(): void {
|
|
83
|
+
if (!this.isOpen || !this.calendarElement) return;
|
|
84
|
+
|
|
85
|
+
// Clear existing content
|
|
86
|
+
this.calendarElement.innerHTML = '';
|
|
87
|
+
|
|
88
|
+
// Render calendar content
|
|
89
|
+
const calendar = renderCalendar(this, (event, data) => {
|
|
90
|
+
switch (event) {
|
|
91
|
+
case 'dateSelected':
|
|
92
|
+
this.handleDateSelection(data.date);
|
|
93
|
+
break;
|
|
94
|
+
|
|
95
|
+
case 'monthSelected':
|
|
96
|
+
this.currentMonth = data.month;
|
|
97
|
+
this.currentView = DATEPICKER_VIEWS.DAY;
|
|
98
|
+
this.updateCalendar();
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
case 'yearSelected':
|
|
102
|
+
this.currentYear = data.year;
|
|
103
|
+
this.currentView = DATEPICKER_VIEWS.MONTH;
|
|
104
|
+
this.updateCalendar();
|
|
105
|
+
break;
|
|
106
|
+
|
|
107
|
+
case 'viewChange':
|
|
108
|
+
this.currentView = data.view;
|
|
109
|
+
this.updateCalendar();
|
|
110
|
+
break;
|
|
111
|
+
|
|
112
|
+
case 'prevMonth':
|
|
113
|
+
this.prevMonth();
|
|
114
|
+
break;
|
|
115
|
+
|
|
116
|
+
case 'nextMonth':
|
|
117
|
+
this.nextMonth();
|
|
118
|
+
break;
|
|
119
|
+
|
|
120
|
+
case 'prevYear':
|
|
121
|
+
this.prevYear();
|
|
122
|
+
break;
|
|
123
|
+
|
|
124
|
+
case 'nextYear':
|
|
125
|
+
this.nextYear();
|
|
126
|
+
break;
|
|
127
|
+
|
|
128
|
+
case 'prevYearRange':
|
|
129
|
+
this.currentYear -= 20;
|
|
130
|
+
this.updateCalendar();
|
|
131
|
+
break;
|
|
132
|
+
|
|
133
|
+
case 'nextYearRange':
|
|
134
|
+
this.currentYear += 20;
|
|
135
|
+
this.updateCalendar();
|
|
136
|
+
break;
|
|
137
|
+
|
|
138
|
+
case 'cancel':
|
|
139
|
+
this.isOpen = false;
|
|
140
|
+
this.render();
|
|
141
|
+
break;
|
|
142
|
+
|
|
143
|
+
case 'confirm':
|
|
144
|
+
this.isOpen = false;
|
|
145
|
+
this.render();
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
this.calendarElement.appendChild(calendar);
|
|
151
|
+
},
|
|
152
|
+
|
|
153
|
+
handleDateSelection(date: Date): void {
|
|
154
|
+
// Range selection
|
|
155
|
+
if (this.selectionMode === DATEPICKER_SELECTION_MODES.RANGE) {
|
|
156
|
+
// If no date is selected yet or both dates are already selected, start a new range
|
|
157
|
+
if (!this.selectedDate || (this.selectedDate && this.rangeEndDate)) {
|
|
158
|
+
this.selectedDate = date;
|
|
159
|
+
this.rangeEndDate = null;
|
|
160
|
+
}
|
|
161
|
+
// If start date is selected but not end date
|
|
162
|
+
else {
|
|
163
|
+
// If selected date is before the start date, swap them
|
|
164
|
+
if (date < this.selectedDate) {
|
|
165
|
+
this.rangeEndDate = this.selectedDate;
|
|
166
|
+
this.selectedDate = date;
|
|
167
|
+
} else {
|
|
168
|
+
this.rangeEndDate = date;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Close if needed
|
|
172
|
+
if (this.closeOnSelect) {
|
|
173
|
+
this.isOpen = false;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// Single date selection
|
|
178
|
+
else {
|
|
179
|
+
this.selectedDate = date;
|
|
180
|
+
|
|
181
|
+
// Close if needed
|
|
182
|
+
if (this.closeOnSelect) {
|
|
183
|
+
this.isOpen = false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Update the input value
|
|
188
|
+
this.updateInputValue();
|
|
189
|
+
|
|
190
|
+
// Update the calendar view
|
|
191
|
+
this.updateCalendar();
|
|
192
|
+
|
|
193
|
+
// Emit change event
|
|
194
|
+
component.emit('change', {
|
|
195
|
+
value: this.selectedDate,
|
|
196
|
+
rangeEndDate: this.rangeEndDate,
|
|
197
|
+
formattedValue: this.input.value
|
|
198
|
+
});
|
|
199
|
+
},
|
|
200
|
+
|
|
201
|
+
prevMonth(): void {
|
|
202
|
+
if (this.currentMonth === 0) {
|
|
203
|
+
this.currentMonth = 11;
|
|
204
|
+
this.currentYear--;
|
|
205
|
+
} else {
|
|
206
|
+
this.currentMonth--;
|
|
207
|
+
}
|
|
208
|
+
this.updateCalendar();
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
nextMonth(): void {
|
|
212
|
+
if (this.currentMonth === 11) {
|
|
213
|
+
this.currentMonth = 0;
|
|
214
|
+
this.currentYear++;
|
|
215
|
+
} else {
|
|
216
|
+
this.currentMonth++;
|
|
217
|
+
}
|
|
218
|
+
this.updateCalendar();
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
prevYear(): void {
|
|
222
|
+
this.currentYear--;
|
|
223
|
+
this.updateCalendar();
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
nextYear(): void {
|
|
227
|
+
this.currentYear++;
|
|
228
|
+
this.updateCalendar();
|
|
229
|
+
},
|
|
230
|
+
|
|
231
|
+
render(): void {
|
|
232
|
+
// Show/hide calendar
|
|
233
|
+
if (this.calendarElement) {
|
|
234
|
+
if (this.isOpen) {
|
|
235
|
+
this.calendarElement.style.display = 'block';
|
|
236
|
+
this.updateCalendar();
|
|
237
|
+
|
|
238
|
+
// Focus on the calendar
|
|
239
|
+
setTimeout(() => {
|
|
240
|
+
this.calendarElement.focus();
|
|
241
|
+
}, 10);
|
|
242
|
+
} else {
|
|
243
|
+
this.calendarElement.style.display = 'none';
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// Initialize with provided value if any
|
|
250
|
+
if (baseConfig.value) {
|
|
251
|
+
if (Array.isArray(baseConfig.value) && baseConfig.selectionMode === DATEPICKER_SELECTION_MODES.RANGE) {
|
|
252
|
+
const start = parseDate(baseConfig.value[0]);
|
|
253
|
+
const end = parseDate(baseConfig.value[1]);
|
|
254
|
+
|
|
255
|
+
if (start && end) {
|
|
256
|
+
state.selectedDate = start;
|
|
257
|
+
state.rangeEndDate = end;
|
|
258
|
+
|
|
259
|
+
// Set current month/year to selected date
|
|
260
|
+
state.currentMonth = start.getMonth();
|
|
261
|
+
state.currentYear = start.getFullYear();
|
|
262
|
+
}
|
|
263
|
+
} else {
|
|
264
|
+
const date = parseDate(baseConfig.value as Date | string);
|
|
265
|
+
if (date) {
|
|
266
|
+
state.selectedDate = date;
|
|
267
|
+
state.currentMonth = date.getMonth();
|
|
268
|
+
state.currentYear = date.getFullYear();
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Create the component
|
|
274
|
+
const component = pipe(
|
|
275
|
+
createBase,
|
|
276
|
+
withEvents(),
|
|
277
|
+
withElement(getContainerConfig(baseConfig)),
|
|
278
|
+
withDisabled(baseConfig),
|
|
279
|
+
withLifecycle()
|
|
280
|
+
)(baseConfig);
|
|
281
|
+
|
|
282
|
+
// Create input element
|
|
283
|
+
const inputComponent = pipe(
|
|
284
|
+
createBase,
|
|
285
|
+
withElement(getInputConfig(baseConfig))
|
|
286
|
+
)(baseConfig);
|
|
287
|
+
|
|
288
|
+
state.input = inputComponent.element;
|
|
289
|
+
component.element.appendChild(state.input);
|
|
290
|
+
|
|
291
|
+
// Update input value
|
|
292
|
+
state.updateInputValue();
|
|
293
|
+
|
|
294
|
+
// Create calendar element
|
|
295
|
+
const calendarConfig = getCalendarConfig(baseConfig);
|
|
296
|
+
state.calendarElement = createElement({
|
|
297
|
+
tag: 'div',
|
|
298
|
+
className: calendarConfig.className,
|
|
299
|
+
attrs: calendarConfig.attrs
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
// Initially hide calendar
|
|
303
|
+
state.calendarElement.style.display = 'none';
|
|
304
|
+
|
|
305
|
+
// Add calendar to container
|
|
306
|
+
component.element.appendChild(state.calendarElement);
|
|
307
|
+
|
|
308
|
+
// Add event listeners
|
|
309
|
+
state.input.addEventListener('click', () => {
|
|
310
|
+
if (!component.element.classList.contains('disabled')) {
|
|
311
|
+
state.isOpen = !state.isOpen;
|
|
312
|
+
state.render();
|
|
313
|
+
|
|
314
|
+
if (state.isOpen) {
|
|
315
|
+
component.emit('open', { value: state.selectedDate });
|
|
316
|
+
} else {
|
|
317
|
+
component.emit('close', { value: state.selectedDate });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
// BUGFIX: Prevent calendar close when clicking inside the calendar
|
|
323
|
+
state.calendarElement.addEventListener('click', (event) => {
|
|
324
|
+
// Stop propagation to prevent the document click handler from closing the calendar
|
|
325
|
+
event.stopPropagation();
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
// Handle outside clicks
|
|
329
|
+
document.addEventListener('click', (event) => {
|
|
330
|
+
if (state.isOpen &&
|
|
331
|
+
!component.element.contains(event.target as Node)) {
|
|
332
|
+
state.isOpen = false;
|
|
333
|
+
state.render();
|
|
334
|
+
component.emit('close', { value: state.selectedDate });
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Enhance with API
|
|
339
|
+
return withAPI(state, getApiConfig(component))(component);
|
|
340
|
+
} catch (error) {
|
|
341
|
+
console.error('DatePicker creation error:', error);
|
|
342
|
+
throw new Error(`Failed to create DatePicker: ${(error as Error).message}`);
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
export default createDatePicker;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// src/components/datepicker/index.ts
|
|
2
|
+
export { default } from './datepicker'
|
|
3
|
+
export {
|
|
4
|
+
DATEPICKER_VARIANTS,
|
|
5
|
+
DATEPICKER_VIEWS,
|
|
6
|
+
DATEPICKER_SELECTION_MODES,
|
|
7
|
+
DEFAULT_DATE_FORMAT
|
|
8
|
+
} from './constants'
|
|
9
|
+
export { DatePickerConfig, DatePickerComponent } from './types'
|