cx 26.2.2 → 26.2.4

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 (335) hide show
  1. package/build/charts/Chart.d.ts.map +1 -1
  2. package/build/charts/Chart.js +5 -4
  3. package/build/charts/ColumnBarBase.d.ts +3 -3
  4. package/build/charts/ColumnBarBase.d.ts.map +1 -1
  5. package/build/charts/ColumnBarBase.js +1 -1
  6. package/build/charts/Legend.d.ts.map +1 -1
  7. package/build/charts/Legend.js +11 -4
  8. package/build/charts/Marker.d.ts +3 -3
  9. package/build/charts/Marker.d.ts.map +1 -1
  10. package/build/charts/MarkerLine.d.ts +7 -7
  11. package/build/charts/MarkerLine.d.ts.map +1 -1
  12. package/build/charts/MarkerLine.js +14 -10
  13. package/build/charts/PieChart.d.ts +4 -4
  14. package/build/charts/PieChart.d.ts.map +1 -1
  15. package/build/charts/PieChart.js +36 -14
  16. package/build/charts/PieLabel.d.ts.map +1 -1
  17. package/build/charts/PieLabel.js +2 -1
  18. package/build/charts/RangeMarker.d.ts +3 -3
  19. package/build/charts/RangeMarker.d.ts.map +1 -1
  20. package/build/charts/RangeMarker.js +1 -1
  21. package/build/charts/axis/TimeAxis.d.ts +3 -3
  22. package/build/charts/axis/TimeAxis.d.ts.map +1 -1
  23. package/build/charts/axis/TimeAxis.js +70 -21
  24. package/build/charts/helpers/SnapPointFinder.d.ts +2 -2
  25. package/build/charts/helpers/SnapPointFinder.d.ts.map +1 -1
  26. package/build/charts/helpers/ValueAtFinder.d.ts +3 -3
  27. package/build/charts/helpers/ValueAtFinder.d.ts.map +1 -1
  28. package/build/data/StructuredSelector.js +3 -4
  29. package/build/data/createAccessorModelProxy.d.ts +6 -11
  30. package/build/data/createAccessorModelProxy.d.ts.map +1 -1
  31. package/build/data/createAccessorModelProxy.js +1 -3
  32. package/build/jsx-runtime.d.ts +2 -1
  33. package/build/jsx-runtime.d.ts.map +1 -1
  34. package/build/svg/Ellipse.d.ts +5 -4
  35. package/build/svg/Ellipse.d.ts.map +1 -1
  36. package/build/svg/Ellipse.js +9 -6
  37. package/build/svg/Line.d.ts +1 -0
  38. package/build/svg/Line.d.ts.map +1 -1
  39. package/build/svg/Line.js +4 -1
  40. package/build/svg/Text.d.ts +12 -6
  41. package/build/svg/Text.d.ts.map +1 -1
  42. package/build/svg/Text.js +12 -4
  43. package/build/ui/Controller.d.ts +2 -0
  44. package/build/ui/Controller.d.ts.map +1 -1
  45. package/build/ui/Controller.js +3 -0
  46. package/build/ui/HoverSync.d.ts.map +1 -1
  47. package/build/ui/HoverSync.js +7 -2
  48. package/build/ui/Prop.d.ts +1 -1
  49. package/build/ui/Prop.d.ts.map +1 -1
  50. package/build/ui/Text.d.ts +3 -3
  51. package/build/ui/Text.d.ts.map +1 -1
  52. package/build/ui/Text.js +5 -5
  53. package/build/ui/adapter/GroupAdapter.d.ts.map +1 -1
  54. package/build/ui/adapter/GroupAdapter.js +20 -10
  55. package/build/ui/app/History.js +1 -1
  56. package/build/ui/createFunctionalComponent.d.ts +4 -1
  57. package/build/ui/createFunctionalComponent.d.ts.map +1 -1
  58. package/build/widgets/List.d.ts.map +1 -1
  59. package/build/widgets/List.js +6 -7
  60. package/build/widgets/drag-drop/DropZone.d.ts +3 -3
  61. package/build/widgets/drag-drop/DropZone.d.ts.map +1 -1
  62. package/build/widgets/form/Calendar.d.ts.map +1 -1
  63. package/build/widgets/form/Calendar.js +30 -11
  64. package/build/widgets/form/ColorField.d.ts.map +1 -1
  65. package/build/widgets/form/ColorField.js +16 -7
  66. package/build/widgets/form/DateTimeField.d.ts.map +1 -1
  67. package/build/widgets/form/DateTimeField.js +23 -10
  68. package/build/widgets/form/Field.d.ts +2 -0
  69. package/build/widgets/form/Field.d.ts.map +1 -1
  70. package/build/widgets/form/Field.js +11 -5
  71. package/build/widgets/form/LookupField.d.ts +1 -1
  72. package/build/widgets/form/LookupField.d.ts.map +1 -1
  73. package/build/widgets/form/LookupField.js +6 -6
  74. package/build/widgets/form/MonthField.d.ts.map +1 -1
  75. package/build/widgets/form/MonthField.js +15 -7
  76. package/build/widgets/form/MonthPicker.d.ts +1 -2
  77. package/build/widgets/form/MonthPicker.d.ts.map +1 -1
  78. package/build/widgets/form/MonthPicker.js +84 -41
  79. package/build/widgets/form/NumberField.d.ts +2 -0
  80. package/build/widgets/form/NumberField.d.ts.map +1 -1
  81. package/build/widgets/form/NumberField.js +45 -15
  82. package/build/widgets/form/TextField.d.ts +1 -9
  83. package/build/widgets/form/TextField.d.ts.map +1 -1
  84. package/build/widgets/form/TextField.js +1 -1
  85. package/build/widgets/form/TimeList.d.ts +3 -1
  86. package/build/widgets/form/TimeList.d.ts.map +1 -1
  87. package/build/widgets/grid/Grid.d.ts +2 -2
  88. package/build/widgets/grid/Grid.d.ts.map +1 -1
  89. package/build/widgets/grid/Grid.js +14 -11
  90. package/build/widgets/grid/Pagination.d.ts.map +1 -1
  91. package/build/widgets/grid/Pagination.js +4 -4
  92. package/build/widgets/grid/TreeNode.d.ts.map +1 -1
  93. package/build/widgets/grid/TreeNode.js +10 -2
  94. package/build/widgets/icons/folder.d.ts.map +1 -1
  95. package/build/widgets/icons/folder.js +1 -0
  96. package/build/widgets/icons/forward.d.ts.map +1 -1
  97. package/build/widgets/icons/forward.js +4 -3
  98. package/build/widgets/icons/loading.d.ts.map +1 -1
  99. package/build/widgets/icons/loading.js +6 -5
  100. package/build/widgets/icons/square.d.ts.map +1 -1
  101. package/build/widgets/icons/square.js +3 -3
  102. package/build/widgets/index.d.ts +3 -1
  103. package/build/widgets/index.d.ts.map +1 -1
  104. package/build/widgets/index.js +3 -1
  105. package/build/widgets/overlay/ContextMenu.d.ts.map +1 -1
  106. package/build/widgets/overlay/ContextMenu.js +2 -0
  107. package/build/widgets/overlay/Dropdown.d.ts +2 -1
  108. package/build/widgets/overlay/Dropdown.d.ts.map +1 -1
  109. package/build/widgets/overlay/Dropdown.js +75 -20
  110. package/build/widgets/overlay/MsgBox.d.ts +1 -0
  111. package/build/widgets/overlay/MsgBox.d.ts.map +1 -1
  112. package/build/widgets/overlay/MsgBox.js +2 -2
  113. package/build/widgets/overlay/Overlay.d.ts +32 -2
  114. package/build/widgets/overlay/Overlay.d.ts.map +1 -1
  115. package/build/widgets/overlay/Overlay.js +47 -16
  116. package/build/widgets/overlay/Toast.d.ts +1 -1
  117. package/build/widgets/overlay/Toast.d.ts.map +1 -1
  118. package/build/widgets/overlay/Toast.js +4 -1
  119. package/build/widgets/overlay/Tooltip.d.ts +6 -0
  120. package/build/widgets/overlay/Tooltip.d.ts.map +1 -1
  121. package/build/widgets/overlay/Tooltip.js +24 -9
  122. package/build/widgets/overlay/Window.d.ts.map +1 -1
  123. package/build/widgets/overlay/Window.js +24 -9
  124. package/dist/charts.css +325 -272
  125. package/dist/charts.js +11 -5
  126. package/dist/data.js +2 -2
  127. package/dist/manifest.js +853 -841
  128. package/dist/svg.css +14 -8
  129. package/dist/svg.js +9 -1
  130. package/dist/ui.js +29 -16
  131. package/dist/widgets.css +997 -294
  132. package/dist/widgets.js +319 -126
  133. package/package.json +1 -1
  134. package/src/charts/Bar.scss +13 -10
  135. package/src/charts/BarGraph.scss +31 -29
  136. package/src/charts/BubbleGraph.scss +11 -8
  137. package/src/charts/Chart.ts +5 -3
  138. package/src/charts/Column.scss +13 -10
  139. package/src/charts/ColumnBarBase.tsx +255 -230
  140. package/src/charts/ColumnGraph.scss +13 -11
  141. package/src/charts/Gridlines.scss +10 -8
  142. package/src/charts/Legend.scss +57 -50
  143. package/src/charts/Legend.tsx +257 -213
  144. package/src/charts/LegendEntry.scss +35 -29
  145. package/src/charts/LineGraph.scss +28 -25
  146. package/src/charts/Marker.scss +12 -10
  147. package/src/charts/Marker.tsx +3 -2
  148. package/src/charts/MarkerLine.scss +11 -8
  149. package/src/charts/MarkerLine.tsx +196 -177
  150. package/src/charts/PieChart.scss +12 -9
  151. package/src/charts/PieChart.tsx +717 -591
  152. package/src/charts/PieLabel.tsx +99 -81
  153. package/src/charts/Range.scss +11 -8
  154. package/src/charts/RangeMarker.tsx +204 -187
  155. package/src/charts/ScatterGraph.scss +12 -9
  156. package/src/charts/axis/Axis.scss +6 -5
  157. package/src/charts/axis/CategoryAxis.scss +10 -8
  158. package/src/charts/axis/NumericAxis.scss +9 -6
  159. package/src/charts/axis/TimeAxis.scss +9 -6
  160. package/src/charts/axis/TimeAxis.tsx +753 -637
  161. package/src/charts/axis/index.scss +4 -5
  162. package/src/charts/axis/variables.scss +4 -2
  163. package/src/charts/helpers/SnapPointFinder.ts +136 -136
  164. package/src/charts/helpers/ValueAtFinder.ts +72 -72
  165. package/src/charts/index.scss +16 -19
  166. package/src/charts/maps.scss +0 -0
  167. package/src/charts/palette.scss +11 -31
  168. package/src/charts/palette.variables.scss +23 -0
  169. package/src/charts/variables.scss +35 -3
  170. package/src/data/StructuredSelector.ts +2 -2
  171. package/src/data/createAccessorModelProxy.ts +66 -74
  172. package/src/index.scss +5 -6
  173. package/src/jsx-runtime.ts +2 -1
  174. package/src/maps.scss +5 -0
  175. package/src/svg/Ellipse.tsx +62 -55
  176. package/src/svg/Line.tsx +57 -42
  177. package/src/svg/Svg.scss +6 -6
  178. package/src/svg/Text.scss +19 -0
  179. package/src/svg/Text.tsx +172 -116
  180. package/src/svg/index.scss +3 -2
  181. package/src/svg/maps.scss +0 -0
  182. package/src/svg/variables.scss +0 -0
  183. package/src/ui/Container.spec.ts +59 -0
  184. package/src/ui/Controller.spec.tsx +30 -0
  185. package/src/ui/Controller.ts +5 -0
  186. package/src/ui/HoverSync.tsx +179 -147
  187. package/src/ui/Prop.ts +1 -1
  188. package/src/ui/Text.ts +12 -9
  189. package/src/ui/adapter/GroupAdapter.spec.ts +42 -0
  190. package/src/ui/adapter/GroupAdapter.ts +25 -14
  191. package/src/ui/app/History.ts +1 -1
  192. package/src/ui/createFunctionalComponent.spec.tsx +55 -0
  193. package/src/ui/createFunctionalComponent.ts +12 -2
  194. package/src/ui/index.scss +1 -1
  195. package/src/ui/layout/LabelsLeftLayout.scss +5 -7
  196. package/src/ui/layout/LabelsTopLayout.scss +4 -6
  197. package/src/ui/layout/index.scss +2 -3
  198. package/src/ui/maps.scss +0 -0
  199. package/src/ui/variables.scss +1 -2
  200. package/src/util/index.scss +4 -2
  201. package/src/util/maps.scss +1 -0
  202. package/src/util/scss/besm.scss +15 -0
  203. package/src/util/scss/calc.scss +103 -11
  204. package/src/util/scss/defaults.scss +24 -0
  205. package/src/util/scss/elements.scss +78 -0
  206. package/src/util/scss/global.scss +15 -0
  207. package/src/util/scss/include.scss +17 -9
  208. package/src/util/scss/index.scss +1 -9
  209. package/src/util/scss/maps.scss +2 -0
  210. package/src/util/scss/pad-size.scss +9 -0
  211. package/src/util/scss/padding.scss +6 -0
  212. package/src/util/scss/screen-size.scss +5 -0
  213. package/src/util/scss/variables.scss +6 -0
  214. package/src/util/variables.scss +1 -0
  215. package/src/variables.scss +5 -217
  216. package/src/widgets/Button.maps.scss +103 -0
  217. package/src/widgets/Button.scss +33 -9
  218. package/src/widgets/Button.variables.scss +8 -104
  219. package/src/widgets/CxCredit.scss +2 -0
  220. package/src/widgets/FlexBox.scss +16 -11
  221. package/src/widgets/Heading.scss +6 -0
  222. package/src/widgets/HighlightedSearchText.scss +8 -1
  223. package/src/widgets/Icon.scss +6 -0
  224. package/src/widgets/List.scss +7 -0
  225. package/src/widgets/List.tsx +6 -7
  226. package/src/widgets/ProgressBar.scss +9 -0
  227. package/src/widgets/Resizer.scss +9 -7
  228. package/src/widgets/Section.scss +53 -56
  229. package/src/widgets/animations.scss +4 -2
  230. package/src/widgets/box.scss +47 -0
  231. package/src/widgets/drag-drop/DragClone.scss +12 -4
  232. package/src/widgets/drag-drop/DragHandle.scss +12 -6
  233. package/src/widgets/drag-drop/DragSource.scss +12 -6
  234. package/src/widgets/drag-drop/DropZone.scss +9 -0
  235. package/src/widgets/drag-drop/DropZone.tsx +3 -3
  236. package/src/widgets/drag-drop/index.scss +4 -4
  237. package/src/widgets/drag-drop/maps.scss +7 -0
  238. package/src/widgets/drag-drop/variables.scss +8 -5
  239. package/src/widgets/form/Calendar.maps.scss +54 -0
  240. package/src/widgets/form/Calendar.scss +49 -11
  241. package/src/widgets/form/Calendar.tsx +755 -653
  242. package/src/widgets/form/Calendar.variables.scss +3 -46
  243. package/src/widgets/form/Checkbox.maps.scss +34 -0
  244. package/src/widgets/form/Checkbox.scss +14 -3
  245. package/src/widgets/form/Checkbox.variables.scss +4 -36
  246. package/src/widgets/form/ColorField.scss +21 -2
  247. package/src/widgets/form/ColorField.tsx +485 -431
  248. package/src/widgets/form/ColorPicker.maps.scss +21 -0
  249. package/src/widgets/form/ColorPicker.scss +26 -9
  250. package/src/widgets/form/ColorPicker.variables.scss +3 -16
  251. package/src/widgets/form/DateTimeField.scss +54 -21
  252. package/src/widgets/form/DateTimeField.tsx +697 -615
  253. package/src/widgets/form/DateTimePicker.scss +14 -4
  254. package/src/widgets/form/Field.maps.scss +122 -0
  255. package/src/widgets/form/Field.scss +54 -18
  256. package/src/widgets/form/Field.tsx +611 -504
  257. package/src/widgets/form/Field.variables.scss +46 -0
  258. package/src/widgets/form/HelpText.scss +8 -5
  259. package/src/widgets/form/Label.scss +10 -3
  260. package/src/widgets/form/LookupField.maps.scss +26 -0
  261. package/src/widgets/form/LookupField.scss +54 -24
  262. package/src/widgets/form/LookupField.tsx +25 -21
  263. package/src/widgets/form/MonthField.scss +48 -26
  264. package/src/widgets/form/MonthField.tsx +645 -567
  265. package/src/widgets/form/MonthPicker.maps.scss +50 -0
  266. package/src/widgets/form/MonthPicker.scss +44 -35
  267. package/src/widgets/form/MonthPicker.tsx +954 -724
  268. package/src/widgets/form/MonthPicker.variables.scss +24 -0
  269. package/src/widgets/form/NumberField.scss +19 -2
  270. package/src/widgets/form/NumberField.tsx +576 -466
  271. package/src/widgets/form/Radio.maps.scss +36 -0
  272. package/src/widgets/form/Radio.scss +12 -2
  273. package/src/widgets/form/Radio.variables.scss +3 -42
  274. package/src/widgets/form/Select.scss +25 -9
  275. package/src/widgets/form/Slider.scss +23 -14
  276. package/src/widgets/form/Switch.scss +18 -8
  277. package/src/widgets/form/TextArea.scss +14 -1
  278. package/src/widgets/form/TextField.scss +24 -3
  279. package/src/widgets/form/TextField.tsx +9 -21
  280. package/src/widgets/form/UploadButton.scss +14 -6
  281. package/src/widgets/form/ValidationError.scss +10 -6
  282. package/src/widgets/form/Wheel.scss +14 -4
  283. package/src/widgets/form/index.scss +22 -24
  284. package/src/widgets/form/maps.scss +81 -0
  285. package/src/widgets/form/variables.scss +111 -355
  286. package/src/widgets/grid/Grid.scss +19 -2
  287. package/src/widgets/grid/Grid.spec.ts +42 -0
  288. package/src/widgets/grid/Grid.tsx +18 -13
  289. package/src/widgets/grid/Pagination.scss +11 -2
  290. package/src/widgets/grid/Pagination.tsx +110 -102
  291. package/src/widgets/grid/TreeNode.scss +25 -8
  292. package/src/widgets/grid/TreeNode.tsx +127 -116
  293. package/src/widgets/grid/index.scss +3 -4
  294. package/src/widgets/grid/maps.scss +110 -0
  295. package/src/widgets/grid/variables.scss +48 -137
  296. package/src/widgets/icons/folder.tsx +1 -2
  297. package/src/widgets/icons/forward.tsx +23 -20
  298. package/src/widgets/icons/loading.tsx +22 -19
  299. package/src/widgets/icons/square.tsx +20 -17
  300. package/src/widgets/index.scss +16 -16
  301. package/src/widgets/index.ts +63 -58
  302. package/src/widgets/lists.scss +42 -0
  303. package/src/widgets/maps.scss +139 -0
  304. package/src/widgets/nav/Link.scss +14 -1
  305. package/src/widgets/nav/Menu.scss +13 -7
  306. package/src/widgets/nav/Menu.variables.scss +1 -12
  307. package/src/widgets/nav/MenuItem.scss +21 -6
  308. package/src/widgets/nav/Scroller.scss +11 -2
  309. package/src/widgets/nav/Tab.maps.scss +78 -0
  310. package/src/widgets/nav/Tab.scss +12 -6
  311. package/src/widgets/nav/Tab.variables.scss +7 -76
  312. package/src/widgets/nav/cover.scss +6 -4
  313. package/src/widgets/nav/index.scss +6 -6
  314. package/src/widgets/nav/maps.scss +32 -0
  315. package/src/widgets/nav/variables.scss +4 -11
  316. package/src/widgets/overlay/ContextMenu.ts +3 -0
  317. package/src/widgets/overlay/Dropdown.scss +47 -16
  318. package/src/widgets/overlay/Dropdown.tsx +851 -676
  319. package/src/widgets/overlay/MsgBox.tsx +125 -111
  320. package/src/widgets/overlay/Overlay.scss +60 -40
  321. package/src/widgets/overlay/Overlay.tsx +948 -800
  322. package/src/widgets/overlay/Toast.scss +42 -34
  323. package/src/widgets/overlay/Toast.ts +11 -1
  324. package/src/widgets/overlay/Tooltip.scss +27 -96
  325. package/src/widgets/overlay/Tooltip.tsx +376 -309
  326. package/src/widgets/overlay/Window.maps.scss +51 -0
  327. package/src/widgets/overlay/Window.scss +17 -17
  328. package/src/widgets/overlay/Window.tsx +291 -236
  329. package/src/widgets/overlay/Window.variables.scss +2 -43
  330. package/src/widgets/overlay/index.d.ts +11 -11
  331. package/src/widgets/overlay/index.scss +6 -15
  332. package/src/widgets/overlay/maps.scss +44 -0
  333. package/src/widgets/overlay/variables.scss +11 -42
  334. package/src/widgets/variables.scss +33 -117
  335. package/src/global.scss +0 -14
