react-day-picker 9.6.5 → 9.6.6

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.
@@ -2,41 +2,49 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.calculateFocusTarget = calculateFocusTarget;
4
4
  const UI_js_1 = require("../UI.js");
5
+ var FocusTargetPriority;
6
+ (function (FocusTargetPriority) {
7
+ FocusTargetPriority[FocusTargetPriority["Today"] = 0] = "Today";
8
+ FocusTargetPriority[FocusTargetPriority["Selected"] = 1] = "Selected";
9
+ FocusTargetPriority[FocusTargetPriority["LastFocused"] = 2] = "LastFocused";
10
+ FocusTargetPriority[FocusTargetPriority["FocusedModifier"] = 3] = "FocusedModifier";
11
+ })(FocusTargetPriority || (FocusTargetPriority = {}));
12
+ function isFocusableDay(modifiers) {
13
+ return (!modifiers[UI_js_1.DayFlag.disabled] &&
14
+ !modifiers[UI_js_1.DayFlag.hidden] &&
15
+ !modifiers[UI_js_1.DayFlag.outside]);
16
+ }
5
17
  function calculateFocusTarget(days, getModifiers, isSelected, lastFocused) {
6
18
  let focusTarget;
7
- let index = 0;
8
- let found = false;
9
- while (index < days.length && !found) {
10
- const day = days[index];
19
+ let foundFocusTargetPriority = -1;
20
+ for (const day of days) {
11
21
  const modifiers = getModifiers(day);
12
- if (!modifiers[UI_js_1.DayFlag.disabled] &&
13
- !modifiers[UI_js_1.DayFlag.hidden] &&
14
- !modifiers[UI_js_1.DayFlag.outside]) {
15
- if (modifiers[UI_js_1.DayFlag.focused]) {
22
+ if (isFocusableDay(modifiers)) {
23
+ if (modifiers[UI_js_1.DayFlag.focused] &&
24
+ foundFocusTargetPriority < FocusTargetPriority.FocusedModifier) {
16
25
  focusTarget = day;
17
- found = true;
26
+ foundFocusTargetPriority = FocusTargetPriority.FocusedModifier;
18
27
  }
19
- else if (lastFocused?.isEqualTo(day)) {
28
+ else if (lastFocused?.isEqualTo(day) &&
29
+ foundFocusTargetPriority < FocusTargetPriority.LastFocused) {
20
30
  focusTarget = day;
21
- found = true;
31
+ foundFocusTargetPriority = FocusTargetPriority.LastFocused;
22
32
  }
23
- else if (isSelected(day.date)) {
33
+ else if (isSelected(day.date) &&
34
+ foundFocusTargetPriority < FocusTargetPriority.Selected) {
24
35
  focusTarget = day;
25
- found = true;
36
+ foundFocusTargetPriority = FocusTargetPriority.Selected;
26
37
  }
27
- else if (modifiers[UI_js_1.DayFlag.today]) {
38
+ else if (modifiers[UI_js_1.DayFlag.today] &&
39
+ foundFocusTargetPriority < FocusTargetPriority.Today) {
28
40
  focusTarget = day;
29
- found = true;
41
+ foundFocusTargetPriority = FocusTargetPriority.Today;
30
42
  }
31
43
  }
32
- index++;
33
44
  }
34
45
  if (!focusTarget) {
35
46
  // return the first day that is focusable
36
- focusTarget = days.find((day) => {
37
- const m = getModifiers(day);
38
- return !m[UI_js_1.DayFlag.disabled] && !m[UI_js_1.DayFlag.hidden] && !m[UI_js_1.DayFlag.outside];
39
- });
47
+ focusTarget = days.find((day) => isFocusableDay(getModifiers(day)));
40
48
  }
41
49
  return focusTarget;
42
50
  }
@@ -1 +1 @@
1
- {"version":3,"file":"calculateFocusTarget.js","sourceRoot":"","sources":["../../../src/helpers/calculateFocusTarget.ts"],"names":[],"mappings":";;AAIA,oDA8CC;AAlDD,oCAAmC;AAInC,SAAgB,oBAAoB,CAClC,IAAmB,EACnB,YAA6C,EAC7C,UAAmC,EACnC,WAAoC;IAEpC,IAAI,WAAoC,CAAC;IAEzC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,KAAK,CAAC;IAElB,OAAO,KAAK,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAEpC,IACE,CAAC,SAAS,CAAC,eAAO,CAAC,QAAQ,CAAC;YAC5B,CAAC,SAAS,CAAC,eAAO,CAAC,MAAM,CAAC;YAC1B,CAAC,SAAS,CAAC,eAAO,CAAC,OAAO,CAAC,EAC3B,CAAC;YACD,IAAI,SAAS,CAAC,eAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,WAAW,GAAG,GAAG,CAAC;gBAClB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,IAAI,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvC,WAAW,GAAG,GAAG,CAAC;gBAClB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChC,WAAW,GAAG,GAAG,CAAC;gBAClB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,IAAI,SAAS,CAAC,eAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpC,WAAW,GAAG,GAAG,CAAC;gBAClB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;QACH,CAAC;QAED,KAAK,EAAE,CAAC;IACV,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,yCAAyC;QACzC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YAC9B,MAAM,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;YAC5B,OAAO,CAAC,CAAC,CAAC,eAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,eAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,eAAO,CAAC,OAAO,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"calculateFocusTarget.js","sourceRoot":"","sources":["../../../src/helpers/calculateFocusTarget.ts"],"names":[],"mappings":";;AAmBA,oDA8CC;AAjED,oCAAmC;AAInC,IAAK,mBAKJ;AALD,WAAK,mBAAmB;IACtB,+DAAS,CAAA;IACT,qEAAQ,CAAA;IACR,2EAAW,CAAA;IACX,mFAAe,CAAA;AACjB,CAAC,EALI,mBAAmB,KAAnB,mBAAmB,QAKvB;AAED,SAAS,cAAc,CAAC,SAAoB;IAC1C,OAAO,CACL,CAAC,SAAS,CAAC,eAAO,CAAC,QAAQ,CAAC;QAC5B,CAAC,SAAS,CAAC,eAAO,CAAC,MAAM,CAAC;QAC1B,CAAC,SAAS,CAAC,eAAO,CAAC,OAAO,CAAC,CAC5B,CAAC;AACJ,CAAC;AAED,SAAgB,oBAAoB,CAClC,IAAmB,EACnB,YAA6C,EAC7C,UAAmC,EACnC,WAAoC;IAEpC,IAAI,WAAoC,CAAC;IAEzC,IAAI,wBAAwB,GAA6B,CAAC,CAAC,CAAC;IAC5D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAEpC,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,IACE,SAAS,CAAC,eAAO,CAAC,OAAO,CAAC;gBAC1B,wBAAwB,GAAG,mBAAmB,CAAC,eAAe,EAC9D,CAAC;gBACD,WAAW,GAAG,GAAG,CAAC;gBAClB,wBAAwB,GAAG,mBAAmB,CAAC,eAAe,CAAC;YACjE,CAAC;iBAAM,IACL,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC;gBAC3B,wBAAwB,GAAG,mBAAmB,CAAC,WAAW,EAC1D,CAAC;gBACD,WAAW,GAAG,GAAG,CAAC;gBAClB,wBAAwB,GAAG,mBAAmB,CAAC,WAAW,CAAC;YAC7D,CAAC;iBAAM,IACL,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;gBACpB,wBAAwB,GAAG,mBAAmB,CAAC,QAAQ,EACvD,CAAC;gBACD,WAAW,GAAG,GAAG,CAAC;gBAClB,wBAAwB,GAAG,mBAAmB,CAAC,QAAQ,CAAC;YAC1D,CAAC;iBAAM,IACL,SAAS,CAAC,eAAO,CAAC,KAAK,CAAC;gBACxB,wBAAwB,GAAG,mBAAmB,CAAC,KAAK,EACpD,CAAC;gBACD,WAAW,GAAG,GAAG,CAAC;gBAClB,wBAAwB,GAAG,mBAAmB,CAAC,KAAK,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,yCAAyC;QACzC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}
@@ -1,39 +1,47 @@
1
1
  import { DayFlag } from "../UI.js";
2
+ var FocusTargetPriority;
3
+ (function (FocusTargetPriority) {
4
+ FocusTargetPriority[FocusTargetPriority["Today"] = 0] = "Today";
5
+ FocusTargetPriority[FocusTargetPriority["Selected"] = 1] = "Selected";
6
+ FocusTargetPriority[FocusTargetPriority["LastFocused"] = 2] = "LastFocused";
7
+ FocusTargetPriority[FocusTargetPriority["FocusedModifier"] = 3] = "FocusedModifier";
8
+ })(FocusTargetPriority || (FocusTargetPriority = {}));
9
+ function isFocusableDay(modifiers) {
10
+ return (!modifiers[DayFlag.disabled] &&
11
+ !modifiers[DayFlag.hidden] &&
12
+ !modifiers[DayFlag.outside]);
13
+ }
2
14
  export function calculateFocusTarget(days, getModifiers, isSelected, lastFocused) {
3
15
  let focusTarget;
4
- let index = 0;
5
- let found = false;
6
- while (index < days.length && !found) {
7
- const day = days[index];
16
+ let foundFocusTargetPriority = -1;
17
+ for (const day of days) {
8
18
  const modifiers = getModifiers(day);
9
- if (!modifiers[DayFlag.disabled] &&
10
- !modifiers[DayFlag.hidden] &&
11
- !modifiers[DayFlag.outside]) {
12
- if (modifiers[DayFlag.focused]) {
19
+ if (isFocusableDay(modifiers)) {
20
+ if (modifiers[DayFlag.focused] &&
21
+ foundFocusTargetPriority < FocusTargetPriority.FocusedModifier) {
13
22
  focusTarget = day;
14
- found = true;
23
+ foundFocusTargetPriority = FocusTargetPriority.FocusedModifier;
15
24
  }
16
- else if (lastFocused?.isEqualTo(day)) {
25
+ else if (lastFocused?.isEqualTo(day) &&
26
+ foundFocusTargetPriority < FocusTargetPriority.LastFocused) {
17
27
  focusTarget = day;
18
- found = true;
28
+ foundFocusTargetPriority = FocusTargetPriority.LastFocused;
19
29
  }
20
- else if (isSelected(day.date)) {
30
+ else if (isSelected(day.date) &&
31
+ foundFocusTargetPriority < FocusTargetPriority.Selected) {
21
32
  focusTarget = day;
22
- found = true;
33
+ foundFocusTargetPriority = FocusTargetPriority.Selected;
23
34
  }
24
- else if (modifiers[DayFlag.today]) {
35
+ else if (modifiers[DayFlag.today] &&
36
+ foundFocusTargetPriority < FocusTargetPriority.Today) {
25
37
  focusTarget = day;
26
- found = true;
38
+ foundFocusTargetPriority = FocusTargetPriority.Today;
27
39
  }
28
40
  }
29
- index++;
30
41
  }
31
42
  if (!focusTarget) {
32
43
  // return the first day that is focusable
33
- focusTarget = days.find((day) => {
34
- const m = getModifiers(day);
35
- return !m[DayFlag.disabled] && !m[DayFlag.hidden] && !m[DayFlag.outside];
36
- });
44
+ focusTarget = days.find((day) => isFocusableDay(getModifiers(day)));
37
45
  }
38
46
  return focusTarget;
39
47
  }
@@ -1 +1 @@
1
- {"version":3,"file":"calculateFocusTarget.js","sourceRoot":"","sources":["../../../src/helpers/calculateFocusTarget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAInC,MAAM,UAAU,oBAAoB,CAClC,IAAmB,EACnB,YAA6C,EAC7C,UAAmC,EACnC,WAAoC;IAEpC,IAAI,WAAoC,CAAC;IAEzC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,KAAK,CAAC;IAElB,OAAO,KAAK,GAAG,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACxB,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAEpC,IACE,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC;YAC5B,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;YAC1B,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAC3B,CAAC;YACD,IAAI,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,WAAW,GAAG,GAAG,CAAC;gBAClB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,IAAI,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;gBACvC,WAAW,GAAG,GAAG,CAAC;gBAClB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,IAAI,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChC,WAAW,GAAG,GAAG,CAAC;gBAClB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,IAAI,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACpC,WAAW,GAAG,GAAG,CAAC;gBAClB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;QACH,CAAC;QAED,KAAK,EAAE,CAAC;IACV,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,yCAAyC;QACzC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YAC9B,MAAM,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;YAC5B,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"calculateFocusTarget.js","sourceRoot":"","sources":["../../../src/helpers/calculateFocusTarget.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAInC,IAAK,mBAKJ;AALD,WAAK,mBAAmB;IACtB,+DAAS,CAAA;IACT,qEAAQ,CAAA;IACR,2EAAW,CAAA;IACX,mFAAe,CAAA;AACjB,CAAC,EALI,mBAAmB,KAAnB,mBAAmB,QAKvB;AAED,SAAS,cAAc,CAAC,SAAoB;IAC1C,OAAO,CACL,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC5B,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;QAC1B,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAC5B,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,IAAmB,EACnB,YAA6C,EAC7C,UAAmC,EACnC,WAAoC;IAEpC,IAAI,WAAoC,CAAC;IAEzC,IAAI,wBAAwB,GAA6B,CAAC,CAAC,CAAC;IAC5D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;QAEpC,IAAI,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,IACE,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC;gBAC1B,wBAAwB,GAAG,mBAAmB,CAAC,eAAe,EAC9D,CAAC;gBACD,WAAW,GAAG,GAAG,CAAC;gBAClB,wBAAwB,GAAG,mBAAmB,CAAC,eAAe,CAAC;YACjE,CAAC;iBAAM,IACL,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC;gBAC3B,wBAAwB,GAAG,mBAAmB,CAAC,WAAW,EAC1D,CAAC;gBACD,WAAW,GAAG,GAAG,CAAC;gBAClB,wBAAwB,GAAG,mBAAmB,CAAC,WAAW,CAAC;YAC7D,CAAC;iBAAM,IACL,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC;gBACpB,wBAAwB,GAAG,mBAAmB,CAAC,QAAQ,EACvD,CAAC;gBACD,WAAW,GAAG,GAAG,CAAC;gBAClB,wBAAwB,GAAG,mBAAmB,CAAC,QAAQ,CAAC;YAC1D,CAAC;iBAAM,IACL,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC;gBACxB,wBAAwB,GAAG,mBAAmB,CAAC,KAAK,EACpD,CAAC;gBACD,WAAW,GAAG,GAAG,CAAC;gBAClB,wBAAwB,GAAG,mBAAmB,CAAC,KAAK,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,yCAAyC;QACzC,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-day-picker",
3
- "version": "9.6.5",
3
+ "version": "9.6.6",
4
4
  "description": "Customizable Date Picker for React",
5
5
  "author": "Giampaolo Bellavite <io@gpbl.dev>",
6
6
  "homepage": "https://daypicker.dev",
@@ -0,0 +1,167 @@
1
+ import { DayFlag } from "../UI.js";
2
+ import { CalendarDay } from "../classes/index.js";
3
+ import type { Modifiers } from "../types/index.js";
4
+
5
+ import { calculateFocusTarget } from "./calculateFocusTarget";
6
+
7
+ const todayModifiers = {
8
+ [DayFlag.today]: true
9
+ };
10
+
11
+ const todayHiddenModifiers = {
12
+ [DayFlag.today]: true,
13
+ [DayFlag.hidden]: true
14
+ };
15
+
16
+ const focusedModifiers = {
17
+ [DayFlag.focused]: true
18
+ };
19
+
20
+ const focusedDisabledModifiers = {
21
+ [DayFlag.focused]: true,
22
+ [DayFlag.disabled]: true
23
+ };
24
+
25
+ const outsideModifiers = {
26
+ [DayFlag.outside]: true
27
+ };
28
+
29
+ const hiddenModifiers = {
30
+ [DayFlag.hidden]: true
31
+ };
32
+
33
+ const disabledModifiers = {
34
+ [DayFlag.disabled]: true
35
+ };
36
+
37
+ const month = new Date(2021, 0, 1);
38
+ const day1 = new CalendarDay(new Date(2021, 0, 1), month);
39
+ const dayToday = new CalendarDay(new Date(2021, 0, 2), month);
40
+ const daySelected = new CalendarDay(new Date(2021, 0, 3), month);
41
+ const dayLastFocused = new CalendarDay(new Date(2021, 0, 4), month);
42
+ const dayFocusedModifier = new CalendarDay(new Date(2021, 0, 5), month);
43
+ const day6 = new CalendarDay(new Date(2021, 0, 6), month);
44
+
45
+ const days: CalendarDay[] = [
46
+ day1,
47
+ dayToday,
48
+ daySelected,
49
+ dayLastFocused,
50
+ dayFocusedModifier,
51
+ day6
52
+ ];
53
+
54
+ const isSelected = (date: Date) => {
55
+ return date.getTime() === daySelected.date.getTime();
56
+ };
57
+
58
+ function getModifiersFactory(
59
+ entries: [CalendarDay, Modifiers][]
60
+ ): (day: CalendarDay) => Modifiers {
61
+ const map = new Map(entries);
62
+ return (day) => map.get(day) ?? {};
63
+ }
64
+
65
+ describe("calculateFocusTarget", () => {
66
+ describe("when determining the focus target based on priority", () => {
67
+ it("should prioritize the day with the 'focused' modifier", () => {
68
+ const getModifiers = getModifiersFactory([
69
+ [day1, outsideModifiers],
70
+ [dayToday, todayModifiers],
71
+ [daySelected, {}],
72
+ [dayLastFocused, {}],
73
+ [dayFocusedModifier, focusedModifiers],
74
+ [day6, {}]
75
+ ]);
76
+
77
+ const focusTarget = calculateFocusTarget(
78
+ days,
79
+ getModifiers,
80
+ isSelected,
81
+ dayLastFocused
82
+ );
83
+
84
+ expect(focusTarget).toBe(dayFocusedModifier);
85
+ });
86
+
87
+ it("should fall back to the last focused day if no day has the 'focused' modifier", () => {
88
+ const getModifiers = getModifiersFactory([
89
+ [day1, outsideModifiers],
90
+ [dayToday, todayModifiers],
91
+ [daySelected, {}],
92
+ [dayLastFocused, {}],
93
+ [dayFocusedModifier, focusedDisabledModifiers],
94
+ [day6, {}]
95
+ ]);
96
+
97
+ const focusTarget = calculateFocusTarget(
98
+ days,
99
+ getModifiers,
100
+ isSelected,
101
+ dayLastFocused
102
+ );
103
+
104
+ expect(focusTarget).toBe(dayLastFocused);
105
+ });
106
+
107
+ it("should prioritize the selected day if no day is focused or last focused", () => {
108
+ const getModifiers = getModifiersFactory([
109
+ [day1, outsideModifiers],
110
+ [dayToday, todayModifiers],
111
+ [daySelected, {}],
112
+ [dayLastFocused, disabledModifiers],
113
+ [dayFocusedModifier, focusedDisabledModifiers],
114
+ [day6, {}]
115
+ ]);
116
+
117
+ const focusTarget = calculateFocusTarget(
118
+ days,
119
+ getModifiers,
120
+ isSelected,
121
+ dayLastFocused
122
+ );
123
+
124
+ expect(focusTarget).toBe(daySelected);
125
+ });
126
+
127
+ it("should prioritize today if no day is focused, last focused, or selected", () => {
128
+ const getModifiers = getModifiersFactory([
129
+ [day1, outsideModifiers],
130
+ [dayToday, todayModifiers],
131
+ [daySelected, hiddenModifiers],
132
+ [dayLastFocused, disabledModifiers],
133
+ [dayFocusedModifier, focusedDisabledModifiers],
134
+ [day6, {}]
135
+ ]);
136
+
137
+ const focusTarget = calculateFocusTarget(
138
+ days,
139
+ getModifiers,
140
+ isSelected,
141
+ dayLastFocused
142
+ );
143
+
144
+ expect(focusTarget).toBe(dayToday);
145
+ });
146
+
147
+ it("should fall back to the first focusable day if no other priority is met", () => {
148
+ const getModifiers = getModifiersFactory([
149
+ [day1, outsideModifiers],
150
+ [dayToday, todayHiddenModifiers],
151
+ [daySelected, hiddenModifiers],
152
+ [dayLastFocused, disabledModifiers],
153
+ [dayFocusedModifier, focusedDisabledModifiers],
154
+ [day6, {}]
155
+ ]);
156
+
157
+ const focusTarget = calculateFocusTarget(
158
+ days,
159
+ getModifiers,
160
+ isSelected,
161
+ dayLastFocused
162
+ );
163
+
164
+ expect(focusTarget).toBe(day6);
165
+ });
166
+ });
167
+ });
@@ -2,6 +2,21 @@ import { DayFlag } from "../UI.js";
2
2
  import type { CalendarDay } from "../classes/index.js";
3
3
  import type { Modifiers } from "../types/index.js";
4
4
 
5
+ enum FocusTargetPriority {
6
+ Today = 0,
7
+ Selected,
8
+ LastFocused,
9
+ FocusedModifier
10
+ }
11
+
12
+ function isFocusableDay(modifiers: Modifiers) {
13
+ return (
14
+ !modifiers[DayFlag.disabled] &&
15
+ !modifiers[DayFlag.hidden] &&
16
+ !modifiers[DayFlag.outside]
17
+ );
18
+ }
19
+
5
20
  export function calculateFocusTarget(
6
21
  days: CalendarDay[],
7
22
  getModifiers: (day: CalendarDay) => Modifiers,
@@ -10,42 +25,42 @@ export function calculateFocusTarget(
10
25
  ) {
11
26
  let focusTarget: CalendarDay | undefined;
12
27
 
13
- let index = 0;
14
- let found = false;
15
-
16
- while (index < days.length && !found) {
17
- const day = days[index];
28
+ let foundFocusTargetPriority: FocusTargetPriority | -1 = -1;
29
+ for (const day of days) {
18
30
  const modifiers = getModifiers(day);
19
31
 
20
- if (
21
- !modifiers[DayFlag.disabled] &&
22
- !modifiers[DayFlag.hidden] &&
23
- !modifiers[DayFlag.outside]
24
- ) {
25
- if (modifiers[DayFlag.focused]) {
32
+ if (isFocusableDay(modifiers)) {
33
+ if (
34
+ modifiers[DayFlag.focused] &&
35
+ foundFocusTargetPriority < FocusTargetPriority.FocusedModifier
36
+ ) {
26
37
  focusTarget = day;
27
- found = true;
28
- } else if (lastFocused?.isEqualTo(day)) {
38
+ foundFocusTargetPriority = FocusTargetPriority.FocusedModifier;
39
+ } else if (
40
+ lastFocused?.isEqualTo(day) &&
41
+ foundFocusTargetPriority < FocusTargetPriority.LastFocused
42
+ ) {
29
43
  focusTarget = day;
30
- found = true;
31
- } else if (isSelected(day.date)) {
44
+ foundFocusTargetPriority = FocusTargetPriority.LastFocused;
45
+ } else if (
46
+ isSelected(day.date) &&
47
+ foundFocusTargetPriority < FocusTargetPriority.Selected
48
+ ) {
32
49
  focusTarget = day;
33
- found = true;
34
- } else if (modifiers[DayFlag.today]) {
50
+ foundFocusTargetPriority = FocusTargetPriority.Selected;
51
+ } else if (
52
+ modifiers[DayFlag.today] &&
53
+ foundFocusTargetPriority < FocusTargetPriority.Today
54
+ ) {
35
55
  focusTarget = day;
36
- found = true;
56
+ foundFocusTargetPriority = FocusTargetPriority.Today;
37
57
  }
38
58
  }
39
-
40
- index++;
41
59
  }
42
60
 
43
61
  if (!focusTarget) {
44
62
  // return the first day that is focusable
45
- focusTarget = days.find((day) => {
46
- const m = getModifiers(day);
47
- return !m[DayFlag.disabled] && !m[DayFlag.hidden] && !m[DayFlag.outside];
48
- });
63
+ focusTarget = days.find((day) => isFocusableDay(getModifiers(day)));
49
64
  }
50
65
  return focusTarget;
51
66
  }