@xh/hoist 87.1.1 → 87.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. package/.npmignore +39 -0
  2. package/CHANGELOG.md +108 -20
  3. package/admin/AdminUtils.ts +64 -0
  4. package/admin/App.scss +88 -0
  5. package/admin/columns/UserData.ts +30 -3
  6. package/admin/detail/RestDetailModel.ts +64 -0
  7. package/admin/detail/RestDetailPanel.ts +106 -0
  8. package/admin/tabs/activity/tracking/ActivityTrackingModel.ts +27 -94
  9. package/admin/tabs/activity/tracking/ActivityTrackingPanel.ts +23 -60
  10. package/admin/tabs/activity/tracking/detail/ActivityDetailView.ts +1 -2
  11. package/admin/tabs/general/alertBanner/AlertBannerPanel.ts +2 -13
  12. package/admin/tabs/general/config/ConfigDetailPanel.ts +72 -0
  13. package/admin/tabs/general/config/ConfigPanel.ts +41 -53
  14. package/admin/tabs/general/config/ConfigPanelModel.ts +3 -0
  15. package/admin/tabs/general/config/ConfigValue.scss +14 -0
  16. package/admin/tabs/general/config/ConfigValue.ts +104 -65
  17. package/admin/tabs/userData/jsonblob/JsonBlobDetailPanel.ts +93 -0
  18. package/admin/tabs/userData/jsonblob/JsonBlobModel.ts +4 -0
  19. package/admin/tabs/userData/jsonblob/JsonBlobPanel.ts +2 -0
  20. package/admin/tabs/userData/prefs/UserPreferenceDetailPanel.ts +62 -0
  21. package/admin/tabs/userData/prefs/UserPreferenceModel.ts +10 -3
  22. package/admin/tabs/userData/prefs/UserPreferencePanel.ts +3 -1
  23. package/admin/tabs/userData/roles/details/RoleDetails.scss +2 -19
  24. package/admin/tabs/userData/roles/details/RoleDetails.ts +13 -13
  25. package/appcontainer/AboutDialogModel.ts +1 -0
  26. package/appcontainer/AppContainerModel.ts +3 -0
  27. package/appcontainer/AppStateModel.ts +1 -0
  28. package/appcontainer/BannerSourceModel.ts +1 -0
  29. package/appcontainer/ChangelogDialogModel.ts +1 -0
  30. package/appcontainer/ColChooserOptionsModel.ts +1 -0
  31. package/appcontainer/ExceptionDialogModel.ts +1 -0
  32. package/appcontainer/FeedbackDialogModel.ts +1 -0
  33. package/appcontainer/ImpersonationBarModel.ts +1 -0
  34. package/appcontainer/MessageSourceModel.ts +1 -0
  35. package/appcontainer/OptionsDialogModel.ts +1 -0
  36. package/appcontainer/PageStateModel.ts +1 -0
  37. package/appcontainer/RouterModel.ts +2 -0
  38. package/appcontainer/SizingModeModel.ts +1 -0
  39. package/appcontainer/ThemeModel.ts +1 -0
  40. package/appcontainer/ToastSourceModel.ts +1 -0
  41. package/appcontainer/UserAgentModel.ts +1 -0
  42. package/appcontainer/ViewportSizeModel.ts +1 -0
  43. package/build/types/admin/AdminUtils.d.ts +29 -0
  44. package/build/types/admin/columns/UserData.d.ts +3 -0
  45. package/build/types/admin/detail/RestDetailModel.d.ts +20 -0
  46. package/build/types/admin/detail/RestDetailPanel.d.ts +34 -0
  47. package/build/types/admin/tabs/activity/tracking/ActivityTrackingModel.d.ts +5 -17
  48. package/build/types/admin/tabs/general/config/ConfigDetailPanel.d.ts +7 -0
  49. package/build/types/admin/tabs/general/config/ConfigValue.d.ts +10 -4
  50. package/build/types/admin/tabs/userData/jsonblob/JsonBlobDetailPanel.d.ts +3 -0
  51. package/build/types/admin/tabs/userData/prefs/UserPreferenceDetailPanel.d.ts +3 -0
  52. package/build/types/admin/tabs/userData/prefs/UserPreferenceModel.d.ts +3 -0
  53. package/build/types/appcontainer/AboutDialogModel.d.ts +1 -0
  54. package/build/types/appcontainer/AppContainerModel.d.ts +1 -0
  55. package/build/types/appcontainer/AppStateModel.d.ts +1 -0
  56. package/build/types/appcontainer/BannerSourceModel.d.ts +1 -0
  57. package/build/types/appcontainer/ChangelogDialogModel.d.ts +1 -0
  58. package/build/types/appcontainer/ColChooserOptionsModel.d.ts +1 -0
  59. package/build/types/appcontainer/ExceptionDialogModel.d.ts +1 -0
  60. package/build/types/appcontainer/FeedbackDialogModel.d.ts +1 -0
  61. package/build/types/appcontainer/ImpersonationBarModel.d.ts +1 -0
  62. package/build/types/appcontainer/MessageSourceModel.d.ts +1 -0
  63. package/build/types/appcontainer/OptionsDialogModel.d.ts +1 -0
  64. package/build/types/appcontainer/PageStateModel.d.ts +1 -0
  65. package/build/types/appcontainer/RouterModel.d.ts +1 -0
  66. package/build/types/appcontainer/SizingModeModel.d.ts +1 -0
  67. package/build/types/appcontainer/ThemeModel.d.ts +1 -0
  68. package/build/types/appcontainer/ToastSourceModel.d.ts +1 -0
  69. package/build/types/appcontainer/UserAgentModel.d.ts +1 -0
  70. package/build/types/appcontainer/ViewportSizeModel.d.ts +1 -0
  71. package/build/types/cmp/ag-grid/AgGridModel.d.ts +3 -1
  72. package/build/types/cmp/card/Card.d.ts +2 -2
  73. package/build/types/cmp/chart/ChartModel.d.ts +2 -0
  74. package/build/types/cmp/dataview/DataViewModel.d.ts +2 -0
  75. package/build/types/cmp/daterange/DateRangePickerModel.d.ts +266 -0
  76. package/build/types/cmp/daterange/DateRangePresets.d.ts +26 -0
  77. package/build/types/cmp/daterange/DateRangeUtils.d.ts +96 -0
  78. package/build/types/cmp/daterange/Types.d.ts +152 -0
  79. package/build/types/cmp/daterange/index.d.ts +4 -0
  80. package/build/types/cmp/filter/FilterChooserModel.d.ts +3 -1
  81. package/build/types/cmp/form/FormModel.d.ts +3 -1
  82. package/build/types/cmp/grid/GridModel.d.ts +2 -0
  83. package/build/types/cmp/grid/Types.d.ts +2 -0
  84. package/build/types/cmp/grid/filter/GridFilterModel.d.ts +1 -1
  85. package/build/types/cmp/grid/impl/ColumnWidthCalculator.d.ts +1 -1
  86. package/build/types/cmp/grouping/GroupingChooserModel.d.ts +3 -1
  87. package/build/types/cmp/input/HoistInputProps.d.ts +49 -2
  88. package/build/types/cmp/tab/TabContainerModel.d.ts +3 -1
  89. package/build/types/cmp/tab/TabModel.d.ts +3 -1
  90. package/build/types/cmp/treemap/TreeMapModel.d.ts +2 -0
  91. package/build/types/cmp/viewmanager/ViewManagerModel.d.ts +2 -0
  92. package/build/types/cmp/zoneGrid/ZoneGridModel.d.ts +2 -0
  93. package/build/types/core/HoistBase.d.ts +7 -0
  94. package/build/types/core/HoistProps.d.ts +26 -1
  95. package/build/types/core/model/RootRefreshContextModel.d.ts +1 -0
  96. package/build/types/core/types/Telemetry.d.ts +1 -1
  97. package/build/types/data/Store.d.ts +3 -1
  98. package/build/types/data/StoreSelectionModel.d.ts +3 -1
  99. package/build/types/data/cube/Cube.d.ts +5 -2
  100. package/build/types/data/cube/View.d.ts +2 -0
  101. package/build/types/desktop/cmp/appOption/AutoRefreshAppOption.d.ts +3 -0
  102. package/build/types/desktop/cmp/appOption/ThemeAppOption.d.ts +3 -0
  103. package/build/types/desktop/cmp/button/Button.d.ts +2 -2
  104. package/build/types/desktop/cmp/button/ButtonGroup.d.ts +2 -2
  105. package/build/types/desktop/cmp/dash/DashConfig.d.ts +2 -0
  106. package/build/types/desktop/cmp/dash/DashViewModel.d.ts +3 -1
  107. package/build/types/desktop/cmp/dash/canvas/DashCanvasModel.d.ts +1 -1
  108. package/build/types/desktop/cmp/dash/container/DashContainerModel.d.ts +1 -1
  109. package/build/types/desktop/cmp/daterange/DateRangePicker.d.ts +66 -0
  110. package/build/types/desktop/cmp/daterange/impl/CustomTab.d.ts +3 -0
  111. package/build/types/desktop/cmp/daterange/impl/DateRangePickerLocalModel.d.ts +121 -0
  112. package/build/types/desktop/cmp/daterange/impl/PeriodTab.d.ts +2 -0
  113. package/build/types/desktop/cmp/daterange/impl/PresetsTab.d.ts +3 -0
  114. package/build/types/desktop/cmp/daterange/impl/RelativeTab.d.ts +3 -0
  115. package/build/types/desktop/cmp/daterange/impl/TabUtils.d.ts +21 -0
  116. package/build/types/desktop/cmp/daterange/index.d.ts +2 -0
  117. package/build/types/desktop/cmp/dock/DockContainerModel.d.ts +3 -1
  118. package/build/types/desktop/cmp/dock/DockViewModel.d.ts +3 -1
  119. package/build/types/desktop/cmp/grouping/GroupingChooser.d.ts +4 -1
  120. package/build/types/desktop/cmp/input/IntentInput.d.ts +38 -0
  121. package/build/types/desktop/cmp/input/NumberInput.d.ts +2 -2
  122. package/build/types/desktop/cmp/input/SegmentedControl.d.ts +25 -4
  123. package/build/types/desktop/cmp/input/TextArea.d.ts +2 -2
  124. package/build/types/desktop/cmp/input/TextInput.d.ts +2 -2
  125. package/build/types/desktop/cmp/input/index.d.ts +1 -0
  126. package/build/types/desktop/cmp/leftrightchooser/LeftRightChooserModel.d.ts +3 -1
  127. package/build/types/desktop/cmp/panel/PanelModel.d.ts +3 -1
  128. package/build/types/desktop/cmp/rest/RestGridModel.d.ts +1 -1
  129. package/build/types/desktop/cmp/tab/impl/TabContainer.d.ts +1 -1
  130. package/build/types/desktop/hooks/UseHotkeys.d.ts +4 -3
  131. package/build/types/icon/Icon.d.ts +3 -0
  132. package/build/types/inspector/impl/InspectorUtils.d.ts +3 -0
  133. package/build/types/inspector/instances/InstancesModel.d.ts +4 -0
  134. package/build/types/kit/react-day-picker/index.d.ts +3 -3
  135. package/build/types/mobile/cmp/button/Button.d.ts +2 -2
  136. package/build/types/mobile/cmp/input/NumberInput.d.ts +2 -2
  137. package/build/types/mobile/cmp/input/SegmentedControl.d.ts +18 -4
  138. package/build/types/mobile/cmp/input/TextArea.d.ts +2 -2
  139. package/build/types/mobile/cmp/input/TextInput.d.ts +2 -2
  140. package/build/types/mobile/cmp/navigator/NavigatorModel.d.ts +8 -2
  141. package/build/types/mobile/cmp/navigator/PageModel.d.ts +3 -1
  142. package/build/types/mobile/cmp/tab/impl/TabContainer.d.ts +1 -1
  143. package/build/types/svc/InspectorService.d.ts +1 -0
  144. package/build/types/utils/js/LangUtils.d.ts +24 -5
  145. package/cmp/README.md +1 -0
  146. package/cmp/ag-grid/AgGridModel.ts +5 -0
  147. package/cmp/badge/Badge.ts +5 -3
  148. package/cmp/card/Card.ts +4 -3
  149. package/cmp/chart/ChartModel.ts +11 -1
  150. package/cmp/clock/Clock.ts +1 -1
  151. package/cmp/dataview/DataViewModel.ts +7 -1
  152. package/cmp/daterange/DateRangePickerModel.ts +628 -0
  153. package/cmp/daterange/DateRangePresets.ts +274 -0
  154. package/cmp/daterange/DateRangeUtils.ts +557 -0
  155. package/cmp/daterange/README.md +434 -0
  156. package/cmp/daterange/Types.ts +203 -0
  157. package/cmp/daterange/index.ts +10 -0
  158. package/cmp/filter/FilterChooserModel.ts +7 -4
  159. package/cmp/form/FormModel.ts +6 -0
  160. package/cmp/form/README.md +1 -0
  161. package/cmp/grid/GridModel.ts +24 -4
  162. package/cmp/grid/Types.ts +3 -0
  163. package/cmp/grid/filter/GridFilterModel.ts +3 -1
  164. package/cmp/grid/impl/ColumnWidthCalculator.ts +5 -10
  165. package/cmp/grouping/GroupingChooserModel.ts +6 -1
  166. package/cmp/input/HoistInputProps.ts +50 -2
  167. package/cmp/input/README.md +42 -0
  168. package/cmp/layout/Box.ts +3 -2
  169. package/cmp/tab/TabContainerModel.ts +9 -1
  170. package/cmp/tab/TabModel.ts +5 -0
  171. package/cmp/treemap/SplitTreeMapModel.ts +12 -2
  172. package/cmp/treemap/TreeMapModel.ts +6 -1
  173. package/cmp/viewmanager/ViewManagerModel.ts +6 -1
  174. package/cmp/zoneGrid/ZoneGridModel.ts +7 -0
  175. package/core/HoistBase.ts +11 -0
  176. package/core/HoistProps.ts +27 -0
  177. package/core/README.md +46 -0
  178. package/core/impl/InstallServices.ts +5 -1
  179. package/core/model/RootRefreshContextModel.ts +2 -0
  180. package/core/types/Telemetry.ts +1 -1
  181. package/data/README.md +3 -1
  182. package/data/Store.ts +7 -0
  183. package/data/StoreSelectionModel.ts +5 -1
  184. package/data/cube/Cube.ts +12 -3
  185. package/data/cube/View.ts +5 -1
  186. package/desktop/README.md +2 -0
  187. package/desktop/appcontainer/LoginPanel.ts +2 -0
  188. package/desktop/cmp/button/Button.scss +71 -42
  189. package/desktop/cmp/button/Button.ts +10 -1
  190. package/desktop/cmp/button/ButtonGroup.ts +4 -1
  191. package/desktop/cmp/button/grid/ColChooserButton.ts +9 -1
  192. package/desktop/cmp/button/zoneGrid/ZoneMapperButton.ts +1 -0
  193. package/desktop/cmp/dash/DashConfig.ts +3 -0
  194. package/desktop/cmp/dash/DashViewModel.ts +14 -1
  195. package/desktop/cmp/dash/canvas/DashCanvasModel.ts +3 -1
  196. package/desktop/cmp/dash/container/DashContainerModel.ts +3 -1
  197. package/desktop/cmp/daterange/DateRangePicker.scss +577 -0
  198. package/desktop/cmp/daterange/DateRangePicker.ts +357 -0
  199. package/desktop/cmp/daterange/impl/CustomTab.ts +165 -0
  200. package/desktop/cmp/daterange/impl/DateRangePickerLocalModel.ts +482 -0
  201. package/desktop/cmp/daterange/impl/PeriodTab.ts +138 -0
  202. package/desktop/cmp/daterange/impl/PresetsTab.ts +58 -0
  203. package/desktop/cmp/daterange/impl/RelativeTab.ts +108 -0
  204. package/desktop/cmp/daterange/impl/TabUtils.ts +34 -0
  205. package/desktop/cmp/daterange/index.ts +8 -0
  206. package/desktop/cmp/dock/DockContainerModel.ts +6 -1
  207. package/desktop/cmp/dock/DockViewModel.ts +6 -1
  208. package/desktop/cmp/filechooser/FileChooser.ts +4 -0
  209. package/desktop/cmp/form/FormField.ts +1 -0
  210. package/desktop/cmp/grid/editors/DateEditor.ts +11 -2
  211. package/desktop/cmp/grouping/GroupingChooser.ts +8 -2
  212. package/desktop/cmp/input/Checkbox.ts +1 -0
  213. package/desktop/cmp/input/CodeInput.ts +1 -0
  214. package/desktop/cmp/input/DateInput.scss +1 -1
  215. package/desktop/cmp/input/DateInput.ts +1 -0
  216. package/desktop/cmp/input/IntentInput.scss +202 -0
  217. package/desktop/cmp/input/IntentInput.ts +213 -0
  218. package/desktop/cmp/input/NumberInput.ts +11 -2
  219. package/desktop/cmp/input/Picker.ts +1 -0
  220. package/desktop/cmp/input/RadioInput.ts +2 -1
  221. package/desktop/cmp/input/SegmentedControl.scss +57 -5
  222. package/desktop/cmp/input/SegmentedControl.ts +66 -11
  223. package/desktop/cmp/input/Select.ts +9 -7
  224. package/desktop/cmp/input/Slider.ts +2 -0
  225. package/desktop/cmp/input/SwitchInput.ts +1 -0
  226. package/desktop/cmp/input/TextArea.ts +11 -2
  227. package/desktop/cmp/input/TextInput.ts +11 -2
  228. package/desktop/cmp/input/index.ts +1 -0
  229. package/desktop/cmp/leftrightchooser/LeftRightChooserModel.ts +5 -0
  230. package/desktop/cmp/panel/Panel.ts +8 -5
  231. package/desktop/cmp/panel/PanelModel.ts +8 -0
  232. package/desktop/cmp/panel/impl/ResizeContainer.ts +2 -1
  233. package/desktop/cmp/rest/RestGridModel.ts +4 -0
  234. package/desktop/cmp/tab/impl/TabContainer.ts +2 -0
  235. package/desktop/cmp/toolbar/Toolbar.scss +20 -6
  236. package/desktop/hooks/UseHotkeys.ts +41 -12
  237. package/docs/README.md +2 -0
  238. package/docs/build-and-publish.md +23 -7
  239. package/docs/doc-registry.json +8 -0
  240. package/docs/version-compatibility.md +2 -0
  241. package/icon/Icon.ts +9 -0
  242. package/icon/index.ts +24 -0
  243. package/inspector/README.md +8 -2
  244. package/inspector/impl/InspectorUtils.ts +12 -0
  245. package/inspector/instances/DiagnosticsModel.ts +3 -2
  246. package/inspector/instances/InstancesModel.ts +81 -14
  247. package/inspector/instances/InstancesPanel.ts +6 -0
  248. package/kit/react-day-picker/index.ts +3 -3
  249. package/mobile/appcontainer/LoginPanel.ts +2 -0
  250. package/mobile/cmp/button/Button.ts +16 -3
  251. package/mobile/cmp/form/FormField.ts +1 -0
  252. package/mobile/cmp/input/Checkbox.ts +1 -0
  253. package/mobile/cmp/input/DateInput.ts +1 -0
  254. package/mobile/cmp/input/Label.ts +13 -8
  255. package/mobile/cmp/input/NumberInput.ts +11 -2
  256. package/mobile/cmp/input/SearchInput.ts +1 -0
  257. package/mobile/cmp/input/SegmentedControl.scss +36 -6
  258. package/mobile/cmp/input/SegmentedControl.ts +37 -11
  259. package/mobile/cmp/input/Select.ts +2 -0
  260. package/mobile/cmp/input/SwitchInput.ts +1 -0
  261. package/mobile/cmp/input/TextArea.ts +11 -2
  262. package/mobile/cmp/input/TextInput.ts +11 -2
  263. package/mobile/cmp/navigator/NavigatorModel.ts +20 -8
  264. package/mobile/cmp/navigator/PageModel.ts +6 -1
  265. package/mobile/cmp/tab/impl/TabContainer.ts +9 -1
  266. package/package.json +19 -19
  267. package/styles/vars.scss +32 -2
  268. package/svc/InspectorService.ts +2 -0
  269. package/svc/TraceService.ts +5 -2
  270. package/utils/js/LangUtils.ts +37 -5
