@os-design/core 1.0.280 → 1.0.282

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
@@ -80,7 +80,7 @@ const hoverStyles = (p) =>
80
80
  css`
81
81
  @media (hover: hover) {
82
82
  &:hover,
83
- &:focus {
83
+ &:focus-visible {
84
84
  ${hoverUncheckedStyles(p)};
85
85
  ${hoverCheckedStyles(p)};
86
86
  }
@@ -161,7 +161,6 @@ const Switch = forwardRef<HTMLButtonElement, SwitchProps>(
161
161
  defaultValue,
162
162
  onChange = () => {},
163
163
  size,
164
- onMouseDown = () => {},
165
164
  onKeyDown = () => {},
166
165
  ...rest
167
166
  },
@@ -178,14 +177,6 @@ const Switch = forwardRef<HTMLButtonElement, SwitchProps>(
178
177
  setForwardedValue(!forwardedValue);
179
178
  }, [disabled, forwardedValue, setForwardedValue]);
180
179
 
181
- const mouseDownHandler = useCallback(
182
- (e) => {
183
- onMouseDown(e);
184
- e.preventDefault();
185
- },
186
- [onMouseDown]
187
- );
188
-
189
180
  const keyDownHandler = useCallback(
190
181
  (e) => {
191
182
  if (e.key === ' ') setForwardedValue(!forwardedValue);
@@ -201,7 +192,6 @@ const Switch = forwardRef<HTMLButtonElement, SwitchProps>(
201
192
  checked={forwardedValue}
202
193
  size={size}
203
194
  onClick={clickHandler}
204
- onMouseDown={mouseDownHandler}
205
195
  onKeyDown={keyDownHandler}
206
196
  role='switch'
207
197
  aria-checked={forwardedValue}
@@ -25,7 +25,7 @@ const StyledTagLink = styled(
25
25
 
26
26
  @media (hover: hover) {
27
27
  &:hover,
28
- &:focus {
28
+ &:focus-visible {
29
29
  background-color: ${(p) => clr(p.theme.tagColorBgHover)};
30
30
  }
31
31
  }
@@ -35,16 +35,8 @@ const StyledTagLink = styled(
35
35
  * The tag component with a link.
36
36
  */
37
37
  const TagLink = forwardRef<HTMLAnchorElement, TagLinkProps>(
38
- ({ left, right, as, onMouseDown = () => {}, children, ...rest }, ref) => (
39
- <StyledTagLink
40
- as={as}
41
- onMouseDown={(e) => {
42
- onMouseDown(e);
43
- e.preventDefault();
44
- }}
45
- {...rest}
46
- ref={ref}
47
- >
38
+ ({ left, right, as, children, ...rest }, ref) => (
39
+ <StyledTagLink as={as} {...rest} ref={ref}>
48
40
  {left && <LeftAddon>{left}</LeftAddon>}
49
41
  {children}
50
42
  {right && <RightAddon>{right}</RightAddon>}
@@ -0,0 +1,189 @@
1
+ import { omitEmotionProps, useForwardedState } from '@os-design/utils';
2
+ import { forwardRef } from 'react';
3
+ import styled from '@emotion/styled';
4
+ import { css } from '@emotion/react';
5
+ import { clr } from '@os-design/theming';
6
+ import { resetButtonStyles, transitionStyles } from '@os-design/styles';
7
+ import timeToString from './utils/timeToString.js';
8
+
9
+ interface Time {
10
+ hour: number;
11
+ minute: number;
12
+ }
13
+
14
+ type JsxDivProps = Omit<
15
+ JSX.IntrinsicElements['div'],
16
+ 'defaultValue' | 'onChange' | 'ref'
17
+ >;
18
+ export interface TimeGridProps extends JsxDivProps {
19
+ /**
20
+ * Times shown in the list in minutes (600 is 10:00).
21
+ * @default []
22
+ */
23
+ times?: Time[];
24
+ /**
25
+ * The time format: 12-hour clock or 24-hour clock.
26
+ * @default false
27
+ */
28
+ hour12?: boolean;
29
+ /**
30
+ * Number of columns where the times are shown.
31
+ * @default 3
32
+ */
33
+ columns?: number;
34
+ /**
35
+ * What times are disabled.
36
+ * @default undefined
37
+ */
38
+ disabledTimes?: Time[];
39
+ /**
40
+ * The selected time.
41
+ * @default undefined
42
+ */
43
+ value?: Time | null;
44
+ /**
45
+ * The default value.
46
+ * @default undefined
47
+ */
48
+ defaultValue?: Time | null;
49
+ /**
50
+ * The change event handler.
51
+ * @default undefined
52
+ */
53
+ onChange?: (value: Time | null) => void;
54
+ }
55
+
56
+ interface ContainerProps {
57
+ columns: number;
58
+ }
59
+ export const Container = styled(
60
+ 'div',
61
+ omitEmotionProps('columns')
62
+ )<ContainerProps>`
63
+ display: grid;
64
+ grid-gap: 0.5em;
65
+ grid-template-columns: repeat(${(p) => p.columns}, auto);
66
+ justify-content: space-evenly;
67
+ `;
68
+
69
+ const selectedStyles = (p) =>
70
+ p.selected &&
71
+ css`
72
+ background-color: ${clr(p.theme.buttonPrimaryColorBg)};
73
+ color: ${clr(p.theme.buttonPrimaryColorText)};
74
+
75
+ @media (hover: hover) {
76
+ &:hover,
77
+ &:focus-visible {
78
+ background-color: ${clr(p.theme.buttonPrimaryColorBgHover)};
79
+ }
80
+ }
81
+ `;
82
+
83
+ const disabledStyles = (p) =>
84
+ p.disabled &&
85
+ css`
86
+ background-color: ${clr(p.theme.colorBg)} !important;
87
+ color: ${clr(p.theme.buttonDisabledGhostColorText)};
88
+ cursor: not-allowed;
89
+ ${p.selected &&
90
+ css`
91
+ background-color: ${clr(p.theme.buttonDisabledPrimaryColorBg)} !important;
92
+ color: ${clr(p.theme.buttonDisabledPrimaryColorText)};
93
+ `}
94
+ `;
95
+
96
+ interface TimeProps {
97
+ selected: boolean;
98
+ disabled: boolean;
99
+ }
100
+ const Time = styled(
101
+ 'button',
102
+ omitEmotionProps('selected', 'disabled')
103
+ )<TimeProps>`
104
+ ${resetButtonStyles};
105
+ cursor: pointer;
106
+ user-select: none;
107
+ font-size: 1em;
108
+ line-height: 1;
109
+ white-space: nowrap;
110
+
111
+ height: ${(p) => p.theme.menuItemHeight}em;
112
+
113
+ display: flex;
114
+ justify-content: center;
115
+ align-items: center;
116
+
117
+ padding: 0 0.8em;
118
+
119
+ background-color: ${(p) => clr(p.theme.colorBg)};
120
+ color: ${(p) => clr(p.theme.colorText)};
121
+ border-radius: ${(p) => p.theme.borderRadius}em;
122
+
123
+ @media (hover: hover) {
124
+ &:hover,
125
+ &:focus-visible {
126
+ background-color: ${(p) => clr(p.theme.menuItemSelectedColorBg)};
127
+ }
128
+ }
129
+
130
+ ${selectedStyles};
131
+ ${disabledStyles};
132
+ ${transitionStyles('background-color')};
133
+ `;
134
+
135
+ /**
136
+ * The component to choose a time in a grid.
137
+ */
138
+ const TimeGrid = forwardRef<HTMLDivElement, TimeGridProps>(
139
+ (
140
+ {
141
+ times = [],
142
+ hour12 = false,
143
+ columns = 3,
144
+ disabledTimes = [],
145
+ value,
146
+ defaultValue,
147
+ onChange = () => {},
148
+ ...rest
149
+ },
150
+ ref
151
+ ) => {
152
+ const [forwardedValue, setForwardedValue] = useForwardedState({
153
+ value,
154
+ defaultValue,
155
+ onChange,
156
+ });
157
+
158
+ return (
159
+ <Container columns={columns} {...rest} ref={ref}>
160
+ {times.map((time) => {
161
+ const key = time.hour * 60 + time.minute;
162
+ const disabled =
163
+ disabledTimes.findIndex(
164
+ ({ hour, minute }) => hour === time.hour && minute === time.minute
165
+ ) >= 0;
166
+ return (
167
+ <div key={key}>
168
+ <Time
169
+ selected={time === forwardedValue}
170
+ disabled={disabled}
171
+ onClick={() => {
172
+ if (!disabled) {
173
+ setForwardedValue(time);
174
+ }
175
+ }}
176
+ >
177
+ {timeToString(time, hour12)}
178
+ </Time>
179
+ </div>
180
+ );
181
+ })}
182
+ </Container>
183
+ );
184
+ }
185
+ );
186
+
187
+ TimeGrid.displayName = 'TimeGrid';
188
+
189
+ export default TimeGrid;
@@ -0,0 +1,15 @@
1
+ export type Meridiem = 'am' | 'pm';
2
+
3
+ export const convertTo12hours = (hours: number): [number, Meridiem] => {
4
+ if (hours >= 12) {
5
+ const hours12 = hours % 12;
6
+ return [hours12 === 0 ? 12 : hours12, 'pm'];
7
+ } else {
8
+ return [hours === 0 ? 12 : hours, 'am'];
9
+ }
10
+ };
11
+
12
+ export const convertTo24hours = (hours: number, meridiem: Meridiem): number => {
13
+ const h = hours === 12 ? 0 : hours;
14
+ return h + (meridiem === 'am' ? 0 : 12);
15
+ };
@@ -0,0 +1,20 @@
1
+ export interface Time {
2
+ hour: number;
3
+ minute: number;
4
+ }
5
+
6
+ const createTimes = (from: Time, to: Time, stepMinutes: number) => {
7
+ const min = from.hour * 60 + from.minute;
8
+ const max = to.hour * 60 + to.minute;
9
+ const times: Time[] = [];
10
+
11
+ for (let i = min; i <= max - stepMinutes; i += stepMinutes) {
12
+ const hour = Math.floor(i / 60);
13
+ const minute = i % 60;
14
+ times.push({ hour, minute });
15
+ }
16
+
17
+ return times;
18
+ };
19
+
20
+ export default createTimes;
@@ -0,0 +1,17 @@
1
+ import { convertTo12hours } from './convertHours.js';
2
+ import type { Time } from './createTimes.js';
3
+
4
+ const timeToString = (time: Time, hour12: boolean) => {
5
+ const minute = time.minute.toString().padStart(2, '0');
6
+
7
+ if (hour12) {
8
+ const [h, meridiem] = convertTo12hours(time.hour);
9
+ const hour = h.toString().padStart(2, '0');
10
+ return `${hour}:${minute} ${meridiem}`;
11
+ }
12
+
13
+ const hour = time.hour.toString().padStart(2, '0');
14
+ return `${hour}:${minute}`;
15
+ };
16
+
17
+ export default timeToString;
@@ -0,0 +1,50 @@
1
+ import styled from '@emotion/styled';
2
+ import { forwardRef } from 'react';
3
+ import Skeleton from '../Skeleton/index.js';
4
+ import { Container } from '../TimeGrid/index.js';
5
+
6
+ export interface TimeGridSkeletonProps {
7
+ /**
8
+ * The number of times.
9
+ * @default 8
10
+ */
11
+ count?: number;
12
+ /**
13
+ * Number of columns where the times are shown.
14
+ * @default 3
15
+ */
16
+ columns?: number;
17
+ }
18
+
19
+ const Time = styled.div`
20
+ height: ${(p) => p.theme.menuItemHeight}em;
21
+
22
+ display: flex;
23
+ justify-content: center;
24
+ align-items: center;
25
+
26
+ padding: 0 0.8em;
27
+ `;
28
+
29
+ let key = 0;
30
+
31
+ /**
32
+ * Provides a time grid placeholder while a user waits for the content to load.
33
+ */
34
+ const TimeGridSkeleton = forwardRef<HTMLDivElement, TimeGridSkeletonProps>(
35
+ ({ count = 8, columns = 3 }, ref) => (
36
+ <Container columns={columns} ref={ref}>
37
+ {Array(count)
38
+ .fill(0)
39
+ .map(() => (
40
+ <Time key={key++}>
41
+ <Skeleton width='2.5em' />
42
+ </Time>
43
+ ))}
44
+ </Container>
45
+ )
46
+ );
47
+
48
+ TimeGridSkeleton.displayName = 'TimeGridSkeleton';
49
+
50
+ export default TimeGridSkeleton;
@@ -0,0 +1,135 @@
1
+ import { omitEmotionProps, useForwardedState } from '@os-design/utils';
2
+ import { forwardRef } from 'react';
3
+ import styled from '@emotion/styled';
4
+ import { css } from '@emotion/react';
5
+ import { clr } from '@os-design/theming';
6
+ import { resetButtonStyles, transitionStyles } from '@os-design/styles';
7
+ import timeToString from './utils/timeToString.js';
8
+
9
+ interface Time {
10
+ hour: number;
11
+ minute: number;
12
+ }
13
+
14
+ type JsxDivProps = Omit<
15
+ JSX.IntrinsicElements['div'],
16
+ 'defaultValue' | 'onChange' | 'ref'
17
+ >;
18
+ export interface TimeListProps extends JsxDivProps {
19
+ /**
20
+ * Times shown in the list.
21
+ * @default []
22
+ */
23
+ times?: Time[];
24
+ /**
25
+ * The time format: 12-hour clock or 24-hour clock.
26
+ * @default false
27
+ */
28
+ hour12?: boolean;
29
+ /**
30
+ * The selected time.
31
+ * @default undefined
32
+ */
33
+ value?: Time | null;
34
+ /**
35
+ * The default value.
36
+ * @default undefined
37
+ */
38
+ defaultValue?: Time | null;
39
+ /**
40
+ * The change event handler.
41
+ * @default undefined
42
+ */
43
+ onChange?: (value: Time | null) => void;
44
+ }
45
+
46
+ const selectedStyles = (p) =>
47
+ p.selected &&
48
+ css`
49
+ background-color: ${clr(p.theme.buttonPrimaryColorBg)};
50
+ color: ${clr(p.theme.buttonPrimaryColorText)};
51
+
52
+ @media (hover: hover) {
53
+ &:hover,
54
+ &:focus-visible {
55
+ background-color: ${clr(p.theme.buttonPrimaryColorBgHover)};
56
+ }
57
+ }
58
+ `;
59
+
60
+ interface TimeProps {
61
+ selected: boolean;
62
+ }
63
+ const Time = styled('button', omitEmotionProps('selected'))<TimeProps>`
64
+ ${resetButtonStyles};
65
+ cursor: pointer;
66
+ user-select: none;
67
+ font-size: 1em;
68
+ line-height: 1;
69
+
70
+ width: 100%;
71
+ height: ${(p) => p.theme.menuItemHeight}em;
72
+
73
+ display: flex;
74
+ justify-content: center;
75
+ align-items: center;
76
+
77
+ padding: 0 0.8em;
78
+
79
+ background-color: ${(p) => clr(p.theme.colorBg)};
80
+ color: ${(p) => clr(p.theme.colorText)};
81
+
82
+ @media (hover: hover) {
83
+ &:hover,
84
+ &:focus-visible {
85
+ background-color: ${(p) => clr(p.theme.menuItemSelectedColorBg)};
86
+ }
87
+ }
88
+
89
+ ${selectedStyles};
90
+ ${transitionStyles('background-color')};
91
+ `;
92
+
93
+ /**
94
+ * The component to choose a time in a list.
95
+ */
96
+ const TimeList = forwardRef<HTMLDivElement, TimeListProps>(
97
+ (
98
+ {
99
+ times = [],
100
+ hour12 = false,
101
+ value,
102
+ defaultValue,
103
+ onChange = () => {},
104
+ ...rest
105
+ },
106
+ ref
107
+ ) => {
108
+ const [forwardedValue, setForwardedValue] = useForwardedState({
109
+ value,
110
+ defaultValue,
111
+ onChange,
112
+ });
113
+
114
+ return (
115
+ <div {...rest} ref={ref}>
116
+ {times.map((time) => {
117
+ const key = time.hour * 60 + time.minute;
118
+ return (
119
+ <Time
120
+ key={key}
121
+ selected={time === forwardedValue}
122
+ onClick={() => setForwardedValue(time)}
123
+ >
124
+ {timeToString(time, hour12)}
125
+ </Time>
126
+ );
127
+ })}
128
+ </div>
129
+ );
130
+ }
131
+ );
132
+
133
+ TimeList.displayName = 'TimeList';
134
+
135
+ export default TimeList;
@@ -0,0 +1,15 @@
1
+ export type Meridiem = 'am' | 'pm';
2
+
3
+ export const convertTo12hours = (hours: number): [number, Meridiem] => {
4
+ if (hours >= 12) {
5
+ const hours12 = hours % 12;
6
+ return [hours12 === 0 ? 12 : hours12, 'pm'];
7
+ } else {
8
+ return [hours === 0 ? 12 : hours, 'am'];
9
+ }
10
+ };
11
+
12
+ export const convertTo24hours = (hours: number, meridiem: Meridiem): number => {
13
+ const h = hours === 12 ? 0 : hours;
14
+ return h + (meridiem === 'am' ? 0 : 12);
15
+ };
@@ -0,0 +1,20 @@
1
+ export interface Time {
2
+ hour: number;
3
+ minute: number;
4
+ }
5
+
6
+ const createTimes = (from: Time, to: Time, stepMinutes: number) => {
7
+ const min = from.hour * 60 + from.minute;
8
+ const max = to.hour * 60 + to.minute;
9
+ const times: Time[] = [];
10
+
11
+ for (let i = min; i <= max - stepMinutes; i += stepMinutes) {
12
+ const hour = Math.floor(i / 60);
13
+ const minute = i % 60;
14
+ times.push({ hour, minute });
15
+ }
16
+
17
+ return times;
18
+ };
19
+
20
+ export default createTimes;
@@ -0,0 +1,17 @@
1
+ import { convertTo12hours } from './convertHours.js';
2
+ import type { Time } from './createTimes.js';
3
+
4
+ const timeToString = (time: Time, hour12: boolean) => {
5
+ const minute = time.minute.toString().padStart(2, '0');
6
+
7
+ if (hour12) {
8
+ const [h, meridiem] = convertTo12hours(time.hour);
9
+ const hour = h.toString().padStart(2, '0');
10
+ return `${hour}:${minute} ${meridiem}`;
11
+ }
12
+
13
+ const hour = time.hour.toString().padStart(2, '0');
14
+ return `${hour}:${minute}`;
15
+ };
16
+
17
+ export default timeToString;
@@ -0,0 +1,44 @@
1
+ import styled from '@emotion/styled';
2
+ import { forwardRef } from 'react';
3
+ import Skeleton from '../Skeleton/index.js';
4
+
5
+ export interface TimeListSkeletonProps {
6
+ /**
7
+ * The number of times.
8
+ * @default 8
9
+ */
10
+ count?: number;
11
+ }
12
+
13
+ const Time = styled.div`
14
+ height: ${(p) => p.theme.menuItemHeight}em;
15
+
16
+ display: flex;
17
+ justify-content: center;
18
+ align-items: center;
19
+
20
+ padding: 0 0.8em;
21
+ `;
22
+
23
+ let key = 0;
24
+
25
+ /**
26
+ * Provides a time list placeholder while a user waits for the content to load.
27
+ */
28
+ const TimeListSkeleton = forwardRef<HTMLDivElement, TimeListSkeletonProps>(
29
+ ({ count = 8 }, ref) => (
30
+ <div ref={ref}>
31
+ {Array(count)
32
+ .fill(0)
33
+ .map(() => (
34
+ <Time key={key++}>
35
+ <Skeleton width='2.5em' />
36
+ </Time>
37
+ ))}
38
+ </div>
39
+ )
40
+ );
41
+
42
+ TimeListSkeleton.displayName = 'TimeListSkeleton';
43
+
44
+ export default TimeListSkeleton;
package/src/index.ts CHANGED
@@ -8,6 +8,7 @@ export { default as Button } from './Button/index.js';
8
8
  export { default as ButtonLink } from './ButtonLink/index.js';
9
9
  export { default as Checkbox } from './Checkbox/index.js';
10
10
  export { default as CheckboxSkeleton } from './CheckboxSkeleton/index.js';
11
+ export { default as DateCalendar } from './DateCalendar/index.js';
11
12
  export { default as DatePicker } from './DatePicker/index.js';
12
13
  export { default as Drawer } from './Drawer/index.js';
13
14
  export { default as Form } from './Form/index.js';
@@ -19,6 +20,7 @@ export { default as HeaderSkeleton } from './HeaderSkeleton/index.js';
19
20
  export { default as Image } from './Image/index.js';
20
21
  export { default as ImageSkeleton } from './ImageSkeleton/index.js';
21
22
  export { default as Input } from './Input/index.js';
23
+ export { default as InputDateUnstyled } from './InputDateUnstyled/index.js';
22
24
  export { default as InputNumber } from './InputNumber/index.js';
23
25
  export { default as InputPassword } from './InputPassword/index.js';
24
26
  export { default as InputSearch } from './InputSearch/index.js';
@@ -63,6 +65,10 @@ export { default as TagSkeleton } from './TagSkeleton/index.js';
63
65
  export { default as TextArea } from './TextArea/index.js';
64
66
  export { default as TextAreaSkeleton } from './TextAreaSkeleton/index.js';
65
67
  export { default as ThemeSwitcher } from './ThemeSwitcher/index.js';
68
+ export { default as TimeGrid } from './TimeGrid/index.js';
69
+ export { default as TimeGridSkeleton } from './TimeGridSkeleton/index.js';
70
+ export { default as TimeList } from './TimeList/index.js';
71
+ export { default as TimeListSkeleton } from './TimeListSkeleton/index.js';
66
72
  export { default as Video } from './Video/index.js';
67
73
 
68
74
  export * from './Alert/index.js';
@@ -75,6 +81,7 @@ export * from './Button/index.js';
75
81
  export * from './ButtonLink/index.js';
76
82
  export * from './Checkbox/index.js';
77
83
  export * from './CheckboxSkeleton/index.js';
84
+ export * from './DateCalendar/index.js';
78
85
  export * from './DatePicker/index.js';
79
86
  export * from './Drawer/index.js';
80
87
  export * from './Form/index.js';
@@ -85,6 +92,7 @@ export * from './HeaderSkeleton/index.js';
85
92
  export * from './Image/index.js';
86
93
  export * from './ImageSkeleton/index.js';
87
94
  export * from './Input/index.js';
95
+ export * from './InputDateUnstyled/index.js';
88
96
  export * from './InputNumber/index.js';
89
97
  export * from './InputPassword/index.js';
90
98
  export * from './InputSearch/index.js';
@@ -128,4 +136,8 @@ export * from './TagSkeleton/index.js';
128
136
  export * from './TextArea/index.js';
129
137
  export * from './TextAreaSkeleton/index.js';
130
138
  export * from './ThemeSwitcher/index.js';
139
+ export * from './TimeGrid/index.js';
140
+ export * from './TimeGridSkeleton/index.js';
141
+ export * from './TimeList/index.js';
142
+ export * from './TimeListSkeleton/index.js';
131
143
  export * from './Video/index.js';
@@ -1,11 +0,0 @@
1
- import { type DatePickerLocale } from '@os-design/date-picker-utils';
2
- import React from 'react';
3
- interface DatePickerCalendarProps {
4
- firstDayOfWeek: 'monday' | 'saturday' | 'sunday';
5
- locale: DatePickerLocale;
6
- value?: Date | [Date, Date] | null;
7
- onSelect?: (value: Date) => void;
8
- }
9
- declare const DatePickerCalendar: React.FC<DatePickerCalendarProps>;
10
- export default DatePickerCalendar;
11
- //# sourceMappingURL=DatePickerCalendar.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DatePickerCalendar.d.ts","sourceRoot":"","sources":["../../src/DatePicker/DatePickerCalendar.tsx"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,gBAAgB,EAGtB,MAAM,8BAA8B,CAAC;AAQtC,OAAO,KAKN,MAAM,OAAO,CAAC;AAGf,UAAU,uBAAuB;IAC/B,cAAc,EAAE,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;IACjD,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,CAAC,EAAE,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAC;CAClC;AAuFD,QAAA,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAkHzD,CAAC;AAEF,eAAe,kBAAkB,CAAC"}