@origostudio/origo-design 0.0.49 → 0.0.51

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 (98) hide show
  1. package/CHANGELOG.md +6 -4
  2. package/dist/packages/angular-renderer/CHANGELOG.md +22 -0
  3. package/dist/packages/angular-renderer/package.json +3 -3
  4. package/dist/packages/angular-renderer/src/components/primitives/autocomplete/autocomplete.component.d.ts +99 -0
  5. package/dist/packages/angular-renderer/src/components/primitives/autocomplete/autocomplete.component.js +306 -0
  6. package/dist/packages/angular-renderer/src/components/primitives/autocomplete/autocomplete.component.js.map +1 -0
  7. package/dist/packages/angular-renderer/src/components/primitives/combobox/combobox.component.d.ts +69 -0
  8. package/dist/packages/angular-renderer/src/components/primitives/combobox/combobox.component.js +276 -0
  9. package/dist/packages/angular-renderer/src/components/primitives/combobox/combobox.component.js.map +1 -0
  10. package/dist/packages/angular-renderer/src/components/primitives/date-picker/date-picker.component.d.ts +57 -0
  11. package/dist/packages/angular-renderer/src/components/primitives/date-picker/date-picker.component.js +257 -0
  12. package/dist/packages/angular-renderer/src/components/primitives/date-picker/date-picker.component.js.map +1 -0
  13. package/dist/packages/angular-renderer/src/components/primitives/date-range-picker/date-range-picker.component.d.ts +67 -0
  14. package/dist/packages/angular-renderer/src/components/primitives/date-range-picker/date-range-picker.component.js +299 -0
  15. package/dist/packages/angular-renderer/src/components/primitives/date-range-picker/date-range-picker.component.js.map +1 -0
  16. package/dist/packages/angular-renderer/src/components/primitives/multi-select/multi-select.component.d.ts +110 -0
  17. package/dist/packages/angular-renderer/src/components/primitives/multi-select/multi-select.component.js +323 -0
  18. package/dist/packages/angular-renderer/src/components/primitives/multi-select/multi-select.component.js.map +1 -0
  19. package/dist/packages/angular-renderer/src/components/primitives/select/select.component.d.ts +80 -19
  20. package/dist/packages/angular-renderer/src/components/primitives/select/select.component.js +201 -24
  21. package/dist/packages/angular-renderer/src/components/primitives/select/select.component.js.map +1 -1
  22. package/dist/packages/angular-renderer/src/components/primitives/select/selection-utils.d.ts +9 -0
  23. package/dist/packages/angular-renderer/src/components/primitives/select/selection-utils.js +69 -0
  24. package/dist/packages/angular-renderer/src/components/primitives/select/selection-utils.js.map +1 -0
  25. package/dist/packages/angular-renderer/src/components/primitives/time-picker/time-picker.component.d.ts +48 -0
  26. package/dist/packages/angular-renderer/src/components/primitives/time-picker/time-picker.component.js +214 -0
  27. package/dist/packages/angular-renderer/src/components/primitives/time-picker/time-picker.component.js.map +1 -0
  28. package/dist/packages/angular-renderer/src/index.d.ts +6 -0
  29. package/dist/packages/angular-renderer/src/index.js +6 -0
  30. package/dist/packages/angular-renderer/src/index.js.map +1 -1
  31. package/dist/packages/angular-renderer/src/lib/primitives.provider.js +12 -0
  32. package/dist/packages/angular-renderer/src/lib/primitives.provider.js.map +1 -1
  33. package/dist/packages/cli/CHANGELOG.md +8 -0
  34. package/dist/packages/cli/package.json +2 -2
  35. package/dist/packages/cli/package.json.bak +2 -2
  36. package/dist/packages/core/CHANGELOG.md +8 -0
  37. package/dist/packages/core/package.json +1 -1
  38. package/dist/packages/core/package.json.bak +1 -1
  39. package/dist/packages/design-tokens/CHANGELOG.md +8 -0
  40. package/dist/packages/design-tokens/package.json +1 -1
  41. package/dist/packages/playground/browser/{chunk-B_swdRuc.js → chunk-2fyh0Go5.js} +1 -1
  42. package/dist/packages/playground/browser/{chunk-C8l8Pst_.js → chunk-6qDdu3iP.js} +1 -1
  43. package/dist/packages/playground/browser/{chunk-G1sQXMvG.js → chunk-BQHgLM1h.js} +1 -1
  44. package/dist/packages/playground/browser/{chunk-Cb2ALrKC.js → chunk-BQrkBjEv.js} +1 -1
  45. package/dist/packages/playground/browser/{chunk-BbeNQQ9Z.js → chunk-BSIGVQT8.js} +1 -1
  46. package/dist/packages/playground/browser/{chunk-BlCRDoSd.js → chunk-CD79k8Eb.js} +1 -1
  47. package/dist/packages/playground/browser/{chunk-CCE_vAje.js → chunk-D6mKAQPx.js} +1 -1
  48. package/dist/packages/playground/browser/{chunk-DoYDPF2-.js → chunk-DBZa4hap.js} +1 -1
  49. package/dist/packages/playground/browser/{chunk-CpaI4VGh.js → chunk-DGb2Oa6d.js} +1 -1
  50. package/dist/packages/playground/browser/{chunk-B8mwHWgW.js → chunk-DPEeny3K.js} +1 -1
  51. package/dist/packages/playground/browser/{chunk-DgLZ-dIi.js → chunk-DeS5TtZS.js} +1 -1
  52. package/dist/packages/playground/browser/{chunk-r4-UbXQJ.js → chunk-DnW3HJ2k.js} +1 -1
  53. package/dist/packages/playground/browser/{chunk-lFsGUZ3A.js → chunk-V8VJI0nO.js} +1 -1
  54. package/dist/packages/playground/browser/{chunk-XTbjIUbx.js → chunk-mGxxpk2V.js} +1 -1
  55. package/dist/packages/playground/browser/{chunk-DkxgAarv.js → chunk-vt9o3pSK.js} +1 -1
  56. package/dist/packages/playground/browser/index.html +1 -1
  57. package/dist/packages/playground/browser/main-6RRVB3JV.js +740 -0
  58. package/package.json +1 -1
  59. package/packages/angular-renderer/CHANGELOG.md +22 -0
  60. package/packages/angular-renderer/package.json +3 -3
  61. package/packages/angular-renderer/src/components/primitives/autocomplete/autocomplete.component.html +83 -0
  62. package/packages/angular-renderer/src/components/primitives/autocomplete/autocomplete.component.scss +161 -0
  63. package/packages/angular-renderer/src/components/primitives/autocomplete/autocomplete.component.ts +338 -0
  64. package/packages/angular-renderer/src/components/primitives/combobox/combobox.component.html +90 -0
  65. package/packages/angular-renderer/src/components/primitives/combobox/combobox.component.scss +189 -0
  66. package/packages/angular-renderer/src/components/primitives/combobox/combobox.component.ts +281 -0
  67. package/packages/angular-renderer/src/components/primitives/date-picker/date-picker.component.html +73 -0
  68. package/packages/angular-renderer/src/components/primitives/date-picker/date-picker.component.scss +77 -0
  69. package/packages/angular-renderer/src/components/primitives/date-picker/date-picker.component.ts +294 -0
  70. package/packages/angular-renderer/src/components/primitives/date-range-picker/date-range-picker.component.html +83 -0
  71. package/packages/angular-renderer/src/components/primitives/date-range-picker/date-range-picker.component.scss +92 -0
  72. package/packages/angular-renderer/src/components/primitives/date-range-picker/date-range-picker.component.ts +357 -0
  73. package/packages/angular-renderer/src/components/primitives/icon-button/icon-button.component.html +1 -1
  74. package/packages/angular-renderer/src/components/primitives/multi-select/multi-select.component.html +150 -0
  75. package/packages/angular-renderer/src/components/primitives/multi-select/multi-select.component.scss +240 -0
  76. package/packages/angular-renderer/src/components/primitives/multi-select/multi-select.component.ts +362 -0
  77. package/packages/angular-renderer/src/components/primitives/select/select.component.html +92 -14
  78. package/packages/angular-renderer/src/components/primitives/select/select.component.scss +188 -13
  79. package/packages/angular-renderer/src/components/primitives/select/select.component.ts +242 -34
  80. package/packages/angular-renderer/src/components/primitives/select/selection-utils.ts +92 -0
  81. package/packages/angular-renderer/src/components/primitives/time-picker/time-picker.component.html +65 -0
  82. package/packages/angular-renderer/src/components/primitives/time-picker/time-picker.component.scss +65 -0
  83. package/packages/angular-renderer/src/components/primitives/time-picker/time-picker.component.ts +229 -0
  84. package/packages/angular-renderer/src/index.ts +6 -0
  85. package/packages/angular-renderer/src/lib/primitives.provider.ts +12 -0
  86. package/packages/cli/CHANGELOG.md +8 -0
  87. package/packages/cli/package.json +2 -2
  88. package/packages/core/CHANGELOG.md +8 -0
  89. package/packages/core/package.json +1 -1
  90. package/packages/design-tokens/CHANGELOG.md +8 -0
  91. package/packages/design-tokens/package.json +1 -1
  92. package/packages/devtools/CHANGELOG.md +14 -0
  93. package/packages/devtools/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  94. package/packages/devtools/package.json +3 -3
  95. package/packages/playground/CHANGELOG.md +8 -0
  96. package/packages/playground/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +1 -1
  97. package/packages/playground/package.json +3 -3
  98. package/dist/packages/playground/browser/main-D2PNGI4C.js +0 -734