@@ -0,0 +1,274 @@
1
+ /*
2
+ * This file belongs to Hoist, an application development toolkit
3
+ * developed by Extremely Heavy Industries (www.xh.io | info@xh.io)
4
+ *
5
+ * Copyright © 2026 Extremely Heavy Industries Inc.
6
+ */
7
+ import type {LocalDate} from '@xh/hoist/utils/datetime';
8
+ import {fmtDateRangeOffset, nextDayInMode, previousDayInMode, singleDay} from './DateRangeUtils';
9
+ import type {
10
+ DateRangeContext,
11
+ DateRangePreset,
12
+ DateRangePresetToken,
13
+ DateRangeUnit,
14
+ LocalDateRange
15
+ } from './Types';
16
+
17
+ /**
18
+ * Presets shipped with Hoist, keyed by token. Offer any subset (in any order) via the `presets`
19
+ * config of {@link DateRangePickerModel}, alongside any app-defined {@link DateRangePreset}s.
20
+ *
21
+ * Labels describe a range without claiming it ends today, since the anchor date need not be
22
+ * today: `Prev 7 Days` rather than `Last 7 Days`. The one exception is `anchorDay`, which reads
23
+ * `Today` when the anchor date is the current day and `As Of` otherwise - the trigger's dates
24
+ * supply the day itself.
25
+ *
26
+ * Period-to-date presets (`wtd`, `mtd`, `qtd`, `ytd`) resolve their prior range as the same span
27
+ * one unit earlier - e.g. MTD on the 12th compares against the 1st through 12th of the prior
28
+ * month. Previous-unit presets (`prevWeek`, `prevMonth`, ...) compare against the unit before.
29
+ * Rolling windows compare against the window of equal length immediately preceding them. The
30
+ * same logic, mirrored by `resolveNext`, drives stepping: `mtd` stepped back once is the prior MTD.
31
+ *
32
+ * A preset that names a specific period reads the same as a pick of that period on the Months &
33
+ * Years tab - `prevMonth` labels as e.g. `Aug 2026` and `prevYear` as `2025` - so the trigger
34
+ * describes the period, whichever way it was chosen. The underlying values stay distinct: a preset
35
+ * re-resolves against the anchor date as time passes, where a pinned month or year does not.
36
+ */
37
+ export const dateRangePresets: Record<DateRangePresetToken, DateRangePreset> = {
38
+ anchorDay: {
39
+ token: 'anchorDay',
40
+ label: anchorLabel,
41
+ name: ctx => (isAnchorToday(ctx) ? 'Today' : 'As Of Date'),
42
+ resolve: ({anchorDate}) => singleDay(anchorDate),
43
+ resolvePrior: priorDay,
44
+ resolveNext: nextDay,
45
+ shiftedLabel: (range, offset, ctx) => dayFromAnchor(offset, ctx)
46
+ },
47
+ prevDay: {
48
+ token: 'prevDay',
49
+ label: 'Prev Day',
50
+ resolve: ctx => singleDay(previousDayInMode(ctx.anchorDate, ctx)),
51
+ resolvePrior: priorDay,
52
+ resolveNext: nextDay,
53
+ // Already one step back - stepped, it reads from the anchor like `anchorDay` does.
54
+ shiftedLabel: (range, offset, ctx) => dayFromAnchor(offset - 1, ctx)
55
+ },
56
+ wtd: {
57
+ token: 'wtd',
58
+ label: 'WTD',
59
+ name: 'Week to Date',
60
+ resolve: toDate('weeks'),
61
+ resolvePrior: shiftedBy('weeks', -1),
62
+ resolveNext: shiftedBy('weeks', 1)
63
+ },
64
+ mtd: {
65
+ token: 'mtd',
66
+ label: 'MTD',
67
+ name: 'Month to Date',
68
+ resolve: toDate('months'),
69
+ resolvePrior: shiftedBy('months', -1),
70
+ resolveNext: shiftedBy('months', 1)
71
+ },
72
+ qtd: {
73
+ token: 'qtd',
74
+ label: 'QTD',
75
+ name: 'Quarter to Date',
76
+ resolve: toDate('quarters'),
77
+ resolvePrior: shiftedBy('quarters', -1),
78
+ resolveNext: shiftedBy('quarters', 1)
79
+ },
80
+ ytd: {
81
+ token: 'ytd',
82
+ label: 'YTD',
83
+ name: 'Year to Date',
84
+ resolve: toDate('years'),
85
+ resolvePrior: shiftedBy('years', -1),
86
+ resolveNext: shiftedBy('years', 1)
87
+ },
88
+ prev7Days: {
89
+ token: 'prev7Days',
90
+ label: 'Prev 7 Days',
91
+ resolve: prevDays(7),
92
+ shiftedLabel: lengthLabel('7 Days')
93
+ },
94
+ prev30Days: {
95
+ token: 'prev30Days',
96
+ label: 'Prev 30 Days',
97
+ resolve: prevDays(30),
98
+ shiftedLabel: lengthLabel('30 Days')
99
+ },
100
+ prev90Days: {
101
+ token: 'prev90Days',
102
+ label: 'Prev 90 Days',
103
+ resolve: prevDays(90),
104
+ shiftedLabel: lengthLabel('90 Days')
105
+ },
106
+ prev3Months: {
107
+ token: 'prev3Months',
108
+ label: 'Prev 3 Months',
109
+ resolve: prevMonths(3),
110
+ resolvePrior: shiftedBy('months', -3),
111
+ resolveNext: shiftedBy('months', 3),
112
+ shiftedLabel: lengthLabel('3 Months')
113
+ },
114
+ prev6Months: {
115
+ token: 'prev6Months',
116
+ label: 'Prev 6 Months',
117
+ resolve: prevMonths(6),
118
+ resolvePrior: shiftedBy('months', -6),
119
+ resolveNext: shiftedBy('months', 6),
120
+ shiftedLabel: lengthLabel('6 Months')
121
+ },
122
+ prev12Months: {
123
+ token: 'prev12Months',
124
+ label: 'Prev 12 Months',
125
+ resolve: prevMonths(12),
126
+ resolvePrior: shiftedBy('years', -1),
127
+ resolveNext: shiftedBy('years', 1),
128
+ shiftedLabel: lengthLabel('12 Months')
129
+ },
130
+ prevWeek: {
131
+ token: 'prevWeek',
132
+ label: 'Prev Week',
133
+ resolve: previousUnit('weeks'),
134
+ resolvePrior: adjacentUnit('weeks', -1),
135
+ resolveNext: adjacentUnit('weeks', 1),
136
+ shiftedLabel: periodLabel('[Wk of] MMM D')
137
+ },
138
+ prevMonth: {
139
+ token: 'prevMonth',
140
+ label: ctx => previousUnitStart(ctx, 'months').format('MMM YYYY'),
141
+ name: ctx => `Prev Month (${previousUnitStart(ctx, 'months').format('MMM YYYY')})`,
142
+ resolve: previousUnit('months'),
143
+ resolvePrior: adjacentUnit('months', -1),
144
+ resolveNext: adjacentUnit('months', 1),
145
+ shiftedLabel: periodLabel('MMM YYYY')
146
+ },
147
+ prevQuarter: {
148
+ token: 'prevQuarter',
149
+ label: ctx => previousUnitStart(ctx, 'quarters').format('[Q]Q YYYY'),
150
+ name: ctx => `Prev Quarter (${previousUnitStart(ctx, 'quarters').format('[Q]Q YYYY')})`,
151
+ resolve: previousUnit('quarters'),
152
+ resolvePrior: adjacentUnit('quarters', -1),
153
+ resolveNext: adjacentUnit('quarters', 1),
154
+ shiftedLabel: periodLabel('[Q]Q YYYY')
155
+ },
156
+ prevYear: {
157
+ token: 'prevYear',
158
+ label: ctx => previousUnitStart(ctx, 'years').format('YYYY'),
159
+ name: ctx => `Prev Year (${previousUnitStart(ctx, 'years').format('YYYY')})`,
160
+ resolve: previousUnit('years'),
161
+ resolvePrior: adjacentUnit('years', -1),
162
+ resolveNext: adjacentUnit('years', 1),
163
+ shiftedLabel: periodLabel('YYYY')
164
+ },
165
+ all: {
166
+ token: 'all',
167
+ label: 'All',
168
+ name: 'All Dates',
169
+ // Everything selectable - unbounded at the start unless the model sets a `minDate`.
170
+ resolve: ({minDate, maxDate}) => ({start: minDate, end: maxDate}),
171
+ resolvePrior: () => null,
172
+ resolveNext: () => null
173
+ }
174
+ };
175
+
176
+ /** Tokens of the presets shipped with Hoist, in a sensible display order. */
177
+ export const DATE_RANGE_PRESET_TOKENS = Object.keys(dateRangePresets) as DateRangePresetToken[];
178
+
179
+ /** Presets offered by {@link DateRangePickerModel} when none are configured. */
180
+ export const DEFAULT_DATE_RANGE_PRESETS: DateRangePresetToken[] = [
181
+ 'anchorDay',
182
+ 'mtd',
183
+ 'qtd',
184
+ 'ytd',
185
+ 'prev7Days',
186
+ 'prev30Days',
187
+ 'prev90Days',
188
+ 'prev12Months',
189
+ 'prevMonth',
190
+ 'prevYear'
191
+ ];
192
+
193
+ //------------------
194
+ // Implementation
195
+ //------------------
196
+ type Resolver = DateRangePreset['resolve'];
197
+ type Shifter = DateRangePreset['resolvePrior'];
198
+ type ShiftedLabel = DateRangePreset['shiftedLabel'];
199
+
200
+ /** From the start of the unit containing the anchor date, through the anchor date. */
201
+ function toDate(unit: DateRangeUnit): Resolver {
202
+ return ({anchorDate}) => ({start: anchorDate.startOf(unit), end: anchorDate});
203
+ }
204
+
205
+ /** A rolling window of `n` days ending on the anchor date. */
206
+ function prevDays(n: number): Resolver {
207
+ return ({anchorDate}) => ({start: anchorDate.subtract(n - 1, 'days'), end: anchorDate});
208
+ }
209
+
210
+ /** A rolling window of `n` months ending on the anchor date. */
211
+ function prevMonths(n: number): Resolver {
212
+ return ({anchorDate}) => ({start: anchorDate.subtract(n, 'months').nextDay(), end: anchorDate});
213
+ }
214
+
215
+ /** The full calendar unit before the one containing the anchor date. */
216
+ function previousUnit(unit: DateRangeUnit): Resolver {
217
+ return ctx => {
218
+ const start = previousUnitStart(ctx, unit);
219
+ return {start, end: start.endOf(unit)};
220
+ };
221
+ }
222
+
223
+ function previousUnitStart({anchorDate}: DateRangeContext, unit: DateRangeUnit): LocalDate {
224
+ return anchorDate.startOf(unit).subtract(1, unit);
225
+ }
226
+
227
+ /** The current range shifted by `n` units - negative back, positive forward - keeping its shape. */
228
+ function shiftedBy(unit: DateRangeUnit, n: number): Shifter {
229
+ return ({start, end}) => ({start: start.add(n, unit), end: end.add(n, unit)});
230
+ }
231
+
232
+ /** The full calendar unit `n` units from a current range that is itself a full unit. */
233
+ function adjacentUnit(unit: DateRangeUnit, n: number): Shifter {
234
+ return ({start}) => {
235
+ const next = start.add(n, unit);
236
+ return {start: next, end: next.endOf(unit)};
237
+ };
238
+ }
239
+
240
+ /** The day before or after a single-day range - by business day in `businessDayMode`. */
241
+ function priorDay({start}: LocalDateRange, ctx: DateRangeContext): LocalDateRange {
242
+ return singleDay(previousDayInMode(start, ctx));
243
+ }
244
+
245
+ function nextDay({start}: LocalDateRange, ctx: DateRangeContext): LocalDateRange {
246
+ return singleDay(nextDayInMode(start, ctx));
247
+ }
248
+
249
+ /** Shifted label for a rolling window - its length alone, e.g. `7 Days`. */
250
+ function lengthLabel(length: string): ShiftedLabel {
251
+ return () => length;
252
+ }
253
+
254
+ /** Shifted label for a previous-unit preset - the period the range now covers. */
255
+ function periodLabel(format: string): ShiftedLabel {
256
+ return ({start}) => start.format(format);
257
+ }
258
+
259
+ function isAnchorToday({anchorDate, today}: DateRangeContext): boolean {
260
+ return anchorDate === today;
261
+ }
262
+
263
+ function anchorLabel(ctx: DateRangeContext): string {
264
+ return isAnchorToday(ctx) ? 'Today' : 'As Of';
265
+ }
266
+
267
+ /**
268
+ * A single day `n` steps from the anchor day, in the T-1 idiom finance users speak - `Today −2`,
269
+ * `As Of −1` - so a walk through single days reads the same however it began. Zero is the anchor
270
+ * day itself.
271
+ */
272
+ function dayFromAnchor(n: number, ctx: DateRangeContext): string {
273
+ return n ? `${anchorLabel(ctx)} ${fmtDateRangeOffset(n)}` : anchorLabel(ctx);
274
+ }