@monolith-forensics/monolith-ui 1.8.0 → 1.8.1-dev.1

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.
Files changed (120) hide show
  1. package/dist/Button/Button.js +9 -58
  2. package/dist/Calendar/Calendar.d.ts +3 -1
  3. package/dist/Calendar/Calendar.js +134 -33
  4. package/dist/Calendar/CalendarStyles.d.ts +3 -0
  5. package/dist/Calendar/CalendarStyles.js +92 -14
  6. package/dist/Calendar/calendarHelpers.d.ts +5 -1
  7. package/dist/Calendar/calendarHelpers.js +13 -5
  8. package/dist/Charts/BarChart/BarChart.d.ts +5 -0
  9. package/dist/Charts/BarChart/BarChart.js +549 -0
  10. package/dist/Charts/BarChart/BarChart.lib.d.ts +31 -0
  11. package/dist/Charts/BarChart/BarChart.lib.js +136 -0
  12. package/dist/Charts/BarChart/BarChart.styled.d.ts +51 -0
  13. package/dist/Charts/BarChart/BarChart.styled.js +115 -0
  14. package/dist/Charts/BarChart/BarChart.types.d.ts +171 -0
  15. package/dist/Charts/BarChart/BarChart.types.js +1 -0
  16. package/dist/Charts/BarChart/index.d.ts +3 -0
  17. package/dist/Charts/BarChart/index.js +2 -0
  18. package/dist/Charts/ChartPrimitives/ChartExportControl.d.ts +11 -0
  19. package/dist/Charts/ChartPrimitives/ChartExportControl.js +29 -0
  20. package/dist/Charts/ChartPrimitives/chartActions.styled.d.ts +1 -0
  21. package/dist/Charts/ChartPrimitives/chartActions.styled.js +8 -0
  22. package/dist/Charts/ChartPrimitives/chartLegend.styled.d.ts +12 -0
  23. package/dist/Charts/ChartPrimitives/chartLegend.styled.js +52 -0
  24. package/dist/Charts/ChartPrimitives/chartTooltip.styled.d.ts +19 -0
  25. package/dist/Charts/ChartPrimitives/chartTooltip.styled.js +61 -0
  26. package/dist/Charts/ChartPrimitives/index.d.ts +4 -0
  27. package/dist/Charts/ChartPrimitives/index.js +4 -0
  28. package/dist/Charts/ChartUtils/chartColors.d.ts +8 -0
  29. package/dist/Charts/ChartUtils/chartColors.js +65 -0
  30. package/dist/Charts/ChartUtils/chartExport.d.ts +47 -0
  31. package/dist/Charts/ChartUtils/chartExport.js +311 -0
  32. package/dist/Charts/ChartUtils/chartMath.d.ts +3 -0
  33. package/dist/Charts/ChartUtils/chartMath.js +3 -0
  34. package/dist/Charts/ChartUtils/index.d.ts +3 -0
  35. package/dist/Charts/ChartUtils/index.js +3 -0
  36. package/dist/Charts/HeatMap/HeatMap.d.ts +5 -0
  37. package/dist/Charts/HeatMap/HeatMap.js +212 -0
  38. package/dist/Charts/HeatMap/HeatMap.lib.d.ts +30 -0
  39. package/dist/Charts/HeatMap/HeatMap.lib.js +115 -0
  40. package/dist/Charts/HeatMap/HeatMap.styled.d.ts +37 -0
  41. package/dist/Charts/HeatMap/HeatMap.styled.js +91 -0
  42. package/dist/Charts/HeatMap/HeatMap.types.d.ts +80 -0
  43. package/dist/Charts/HeatMap/HeatMap.types.js +1 -0
  44. package/dist/Charts/HeatMap/index.d.ts +3 -0
  45. package/dist/Charts/HeatMap/index.js +2 -0
  46. package/dist/Charts/LineChart/LineChart.d.ts +5 -0
  47. package/dist/Charts/LineChart/LineChart.js +529 -0
  48. package/dist/Charts/LineChart/LineChart.lib.d.ts +24 -0
  49. package/dist/Charts/LineChart/LineChart.lib.js +132 -0
  50. package/dist/Charts/LineChart/LineChart.styled.d.ts +59 -0
  51. package/dist/Charts/LineChart/LineChart.styled.js +147 -0
  52. package/dist/Charts/LineChart/LineChart.types.d.ts +193 -0
  53. package/dist/Charts/LineChart/LineChart.types.js +1 -0
  54. package/dist/Charts/LineChart/index.d.ts +3 -0
  55. package/dist/Charts/LineChart/index.js +2 -0
  56. package/dist/Charts/PieChart/PieChart.d.ts +4 -0
  57. package/dist/Charts/PieChart/PieChart.js +199 -0
  58. package/dist/Charts/PieChart/PieChart.lib.d.ts +5 -0
  59. package/dist/Charts/PieChart/PieChart.lib.js +19 -0
  60. package/dist/Charts/PieChart/PieChart.styled.d.ts +51 -0
  61. package/dist/Charts/PieChart/PieChart.styled.js +163 -0
  62. package/dist/Charts/PieChart/PieChart.types.d.ts +100 -0
  63. package/dist/Charts/PieChart/PieChart.types.js +1 -0
  64. package/dist/Charts/PieChart/index.d.ts +2 -0
  65. package/dist/Charts/PieChart/index.js +1 -0
  66. package/dist/Charts/index.d.ts +5 -0
  67. package/dist/Charts/index.js +4 -0
  68. package/dist/CheckBox/CheckBox.js +2 -16
  69. package/dist/DateInput/DateInput.js +198 -143
  70. package/dist/DropDownMenu/components/MenuComponent.js +2 -1
  71. package/dist/DropDownMenu/components/MenuItem.js +5 -14
  72. package/dist/DropDownMenu/components/MenuItemList.js +7 -24
  73. package/dist/DropDownMenu/components/StyledFloatContainer.js +1 -1
  74. package/dist/FieldLabel/FieldLabel.js +4 -12
  75. package/dist/FileInputField/FileInputField.js +4 -23
  76. package/dist/FormSection/FormSection.js +5 -25
  77. package/dist/IconButton/IconButton.js +2 -16
  78. package/dist/Input/Input.js +7 -56
  79. package/dist/Pill/Pill.js +8 -79
  80. package/dist/Popover/Popover.context.d.ts +2 -1
  81. package/dist/Popover/Popover.js +5 -2
  82. package/dist/Popover/Popover.styles.d.ts +1 -6
  83. package/dist/Popover/Popover.styles.js +11 -28
  84. package/dist/Popover/Popover.transitions.d.ts +4 -2
  85. package/dist/Popover/Popover.transitions.js +23 -49
  86. package/dist/Popover/PopoverDropdown.js +6 -8
  87. package/dist/Popover/PopoverTarget.js +6 -3
  88. package/dist/SegmentedControl/SegmentedControl.utils.d.ts +2 -2
  89. package/dist/SegmentedControl/SegmentedControl.utils.js +3 -30
  90. package/dist/SelectBox/SelectBox.js +5 -5
  91. package/dist/SelectBox/select-box.styled-components.d.ts +4 -1
  92. package/dist/SelectBox/select-box.styled-components.js +11 -48
  93. package/dist/SelectBox/types.d.ts +1 -0
  94. package/dist/Switch/Switch.d.ts +2 -2
  95. package/dist/Switch/Switch.js +18 -83
  96. package/dist/Table/StateStorage.d.ts +4 -0
  97. package/dist/Table/StateStorage.js +13 -0
  98. package/dist/Table/Table.js +160 -12
  99. package/dist/Table/TableComponents.d.ts +10 -0
  100. package/dist/Table/TableComponents.js +57 -0
  101. package/dist/Table/TableDefaults.d.ts +7 -0
  102. package/dist/Table/TableDefaults.js +7 -0
  103. package/dist/Table/TableProvider.js +263 -71
  104. package/dist/Table/TableRow.js +15 -10
  105. package/dist/Table/types.d.ts +64 -0
  106. package/dist/TagBox/TagBox.js +18 -76
  107. package/dist/TextArea/TextArea.js +4 -23
  108. package/dist/TextInput/TextInput.js +12 -6
  109. package/dist/Utilities/parseTimestamp.js +11 -6
  110. package/dist/core/ArrowButton.d.ts +2 -0
  111. package/dist/core/ArrowButton.js +7 -3
  112. package/dist/core/ClearButton.d.ts +2 -0
  113. package/dist/core/ClearButton.js +7 -3
  114. package/dist/core/controlSizes.d.ts +34 -0
  115. package/dist/core/controlSizes.js +190 -0
  116. package/dist/core/index.d.ts +1 -0
  117. package/dist/core/index.js +1 -0
  118. package/dist/index.d.ts +1 -0
  119. package/dist/index.js +1 -0
  120. package/package.json +5 -1
