@happyvertical/smrt-ui 0.51.39 → 0.52.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 (212) hide show
  1. package/AGENTS.md +14 -2
  2. package/README.md +257 -5
  3. package/dist/actions/__tests__/swipe-dismiss.test.js +69 -0
  4. package/dist/actions/swipe-dismiss.d.ts +42 -0
  5. package/dist/actions/swipe-dismiss.d.ts.map +1 -0
  6. package/dist/actions/swipe-dismiss.js +69 -0
  7. package/dist/components/calendar/Calendar.svelte +5 -0
  8. package/dist/components/calendar/Calendar.svelte.d.ts.map +1 -1
  9. package/dist/components/calendar/CalendarView.svelte +1250 -0
  10. package/dist/components/calendar/CalendarView.svelte.d.ts +66 -0
  11. package/dist/components/calendar/CalendarView.svelte.d.ts.map +1 -0
  12. package/dist/components/calendar/DayView.svelte +5 -0
  13. package/dist/components/calendar/DayView.svelte.d.ts.map +1 -1
  14. package/dist/components/calendar/__tests__/CalendarView.test.js +226 -0
  15. package/dist/components/calendar/__tests__/calendar-model.test.js +138 -0
  16. package/dist/components/calendar/calendar-model.d.ts +178 -0
  17. package/dist/components/calendar/calendar-model.d.ts.map +1 -0
  18. package/dist/components/calendar/calendar-model.js +362 -0
  19. package/dist/components/calendar/index.d.ts +12 -1
  20. package/dist/components/calendar/index.d.ts.map +1 -1
  21. package/dist/components/calendar/index.js +11 -1
  22. package/dist/components/data/CollectionList.svelte +23 -5
  23. package/dist/components/data/CollectionList.svelte.d.ts +8 -2
  24. package/dist/components/data/CollectionList.svelte.d.ts.map +1 -1
  25. package/dist/components/data/DataTable.svelte +118 -40
  26. package/dist/components/data/DataTable.svelte.d.ts.map +1 -1
  27. package/dist/components/data/DataTableController.d.ts +4 -0
  28. package/dist/components/data/DataTableController.d.ts.map +1 -1
  29. package/dist/components/data/DataTableController.js +11 -4
  30. package/dist/components/data/ListSortSelect.svelte +121 -0
  31. package/dist/components/data/ListSortSelect.svelte.d.ts +22 -0
  32. package/dist/components/data/ListSortSelect.svelte.d.ts.map +1 -0
  33. package/dist/components/data/SortableHeader.svelte +169 -0
  34. package/dist/components/data/SortableHeader.svelte.d.ts +30 -0
  35. package/dist/components/data/SortableHeader.svelte.d.ts.map +1 -0
  36. package/dist/components/data/__tests__/CollectionList.test.js +37 -0
  37. package/dist/components/data/__tests__/DataTable.test.js +76 -0
  38. package/dist/components/data/__tests__/DataTableController.test.js +35 -0
  39. package/dist/components/data/__tests__/SortableHeader.test.js +101 -0
  40. package/dist/components/data/__tests__/link-step-surface.test.js +172 -0
  41. package/dist/components/data/__tests__/list-sort-state.svelte.test.js +71 -0
  42. package/dist/components/data/__tests__/list-sort.test.js +91 -0
  43. package/dist/components/data/__tests__/surface-navigation.test.js +121 -0
  44. package/dist/components/data/data-surface.d.ts +1 -0
  45. package/dist/components/data/data-surface.d.ts.map +1 -1
  46. package/dist/components/data/data-surface.js +1 -0
  47. package/dist/components/data/index.d.ts +6 -0
  48. package/dist/components/data/index.d.ts.map +1 -1
  49. package/dist/components/data/index.js +6 -0
  50. package/dist/components/data/link-surface.d.ts +79 -0
  51. package/dist/components/data/link-surface.d.ts.map +1 -0
  52. package/dist/components/data/link-surface.js +155 -0
  53. package/dist/components/data/list-sort-state.svelte.d.ts +39 -0
  54. package/dist/components/data/list-sort-state.svelte.d.ts.map +1 -0
  55. package/dist/components/data/list-sort-state.svelte.js +47 -0
  56. package/dist/components/data/list-sort.d.ts +94 -0
  57. package/dist/components/data/list-sort.d.ts.map +1 -0
  58. package/dist/components/data/list-sort.js +182 -0
  59. package/dist/components/data/step-surface.d.ts +73 -0
  60. package/dist/components/data/step-surface.d.ts.map +1 -0
  61. package/dist/components/data/step-surface.js +177 -0
  62. package/dist/components/data/surface-navigation.d.ts +49 -0
  63. package/dist/components/data/surface-navigation.d.ts.map +1 -0
  64. package/dist/components/data/surface-navigation.js +100 -0
  65. package/dist/components/data/types.d.ts +19 -0
  66. package/dist/components/data/types.d.ts.map +1 -1
  67. package/dist/components/feedback/PhoneSheet.svelte +224 -0
  68. package/dist/components/feedback/PhoneSheet.svelte.d.ts +35 -0
  69. package/dist/components/feedback/PhoneSheet.svelte.d.ts.map +1 -0
  70. package/dist/components/feedback/WorkingStrip.svelte +426 -0
  71. package/dist/components/feedback/WorkingStrip.svelte.d.ts +37 -0
  72. package/dist/components/feedback/WorkingStrip.svelte.d.ts.map +1 -0
  73. package/dist/components/feedback/__tests__/PhoneSheet.test.js +101 -0
  74. package/dist/components/feedback/__tests__/WorkingStrip.test.js +172 -0
  75. package/dist/components/feedback/index.d.ts +4 -0
  76. package/dist/components/feedback/index.d.ts.map +1 -1
  77. package/dist/components/feedback/index.js +5 -0
  78. package/dist/components/feedback/working-status.d.ts +34 -0
  79. package/dist/components/feedback/working-status.d.ts.map +1 -0
  80. package/dist/components/feedback/working-status.js +5 -0
  81. package/dist/components/forms/Checkbox.svelte +26 -2
  82. package/dist/components/forms/Combobox.svelte +68 -12
  83. package/dist/components/forms/Combobox.svelte.d.ts +6 -0
  84. package/dist/components/forms/Combobox.svelte.d.ts.map +1 -1
  85. package/dist/components/forms/DictationButton.svelte +128 -0
  86. package/dist/components/forms/DictationButton.svelte.d.ts +19 -0
  87. package/dist/components/forms/DictationButton.svelte.d.ts.map +1 -0
  88. package/dist/components/forms/DictationStatus.svelte +164 -0
  89. package/dist/components/forms/DictationStatus.svelte.d.ts +11 -0
  90. package/dist/components/forms/DictationStatus.svelte.d.ts.map +1 -0
  91. package/dist/components/forms/Fieldset.svelte +5 -1
  92. package/dist/components/forms/Fieldset.svelte.d.ts +2 -0
  93. package/dist/components/forms/Fieldset.svelte.d.ts.map +1 -1
  94. package/dist/components/forms/FormActionBar.svelte +84 -0
  95. package/dist/components/forms/FormActionBar.svelte.d.ts +23 -0
  96. package/dist/components/forms/FormActionBar.svelte.d.ts.map +1 -0
  97. package/dist/components/forms/Input.svelte +9 -0
  98. package/dist/components/forms/Radio.svelte +15 -4
  99. package/dist/components/forms/SearchInput.svelte +207 -0
  100. package/dist/components/forms/SearchInput.svelte.d.ts +22 -0
  101. package/dist/components/forms/SearchInput.svelte.d.ts.map +1 -0
  102. package/dist/components/forms/Select.svelte +9 -0
  103. package/dist/components/forms/StagedControlReview.svelte +21 -12
  104. package/dist/components/forms/StagedControlReview.svelte.d.ts.map +1 -1
  105. package/dist/components/forms/Switch.svelte +11 -5
  106. package/dist/components/forms/TagsInput.svelte +8 -1
  107. package/dist/components/forms/Textarea.svelte +8 -0
  108. package/dist/components/forms/__tests__/Combobox.test.js +87 -0
  109. package/dist/components/forms/__tests__/ControlHitArea.test.js +73 -0
  110. package/dist/components/forms/__tests__/DictationButton.test.js +176 -0
  111. package/dist/components/forms/__tests__/Fieldset.test.js +37 -0
  112. package/dist/components/forms/__tests__/FormActionBar.test.js +22 -0
  113. package/dist/components/forms/__tests__/SearchInput.test.js +92 -0
  114. package/dist/components/forms/__tests__/StagedControlReview.test.js +37 -3
  115. package/dist/components/forms/__tests__/combobox-labels.fixture.svelte +19 -0
  116. package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts +11 -0
  117. package/dist/components/forms/__tests__/combobox-labels.fixture.svelte.d.ts.map +1 -0
  118. package/dist/components/forms/__tests__/composite-registration.fixture.svelte +29 -0
  119. package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts +8 -0
  120. package/dist/components/forms/__tests__/composite-registration.fixture.svelte.d.ts.map +1 -0
  121. package/dist/components/forms/__tests__/control-interaction.test.js +19 -1
  122. package/dist/components/forms/__tests__/control-proposals.test.js +63 -0
  123. package/dist/components/forms/__tests__/dictation-recording.test.js +582 -0
  124. package/dist/components/forms/__tests__/dictation.test.js +486 -0
  125. package/dist/components/forms/__tests__/long-press.test.js +175 -0
  126. package/dist/components/forms/__tests__/place-picker.fixture.svelte +33 -0
  127. package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts +12 -0
  128. package/dist/components/forms/__tests__/place-picker.fixture.svelte.d.ts.map +1 -0
  129. package/dist/components/forms/audio-capture.d.ts +69 -0
  130. package/dist/components/forms/audio-capture.d.ts.map +1 -0
  131. package/dist/components/forms/audio-capture.js +193 -0
  132. package/dist/components/forms/control-interaction.d.ts +6 -0
  133. package/dist/components/forms/control-interaction.d.ts.map +1 -1
  134. package/dist/components/forms/control-interaction.js +12 -1
  135. package/dist/components/forms/control-proposals.d.ts +55 -0
  136. package/dist/components/forms/control-proposals.d.ts.map +1 -0
  137. package/dist/components/forms/control-proposals.js +188 -0
  138. package/dist/components/forms/dictation-transcribe.d.ts +36 -0
  139. package/dist/components/forms/dictation-transcribe.d.ts.map +1 -0
  140. package/dist/components/forms/dictation-transcribe.js +65 -0
  141. package/dist/components/forms/dictation.svelte.d.ts +200 -0
  142. package/dist/components/forms/dictation.svelte.d.ts.map +1 -0
  143. package/dist/components/forms/dictation.svelte.js +686 -0
  144. package/dist/components/forms/index.d.ts +14 -1
  145. package/dist/components/forms/index.d.ts.map +1 -1
  146. package/dist/components/forms/index.js +14 -1
  147. package/dist/components/forms/insert-text.d.ts +12 -0
  148. package/dist/components/forms/insert-text.d.ts.map +1 -0
  149. package/dist/components/forms/insert-text.js +38 -0
  150. package/dist/components/forms/long-press.d.ts +88 -0
  151. package/dist/components/forms/long-press.d.ts.map +1 -0
  152. package/dist/components/forms/long-press.js +213 -0
  153. package/dist/components/forms/ready-beep.d.ts +24 -0
  154. package/dist/components/forms/ready-beep.d.ts.map +1 -0
  155. package/dist/components/forms/ready-beep.js +82 -0
  156. package/dist/components/layout/PageHeader.svelte +151 -17
  157. package/dist/components/layout/PageHeader.svelte.d.ts +47 -7
  158. package/dist/components/layout/PageHeader.svelte.d.ts.map +1 -1
  159. package/dist/components/layout/__tests__/PageHeader.test.js +87 -1
  160. package/dist/components/layout/index.d.ts +1 -0
  161. package/dist/components/layout/index.d.ts.map +1 -1
  162. package/dist/components/layout/index.js +1 -0
  163. package/dist/components/layout/page-header-context.d.ts +25 -0
  164. package/dist/components/layout/page-header-context.d.ts.map +1 -0
  165. package/dist/components/layout/page-header-context.js +16 -0
  166. package/dist/components/nav/Tabs.svelte +241 -0
  167. package/dist/components/nav/Tabs.svelte.d.ts +15 -0
  168. package/dist/components/nav/Tabs.svelte.d.ts.map +1 -1
  169. package/dist/components/nav/__tests__/LinkTabs.test.js +117 -0
  170. package/dist/components/nav/index.d.ts +1 -0
  171. package/dist/components/nav/index.d.ts.map +1 -1
  172. package/dist/components/nav/index.js +1 -0
  173. package/dist/components/nav/tabs-overflow.d.ts +12 -0
  174. package/dist/components/nav/tabs-overflow.d.ts.map +1 -0
  175. package/dist/components/nav/tabs-overflow.js +17 -0
  176. package/dist/components/nav/types.d.ts +8 -0
  177. package/dist/components/nav/types.d.ts.map +1 -1
  178. package/dist/components/ui/Button.svelte +7 -0
  179. package/dist/components/ui/Card.svelte +14 -5
  180. package/dist/components/ui/Dropdown.svelte +55 -1
  181. package/dist/components/ui/Dropdown.svelte.d.ts +8 -0
  182. package/dist/components/ui/Dropdown.svelte.d.ts.map +1 -1
  183. package/dist/components/ui/IconToggle.svelte +139 -0
  184. package/dist/components/ui/IconToggle.svelte.d.ts +32 -0
  185. package/dist/components/ui/IconToggle.svelte.d.ts.map +1 -0
  186. package/dist/components/ui/IconToggleGroup.svelte +56 -0
  187. package/dist/components/ui/IconToggleGroup.svelte.d.ts +21 -0
  188. package/dist/components/ui/IconToggleGroup.svelte.d.ts.map +1 -0
  189. package/dist/components/ui/Pagination.svelte +1 -1
  190. package/dist/components/ui/Popover.svelte +17 -1
  191. package/dist/components/ui/Popover.svelte.d.ts +8 -0
  192. package/dist/components/ui/Popover.svelte.d.ts.map +1 -1
  193. package/dist/components/ui/__tests__/IconToggle.test.js +59 -0
  194. package/dist/components/ui/__tests__/IconToggleGroup.test.js +30 -0
  195. package/dist/components/ui/__tests__/Popover.test.js +44 -0
  196. package/dist/components/ui/__tests__/dropdown-popover-icon.test.js +125 -0
  197. package/dist/components/ui/__tests__/phone-touch-targets.test.js +39 -0
  198. package/dist/components/ui/index.d.ts +2 -0
  199. package/dist/components/ui/index.d.ts.map +1 -1
  200. package/dist/components/ui/index.js +2 -0
  201. package/dist/i18n/strings.ui.d.ts +41 -0
  202. package/dist/i18n/strings.ui.d.ts.map +1 -1
  203. package/dist/i18n/strings.ui.js +46 -0
  204. package/dist/svelte/__tests__/playground.test.js +1 -0
  205. package/dist/svelte/playground/CalendarPreview.svelte +140 -0
  206. package/dist/svelte/playground/CalendarPreview.svelte.d.ts +4 -0
  207. package/dist/svelte/playground/CalendarPreview.svelte.d.ts.map +1 -0
  208. package/dist/svelte/playground.d.ts.map +1 -1
  209. package/dist/svelte/playground.js +10 -0
  210. package/dist/types-generic.d.ts +2 -0
  211. package/dist/types-generic.d.ts.map +1 -1
  212. package/package.json +3 -3
