@os-design/core 1.0.280 → 1.0.281

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 (198) hide show
  1. package/dist/Avatar/utils/nameToInitials.d.ts.map +1 -1
  2. package/dist/Avatar/utils/strToHue.d.ts.map +1 -1
  3. package/dist/Button/index.d.ts.map +1 -1
  4. package/dist/Button/index.js +1 -1
  5. package/dist/Button/utils/useButtonColors.d.ts.map +1 -1
  6. package/dist/ButtonLink/index.d.ts.map +1 -1
  7. package/dist/ButtonLink/index.js +0 -5
  8. package/dist/Checkbox/index.d.ts.map +1 -1
  9. package/dist/Checkbox/index.js +1 -6
  10. package/dist/DateCalendar/Calendar.d.ts +25 -0
  11. package/dist/DateCalendar/Calendar.d.ts.map +1 -0
  12. package/dist/DateCalendar/Calendar.js +271 -0
  13. package/dist/DateCalendar/MonthPicker.d.ts +12 -0
  14. package/dist/DateCalendar/MonthPicker.d.ts.map +1 -0
  15. package/dist/DateCalendar/MonthPicker.js +159 -0
  16. package/dist/DateCalendar/index.d.ts +41 -0
  17. package/dist/DateCalendar/index.d.ts.map +1 -0
  18. package/dist/DateCalendar/index.js +77 -0
  19. package/dist/DateCalendar/locale.d.ts +6 -0
  20. package/dist/DateCalendar/locale.d.ts.map +1 -0
  21. package/dist/DateCalendar/locale.js +4 -0
  22. package/dist/DateCalendar/utils/calendarDays.d.ts +10 -0
  23. package/dist/DateCalendar/utils/calendarDays.d.ts.map +1 -0
  24. package/dist/DateCalendar/utils/calendarDays.js +46 -0
  25. package/dist/DateCalendar/utils/dayOfWeek.d.ts +8 -0
  26. package/dist/DateCalendar/utils/dayOfWeek.d.ts.map +1 -0
  27. package/dist/DateCalendar/utils/dayOfWeek.js +6 -0
  28. package/dist/DateCalendar/utils/daysInMonth.d.ts +7 -0
  29. package/dist/DateCalendar/utils/daysInMonth.d.ts.map +1 -0
  30. package/dist/DateCalendar/utils/daysInMonth.js +14 -0
  31. package/dist/DateCalendar/utils/month.d.ts +14 -0
  32. package/dist/DateCalendar/utils/month.d.ts.map +1 -0
  33. package/dist/DateCalendar/utils/month.js +24 -0
  34. package/dist/DateCalendar/utils/shift.d.ts +3 -0
  35. package/dist/DateCalendar/utils/shift.d.ts.map +1 -0
  36. package/dist/DateCalendar/utils/shift.js +12 -0
  37. package/dist/DatePicker/index.d.ts +68 -62
  38. package/dist/DatePicker/index.d.ts.map +1 -1
  39. package/dist/DatePicker/index.js +359 -265
  40. package/dist/DatePicker/utils/createTimes.d.ts +7 -0
  41. package/dist/DatePicker/utils/createTimes.d.ts.map +1 -0
  42. package/dist/DatePicker/utils/createTimes.js +15 -0
  43. package/dist/GlobalStyles/resetStyles.d.ts.map +1 -1
  44. package/dist/GlobalStyles/typographyStyles.d.ts.map +1 -1
  45. package/dist/Input/index.d.ts +15 -0
  46. package/dist/Input/index.d.ts.map +1 -1
  47. package/dist/Input/index.js +5 -5
  48. package/dist/Input/utils/getFocusableElements.d.ts.map +1 -1
  49. package/dist/InputDateUnstyled/index.d.ts +94 -0
  50. package/dist/InputDateUnstyled/index.d.ts.map +1 -0
  51. package/dist/InputDateUnstyled/index.js +406 -0
  52. package/dist/InputDateUnstyled/utils/convertHours.d.ts +4 -0
  53. package/dist/InputDateUnstyled/utils/convertHours.d.ts.map +1 -0
  54. package/dist/InputDateUnstyled/utils/convertHours.js +12 -0
  55. package/dist/InputDateUnstyled/utils/convertToFullYear.d.ts +3 -0
  56. package/dist/InputDateUnstyled/utils/convertToFullYear.d.ts.map +1 -0
  57. package/dist/InputDateUnstyled/utils/convertToFullYear.js +10 -0
  58. package/dist/InputDateUnstyled/utils/dateToString.d.ts +3 -0
  59. package/dist/InputDateUnstyled/utils/dateToString.d.ts.map +1 -0
  60. package/dist/InputDateUnstyled/utils/dateToString.js +10 -0
  61. package/dist/InputDateUnstyled/utils/daysInMonth.d.ts +7 -0
  62. package/dist/InputDateUnstyled/utils/daysInMonth.d.ts.map +1 -0
  63. package/dist/InputDateUnstyled/utils/daysInMonth.js +14 -0
  64. package/dist/InputDateUnstyled/utils/ensureCaretVisible.d.ts +3 -0
  65. package/dist/InputDateUnstyled/utils/ensureCaretVisible.d.ts.map +1 -0
  66. package/dist/InputDateUnstyled/utils/ensureCaretVisible.js +32 -0
  67. package/dist/InputDateUnstyled/utils/eraseSelectedTokens.d.ts +10 -0
  68. package/dist/InputDateUnstyled/utils/eraseSelectedTokens.d.ts.map +1 -0
  69. package/dist/InputDateUnstyled/utils/eraseSelectedTokens.js +29 -0
  70. package/dist/InputDateUnstyled/utils/replaceSubstring.d.ts +3 -0
  71. package/dist/InputDateUnstyled/utils/replaceSubstring.d.ts.map +1 -0
  72. package/dist/InputDateUnstyled/utils/replaceSubstring.js +9 -0
  73. package/dist/InputDateUnstyled/utils/same.d.ts +6 -0
  74. package/dist/InputDateUnstyled/utils/same.d.ts.map +1 -0
  75. package/dist/InputDateUnstyled/utils/same.js +3 -0
  76. package/dist/InputDateUnstyled/utils/stringToDay.d.ts +12 -0
  77. package/dist/InputDateUnstyled/utils/stringToDay.d.ts.map +1 -0
  78. package/dist/InputDateUnstyled/utils/stringToDay.js +55 -0
  79. package/dist/InputDateUnstyled/utils/stringToTime.d.ts +7 -0
  80. package/dist/InputDateUnstyled/utils/stringToTime.d.ts.map +1 -0
  81. package/dist/InputDateUnstyled/utils/stringToTime.js +40 -0
  82. package/dist/InputDateUnstyled/utils/token.d.ts +9 -0
  83. package/dist/InputDateUnstyled/utils/token.d.ts.map +1 -0
  84. package/dist/InputDateUnstyled/utils/token.js +66 -0
  85. package/dist/Link/index.d.ts.map +1 -1
  86. package/dist/Link/index.js +3 -8
  87. package/dist/LinkButton/index.d.ts.map +1 -1
  88. package/dist/LinkButton/index.js +0 -5
  89. package/dist/List/utils/bodyPointerEvents.d.ts.map +1 -1
  90. package/dist/List/utils/frameTimeout.d.ts.map +1 -1
  91. package/dist/List/utils/useRWLoadNext.d.ts.map +1 -1
  92. package/dist/LogoLink/index.d.ts.map +1 -1
  93. package/dist/LogoLink/index.js +1 -6
  94. package/dist/Menu/utils/useFocusWithArrows.d.ts.map +1 -1
  95. package/dist/Modal/index.d.ts +5 -0
  96. package/dist/Modal/index.d.ts.map +1 -1
  97. package/dist/Modal/index.js +53 -48
  98. package/dist/Navigation/utils/useScrollFlags.d.ts.map +1 -1
  99. package/dist/NavigationItem/index.d.ts.map +1 -1
  100. package/dist/NavigationItem/index.js +1 -6
  101. package/dist/Popover/utils/usePopoverPosition.d.ts.map +1 -1
  102. package/dist/ScrollButton/utils/useContainerPosition.d.ts.map +1 -1
  103. package/dist/ScrollButton/utils/useVisibility.d.ts.map +1 -1
  104. package/dist/Select/index.d.ts.map +1 -1
  105. package/dist/Select/index.js +2 -3
  106. package/dist/Switch/index.d.ts.map +1 -1
  107. package/dist/Switch/index.js +1 -7
  108. package/dist/TagLink/index.d.ts.map +1 -1
  109. package/dist/TagLink/index.js +1 -6
  110. package/dist/TimeGrid/index.d.ts +63 -0
  111. package/dist/TimeGrid/index.d.ts.map +1 -0
  112. package/dist/TimeGrid/index.js +111 -0
  113. package/dist/TimeGrid/utils/convertHours.d.ts +4 -0
  114. package/dist/TimeGrid/utils/convertHours.d.ts.map +1 -0
  115. package/dist/TimeGrid/utils/convertHours.js +12 -0
  116. package/dist/TimeGrid/utils/createTimes.d.ts +7 -0
  117. package/dist/TimeGrid/utils/createTimes.d.ts.map +1 -0
  118. package/dist/TimeGrid/utils/createTimes.js +15 -0
  119. package/dist/TimeGrid/utils/timeToString.d.ts +4 -0
  120. package/dist/TimeGrid/utils/timeToString.d.ts.map +1 -0
  121. package/dist/TimeGrid/utils/timeToString.js +12 -0
  122. package/dist/TimeGridSkeleton/index.d.ts +18 -0
  123. package/dist/TimeGridSkeleton/index.d.ts.map +1 -0
  124. package/dist/TimeGridSkeleton/index.js +33 -0
  125. package/dist/TimeList/index.d.ts +45 -0
  126. package/dist/TimeList/index.d.ts.map +1 -0
  127. package/dist/TimeList/index.js +80 -0
  128. package/dist/TimeList/utils/convertHours.d.ts +4 -0
  129. package/dist/TimeList/utils/convertHours.d.ts.map +1 -0
  130. package/dist/TimeList/utils/convertHours.js +12 -0
  131. package/dist/TimeList/utils/createTimes.d.ts +7 -0
  132. package/dist/TimeList/utils/createTimes.d.ts.map +1 -0
  133. package/dist/TimeList/utils/createTimes.js +15 -0
  134. package/dist/TimeList/utils/timeToString.d.ts +4 -0
  135. package/dist/TimeList/utils/timeToString.d.ts.map +1 -0
  136. package/dist/TimeList/utils/timeToString.js +12 -0
  137. package/dist/TimeListSkeleton/index.d.ts +13 -0
  138. package/dist/TimeListSkeleton/index.d.ts.map +1 -0
  139. package/dist/TimeListSkeleton/index.js +30 -0
  140. package/dist/index.d.ts +12 -0
  141. package/dist/index.d.ts.map +1 -1
  142. package/dist/index.js +12 -0
  143. package/dist/message/styles.d.ts.map +1 -1
  144. package/package.json +8 -8
  145. package/src/Button/index.tsx +1 -1
  146. package/src/ButtonLink/index.tsx +0 -5
  147. package/src/Checkbox/index.tsx +1 -6
  148. package/src/DateCalendar/Calendar.tsx +400 -0
  149. package/src/DateCalendar/MonthPicker.tsx +212 -0
  150. package/src/DateCalendar/index.tsx +135 -0
  151. package/src/DateCalendar/locale.ts +22 -0
  152. package/src/DateCalendar/utils/calendarDays.ts +61 -0
  153. package/src/DateCalendar/utils/dayOfWeek.ts +14 -0
  154. package/src/DateCalendar/utils/daysInMonth.ts +22 -0
  155. package/src/DateCalendar/utils/month.ts +30 -0
  156. package/src/DateCalendar/utils/shift.ts +14 -0
  157. package/src/DatePicker/index.tsx +506 -417
  158. package/src/DatePicker/utils/createTimes.ts +20 -0
  159. package/src/Input/index.tsx +11 -8
  160. package/src/InputDateUnstyled/index.tsx +533 -0
  161. package/src/InputDateUnstyled/utils/convertHours.ts +15 -0
  162. package/src/InputDateUnstyled/utils/convertToFullYear.ts +11 -0
  163. package/src/InputDateUnstyled/utils/dateToString.ts +21 -0
  164. package/src/InputDateUnstyled/utils/daysInMonth.ts +22 -0
  165. package/src/InputDateUnstyled/utils/ensureCaretVisible.ts +37 -0
  166. package/src/InputDateUnstyled/utils/eraseSelectedTokens.ts +38 -0
  167. package/src/InputDateUnstyled/utils/replaceSubstring.ts +10 -0
  168. package/src/InputDateUnstyled/utils/same.ts +15 -0
  169. package/src/InputDateUnstyled/utils/stringToDay.ts +69 -0
  170. package/src/InputDateUnstyled/utils/stringToTime.ts +48 -0
  171. package/src/InputDateUnstyled/utils/token.ts +102 -0
  172. package/src/Link/index.tsx +5 -25
  173. package/src/LinkButton/index.tsx +2 -15
  174. package/src/LogoLink/index.tsx +2 -6
  175. package/src/Modal/index.tsx +71 -60
  176. package/src/NavigationItem/index.tsx +2 -16
  177. package/src/Select/index.tsx +2 -3
  178. package/src/Switch/index.tsx +1 -11
  179. package/src/TagLink/index.tsx +3 -11
  180. package/src/TimeGrid/index.tsx +189 -0
  181. package/src/TimeGrid/utils/convertHours.ts +15 -0
  182. package/src/TimeGrid/utils/createTimes.ts +20 -0
  183. package/src/TimeGrid/utils/timeToString.ts +17 -0
  184. package/src/TimeGridSkeleton/index.tsx +50 -0
  185. package/src/TimeList/index.tsx +135 -0
  186. package/src/TimeList/utils/convertHours.ts +15 -0
  187. package/src/TimeList/utils/createTimes.ts +20 -0
  188. package/src/TimeList/utils/timeToString.ts +17 -0
  189. package/src/TimeListSkeleton/index.tsx +44 -0
  190. package/src/index.ts +12 -0
  191. package/dist/DatePicker/DatePickerCalendar.d.ts +0 -11
  192. package/dist/DatePicker/DatePickerCalendar.d.ts.map +0 -1
  193. package/dist/DatePicker/DatePickerCalendar.js +0 -178
  194. package/dist/TimePicker/index.d.ts +0 -29
  195. package/dist/TimePicker/index.d.ts.map +0 -1
  196. package/dist/TimePicker/index.js +0 -100
  197. package/src/DatePicker/DatePickerCalendar.tsx +0 -230
  198. package/src/TimePicker/index.tsx +0 -144