@@ -13,6 +13,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
13
13
  import { forwardRef } from "react";
14
14
  import styled from "styled-components";
15
15
  import { Loader2Icon } from "lucide-react";
16
+ import { getControlSizeTokens } from "../core";
16
17
  const colors = {
17
18
  gray: "#888888",
18
19
  lightGray: "#f0f0f0",
@@ -35,63 +36,14 @@ const StyledButton = styled.button `
35
36
  white-space: nowrap;
36
37
 
37
38
  width: ${({ fullWidth }) => (fullWidth ? "100%" : "fit-content")};
38
- height: ${({ theme, size }) => {
39
- switch (size) {
40
- case "xxs":
41
- return `24px`;
42
- case "xs":
43
- return `28px`;
44
- case "sm":
45
- return `34px`;
46
- case "md":
47
- return `40px`;
48
- case "lg":
49
- return `48px`;
50
- case "xl":
51
- return `58px`;
52
- default:
53
- return `34px`;
54
- }
55
- }};
39
+ height: ${({ size }) => `${getControlSizeTokens(size).height}px`};
56
40
 
57
- font-size: ${({ theme, size }) => {
58
- switch (size) {
59
- case "xxs":
60
- return `11px`;
61
- case "xs":
62
- return `12px`;
63
- case "sm":
64
- return `14px`;
65
- case "md":
66
- return `16px`;
67
- case "lg":
68
- return `18px`;
69
- case "xl":
70
- return `20px`;
71
- default:
72
- return `14px`;
73
- }
74
- }};
41
+ font-size: ${({ size }) => `${getControlSizeTokens(size).fontSize}px`};
75
42
 
76
43
  padding: ${({ theme, size, variant }) => {
77
44
  if (variant === "text")
78
45
  return `0px 0px`;
79
- switch (size) {
80
- case "xxs":
81
- return `0px 8px`;
82
- case "xs":
83
- return `0px 12px`;
84
- case "sm":
85
- return `0px 16px`;
86
- case "md":
87
- return `0px 20px`;
88
- case "lg":
89
- return `0px 24px`;
90
- case "xl":
91
- return `0px 30px`;
92
- default:
93
- return `0px 16px`;
94
- }
46
+ return `0px ${getControlSizeTokens(size).buttonPaddingX}px`;
95
47
  }};
96
48
 
97
49
  color: ${({ theme, variant, color }) => {
@@ -175,6 +127,7 @@ const StyledButton = styled.button `
175
127
  display: flex;
176
128
  align-items: center;
177
129
  justify-content: center;
130
+ gap: ${({ size }) => `${getControlSizeTokens(size).iconGap}px`};
178
131
  }
