foldkit 0.159.0 → 0.160.0-canary.41f95ced5e07

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 (38) hide show
  1. package/dist/calendar/calendarDate.js +1 -1
  2. package/dist/calendar/index.d.ts +1 -1
  3. package/dist/calendar/index.d.ts.map +1 -1
  4. package/dist/calendar/index.js +1 -1
  5. package/dist/calendar/locale.d.ts +219 -10
  6. package/dist/calendar/locale.d.ts.map +1 -1
  7. package/dist/calendar/locale.js +166 -82
  8. package/dist/calendar/public.d.ts +1 -1
  9. package/dist/calendar/public.d.ts.map +1 -1
  10. package/dist/calendar/public.js +1 -1
  11. package/dist/command/index.d.ts +10 -8
  12. package/dist/command/index.d.ts.map +1 -1
  13. package/dist/command/index.js +8 -6
  14. package/dist/managedResource/managedResource.d.ts +44 -2
  15. package/dist/managedResource/managedResource.d.ts.map +1 -1
  16. package/dist/managedResource/managedResource.js +40 -10
  17. package/dist/mount/index.d.ts +2 -2
  18. package/dist/runtime/start.d.ts.map +1 -1
  19. package/dist/runtime/start.js +3 -14
  20. package/dist/schema/index.d.ts.map +1 -1
  21. package/dist/schema/index.js +21 -16
  22. package/dist/subscription/fromEvent.d.ts +193 -26
  23. package/dist/subscription/fromEvent.d.ts.map +1 -1
  24. package/dist/subscription/fromEvent.js +131 -29
  25. package/dist/subscription/keyboardShortcuts.d.ts +110 -0
  26. package/dist/subscription/keyboardShortcuts.d.ts.map +1 -0
  27. package/dist/subscription/keyboardShortcuts.js +444 -0
  28. package/dist/subscription/public.d.ts +4 -2
  29. package/dist/subscription/public.d.ts.map +1 -1
  30. package/dist/subscription/public.js +2 -1
  31. package/dist/subscription/subscription.d.ts +61 -1
  32. package/dist/subscription/subscription.d.ts.map +1 -1
  33. package/dist/subscription/subscription.js +51 -8
  34. package/dist/test/vitest.d.ts +2 -2
  35. package/dist/test/vitest.d.ts.map +1 -1
  36. package/dist/test/vitest.js +1 -1
  37. package/dist/url/index.js +1 -1
  38. package/package.json +8 -6
@@ -178,7 +178,7 @@ const isoPattern = /^(\d{4})-(\d{2})-(\d{2})$/;
178
178
  * encode(Calendar.make(2026, 4, 13)) // "2026-04-13"
