@tactics/toddle-styleguide 5.3.1 → 5.4.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 (178) hide show
  1. package/App.tsx +0 -19
  2. package/app.json +8 -4
  3. package/index.tsx +0 -4
  4. package/package.json +61 -28
  5. package/src/components/atoms/calendar/calendar.component.tsx +10 -6
  6. package/src/components/atoms/calendar/calendar.preview.tsx +4 -3
  7. package/src/components/molecules/amount/amount.component.tsx +5 -4
  8. package/src/components/molecules/calendar-select/calendar-select.component.d.ts +4 -4
  9. package/src/components/molecules/calendar-select/calendar-select.component.tsx +17 -16
  10. package/src/components/molecules/calendar-select/calendar-select.preview.tsx +16 -5
  11. package/src/components/molecules/date-input/date-input.component.d.ts +2 -2
  12. package/src/components/molecules/date-input/date-input.component.tsx +3 -3
  13. package/src/components/molecules/date-input/date-input.preview.tsx +5 -5
  14. package/src/components/molecules/day/day.component.d.ts +3 -3
  15. package/src/components/molecules/day/day.component.tsx +22 -17
  16. package/src/components/molecules/selectable-list-item/selectable-list-item.component.tsx +12 -7
  17. package/src/components/molecules/timestamp/timestamp.component.d.ts +2 -2
  18. package/src/components/molecules/timestamp/timestamp.component.tsx +12 -5
  19. package/src/components/organisms/journal-entry/components/journal-entry-type/journal-entry-type.component.d.ts +2 -2
  20. package/src/components/organisms/journal-entry/components/journal-entry-type/journal-entry-type.component.tsx +5 -5
  21. package/src/components/organisms/journal-entry/journal-entry.component.d.ts +3 -3
  22. package/src/components/organisms/journal-entry/journal-entry.component.tsx +7 -3
  23. package/src/components/organisms/journal-entry/journal-entry.preview.tsx +7 -3
  24. package/src/components/organisms/text-bubble/text-bubble.component.d.ts +2 -2
  25. package/src/components/organisms/text-bubble/text-bubble.component.tsx +6 -3
  26. package/src/components/organisms/text-bubble/text-bubble.preview.tsx +19 -7
  27. package/src/components/templates/popover-action/popover-action.component.tsx +9 -8
  28. package/src/icons/solid/cloud-download/cloud-download.icon.tsx +1 -1
  29. package/src/icons/solid/refresh/refresh-solid.icon.tsx +2 -2
  30. package/src/utilities/datetime/clock.class.tsx +14 -0
  31. package/src/utilities/datetime/dateonly.class.tsx +287 -0
  32. package/src/utilities/datetime/datetime.class.tsx +288 -0
  33. package/src/utilities/datetime/day.class.tsx +48 -0
  34. package/src/utilities/datetime/dayjs-config.ts +96 -0
  35. package/src/utilities/datetime/dayoftheweek.class.tsx +242 -0
  36. package/src/utilities/datetime/hour.class.tsx +60 -0
  37. package/src/utilities/datetime/locale.tsx +6 -0
  38. package/src/utilities/datetime/millisecond.class.tsx +48 -0
  39. package/src/utilities/datetime/minute.class.tsx +55 -0
  40. package/src/utilities/datetime/month.class.tsx +74 -0
  41. package/src/utilities/datetime/second.class.tsx +52 -0
  42. package/src/utilities/datetime/time.class.tsx +190 -0
  43. package/src/utilities/datetime/timezone.class.tsx +36 -0
  44. package/src/utilities/datetime/year.class.tsx +78 -0
  45. package/src/utilities/datetime/yearandmonth.class.tsx +80 -0
  46. package/src/components/atoms/background-gradient/__snapshots__/background-gradient.test.js.snap +0 -40
  47. package/src/components/atoms/background-gradient/background-gradient.test.js +0 -10
  48. package/src/components/atoms/calendar/__snapshots__/calendar.test.js.snap +0 -6817
  49. package/src/components/atoms/calendar/calendar.test.js +0 -35
  50. package/src/components/atoms/check-switch/__snapshots__/check-switch.test.js.snap +0 -84
  51. package/src/components/atoms/check-switch/check-switch.test.js +0 -13
  52. package/src/components/atoms/heading-components/all-caps-heading/__snapshots__/all-caps-heading.test.js.snap +0 -113
  53. package/src/components/atoms/heading-components/all-caps-heading/all-caps-heading.test.js +0 -44
  54. package/src/components/atoms/heading-components/heading1/__snapshots__/heading1.test.js.snap +0 -121
  55. package/src/components/atoms/heading-components/heading1/heading1.test.js +0 -51
  56. package/src/components/atoms/heading-components/heading2/__snapshots__/heading2.test.js.snap +0 -121
  57. package/src/components/atoms/heading-components/heading2/heading2.test.js +0 -51
  58. package/src/components/atoms/heading-components/heading3/__snapshots__/heading3.test.js.snap +0 -121
  59. package/src/components/atoms/heading-components/heading3/heading3.test.js +0 -51
  60. package/src/components/atoms/heading-components/heading4/__snapshots__/heading4.test.js.snap +0 -121
  61. package/src/components/atoms/heading-components/heading4/heading4.test.js +0 -51
  62. package/src/components/atoms/image-bubble/__snapshots__/image-bubble.test.js.snap +0 -67
  63. package/src/components/atoms/image-bubble/image-bubble.test.js +0 -20
  64. package/src/components/atoms/increment-input/__snapshots__/increment-input.test.js.snap +0 -269
  65. package/src/components/atoms/increment-input/increment-input.test.js +0 -14
  66. package/src/components/atoms/logo/__snapshots__/logo.test.js.snap +0 -113
  67. package/src/components/atoms/logo/logo.test.js +0 -16
  68. package/src/components/atoms/paragraph-components/paragraph/__snapshots__/paragraph.test.js.snap +0 -121
  69. package/src/components/atoms/paragraph-components/paragraph/paragraph.test.js +0 -76
  70. package/src/components/atoms/paragraph-components/small-text/__snapshots__/small-text.test.js.snap +0 -121
  71. package/src/components/atoms/paragraph-components/small-text/small-text.test.js +0 -76
  72. package/src/components/atoms/paragraph-components/tiny-text/__snapshots__/tiny-text.test.js.snap +0 -121
  73. package/src/components/atoms/paragraph-components/tiny-text/tiny-text.test.js +0 -76
  74. package/src/components/atoms/quick-message/__snapshots__/quick-message.test.js.snap +0 -143
  75. package/src/components/atoms/quick-message/quick-message.test.js +0 -58
  76. package/src/components/atoms/split-container/__snapshots__/split-container.test.js.snap +0 -333
  77. package/src/components/atoms/split-container/split-container.test.js +0 -45
  78. package/src/components/atoms/text-input/__snapshots__/text-input.test.js.snap +0 -123
  79. package/src/components/atoms/text-input/text-input.test.js +0 -59
  80. package/src/components/molecules/avatar/__snapshots__/avatar.test.js.snap +0 -97
  81. package/src/components/molecules/avatar/avatar.test.js +0 -22
  82. package/src/components/molecules/blocked-message/__snapshots__/blocked-message.test.js.snap +0 -107
  83. package/src/components/molecules/blocked-message/blocked-message.test.js +0 -12
  84. package/src/components/molecules/button/__snapshots__/button.test.js.snap +0 -652
  85. package/src/components/molecules/button/button.test.js +0 -56
  86. package/src/components/molecules/calendar-select/__snapshots__/calendar-select.test.js.snap +0 -343
  87. package/src/components/molecules/calendar-select/calendar-select.test.js +0 -20
  88. package/src/components/molecules/cancel-link/__snapshots__/cancel-link.test.js.snap +0 -139
  89. package/src/components/molecules/cancel-link/cancel-link.test.js +0 -28
  90. package/src/components/molecules/checkbox/__snapshots__/checkbox.test.js.snap +0 -176
  91. package/src/components/molecules/checkbox/checkbox.test.js +0 -30
  92. package/src/components/molecules/contact-address/__snapshots__/contact-address.test.js.snap +0 -113
  93. package/src/components/molecules/contact-address/contact-address.test.js +0 -18
  94. package/src/components/molecules/contact-role/__snapshots__/contact-role.test.js.snap +0 -113
  95. package/src/components/molecules/contact-role/contact-role.test.js +0 -18
  96. package/src/components/molecules/date-input/__snapshots__/date-input.test.js.snap +0 -140
  97. package/src/components/molecules/date-input/date-input.test.js +0 -23
  98. package/src/components/molecules/day/__snapshots__/day.test.js.snap +0 -263
  99. package/src/components/molecules/day/day.test.js +0 -37
  100. package/src/components/molecules/default-select/__snapshots__/default-select.test.js.snap +0 -140
  101. package/src/components/molecules/default-select/default-select.test.js +0 -17
  102. package/src/components/molecules/department_logo/__snapshots__/department-logo.test.js.snap +0 -27
  103. package/src/components/molecules/department_logo/department-logo.test.js +0 -12
  104. package/src/components/molecules/failed-to-send/__snapshots__/failed-bubble.test.js.snap +0 -386
  105. package/src/components/molecules/failed-to-send/failed-bubble.test.js +0 -75
  106. package/src/components/molecules/filter-range/__snapshots__/filter-range.test.js.snap +0 -208
  107. package/src/components/molecules/filter-range/filter-range.test.js +0 -20
  108. package/src/components/molecules/filter-tab/__snapshots__/filter-tab.test.js.snap +0 -536
  109. package/src/components/molecules/filter-tab/filter-tab.test.js +0 -42
  110. package/src/components/molecules/info/__snapshots__/info.test.js.snap +0 -64
  111. package/src/components/molecules/info/info.test.js +0 -18
  112. package/src/components/molecules/language-button/__snapshots__/language-button.test.js.snap +0 -129
  113. package/src/components/molecules/language-button/language-button.test.js +0 -29
  114. package/src/components/molecules/message-input/__snapshots__/message-input.test.js.snap +0 -611
  115. package/src/components/molecules/message-input/message-input.test.js +0 -63
  116. package/src/components/molecules/more-info-button/__snapshots__/more-info-button.test.js.snap +0 -133
  117. package/src/components/molecules/more-info-button/more-info-button.test.js +0 -29
  118. package/src/components/molecules/password-input/__snapshots__/password-input.test.js.snap +0 -504
  119. package/src/components/molecules/password-input/password-input.test.js +0 -46
  120. package/src/components/molecules/pill/__snapshots__/pill.test.js.snap +0 -226
  121. package/src/components/molecules/pill/pill.test.js +0 -42
  122. package/src/components/molecules/pressable-icon/__snapshots__/pressable-icon.test.js.snap +0 -460
  123. package/src/components/molecules/pressable-icon/pressable-icon.test.js +0 -51
  124. package/src/components/molecules/quick-filter/__snapshots__/quick-filter.test.js.snap +0 -557
  125. package/src/components/molecules/quick-filter/quick-filter.test.js +0 -134
  126. package/src/components/molecules/search-input/__snapshots__/search.test.js.snap +0 -145
  127. package/src/components/molecules/search-input/search.test.js +0 -22
  128. package/src/components/molecules/select-link/__snapshots__/select-link.test.js.snap +0 -70
  129. package/src/components/molecules/select-link/select-link.test.js +0 -17
  130. package/src/components/molecules/select-list-item/__snapshots__/select-list-item.test.js.snap +0 -762
  131. package/src/components/molecules/select-list-item/select-list-item.test.js +0 -38
  132. package/src/components/molecules/select-picker/__snapshots__/select-picker.test.js.snap +0 -407
  133. package/src/components/molecules/select-picker/select-picker.test.js +0 -31
  134. package/src/components/molecules/send-bubble/__snapshots__/send-text-bubble.test.js.snap +0 -1979
  135. package/src/components/molecules/send-bubble/send-text-bubble.test.js +0 -156
  136. package/src/components/molecules/snackbar/__snapshots__/snackbar.test.js.snap +0 -557
  137. package/src/components/molecules/snackbar/snackbar.test.js +0 -35
  138. package/src/components/molecules/swipe/__snapshots__/swipe.test.js.snap +0 -340
  139. package/src/components/molecules/swipe/swipe.test.js +0 -46
  140. package/src/components/molecules/tag/__snapshots__/tag.test.js.snap +0 -139
  141. package/src/components/molecules/tag/tag.test.js +0 -34
  142. package/src/components/molecules/time-picker/__snapshots__/time-picker.test.js.snap +0 -2221
  143. package/src/components/molecules/time-picker/time-picker.test.js +0 -18
  144. package/src/components/molecules/time-tracker/__snapshots__/time-tracker.test.js.snap +0 -266
  145. package/src/components/molecules/time-tracker/time-tracker.test.js +0 -36
  146. package/src/components/molecules/timeline/__snapshots__/timeline.test.js.snap +0 -257
  147. package/src/components/molecules/timeline/timeline.test.js +0 -18
  148. package/src/components/molecules/timestamp/__snapshots__/timestamp.test.js.snap +0 -28
  149. package/src/components/molecules/timestamp/timestamp.test.js +0 -16
  150. package/src/components/molecules/wave-background/__snapshots__/wave.test.js.snap +0 -173
  151. package/src/components/molecules/wave-background/wave.test.js +0 -25
  152. package/src/components/molecules/wide-button/__snapshots__/wide-button.test.js.snap +0 -269
  153. package/src/components/molecules/wide-button/wide-button.test.js +0 -30
  154. package/src/components/organisms/child-list-item/__snapshots__/child-list-item.test.js.snap +0 -1040
  155. package/src/components/organisms/child-list-item/child-list-item.test.js +0 -75
  156. package/src/components/organisms/contact-item/__snapshots__/contact-item.test.js.snap +0 -404
  157. package/src/components/organisms/contact-item/contact-item.test.js +0 -22
  158. package/src/components/organisms/loading-indicator/__snapshots__/loading-indicator.test.js.snap +0 -474
  159. package/src/components/organisms/loading-indicator/loading-indicator.test.js +0 -41
  160. package/src/components/organisms/my-child-list-item/__snapshots__/my-child-list-item.test.js.snap +0 -293
  161. package/src/components/organisms/my-child-list-item/my-child-list-item.test.js +0 -23
  162. package/src/components/organisms/person-info-card/__snapshots__/person-info-card.test.js.snap +0 -709
  163. package/src/components/organisms/person-info-card/person-info-card.test.js +0 -85
  164. package/src/components/organisms/text-bubble/__snapshots__/text-bubble.test.js.snap +0 -3046
  165. package/src/components/organisms/text-bubble/text-bubble.test.js +0 -144
  166. package/src/utilities/toddle-datetime/interfaces/duration.interface.d.ts +0 -22
  167. package/src/utilities/toddle-datetime/interfaces/duration.interface.tsx +0 -23
  168. package/src/utilities/toddle-datetime/interfaces/toddle-datetime.interface.d.ts +0 -22
  169. package/src/utilities/toddle-datetime/interfaces/toddle-datetime.interface.tsx +0 -25
  170. package/src/utilities/toddle-datetime/toddle-datetime.class.d.ts +0 -50
  171. package/src/utilities/toddle-datetime/toddle-datetime.class.tsx +0 -206
  172. package/src/utilities/toddle-datetime/toddle-datetime.preview.d.ts +0 -2
  173. package/src/utilities/toddle-datetime/toddle-datetime.preview.tsx +0 -160
  174. package/src/utilities/toddle-datetime/toddle-datetime.test.js +0 -127
  175. package/src/utilities/toddle-datetime/types/duration.type.d.ts +0 -4
  176. package/src/utilities/toddle-datetime/types/duration.type.tsx +0 -6
  177. package/src/utilities/toddle-datetime/types/toddle-datetime.type.d.ts +0 -5
  178. package/src/utilities/toddle-datetime/types/toddle-datetime.type.tsx +0 -23