179
132
 
180
133
  .button-label {
@@ -183,17 +136,15 @@ const StyledButton = styled.button `
183
136
  }
184
137
 
185
138
  [data-position="left"] {
186
- margin-inline-end: 6px;
187
139
  display: flex;
188
140
  align-items: center;
189
141
  }
190
142
 
191
143
  [data-position="right"] {
192
- margin-inline-start: 6px;
193
- padding-inline-start: 6px;
194
144
  margin-left: auto;
195
145
  display: flex;
196
146
  align-items: center;
147
+ padding-inline-start: ${({ size }) => `${getControlSizeTokens(size).iconGap}px`};
197
148
  }
198
149
 
199
150
  &:hover {
@@ -264,8 +215,8 @@ const StyledAnchor = styled.a `
264
215
  `;
265
216
  const StyledLoader = styled.span `
266
217
  svg {
267
- width: 16px;
268
- height: 16px;
218
+ width: ${({ size }) => `${getControlSizeTokens(size).iconSize}px`};
219
+ height: ${({ size }) => `${getControlSizeTokens(size).iconSize}px`};
269
220
  color: ${({ theme, color }) => {
270
221
  var _a;
271
222
  return color
@@ -285,6 +236,6 @@ const StyledLoader = styled.span `
285
236
  `;
286
237
  export const Button = forwardRef((props, ref) => {
287
238
  const { children, loading = false, leftSection = null, rightSection = null, href = null, download = null, justify = "center" } = props, other = __rest(props, ["children", "loading", "leftSection", "rightSection", "href", "download", "justify"]);
288
- const buttonContent = (_jsx("div", { className: "inner-span", style: { height: "100%", width: "100%", justifyContent: justify }, children: loading ? (_jsx(StyledLoader, { children: _jsx(Loader2Icon, {}) })) : (_jsxs(_Fragment, { children: [leftSection && _jsx("div", { "data-position": "left", children: leftSection }), _jsx("div", { className: "button-label", children: children }), rightSection && _jsx("div", { "data-position": "right", children: rightSection })] })) }));
239
+ const buttonContent = (_jsx("div", { className: "inner-span", style: { height: "100%", width: "100%", justifyContent: justify }, children: loading ? (_jsx(StyledLoader, { size: other.size, children: _jsx(Loader2Icon, {}) })) : (_jsxs(_Fragment, { children: [leftSection && _jsx("div", { "data-position": "left", children: leftSection }), _jsx("div", { className: "button-label", children: children }), rightSection && _jsx("div", { "data-position": "right", children: rightSection })] })) }));
289
240
  return (_jsx(StyledButton, Object.assign({ ref: ref }, other, { children: href ? (_jsx(StyledAnchor, { href: href, download: download, children: buttonContent })) : (buttonContent) })));
290
241
  });
@@ -1,7 +1,9 @@
1
1
  interface CalendarProps {
2
2
  defaultValue?: Date;
3
3
  value?: Date | null;
4
- onChange?: (date: Date | null) => void;
4
+ onChange?: (date: Date | null, meta?: {
5
+ source: "date" | "month" | "year" | "time" | "clear";
6
+ }) => void;
5
7
  hourFormat?: "12" | "24";
6
8
  includeTime?: boolean;
7
9
  clearable?: boolean;
@@ -1,8 +1,9 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Fragment, useEffect, useRef, useState } from "react";
3
3
  import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
4
- import { CalendarContainer, CalendarHeader, CalendarGrid, CalendarMonth, CalendarDay, CalendarDate, HighlightedCalendarDate, TodayCalendarDate, TimeContainer, MainContainer, TimePickerContainer, TimeHourSelect, TimeHeader, TimeMinuteSelect, TimeItem, TimeItemActive, NoValueButton, } from "./CalendarStyles";
5
- import calendar, { isDate, isSameDay, isSameMonth, getDateISO, getNextMonth, getPreviousMonth, WEEK_DAYS, CALENDAR_MONTHS, HOURS24, HOURS12, MINUTES, } from "./calendarHelpers";
4
+ import { CalendarContainer, CalendarHeader, CalendarHeaderControls, CalendarHeaderSelect, CalendarNavButton, CalendarGrid, CalendarMonth, CalendarDay, CalendarDate, HighlightedCalendarDate, TodayCalendarDate, TimeContainer, MainContainer, TimePickerContainer, TimeHourSelect, TimeHeader, TimeMinuteSelect, TimeItem, TimeItemActive, NoValueButton, } from "./CalendarStyles";
5
+ import { DropDownMenu } from "../DropDownMenu";
6
+ import calendar, { createLocalDate, isDate, isSameDay, isSameMonth, getDateISO, getMonthDays, getNextMonth, getPreviousMonth, WEEK_DAYS, CALENDAR_MONTHS, HOURS24, HOURS12, MINUTES, } from "./calendarHelpers";
6
7
  import moment from "moment";
7
8
  const checkValidRange = (value, min, max) => {
8
9
  if (min && moment(value).startOf("day").isBefore(moment(min).startOf("day")))
@@ -20,6 +21,10 @@ const resolveValue = (value) => {
20
21
  minutes: safeValue.getMinutes(),
21
22
  };
22
23
  };
24
+ const MONTH_OPTIONS = Object.keys(CALENDAR_MONTHS).map((monthName, index) => ({
25
+ label: monthName,
26
+ value: index + 1,
27
+ }));
23
28
  const Calendar = ({ defaultValue = new Date(), value, onChange = () => { }, hourFormat = "24", includeTime = true, clearable = true, min, max, }) => {
24
29
  const isControlled = useRef(value !== undefined);
25
30
  const [valueState, setValueState] = useState(defaultValue);
@@ -33,16 +38,44 @@ const Calendar = ({ defaultValue = new Date(), value, onChange = () => { }, hour
33
38
  let pressureTimer;
34
39
  let pressureTimeout;
35
40
  let dayTimeout;
41
+ const syncCalendarState = (date) => {
42
+ setCalendarState({
43
+ month: +date.getMonth() + 1,
44
+ year: date.getFullYear(),
45
+ hours: date.getHours(),
46
+ minutes: date.getMinutes(),
47
+ });
48
+ };
49
+ const commitDate = (date, source = "date") => {
50
+ if (date && isDate(date)) {
51
+ if (!isControlled.current) {
52
+ setValueState(date);
53
+ }
54
+ syncCalendarState(date);
55
+ onChange(date, { source });
56
+ return;
57
+ }
58
+ if (!isControlled.current) {
59
+ setValueState(null);
60
+ }
61
+ onChange(null, { source: "clear" });
62
+ };
63
+ const getWorkingDate = () => {
64
+ if (_value && isDate(_value)) {
65
+ return _value;
66
+ }
67
+ const fallbackDay = Math.min(today.getDate(), getMonthDays(calendarState.month, calendarState.year));
68
+ const fallbackDate = createLocalDate(calendarState.year, calendarState.month, fallbackDay);
69
+ fallbackDate.setHours(calendarState.hours, calendarState.minutes, 0, 0);
70
+ return fallbackDate;
71
+ };
36
72
  const addDateToState = (date) => {
37
73
  const isDateObject = isDate(date);
38
74
  const _date = isDateObject ? date : new Date();
39
- setValueState(_date);
40
- setCalendarState({
41
- month: +_date.getMonth() + 1,
42
- year: _date.getFullYear(),
43
- hours: _date.getHours(),
44
- minutes: _date.getMinutes(),
45
- });
75
+ if (!isControlled.current) {
76
+ setValueState(_date);
77
+ }
78
+ syncCalendarState(_date);
46
79
  };
47
80
  const getCalendarDates = () => {
48
81
  const { month, year } = calendarState;
@@ -50,37 +83,87 @@ const Calendar = ({ defaultValue = new Date(), value, onChange = () => { }, hour
50
83
  const calendarYear = year || (_value === null || _value === void 0 ? void 0 : _value.getFullYear()) || new Date().getFullYear();
51
84
  return calendar(calendarMonth, calendarYear);
52
85
  };
53
- //new start
86
+ const setCalendarView = (nextMonth, nextYear) => {
87
+ setCalendarState((prev) => (Object.assign(Object.assign({}, prev), { month: nextMonth, year: nextYear })));
88
+ };
89
+ const commitMonthOrYearSelection = (nextMonth, nextYear, source) => {
90
+ const workingDate = getWorkingDate();
91
+ const clampedDay = Math.min(workingDate.getDate(), getMonthDays(nextMonth, nextYear));
92
+ const nextDate = createLocalDate(nextYear, nextMonth, clampedDay);
93
+ nextDate.setHours(workingDate.getHours(), workingDate.getMinutes(), 0, 0);
94
+ commitDate(nextDate, source);
95
+ };
96
+ const getYearOptions = () => {
97
+ var _a, _b;
98
+ const currentYear = calendarState.year;
99
+ const minYear = (_a = min === null || min === void 0 ? void 0 : min.getFullYear()) !== null && _a !== void 0 ? _a : currentYear - 50;
100
+ const maxYear = (_b = max === null || max === void 0 ? void 0 : max.getFullYear()) !== null && _b !== void 0 ? _b : currentYear + 50;
101
+ return Array.from({ length: maxYear - minYear + 1 }, (_, index) => {
102
+ const optionYear = minYear + index;
103
+ return {
104
+ label: `${optionYear}`,
105
+ value: optionYear,
106
+ };
107
+ });
108
+ };
54
109
  const renderMonthAndYear = () => {
55
110
  const { month, year } = calendarState;
56
- // Resolve the month name from the CALENDAR_MONTHS object map
57
- const monthname = Object.keys(CALENDAR_MONTHS)[Math.max(0, Math.min(month - 1, 11))];
58
- return (_jsxs(CalendarHeader, { children: [_jsx(ChevronLeftIcon, { onMouseDown: handlePrevious, onMouseUp: clearPressureTimer }), _jsxs(CalendarMonth, { children: [monthname, " ", year] }), _jsx(ChevronRightIcon, { onMouseDown: handleNext, onMouseUp: clearPressureTimer })] }));
111
+ const monthName = Object.keys(CALENDAR_MONTHS)[Math.max(0, Math.min(month - 1, 11))];
112
+ const yearOptions = getYearOptions();
113
+ return (_jsxs(CalendarHeader, { children: [_jsx(CalendarNavButton, { type: "button", onClick: handlePrevious, onMouseUp: clearPressureTimer, "aria-label": "Go to previous month", title: "Previous month. Hold Shift to jump by year.", children: _jsx(ChevronLeftIcon, { "aria-hidden": "true" }) }), _jsxs(CalendarHeaderControls, { children: [_jsx(CalendarHeaderSelect, { children: _jsx(DropDownMenu, { data: MONTH_OPTIONS, variant: "outlined", size: "xs", arrow: true, onItemSelect: (item) => commitMonthOrYearSelection(Number(item.value), year, "month"), dropDownProps: {
114
+ style: { width: 75, maxHeight: 260 },
115
+ }, buttonProps: {
116
+ title: "Select month",
117
+ size: "xxs",
118
+ style: { minWidth: 95 },
119
+ }, children: _jsx(CalendarMonth, { children: monthName }) }) }), _jsx(CalendarHeaderSelect, { children: _jsx(DropDownMenu, { data: yearOptions, variant: "outlined", size: "xs", arrow: true, searchable: true, onItemSelect: (item) => commitMonthOrYearSelection(month, Number(item.value), "year"), dropDownProps: {
120
+ style: { width: 120, maxHeight: 260 },
121
+ }, buttonProps: {
122
+ title: "Select year",
123
+ size: "xxs",
124
+ style: { minWidth: 50 },
125
+ }, children: _jsx(CalendarMonth, { children: year }) }) })] }), _jsx(CalendarNavButton, { type: "button", onClick: handleNext, onMouseUp: clearPressureTimer, "aria-label": "Go to next month", title: "Next month. Hold Shift to jump by year.", children: _jsx(ChevronRightIcon, { "aria-hidden": "true" }) })] }));
126
+ };
127
+ const handleActionKeyDown = (action) => (evt) => {
128
+ if (evt.key === "Enter" || evt.key === " ") {
129
+ evt.preventDefault();
130
+ action();
131
+ }
59
132
  };
60
133
  // Render the label for day of the week
61
134
  // This method is used as a map callback as seen in render()
62
135
  const renderDayLabel = (day, index) => {
63
136
  // Resolve the day of the week label from the WEEK_DAYS object map
64
137
  const daylabel = WEEK_DAYS[day];
65
- return (_jsx(CalendarDay, { index: index, children: daylabel }, daylabel));
138
+ return (_jsx(CalendarDay, { index: index, role: "columnheader", children: daylabel }, daylabel));
66
139
  };
67
140
  // Render a calendar date as returned from the calendar builder function
68
141
  // This method is used as a map callback as seen in render()
69
142
  const renderCalendarDate = (date, index) => {
143
+ const [dateYear, dateMonth, dateDay] = date.map(Number);
70
144
  const { month, year } = calendarState;
71
- const _date = new Date(date.join("-"));
145
+ const _date = createLocalDate(dateYear, dateMonth, dateDay);
72
146
  // Check if calendar date is same day as today
73
147
  const isToday = isSameDay(_date, today);
74
148
  // Check if calendar date is same day as currently selected date
75
149
  const isCurrent = _value && isSameDay(_date, _value);
76
150
  // Check if calendar date is in the same month as the state month and year
77
- const inMonth = month && year && isSameMonth(_date, new Date([year, month, 1].join("-")));
151
+ const inMonth = month && year && isSameMonth(_date, createLocalDate(year, month, 1));
152
+ const isDisabled = !checkValidRange(getDateISO(_date), min || null, max || null);
153
+ const ariaCurrent = isToday ? "date" : undefined;
78
154
  // The click handler
79
155
  const props = {
80
- "data-disabled": !checkValidRange(getDateISO(_date), min || null, max || null),
156
+ "data-disabled": isDisabled,
157
+ "aria-current": ariaCurrent,
158
+ "aria-disabled": isDisabled,
159
+ "aria-label": `${isCurrent ? "Selected" : "Select"} ${_date.toDateString()}`,
160
+ "aria-pressed": Boolean(isCurrent),
81
161
  index,
82
162
  key: getDateISO(_date),
83
163
  onClick: gotoDate(_date),
164
+ onKeyDown: handleActionKeyDown(() => gotoDate(_date)(undefined)),
165
+ role: "button",
166
+ tabIndex: isDisabled ? -1 : 0,
84
167
  title: _date.toDateString(),
85
168
  inMonth,
86
169
  };
@@ -92,28 +175,42 @@ const Calendar = ({ defaultValue = new Date(), value, onChange = () => { }, hour
92
175
  const hoursArray = hourFormat === "24" ? HOURS24 : HOURS12;
93
176
  return hoursArray.map((hour, index) => {
94
177
  const HourComponent = hour.value === hours ? TimeItemActive : TimeItem;
95
- return (_jsx(HourComponent, {
178
+ return (_jsx(HourComponent, { role: "button", tabIndex: 0, "aria-label": `Select ${hour.label}`, "aria-pressed": hour.value === hours,
96
179
  // value={hour.value}
97
180
  onClick: (e) => {
98
- const newTime = moment(_value).hours(hour.value).toDate();
99
- setCalendarState(Object.assign(Object.assign({}, calendarState), { hours: hour.value }));
100
- setValueState(newTime);
101
- onChange === null || onChange === void 0 ? void 0 : onChange(newTime);
102
- }, children: hour.label }, hour.value));
181
+ const newTime = moment(getWorkingDate())
182
+ .hours(hour.value)
183
+ .minutes(calendarState.minutes)
184
+ .toDate();
185
+ commitDate(newTime, "time");
186
+ }, onKeyDown: handleActionKeyDown(() => {
187
+ const newTime = moment(getWorkingDate())
188
+ .hours(hour.value)
189
+ .minutes(calendarState.minutes)
190
+ .toDate();
191
+ commitDate(newTime, "time");
192
+ }), children: hour.label }, hour.value));
103
193
  });
104
194
  };
105
195
  const renderMinutes = () => {
106
196
  const { minutes } = calendarState;
107
197
  return MINUTES.map((minute) => {
108
- const MinuteComponent = minute === minutes ? TimeItemActive : TimeItem;
109
- return (_jsx(MinuteComponent, {
198
+ const MinuteComponent = minute.value === minutes ? TimeItemActive : TimeItem;
199
+ return (_jsx(MinuteComponent, { role: "button", tabIndex: 0, "aria-label": `Select ${minute.label} minutes`, "aria-pressed": minute.value === minutes,
110
200
  // value={minute}
111
201
  onClick: (e) => {
112
- const newTime = moment(_value).minutes(Number(minute)).toDate();
113
- setCalendarState(Object.assign(Object.assign({}, calendarState), { minutes: Number(minute) }));
114
- setValueState(newTime);
115
- onChange === null || onChange === void 0 ? void 0 : onChange(newTime);
116
- }, children: minute }, minute));
202
+ const newTime = moment(getWorkingDate())
203
+ .hours(calendarState.hours)
204
+ .minutes(minute.value)
205
+ .toDate();
206
+ commitDate(newTime, "time");
207
+ }, onKeyDown: handleActionKeyDown(() => {
208
+ const newTime = moment(getWorkingDate())
209
+ .hours(calendarState.hours)
210
+ .minutes(minute.value)
211
+ .toDate();
212
+ commitDate(newTime, "time");
213
+ }), children: minute.label }, minute.value));
117
214
  });
118
215
  };
119
216
  // new 2
@@ -124,8 +221,12 @@ const Calendar = ({ defaultValue = new Date(), value, onChange = () => { }, hour
124
221
  .hours(includeTime ? calendarState.hours : 0)
125
222
  .minutes(includeTime ? calendarState.minutes : 0)
126
223
  .toDate();
127
- !(_value && isSameDay(newTime, _value)) && addDateToState(newTime);
128
- onChange(newTime);
224
+ if (!(_value && isSameDay(newTime, _value))) {
225
+ commitDate(newTime, "date");
226
+ return;
227
+ }
228
+ syncCalendarState(newTime);
229
+ onChange(newTime, { source: "date" });
129
230
  };
130
231
  const gotoPreviousMonth = () => {
131
232
  const { month, year } = calendarState;
@@ -202,7 +303,7 @@ const Calendar = ({ defaultValue = new Date(), value, onChange = () => { }, hour
202
303
  // const clearDayTimeout = () => {
203
304
  // dayTimeout && clearTimeout(dayTimeout);
204
305
  // };
205
- return (_jsxs(MainContainer, { children: [_jsxs(CalendarContainer, { children: [renderMonthAndYear(), _jsxs(CalendarGrid, { children: [_jsx(Fragment, { children: Object.keys(WEEK_DAYS).map(renderDayLabel) }), _jsx(Fragment, { children: getCalendarDates().map(renderCalendarDate) })] }), clearable && (_jsx("div", { style: { textAlign: "center", marginTop: 3 }, children: _jsx(NoValueButton, { onClick: () => onChange(null), children: "Clear Date" }) }))] }), includeTime && (_jsxs(TimeContainer, { children: [_jsx(TimeHeader, { children: "Select Time" }), _jsxs(TimePickerContainer, { children: [_jsx(TimeHourSelect, { children: renderHours() }), _jsx(TimeMinuteSelect, { children: renderMinutes() })] })] }))] }));
306
+ return (_jsxs(MainContainer, { children: [_jsxs(CalendarContainer, { children: [renderMonthAndYear(), _jsxs(CalendarGrid, { role: "grid", "aria-label": `Calendar view for ${Object.keys(CALENDAR_MONTHS)[calendarState.month - 1]} ${calendarState.year}`, children: [_jsx(Fragment, { children: Object.keys(WEEK_DAYS).map(renderDayLabel) }), _jsx(Fragment, { children: getCalendarDates().map(renderCalendarDate) })] }), clearable && (_jsx("div", { style: { textAlign: "center", marginTop: 3 }, children: _jsx(NoValueButton, { type: "button", onClick: () => commitDate(null, "clear"), "aria-label": "Clear selected date", children: "Clear Date" }) }))] }), includeTime && (_jsxs(TimeContainer, { children: [_jsx(TimeHeader, { children: "Select Time" }), _jsxs(TimePickerContainer, { children: [_jsx(TimeHourSelect, { children: renderHours() }), _jsx(TimeMinuteSelect, { children: renderMinutes() })] })] }))] }));
206
307
  };
207
308
  Calendar.displayName = "Calendar";
208
309
  export default Calendar;
@@ -1,8 +1,11 @@
1
1
  export declare const MainContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
2
2
  export declare const CalendarContainer: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
3
3
  export declare const CalendarHeader: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
4
+ export declare const CalendarHeaderControls: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
5
+ export declare const CalendarNavButton: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").ButtonHTMLAttributes<HTMLButtonElement>, HTMLButtonElement>, never>> & string;
4
6
  export declare const CalendarGrid: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
5
7
  export declare const CalendarMonth: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
8
+ export declare const CalendarHeaderSelect: import("styled-components/dist/types").IStyledComponentBase<"web", import("styled-components").FastOmit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
6
9
  interface CalendarCellProps {
7
10
  index?: number;
8
11
  inMonth?: boolean | 0;
@@ -1,70 +1,133 @@
1
1
  import styled from "styled-components";
2
2
  export const MainContainer = styled.div `
3
3
  display: flex;
4
+ align-items: flex-start;
5
+ gap: 8px;
4
6
  `;
5
7
  export const CalendarContainer = styled.div `
6
- font-size: 5px;
7
- width: 250px;
8
+ width: 264px;
8
9
  border-radius: 4px;
9
10
  overflow: hidden;
11
+ box-sizing: border-box;
10
12
  `;
11
13
  export const CalendarHeader = styled.div `
12
14
  display: flex;
13
15
  align-items: center;
14
16
  justify-content: space-between;
17
+ gap: 4px;
18
+ padding: 0 2px 6px;
19
+ `;
20
+ export const CalendarHeaderControls = styled.div `
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: center;
24
+ gap: 4px;
25
+ flex: 1;
26
+ min-width: 0;
27
+ `;
28
+ export const CalendarNavButton = styled.button `
29
+ display: inline-flex;
30
+ align-items: center;
31
+ justify-content: center;
32
+ padding: 4px;
33
+ border: none;
34
+ border-radius: 4px;
35
+ background: transparent;
36
+ color: ${(props) => props.theme.palette.text.secondary};
37
+ cursor: pointer;
38
+ transition: background 0.2s ease-out;
39
+
40
+ &:hover {
41
+ background: ${(props) => props.theme.palette.action.hover};
42
+ }
43
+
44
+ &:focus-visible {
45
+ outline: 2px solid ${(props) => props.theme.palette.primary.main};
46
+ outline-offset: 2px;
47
+ }
15
48
  `;
16
49
  export const CalendarGrid = styled.div `
17
50
  display: grid;
18
51
  grid-template: repeat(7, auto) / repeat(7, auto);
52
+ gap: 3px;
19
53
  `;
20
54
  export const CalendarMonth = styled.div `
21
55
  font-weight: 500;
22
56
  font-size: 12px;
23
57
  color: ${(props) => props.theme.palette.text.primary};
24
58
  text-align: center;
25
- padding: 0.5em 0.25em;
59
+ padding: 8px 4px;
26
60
  word-spacing: 5px;
27
61
  user-select: none;
62
+ flex: 1;
63
+ `;
64
+ export const CalendarHeaderSelect = styled.div `
65
+ .mfui-DropDownMenu {
66
+ min-width: 0;
67
+ }
28
68
  `;
29
69
  export const CalendarCell = styled.div `
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: center;
30
73
  text-align: center;
31
74
  align-self: center;
32
75
  letter-spacing: 0.1rem;
33
- padding: 7px;
76
+ min-width: 32px;
77
+ min-height: 32px;
78
+ padding: 6px 4px;
34
79
  user-select: none;
35
80
  border-radius: 5px;
36
81
  border: 1px solid transparent;
82
+ box-sizing: border-box;
37
83
  grid-column: ${({ index = 0 }) => (index % 7) + 1} / span 1;
38
84
  `;
39
85
  export const CalendarDay = styled(CalendarCell) `
40
86
  font-weight: bold;
41
- font-size: 10px;
87
+ font-size: 11px;
42
88
  border-radius: 0px;
43
89
  color: ${(props) => props.theme.palette.text.secondary};
90
+ min-height: 24px;
44
91
  `;
45
92
  export const CalendarDate = styled(CalendarCell) `
46
93
  font-weight: ${(props) => (props.inMonth ? 500 : 300)};
47
- font-size: 10px;
94
+ font-size: 11px;
95
+ line-height: 1.1;
48
96
  cursor: pointer;
49
97
 
50
98
  color: ${({ inMonth, theme }) => inMonth ? theme.palette.text.primary : theme.palette.text.secondary};
99
+ background: transparent;
100
+ opacity: ${({ inMonth }) => (inMonth ? 1 : 0.65)};
51
101
  grid-row: ${({ index }) => Math.floor((index || 0) / 7) + 2} / span 1;
52
102
  transition: all 0.2s ease-out;
53
103
  border-radius: 5px;
54
104
  &:hover {
55
105
  background: ${({ theme }) => theme.palette.action.hover};
106
+ opacity: 1;
107
+ }
108
+
109
+ &:focus-visible {
110
+ outline: 2px solid ${({ theme }) => theme.palette.primary.main};
111
+ outline-offset: 1px;
56
112
  }
57
113
 
58
114
  &[data-disabled="true"] {
59
115
  pointer-events: none;
60
116
  color: ${({ theme }) => theme.palette.text.disabled};
117
+ background: ${({ theme }) => `${theme.palette.action.hover}99`};
118
+ opacity: 0.45;
119
+ border-style: dashed;
61
120
  }
62
121
  `;
63
122
  export const HighlightedCalendarDate = styled(CalendarDate) `
64
123
  color: white !important;
65
124
  background: ${(props) => props.theme.palette.primary.main} !important;
66
125
  border: 1px solid ${(props) => props.theme.palette.primary.main} !important;
126
+ font-weight: 700;
127
+ opacity: 1;
67
128
  position: relative;
129
+ box-shadow: inset 0 0 0 1px ${(props) => props.theme.palette.primary.main},
130
+ 0 4px 10px ${(props) => `${props.theme.palette.primary.main}33`};
68
131
  ::before {
69
132
  content: "";
70
133
  position: absolute;
@@ -76,24 +139,29 @@ export const HighlightedCalendarDate = styled(CalendarDate) `
76
139
  `;
77
140
  export const TodayCalendarDate = styled(HighlightedCalendarDate) `
78
141
  color: ${(props) => props.theme.palette.text.primary} !important;
79
- background: transparent !important;
142
+ background: ${(props) => `${props.theme.palette.primary.main}14`} !important;
143
+ border: 1px dashed ${(props) => props.theme.palette.primary.main} !important;
144
+ box-shadow: none;
145
+ font-weight: 600;
80
146
  ::after {
81
147
  content: "";
82
148
  position: absolute;
83
- right: 0;
84
- bottom: 0;
85
- border-bottom: 0.75em solid #06c;
86
- border-left: 0.75em solid transparent;
87
- border-top: 0.75em solid transparent;
149
+ left: 50%;
150
+ bottom: 3px;
151
+ width: 4px;
152
+ height: 4px;
153
+ border-radius: 999px;
154
+ background: ${(props) => props.theme.palette.primary.main};
155
+ transform: translateX(-50%);
88
156
  }
89
157
  :hover {
90
158
  color: ${(props) => props.theme.palette.text.primary} !important;
91
- background: ${(props) => props.theme.palette.action.hover} !important;
159
+ background: ${(props) => `${props.theme.palette.primary.main}20`} !important;
92
160
  }
93
161
  `;
94
162
  export const TimeContainer = styled.div `
95
163
  font-size: 12px;
96
- width: 150px;
164
+ width: 152px;
97
165
  height: 100%;
98
166
  border: 1px solid ${(props) => props.theme.palette.divider};
99
167
  border-left: none;
@@ -138,6 +206,11 @@ export const TimeItem = styled.div `
138
206
  :hover {
139
207
  background: ${(props) => props.theme.palette.action.hover};
140
208
  }
209
+
210
+ &:focus-visible {
211
+ outline: 2px solid ${(props) => props.theme.palette.primary.main};
212
+ outline-offset: -2px;
213
+ }
141
214
  `;
142
215
  export const TimeItemActive = styled(TimeItem) `
143
216
  background: ${(props) => props.theme.palette.primary.main};
@@ -161,4 +234,9 @@ export const NoValueButton = styled.button `
161
234
  :hover {
162
235
  background: ${(props) => props.theme.palette.action.hover};
163
236
  }
237
+
238
+ &:focus-visible {
239
+ outline: 2px solid ${(props) => props.theme.palette.primary.main};
240
+ outline-offset: 2px;
241
+ }
164
242
  `;
@@ -8,7 +8,10 @@ export declare const HOURS12: {
8
8
  value: number;
9
9
  label: string;
10
10
  }[];
11
- export declare const MINUTES: (string | number)[];
11
+ export declare const MINUTES: {
12
+ value: number;
13
+ label: string;
14
+ }[];
12
15
  export declare const WEEK_DAYS: {
13
16
  Sunday: string;
14
17
  Monday: string;
@@ -35,6 +38,7 @@ export declare const CALENDAR_MONTHS: {
35
38
  };
36
39
  export declare const CALENDAR_WEEKS = 6;
37
40
  export declare const zeroPad: (value: number, length: number) => string;
41
+ export declare const createLocalDate: (year: number, month: number, day: number) => Date;
38
42
  export declare const getMonthDays: (month?: number, year?: number) => 28 | 29 | 30 | 31;
39
43
  export declare const getMonthFirstDay: (month?: number, year?: number) => number;
40
44
  export declare const isDate: (date: Date) => boolean;