179
179
  * ```
180
180
  */
181
- export const CalendarDateFromIsoString = Schema.String.pipe(Schema.decodeTo(CalendarDate, SchemaTransformation.transformOrFail({
181
+ export const CalendarDateFromIsoString = Schema.String.pipe(Schema.decodeTo(CalendarDate, SchemaTransformation.transformEffect({
182
182
  decode: input => {
183
183
  const match = input.match(isoPattern);
184
184
  if (match === null) {
@@ -3,5 +3,5 @@ export { addDays, addMonths, addYears, daysSince, daysUntil, subtractDays, subtr
3
3
  export { between, clamp, Equivalence, isAfter, isAfterOrEqual, isBefore, isBeforeOrEqual, isEqual, max, min, Order, } from './comparison.js';
4
4
  export { DayOfWeek, dayOfWeek, endOfWeek, firstOfMonth, lastOfMonth, startOfWeek, } from './info.js';
5
5
  export { today } from './today.js';
6
- export { defaultEnglishLocale, formatAriaLabel, formatLong, formatShort, LocaleConfig, } from './locale.js';
6
+ export { DateFormat, DatePart, defaultEnglishLocale, format, formatAriaLabel, formatLong, formatMonthYear, formatShort, LocaleConfig, MonthYearFormat, } from './locale.js';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/calendar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,yBAAyB,EACzB,WAAW,EACX,cAAc,EACd,aAAa,EACb,cAAc,EACd,UAAU,EACV,IAAI,EACJ,WAAW,EACX,UAAU,GACX,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EACL,OAAO,EACP,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,YAAY,EACZ,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,OAAO,EACP,KAAK,EACL,WAAW,EACX,OAAO,EACP,cAAc,EACd,QAAQ,EACR,eAAe,EACf,OAAO,EACP,GAAG,EACH,GAAG,EACH,KAAK,GACN,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,WAAW,GACZ,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElC,OAAO,EACL,oBAAoB,EACpB,eAAe,EACf,UAAU,EACV,WAAW,EACX,YAAY,GACb,MAAM,aAAa,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/calendar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,yBAAyB,EACzB,WAAW,EACX,cAAc,EACd,aAAa,EACb,cAAc,EACd,UAAU,EACV,IAAI,EACJ,WAAW,EACX,UAAU,GACX,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EACL,OAAO,EACP,SAAS,EACT,QAAQ,EACR,SAAS,EACT,SAAS,EACT,YAAY,EACZ,cAAc,EACd,aAAa,GACd,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,OAAO,EACP,KAAK,EACL,WAAW,EACX,OAAO,EACP,cAAc,EACd,QAAQ,EACR,eAAe,EACf,OAAO,EACP,GAAG,EACH,GAAG,EACH,KAAK,GACN,MAAM,iBAAiB,CAAA;AAExB,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,YAAY,EACZ,WAAW,EACX,WAAW,GACZ,MAAM,WAAW,CAAA;AAElB,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAElC,OAAO,EACL,UAAU,EACV,QAAQ,EACR,oBAAoB,EACpB,MAAM,EACN,eAAe,EACf,UAAU,EACV,eAAe,EACf,WAAW,EACX,YAAY,EACZ,eAAe,GAChB,MAAM,aAAa,CAAA"}
@@ -3,4 +3,4 @@ export { addDays, addMonths, addYears, daysSince, daysUntil, subtractDays, subtr
3
3
  export { between, clamp, Equivalence, isAfter, isAfterOrEqual, isBefore, isBeforeOrEqual, isEqual, max, min, Order, } from './comparison.js';
4
4
  export { DayOfWeek, dayOfWeek, endOfWeek, firstOfMonth, lastOfMonth, startOfWeek, } from './info.js';
5
5
  export { today } from './today.js';
6
- export { defaultEnglishLocale, formatAriaLabel, formatLong, formatShort, LocaleConfig, } from './locale.js';
6
+ export { DateFormat, DatePart, defaultEnglishLocale, format, formatAriaLabel, formatLong, formatMonthYear, formatShort, LocaleConfig, MonthYearFormat, } from './locale.js';
@@ -1,10 +1,101 @@
1
1
  import { Schema } from 'effect';
2
2
  import type { CalendarDate } from './calendarDate.js';
3
3
  /**
4
- * Locale configuration for rendering calendar dates. Contains only data
5
- * month/day names and the first day of the week. Formatting functions
6
- * (`formatLong`, `formatShort`, `formatAriaLabel`) are separate exports that
7
- * take a `LocaleConfig` as input.
4
+ * One part of a `DateFormat`. Name parts draw from the `LocaleConfig`, number
5
+ * parts draw from the date, and `LiteralText` supplies separators,
6
+ * punctuation, or suffixes such as `年`.
7
+ *
8
+ * `MonthName`, `DayName`, and their `Short*` counterparts select from the
9
+ * corresponding locale name arrays. `MonthNumber` and `DayNumber` render
10
+ * unpadded numbers; their `Padded*` counterparts render two digits.
11
+ * `YearNumber` renders the full year.
12
+ */
13
+ export declare const DatePart: import("../schema/index.js").TaggedUnion<{
14
+ readonly MonthName: {};
15
+ readonly ShortMonthName: {};
16
+ readonly MonthNumber: {};
17
+ readonly PaddedMonthNumber: {};
18
+ readonly DayNumber: {};
19
+ readonly PaddedDayNumber: {};
20
+ readonly DayName: {};
21
+ readonly ShortDayName: {};
22
+ readonly YearNumber: {};
23
+ readonly LiteralText: {
24
+ text: Schema.String;
25
+ };
26
+ }>;
27
+ export type DatePart = typeof DatePart.Type;
28
+ /**
29
+ * A non-empty ordered list of parts rendered left to right. Because ordering
30
+ * lives in the data rather than in the formatting functions, a locale whose
31
+ * dates read day-first or year-first renders correctly without a code change.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import { Calendar } from 'foldkit'
36
+ *
37
+ * // "15. Januar 2026"
38
+ * const germanLong: Calendar.DateFormat = [
39
+ * Calendar.DatePart.DayNumber(),
40
+ * Calendar.DatePart.LiteralText({ text: '. ' }),
41
+ * Calendar.DatePart.MonthName(),
42
+ * Calendar.DatePart.LiteralText({ text: ' ' }),
43
+ * Calendar.DatePart.YearNumber(),
44
+ * ]
45
+ * ```
46
+ */
47
+ export declare const DateFormat: Schema.NonEmptyArray<import("../schema/index.js").TaggedUnion<{
48
+ readonly MonthName: {};
49
+ readonly ShortMonthName: {};
50
+ readonly MonthNumber: {};
51
+ readonly PaddedMonthNumber: {};
52
+ readonly DayNumber: {};
53
+ readonly PaddedDayNumber: {};
54
+ readonly DayName: {};
55
+ readonly ShortDayName: {};
56
+ readonly YearNumber: {};
57
+ readonly LiteralText: {
58
+ text: Schema.String;
59
+ };
60
+ }>>;
61
+ export type DateFormat = typeof DateFormat.Type;
62
+ /** A non-empty format restricted to month and year parts. */
63
+ export declare const MonthYearFormat: Schema.NonEmptyArray<Schema.Union<readonly [Schema.TaggedStruct<"MonthName", {}> & ((value?: void | {
64
+ readonly _tag?: "MonthName";
65
+ } | undefined) => {
66
+ readonly _tag: "MonthName";
67
+ }), Schema.TaggedStruct<"ShortMonthName", {}> & ((value?: void | {
68
+ readonly _tag?: "ShortMonthName";
69
+ } | undefined) => {
70
+ readonly _tag: "ShortMonthName";
71
+ }), Schema.TaggedStruct<"MonthNumber", {}> & ((value?: void | {
72
+ readonly _tag?: "MonthNumber";
73
+ } | undefined) => {
74
+ readonly _tag: "MonthNumber";
75
+ }), Schema.TaggedStruct<"PaddedMonthNumber", {}> & ((value?: void | {
76
+ readonly _tag?: "PaddedMonthNumber";
77
+ } | undefined) => {
78
+ readonly _tag: "PaddedMonthNumber";
79
+ }), Schema.TaggedStruct<"YearNumber", {}> & ((value?: void | {
80
+ readonly _tag?: "YearNumber";
81
+ } | undefined) => {
82
+ readonly _tag: "YearNumber";
83
+ }), Schema.TaggedStruct<"LiteralText", {
84
+ readonly text: Schema.String;
85
+ }> & ((value: {
86
+ readonly _tag?: "LiteralText";
87
+ readonly text: string;
88
+ }) => {
89
+ readonly _tag: "LiteralText";
90
+ readonly text: string;
91
+ })]>>;
92
+ export type MonthYearFormat = typeof MonthYearFormat.Type;
93
+ /**
94
+ * Locale configuration for rendering calendar dates. Contains only data: the
95
+ * month and day names, the first day of the week, and the `DateFormat` for
96
+ * each of the four shapes the formatters produce. Formatting functions
97
+ * (`formatLong`, `formatShort`, `formatAriaLabel`, `formatMonthYear`) are
98
+ * separate exports that take a `LocaleConfig` as input.
8
99
  *
9
100
  * Day names are always stored Sunday-first in the config; `firstDayOfWeek`
10
101
  * controls how the view rotates them at render time.
@@ -15,16 +106,112 @@ export declare const LocaleConfig: Schema.Struct<{
15
106
  readonly shortMonthNames: Schema.Tuple<readonly [Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String]>;
16
107
  readonly dayNames: Schema.Tuple<readonly [Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String]>;
17
108
  readonly shortDayNames: Schema.Tuple<readonly [Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String, Schema.String]>;
109
+ readonly longFormat: Schema.NonEmptyArray<import("../schema/index.js").TaggedUnion<{
110
+ readonly MonthName: {};
111
+ readonly ShortMonthName: {};
112
+ readonly MonthNumber: {};
113
+ readonly PaddedMonthNumber: {};
114
+ readonly DayNumber: {};
115
+ readonly PaddedDayNumber: {};
116
+ readonly DayName: {};
117
+ readonly ShortDayName: {};
118
+ readonly YearNumber: {};
119
+ readonly LiteralText: {
120
+ text: Schema.String;
121
+ };
122
+ }>>;
123
+ readonly shortFormat: Schema.NonEmptyArray<import("../schema/index.js").TaggedUnion<{
124
+ readonly MonthName: {};
125
+ readonly ShortMonthName: {};
126
+ readonly MonthNumber: {};
127
+ readonly PaddedMonthNumber: {};
128
+ readonly DayNumber: {};
129
+ readonly PaddedDayNumber: {};
130
+ readonly DayName: {};
131
+ readonly ShortDayName: {};
132
+ readonly YearNumber: {};
133
+ readonly LiteralText: {
134
+ text: Schema.String;
135
+ };
136
+ }>>;
137
+ readonly ariaLabelFormat: Schema.NonEmptyArray<import("../schema/index.js").TaggedUnion<{
138
+ readonly MonthName: {};
139
+ readonly ShortMonthName: {};
140
+ readonly MonthNumber: {};
141
+ readonly PaddedMonthNumber: {};
142
+ readonly DayNumber: {};
143
+ readonly PaddedDayNumber: {};
144
+ readonly DayName: {};
145
+ readonly ShortDayName: {};
146
+ readonly YearNumber: {};
147
+ readonly LiteralText: {
148
+ text: Schema.String;
149
+ };
150
+ }>>;
151
+ readonly monthYearFormat: Schema.NonEmptyArray<Schema.Union<readonly [Schema.TaggedStruct<"MonthName", {}> & ((value?: void | {
152
+ readonly _tag?: "MonthName";
153
+ } | undefined) => {
154
+ readonly _tag: "MonthName";
155
+ }), Schema.TaggedStruct<"ShortMonthName", {}> & ((value?: void | {
156
+ readonly _tag?: "ShortMonthName";
157
+ } | undefined) => {
158
+ readonly _tag: "ShortMonthName";
159
+ }), Schema.TaggedStruct<"MonthNumber", {}> & ((value?: void | {
160
+ readonly _tag?: "MonthNumber";
161
+ } | undefined) => {
162
+ readonly _tag: "MonthNumber";
163
+ }), Schema.TaggedStruct<"PaddedMonthNumber", {}> & ((value?: void | {
164
+ readonly _tag?: "PaddedMonthNumber";
165
+ } | undefined) => {
166
+ readonly _tag: "PaddedMonthNumber";
167
+ }), Schema.TaggedStruct<"YearNumber", {}> & ((value?: void | {
168
+ readonly _tag?: "YearNumber";
169
+ } | undefined) => {
170
+ readonly _tag: "YearNumber";
171
+ }), Schema.TaggedStruct<"LiteralText", {
172
+ readonly text: Schema.String;
173
+ }> & ((value: {
174
+ readonly _tag?: "LiteralText";
175
+ readonly text: string;
176
+ }) => {
177
+ readonly _tag: "LiteralText";
178
+ readonly text: string;
179
+ })]>>;
18
180
  }>;
19
181
  export type LocaleConfig = typeof LocaleConfig.Type;
20
182
  /**
21
- * Default English (United States) locale. Picker components default to this
22
- * when no locale is passed via ViewConfig. Consumers who want a different
183
+ * Default English (United States) locale. Calendar components default to this
184
+ * when initialization receives no locale. Consumers who want a different
23
185
  * locale pass their own `LocaleConfig`.
24
186
  */