@@ -3,7 +3,12 @@
3
3
  import { Widget, VDOM } from "../../ui/Widget";
4
4
  import { Field, getFieldTooltip, FieldInstance, FieldConfig } from "./Field";
5
5
  import { Culture } from "../../ui/Culture";
6
- import { FocusManager, oneFocusOut, offFocusOut, preventFocusOnTouch } from "../../ui/FocusManager";
6
+ import {
7
+ FocusManager,
8
+ oneFocusOut,
9
+ offFocusOut,
10
+ preventFocusOnTouch,
11
+ } from "../../ui/FocusManager";
7
12
  import { StringTemplate } from "../../data/StringTemplate";
8
13
  import { monthStart } from "../../util/date/monthStart";
9
14
  import { dateDiff } from "../../util/date/dateDiff";
@@ -14,11 +19,11 @@ import { upperBoundCheck } from "../../util/date/upperBoundCheck";
14
19
  import { Console } from "../../util/Console";
15
20
  import { KeyCode } from "../../util/KeyCode";
16
21
  import {
17
- tooltipParentWillReceiveProps,
18
- tooltipParentWillUnmount,
19
- tooltipMouseMove,
20
- tooltipMouseLeave,
21
- tooltipParentDidMount,
22
+ tooltipParentWillReceiveProps,
23
+ tooltipParentWillUnmount,
24
+ tooltipMouseMove,
25
+ tooltipMouseLeave,
26
+ tooltipParentDidMount,
22
27
  } from "../overlay/tooltip-ops";