@@ -0,0 +1,77 @@
1
+ :host {
2
+ display: block;
3
+ position: relative;
4
+ font-family: var(--origo-typography-body-font-family);
5
+ }
6
+
7
+ .origo-date-picker__input {
8
+ width: 100%;
9
+ padding: var(--origo-spacing-sm) var(--origo-spacing-md);
10
+ border: 1px solid var(--origo-color-neutral-300);
11
+ border-radius: var(--origo-border-radius-md);
12
+ background-color: var(--origo-color-surface-default);
13
+ cursor: pointer;
14
+ }
15
+
16
+ .origo-date-picker__calendar {
17
+ position: absolute;
18
+ top: calc(100% + var(--origo-spacing-xs));
19
+ left: 0;
20
+ z-index: 1000;
21
+ background: var(--origo-color-surface-default);
22
+ border: 1px solid var(--origo-color-neutral-200);
23
+ border-radius: var(--origo-border-radius-md);
24
+ box-shadow: var(--origo-shadow-md);
25
+ padding: var(--origo-spacing-md);
26
+ min-width: 280px;
27
+ }
28
+
29
+ .origo-date-picker__header {
30
+ display: flex;
31
+ justify-content: space-between;
32
+ align-items: center;
33
+ margin-bottom: var(--origo-spacing-md);
34
+ font-weight: bold;
35
+ }
36
+
37
+ .origo-date-picker__weekdays,
38
+ .origo-date-picker__days > div {
39
+ display: grid;
40
+ grid-template-columns: repeat(7, 1fr);
41
+ text-align: center;
42
+ gap: var(--origo-spacing-xs);
43
+ }
44
+
45
+ .origo-date-picker__weekdays {
46
+ font-size: 0.85em;
47
+ color: var(--origo-color-neutral-500);
48
+ margin-bottom: var(--origo-spacing-sm);
49
+ }
50
+
51
+ .origo-date-picker__day {
52
+ padding: var(--origo-spacing-sm) var(--origo-spacing-xs);
53
+ border-radius: var(--origo-border-radius-sm);
54
+ cursor: pointer;
55
+ }
56
+
57
+ .origo-date-picker__day:hover:not(.origo-date-picker__day--disabled) {
58
+ background-color: var(--origo-color-neutral-100);
59
+ }
60
+
61
+ .origo-date-picker__day--disabled {
62
+ opacity: 0.5;
63
+ cursor: not-allowed;
64
+ }
65
+
66
+ .origo-date-picker__day--other-month {
67
+ color: var(--origo-color-neutral-400);
68
+ }
69
+
70
+ .origo-date-picker__day--selected {
71
+ background-color: var(--origo-color-primary-main);
72
+ color: var(--origo-color-surface-default);
73
+ }
74
+
75
+ .origo-date-picker__day--selected:hover:not(.origo-date-picker__day--disabled) {
76
+ background-color: var(--origo-color-primary-dark);
77
+ }
@@ -0,0 +1,294 @@
1
+ import {
2
+ Component,
3
+ ChangeDetectionStrategy,
4
+ ViewEncapsulation,
5
+ input,
6
+ model,
7
+ signal,
8
+ computed,
9
+ inject,
10
+ effect,
11
+ untracked,
12
+ HostListener,
13
+ ElementRef,
14
+ } from '@angular/core';
15
+ import { InteractionContract } from '@origostudio/core';
16
+ import { OrigoAdapter } from '../../../adapters/web/adapter';
17
+ import { WebExperienceAdapterService } from '../../../adapters/web/experience-adapter.service';
18
+
19
+ export interface DatePickerProps {
20
+ format?: string;
21
+ minDate?: string;
22
+ maxDate?: string;
23
+ showTime?: boolean;
24
+ timezone?: string;
25
+ value?: string; // ISO 8601 UTC
26
+ 'aria-label'?: string;
27
+ }
28
+
29
+ interface CalendarDay {
30
+ date: Date;
31
+ isCurrentMonth: boolean;
32
+ isToday: boolean;
33
+ disabled: boolean;
34
+ }
35
+
36
+ @Component({
37
+ selector: 'origo-date-picker',
38
+ standalone: true,
39
+ templateUrl: './date-picker.component.html',
40
+ styleUrls: ['./date-picker.component.scss'],
41
+ changeDetection: ChangeDetectionStrategy.OnPush,
42
+ encapsulation: ViewEncapsulation.ShadowDom,
43
+ })
44
+ export class DatePickerComponent implements OrigoAdapter<DatePickerProps> {
45
+ static readonly contractSchema = {
46
+ format: 'string',
47
+ minDate: 'string',
48
+ maxDate: 'string',
49
+ showTime: 'boolean',
50
+ timezone: 'string',
51
+ value: 'string',
52
+ 'aria-label': 'string',
53
+ permissions: 'array',
54
+ rules: 'array',
55
+ metadata: 'object',
56
+ };
57
+ static readonly strictContract = false;
58
+
59
+ contract = input.required<InteractionContract<DatePickerProps>>();
60
+ value = model<string | null>(null);
61
+
62
+ isOpen = signal<boolean>(false);
63
+ currentViewDate = signal<Date>(
64
+ new Date(Date.UTC(new Date().getUTCFullYear(), new Date().getUTCMonth(), 1))
65
+ );
66
+
67
+ private experienceAdapter = inject(WebExperienceAdapterService);
68
+ private elementRef = inject(ElementRef);
69
+
70
+ weekDays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
71
+
72
+ computedAriaLabel = computed(() => this.contract().props?.['aria-label'] || 'Date Picker');
73
+
74
+ displayValue = computed(() => {
75
+ const val = this.value();
76
+ if (!val) return '';
77
+ const d = this.parseSafeUTC(val);
78
+ if (!d) return '';
79
+ // Format as YYYY-MM-DD using UTC methods
80
+ return `${d.getUTCFullYear()}-${String(d.getUTCMonth() + 1).padStart(2, '0')}-${String(d.getUTCDate()).padStart(2, '0')}`;
81
+ });
82
+
83
+ private parseSafeUTC(isoString: string): Date | null {
84
+ if (!isoString) return null;
85
+ const d = new Date(isoString);
86
+ if (isNaN(d.getTime())) return null;
87
+ return d;
88
+ }
89
+
90
+ constructor() {
91
+ effect(() => {
92
+ const contractVal = this.contract().props?.value;
93
+ untracked(() => {
94
+ if (contractVal === undefined || contractVal === null) {
95
+ this.value.set(null);
96
+ } else {
97
+ this.value.set(String(contractVal));
98
+ const d = this.parseSafeUTC(String(contractVal));
99
+ if (d) {
100
+ this.currentViewDate.set(new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1)));
101
+ }
102
+ }
103
+ });
104
+ });
105
+ }
106
+
107
+ @HostListener('document:mousedown', ['$event'])
108
+ onClickOutside(event: MouseEvent) {
109
+ if (this.isOpen() && !this.elementRef.nativeElement.contains(event.target)) {
110
+ this.isOpen.set(false);
111
+ }
112
+ }
113
+
114
+ @HostListener('document:keydown.escape')
115
+ onEscape() {
116
+ if (this.isOpen()) {
117
+ this.isOpen.set(false);
118
+ }
119
+ }
120
+
121
+ toggleCalendar() {
122
+ this.isOpen.update(v => !v);
123
+ }
124
+
125
+ currentMonthYear = computed(() => {
126
+ const d = this.currentViewDate();
127
+ const months = [
128
+ 'January',
129
+ 'February',
130
+ 'March',
131
+ 'April',
132
+ 'May',
133
+ 'June',
134
+ 'July',
135
+ 'August',
136
+ 'September',
137
+ 'October',
138
+ 'November',
139
+ 'December',
140
+ ];
141
+ return `${months[d.getUTCMonth()]} ${d.getUTCFullYear()}`;
142
+ });
143
+
144
+ private isDateDisabled(date: Date): boolean {
145
+ const minDateStr = this.contract().props?.minDate;
146
+ const maxDateStr = this.contract().props?.maxDate;
147
+
148
+ if (minDateStr) {
149
+ const minD = this.parseSafeUTC(minDateStr);
150
+ if (minD && date < minD) return true;
151
+ }
152
+ if (maxDateStr) {
153
+ const maxD = this.parseSafeUTC(maxDateStr);
154
+ if (maxD && date > maxD) return true;
155
+ }
156
+ return false;
157
+ }
158
+
159
+ calendarGrid = computed(() => {
160
+ const viewDate = this.currentViewDate();
161
+ const year = viewDate.getUTCFullYear();
162
+ const month = viewDate.getUTCMonth();
163
+
164
+ const firstDayOfMonth = new Date(Date.UTC(year, month, 1));
165
+
166
+ const startingDayOfWeek = firstDayOfMonth.getUTCDay();
167
+
168
+ const startDate = new Date(firstDayOfMonth);
169
+ startDate.setUTCDate(startDate.getUTCDate() - startingDayOfWeek);
170
+
171
+ const weeks: CalendarDay[][] = [];
172
+ const currentDay = new Date(startDate);
173
+
174
+ const today = new Date();
175
+
176
+ while (weeks.length < 6) {
177
+ if (currentDay.getUTCDay() === 0) {
178
+ weeks.push([]);
179
+ }
180
+
181
+ const isCurrentMonth = currentDay.getUTCMonth() === month;
182
+
183
+ weeks[weeks.length - 1].push({
184
+ date: new Date(currentDay),
185
+ isCurrentMonth,
186
+ isToday:
187
+ currentDay.getUTCFullYear() === today.getUTCFullYear() &&
188
+ currentDay.getUTCMonth() === today.getUTCMonth() &&
189
+ currentDay.getUTCDate() === today.getUTCDate(),
190
+ disabled: this.isDateDisabled(currentDay),
191
+ });
192
+
193
+ currentDay.setUTCDate(currentDay.getUTCDate() + 1);
194
+ }
195
+
196
+ return weeks;
197
+ });
198
+
199
+ hasSelection(): boolean {
200
+ return !!this.value();
201
+ }
202
+
203
+ isSelected(date: Date): boolean {
204
+ const val = this.value();
205
+ if (!val) return false;
206
+ const selected = this.parseSafeUTC(val);
207
+ if (!selected) return false;
208
+ return (
209
+ selected.getUTCFullYear() === date.getUTCFullYear() &&
210
+ selected.getUTCMonth() === date.getUTCMonth() &&
211
+ selected.getUTCDate() === date.getUTCDate()
212
+ );
213
+ }
214
+
215
+ selectDate(year: number, month: number, day: number) {
216
+ const selectedDate = new Date(Date.UTC(year, month, day, 0, 0, 0, 0));
217
+ if (this.isDateDisabled(selectedDate)) return;
218
+
219
+ const isoString = selectedDate.toISOString();
220
+ this.value.set(isoString);
221
+ this.experienceAdapter.updateState(this.contract().id, 'value', isoString);
222
+ this.isOpen.set(false);
223
+ }
224
+
225
+ prevMonth() {
226
+ const d = this.currentViewDate();
227
+ this.currentViewDate.set(new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() - 1, 1)));
228
+ }
229
+
230
+ nextMonth() {
231
+ const d = this.currentViewDate();
232
+ this.currentViewDate.set(new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 1)));
233
+ }
234
+
235
+ onInputKeyDown(event: KeyboardEvent) {
236
+ if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown') {
237
+ event.preventDefault();
238
+ this.isOpen.set(true);
239
+ }
240
+ }
241
+
242
+ onDayKeyDown(event: KeyboardEvent, date: Date) {
243
+ const d = new Date(date);
244
+ let handled = false;
245
+
246
+ switch (event.key) {
247
+ case 'Enter':
248
+ case ' ':
249
+ this.selectDate(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate());
250
+ handled = true;
251
+ break;
252
+ case 'ArrowRight':
253
+ d.setUTCDate(d.getUTCDate() + 1);
254
+ handled = true;
255
+ break;
256
+ case 'ArrowLeft':
257
+ d.setUTCDate(d.getUTCDate() - 1);
258
+ handled = true;
259
+ break;
260
+ case 'ArrowDown':
261
+ d.setUTCDate(d.getUTCDate() + 7);
262
+ handled = true;
263
+ break;
264
+ case 'ArrowUp':
265
+ d.setUTCDate(d.getUTCDate() - 7);
266
+ handled = true;
267
+ break;
268
+ case 'PageUp':
269
+ d.setUTCMonth(d.getUTCMonth() - 1);
270
+ handled = true;
271
+ break;
272
+ case 'PageDown':
273
+ d.setUTCMonth(d.getUTCMonth() + 1);
274
+ handled = true;
275
+ break;
276
+ }
277
+
278
+ if (handled) {
279
+ event.preventDefault();
280
+ if (
281
+ d.getUTCMonth() !== this.currentViewDate().getUTCMonth() ||
282
+ d.getUTCFullYear() !== this.currentViewDate().getUTCFullYear()
283
+ ) {
284
+ this.currentViewDate.set(new Date(Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), 1)));
285
+ }
286
+ // Focus management for a11y: find the element with matching date in the DOM and focus it
287
+ setTimeout(() => {
288
+ const id = `day-${d.getUTCFullYear()}-${d.getUTCMonth()}-${d.getUTCDate()}`;
289
+ const el = this.elementRef.nativeElement.shadowRoot?.getElementById(id);
290
+ if (el) el.focus();
291
+ }, 0);
292
+ }
293
+ }
294
+ }
@@ -0,0 +1,83 @@
1
+ <div class="origo-date-range-picker-wrapper">
2
+ <div class="origo-date-range-picker__inputs">
3
+ <input
4
+ type="text"
5
+ class="origo-date-range-picker__input"
6
+ readonly
7
+ inputmode="none"
8
+ placeholder="Start Date"
9
+ [value]="displayStartValue()"
10
+ (click)="toggleCalendar()"
11
+ (keydown)="onInputKeyDown($event)"
12
+ aria-haspopup="grid"
13
+ [attr.aria-expanded]="isOpen()"
14
+ />
15
+ <span class="origo-date-range-picker__separator">to</span>
16
+ <input
17
+ type="text"
18
+ class="origo-date-range-picker__input"
19
+ readonly
20
+ inputmode="none"
21
+ placeholder="End Date"
22
+ [value]="displayEndValue()"
23
+ (click)="toggleCalendar()"
24
+ (keydown)="onInputKeyDown($event)"
25
+ aria-haspopup="grid"
26
+ [attr.aria-expanded]="isOpen()"
27
+ />
28
+ </div>
29
+
30
+ @if (isOpen()) {
31
+ <div class="origo-date-range-picker__calendar" role="grid" aria-label="Calendar">
32
+ <div class="origo-date-range-picker__header">
33
+ <button type="button" (click)="prevMonth()" aria-label="Previous Month">&lt;</button>
34
+ <span aria-live="polite">{{ currentMonthYear() }}</span>
35
+ <button type="button" (click)="nextMonth()" aria-label="Next Month">&gt;</button>
36
+ </div>
37
+
38
+ <div role="row" class="origo-date-range-picker__weekdays">
39
+ @for (day of weekDays; track day) {
40
+ <div role="columnheader">{{ day }}</div>
41
+ }
42
+ </div>
43
+
44
+ <div class="origo-date-range-picker__days">
45
+ @for (week of calendarGrid(); track $index) {
46
+ <div role="row">
47
+ @for (day of week; track day.date.toISOString()) {
48
+ <div
49
+ role="gridcell"
50
+ [id]="
51
+ 'day-' +
52
+ day.date.getUTCFullYear() +
53
+ '-' +
54
+ day.date.getUTCMonth() +
55
+ '-' +
56
+ day.date.getUTCDate()
57
+ "
58
+ class="origo-date-range-picker__day"
59
+ [class.origo-date-range-picker__day--other-month]="!day.isCurrentMonth"
60
+ [class.origo-date-range-picker__day--selected]="isSelected(day.date)"
61
+ [class.origo-date-range-picker__day--in-range]="isInRange(day.date)"
62
+ [class.origo-date-range-picker__day--disabled]="day.disabled"
63
+ [attr.aria-selected]="isSelected(day.date)"
64
+ [attr.aria-disabled]="day.disabled"
65
+ [attr.tabindex]="
66
+ isSelected(day.date) || day.isToday
67
+ ? 0
68
+ : day.isCurrentMonth && !day.disabled
69
+ ? 0
70
+ : -1
71
+ "
72
+ (click)="onDayClick(day.date)"
73
+ (keydown)="onDayKeyDown($event, day.date)"
74
+ >
75
+ {{ day.date.getUTCDate() }}
76
+ </div>
77
+ }
78
+ </div>
79
+ }
80
+ </div>
81
+ </div>
82
+ }
83
+ </div>
@@ -0,0 +1,92 @@
1
+ :host {
2
+ display: block;
3
+ position: relative;
4
+ font-family: var(--origo-typography-body-font-family);
5
+ }
6
+
7
+ .origo-date-range-picker__inputs {
8
+ display: flex;
9
+ align-items: center;
10
+ gap: var(--origo-spacing-sm);
11
+ }
12
+
13
+ .origo-date-range-picker__input {
14
+ flex: 1;
15
+ width: 100%;
16
+ padding: var(--origo-spacing-sm) var(--origo-spacing-md);
17
+ border: 1px solid var(--origo-color-neutral-300);
18
+ border-radius: var(--origo-border-radius-md);
19
+ background-color: var(--origo-color-surface-default);
20
+ cursor: pointer;
21
+ }
22
+
23
+ .origo-date-range-picker__separator {
24
+ color: var(--origo-color-neutral-500);
25
+ }
26
+
27
+ .origo-date-range-picker__calendar {
28
+ position: absolute;
29
+ top: calc(100% + var(--origo-spacing-xs));
30
+ left: 0;
31
+ z-index: 1000;
32
+ background: var(--origo-color-surface-default);
33
+ border: 1px solid var(--origo-color-neutral-200);
34
+ border-radius: var(--origo-border-radius-md);
35
+ box-shadow: var(--origo-shadow-md);
36
+ padding: var(--origo-spacing-md);
37
+ min-width: 280px;
38
+ }
39
+
40
+ .origo-date-range-picker__header {
41
+ display: flex;
42
+ justify-content: space-between;
43
+ align-items: center;
44
+ margin-bottom: var(--origo-spacing-md);
45
+ font-weight: bold;
46
+ }
47
+
48
+ .origo-date-range-picker__weekdays,
49
+ .origo-date-range-picker__days > div {
50
+ display: grid;
51
+ grid-template-columns: repeat(7, 1fr);
52
+ text-align: center;
53
+ gap: var(--origo-spacing-xs);
54
+ }
55
+
56
+ .origo-date-range-picker__weekdays {
57
+ font-size: 0.85em;
58
+ color: var(--origo-color-neutral-500);
59
+ margin-bottom: var(--origo-spacing-sm);
60
+ }
61
+
62
+ .origo-date-range-picker__day {
63
+ padding: var(--origo-spacing-sm) var(--origo-spacing-xs);
64
+ border-radius: var(--origo-border-radius-sm);
65
+ cursor: pointer;
66
+ }
67
+
68
+ .origo-date-range-picker__day:hover:not(.origo-date-range-picker__day--disabled) {
69
+ background-color: var(--origo-color-neutral-100);
70
+ }
71
+
72
+ .origo-date-range-picker__day--disabled {
73
+ opacity: 0.5;
74
+ cursor: not-allowed;
75
+ }
76
+
77
+ .origo-date-range-picker__day--other-month {
78
+ color: var(--origo-color-neutral-400);
79
+ }
80
+
81
+ .origo-date-range-picker__day--selected {
82
+ background-color: var(--origo-color-primary-main);
83
+ color: var(--origo-color-surface-default);
84
+ }
85
+
86
+ .origo-date-range-picker__day--in-range:not(.origo-date-range-picker__day--selected) {
87
+ background-color: var(--origo-color-primary-light);
88
+ }
89
+
90
+ .origo-date-range-picker__day--selected:hover:not(.origo-date-range-picker__day--disabled) {
91
+ background-color: var(--origo-color-primary-dark);
92
+ }