25
187
  export declare const defaultEnglishLocale: LocaleConfig;
26
188
  /**
27
- * Renders a calendar date in long form. Example: `"January 15, 2026"`.
189
+ * Renders a calendar date through an arbitrary `DateFormat`. The four named
190
+ * formatters below are this function applied to the matching field of the
191
+ * `LocaleConfig`; reach for it directly when a view needs a shape the locale
192
+ * does not carry.
193
+ *
194
+ * @example
195
+ * ```ts
196
+ * import { Calendar } from 'foldkit'
197
+ *
198
+ * Calendar.format(Calendar.make(2026, 1, 15), Calendar.defaultEnglishLocale, [
199
+ * Calendar.DatePart.YearNumber(),
200
+ * Calendar.DatePart.LiteralText({ text: '-' }),
201
+ * Calendar.DatePart.PaddedMonthNumber(),
202
+ * Calendar.DatePart.LiteralText({ text: '-' }),
203
+ * Calendar.DatePart.PaddedDayNumber(),
204
+ * ])
205
+ * // "2026-01-15"
206
+ * ```
207
+ */
208
+ export declare const format: {
209
+ (locale: LocaleConfig, dateFormat: DateFormat): (self: CalendarDate) => string;
210
+ (self: CalendarDate, locale: LocaleConfig, dateFormat: DateFormat): string;
211
+ };
212
+ /**
213
+ * Renders a calendar date through the locale's `longFormat`. Under
214
+ * `defaultEnglishLocale`: `"January 15, 2026"`.
28
215
  *
29
216
  * @example
30
217
  * ```ts
@@ -46,15 +233,17 @@ export declare const formatLong: {
46
233
  (self: CalendarDate, locale: LocaleConfig): string;
47
234
  };
48
235
  /**
49
- * Renders a calendar date in short form. Example: `"Jan 15, 2026"`.
236
+ * Renders a calendar date through the locale's `shortFormat`. Under
237
+ * `defaultEnglishLocale`: `"Jan 15, 2026"`.
50
238
  */