@@ -0,0 +1,37 @@
1
+ let span: HTMLSpanElement | undefined;
2
+
3
+ const getHiddenSpan = () => {
4
+ if (!span) {
5
+ span = document.createElement('span');
6
+ span.style.position = 'absolute';
7
+ span.style.top = '-9999px';
8
+ span.style.left = '-9999px';
9
+ span.style.visibility = 'hidden';
10
+ span.style.whiteSpace = 'pre'; // To take into account spaces at the end
11
+ document.body.appendChild(span);
12
+ }
13
+ return span;
14
+ };
15
+
16
+ const getCaretX = (input: HTMLInputElement) => {
17
+ const span = getHiddenSpan();
18
+ const computedInputStyle = window.getComputedStyle(input);
19
+ span.style.font = computedInputStyle.font;
20
+ span.style.padding = computedInputStyle.padding;
21
+ span.textContent = input.value.slice(0, input.selectionStart || 0);
22
+ return span.clientWidth;
23
+ };
24
+
25
+ const caretMargin = 15;
26
+
27
+ const ensureCaretVisible = (input: HTMLInputElement) => {
28
+ const caretX = getCaretX(input);
29
+ const offsetX = input.clientWidth / 2; // 20
30
+ if (caretX > input.clientWidth + input.scrollLeft - caretMargin) {
31
+ input.scrollLeft = caretX - input.clientWidth + offsetX;
32
+ } else if (caretX < input.scrollLeft + caretMargin) {
33
+ input.scrollLeft = caretX - offsetX;
34
+ }
35
+ };
36
+
37
+ export default ensureCaretVisible;
@@ -0,0 +1,38 @@
1
+ import replaceSubstring from './replaceSubstring.js';
2
+ import { nextToken } from './token.js';
3
+
4
+ interface EraseSelectedTokensProps {
5
+ value: string;
6
+ start: number;
7
+ end: number;
8
+ format: string;
9
+ tokens: readonly string[];
10
+ }
11
+
12
+ const eraseSelectedTokens = (props: EraseSelectedTokensProps) => {
13
+ const { value, start, end, format, tokens } = props;
14
+
15
+ if (end > start) {
16
+ let substr = value.slice(start, end);
17
+
18
+ let i = start;
19
+ while (i < end) {
20
+ const next = nextToken(i, format, tokens);
21
+ if (!next) break;
22
+
23
+ if (next.pos < end) {
24
+ const substr2 = '_'.repeat(next.end - next.pos);
25
+ substr = replaceSubstring(substr, next.pos - start, substr2);
26
+ i = next.end;
27
+ } else {
28
+ i = next.pos;
29
+ }
30
+ }
31
+
32
+ return replaceSubstring(value, start, substr);
33
+ }
34
+
35
+ return value;
36
+ };
37
+
38
+ export default eraseSelectedTokens;
@@ -0,0 +1,10 @@
1
+ const replaceSubstring = (str: string, index: number, substr: string) => {
2
+ if (index < 0) {
3
+ throw new Error('Negative index');
4
+ }
5
+ const left = str.slice(0, index);
6
+ const right = str.slice(index + substr.length);
7
+ return `${left}${substr}${right}`;
8
+ };
9
+
10
+ export default replaceSubstring;
@@ -0,0 +1,15 @@
1
+ import type { Day } from './stringToDay.js';
2
+ import type { Time } from './stringToTime.js';
3
+
4
+ export const sameDay = (day1: Day, day2: Day) =>
5
+ day1.year === day2.year && day1.month === day2.month && day1.day === day2.day;
6
+
7
+ export const sameTime = (time1: Time, time2: Time) =>
8
+ time1.hour === time2.hour && time1.minute === time2.minute;
9
+
10
+ export const sameDate = (date1: Date, date2: Date) =>
11
+ date1.getFullYear() === date2.getFullYear() &&
12
+ date1.getMonth() === date2.getMonth() &&
13
+ date1.getDate() === date2.getDate() &&
14
+ date1.getHours() === date2.getHours() &&
15
+ date1.getMinutes() === date2.getMinutes();
@@ -0,0 +1,69 @@
1
+ import convertToFullYear from './convertToFullYear.js';
2
+ import daysInMonth from './daysInMonth.js';
3
+
4
+ export interface Day {
5
+ year: number;
6
+ month: number;
7
+ day: number;
8
+ }
9
+
10
+ export interface DayErrorPayload extends Day {
11
+ maxDay: number;
12
+ }
13
+
14
+ export type OnDayError = (data: DayErrorPayload) => void;
15
+
16
+ const stringToDay = (
17
+ str: string,
18
+ format: string,
19
+ onDayError: OnDayError = () => {}
20
+ ): Day | null => {
21
+ const fullYearIndex = format.indexOf('YYYY');
22
+ const yearIndex = format.indexOf('YY');
23
+ const monthIndex = format.indexOf('MM');
24
+ const dayIndex = format.indexOf('DD');
25
+
26
+ let year: number | null = null;
27
+ let month: number | null = null;
28
+ let day: number | null = null;
29
+
30
+ if (fullYearIndex >= 0) {
31
+ const fullYearStr = str.slice(fullYearIndex, fullYearIndex + 4);
32
+ if (/^[0-9]{4}$/.test(fullYearStr)) {
33
+ year = Number(fullYearStr);
34
+ }
35
+ } else if (yearIndex >= 0) {
36
+ const yearStr = str.slice(yearIndex, yearIndex + 2);
37
+ if (/^[0-9]{2}$/.test(yearStr)) {
38
+ year = convertToFullYear(Number(yearStr), new Date().getFullYear());
39
+ }
40
+ }
41
+ if (monthIndex >= 0) {
42
+ const monthStr = str.slice(monthIndex, monthIndex + 2);
43
+ if (/^0[1-9]|1[0-2]$/.test(monthStr)) {
44
+ month = Number(monthStr) - 1;
45
+ }
46
+ }
47
+ if (dayIndex >= 0) {
48
+ const dayStr = str.slice(dayIndex, dayIndex + 2);
49
+ if (/^0[1-9]|[1-2][0-9]|3[0-1]$/.test(dayStr)) {
50
+ day = Number(dayStr);
51
+ }
52
+ }
53
+
54
+ if (year === null || month === null || day === null) {
55
+ return null;
56
+ }
57
+
58
+ const maxDay = daysInMonth({ month, year });
59
+ const res = { year, month, day };
60
+
61
+ if (day > maxDay) {
62
+ onDayError({ ...res, maxDay });
63
+ return null;
64
+ }
65
+
66
+ return res;
67
+ };
68
+
69
+ export default stringToDay;
@@ -0,0 +1,48 @@
1
+ import { convertTo24hours } from './convertHours.js';
2
+
3
+ export interface Time {
4
+ hour: number;
5
+ minute: number;
6
+ }
7
+
8
+ const stringToTime = (str: string, format: string): Time | null => {
9
+ const hour12Index = format.indexOf('hh');
10
+ const hour24Index = format.indexOf('HH');
11
+ const minuteIndex = format.indexOf('mm');
12
+ const meridiemIndex = format.indexOf('aa');
13
+
14
+ let hour: number | null = null;
15
+ let minute: number | null = null;
16
+
17
+ if (hour12Index >= 0) {
18
+ const hourStr = str.slice(hour12Index, hour12Index + 2);
19
+ if (/^0[1-9]|1[0-2]$/.test(hourStr)) {
20
+ let meridiem: 'am' | 'pm' = 'am';
21
+ if (meridiemIndex >= 0) {
22
+ const meridiemStr = str.slice(meridiemIndex, meridiemIndex + 2);
23
+ meridiem = meridiemStr === 'pm' ? 'pm' : 'am';
24
+ }
25
+ hour = convertTo24hours(Number(hourStr), meridiem);
26
+ }
27
+ }
28
+ if (hour24Index >= 0) {
29
+ const hour24Str = str.slice(hour24Index, hour24Index + 2);
30
+ if (/^[0-1][0-9]|2[0-3]$/.test(hour24Str)) {
31
+ hour = Number(hour24Str);
32
+ }
33
+ }
34
+ if (minuteIndex >= 0) {
35
+ const minuteStr = str.slice(minuteIndex, minuteIndex + 2);
36
+ if (/^[0-5][0-9]$/.test(minuteStr)) {
37
+ minute = Number(minuteStr);
38
+ }
39
+ }
40
+
41
+ if (hour === null || minute === null) {
42
+ return null;
43
+ }
44
+
45
+ return { hour, minute };
46
+ };
47
+
48
+ export default stringToTime;
@@ -0,0 +1,102 @@
1
+ export interface FoundToken<T> {
2
+ token: T;
3
+ start: number;
4
+ end: number;
5
+ pos: number;
6
+ }
7
+
8
+ export const nextToken = <T extends string>(
9
+ startPos: number,
10
+ format: string,
11
+ tokens: readonly T[]
12
+ ): FoundToken<T> | null => {
13
+ // Check if it's not the middle of the token
14
+ if (startPos > 0) {
15
+ for (let i = 0; i < tokens.length; i++) {
16
+ if (tokens[i].length >= 2) {
17
+ for (
18
+ let j = Math.max(1, tokens[i].length - (format.length - startPos));
19
+ j <= Math.min(tokens[i].length - 1, startPos);
20
+ j++
21
+ ) {
22
+ if (
23
+ format.slice(startPos - j, startPos - j + tokens[i].length) ===
24
+ tokens[i]
25
+ ) {
26
+ return {
27
+ token: tokens[i],
28
+ start: startPos - j,
29
+ end: startPos - j + tokens[i].length,
30
+ pos: startPos,
31
+ };
32
+ }
33
+ }
34
+ }
35
+ }
36
+ }
37
+ // Find the next token
38
+ for (let i = startPos; i < format.length; i++) {
39
+ for (let j = 0; j < tokens.length; j++) {
40
+ if (
41
+ format.length - i >= tokens[j].length &&
42
+ format.slice(i, i + tokens[j].length) === tokens[j]
43
+ ) {
44
+ return {
45
+ token: tokens[j],
46
+ start: i,
47
+ end: i + tokens[j].length,
48
+ pos: i,
49
+ };
50
+ }
51
+ }
52
+ }
53
+ return null;
54
+ };
55
+
56
+ export const prevToken = <T extends string>(
57
+ startPos: number,
58
+ format: string,
59
+ tokens: readonly T[]
60
+ ): FoundToken<T> | null => {
61
+ // Check if it's not the middle of the token
62
+ if (startPos < format.length) {
63
+ for (let i = 0; i < tokens.length; i++) {
64
+ if (tokens[i].length >= 2) {
65
+ for (
66
+ let j = Math.max(1, tokens[i].length - startPos);
67
+ j <= Math.min(tokens[i].length - 1, format.length - startPos);
68
+ j++
69
+ ) {
70
+ if (
71
+ format.slice(startPos - (tokens[i].length - j), startPos + j) ===
72
+ tokens[i]
73
+ ) {
74
+ return {
75
+ token: tokens[i],
76
+ start: startPos - (tokens[i].length - j),
77
+ end: startPos + j,
78
+ pos: startPos,
79
+ };
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+ // Find the previous token
86
+ for (let i = startPos; i > 0; i--) {
87
+ for (let j = 0; j < tokens.length; j++) {
88
+ if (
89
+ i >= tokens[j].length &&
90
+ format.slice(i - tokens[j].length, i) === tokens[j]
91
+ ) {
92
+ return {
93
+ token: tokens[j],
94
+ start: i - tokens[j].length,
95
+ end: i,
96
+ pos: i,
97
+ };
98
+ }
99
+ }
100
+ }
101
+ return null;
102
+ };
@@ -62,7 +62,7 @@ export const underlineHoverStyles = (p) =>
62
62
  }
63
63
 
64
64
  &:hover::after,
65
- &:focus::after {
65
+ &:focus-visible::after {
66
66
  width: 100%;
67
67
  opacity: 1;
68
68
  }
@@ -87,7 +87,7 @@ const disabledStyles = (p) =>
87
87
 
88
88
  &,
89
89
  &:active,
90
- &:focus {
90
+ &:focus-visible {
91
91
  color: ${clr(p.theme.inputColorPlaceholder)};
92
92
  }
93
93
  `;
@@ -111,7 +111,7 @@ const StyledLink = styled(
111
111
 
112
112
  &,
113
113
  &:active,
114
- &:focus {
114
+ &:focus-visible {
115
115
  color: ${(p) => clr(p.theme.linkColor)};
116
116
  }
117
117
 
@@ -125,16 +125,7 @@ const StyledLink = styled(
125
125
  * The link component to navigate between pages.
126
126
  */
127
127
  const Link = forwardRef<HTMLAnchorElement, LinkProps>(
128
- (
129
- {
130
- underline = 'hover',
131
- disabled = false,
132
- as,
133
- onMouseDown = () => {},
134
- ...rest
135
- },
136
- ref
137
- ) => {
128
+ ({ underline = 'hover', disabled = false, as, ...rest }, ref) => {
138
129
  if (disabled) {
139
130
  return (
140
131
  <DisabledWrapper>
@@ -143,18 +134,7 @@ const Link = forwardRef<HTMLAnchorElement, LinkProps>(
143
134
  );
144
135
  }
145
136
 
146
- return (
147
- <StyledLink
148
- underline={underline}
149
- as={as}
150
- onMouseDown={(e) => {
151
- onMouseDown(e);
152
- e.preventDefault();
153
- }}
154
- {...rest}
155
- ref={ref}
156
- />
157
- );
137
+ return <StyledLink underline={underline} as={as} {...rest} ref={ref} />;
158
138
  }
159
139
  );
160
140
 
@@ -58,10 +58,7 @@ const StyledButton = styled(
58
58
  * The link component that is rendered as a button.
59
59
  */
60
60
  const LinkButton = forwardRef<HTMLButtonElement, LinkButtonProps>(
61
- (
62
- { underline = 'hover', disabled = false, onMouseDown = () => {}, ...rest },
63
- ref
64
- ) => {
61
+ ({ underline = 'hover', disabled = false, ...rest }, ref) => {
65
62
  if (disabled) {
66
63
  return (
67
64
  <DisabledWrapper>
@@ -70,17 +67,7 @@ const LinkButton = forwardRef<HTMLButtonElement, LinkButtonProps>(
70
67
  );
71
68
  }
72
69
 
73
- return (
74
- <StyledButton
75
- underline={underline}
76
- onMouseDown={(e) => {
77
- onMouseDown(e);
78
- e.preventDefault();
79
- }}
80
- {...rest}
81
- ref={ref}
82
- />
83
- );
70
+ return <StyledButton underline={underline} {...rest} ref={ref} />;
84
71
  }
85
72
  );
86
73
 
@@ -52,7 +52,7 @@ const StyledLogoLink = styled(
52
52
 
53
53
  @media (hover: hover) {
54
54
  &:hover,
55
- &:focus {
55
+ &:focus-visible {
56
56
  opacity: 0.7;
57
57
  }
58
58
  }
@@ -66,7 +66,7 @@ const StyledLogoLink = styled(
66
66
  * Logo with a link.
67
67
  */
68
68
  const LogoLink = forwardRef<HTMLAnchorElement, LogoLinkProps>(
69
- ({ src, as, onMouseDown = () => {}, ...rest }, ref) => {
69
+ ({ src, as, ...rest }, ref) => {
70
70
  const { activeTheme } = useTheme();
71
71
  const ariaLabel = rest['aria-label'] || 'Logo';
72
72
 
@@ -75,10 +75,6 @@ const LogoLink = forwardRef<HTMLAnchorElement, LogoLinkProps>(
75
75
  dark={activeTheme === 'dark'}
76
76
  aria-label={ariaLabel}
77
77
  as={as}
78
- onMouseDown={(e) => {
79
- onMouseDown(e);
80
- e.preventDefault();
81
- }}
82
78
  {...rest}
83
79
  ref={ref}
84
80
  >
@@ -73,6 +73,11 @@ export interface ModalProps extends JsxDivProps, WithSize {
73
73
  * @default undefined
74
74
  */
75
75
  locale?: ModalLocale;
76
+ /**
77
+ * Whether the focus is locked.
78
+ * @default undefined
79
+ */
80
+ lockedFocus?: boolean;
76
81
  /**
77
82
  * Specifies a callback that will be called when a user clicks the mask or
78
83
  * the close button. The callback should set the visible state to false.
@@ -289,6 +294,7 @@ const Modal = forwardRef<HTMLDivElement, ModalProps>(
289
294
  footer,
290
295
  visible = false,
291
296
  locale = defaultLocale,
297
+ lockedFocus = true,
292
298
  onClose = () => {},
293
299
  onOk,
294
300
  size,
@@ -358,6 +364,65 @@ const Modal = forwardRef<HTMLDivElement, ModalProps>(
358
364
 
359
365
  if (!mounted) return null;
360
366
 
367
+ const content = (
368
+ <CloseModalContext.Provider value={onClose}>
369
+ <Content
370
+ visible={visible}
371
+ size={size}
372
+ tabIndex={-1}
373
+ onKeyDown={contentKeyDownHandler}
374
+ onPointerDown={stopPointerHandler}
375
+ onPointerUp={stopPointerHandler}
376
+ role='dialog'
377
+ aria-modal
378
+ aria-labelledby={ariaLabelledBy}
379
+ aria-describedby={bodyId}
380
+ ref={contentRef}
381
+ >
382
+ {header === undefined ? (
383
+ <ThemeOverrider
384
+ overrides={(t) => ({
385
+ buttonPaddingHorizontal: t.modalCloseButtonPaddingHorizontal,
386
+ })}
387
+ >
388
+ <Header>
389
+ <Title id={titleId}>{title}</Title>
390
+ <Button
391
+ type='ghost'
392
+ wide='never'
393
+ onClick={onClose}
394
+ aria-label={locale.closeLabel}
395
+ >
396
+ <Close />
397
+ </Button>
398
+ </Header>
399
+ </ThemeOverrider>
400
+ ) : (
401
+ header
402
+ )}
403
+
404
+ <Body id={bodyId} {...rest} ref={ref}>
405
+ {children}
406
+ </Body>
407
+
408
+ {footer === undefined ? (
409
+ <Footer>
410
+ <Button
411
+ danger={okDanger}
412
+ loading={okLoading}
413
+ disabled={okDisabled}
414
+ onClick={onOk}
415
+ >
416
+ {okText}
417
+ </Button>
418
+ </Footer>
419
+ ) : (
420
+ footer
421
+ )}
422
+ </Content>
423
+ </CloseModalContext.Provider>
424
+ );
425
+
361
426
  return (
362
427
  <Portal>
363
428
  <ModalMask visible={visible} />
@@ -366,66 +431,12 @@ const Modal = forwardRef<HTMLDivElement, ModalProps>(
366
431
  onPointerUp={pointerUpHandler}
367
432
  onClick={(e) => e.stopPropagation()}
368
433
  >
369
- {/* @ts-expect-error FocusLock has problems with types */}
370
- <FocusLock autoFocus={false}>
371
- <CloseModalContext.Provider value={onClose}>
372
- <Content
373
- visible={visible}
374
- size={size}
375
- tabIndex={-1}
376
- onKeyDown={contentKeyDownHandler}
377
- onPointerDown={stopPointerHandler}
378
- onPointerUp={stopPointerHandler}
379
- role='dialog'
380
- aria-modal
381
- aria-labelledby={ariaLabelledBy}
382
- aria-describedby={bodyId}
383
- ref={contentRef}
384
- >
385
- {header === undefined ? (
386
- <ThemeOverrider
387
- overrides={(t) => ({
388
- buttonPaddingHorizontal:
389
- t.modalCloseButtonPaddingHorizontal,
390
- })}
391
- >
392
- <Header>
393
- <Title id={titleId}>{title}</Title>
394
- <Button
395
- type='ghost'
396
- wide='never'
397
- onClick={onClose}
398
- aria-label={locale.closeLabel}
399
- >
400
- <Close />
401
- </Button>
402
- </Header>
403
- </ThemeOverrider>
404
- ) : (
405
- header
406
- )}
407
-
408
- <Body id={bodyId} {...rest} ref={ref}>
409
- {children}
410
- </Body>
411
-
412
- {footer === undefined ? (
413
- <Footer>
414
- <Button
415
- danger={okDanger}
416
- loading={okLoading}
417
- disabled={okDisabled}
418
- onClick={onOk}
419
- >
420
- {okText}
421
- </Button>
422
- </Footer>
423
- ) : (
424
- footer
425
- )}
426
- </Content>
427
- </CloseModalContext.Provider>
428
- </FocusLock>
434
+ {lockedFocus ? (
435
+ // @ts-expect-error FocusLock has problems with types
436
+ <FocusLock autoFocus={false}>{content}</FocusLock>
437
+ ) : (
438
+ content
439
+ )}
429
440
  </Container>
430
441
  </Portal>
431
442
  );
@@ -50,7 +50,7 @@ const NavigationLink = styled(
50
50
  color: ${(p) => clr(p.theme.navigationItemColorText)};
51
51
  @media (hover: hover) {
52
52
  &:hover,
53
- &:focus {
53
+ &:focus-visible {
54
54
  background-color: ${(p) => clr(p.theme.navigationItemColorBgHover)};
55
55
  }
56
56
  }
@@ -101,25 +101,11 @@ const Title = styled.span`
101
101
  * The item of the navigation.
102
102
  */
103
103
  const NavigationItem = forwardRef<HTMLAnchorElement, NavigationItemProps>(
104
- (
105
- {
106
- icon,
107
- currentPage = false,
108
- as,
109
- onMouseDown = () => {},
110
- children,
111
- ...rest
112
- },
113
- ref
114
- ) => (
104
+ ({ icon, currentPage = false, as, children, ...rest }, ref) => (
115
105
  <div role='listitem'>
116
106
  <NavigationLink
117
107
  currentPage={currentPage}
118
108
  as={as}
119
- onMouseDown={(e) => {
120
- onMouseDown(e);
121
- e.preventDefault();
122
- }}
123
109
  aria-current={currentPage ? 'page' : undefined}
124
110
  {...rest}
125
111
  ref={ref}
@@ -232,7 +232,7 @@ const selectContainerUnborderedHoverStyles = (p) =>
232
232
  css`
233
233
  @media (hover: hover) {
234
234
  &:hover,
235
- &:focus {
235
+ &:focus-visible {
236
236
  background-color: ${clr(p.theme.buttonGhostColorBgHover)};
237
237
  }
238
238
  }
@@ -385,7 +385,7 @@ const DeleteButton = styled.button`
385
385
 
386
386
  @media (hover: hover) {
387
387
  &:hover,
388
- &:focus {
388
+ &:focus-visible {
389
389
  color: ${(p) => clr(p.theme.selectToggleDeleteButtonColorIconHover)};
390
390
  }
391
391
  }
@@ -884,7 +884,6 @@ const Select = forwardRef<HTMLDivElement, SelectProps>(
884
884
  e.preventDefault();
885
885
  }
886
886
  }}
887
- onMouseDown={(e) => e.preventDefault()}
888
887
  onBlur={blurHandler}
889
888
  role='combobox'
890
889
  aria-disabled={disabled}