@@ -0,0 +1,190 @@
1
+ import {Hour, HourOutputFormat} from './hour.class';
2
+ import {Minute, MinuteOutputFormat} from './minute.class';
3
+ import {Second, SecondOutputFormat} from './second.class';
4
+ import {Millisecond, MilliSecondOutputFormat} from './millisecond.class';
5
+
6
+ export class InvalidTimeOutputFormat extends Error {
7
+ static unknownFormat() {
8
+ return new InvalidTimeOutputFormat("The provided format is invalid.");
9
+ }
10
+ }
11
+
12
+ export enum TimeInputFormat {
13
+ SHORT = "HH:mm",
14
+ WITH_SECONDS = "HH:mm:ss",
15
+ WITH_MILLISECONDS = "HH:mm:ss.SSS",
16
+ }
17
+
18
+ export enum TimeOutputFormat {
19
+ TIME_SHORT = "HH:mm",
20
+ TIME_WITH_SECONDS = "HH:mm:ss",
21
+ TIME_WITH_MILLISECONDS = "HH:mm:ss.SSS",
22
+ }
23
+
24
+ export interface TimeInterface {
25
+ hour: Hour;
26
+ minute: Minute;
27
+ second: Second;
28
+ millisecond: Millisecond;
29
+ format(format: TimeOutputFormat): string;
30
+ // formatLocale is not included since time don't get formatted local.
31
+
32
+ isSame(time: TimeInterface): boolean;
33
+ isBefore(other: TimeInterface): boolean;
34
+ isAfter(other: TimeInterface): boolean;
35
+ toMilliseconds(): number;
36
+ toIso8601(): string;
37
+ }
38
+
39
+ export class Time implements TimeInterface {
40
+ private constructor(
41
+ public readonly hour: Hour,
42
+ public readonly minute: Minute,
43
+ public readonly second: Second,
44
+ public readonly millisecond: Millisecond,
45
+ ) {}
46
+
47
+ static from(
48
+ hour: number,
49
+ minute: number,
50
+ second?: number,
51
+ millisecond?: number,
52
+ ): Time {
53
+ return new Time(
54
+ Hour.from(hour),
55
+ Minute.from(minute),
56
+ second ? Second.from(second) : Second.from(0),
57
+ millisecond ? Millisecond.from(millisecond) : Millisecond.from(0),
58
+ );
59
+ }
60
+
61
+ private static fromShort(timeString: string) {
62
+ const split = timeString.split(":").map(Number);
63
+ if (split.length !== 2) {
64
+ throw new Error(
65
+ 'Invalid time string format. Expected format is "HH:mm".',
66
+ );
67
+ }
68
+
69
+ const [hour, minute] = split;
70
+
71
+ if (isNaN(hour) || isNaN(minute)) {
72
+ throw new Error(
73
+ 'Invalid time string format. Expected format is "HH:mm".',
74
+ );
75
+ }
76
+
77
+ return Time.from(hour, minute, 0, 0);
78
+ }
79
+
80
+ private static fromWithSeconds(timeString: string) {
81
+ const split = timeString.split(":").map(Number);
82
+ if (split.length !== 3) {
83
+ throw new Error(
84
+ 'Invalid time string format. Expected format is "HH:mm:ss".',
85
+ );
86
+ }
87
+
88
+ const [hour, minute, second] = split;
89
+
90
+ if (isNaN(hour) || isNaN(minute) || isNaN(second)) {
91
+ throw new Error(
92
+ 'Invalid time string format. Expected format is "HH:mm:ss".',
93
+ );
94
+ }
95
+
96
+ return Time.from(hour, minute, second, 0);
97
+ }
98
+
99
+ private static fromWithMilliSeconds(timeString: string) {
100
+ const split = timeString.split(".");
101
+
102
+ if (split.length !== 2) {
103
+ throw new Error(
104
+ 'Invalid time string format. Expected format is "HH:mm:ss.SSS".',
105
+ );
106
+ }
107
+
108
+ const [rest, millies] = split;
109
+
110
+ const restSplit = rest.split(":").map(Number);
111
+ const millisec = Number(millies);
112
+
113
+ if (restSplit.length !== 3) {
114
+ throw new Error(
115
+ 'Invalid time string format. Expected format is "HH:mm:ss.SSS".',
116
+ );
117
+ }
118
+
119
+ const [hour, minute, second] = restSplit;
120
+
121
+ if (isNaN(hour) || isNaN(minute) || isNaN(second) || isNaN(millisec)) {
122
+ throw new Error(
123
+ 'Invalid time string format. Expected format is "HH:mm:ss.SSS".',
124
+ );
125
+ }
126
+
127
+ return Time.from(hour, minute, second, millisec);
128
+ }
129
+
130
+ static fromFormat(timeString: string, format: TimeInputFormat): Time {
131
+ switch (format) {
132
+ case TimeInputFormat.WITH_MILLISECONDS:
133
+ return Time.fromWithMilliSeconds(timeString);
134
+ case TimeInputFormat.WITH_SECONDS:
135
+ return Time.fromWithSeconds(timeString);
136
+ case TimeInputFormat.SHORT:
137
+ return Time.fromShort(timeString);
138
+ default:
139
+ throw InvalidTimeOutputFormat.unknownFormat();
140
+ }
141
+ }
142
+
143
+ public toIso8601(): string {
144
+ return this.format(TimeOutputFormat.TIME_WITH_MILLISECONDS);
145
+ }
146
+
147
+ // Formats the time (hh:mm format)
148
+ format(format: TimeOutputFormat): string {
149
+ const formattedHour = this.hour.format(HourOutputFormat.HOUR_TWO_DIGIT);
150
+ const formattedMinute = this.minute.format(
151
+ MinuteOutputFormat.MINUTE_TWO_DIGIT,
152
+ );
153
+
154
+ switch (format) {
155
+ case TimeOutputFormat.TIME_WITH_MILLISECONDS:
156
+ return `${formattedHour}:${formattedMinute}:${this.second.format(SecondOutputFormat.SECOND_TWO_DIGIT)}.${this.millisecond.format(MilliSecondOutputFormat.MILLISECOND_THREE_DIGIT)}`;
157
+ case TimeOutputFormat.TIME_WITH_SECONDS:
158
+ return `${formattedHour}:${formattedMinute}:${this.second.format(SecondOutputFormat.SECOND_TWO_DIGIT)}`;
159
+ case TimeOutputFormat.TIME_SHORT:
160
+ return `${formattedHour}:${formattedMinute}`;
161
+ }
162
+ }
163
+
164
+ isSame(other: TimeInterface): boolean {
165
+ return (
166
+ this.hour.isSame(other.hour) &&
167
+ this.minute.isSame(other.minute) &&
168
+ this.second.isSame(other.second) &&
169
+ this.millisecond.isSame(other.millisecond)
170
+ );
171
+ }
172
+
173
+ isBefore(other: TimeInterface): boolean {
174
+ return this.toMilliseconds() < other.toMilliseconds();
175
+ }
176
+
177
+ isAfter(other: Time): boolean {
178
+ return this.toMilliseconds() > other.toMilliseconds();
179
+ }
180
+
181
+ toMilliseconds(): number {
182
+ return (
183
+ (this.hour.asInt() * 3600 +
184
+ this.minute.asInt() * 60 +
185
+ this.second.asInt()) *
186
+ 1000 +
187
+ this.millisecond.asInt()
188
+ );
189
+ }
190
+ }
@@ -0,0 +1,36 @@
1
+ import dayjs from './dayjs-config';
2
+
3
+ export interface TimeZoneInterface {
4
+ name(): string;
5
+ isSame(zone: TimeZoneInterface): boolean;
6
+ }
7
+
8
+ export class TimeZone implements TimeZoneInterface {
9
+ private readonly zone: string;
10
+
11
+ private constructor(private readonly timezone: string) {
12
+ this.zone = timezone;
13
+ }
14
+
15
+ static from(timezone: string): TimeZoneInterface {
16
+ return new TimeZone(timezone);
17
+ }
18
+
19
+ static UTC(): TimeZoneInterface {
20
+ return new TimeZone('UTC');
21
+ }
22
+
23
+ isSame(zone: TimeZoneInterface): boolean {
24
+ return this.name() === zone.name();
25
+ }
26
+
27
+ name(): string {
28
+ return this.zone;
29
+ }
30
+ }
31
+
32
+ export const SystemTimezone: TimeZoneInterface = TimeZone.from(
33
+ dayjs.tz.guess(),
34
+ );
35
+
36
+ export const UTCTimezone: TimeZoneInterface = TimeZone.UTC();
@@ -0,0 +1,78 @@
1
+ export class InvalidYear extends Error {
2
+ static negativeNumber() {
3
+ return new InvalidYear("Year must be a non-negative number.");
4
+ }
5
+ }
6
+
7
+ export enum YearOutputFormat {
8
+ /** Month and day numeric (e.g., 2020) */
9
+ YEAR_NUMERIC = "year-numeric",
10
+ /** Month and day numeric (e.g., 20) */
11
+ YEAR_TWO_DIGIT = "year-2-digit",
12
+ }
13
+
14
+ export interface YearInterface {
15
+ isSame(year: Year): boolean;
16
+ isBefore(year: Year): boolean;
17
+ isAfter(year: Year): boolean;
18
+ asInt(): number;
19
+ previous(): Year;
20
+ next(): Year;
21
+ add(years: number): Year;
22
+
23
+ format(format: YearOutputFormat): string;
24
+ // formatLocale is not included since year don't get formatted local.
25
+ }
26
+
27
+ export class Year implements YearInterface {
28
+ constructor(private readonly year: number) {
29
+ if (year < 0) {
30
+ throw InvalidYear.negativeNumber();
31
+ }
32
+
33
+ this.year = year;
34
+ }
35
+
36
+ static from(year: number): Year {
37
+ return new Year(year);
38
+ }
39
+
40
+ asInt() : number {
41
+ return this.year;
42
+ }
43
+
44
+ format(format: YearOutputFormat): string {
45
+ switch (format) {
46
+ case YearOutputFormat.YEAR_NUMERIC:
47
+ return String(this.year);
48
+ case YearOutputFormat.YEAR_TWO_DIGIT:
49
+ return String(this.year).slice(-2);
50
+ default:
51
+ throw new Error(`Unsupported format: ${format}`);
52
+ }
53
+ }
54
+
55
+ add(years: number): Year {
56
+ return Year.from(this.asInt() + years);
57
+ }
58
+
59
+ previous(): Year {
60
+ return Year.from(this.asInt() - 1);
61
+ }
62
+
63
+ next(): Year {
64
+ return Year.from(this.asInt() + 1);
65
+ }
66
+
67
+ isBefore(year: Year): boolean {
68
+ return this.asInt() < year.asInt();
69
+ }
70
+
71
+ isAfter(year: Year): boolean {
72
+ return this.asInt() > year.asInt();
73
+ }
74
+
75
+ isSame(year: Year): boolean {
76
+ return this.asInt() === year.asInt();
77
+ }
78
+ }
@@ -0,0 +1,80 @@
1
+ import {Year, YearOutputFormat} from './year.class';
2
+ import {Month, MonthOutputFormat} from './month.class';
3
+ import {Day, DayOutputFormat} from './day.class';
4
+ import {Locale} from './locale';
5
+ import dayjs from './dayjs-config';
6
+
7
+ export enum YearAndMonthLocaleAwareOutputFormat {
8
+ /** Month and year only (e.g., October 2024) */
9
+ YEAR_AND_MONTH_FULL = "MMMM yyyy",
10
+
11
+ /** Month and year only (e.g., Oct 2024) */
12
+ YEAR_AND_MONTH_SHORT = "MM yyyy",
13
+ }
14
+
15
+ export enum YearAndMonthOutputFormat {
16
+ /** Month and day numeric (e.g., 10/2024) */
17
+ YEAR_AND_MONTH_NUMERIC = "MM/yyyy",
18
+ }
19
+
20
+ export interface YearAndMonthInterface {
21
+ daysInMonth(): 28 | 29 | 30 | 31;
22
+ format(format: YearAndMonthOutputFormat): string;
23
+ formatLocale(format: YearAndMonthLocaleAwareOutputFormat, locale: Locale): string;
24
+ }
25
+
26
+ export class YearAndMonth implements YearAndMonthInterface {
27
+ private constructor(
28
+ private readonly year: Year,
29
+ private readonly month: Month,
30
+ ) {}
31
+
32
+ static from(year: Year, month: Month): YearAndMonth {
33
+ return new YearAndMonth(year, month);
34
+ }
35
+
36
+ daysInMonth(): 28 | 29 | 30 | 31 {
37
+ const currentMonth = new Date(
38
+ this.year.asInt(),
39
+ this.month.asInt() + 1, // We add 1 to get the next month
40
+ 0, // Will return the last day of the previous month
41
+ );
42
+ return currentMonth.getDate() as 28 | 29 | 30 | 31;
43
+ }
44
+
45
+ format(format: YearAndMonthOutputFormat): string {
46
+ switch (format) {
47
+ case YearAndMonthOutputFormat.YEAR_AND_MONTH_NUMERIC:
48
+ return String(this.year.asInt() + '/' + this.month.asInt());
49
+ default:
50
+ throw new Error(`Unsupported format: ${format}`);
51
+ }
52
+ }
53
+
54
+ formatLocale(format: YearAndMonthLocaleAwareOutputFormat, locale: Locale): string {
55
+
56
+ const day = Day.from(1);
57
+
58
+ // Fake a day to let dayjs handle the local formatting.
59
+ // this works since we only format year and month, and date is not changed.
60
+ const fakedDay = dayjs.utc(
61
+ this.year.format(YearOutputFormat.YEAR_NUMERIC) + '-' + this.month.format(MonthOutputFormat.MONTH_TWO_DIGIT) + '-' + day.format(DayOutputFormat.DAY_TWO_DIGIT) + 'T' + '12:00:00'
62
+ );
63
+
64
+ if (!fakedDay.isValid()) {
65
+ throw new Error(`Invalid day`);
66
+ }
67
+
68
+ const localeAware = fakedDay.locale(locale)
69
+
70
+ switch (format) {
71
+ case YearAndMonthLocaleAwareOutputFormat.YEAR_AND_MONTH_SHORT:
72
+ return localeAware.format('MMM YYYY')
73
+ case YearAndMonthLocaleAwareOutputFormat.YEAR_AND_MONTH_FULL:
74
+ return localeAware.format('MMMM YYYY')
75
+ default:
76
+ throw new Error(`Unsupported format: ${format}`);
77
+ }
78
+ }
79
+
80
+ }
@@ -1,40 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`test gradient background should render a gradient background 1`] = `
4
- <ViewManagerAdapter_ExpoLinearGradient
5
- colors={
6
- [
7
- 4281681564,
8
- 4284775115,
9
- 4284775115,
10
- ]
11
- }
12
- endPoint={
13
- [
14
- 0.9,
15
- 0.9,
16
- ]
17
- }
18
- locations={
19
- [
20
- 0,
21
- 0.55,
22
- 1,
23
- ]
24
- }
25
- startPoint={
26
- [
27
- 0.1,
28
- 0.1,
29
- ]
30
- }
31
- style={
32
- {
33
- "height": "100%",
34
- "position": "absolute",
35
- "width": "100%",
36
- "zIndex": -1,
37
- }
38
- }
39
- />
40
- `;
@@ -1,10 +0,0 @@
1
- import React from 'react';
2
- import render from 'react-test-renderer';
3
- import {BackgroundGradient} from './background-gradient.component';
4
-
5
- describe('test gradient background', () => {
6
- it('should render a gradient background', () => {
7
- const tree = render.create(<BackgroundGradient />).toJSON();
8
- expect(tree).toMatchSnapshot();
9
- });
10
- });