51
239
  export declare const formatShort: {
52
240
  (locale: LocaleConfig): (self: CalendarDate) => string;
53
241
  (self: CalendarDate, locale: LocaleConfig): string;
54
242
  };
55
243
  /**
56
- * Renders an accessibility label for a calendar date, suitable for
57
- * `aria-label` on a grid cell. Example: `"Monday, January 15, 2026"`.
244
+ * Renders a calendar date through the locale's `ariaLabelFormat`, suitable
245
+ * for `aria-label` on a grid cell. Under `defaultEnglishLocale`:
246
+ * `"Thursday, January 15, 2026"`.
58
247
  *
59
248
  * @example
60
249
  * ```ts
@@ -68,4 +257,24 @@ export declare const formatAriaLabel: {
68
257
  (locale: LocaleConfig): (self: CalendarDate) => string;
69
258
  (self: CalendarDate, locale: LocaleConfig): string;
70
259
  };
260
+ /**
261
+ * Renders the month and year of a calendar date through the locale's
262
+ * `monthYearFormat`, for calendar headings and month-cell labels. Under
263
+ * `defaultEnglishLocale`: `"January 2026"`.
264
+ *
265
+ * The day of `self` is ignored, so callers with only a year and month can pass
266
+ * any valid day.
267
+ *
268
+ * @example
269
+ * ```ts
270
+ * import { Calendar } from 'foldkit'
271
+ *
272
+ * Calendar.formatMonthYear(Calendar.make(2026, 1, 1), Calendar.defaultEnglishLocale)
273
+ * // "January 2026"
274
+ * ```
275
+ */
276
+ export declare const formatMonthYear: {
277
+ (locale: LocaleConfig): (self: CalendarDate) => string;
278
+ (self: CalendarDate, locale: LocaleConfig): string;
279
+ };
71
280
  //# sourceMappingURL=locale.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../src/calendar/locale.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,MAAM,EAAE,MAAM,QAAQ,CAAA;AAEzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AA4BrD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY;;;;;;EAMvB,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AAEnD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,YAwClC,CAAA;AA0CD;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,UAAU,EAAE;IACvB,CAAC,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAA;IACtD,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAAA;CAKnD,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE;IACxB,CAAC,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAA;IACtD,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAAA;CAKnD,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,eAAe,EAAE;IAC5B,CAAC,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAA;IACtD,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAAA;CAKlD,CAAA"}