@@ -0,0 +1,362 @@
1
+ /**
2
+ * Pure, Svelte-free date model for `CalendarView`.
3
+ *
4
+ * Every calendar day is a `YYYY-MM-DD` key in the view's IANA time zone.
5
+ * Instants are projected into that zone through `Intl` exactly once; all
6
+ * further math (grids, spans, lanes) runs on keys, so the browser's own zone
7
+ * never leaks into what a day contains.
8
+ */
9
+ const DATE_KEY = /^(\d{4})-(\d{2})-(\d{2})$/;
10
+ const DAY_MS = 86_400_000;
11
+ const TONES = [
12
+ 'primary',
13
+ 'tertiary',
14
+ 'secondary',
15
+ 'success',
16
+ 'warning',
17
+ 'error',
18
+ ];
19
+ const partsFormatters = new Map();
20
+ function partsFormatter(timeZone) {
21
+ let formatter = partsFormatters.get(timeZone);
22
+ if (!formatter) {
23
+ formatter = new Intl.DateTimeFormat('en-US', {
24
+ timeZone,
25
+ hourCycle: 'h23',
26
+ year: 'numeric',
27
+ month: '2-digit',
28
+ day: '2-digit',
29
+ hour: '2-digit',
30
+ minute: '2-digit',
31
+ second: '2-digit',
32
+ });
33
+ partsFormatters.set(timeZone, formatter);
34
+ }
35
+ return formatter;
36
+ }
37
+ function zonedParts(instant, timeZone) {
38
+ const parts = partsFormatter(timeZone).formatToParts(instant);
39
+ const get = (type) => parts.find((part) => part.type === type)?.value ?? '00';
40
+ return {
41
+ key: `${get('year').padStart(4, '0')}-${get('month')}-${get('day')}`,
42
+ midnight: Number(get('hour')) % 24 === 0 &&
43
+ get('minute') === '00' &&
44
+ get('second') === '00',
45
+ };
46
+ }
47
+ /** The browser's resolved IANA zone (`UTC` when unavailable). */
48
+ export function defaultTimeZone() {
49
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC';
50
+ }
51
+ /** Whether `timeZone` is an IANA zone this runtime's `Intl` accepts. */
52
+ export function isValidTimeZone(timeZone) {
53
+ if (typeof timeZone !== 'string' || timeZone === '')
54
+ return false;
55
+ try {
56
+ new Intl.DateTimeFormat('en-US', { timeZone });
57
+ return true;
58
+ }
59
+ catch {
60
+ return false;
61
+ }
62
+ }
63
+ /**
64
+ * `timeZone` when valid, otherwise the runtime default. `onInvalid` hears
65
+ * about a rejected non-empty zone (a typo, a zone this runtime lacks), so a
66
+ * view can warn instead of throwing from its render.
67
+ */
68
+ export function resolveTimeZone(timeZone, onInvalid) {
69
+ if (!timeZone)
70
+ return defaultTimeZone();
71
+ if (isValidTimeZone(timeZone))
72
+ return timeZone;
73
+ onInvalid?.(timeZone);
74
+ return defaultTimeZone();
75
+ }
76
+ /**
77
+ * The calendar day of an instant in a time zone.
78
+ *
79
+ * @param instant - Instant to project
80
+ * @param timeZone - IANA time zone
81
+ * @returns `YYYY-MM-DD`
82
+ */
83
+ export function dateKeyInZone(instant, timeZone) {
84
+ return zonedParts(instant, timeZone).key;
85
+ }
86
+ /** Today's `YYYY-MM-DD` in a time zone. */
87
+ export function todayKey(timeZone, now = new Date()) {
88
+ return dateKeyInZone(now, timeZone);
89
+ }
90
+ /** Whether a string is a `YYYY-MM-DD` date key. */
91
+ export function isDateKey(value) {
92
+ return typeof value === 'string' && DATE_KEY.test(value);
93
+ }
94
+ function keyToDayNumber(key) {
95
+ const match = DATE_KEY.exec(key);
96
+ if (!match)
97
+ throw new RangeError(`Invalid date key: ${key}`);
98
+ return Math.floor(Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3])) / DAY_MS);
99
+ }
100
+ function dayNumberToKey(dayNumber) {
101
+ const date = new Date(dayNumber * DAY_MS);
102
+ return formatKey(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate());
103
+ }
104
+ /** Build a `YYYY-MM-DD` key (month 1-12). */
105
+ export function formatKey(year, month, day) {
106
+ return `${String(year).padStart(4, '0')}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
107
+ }
108
+ /** Split a key into numbers (month 1-12). */
109
+ export function parseKey(key) {
110
+ const match = DATE_KEY.exec(key);
111
+ if (!match)
112
+ throw new RangeError(`Invalid date key: ${key}`);
113
+ return {
114
+ year: Number(match[1]),
115
+ month: Number(match[2]),
116
+ day: Number(match[3]),
117
+ };
118
+ }
119
+ /** Add days to a key. */
120
+ export function addDays(key, days) {
121
+ return dayNumberToKey(keyToDayNumber(key) + days);
122
+ }
123
+ /** Day of week of a key (0 = Sunday). */
124
+ export function weekdayOfKey(key) {
125
+ return (((keyToDayNumber(key) + 4) % 7) + 7) % 7;
126
+ }
127
+ /** The month a key falls in. */
128
+ export function monthOfKey(key) {
129
+ const { year, month } = parseKey(key);
130
+ return { year, month };
131
+ }
132
+ /** Shift a month by `delta` months. */
133
+ export function shiftMonth(value, delta) {
134
+ const index = value.year * 12 + (value.month - 1) + delta;
135
+ return { year: Math.floor(index / 12), month: (index % 12) + 1 };
136
+ }
137
+ /** Days in a month. */
138
+ export function daysInMonth(value) {
139
+ return new Date(Date.UTC(value.year, value.month, 0)).getUTCDate();
140
+ }
141
+ /** Move a key by whole months, clamping the day (Jan 31 + 1 month = Feb 28). */
142
+ export function addMonthsToKey(key, delta) {
143
+ const { day } = parseKey(key);
144
+ const target = shiftMonth(monthOfKey(key), delta);
145
+ return formatKey(target.year, target.month, Math.min(day, daysInMonth(target)));
146
+ }
147
+ /** Every key of a month, in order. */
148
+ export function monthKeys(value) {
149
+ const length = daysInMonth(value);
150
+ return Array.from({ length }, (_, index) => formatKey(value.year, value.month, index + 1));
151
+ }
152
+ /**
153
+ * Full weeks covering a month.
154
+ *
155
+ * @param value - Month to cover
156
+ * @param weekStartsOn - First column (0 = Sunday, 1 = Monday, …)
157
+ * @returns Week rows of seven keys each
158
+ */
159
+ export function monthWeeks(value, weekStartsOn) {
160
+ const first = formatKey(value.year, value.month, 1);
161
+ const last = formatKey(value.year, value.month, daysInMonth(value));
162
+ let cursor = addDays(first, -((weekdayOfKey(first) - weekStartsOn + 7) % 7));
163
+ const weeks = [];
164
+ while (cursor <= last) {
165
+ const week = [];
166
+ for (let index = 0; index < 7; index++) {
167
+ week.push(cursor);
168
+ cursor = addDays(cursor, 1);
169
+ }
170
+ weeks.push(week);
171
+ }
172
+ return weeks;
173
+ }
174
+ /**
175
+ * First day of the week for a locale (0 = Sunday), from `Intl.Locale` week
176
+ * info where the runtime provides it; Sunday otherwise.
177
+ */
178
+ export function defaultWeekStart(locale) {
179
+ try {
180
+ const intlLocale = new Intl.Locale(locale || 'en-US');
181
+ const info = intlLocale.getWeekInfo?.() ?? intlLocale.weekInfo;
182
+ if (info?.firstDay)
183
+ return info.firstDay % 7;
184
+ }
185
+ catch {
186
+ // An invalid locale tag falls through to the Sunday default below.
187
+ }
188
+ return 0;
189
+ }
190
+ /** Tone for an item: explicit tone, else a stable tone for its group. */
191
+ export function toneFor(item) {
192
+ if (item.tone)
193
+ return item.tone;
194
+ if (!item.group)
195
+ return 'primary';
196
+ let hash = 0;
197
+ for (const char of item.group)
198
+ hash = (hash * 31 + char.charCodeAt(0)) >>> 0;
199
+ return TONES[hash % TONES.length];
200
+ }
201
+ function toInstant(value) {
202
+ return value instanceof Date ? value : new Date(value);
203
+ }
204
+ /**
205
+ * Project items onto day keys. Items with unparseable dates are dropped and
206
+ * reported through `onInvalid`.
207
+ *
208
+ * @param items - Calendar items
209
+ * @param timeZone - IANA zone the calendar shows
210
+ * @param onInvalid - Called for each dropped item
211
+ * @returns Entries sorted by start
212
+ */
213
+ export function toEntries(items, timeZone, onInvalid) {
214
+ const entries = [];
215
+ for (const item of items) {
216
+ const dateOnlyStart = isDateKey(item.start);
217
+ const allDay = item.allDay ?? dateOnlyStart;
218
+ let startKey;
219
+ let startMs;
220
+ if (dateOnlyStart) {
221
+ startKey = item.start;
222
+ startMs = keyToDayNumber(startKey) * DAY_MS;
223
+ }
224
+ else {
225
+ const start = toInstant(item.start);
226
+ if (Number.isNaN(start.getTime())) {
227
+ onInvalid?.(item);
228
+ continue;
229
+ }
230
+ startKey = dateKeyInZone(start, timeZone);
231
+ startMs = allDay ? keyToDayNumber(startKey) * DAY_MS : start.getTime();
232
+ }
233
+ let endKey = startKey;
234
+ if (item.end !== undefined && item.end !== null && item.end !== '') {
235
+ if (isDateKey(item.end)) {
236
+ endKey = item.end;
237
+ }
238
+ else {
239
+ const end = toInstant(item.end);
240
+ if (Number.isNaN(end.getTime())) {
241
+ onInvalid?.(item);
242
+ continue;
243
+ }
244
+ if (allDay) {
245
+ const parts = zonedParts(end, timeZone);
246
+ endKey =
247
+ parts.midnight && parts.key > startKey
248
+ ? addDays(parts.key, -1)
249
+ : parts.key;
250
+ }
251
+ else if (end.getTime() > startMs) {
252
+ endKey = dateKeyInZone(new Date(end.getTime() - 1), timeZone);
253
+ }
254
+ }
255
+ }
256
+ if (endKey < startKey)
257
+ endKey = startKey;
258
+ entries.push({
259
+ item,
260
+ startKey,
261
+ endKey,
262
+ allDay,
263
+ band: allDay || endKey !== startKey,
264
+ startMs,
265
+ });
266
+ }
267
+ return entries.sort(compareEntries);
268
+ }
269
+ function compareEntries(a, b) {
270
+ if (a.band !== b.band)
271
+ return a.band ? -1 : 1;
272
+ if (a.startKey !== b.startKey)
273
+ return a.startKey < b.startKey ? -1 : 1;
274
+ if (a.band && a.endKey !== b.endKey)
275
+ return a.endKey > b.endKey ? -1 : 1;
276
+ if (a.startMs !== b.startMs)
277
+ return a.startMs - b.startMs;
278
+ return a.item.title.localeCompare(b.item.title);
279
+ }
280
+ /** Every entry on a day: bands covering it first, then timed items by start. */
281
+ export function entriesOnDay(entries, key) {
282
+ return entries.filter((entry) => entry.band
283
+ ? entry.startKey <= key && entry.endKey >= key
284
+ : entry.startKey === key);
285
+ }
286
+ /**
287
+ * Lay out a month grid: bands get lanes per week, each day shows what fits in
288
+ * `maxPerDay` rows, and the rest is counted for a "+N more" control.
289
+ *
290
+ * @param value - Visible month
291
+ * @param entries - Entries from {@link toEntries}
292
+ * @param options - First weekday and per-day row budget
293
+ * @returns Week rows
294
+ */
295
+ export function layoutMonth(value, entries, options) {
296
+ const maxPerDay = Math.max(1, Math.floor(options.maxPerDay));
297
+ const bands = entries.filter((entry) => entry.band);
298
+ const timed = entries.filter((entry) => !entry.band);
299
+ return monthWeeks(value, options.weekStartsOn).map((keys) => {
300
+ const weekStart = keys[0];
301
+ const weekEnd = keys[6];
302
+ const hidden = new Map();
303
+ const laneEnds = [];
304
+ const segments = [];
305
+ const inWeek = bands
306
+ .filter((entry) => entry.startKey <= weekEnd && entry.endKey >= weekStart)
307
+ .map((entry) => {
308
+ const from = entry.startKey < weekStart ? weekStart : entry.startKey;
309
+ const to = entry.endKey > weekEnd ? weekEnd : entry.endKey;
310
+ const column = keys.indexOf(from);
311
+ return { entry, column, span: keys.indexOf(to) - column + 1 };
312
+ })
313
+ .sort((a, b) => a.column - b.column ||
314
+ b.span - a.span ||
315
+ compareEntries(a.entry, b.entry));
316
+ const assigned = inWeek.map((segment) => {
317
+ let lane = laneEnds.findIndex((end) => end < segment.column);
318
+ if (lane === -1) {
319
+ lane = laneEnds.length;
320
+ laneEnds.push(-1);
321
+ }
322
+ laneEnds[lane] = segment.column + segment.span - 1;
323
+ return { ...segment, lane };
324
+ });
325
+ // When bands overflow, keep the last row free for "+N more".
326
+ const lanes = laneEnds.length > maxPerDay ? maxPerDay - 1 : laneEnds.length;
327
+ for (const segment of assigned) {
328
+ if (segment.lane < lanes) {
329
+ segments.push({
330
+ ...segment,
331
+ continuesBefore: segment.entry.startKey < weekStart,
332
+ continuesAfter: segment.entry.endKey > weekEnd,
333
+ });
334
+ }
335
+ else {
336
+ for (let offset = 0; offset < segment.span; offset++) {
337
+ const key = keys[segment.column + offset];
338
+ hidden.set(key, (hidden.get(key) ?? 0) + 1);
339
+ }
340
+ }
341
+ }
342
+ const rows = maxPerDay - lanes;
343
+ const days = keys.map((key) => {
344
+ const dayTimed = timed.filter((entry) => entry.startKey === key);
345
+ const hiddenBands = hidden.get(key) ?? 0;
346
+ const fits = hiddenBands === 0 && dayTimed.length <= rows;
347
+ const visible = fits
348
+ ? dayTimed
349
+ : dayTimed.slice(0, Math.max(0, rows - 1));
350
+ const parts = parseKey(key);
351
+ return {
352
+ key,
353
+ day: parts.day,
354
+ inMonth: parts.month === value.month && parts.year === value.year,
355
+ visible,
356
+ hiddenCount: hiddenBands + dayTimed.length - visible.length,
357
+ all: entriesOnDay(entries, key),
358
+ };
359
+ });
360
+ return { days, bands: segments, lanes };
361
+ });
362
+ }
@@ -1,6 +1,17 @@
1
1
  /**
2
- * Calendar components - Month and day views with event support
2
+ * Calendar components.
3
+ *
4
+ * `CalendarView` is the generic, time-zone-aware month grid + phone agenda.
5
+ * `Calendar` and `DayView` are deprecated: they compute days in the browser
6
+ * zone, print English-only names, hard-code game/meeting/event item types
7
+ * and `/events/y/m/d` links. Migrate to `CalendarView` (see the package
8
+ * README, "Calendar").
3
9
  */
10
+ /** @deprecated Use `CalendarView`; see the smrt-ui README "Calendar" migration note. */
4
11
  export { default as Calendar } from './Calendar.svelte';
12
+ export { default as CalendarView } from './CalendarView.svelte';
13
+ export type { CalendarBandSegment, CalendarDayCell, CalendarEntry, CalendarItem, CalendarMode, CalendarMonth, CalendarTone, CalendarWeek, } from './calendar-model.js';
14
+ export { addDays, addMonthsToKey, dateKeyInZone, defaultTimeZone, defaultWeekStart, entriesOnDay, formatKey, isDateKey, layoutMonth, monthKeys, monthOfKey, monthWeeks, parseKey, shiftMonth, todayKey, toEntries, toneFor, weekdayOfKey, } from './calendar-model.js';
15
+ /** @deprecated Use `CalendarView` (agenda mode or its day panel); see the smrt-ui README. */
5
16
  export { default as DayView } from './DayView.svelte';
6
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/calendar/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/calendar/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,wFAAwF;AACxF,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAChE,YAAY,EACV,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,YAAY,GACb,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,OAAO,EACP,cAAc,EACd,aAAa,EACb,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,UAAU,EACV,UAAU,EACV,QAAQ,EACR,UAAU,EACV,QAAQ,EACR,SAAS,EACT,OAAO,EACP,YAAY,GACb,MAAM,qBAAqB,CAAC;AAC7B,6FAA6F;AAC7F,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,kBAAkB,CAAC"}
@@ -1,5 +1,15 @@
1
1
  /**
2
- * Calendar components - Month and day views with event support
2
+ * Calendar components.
3
+ *
4
+ * `CalendarView` is the generic, time-zone-aware month grid + phone agenda.
5
+ * `Calendar` and `DayView` are deprecated: they compute days in the browser
6
+ * zone, print English-only names, hard-code game/meeting/event item types
7
+ * and `/events/y/m/d` links. Migrate to `CalendarView` (see the package
8
+ * README, "Calendar").
3
9
  */
10
+ /** @deprecated Use `CalendarView`; see the smrt-ui README "Calendar" migration note. */
4
11
  export { default as Calendar } from './Calendar.svelte';
12
+ export { default as CalendarView } from './CalendarView.svelte';
13
+ export { addDays, addMonthsToKey, dateKeyInZone, defaultTimeZone, defaultWeekStart, entriesOnDay, formatKey, isDateKey, layoutMonth, monthKeys, monthOfKey, monthWeeks, parseKey, shiftMonth, todayKey, toEntries, toneFor, weekdayOfKey, } from './calendar-model.js';
14
+ /** @deprecated Use `CalendarView` (agenda mode or its day panel); see the smrt-ui README. */
5
15
  export { default as DayView } from './DayView.svelte';
@@ -10,8 +10,14 @@ export interface Props<T> {
10
10
  title?: keyof T | ((item: T) => string);
11
11
  /** Field name or function to extract the description text for each item. */
12
12
  description?: keyof T | ((item: T) => string | undefined);
13
- /** Display layout: list (single column) or grid (multiple columns). */
14
- layout?: 'list' | 'grid';
13
+ /**
14
+ * Display layout: list (single column of cards), divided (a flat single
15
+ * column: no card surface, rows separated by a hairline, a selected row shown
16
+ * by its checkbox), grid (multiple columns of cards), or gallery
17
+ * (picture-first tiles: the `item` snippet fills the tile, the selection
18
+ * checkbox and `actions` float over its top corners).
19
+ */
20
+ layout?: 'list' | 'divided' | 'grid' | 'gallery';
15
21
  /** Whether to show checkboxes for selecting multiple items. */
16
22
  selectable?: boolean;
17
23
  /** Set of currently selected item keys (bindable). */
@@ -85,7 +91,7 @@ function toggle(key: string | number) {
85
91
  {@const isSelected = selected.has(key)}
86
92
  {@const itemTitle = textOf(entry, title) ?? `Item ${index + 1}`}
87
93
  <li class:selected={isSelected}>
88
- {#if selectable}<input type="checkbox" checked={isSelected} aria-label={`Select ${itemTitle}`} onchange={() => toggle(key)} />{/if}
94
+ {#if selectable}<label class="select"><input type="checkbox" checked={isSelected} aria-label={`Select ${itemTitle}`} onchange={() => toggle(key)} /></label>{/if}
89
95
  {#if onitemclick}
90
96
  <button type="button" class="main" onclick={() => onitemclick?.(entry, index)}>
91
97
  {#if item}{@render item({ item: entry, index, selected: isSelected })}{:else}<strong>{itemTitle}</strong>{#if description}<span>{textOf(entry, description)}</span>{/if}{/if}
@@ -104,15 +110,27 @@ function toggle(key: string | number) {
104
110
  <style>
105
111
  .collection { display: grid; gap: var(--smrt-spacing-2); margin: 0; padding: 0; list-style: none; }
106
112
  .collection--grid { grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr)); }
107
- li { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--smrt-spacing-3); min-width: 0; padding: var(--smrt-spacing-3); border: 1px solid var(--smrt-color-outline-variant); border-radius: var(--smrt-radius-medium); background: var(--smrt-color-surface); color: var(--smrt-color-on-surface); }
113
+ li { position: relative; display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--smrt-spacing-3); min-width: 0; padding: var(--smrt-spacing-3); border: var(--smrt-card-border, 1px solid var(--smrt-color-outline-variant)); border-radius: var(--smrt-radius-medium); background: var(--smrt-card-background, var(--smrt-color-surface)); color: var(--smrt-color-on-surface); }
108
114
  li.selected { border-color: var(--smrt-color-primary); background: var(--smrt-color-primary-container); }
115
+ /* The selection box and actions sit above an item's stretched link. */
116
+ .select { position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center; min-width: 2.75rem; min-height: 2.75rem; }
109
117
  input { width: 1.125rem; height: 1.125rem; accent-color: var(--smrt-color-primary); }
110
118
  .main { display: grid; min-width: 0; gap: var(--smrt-spacing-1); padding: 0; border: 0; background: transparent; color: inherit; font: inherit; text-align: left; }
111
119
  button.main { width: 100%; cursor: pointer; }
112
120
  button.main:focus-visible { outline: 2px solid var(--smrt-color-primary); outline-offset: 3px; }
113
121
  .main strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font: var(--smrt-typography-title-small-font); }
114
122
  .main span { color: var(--smrt-color-on-surface-variant); }
115
- .actions { display: flex; gap: var(--smrt-spacing-1); }
123
+ .actions { position: relative; z-index: 1; display: flex; gap: var(--smrt-spacing-1); }
124
+ .collection--divided { --collection-divider: color-mix(in srgb, var(--smrt-color-outline-variant) 55%, transparent); gap: 0; }
125
+ .collection--divided li { padding-inline: 0; border: none; border-radius: 0; background: transparent; }
126
+ .collection--divided li + li { border-block-start: 1px solid var(--collection-divider); }
127
+ .collection--divided li.selected { border-color: var(--collection-divider); background: transparent; }
128
+ .collection--gallery { grid-template-columns: repeat(auto-fill, minmax(min(11rem, 100%), 1fr)); }
129
+ .collection--gallery li { display: block; padding: 0; }
130
+ .collection--gallery .main { gap: 0; }
131
+ .collection--gallery .select, .collection--gallery .actions { position: absolute; top: var(--smrt-spacing-1); z-index: 2; min-width: 2.75rem; min-height: 2.75rem; align-items: center; justify-content: center; border-radius: var(--smrt-radius-full, 999px); background: color-mix(in srgb, var(--smrt-color-surface) 82%, transparent); }
132
+ .collection--gallery .select { left: var(--smrt-spacing-1); }
133
+ .collection--gallery .actions { right: var(--smrt-spacing-1); }
116
134
  .loading, .empty { display: flex; min-height: 8rem; align-items: center; justify-content: center; gap: var(--smrt-spacing-2); color: var(--smrt-color-on-surface-variant); }
117
135
  .spinner { width: 1rem; height: 1rem; border: 2px solid var(--smrt-color-outline-variant); border-top-color: var(--smrt-color-primary); border-radius: 50%; animation: spin .8s linear infinite; }
118
136
  @keyframes spin { to { transform: rotate(360deg); } }
@@ -8,8 +8,14 @@ export interface Props<T> {
8
8
  title?: keyof T | ((item: T) => string);
9
9
  /** Field name or function to extract the description text for each item. */
10
10
  description?: keyof T | ((item: T) => string | undefined);
11
- /** Display layout: list (single column) or grid (multiple columns). */
12
- layout?: 'list' | 'grid';
11
+ /**
12
+ * Display layout: list (single column of cards), divided (a flat single
13
+ * column: no card surface, rows separated by a hairline, a selected row shown
14
+ * by its checkbox), grid (multiple columns of cards), or gallery
15
+ * (picture-first tiles: the `item` snippet fills the tile, the selection
16
+ * checkbox and `actions` float over its top corners).
17
+ */
18
+ layout?: 'list' | 'divided' | 'grid' | 'gallery';
13
19
  /** Whether to show checkboxes for selecting multiple items. */
14
20
  selectable?: boolean;
15
21
  /** Set of currently selected item keys (bindable). */
@@ -1 +1 @@
1
- {"version":3,"file":"CollectionList.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/data/CollectionList.svelte.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CollectionList.svelte.d.ts","sourceRoot":"","sources":["../../../src/components/data/CollectionList.svelte.ts"],"names":[],"mappings":"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"}