23
28
  import { Localization } from "../../ui/Localization";
24
29
  import { scrollElementIntoView } from "../../util/scrollElementIntoView";
@@ -35,214 +40,275 @@ import { parseDateInvariant } from "../../util";
35
40
  import { HtmlElement } from "../HtmlElement";
36
41
  enableCultureSensitiveFormatting();
37
42
 
38
- export class MonthPickerInstance<F extends MonthPicker = MonthPicker> extends FieldInstance<F> {
39
- isMonthDateSelectable?: (monthDate: Date) => boolean;
43
+ export class MonthPickerInstance<
44
+ F extends MonthPicker = MonthPicker,
45
+ > extends FieldInstance<F> {
46
+ isMonthDateSelectable?: (monthDate: Date) => boolean;
40
47
  }
41
48
 
42
49
  export interface MonthPickerConfig extends FieldConfig {
43
- range?: BooleanProp;
44
- from?: Prop<string | Date>;
45
- to?: Prop<string | Date>;
46
- value?: Prop<string | Date>;
47
- refDate?: Prop<string | Date>;
48
- minValue?: Prop<string | Date>;
49
- minExclusive?: BooleanProp;
50
- maxValue?: Prop<string | Date>;
51
- maxExclusive?: BooleanProp;
52
- startYear?: number;
53
- endYear?: number;
54
- bufferSize?: number;
55
- maxValueErrorText?: string;
56
- maxExclusiveErrorText?: string;
57
- minValueErrorText?: string;
58
- minExclusiveErrorText?: string;
59
- encoding?: (date: Date) => any;
60
- inclusiveTo?: boolean;
61
- onBeforeSelect?: (e: Event, instance: MonthPickerInstance, dateFrom?: Date, dateTo?: Date) => boolean;
62
- onSelect?: (instance: MonthPickerInstance, dateFrom?: Date, dateTo?: Date) => void;
63
- hideQuarters?: boolean;
64
- onCreateIsMonthDateSelectable?: (
65
- validationParams: Record<string, any>,
66
- instance: MonthPickerInstance,
67
- ) => (monthDate: Date) => boolean;
68
- handleSelect?: (e: React.MouseEvent, instance: MonthPickerInstance, dateFrom?: Date, dateTo?: Date) => void;
69
- onBlur?: string | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
70
- onFocusOut?: string | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
71
- autoFocus?: boolean;
50
+ range?: BooleanProp;
51
+ from?: Prop<string | Date>;
52
+ to?: Prop<string | Date>;
53
+ value?: Prop<string | Date>;
54
+ refDate?: Prop<string | Date>;
55
+ minValue?: Prop<string | Date>;
56
+ minExclusive?: BooleanProp;
57
+ maxValue?: Prop<string | Date>;
58
+ maxExclusive?: BooleanProp;
59
+ startYear?: number;
60
+ endYear?: number;
61
+ bufferSize?: number;
62
+ maxValueErrorText?: string;
63
+ maxExclusiveErrorText?: string;
64
+ minValueErrorText?: string;
65
+ minExclusiveErrorText?: string;
66
+ encoding?: (date: Date) => any;
67
+ inclusiveTo?: boolean;
68
+ onBeforeSelect?: (
69
+ e: Event,
70
+ instance: MonthPickerInstance,
71
+ dateFrom?: Date,
72
+ dateTo?: Date,
73
+ ) => boolean;
74
+ onSelect?: (
75
+ instance: MonthPickerInstance,
76
+ dateFrom?: Date,
77
+ dateTo?: Date,
78
+ ) => void;
79
+ hideQuarters?: boolean;
80
+ onCreateIsMonthDateSelectable?: (
81
+ validationParams: Record<string, any>,
82
+ instance: MonthPickerInstance,
83
+ ) => (monthDate: Date) => boolean;
84
+ handleSelect?: (
85
+ e: React.MouseEvent,
86
+ instance: MonthPickerInstance,
87
+ dateFrom?: Date,
88
+ dateTo?: Date,
89
+ ) => void;
90
+ onBlur?:
91
+ | string
92
+ | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
93
+ onFocusOut?:
94
+ | string
95
+ | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
96
+ autoFocus?: boolean;
72
97
  }
73
98
 
74
- export class MonthPicker<Config extends MonthPickerConfig = MonthPickerConfig> extends Field<
75
- Config,
76
- MonthPickerInstance
77
- > {
78
- declare public baseClass: string;
79
- declare public mode?: string;
80
- declare public range?: BooleanProp;
81
- declare public from?: Prop<string | Date>;
82
- declare public to?: Prop<string | Date>;
83
- declare public value?: Prop<string | Date>;
84
- declare public refDate?: Prop<string | Date>;
85
- declare public minValue?: Prop<string | Date>;
86
- declare public minExclusive?: BooleanProp;
87
- declare public maxValue?: Prop<string | Date>;
88
- declare public maxExclusive?: BooleanProp;
89
- declare public startYear: number;
90
- declare public endYear: number;
91
- declare public bufferSize: number;
92
- declare public maxValueErrorText: string;
93
- declare public maxExclusiveErrorText: string;
94
- declare public minValueErrorText: string;
95
- declare public minExclusiveErrorText: string;
96
- declare public encoding?: (date: Date) => any;
97
- declare public inclusiveTo?: boolean;
98
- declare public onBeforeSelect?: (e: Event, instance: MonthPickerInstance, dateFrom?: Date, dateTo?: Date) => boolean;
99
- declare public onSelect?: (instance: MonthPickerInstance, dateFrom?: Date, dateTo?: Date) => void;
100
- declare public hideQuarters?: boolean;
101
- declare public onCreateIsMonthDateSelectable?: (
102
- validationParams: Record<string, any>,
103
- instance: MonthPickerInstance,
104
- ) => (monthDate: Date) => boolean;
105
- declare public onBlur?: string | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
106
- declare public onFocusOut?: string | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
107
-
108
- declareData(...args: Record<string, unknown>[]): void {
109
- let values: Record<string, unknown> = {};
110
-
111
- if (this.mode == "range") {
112
- this.range = true;
113
- this.mode = "edit";
114
- Console.warn('Please use the range flag on MonthPickers. Syntax mode="range" is deprecated.', this);
115
- }
116
-
117
- if (this.range) {
118
- values = {
119
- from: null,
120
- to: null,
121
- };
122
- } else {
123
- values = {
124
- value: this.emptyValue,
125
- };
126
- }
127
-
128
- super.declareData(
129
- values,
130
- {
131
- refDate: undefined,
132
- disabled: undefined,
133
- minValue: undefined,
134
- minExclusive: undefined,
135
- maxValue: undefined,
136
- maxExclusive: undefined,
137
- },
138
- ...args,
99
+ export class MonthPicker<
100
+ Config extends MonthPickerConfig = MonthPickerConfig,
101
+ > extends Field<Config, MonthPickerInstance> {
102
+ declare public baseClass: string;
103
+ declare public mode?: string;
104
+ declare public range?: BooleanProp;
105
+ declare public from?: Prop<string | Date>;
106
+ declare public to?: Prop<string | Date>;
107
+ declare public value?: Prop<string | Date>;
108
+ declare public refDate?: Prop<string | Date>;
109
+ declare public minValue?: Prop<string | Date>;
110
+ declare public minExclusive?: BooleanProp;
111
+ declare public maxValue?: Prop<string | Date>;
112
+ declare public maxExclusive?: BooleanProp;
113
+ declare public startYear: number;
114
+ declare public endYear: number;
115
+ declare public bufferSize: number;
116
+ declare public maxValueErrorText: string;
117
+ declare public maxExclusiveErrorText: string;
118
+ declare public minValueErrorText: string;
119
+ declare public minExclusiveErrorText: string;
120
+ declare public encoding?: (date: Date) => any;
121
+ declare public inclusiveTo?: boolean;
122
+ declare public onBeforeSelect?: (
123
+ e: Event,
124
+ instance: MonthPickerInstance,
125
+ dateFrom?: Date,
126
+ dateTo?: Date,
127
+ ) => boolean;
128
+ declare public onSelect?: (
129
+ instance: MonthPickerInstance,
130
+ dateFrom?: Date,
131
+ dateTo?: Date,
132
+ ) => void;
133
+ declare public hideQuarters?: boolean;
134
+ declare public onCreateIsMonthDateSelectable?: (
135
+ validationParams: Record<string, any>,
136
+ instance: MonthPickerInstance,
137
+ ) => (monthDate: Date) => boolean;
138
+ declare public onBlur?:
139
+ | string
140
+ | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
141
+ declare public onFocusOut?:
142
+ | string
143
+ | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
144
+
145
+ declareData(...args: Record<string, unknown>[]): void {
146
+ let values: Record<string, unknown> = {};
147
+
148
+ if (this.mode == "range") {
149
+ this.range = true;
150
+ this.mode = "edit";
151
+ Console.warn(
152
+ 'Please use the range flag on MonthPickers. Syntax mode="range" is deprecated.',
153
+ this,
139
154
  );
140
- }
155
+ }
141
156
 
142
- init(): void {
143
- super.init();
144
- }
145
-
146
- prepareData(context: RenderingContext, instance: MonthPickerInstance): void {
147
- let { data } = instance;
148
- data.stateMods = {
149
- disabled: data.disabled,
157
+ if (this.range) {
158
+ values = {
159
+ from: null,
160
+ to: null,
150
161
  };
151
-
152
- if (!this.range && data.value) data.date = monthStart(parseDateInvariant(data.value));
153
-
154
- if (this.range) {
155
- if (data.from) data.from = monthStart(parseDateInvariant(data.from));
156
-
157
- if (data.to) {
158
- let date = parseDateInvariant(data.to);
159
- if (this.inclusiveTo) date.setDate(date.getDate() + 1);
160
- data.to = monthStart(date);
161
- }
162
+ } else {
163
+ values = {
164
+ value: this.emptyValue,
165
+ };
166
+ }
167
+
168
+ super.declareData(
169
+ values,
170
+ {
171
+ refDate: undefined,
172
+ disabled: undefined,
173
+ minValue: undefined,
174
+ minExclusive: undefined,
175
+ maxValue: undefined,
176
+ maxExclusive: undefined,
177
+ },
178
+ ...args,
179
+ );
180
+ }
181
+
182
+ init(): void {
183
+ super.init();
184
+ }
185
+
186
+ prepareData(context: RenderingContext, instance: MonthPickerInstance): void {
187
+ let { data } = instance;
188
+ data.stateMods = {
189
+ disabled: data.disabled,
190
+ };
191
+
192
+ if (!this.range && data.value)
193
+ data.date = monthStart(parseDateInvariant(data.value));
194
+
195
+ if (this.range) {
196
+ if (data.from) data.from = monthStart(parseDateInvariant(data.from));
197
+
198
+ if (data.to) {
199
+ let date = parseDateInvariant(data.to);
200
+ if (this.inclusiveTo) date.setDate(date.getDate() + 1);
201
+ data.to = monthStart(date);
162
202
  }
203
+ }
163
204
 
164
- if (data.refDate) data.refDate = monthStart(parseDateInvariant(data.refDate));
205
+ if (data.refDate)
206
+ data.refDate = monthStart(parseDateInvariant(data.refDate));
165
207
 
166
- if (data.maxValue) data.maxValue = monthStart(parseDateInvariant(data.maxValue));
208
+ if (data.maxValue)
209
+ data.maxValue = monthStart(parseDateInvariant(data.maxValue));
167
210
 
168
- if (data.minValue) data.minValue = monthStart(parseDateInvariant(data.minValue));
211
+ if (data.minValue)
212
+ data.minValue = monthStart(parseDateInvariant(data.minValue));
169
213
 
170
- if (this.onCreateIsMonthDateSelectable) {
171
- instance.isMonthDateSelectable = instance.invoke(
172
- "onCreateIsMonthDateSelectable",
173
- data.validationParams,
174
- instance,
175
- );
214
+ if (this.onCreateIsMonthDateSelectable) {
215
+ instance.isMonthDateSelectable = instance.invoke(
216
+ "onCreateIsMonthDateSelectable",
217
+ data.validationParams,
218
+ instance,
219
+ );
220
+ }
221
+
222
+ super.prepareData(context, instance);
223
+ }
224
+
225
+ validate(context: RenderingContext, instance: MonthPickerInstance): void {
226
+ super.validate(context, instance);
227
+ let { data } = instance;
228
+ if (!data.error && data.date) {
229
+ let d;
230
+ if (data.maxValue) {
231
+ d = dateDiff(data.date, data.maxValue);
232
+ if (d > 0)
233
+ data.error = StringTemplate.format(
234
+ this.maxValueErrorText,
235
+ data.maxValue,
236
+ );
237
+ else if (d == 0 && data.maxExclusive)
238
+ data.error = StringTemplate.format(
239
+ this.maxExclusiveErrorText,
240
+ data.maxValue,
241
+ );
176
242
  }
177
243
 
178
- super.prepareData(context, instance);
179
- }
180
-
181
- validate(context: RenderingContext, instance: MonthPickerInstance): void {
182
- super.validate(context, instance);
183
- let { data } = instance;
184
- if (!data.error && data.date) {
185
- let d;
186
- if (data.maxValue) {
187
- d = dateDiff(data.date, data.maxValue);
188
- if (d > 0) data.error = StringTemplate.format(this.maxValueErrorText, data.maxValue);
189
- else if (d == 0 && data.maxExclusive)
190
- data.error = StringTemplate.format(this.maxExclusiveErrorText, data.maxValue);
191
- }
192
-
193
- if (data.minValue) {
194
- d = dateDiff(data.date, data.minValue);
195
- if (d < 0) data.error = StringTemplate.format(this.minValueErrorText, data.minValue);
196
- else if (d == 0 && data.minExclusive)
197
- data.error = StringTemplate.format(this.minExclusiveErrorText, data.minValue);
198
- }
244
+ if (data.minValue) {
245
+ d = dateDiff(data.date, data.minValue);
246
+ if (d < 0)
247
+ data.error = StringTemplate.format(
248
+ this.minValueErrorText,
249
+ data.minValue,
250
+ );
251
+ else if (d == 0 && data.minExclusive)
252
+ data.error = StringTemplate.format(
253
+ this.minExclusiveErrorText,
254
+ data.minValue,
255
+ );
199
256
  }
200
- }
201
-
202
- renderInput(context: RenderingContext, instance: MonthPickerInstance, key: string): React.ReactNode {
203
- return (
204
- <MonthPickerComponent
205
- key={key}
206
- instance={instance}
207
- onBlur={this.onBlur}
208
- onFocusOut={this.onFocusOut}
209
- onKeyDown={this.onKeyDown}
210
- autoFocus={this.autoFocus}
211
- />
212
- );
213
- }
214
-
215
- handleSelect(
216
- e: React.KeyboardEvent | React.MouseEvent | React.TouchEvent,
217
- instance: MonthPickerInstance,
218
- date1: Date,
219
- date2: Date,
220
- ): void {
221
- let { data, widget, isMonthDateSelectable } = instance;
222
- let encode = widget.encoding || Culture.getDefaultDateEncoding();
223
-
224
- if (data.disabled) return;
225
-
226
- if (isMonthDateSelectable && !isMonthDateSelectable(date1)) return;
227
- if (!dateSelectableCheck(date1, data)) return;
228
-
229
- if (this.onBeforeSelect && instance.invoke("onBeforeSelect", e, instance, date1, date2) === false) return;
230
-
231
- if (this.range) {
232
- instance.set("from", encode(date1));
233
- let toDate = new Date(date2);
234
- if (this.inclusiveTo) toDate.setDate(toDate.getDate() - 1);
235
- instance.set("to", encode(toDate));
236
- } else instance.set("value", encode(date1));
237
-
238
- if (this.onSelect) instance.invoke("onSelect", instance, date1, date2);
239
- }
257
+ }
258
+ }
259
+
260
+ renderInput(
261
+ context: RenderingContext,
262
+ instance: MonthPickerInstance,
263
+ key: string,
264
+ ): React.ReactNode {
265
+ return (
266
+ <MonthPickerComponent
267
+ key={key}
268
+ instance={instance}
269
+ onBlur={this.onBlur}
270
+ onFocusOut={this.onFocusOut}
271
+ onKeyDown={this.onKeyDown}
272
+ autoFocus={this.autoFocus}
273
+ />
274
+ );
275
+ }
276
+
277
+ handleSelect(
278
+ e: React.KeyboardEvent | React.MouseEvent | React.TouchEvent,
279
+ instance: MonthPickerInstance,
280
+ date1: Date,
281
+ date2: Date,
282
+ ): void {
283
+ let { data, widget, isMonthDateSelectable } = instance;
284
+ let encode = widget.encoding || Culture.getDefaultDateEncoding();
285
+
286
+ if (data.disabled) return;
287
+
288
+ if (isMonthDateSelectable && !isMonthDateSelectable(date1)) return;
289
+ if (!dateSelectableCheck(date1, data)) return;
290
+
291
+ if (
292
+ this.onBeforeSelect &&
293
+ instance.invoke("onBeforeSelect", e, instance, date1, date2) === false
294
+ )
295
+ return;
296
+
297
+ if (this.range) {
298
+ instance.set("from", encode(date1));
299
+ let toDate = new Date(date2);
300
+ if (this.inclusiveTo) toDate.setDate(toDate.getDate() - 1);
301
+ instance.set("to", encode(toDate));
302
+ } else instance.set("value", encode(date1));
303
+
304
+ if (this.onSelect) instance.invoke("onSelect", instance, date1, date2);
305
+ }
240
306
  }
241
307
 
242
308
  MonthPicker.prototype.baseClass = "monthpicker";
243
309
  MonthPicker.prototype.range = false;
244
310
  MonthPicker.prototype.startYear = 1980;
245
- MonthPicker.prototype.endYear = 2030;
311
+ MonthPicker.prototype.endYear = 2050;
246
312
  MonthPicker.prototype.bufferSize = 15;
247
313
  MonthPicker.prototype.hideQuarters = false;
248
314
 
@@ -257,575 +323,739 @@ Localization.registerPrototype("cx/widgets/MonthPicker", MonthPicker);
257
323
 
258
324
  Widget.alias("month-picker", MonthPicker);
259
325
 
260
- const dateSelectableCheck = (date: Date, data: Record<string, any>): boolean => {
261
- if (data.maxValue && !upperBoundCheck(date, data.maxValue as Date, data.maxExclusive)) return false;
262
-
263
- if (data.minValue && !lowerBoundCheck(date, data.minValue as Date, data.minExclusive)) return false;
264
-
265
- return true;
326
+ const dateSelectableCheck = (
327
+ date: Date,
328
+ data: Record<string, any>,
329
+ ): boolean => {
330
+ if (
331
+ data.maxValue &&
332
+ !upperBoundCheck(date, data.maxValue as Date, data.maxExclusive)
333
+ )
334
+ return false;
335
+
336
+ if (
337
+ data.minValue &&
338
+ !lowerBoundCheck(date, data.minValue as Date, data.minExclusive)
339
+ )
340
+ return false;
341
+
342
+ return true;
266
343
  };
267
344
 
268
345
  const monthNumber = (date: Date): number => {
269
- return date.getFullYear() * 12 + date.getMonth();
346
+ return date.getFullYear() * 12 + date.getMonth();
270
347
  };
271
348
 
272
349
  interface MonthPickerComponentProps {
273
- instance: MonthPickerInstance;
274
- onBlur?: string | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
275
- onFocusOut?: string | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
276
- onKeyDown?: string | ((e: React.KeyboardEvent, instance: MonthPickerInstance) => boolean | void);
277
- autoFocus?: boolean;
350
+ instance: MonthPickerInstance;
351
+ onBlur?:
352
+ | string
353
+ | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
354
+ onFocusOut?:
355
+ | string
356
+ | ((e: React.FocusEvent, instance: MonthPickerInstance) => void);
357
+ onKeyDown?:
358
+ | string
359
+ | ((
360
+ e: React.KeyboardEvent,
361
+ instance: MonthPickerInstance,
362
+ ) => boolean | void);
363
+ autoFocus?: boolean;
278
364
  }
279
365
 
280
366
  interface MonthPickerComponentState {
281
- cursorYear: number;
282
- cursorMonth: number;
283
- cursorQuarter: number;
284
- column: string;
285
- start: number;
286
- end: number;
287
- state?: string;
288
- hover?: boolean;
289
- focused?: boolean;
290
- yearHeight?: number;
367
+ cursorYear: number;
368
+ cursorMonth: number;
369
+ cursorQuarter: number;
370
+ column: string;
371
+ start: number;
372
+ end: number;
373
+ state?: string;
374
+ focused?: boolean;
375
+ yearHeight?: number;
291
376
  }
292
377
 
293
378
  interface CursorInfo {
294
- column: string;
295
- cursorYear: number;
296
- cursorMonth: number;
297
- cursorQuarter: number;
298
- hover?: boolean;
379
+ column: string;
380
+ cursorYear: number;
381
+ cursorMonth: number;
382
+ cursorQuarter: number;
299
383
  }
300
384
 
301
- export class MonthPickerComponent extends VDOM.Component<MonthPickerComponentProps, MonthPickerComponentState> {
302
- dom: {
303
- el?: HTMLDivElement | null;
304
- table?: HTMLTableElement | null;
305
- } = {};
306
- dragStartDates?: [Date, Date];
307
-
308
- constructor(props: MonthPickerComponentProps) {
309
- super(props);
310
- let { data, widget } = props.instance;
311
-
312
- let cursor = monthStart(data.refDate ? data.refDate : data.date || data.from || new Date());
313
-
314
- this.dom = {};
385
+ export class MonthPickerComponent extends VDOM.Component<
386
+ MonthPickerComponentProps,
387
+ MonthPickerComponentState
388
+ > {
389
+ dom: {
390
+ el?: HTMLDivElement | null;
391
+ table?: HTMLTableElement | null;
392
+ } = {};
393
+ dragStartDates?: [Date, Date];
394
+
395
+ constructor(props: MonthPickerComponentProps) {
396
+ super(props);
397
+ let { data, widget } = props.instance;
398
+
399
+ let cursor = monthStart(
400
+ data.refDate ? data.refDate : data.date || data.from || new Date(),
401
+ );
402
+
403
+ this.dom = {};
404
+
405
+ this.state = {
406
+ cursorYear: cursor.getFullYear(),
407
+ cursorMonth: cursor.getMonth() + 1,
408
+ cursorQuarter: cursor.getMonth() / 3,
409
+ column: "M",
410
+ start: widget.startYear,
411
+ end: Math.min(widget.startYear + widget.bufferSize, widget.endYear),
412
+ };
413
+
414
+ this.handleMouseDown = this.handleMouseDown.bind(this);
415
+ this.handleMouseUp = this.handleMouseUp.bind(this);
416
+ this.handleMouseEnter = this.handleMouseEnter.bind(this);
417
+ this.handleKeyPress = this.handleKeyPress.bind(this);
418
+ this.handleTouchMove = this.handleTouchMove.bind(this);
419
+ this.handleTouchEnd = this.handleTouchEnd.bind(this);
420
+ }
421
+
422
+ extractCursorInfo(el: HTMLElement): CursorInfo | false {
423
+ const dataPoint = el.getAttribute("data-point");
424
+ if (!dataPoint) return false;
425
+ let parts = dataPoint.split("-");
426
+ if (parts[0] != "Y") return false;
427
+ let cursor: CursorInfo = {
428
+ column: "Y",
429
+ cursorYear: Number(parts[1]),
430
+ cursorMonth: 1,
431
+ cursorQuarter: 1,
432
+ };
433
+ if (parts.length == 4) {
434
+ cursor.column = parts[2];
435
+ if (cursor.column == "M") cursor.cursorMonth = Number(parts[3]);
436
+ else cursor.cursorQuarter = Number(parts[3]);
437
+ }
438
+ return cursor;
439
+ }
440
+
441
+ moveCursor<K extends keyof MonthPickerComponentState>(
442
+ e: React.KeyboardEvent | React.MouseEvent | React.TouchEvent,
443
+ data: Pick<MonthPickerComponentState, K>,
444
+ options: { ensureVisible?: boolean; select?: boolean } = {},
445
+ ): void {
446
+ //e.preventDefault();
447
+ e.stopPropagation();
448
+
449
+ if ("cursorYear" in data && data.cursorYear !== undefined) {
450
+ let { startYear, endYear } = this.props.instance.widget;
451
+ (data as any).cursorYear = Math.max(
452
+ startYear,
453
+ Math.min(endYear, data.cursorYear as number),
454
+ );
455
+ }
315
456
 
316
- this.state = {
317
- cursorYear: cursor.getFullYear(),
318
- cursorMonth: cursor.getMonth() + 1,
319
- cursorQuarter: cursor.getMonth() / 3,
320
- column: "M",
321
- start: widget.startYear,
322
- end: Math.min(widget.startYear + widget.bufferSize, widget.endYear),
323
- };
457
+ if (Object.keys(data).every((k) => this.state[k as K] == (data as any)[k]))
458
+ return;
324
459
 
325
- this.handleMouseDown = this.handleMouseDown.bind(this);
326
- this.handleMouseUp = this.handleMouseUp.bind(this);
327
- this.handleMouseEnter = this.handleMouseEnter.bind(this);
328
- this.handleKeyPress = this.handleKeyPress.bind(this);
329
- this.handleTouchMove = this.handleTouchMove.bind(this);
330
- this.handleTouchEnd = this.handleTouchEnd.bind(this);
331
- }
332
-
333
- extractCursorInfo(el: HTMLElement): CursorInfo | false {
334
- const dataPoint = el.getAttribute("data-point");
335
- if (!dataPoint) return false;
336
- let parts = dataPoint.split("-");
337
- if (parts[0] != "Y") return false;
338
- let cursor: CursorInfo = {
339
- column: "Y",
340
- cursorYear: Number(parts[1]),
341
- cursorMonth: 1,
342
- cursorQuarter: 1,
343
- };
344
- if (parts.length == 4) {
345
- cursor.column = parts[2];
346
- if (cursor.column == "M") cursor.cursorMonth = Number(parts[3]);
347
- else cursor.cursorQuarter = Number(parts[3]);
348
- }
349
- return cursor;
350
- }
351
-
352
- moveCursor<K extends keyof MonthPickerComponentState>(
353
- e: React.KeyboardEvent | React.MouseEvent | React.TouchEvent,
354
- data: Pick<MonthPickerComponentState, K>,
355
- options: { ensureVisible?: boolean } = {},
356
- ): void {
357
- e.preventDefault();
358
- e.stopPropagation();
359
-
360
- if ("cursorYear" in data && data.cursorYear !== undefined) {
361
- let { startYear, endYear } = this.props.instance.widget;
362
- (data as any).cursorYear = Math.max(startYear, Math.min(endYear, data.cursorYear as number));
460
+ this.setState(data, () => {
461
+ if (options.ensureVisible) {
462
+ let index = this.state.cursorYear - this.state.start;
463
+ let tbody = this.dom.table?.children?.[index];
464
+ if (tbody) scrollElementIntoView(tbody);
363
465
  }
364
466
 
365
- if (Object.keys(data).every((k) => this.state[k as K] == (data as any)[k])) return;
366
-
367
- this.setState(data, () => {
368
- if (options.ensureVisible) {
369
- let index = this.state.cursorYear - this.state.start;
370
- let tbody = this.dom.table?.children?.[index];
371
- if (tbody) scrollElementIntoView(tbody);
372
- }
373
- });
374
- }
375
-
376
- handleKeyPress(e: React.KeyboardEvent): void {
377
- let { instance } = this.props;
378
- let { widget } = this.props.instance;
379
- let { cursorMonth, cursorYear, cursorQuarter, column } = this.state;
380
-
381
- switch (e.keyCode) {
382
- case KeyCode.enter:
383
- // if (widget.range && e.shiftKey && !this.dragStartDates) {
384
- // this.handleMouseDown(e, {}, false);
385
- // } else {
386
- // this.handleMouseUp(e);
387
- // }
388
- this.handleMouseUp(e);
389
- e.preventDefault();
390
- e.stopPropagation();
391
- break;
392
-
393
- case KeyCode.left:
394
- if (column == "Y") this.moveCursor(e, { cursorQuarter: 3, cursorYear: cursorYear - 1, column: "Q" });
395
- else if (column == "Q") this.moveCursor(e, { cursorMonth: cursorQuarter * 4, column: "M" });
396
- else if (column == "M" && (cursorMonth - 1) % 3 == 0) this.moveCursor(e, { column: "Y" });
397
- else this.moveCursor(e, { cursorMonth: cursorMonth - 1 });
398
- break;
399
-
400
- case KeyCode.right:
401
- if (column == "Y") this.moveCursor(e, { cursorMonth: 1, column: "M" });
402
- else if (column == "Q")
403
- this.moveCursor(e, { column: "Y", cursorYear: cursorQuarter == 3 ? cursorYear + 1 : cursorYear });
404
- else if (column == "M" && (cursorMonth - 1) % 3 == 2)
405
- this.moveCursor(e, { column: "Q", cursorQuarter: Math.floor((cursorMonth - 1) / 3) });
406
- else this.moveCursor(e, { cursorMonth: cursorMonth + 1 });
407
- break;
408
-
409
- case KeyCode.up:
410
- if (column == "Y") this.moveCursor(e, { cursorYear: cursorYear - 1 }, { ensureVisible: true });
411
- else if (column == "Q")
412
- this.moveCursor(
413
- e,
414
- {
415
- cursorQuarter: (cursorQuarter + 3) % 4,
416
- cursorYear: cursorQuarter == 0 ? cursorYear - 1 : cursorYear,
417
- },
418
- { ensureVisible: true },
419
- );
420
- else if (column == "M")
421
- if (cursorMonth > 3) this.moveCursor(e, { cursorMonth: cursorMonth - 3 }, { ensureVisible: true });
422
- else
423
- this.moveCursor(
424
- e,
425
- { cursorMonth: cursorMonth + 9, cursorYear: cursorYear - 1 },
426
- { ensureVisible: true },
427
- );
428
- break;
429
-
430
- case KeyCode.down:
431
- if (column == "Y") this.moveCursor(e, { cursorYear: cursorYear + 1 }, { ensureVisible: true });
432
- else if (column == "Q")
433
- this.moveCursor(
434
- e,
435
- {
436
- cursorQuarter: (cursorQuarter + 1) % 4,
437
- cursorYear: cursorQuarter == 3 ? cursorYear + 1 : cursorYear,
438
- },
439
- { ensureVisible: true },
440
- );
441
- else if (column == "M")
442
- if (cursorMonth < 10) this.moveCursor(e, { cursorMonth: cursorMonth + 3 }, { ensureVisible: true });
443
- else
444
- this.moveCursor(
445
- e,
446
- { cursorMonth: cursorMonth - 9, cursorYear: cursorYear + 1 },
447
- { ensureVisible: true },
448
- );
449
- break;
450
-
451
- case KeyCode.pageUp:
452
- this.moveCursor(e, { cursorYear: this.state.cursorYear - 1 });
453
- break;
454
-
455
- case KeyCode.pageDown:
456
- this.moveCursor(e, { cursorYear: this.state.cursorYear + 1 });
457
- break;
458
-
459
- default:
460
- if (widget.onKeyDown) instance.invoke("onKeyDown", e, instance);
461
- break;
467
+ if (options.select) {
468
+ let { instance } = this.props;
469
+ let { widget, data } = instance;
470
+
471
+ let [cursorFromDate, cursorToDate] = this.getCursorDates();
472
+ let originFromDate = cursorFromDate,
473
+ originToDate = cursorToDate;
474
+
475
+ if (widget.range) {
476
+ if (data.from) originFromDate = data.from;
477
+ if (data.to) originToDate = data.to;
478
+ }
479
+
480
+ widget.handleSelect(
481
+ e,
482
+ instance,
483
+ minDate(originFromDate, cursorFromDate),
484
+ maxDate(originToDate, cursorToDate),
485
+ );
462
486
  }
463
- }
464
-
465
- handleBlur(e: React.FocusEvent): void {
466
- FocusManager.nudge();
467
- let { instance } = this.props;
468
- let { widget } = instance;
469
- if (widget.onBlur) instance.invoke("onBlur", e, instance);
470
- this.setState({
471
- focused: false,
472
- });
473
- }
474
-
475
- handleFocus(e: React.FocusEvent): void {
487
+ });
488
+ }
489
+
490
+ handleKeyPress(e: React.KeyboardEvent): void {
491
+ let { instance } = this.props;
492
+ let { widget } = this.props.instance;
493
+ let { cursorMonth, cursorYear, cursorQuarter, column } = this.state;
494
+ let select = widget.range && e.shiftKey;
495
+
496
+ switch (e.keyCode) {
497
+ case KeyCode.enter:
498
+ // if (widget.range && e.shiftKey && !this.dragStartDates) {
499
+ // this.handleMouseDown(e, {}, false);
500
+ // } else {
501
+ // this.handleMouseUp(e);
502
+ // }
503
+ this.handleMouseUp(e);
504
+ e.preventDefault();
505
+ e.stopPropagation();
506
+ break;
507
+
508
+ case KeyCode.left:
509
+ if (column == "Y")
510
+ this.moveCursor(
511
+ e,
512
+ {
513
+ cursorQuarter: 3,
514
+ cursorYear: cursorYear - 1,
515
+ column: "Q",
516
+ },
517
+ { select },
518
+ );
519
+ else if (column == "Q")
520
+ this.moveCursor(
521
+ e,
522
+ { cursorMonth: cursorQuarter * 4, column: "M" },
523
+ { select },
524
+ );
525
+ else if (column == "M" && (cursorMonth - 1) % 3 == 0)
526
+ this.moveCursor(e, { column: "Y" });
527
+ else this.moveCursor(e, { cursorMonth: cursorMonth - 1 }, { select });
528
+ break;
529
+
530
+ case KeyCode.right:
531
+ if (column == "Y")
532
+ this.moveCursor(e, { cursorMonth: 1, column: "M" }, { select });
533
+ else if (column == "Q")
534
+ this.moveCursor(
535
+ e,
536
+ {
537
+ column: "Y",
538
+ cursorYear: cursorQuarter == 3 ? cursorYear + 1 : cursorYear,
539
+ },
540
+ { select },
541
+ );
542
+ else if (column == "M" && (cursorMonth - 1) % 3 == 2)
543
+ this.moveCursor(
544
+ e,
545
+ {
546
+ column: "Q",
547
+ cursorQuarter: Math.floor((cursorMonth - 1) / 3),
548
+ },
549
+ { select },
550
+ );
551
+ else this.moveCursor(e, { cursorMonth: cursorMonth + 1 }, { select });
552
+ break;
553
+
554
+ case KeyCode.up:
555
+ e.preventDefault(); // prevent scroll
556
+ if (column == "Y")
557
+ this.moveCursor(
558
+ e,
559
+ { cursorYear: cursorYear - 1 },
560
+ { ensureVisible: true, select },
561
+ );
562
+ else if (column == "Q")
563
+ this.moveCursor(
564
+ e,
565
+ {
566
+ cursorQuarter: (cursorQuarter + 3) % 4,
567
+ cursorYear: cursorQuarter == 0 ? cursorYear - 1 : cursorYear,
568
+ },
569
+ { ensureVisible: true, select },
570
+ );
571
+ else if (column == "M")
572
+ if (cursorMonth > 3)
573
+ this.moveCursor(
574
+ e,
575
+ { cursorMonth: cursorMonth - 3 },
576
+ { ensureVisible: true, select },
577
+ );
578
+ else
579
+ this.moveCursor(
580
+ e,
581
+ { cursorMonth: cursorMonth + 9, cursorYear: cursorYear - 1 },
582
+ { ensureVisible: true, select },
583
+ );
584
+ break;
585
+
586
+ case KeyCode.down:
587
+ e.preventDefault(); // prevent scroll
588
+ if (column == "Y")
589
+ this.moveCursor(
590
+ e,
591
+ { cursorYear: cursorYear + 1 },
592
+ { ensureVisible: true, select },
593
+ );
594
+ else if (column == "Q")
595
+ this.moveCursor(
596
+ e,
597
+ {
598
+ cursorQuarter: (cursorQuarter + 1) % 4,
599
+ cursorYear: cursorQuarter == 3 ? cursorYear + 1 : cursorYear,
600
+ },
601
+ { ensureVisible: true, select },
602
+ );
603
+ else if (column == "M")
604
+ if (cursorMonth < 10)
605
+ this.moveCursor(
606
+ e,
607
+ { cursorMonth: cursorMonth + 3 },
608
+ { ensureVisible: true, select },
609
+ );
610
+ else
611
+ this.moveCursor(
612
+ e,
613
+ { cursorMonth: cursorMonth - 9, cursorYear: cursorYear + 1 },
614
+ { ensureVisible: true, select },
615
+ );
616
+ break;
617
+
618
+ case KeyCode.pageUp:
619
+ this.moveCursor(
620
+ e,
621
+ { cursorYear: this.state.cursorYear - 1 },
622
+ { ensureVisible: true, select },
623
+ );
624
+ break;
625
+
626
+ case KeyCode.pageDown:
627
+ this.moveCursor(
628
+ e,
629
+ { cursorYear: this.state.cursorYear + 1 },
630
+ { ensureVisible: true, select },
631
+ );
632
+ break;
633
+
634
+ default:
635
+ if (widget.onKeyDown) instance.invoke("onKeyDown", e, instance);
636
+ break;
637
+ }
638
+ }
639
+
640
+ handleBlur(e: React.FocusEvent): void {
641
+ FocusManager.nudge();
642
+ let { instance } = this.props;
643
+ let { widget } = instance;
644
+ if (widget.onBlur) instance.invoke("onBlur", e, instance);
645
+ this.setState({
646
+ focused: false,
647
+ });
648
+ }
649
+
650
+ handleFocus(e: React.FocusEvent): void {
651
+ this.setState({
652
+ focused: true,
653
+ });
654
+ if (this.props.onFocusOut && this.dom.el)
655
+ oneFocusOut(this, this.dom.el, this.handleFocusOut.bind(this));
656
+ }
657
+
658
+ handleFocusOut(e: React.FocusEvent): void {
659
+ let { instance } = this.props;
660
+ let { widget } = instance;
661
+ if (widget.onFocusOut) instance.invoke("onFocusOut", e, instance);
662
+ }
663
+
664
+ getCursorDates(cursor?: CursorInfo): [Date, Date] {
665
+ let { cursorMonth, cursorYear, cursorQuarter, column } =
666
+ cursor ?? this.state;
667
+ switch (column) {
668
+ case "M":
669
+ return [
670
+ new Date(cursorYear, cursorMonth - 1, 1),
671
+ new Date(cursorYear, cursorMonth, 1),
672
+ ];
673
+
674
+ case "Q":
675
+ return [
676
+ new Date(cursorYear, cursorQuarter * 3, 1),
677
+ new Date(cursorYear, cursorQuarter * 3 + 3, 1),
678
+ ];
679
+
680
+ default:
681
+ case "Y":
682
+ return [new Date(cursorYear, 0, 1), new Date(cursorYear + 1, 0, 1)];
683
+ }
684
+ }
685
+
686
+ handleTouchMove(e: React.TouchEvent): void {
687
+ let cursorPos = getCursorPos(e);
688
+ let el = document.elementFromPoint(cursorPos.clientX, cursorPos.clientY);
689
+ if (
690
+ this.dom.table &&
691
+ el &&
692
+ this.dom.table.contains(el) &&
693
+ el instanceof HTMLElement &&
694
+ isString(el.dataset.point)
695
+ ) {
696
+ let cursor = this.extractCursorInfo(el);
697
+ if (cursor) this.moveCursor(e, cursor);
698
+ }
699
+ }
700
+
701
+ handleTouchEnd(e: React.TouchEvent): void {
702
+ if (this.state.state == "drag") this.handleMouseUp(e);
703
+ }
704
+
705
+ handleMouseEnter(e: React.MouseEvent): void {
706
+ if (this.state.state != "drag") return;
707
+ let cursor = this.extractCursorInfo(e.target as HTMLElement);
708
+ if (cursor) {
709
+ this.moveCursor(e, cursor);
710
+ }
711
+ }
712
+
713
+ handleMouseDown(
714
+ e: React.MouseEvent | React.TouchEvent,
715
+ cursor?: CursorInfo | false,
716
+ drag: boolean = true,
717
+ ): void {
718
+ let { instance } = this.props;
719
+ let { widget } = instance;
720
+
721
+ if (!cursor) {
722
+ cursor = this.extractCursorInfo(e.currentTarget as HTMLElement);
723
+ if (!cursor) return;
724
+ this.moveCursor(e, cursor, { select: !widget.range });
725
+ }
726
+
727
+ e.stopPropagation();
728
+ preventFocusOnTouch(e);
729
+
730
+ this.dragStartDates = this.getCursorDates(cursor);
731
+ if (drag) {
476
732
  this.setState({
477
- focused: true,
733
+ state: "drag",
734
+ ...cursor,
478
735
  });
479
- if (this.props.onFocusOut && this.dom.el) oneFocusOut(this, this.dom.el, this.handleFocusOut.bind(this));
480
- }
481
-
482
- handleFocusOut(e: React.FocusEvent): void {
483
- let { instance } = this.props;
484
- let { widget } = instance;
485
- if (widget.onFocusOut) instance.invoke("onFocusOut", e, instance);
486
- }
487
-
488
- getCursorDates(cursor?: CursorInfo): [Date, Date] {
489
- let { cursorMonth, cursorYear, cursorQuarter, column } = cursor ?? this.state;
490
- switch (column) {
491
- case "M":
492
- return [new Date(cursorYear, cursorMonth - 1, 1), new Date(cursorYear, cursorMonth, 1)];
493
-
494
- case "Q":
495
- return [new Date(cursorYear, cursorQuarter * 3, 1), new Date(cursorYear, cursorQuarter * 3 + 3, 1)];
496
-
497
- default:
498
- case "Y":
499
- return [new Date(cursorYear, 0, 1), new Date(cursorYear + 1, 0, 1)];
500
- }
501
- }
502
-
503
- handleTouchMove(e: React.TouchEvent): void {
504
- let cursorPos = getCursorPos(e);
505
- let el = document.elementFromPoint(cursorPos.clientX, cursorPos.clientY);
506
- if (
507
- this.dom.table &&
508
- el &&
509
- this.dom.table.contains(el) &&
510
- el instanceof HTMLElement &&
511
- isString(el.dataset.point)
512
- ) {
513
- let cursor = this.extractCursorInfo(el);
514
- if (cursor) this.moveCursor(e, cursor);
515
- }
516
- }
517
-
518
- handleTouchEnd(e: React.TouchEvent): void {
519
- if (this.state.state == "drag") this.handleMouseUp(e);
520
- }
521
-
522
- handleMouseEnter(e: React.MouseEvent): void {
523
- let cursor = this.extractCursorInfo(e.target as HTMLElement);
524
- if (cursor) {
525
- cursor.hover = !isTouchEvent();
526
- this.moveCursor(e, cursor);
527
- }
528
- }
529
-
530
- handleMouseDown(e: React.MouseEvent | React.TouchEvent, cursor?: CursorInfo | false, drag: boolean = true): void {
531
- let { instance } = this.props;
532
- let { widget } = instance;
533
-
534
- if (!cursor) {
535
- cursor = this.extractCursorInfo(e.currentTarget as HTMLElement);
536
- if (!cursor) return;
537
- this.moveCursor(e, cursor);
736
+ }
737
+ }
738
+
739
+ handleMouseUp(
740
+ e: React.KeyboardEvent | React.MouseEvent | React.TouchEvent,
741
+ ): void {
742
+ let { instance } = this.props;
743
+ let { widget, data } = instance;
744
+
745
+ e.stopPropagation();
746
+ e.preventDefault();
747
+
748
+ let [cursorFromDate, cursorToDate] = this.getCursorDates();
749
+ let originFromDate = cursorFromDate,
750
+ originToDate = cursorToDate;
751
+ if (widget.range && e.shiftKey) {
752
+ if (data.from) originFromDate = data.from;
753
+ if (data.to) originToDate = data.to;
754
+ } else if (this.state.state == "drag") {
755
+ if (widget.range) {
756
+ [originFromDate, originToDate] = this.dragStartDates!;
538
757
  }
539
-
540
- e.stopPropagation();
541
- preventFocusOnTouch(e);
542
-
543
- this.dragStartDates = this.getCursorDates(cursor);
544
- if (drag) {
545
- this.setState({
546
- state: "drag",
547
- ...cursor,
548
- });
758
+ this.setState({ state: "normal" });
759
+ } else {
760
+ //skip mouse events originated somewhere else
761
+ if (e.type != "keydown") return;
762
+ }
763
+ widget.handleSelect(
764
+ e,
765
+ instance,
766
+ minDate(originFromDate, cursorFromDate),
767
+ maxDate(originToDate, cursorToDate),
768
+ );
769
+ }
770
+
771
+ render(): React.ReactNode {
772
+ let { instance } = this.props;
773
+ let { data, widget, isMonthDateSelectable } = instance;
774
+ let { CSS, baseClass, startYear, endYear, hideQuarters } = widget;
775
+
776
+ let years = [];
777
+
778
+ let { start, end } = this.state;
779
+
780
+ let from = 10000,
781
+ to = 0,
782
+ a,
783
+ b;
784
+
785
+ if (data.date && !widget.range) {
786
+ from = monthNumber(data.date);
787
+ to = from + 0.1;
788
+ } else if (widget.range) {
789
+ if (this.state.state == "drag") {
790
+ let [originFromDate, originToDate] = this.dragStartDates!;
791
+ let [cursorFromDate, cursorToDate] = this.getCursorDates();
792
+ a = Math.min(monthNumber(originFromDate), monthNumber(cursorFromDate));
793
+ b = Math.max(monthNumber(originToDate), monthNumber(cursorToDate));
794
+ from = Math.min(a, b);
795
+ to = Math.max(a, b);
796
+ } else if (data.from && data.to) {
797
+ a = monthNumber(data.from);
798
+ b = monthNumber(data.to);
799
+ from = Math.min(a, b);
800
+ to = Math.max(a, b);
549
801
  }
550
- }
551
-
552
- handleMouseUp(e: React.KeyboardEvent | React.MouseEvent | React.TouchEvent): void {
553
- let { instance } = this.props;
554
- let { widget, data } = instance;
555
-
556
- e.stopPropagation();
557
- e.preventDefault();
558
-
559
- let [cursorFromDate, cursorToDate] = this.getCursorDates();
560
- let originFromDate = cursorFromDate,
561
- originToDate = cursorToDate;
562
- if (widget.range && e.shiftKey) {
563
- if (data.from) originFromDate = data.from;
564
- if (data.to) originToDate = data.to;
565
- } else if (this.state.state == "drag") {
566
- if (widget.range) {
567
- [originFromDate, originToDate] = this.dragStartDates!;
568
- }
569
- this.setState({ state: "normal" });
570
- } else {
571
- //skip mouse events originated somewhere else
572
- if (e.type != "keydown") return;
802
+ }
803
+
804
+ let monthNames = Culture.getDateTimeCulture().getMonthNames("short");
805
+ let showCursor = this.state.focused;
806
+
807
+ for (let y = start; y <= end; y++) {
808
+ let selectableMonths = 0b111111111111;
809
+ // Loop through the months in a year to check if all months are unselectable
810
+ for (let i = 0; i < 12; i++) {
811
+ if (
812
+ (isMonthDateSelectable &&
813
+ !isMonthDateSelectable(new Date(y, i, 1))) ||
814
+ !dateSelectableCheck(new Date(y, i, 1), data)
815
+ ) {
816
+ // Set month as unselectable at specified bit
817
+ selectableMonths &= ~(1 << i);
818
+ }
573
819
  }
574
- widget.handleSelect(e, instance, minDate(originFromDate, cursorFromDate), maxDate(originToDate, cursorToDate));
575
- }
576
-
577
- render(): React.ReactNode {
578
- let { instance } = this.props;
579
- let { data, widget, isMonthDateSelectable } = instance;
580
- let { CSS, baseClass, startYear, endYear, hideQuarters } = widget;
581
-
582
- let years = [];
583
-
584
- let { start, end } = this.state;
585
-
586
- let from = 10000,
587
- to = 0,
588
- a,
589
- b;
590
-
591
- if (data.date && !widget.range) {
592
- from = monthNumber(data.date);
593
- to = from + 0.1;
594
- } else if (widget.range) {
595
- if (this.state.state == "drag") {
596
- let [originFromDate, originToDate] = this.dragStartDates!;
597
- let [cursorFromDate, cursorToDate] = this.getCursorDates();
598
- a = Math.min(monthNumber(originFromDate), monthNumber(cursorFromDate));
599
- b = Math.max(monthNumber(originToDate), monthNumber(cursorToDate));
600
- from = Math.min(a, b);
601
- to = Math.max(a, b);
602
- } else if (data.from && data.to) {
603
- a = monthNumber(data.from);
604
- b = monthNumber(data.to);
605
- from = Math.min(a, b);
606
- to = Math.max(a, b);
607
- }
608
- }
609
-
610
- let monthNames = Culture.getDateTimeCulture().getMonthNames("short");
611
- let showCursor = this.state.hover || this.state.focused;
612
-
613
- for (let y = start; y <= end; y++) {
614
- let selectableMonths = 0b111111111111;
615
- // Loop through the months in a year to check if all months are unselectable
616
- for (let i = 0; i < 12; i++) {
617
- if (
618
- (isMonthDateSelectable && !isMonthDateSelectable(new Date(y, i, 1))) ||
619
- !dateSelectableCheck(new Date(y, i, 1), data)
620
- ) {
621
- // Set month as unselectable at specified bit
622
- selectableMonths &= ~(1 << i);
623
- }
624
- }
625
-
626
- // All bits are 0 - all months are unselectable
627
- const unselectableYear = selectableMonths === 0;
628
-
629
- let rows = [];
630
- for (let q = 0; q < 4; q++) {
631
- let row = [];
632
- if (q == 0) {
633
- row.push(
634
- <th
635
- key="year"
636
- rowSpan={4}
637
- data-point={`Y-${y}`}
638
- className={CSS.expand(
639
- CSS.element(baseClass, "year", {
640
- cursor: showCursor && this.state.column == "Y" && y == this.state.cursorYear,
641
- }),
642
- CSS.state({ unselectable: unselectableYear }),
643
- )}
644
- onMouseEnter={unselectableYear ? undefined : this.handleMouseEnter}
645
- onMouseDown={unselectableYear ? undefined : this.handleMouseDown}
646
- onMouseUp={unselectableYear ? undefined : this.handleMouseUp}
647
- >
648
- {y}
649
- </th>,
650
- );
651
- }
652
820
 
653
- for (let i = 0; i < 3; i++) {
654
- let m = q * 3 + i + 1;
655
- const unselectableMonth = (selectableMonths & (1 << (m - 1))) === 0;
656
- let mno = y * 12 + m - 1;
657
- let handle = true; //isTouchDevice(); //mno === from || mno === to - 1;
658
- row.push(
659
- <td
660
- key={`M${m}`}
661
- className={CSS.state({
662
- cursor:
663
- showCursor &&
664
- this.state.column == "M" &&
665
- y == this.state.cursorYear &&
666
- m == this.state.cursorMonth,
667
- handle,
668
- selected: mno >= from && mno < to,
669
- unselectable: unselectableMonth,
670
- })}
671
- data-point={`Y-${y}-M-${m}`}
672
- onMouseEnter={unselectableMonth ? undefined : this.handleMouseEnter}
673
- onMouseDown={unselectableMonth ? undefined : this.handleMouseDown}
674
- onMouseUp={unselectableMonth ? undefined : this.handleMouseUp}
675
- onTouchStart={unselectableMonth ? undefined : this.handleMouseDown}
676
- onTouchMove={unselectableMonth ? undefined : this.handleTouchMove}
677
- onTouchEnd={this.handleMouseUp}
678
- >
679
- {monthNames[m - 1].substr(0, 3)}
680
- </td>,
681
- );
682
- }
683
-
684
- if (!hideQuarters) {
685
- let unselectableQuarter = true;
686
- const start = q * 3;
687
- for (let i = start; i < start + 3; i++) {
688
- if ((selectableMonths & (1 << i)) !== 0) {
689
- // found a selectable month in a quarter
690
- unselectableQuarter = false;
691
- break;
692
- }
693
- }
694
-
695
- row.push(
696
- <th
697
- key={`q${q}`}
698
- className={CSS.state({
699
- cursor:
700
- showCursor &&
701
- this.state.column == "Q" &&
702
- y == this.state.cursorYear &&
703
- q == this.state.cursorQuarter,
704
- unselectable: unselectableQuarter,
705
- })}
706
- data-point={`Y-${y}-Q-${q}`}
707
- onMouseEnter={unselectableQuarter ? undefined : this.handleMouseEnter}
708
- onMouseDown={unselectableQuarter ? undefined : this.handleMouseDown}
709
- onMouseUp={unselectableQuarter ? undefined : this.handleMouseUp}
710
- >
711
- {`Q${q + 1}`}
712
- </th>,
713
- );
821
+ // All bits are 0 - all months are unselectable
822
+ const unselectableYear = selectableMonths === 0;
823
+
824
+ let rows = [];
825
+ for (let q = 0; q < 4; q++) {
826
+ let row = [];
827
+ if (q == 0) {
828
+ row.push(
829
+ <th
830
+ key="year"
831
+ rowSpan={4}
832
+ data-point={`Y-${y}`}
833
+ className={CSS.expand(
834
+ CSS.element(baseClass, "year", {
835
+ cursor:
836
+ showCursor &&
837
+ this.state.column == "Y" &&
838
+ y == this.state.cursorYear,
839
+ }),
840
+ CSS.state({ unselectable: unselectableYear }),
841
+ )}
842
+ onMouseEnter={
843
+ unselectableYear ? undefined : this.handleMouseEnter
844
+ }
845
+ onMouseDown={unselectableYear ? undefined : this.handleMouseDown}
846
+ onMouseUp={unselectableYear ? undefined : this.handleMouseUp}
847
+ >
848
+ {y}
849
+ </th>,
850
+ );
851
+ }
852
+
853
+ for (let i = 0; i < 3; i++) {
854
+ let m = q * 3 + i + 1;
855
+ const unselectableMonth = (selectableMonths & (1 << (m - 1))) === 0;
856
+ let mno = y * 12 + m - 1;
857
+ let handle = true; //isTouchDevice(); //mno === from || mno === to - 1;
858
+ row.push(
859
+ <td
860
+ key={`M${m}`}
861
+ className={CSS.state({
862
+ cursor:
863
+ showCursor &&
864
+ this.state.column == "M" &&
865
+ y == this.state.cursorYear &&
866
+ m == this.state.cursorMonth,
867
+ handle,
868
+ selected: mno >= from && mno < to,
869
+ unselectable: unselectableMonth,
870
+ })}
871
+ data-point={`Y-${y}-M-${m}`}
872
+ onMouseEnter={
873
+ unselectableMonth ? undefined : this.handleMouseEnter
874
+ }
875
+ onMouseDown={unselectableMonth ? undefined : this.handleMouseDown}
876
+ onMouseUp={unselectableMonth ? undefined : this.handleMouseUp}
877
+ onTouchStart={
878
+ unselectableMonth ? undefined : this.handleMouseDown
879
+ }
880
+ onTouchMove={unselectableMonth ? undefined : this.handleTouchMove}
881
+ onTouchEnd={this.handleMouseUp}
882
+ >
883
+ {monthNames[m - 1].substr(0, 3)}
884
+ </td>,
885
+ );
886
+ }
887
+
888
+ if (!hideQuarters) {
889
+ let unselectableQuarter = true;
890
+ const start = q * 3;
891
+ for (let i = start; i < start + 3; i++) {
892
+ if ((selectableMonths & (1 << i)) !== 0) {
893
+ // found a selectable month in a quarter
894
+ unselectableQuarter = false;
895
+ break;
714
896
  }
897
+ }
898
+
899
+ row.push(
900
+ <th
901
+ key={`q${q}`}
902
+ className={CSS.state({
903
+ cursor:
904
+ showCursor &&
905
+ this.state.column == "Q" &&
906
+ y == this.state.cursorYear &&
907
+ q == this.state.cursorQuarter,
908
+ unselectable: unselectableQuarter,
909
+ })}
910
+ data-point={`Y-${y}-Q-${q}`}
911
+ onMouseEnter={
912
+ unselectableQuarter ? undefined : this.handleMouseEnter
913
+ }
914
+ onMouseDown={
915
+ unselectableQuarter ? undefined : this.handleMouseDown
916
+ }
917
+ onMouseUp={unselectableQuarter ? undefined : this.handleMouseUp}
918
+ >
919
+ {`Q${q + 1}`}
920
+ </th>,
921
+ );
922
+ }
715
923
 
716
- rows.push(row);
717
- }
718
- years.push(rows);
924
+ rows.push(row);
719
925
  }
720
-
721
- return (
722
- <div
723
- ref={(el) => {
724
- this.dom.el = el;
926
+ years.push(rows);
927
+ }
928
+
929
+ return (
930
+ <div
931
+ ref={(el) => {
932
+ this.dom.el = el;
933
+ }}
934
+ className={data.classNames}
935
+ style={data.style}
936
+ tabIndex={data.disabled ? null : data.tabIndex || 0}
937
+ onKeyDown={this.handleKeyPress}
938
+ onMouseDown={stopPropagation}
939
+ onMouseMove={(e) =>
940
+ tooltipMouseMove(e, ...getFieldTooltip(this.props.instance))
941
+ }
942
+ onMouseLeave={this.handleMouseLeave.bind(this)}
943
+ onFocus={(e) => this.handleFocus(e)}
944
+ onBlur={this.handleBlur.bind(this)}
945
+ onScroll={this.onScroll.bind(this)}
946
+ >
947
+ {this.state.yearHeight && (
948
+ <div
949
+ style={{
950
+ height: `${(start - startYear) * this.state.yearHeight}px`,
725
951
  }}
726
- className={data.classNames}
727
- style={data.style}
728
- tabIndex={data.disabled ? null : data.tabIndex || 0}
729
- onKeyDown={this.handleKeyPress}
730
- onMouseDown={stopPropagation}
731
- onMouseMove={(e) => tooltipMouseMove(e, ...getFieldTooltip(this.props.instance))}
732
- onMouseLeave={this.handleMouseLeave.bind(this)}
733
- onFocus={(e) => this.handleFocus(e)}
734
- onBlur={this.handleBlur.bind(this)}
735
- onScroll={this.onScroll.bind(this)}
736
- >
737
- {this.state.yearHeight && <div style={{ height: `${(start - startYear) * this.state.yearHeight}px` }} />}
738
- <table
739
- ref={(el) => {
740
- this.dom.table = el;
741
- }}
742
- >
743
- {years.map((rows, y) => (
744
- <tbody key={start + y}>
745
- {rows.map((cells, i) => (
746
- <tr key={i}>{cells}</tr>
747
- ))}
748
- </tbody>
749
- ))}
750
- </table>
751
- {this.state.yearHeight && (
752
- <div style={{ height: `${Math.max(0, endYear - end) * this.state.yearHeight}px` }} />
753
- )}
754
- </div>
755
- );
756
- }
757
-
758
- onScroll(): void {
759
- if (!this.dom.el || !this.state.yearHeight) return;
760
- let { startYear, endYear, bufferSize } = this.props.instance.widget;
761
- let visibleItems = ceil5(Math.ceil(this.dom.el.offsetHeight / this.state.yearHeight));
762
- let start = Math.max(
763
- startYear,
764
- startYear + floor5(Math.floor(this.dom.el.scrollTop / this.state.yearHeight)) - visibleItems,
765
- );
766
- if (start != this.state.start && start + bufferSize <= endYear) {
767
- this.setState({
768
- start,
769
- end: start + 15,
770
- });
771
- }
772
- }
773
-
774
- handleMouseLeave(e: React.MouseEvent): void {
775
- tooltipMouseLeave(e, ...getFieldTooltip(this.props.instance));
776
- this.moveCursor(e, {
777
- hover: false,
952
+ />
953
+ )}
954
+ <table
955
+ ref={(el) => {
956
+ this.dom.table = el;
957
+ }}
958
+ >
959
+ {years.map((rows, y) => (
960
+ <tbody key={start + y}>
961
+ {rows.map((cells, i) => (
962
+ <tr key={i}>{cells}</tr>
963
+ ))}
964
+ </tbody>
965
+ ))}
966
+ </table>
967
+ {this.state.yearHeight && (
968
+ <div
969
+ style={{
970
+ height: `${Math.max(0, endYear - end) * this.state.yearHeight}px`,
971
+ }}
972
+ />
973
+ )}
974
+ </div>
975
+ );
976
+ }
977
+
978
+ onScroll(): void {
979
+ if (!this.dom.el || !this.state.yearHeight) return;
980
+ let { startYear, endYear, bufferSize } = this.props.instance.widget;
981
+ let visibleItems = ceil5(
982
+ Math.ceil(this.dom.el.offsetHeight / this.state.yearHeight),
983
+ );
984
+ let start = Math.max(
985
+ startYear,
986
+ startYear +
987
+ floor5(Math.floor(this.dom.el.scrollTop / this.state.yearHeight)) -
988
+ visibleItems,
989
+ );
990
+ if (start != this.state.start) {
991
+ this.setState({
992
+ start,
993
+ end: Math.min(start + bufferSize, endYear),
778
994
  });
779
- }
995
+ }
996
+ }
780
997
 
781
- componentDidMount(): void {
782
- //non-input, ok to focus on mobile
783
- if (this.props.autoFocus && this.dom.el) this.dom.el.focus();
998
+ handleMouseLeave(e: React.MouseEvent): void {
999
+ tooltipMouseLeave(e, ...getFieldTooltip(this.props.instance));
1000
+ }
784
1001
 
785
- if (this.dom.el && this.dom.table) {
786
- tooltipParentDidMount(this.dom.el, ...getFieldTooltip(this.props.instance));
787
- let yearHeight = this.dom.table.scrollHeight / (this.props.instance.widget.bufferSize + 1);
788
- this.setState(
789
- {
790
- yearHeight: yearHeight,
791
- },
792
- () => {
793
- let { widget, data } = this.props.instance;
794
- let { startYear } = widget;
795
- let yearCount = 1;
796
- if (widget.range && data.from && data.to) {
797
- yearCount = data.to.getFullYear() - data.from.getFullYear() + 1;
798
- if (data.to.getMonth() == 0 && data.to.getDate() == 1) yearCount--;
799
- }
800
- if (this.dom.el && this.state.yearHeight) {
801
- this.dom.el.scrollTop =
802
- (this.state.cursorYear - startYear + yearCount / 2) * this.state.yearHeight -
803
- this.dom.el.offsetHeight / 2;
804
- }
805
- },
806
- );
807
- }
808
- }
1002
+ componentDidMount(): void {
1003
+ //non-input, ok to focus on mobile
1004
+ if (this.props.autoFocus && this.dom.el) this.dom.el.focus();
809
1005
 
810
- UNSAFE_componentWillReceiveProps(props: MonthPickerComponentProps): void {
811
- this.setState({
812
- state: "normal",
813
- });
814
- if (this.dom.el) {
815
- tooltipParentWillReceiveProps(this.dom.el, ...getFieldTooltip(props.instance));
816
- }
817
- }
1006
+ if (this.dom.el && this.dom.table) {
1007
+ tooltipParentDidMount(
1008
+ this.dom.el,
1009
+ ...getFieldTooltip(this.props.instance),
1010
+ );
1011
+ let yearHeight =
1012
+ this.dom.table.scrollHeight /
1013
+ (this.props.instance.widget.bufferSize + 1);
1014
+ this.setState(
1015
+ {
1016
+ yearHeight: yearHeight,
1017
+ },
1018
+ () => {
1019
+ let { widget, data } = this.props.instance;
1020
+ let { startYear } = widget;
1021
+ let yearCount = 1;
1022
+ if (widget.range && data.from && data.to) {
1023
+ yearCount = data.to.getFullYear() - data.from.getFullYear() + 1;
1024
+ if (data.to.getMonth() == 0 && data.to.getDate() == 1) yearCount--;
1025
+ }
1026
+ if (this.dom.el && this.state.yearHeight) {
1027
+ this.dom.el.scrollTop =
1028
+ (this.state.cursorYear - startYear + yearCount / 2) *
1029
+ this.state.yearHeight -
1030
+ this.dom.el.offsetHeight / 2;
1031
+ }
1032
+ },
1033
+ );
1034
+ }
1035
+ }
1036
+
1037
+ UNSAFE_componentWillReceiveProps(props: MonthPickerComponentProps): void {
1038
+ this.setState({
1039
+ state: "normal",
1040
+ });
1041
+ if (this.dom.el) {
1042
+ tooltipParentWillReceiveProps(
1043
+ this.dom.el,
1044
+ ...getFieldTooltip(props.instance),
1045
+ );
1046
+ }
1047
+ }
818
1048
 
819
- componentWillUnmount(): void {
820
- offFocusOut(this);
821
- tooltipParentWillUnmount(this.props.instance);
822
- }
1049
+ componentWillUnmount(): void {
1050
+ offFocusOut(this);
1051
+ tooltipParentWillUnmount(this.props.instance);
1052
+ }
823
1053
  }
824
1054
 
825
1055
  function ceil5(x: number): number {
826
- return Math.ceil(x / 5) * 5;
1056
+ return Math.ceil(x / 5) * 5;
827
1057
  }
828
1058
 
829
1059
  function floor5(x: number): number {
830
- return Math.floor(x / 5) * 5;
1060
+ return Math.floor(x / 5) * 5;
831
1061
  }