1
+ {"version":3,"file":"locale.d.ts","sourceRoot":"","sources":["../../src/calendar/locale.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,MAAM,EAAQ,MAAM,QAAQ,CAAA;AAG9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AA8BrD;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ;;;;;;;;;;;QAUJ,IAAI;;EACnB,CAAA;AAEF,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC,IAAI,CAAA;AAE3C;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;QAxBN,IAAI;;GAwBmC,CAAA;AAExD,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAE/C,6DAA6D;AAC7D,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAS3B,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;AAEzD;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;YApDR,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA8DnB,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AAEnD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,YAoElC,CAAA;AAkDD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,MAAM,EAAE;IACnB,CAAC,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAA;IAC9E,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,GAAG,MAAM,CAAA;CAS3E,CAAA;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,UAAU,EAAE;IACvB,CAAC,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAA;IACtD,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAAA;CAGnD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE;IACxB,CAAC,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAA;IACtD,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAAA;CAGnD,CAAA;AAED;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,eAAe,EAAE;IAC5B,CAAC,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAA;IACtD,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAAA;CAGnD,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,EAAE;IAC5B,CAAC,MAAM,EAAE,YAAY,GAAG,CAAC,IAAI,EAAE,YAAY,KAAK,MAAM,CAAA;IACtD,CAAC,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAAA;CAGnD,CAAA"}
@@ -1,4 +1,5 @@
1
- import { Function, Schema } from 'effect';
1
+ import { Array, Function, Option, Schema, pipe } from 'effect';
2
+ import { defineTaggedUnion } from '../schema/index.js';
2
3
  import { DayOfWeek, dayOfWeek } from './info.js';
3
4
  const twelveStrings = Schema.Tuple([
4
5
  Schema.String,
@@ -23,11 +24,64 @@ const sevenStrings = Schema.Tuple([
23
24
  Schema.String,
24
25
  Schema.String,
25
26
  ]);
27
+ // DATE FORMAT
26
28
  /**
27
- * Locale configuration for rendering calendar dates. Contains only data
28
- * month/day names and the first day of the week. Formatting functions
29
- * (`formatLong`, `formatShort`, `formatAriaLabel`) are separate exports that
30
- * take a `LocaleConfig` as input.
29
+ * One part of a `DateFormat`. Name parts draw from the `LocaleConfig`, number
30
+ * parts draw from the date, and `LiteralText` supplies separators,
31
+ * punctuation, or suffixes such as `年`.
32
+ *
33
+ * `MonthName`, `DayName`, and their `Short*` counterparts select from the
34
+ * corresponding locale name arrays. `MonthNumber` and `DayNumber` render
35
+ * unpadded numbers; their `Padded*` counterparts render two digits.
36
+ * `YearNumber` renders the full year.
37
+ */
38
+ export const DatePart = defineTaggedUnion({
39
+ MonthName: {},
40
+ ShortMonthName: {},
41
+ MonthNumber: {},
42
+ PaddedMonthNumber: {},
43
+ DayNumber: {},
44
+ PaddedDayNumber: {},
45
+ DayName: {},
46
+ ShortDayName: {},
47
+ YearNumber: {},
48
+ LiteralText: { text: Schema.String },
49
+ });
50
+ /**
51
+ * A non-empty ordered list of parts rendered left to right. Because ordering
52
+ * lives in the data rather than in the formatting functions, a locale whose
53
+ * dates read day-first or year-first renders correctly without a code change.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * import { Calendar } from 'foldkit'
58
+ *
59
+ * // "15. Januar 2026"
60
+ * const germanLong: Calendar.DateFormat = [
61
+ * Calendar.DatePart.DayNumber(),
62
+ * Calendar.DatePart.LiteralText({ text: '. ' }),
63
+ * Calendar.DatePart.MonthName(),
64
+ * Calendar.DatePart.LiteralText({ text: ' ' }),
65
+ * Calendar.DatePart.YearNumber(),
66
+ * ]
67
+ * ```
68
+ */
69
+ export const DateFormat = Schema.NonEmptyArray(DatePart);
70
+ /** A non-empty format restricted to month and year parts. */
71
+ export const MonthYearFormat = Schema.NonEmptyArray(DatePart.subset([
72
+ 'MonthName',
73
+ 'ShortMonthName',
74
+ 'MonthNumber',
75
+ 'PaddedMonthNumber',
76
+ 'YearNumber',
77
+ 'LiteralText',
78
+ ]));
79
+ /**
80
+ * Locale configuration for rendering calendar dates. Contains only data: the
81
+ * month and day names, the first day of the week, and the `DateFormat` for
82
+ * each of the four shapes the formatters produce. Formatting functions
83
+ * (`formatLong`, `formatShort`, `formatAriaLabel`, `formatMonthYear`) are
84
+ * separate exports that take a `LocaleConfig` as input.
31
85
  *
32
86
  * Day names are always stored Sunday-first in the config; `firstDayOfWeek`
33
87
  * controls how the view rotates them at render time.
@@ -38,10 +92,14 @@ export const LocaleConfig = Schema.Struct({
38
92
  shortMonthNames: twelveStrings,
39
93
  dayNames: sevenStrings,
40
94
  shortDayNames: sevenStrings,
95
+ longFormat: DateFormat,
96
+ shortFormat: DateFormat,
97
+ ariaLabelFormat: DateFormat,
98
+ monthYearFormat: MonthYearFormat,
41
99
  });
42
100
  /**
43
- * Default English (United States) locale. Picker components default to this
44
- * when no locale is passed via ViewConfig. Consumers who want a different
101
+ * Default English (United States) locale. Calendar components default to this
102
+ * when initialization receives no locale. Consumers who want a different
45
103
  * locale pass their own `LocaleConfig`.
46
104
  */
47
105
  export const defaultEnglishLocale = {
@@ -84,74 +142,85 @@ export const defaultEnglishLocale = {
84
142
  'Saturday',
85
143
  ],
86
144
  shortDayNames: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
145
+ longFormat: [
146
+ DatePart.MonthName(),
147
+ DatePart.LiteralText({ text: ' ' }),
148
+ DatePart.DayNumber(),
149
+ DatePart.LiteralText({ text: ', ' }),
150
+ DatePart.YearNumber(),
151
+ ],
152
+ shortFormat: [
153
+ DatePart.ShortMonthName(),
154
+ DatePart.LiteralText({ text: ' ' }),
155
+ DatePart.DayNumber(),
156
+ DatePart.LiteralText({ text: ', ' }),
157
+ DatePart.YearNumber(),
158
+ ],
159
+ ariaLabelFormat: [
160
+ DatePart.DayName(),
161
+ DatePart.LiteralText({ text: ', ' }),
162
+ DatePart.MonthName(),
163
+ DatePart.LiteralText({ text: ' ' }),
164
+ DatePart.DayNumber(),
165
+ DatePart.LiteralText({ text: ', ' }),
166
+ DatePart.YearNumber(),
167
+ ],
168
+ monthYearFormat: [
169
+ DatePart.MonthName(),
170
+ DatePart.LiteralText({ text: ' ' }),
171
+ DatePart.YearNumber(),
172
+ ],
87
173
  };
88
- const pickMonthName = (locale, month) => {
89
- if (month === 1)
90
- return locale.monthNames[0];
91
- if (month === 2)
92
- return locale.monthNames[1];
93
- if (month === 3)
94
- return locale.monthNames[2];
95
- if (month === 4)
96
- return locale.monthNames[3];
97
- if (month === 5)
98
- return locale.monthNames[4];
99
- if (month === 6)
100
- return locale.monthNames[5];
101
- if (month === 7)
102
- return locale.monthNames[6];
103
- if (month === 8)
104
- return locale.monthNames[7];
105
- if (month === 9)
106
- return locale.monthNames[8];
107
- if (month === 10)
108
- return locale.monthNames[9];
109
- if (month === 11)
110
- return locale.monthNames[10];
111
- return locale.monthNames[11];
112
- };
113
- const pickShortMonthName = (locale, month) => {
114
- if (month === 1)
115
- return locale.shortMonthNames[0];
116
- if (month === 2)
117
- return locale.shortMonthNames[1];
118
- if (month === 3)
119
- return locale.shortMonthNames[2];
120
- if (month === 4)
121
- return locale.shortMonthNames[3];
122
- if (month === 5)
123
- return locale.shortMonthNames[4];
124
- if (month === 6)
125
- return locale.shortMonthNames[5];
126
- if (month === 7)
127
- return locale.shortMonthNames[6];
128
- if (month === 8)
129
- return locale.shortMonthNames[7];
130
- if (month === 9)
131
- return locale.shortMonthNames[8];
132
- if (month === 10)
133
- return locale.shortMonthNames[9];
134
- if (month === 11)
135
- return locale.shortMonthNames[10];
136
- return locale.shortMonthNames[11];
137
- };
138
- const pickDayName = (locale, day) => {
139
- if (day === 'Sunday')
140
- return locale.dayNames[0];
141
- if (day === 'Monday')
142
- return locale.dayNames[1];
143
- if (day === 'Tuesday')
144
- return locale.dayNames[2];
145
- if (day === 'Wednesday')
146
- return locale.dayNames[3];
147
- if (day === 'Thursday')
148
- return locale.dayNames[4];
149
- if (day === 'Friday')
150
- return locale.dayNames[5];
151
- return locale.dayNames[6];
174
+ const pickByMonth = (names, month) => pipe(names, Array.get(month - 1), Option.getOrElse(() => Array.lastNonEmpty(names)));
175
+ const DAY_OF_WEEK_INDEX = {
176
+ Sunday: 0,
177
+ Monday: 1,
178
+ Tuesday: 2,
179
+ Wednesday: 3,
180
+ Thursday: 4,
181
+ Friday: 5,
182
+ Saturday: 6,
152
183
  };
184
+ const pickByDay = (names, day) => pipe(names, Array.get(DAY_OF_WEEK_INDEX[day]), Option.getOrElse(() => Array.lastNonEmpty(names)));
185
+ const PAD_WIDTH = 2;
186
+ const PAD_CHARACTER = '0';
187
+ const toPaddedNumber = (value) => String(value).padStart(PAD_WIDTH, PAD_CHARACTER);
188
+ const renderPart = (self, locale, part) => DatePart.match(part, {
189
+ MonthName: () => pickByMonth(locale.monthNames, self.month),
190
+ ShortMonthName: () => pickByMonth(locale.shortMonthNames, self.month),
191
+ MonthNumber: () => String(self.month),
192
+ PaddedMonthNumber: () => toPaddedNumber(self.month),
193
+ DayNumber: () => String(self.day),
194
+ PaddedDayNumber: () => toPaddedNumber(self.day),
195
+ DayName: () => pickByDay(locale.dayNames, dayOfWeek(self)),
196
+ ShortDayName: () => pickByDay(locale.shortDayNames, dayOfWeek(self)),
197
+ YearNumber: () => String(self.year),
198
+ LiteralText: ({ text }) => text,
199
+ });
153
200
  /**
154
- * Renders a calendar date in long form. Example: `"January 15, 2026"`.
201
+ * Renders a calendar date through an arbitrary `DateFormat`. The four named
202
+ * formatters below are this function applied to the matching field of the
203
+ * `LocaleConfig`; reach for it directly when a view needs a shape the locale
204
+ * does not carry.
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * import { Calendar } from 'foldkit'
209
+ *
210
+ * Calendar.format(Calendar.make(2026, 1, 15), Calendar.defaultEnglishLocale, [
211
+ * Calendar.DatePart.YearNumber(),
212
+ * Calendar.DatePart.LiteralText({ text: '-' }),
213
+ * Calendar.DatePart.PaddedMonthNumber(),
214
+ * Calendar.DatePart.LiteralText({ text: '-' }),
215
+ * Calendar.DatePart.PaddedDayNumber(),
216
+ * ])
217
+ * // "2026-01-15"
218
+ * ```
219
+ */
220
+ export const format = Function.dual(3, (self, locale, dateFormat) => pipe(dateFormat, Array.map(part => renderPart(self, locale, part)), Array.join('')));
221
+ /**
222
+ * Renders a calendar date through the locale's `longFormat`. Under
223
+ * `defaultEnglishLocale`: `"January 15, 2026"`.
155
224
  *
156
225
  * @example
157
226
  * ```ts
@@ -168,14 +237,16 @@ const pickDayName = (locale, day) => {
168
237
  * // "January 15, 2026"
169
238
  * ```
170
239
  */
171
- export const formatLong = Function.dual(2, (self, locale) => `${pickMonthName(locale, self.month)} ${self.day}, ${self.year}`);
240
+ export const formatLong = Function.dual(2, (self, locale) => format(self, locale, locale.longFormat));
172
241
  /**
173
- * Renders a calendar date in short form. Example: `"Jan 15, 2026"`.
242
+ * Renders a calendar date through the locale's `shortFormat`. Under
243
+ * `defaultEnglishLocale`: `"Jan 15, 2026"`.
174
244
  */
175
- export const formatShort = Function.dual(2, (self, locale) => `${pickShortMonthName(locale, self.month)} ${self.day}, ${self.year}`);
245
+ export const formatShort = Function.dual(2, (self, locale) => format(self, locale, locale.shortFormat));
176
246
  /**
177
- * Renders an accessibility label for a calendar date, suitable for
178
- * `aria-label` on a grid cell. Example: `"Monday, January 15, 2026"`.
247
+ * Renders a calendar date through the locale's `ariaLabelFormat`, suitable
248
+ * for `aria-label` on a grid cell. Under `defaultEnglishLocale`:
249
+ * `"Thursday, January 15, 2026"`.
179
250
  *
180
251
  * @example
181
252
  * ```ts
@@ -185,8 +256,21 @@ export const formatShort = Function.dual(2, (self, locale) => `${pickShortMonthN
185
256
  * // "Thursday, January 15, 2026"
186
257
  * ```
187
258
  */
188
- export const formatAriaLabel = Function.dual(2, (self, locale) => {
189
- const dayName = pickDayName(locale, dayOfWeek(self));
190
- const monthName = pickMonthName(locale, self.month);
191
- return `${dayName}, ${monthName} ${self.day}, ${self.year}`;
192
- });
259
+ export const formatAriaLabel = Function.dual(2, (self, locale) => format(self, locale, locale.ariaLabelFormat));
260
+ /**
261
+ * Renders the month and year of a calendar date through the locale's
262
+ * `monthYearFormat`, for calendar headings and month-cell labels. Under
263
+ * `defaultEnglishLocale`: `"January 2026"`.
264
+ *
265
+ * The day of `self` is ignored, so callers with only a year and month can pass
266
+ * any valid day.
267
+ *
268
+ * @example
269
+ * ```ts
270
+ * import { Calendar } from 'foldkit'
271
+ *
272
+ * Calendar.formatMonthYear(Calendar.make(2026, 1, 1), Calendar.defaultEnglishLocale)
273
+ * // "January 2026"
274
+ * ```
275
+ */
276
+ export const formatMonthYear = Function.dual(2, (self, locale) => format(self, locale, locale.monthYearFormat));
@@ -1,2 +1,2 @@
1
- export { addDays, addMonths, addYears, between, CalendarDate, CalendarDateFromIsoString, clamp, DayOfWeek, dayOfWeek, daysInMonth, daysSince, daysUntil, defaultEnglishLocale, endOfWeek, Equivalence, firstOfMonth, formatAriaLabel, formatLong, formatShort, fromDateInZone, fromDateLocal, isAfter, isAfterOrEqual, isBefore, isBeforeOrEqual, isCalendarDate, isEqual, isLeapYear, lastOfMonth, LocaleConfig, make, max, min, Order, startOfWeek, subtractDays, subtractMonths, subtractYears, toDateLocal, today, } from './index.js';
1
+ export { addDays, addMonths, addYears, between, CalendarDate, CalendarDateFromIsoString, clamp, DateFormat, DatePart, DayOfWeek, dayOfWeek, daysInMonth, daysSince, daysUntil, defaultEnglishLocale, endOfWeek, Equivalence, firstOfMonth, format, formatAriaLabel, formatLong, formatMonthYear, formatShort, fromDateInZone, fromDateLocal, isAfter, isAfterOrEqual, isBefore, isBeforeOrEqual, isCalendarDate, isEqual, isLeapYear, lastOfMonth, LocaleConfig, make, max, min, MonthYearFormat, Order, startOfWeek, subtractDays, subtractMonths, subtractYears, toDateLocal, today, } from './index.js';
2
2
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/calendar/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,SAAS,EACT,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,yBAAyB,EACzB,KAAK,EACL,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,oBAAoB,EACpB,SAAS,EACT,WAAW,EACX,YAAY,EACZ,eAAe,EACf,UAAU,EACV,WAAW,EACX,cAAc,EACd,aAAa,EACb,OAAO,EACP,cAAc,EACd,QAAQ,EACR,eAAe,EACf,cAAc,EACd,OAAO,EACP,UAAU,EACV,WAAW,EACX,YAAY,EACZ,IAAI,EACJ,GAAG,EACH,GAAG,EACH,KAAK,EACL,WAAW,EACX,YAAY,EACZ,cAAc,EACd,aAAa,EACb,WAAW,EACX,KAAK,GACN,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/calendar/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,SAAS,EACT,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,yBAAyB,EACzB,KAAK,EACL,UAAU,EACV,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,oBAAoB,EACpB,SAAS,EACT,WAAW,EACX,YAAY,EACZ,MAAM,EACN,eAAe,EACf,UAAU,EACV,eAAe,EACf,WAAW,EACX,cAAc,EACd,aAAa,EACb,OAAO,EACP,cAAc,EACd,QAAQ,EACR,eAAe,EACf,cAAc,EACd,OAAO,EACP,UAAU,EACV,WAAW,EACX,YAAY,EACZ,IAAI,EACJ,GAAG,EACH,GAAG,EACH,eAAe,EACf,KAAK,EACL,WAAW,EACX,YAAY,EACZ,cAAc,EACd,aAAa,EACb,WAAW,EACX,KAAK,GACN,MAAM,YAAY,CAAA"}
@@ -1 +1 @@
1
- export { addDays, addMonths, addYears, between, CalendarDate, CalendarDateFromIsoString, clamp, DayOfWeek, dayOfWeek, daysInMonth, daysSince, daysUntil, defaultEnglishLocale, endOfWeek, Equivalence, firstOfMonth, formatAriaLabel, formatLong, formatShort, fromDateInZone, fromDateLocal, isAfter, isAfterOrEqual, isBefore, isBeforeOrEqual, isCalendarDate, isEqual, isLeapYear, lastOfMonth, LocaleConfig, make, max, min, Order, startOfWeek, subtractDays, subtractMonths, subtractYears, toDateLocal, today, } from './index.js';
1
+ export { addDays, addMonths, addYears, between, CalendarDate, CalendarDateFromIsoString, clamp, DateFormat, DatePart, DayOfWeek, dayOfWeek, daysInMonth, daysSince, daysUntil, defaultEnglishLocale, endOfWeek, Equivalence, firstOfMonth, format, formatAriaLabel, formatLong, formatMonthYear, formatShort, fromDateInZone, fromDateLocal, isAfter, isAfterOrEqual, isBefore, isBeforeOrEqual, isCalendarDate, isEqual, isLeapYear, lastOfMonth, LocaleConfig, make, max, min, MonthYearFormat, Order, startOfWeek, subtractDays, subtractMonths, subtractYears, toDateLocal, today, } from './index.js';
@@ -172,18 +172,20 @@ export declare function define<const Name extends string, const Messages extends
172
172
  interrupt?: never;
173
173
  execute: Eff;
174
174
  }>): CommandDefinitionNoArgs<Name, Eff>;
175
- /** Transforms the Effect inside a Command while preserving its name, args, and
176
- * message-mapping chain. Reach for this to adjust the Effect itself (provide a
177
- * service, add a delay or retry), not to lift the result Message. Never use it
178
- * to transform the result Message, even via
179
- * `Effect.map(childMessage => Parent({ childMessage }))`. That dispatches
175
+ /** Transforms the Effect inside a Command while preserving its result Message,
176
+ * name, args, and message-mapping chain. Reach for this to provide a service,
177
+ * add a delay or retry, or change the error or requirement channel. Its type
178
+ * prevents the transform from changing the result Message. Never use it to
179
+ * lift that Message, even via
180
+ * `Effect.map(message => Message.GotChildMessage({ message }))`. That dispatches
180
181
  * correctly in production but is invisible to `Story`/`Scene` `resolve`, which
181
182
  * replays only the recorded chain and never runs the Effect, so the test would
182
183
  * see the child's raw Message instead of the wrapped one. Lift result Messages
183
- * with {@link mapMessage} / {@link mapMessages}, which record the lift. */
184
+ * with {@link mapMessage} / {@link mapMessages}, which record the lift. The
185
+ * `foldkit/prefer-command-mapmessage` lint rule flags this misuse. */
184
186
  export declare const mapEffect: {
185
- <A, E1, R1, B, E2, R2>(f: (effect: Effect.Effect<A, E1, R1>) => Effect.Effect<B, E2, R2>): (command: Command<A, E1, R1>) => Command<B, E2, R2>;
186
- <A, E1, R1, B, E2, R2>(command: Command<A, E1, R1>, f: (effect: Effect.Effect<A, E1, R1>) => Effect.Effect<B, E2, R2>): Command<B, E2, R2>;
187
+ <A, E1, R1, E2, R2>(f: (effect: Effect.Effect<A, E1, R1>) => Effect.Effect<NoInfer<A>, E2, R2>): (command: Command<A, E1, R1>) => Command<A, E2, R2>;
188
+ <A, E1, R1, E2, R2>(command: Command<A, E1, R1>, f: (effect: Effect.Effect<A, E1, R1>) => Effect.Effect<NoInfer<A>, E2, R2>): Command<A, E2, R2>;
187
189
  };
188
190
  /** Lifts a single Command's result Message through `f`, transforming
189
191
  * `FromMessage` to `ToMessage`. The singular complement to