@linked.cm/calendar 0.1.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 (44) hide show
  1. package/LICENSE +12 -0
  2. package/README.md +48 -0
  3. package/THIRD_PARTY_NOTICES.md +12 -0
  4. package/lib/esm/Calendar.d.ts +57 -0
  5. package/lib/esm/Calendar.js +202 -0
  6. package/lib/esm/Calendar.js.map +1 -0
  7. package/lib/esm/Calendar.module.css +912 -0
  8. package/lib/esm/EventPopover.d.ts +17 -0
  9. package/lib/esm/EventPopover.js +104 -0
  10. package/lib/esm/EventPopover.js.map +1 -0
  11. package/lib/esm/ResourceGrid.d.ts +11 -0
  12. package/lib/esm/ResourceGrid.js +36 -0
  13. package/lib/esm/ResourceGrid.js.map +1 -0
  14. package/lib/esm/TimeGrid.d.ts +15 -0
  15. package/lib/esm/TimeGrid.js +276 -0
  16. package/lib/esm/TimeGrid.js.map +1 -0
  17. package/lib/esm/index.d.ts +10 -0
  18. package/lib/esm/index.js +12 -0
  19. package/lib/esm/index.js.map +1 -0
  20. package/lib/esm/package.d.ts +8 -0
  21. package/lib/esm/package.js +10 -0
  22. package/lib/esm/package.js.map +1 -0
  23. package/lib/esm/range.d.ts +3 -0
  24. package/lib/esm/range.js +22 -0
  25. package/lib/esm/range.js.map +1 -0
  26. package/lib/esm/recurrence.d.ts +14 -0
  27. package/lib/esm/recurrence.js +60 -0
  28. package/lib/esm/recurrence.js.map +1 -0
  29. package/lib/esm/refreshBus.d.ts +10 -0
  30. package/lib/esm/refreshBus.js +25 -0
  31. package/lib/esm/refreshBus.js.map +1 -0
  32. package/lib/esm/styles.d.ts +4 -0
  33. package/lib/esm/translations/en.json +49 -0
  34. package/lib/esm/translations.d.ts +56 -0
  35. package/lib/esm/translations.js +44 -0
  36. package/lib/esm/translations.js.map +1 -0
  37. package/lib/esm/types.d.ts +97 -0
  38. package/lib/esm/types.js +11 -0
  39. package/lib/esm/types.js.map +1 -0
  40. package/lib/esm/tz.d.ts +30 -0
  41. package/lib/esm/tz.js +78 -0
  42. package/lib/esm/tz.js.map +1 -0
  43. package/package.json +98 -0
  44. package/src/translations/en.json +49 -0
@@ -0,0 +1,22 @@
1
+ const startOfDay = (date) => new Date(date.getFullYear(), date.getMonth(), date.getDate());
2
+ const addDays = (date, days) => new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);
3
+ /** The bounded recurrence/query window rendered by a calendar view. */
4
+ export function rangeForCalendarView(view, cursor) {
5
+ if (view === 'day' || view === 'resource') {
6
+ const start = startOfDay(cursor);
7
+ return { start, end: addDays(start, 1) };
8
+ }
9
+ if (view === 'week') {
10
+ const day = startOfDay(cursor);
11
+ const start = addDays(day, -day.getDay());
12
+ return { start, end: addDays(start, 7) };
13
+ }
14
+ if (view === 'agenda') {
15
+ const start = new Date(cursor.getFullYear(), cursor.getMonth(), 1);
16
+ return { start, end: new Date(cursor.getFullYear(), cursor.getMonth() + 1, 1) };
17
+ }
18
+ const first = new Date(cursor.getFullYear(), cursor.getMonth(), 1);
19
+ const start = addDays(first, -first.getDay());
20
+ return { start, end: addDays(start, 42) };
21
+ }
22
+ //# sourceMappingURL=range.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range.js","sourceRoot":"","sources":["../../src/range.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,GAAG,CAAC,IAAU,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;AACjG,MAAM,OAAO,GAAG,CAAC,IAAU,EAAE,IAAY,EAAE,EAAE,CAC3C,IAAI,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;AAEvE,uEAAuE;AACvE,MAAM,UAAU,oBAAoB,CAAC,IAAa,EAAE,MAAY;IAC9D,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;QAC1C,MAAM,KAAK,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;IAC3C,CAAC;IACD,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;QACpB,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QAC1C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;IAC3C,CAAC;IACD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;QACnE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;IAClF,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { CalEventData, CalRange } from './types.js';
2
+ /**
3
+ * Expand one graph-projected base event into instances overlapping `win`.
4
+ *
5
+ * `rule` accepts an RRULE value (`FREQ=...`), a prefixed `RRULE:` line, or an iCalendar recurrence
6
+ * fragment containing DTSTART/RRULE/RDATE/EXDATE lines. Expansion remains a bounded view operation; the
7
+ * returned instances are projections and never become an authoritative event store.
8
+ */
9
+ export declare function expandRule(base: CalEventData, rule: string | undefined, win: CalRange): CalEventData[];
10
+ /** Expand a list of (base, rule) pairs into all instances within the window, sorted by start. */
11
+ export declare function expandEvents(items: {
12
+ event: CalEventData;
13
+ rule?: string;
14
+ }[], win: CalRange): CalEventData[];
@@ -0,0 +1,60 @@
1
+ var _a, _b;
2
+ import * as rruleModule from 'rrule';
3
+ // rrule publishes ESM metadata over a CommonJS main. Vite exposes named exports
4
+ // in its browser prebundle but only `default` in Node SSR, so normalize the
5
+ // namespace without requiring either export form statically.
6
+ const rruleApi = rruleModule;
7
+ const rrulestr = (_a = rruleApi.rrulestr) !== null && _a !== void 0 ? _a : (_b = rruleApi.default) === null || _b === void 0 ? void 0 : _b.rrulestr;
8
+ if (!rrulestr) {
9
+ throw new Error('rrule package does not expose rrulestr');
10
+ }
11
+ function overlaps(start, end, win) {
12
+ return start < win.end && end > win.start;
13
+ }
14
+ function formatUtcRecurrenceDate(date) {
15
+ return date.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}Z$/, 'Z');
16
+ }
17
+ function withDtstart(rule, start) {
18
+ return /^DTSTART(?:;|:)/im.test(rule)
19
+ ? rule
20
+ : `DTSTART:${formatUtcRecurrenceDate(start)}\n${rule}`;
21
+ }
22
+ /**
23
+ * Expand one graph-projected base event into instances overlapping `win`.
24
+ *
25
+ * `rule` accepts an RRULE value (`FREQ=...`), a prefixed `RRULE:` line, or an iCalendar recurrence
26
+ * fragment containing DTSTART/RRULE/RDATE/EXDATE lines. Expansion remains a bounded view operation; the
27
+ * returned instances are projections and never become an authoritative event store.
28
+ */
29
+ export function expandRule(base, rule, win) {
30
+ if (!rule)
31
+ return overlaps(base.start, base.end, win) ? [base] : [];
32
+ const duration = base.end.getTime() - base.start.getTime();
33
+ if (!Number.isFinite(duration) || duration < 0) {
34
+ throw new RangeError(`Calendar event ${base.id} has an invalid interval`);
35
+ }
36
+ if (!(win.start < win.end)) {
37
+ throw new RangeError('Calendar recurrence window must end after it starts');
38
+ }
39
+ const recurrence = rrulestr(withDtstart(rule, base.start), {
40
+ forceset: true,
41
+ unfold: true,
42
+ });
43
+ // An occurrence may start before the visible window and still overlap it. Query from one event duration
44
+ // before the window, then enforce the calendar's half-open overlap contract below.
45
+ const queryStart = new Date(win.start.getTime() - duration);
46
+ return recurrence
47
+ .between(queryStart, win.end, true)
48
+ .map((occurrenceStart) => {
49
+ const start = new Date(occurrenceStart);
50
+ const end = new Date(start.getTime() + duration);
51
+ return { ...base, id: `${base.id}@${start.toISOString()}`, start, end, recurringInstance: true };
52
+ })
53
+ .filter(({ start, end }) => overlaps(start, end, win));
54
+ }
55
+ /** Expand a list of (base, rule) pairs into all instances within the window, sorted by start. */
56
+ export function expandEvents(items, win) {
57
+ const all = items.flatMap(({ event, rule }) => expandRule(event, rule, win));
58
+ return all.sort((a, b) => a.start.getTime() - b.start.getTime());
59
+ }
60
+ //# sourceMappingURL=recurrence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"recurrence.js","sourceRoot":"","sources":["../../src/recurrence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ export interface RefreshBus {
2
+ ping(): void;
3
+ subscribe(fn: () => void): () => void;
4
+ version(): number;
5
+ }
6
+ export declare function createRefreshBus(): RefreshBus;
7
+ /** Subscribe a component to a bus; returns the current version (changes on every ping → re-render/refetch). */
8
+ export declare function useRefreshVersion(bus: RefreshBus): number;
9
+ /** App-wide compatibility bus — a domain's committed-change adapter pings this. */
10
+ export declare const calendarBus: RefreshBus;
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ export function createRefreshBus() {
3
+ let v = 0;
4
+ const subs = new Set();
5
+ return {
6
+ ping() {
7
+ v++;
8
+ subs.forEach((fn) => fn());
9
+ },
10
+ subscribe(fn) {
11
+ subs.add(fn);
12
+ return () => subs.delete(fn);
13
+ },
14
+ version() {
15
+ return v;
16
+ },
17
+ };
18
+ }
19
+ /** Subscribe a component to a bus; returns the current version (changes on every ping → re-render/refetch). */
20
+ export function useRefreshVersion(bus) {
21
+ return React.useSyncExternalStore((cb) => bus.subscribe(cb), () => bus.version(), () => bus.version());
22
+ }
23
+ /** App-wide compatibility bus — a domain's committed-change adapter pings this. */
24
+ export const calendarBus = createRefreshBus();
25
+ //# sourceMappingURL=refreshBus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refreshBus.js","sourceRoot":"","sources":["../../src/refreshBus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAY1B,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,MAAM,IAAI,GAAG,IAAI,GAAG,EAAc,CAAC;IACnC,OAAO;QACL,IAAI;YACF,CAAC,EAAE,CAAC;YACJ,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QAC7B,CAAC;QACD,SAAS,CAAC,EAAE;YACV,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACb,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO;YACL,OAAO,CAAC,CAAC;QACX,CAAC;KACF,CAAC;AACJ,CAAC;AAED,+GAA+G;AAC/G,MAAM,UAAU,iBAAiB,CAAC,GAAe;IAC/C,OAAO,KAAK,CAAC,oBAAoB,CAC/B,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,EACzB,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,EACnB,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,EAAE,CACpB,CAAC;AACJ,CAAC;AAED,mFAAmF;AACnF,MAAM,CAAC,MAAM,WAAW,GAAe,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ declare module '*.module.css' {
2
+ const classes: Record<string, string>;
3
+ export default classes;
4
+ }
@@ -0,0 +1,49 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "packageName": "@_linked/calendar",
4
+ "shapes": [],
5
+ "components": [
6
+ {
7
+ "componentIri": "https://linked.cm/comp/calendar/Calendar",
8
+ "entries": [
9
+ { "key": "calendar.today", "sourceText": "Today" },
10
+ { "key": "calendar.previous", "sourceText": "Previous" },
11
+ { "key": "calendar.next", "sourceText": "Next" },
12
+ { "key": "calendar.view.month", "sourceText": "Month" },
13
+ { "key": "calendar.view.week", "sourceText": "Week" },
14
+ { "key": "calendar.view.day", "sourceText": "Day" },
15
+ { "key": "calendar.view.agenda", "sourceText": "Agenda" },
16
+ { "key": "calendar.view.resource", "sourceText": "Resources" },
17
+ { "key": "calendar.viewSwitcher", "sourceText": "Calendar view" },
18
+ { "key": "calendar.loading", "sourceText": "Loading…" },
19
+ { "key": "calendar.allDay", "sourceText": "All day" },
20
+ { "key": "calendar.more", "sourceText": "+{count} more", "format": "icu" },
21
+ { "key": "calendar.empty", "sourceText": "Nothing scheduled this month." },
22
+ { "key": "calendar.resource.view", "sourceText": "Schedule by resource" },
23
+ { "key": "calendar.resource.empty", "sourceText": "No resources or unassigned events for this day." },
24
+ { "key": "calendar.resource.columnEmpty", "sourceText": "Nothing assigned" },
25
+ { "key": "calendar.resource.unassigned", "sourceText": "Unassigned" },
26
+ { "key": "calendar.start", "sourceText": "Start" },
27
+ { "key": "calendar.end", "sourceText": "End" },
28
+ { "key": "calendar.save", "sourceText": "Save" },
29
+ { "key": "calendar.cancel", "sourceText": "Cancel" },
30
+ { "key": "calendar.edit", "sourceText": "Edit" },
31
+ { "key": "calendar.eventLocalTime", "sourceText": "{time} · event’s local time", "format": "icu" },
32
+ { "key": "calendar.directions", "sourceText": "Directions" },
33
+ { "key": "calendar.join", "sourceText": "Join" },
34
+ { "key": "calendar.share", "sourceText": "Share" },
35
+ { "key": "calendar.checkIn", "sourceText": "Check in" },
36
+ { "key": "calendar.expand", "sourceText": "Expand ↗" },
37
+ { "key": "calendar.close", "sourceText": "Close calendar details" },
38
+ { "key": "calendar.continued", "sourceText": "continued" },
39
+ { "key": "calendar.confirm", "sourceText": "Confirm" },
40
+ { "key": "calendar.interactionHint", "sourceText": "Tap to open · hold or drag to move across days · drag either edge to resize" }
41
+ ]
42
+ }
43
+ ],
44
+ "labels": [],
45
+ "controlledValues": [],
46
+ "workflowRoles": [],
47
+ "skosConcepts": [],
48
+ "content": []
49
+ }
@@ -0,0 +1,56 @@
1
+ export declare const calendarTranslations: {
2
+ schemaVersion: number;
3
+ packageName: string;
4
+ shapes: never[];
5
+ components: {
6
+ componentIri: string;
7
+ entries: ({
8
+ key: string;
9
+ sourceText: string;
10
+ format?: undefined;
11
+ } | {
12
+ key: string;
13
+ sourceText: string;
14
+ format: string;
15
+ })[];
16
+ }[];
17
+ labels: never[];
18
+ controlledValues: never[];
19
+ workflowRoles: never[];
20
+ skosConcepts: never[];
21
+ content: never[];
22
+ };
23
+ export declare const defaultCalendarText: {
24
+ readonly today: string;
25
+ readonly previous: string;
26
+ readonly next: string;
27
+ readonly month: string;
28
+ readonly week: string;
29
+ readonly day: string;
30
+ readonly agenda: string;
31
+ readonly resource: string;
32
+ readonly viewSwitcher: string;
33
+ readonly loading: string;
34
+ readonly allDay: string;
35
+ readonly more: string;
36
+ readonly empty: string;
37
+ readonly resourceView: string;
38
+ readonly resourceEmpty: string;
39
+ readonly resourceColumnEmpty: string;
40
+ readonly unassigned: string;
41
+ readonly start: string;
42
+ readonly end: string;
43
+ readonly save: string;
44
+ readonly cancel: string;
45
+ readonly edit: string;
46
+ readonly eventLocalTime: string;
47
+ readonly directions: string;
48
+ readonly join: string;
49
+ readonly share: string;
50
+ readonly checkIn: string;
51
+ readonly expand: string;
52
+ readonly close: string;
53
+ readonly continued: string;
54
+ readonly confirm: string;
55
+ readonly interactionHint: string;
56
+ };
@@ -0,0 +1,44 @@
1
+ import calendarTranslationCatalog from './translations/en.json' with { type: 'json' };
2
+ const entries = new Map(calendarTranslationCatalog.components.flatMap((component) => component.entries.map((entry) => [entry.key, entry])));
3
+ function sourceText(key) {
4
+ const entry = entries.get(key);
5
+ if (!entry)
6
+ throw new Error(`Missing @_linked/calendar source translation: ${key}`);
7
+ return entry.sourceText;
8
+ }
9
+ export const calendarTranslations = calendarTranslationCatalog;
10
+ export const defaultCalendarText = {
11
+ today: sourceText('calendar.today'),
12
+ previous: sourceText('calendar.previous'),
13
+ next: sourceText('calendar.next'),
14
+ month: sourceText('calendar.view.month'),
15
+ week: sourceText('calendar.view.week'),
16
+ day: sourceText('calendar.view.day'),
17
+ agenda: sourceText('calendar.view.agenda'),
18
+ resource: sourceText('calendar.view.resource'),
19
+ viewSwitcher: sourceText('calendar.viewSwitcher'),
20
+ loading: sourceText('calendar.loading'),
21
+ allDay: sourceText('calendar.allDay'),
22
+ more: sourceText('calendar.more'),
23
+ empty: sourceText('calendar.empty'),
24
+ resourceView: sourceText('calendar.resource.view'),
25
+ resourceEmpty: sourceText('calendar.resource.empty'),
26
+ resourceColumnEmpty: sourceText('calendar.resource.columnEmpty'),
27
+ unassigned: sourceText('calendar.resource.unassigned'),
28
+ start: sourceText('calendar.start'),
29
+ end: sourceText('calendar.end'),
30
+ save: sourceText('calendar.save'),
31
+ cancel: sourceText('calendar.cancel'),
32
+ edit: sourceText('calendar.edit'),
33
+ eventLocalTime: sourceText('calendar.eventLocalTime'),
34
+ directions: sourceText('calendar.directions'),
35
+ join: sourceText('calendar.join'),
36
+ share: sourceText('calendar.share'),
37
+ checkIn: sourceText('calendar.checkIn'),
38
+ expand: sourceText('calendar.expand'),
39
+ close: sourceText('calendar.close'),
40
+ continued: sourceText('calendar.continued'),
41
+ confirm: sourceText('calendar.confirm'),
42
+ interactionHint: sourceText('calendar.interactionHint'),
43
+ };
44
+ //# sourceMappingURL=translations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"translations.js","sourceRoot":"","sources":["../../src/translations.ts"],"names":[],"mappings":"AAAA,OAAO,0BAA0B,MAAM,wBAAwB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAC;AAQtF,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,0BAA0B,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE,CAC1D,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAU,CAAC,CAC9D,CACF,CAAC;AAEF,SAAS,UAAU,CAAC,GAAW;IAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAA6B,CAAC;IAC3D,IAAI,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,iDAAiD,GAAG,EAAE,CAAC,CAAC;IACpF,OAAO,KAAK,CAAC,UAAU,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAE/D,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC;IACnC,QAAQ,EAAE,UAAU,CAAC,mBAAmB,CAAC;IACzC,IAAI,EAAE,UAAU,CAAC,eAAe,CAAC;IACjC,KAAK,EAAE,UAAU,CAAC,qBAAqB,CAAC;IACxC,IAAI,EAAE,UAAU,CAAC,oBAAoB,CAAC;IACtC,GAAG,EAAE,UAAU,CAAC,mBAAmB,CAAC;IACpC,MAAM,EAAE,UAAU,CAAC,sBAAsB,CAAC;IAC1C,QAAQ,EAAE,UAAU,CAAC,wBAAwB,CAAC;IAC9C,YAAY,EAAE,UAAU,CAAC,uBAAuB,CAAC;IACjD,OAAO,EAAE,UAAU,CAAC,kBAAkB,CAAC;IACvC,MAAM,EAAE,UAAU,CAAC,iBAAiB,CAAC;IACrC,IAAI,EAAE,UAAU,CAAC,eAAe,CAAC;IACjC,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC;IACnC,YAAY,EAAE,UAAU,CAAC,wBAAwB,CAAC;IAClD,aAAa,EAAE,UAAU,CAAC,yBAAyB,CAAC;IACpD,mBAAmB,EAAE,UAAU,CAAC,+BAA+B,CAAC;IAChE,UAAU,EAAE,UAAU,CAAC,8BAA8B,CAAC;IACtD,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC;IACnC,GAAG,EAAE,UAAU,CAAC,cAAc,CAAC;IAC/B,IAAI,EAAE,UAAU,CAAC,eAAe,CAAC;IACjC,MAAM,EAAE,UAAU,CAAC,iBAAiB,CAAC;IACrC,IAAI,EAAE,UAAU,CAAC,eAAe,CAAC;IACjC,cAAc,EAAE,UAAU,CAAC,yBAAyB,CAAC;IACrD,UAAU,EAAE,UAAU,CAAC,qBAAqB,CAAC;IAC7C,IAAI,EAAE,UAAU,CAAC,eAAe,CAAC;IACjC,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC;IACnC,OAAO,EAAE,UAAU,CAAC,kBAAkB,CAAC;IACvC,MAAM,EAAE,UAAU,CAAC,iBAAiB,CAAC;IACrC,KAAK,EAAE,UAAU,CAAC,gBAAgB,CAAC;IACnC,SAAS,EAAE,UAAU,CAAC,oBAAoB,CAAC;IAC3C,OAAO,EAAE,UAAU,CAAC,kBAAkB,CAAC;IACvC,eAAe,EAAE,UAAU,CAAC,0BAA0B,CAAC;CAC/C,CAAC"}
@@ -0,0 +1,97 @@
1
+ export type CalView = 'month' | 'week' | 'day' | 'agenda' | 'resource';
2
+ /** A flat, render-ready calendar item. The host app maps its domain (Serve: Event/Mission) into these. */
3
+ export interface CalEventData {
4
+ id: string;
5
+ title: string;
6
+ start: Date;
7
+ end: Date;
8
+ allDay?: boolean;
9
+ /** the event LOCATION's own IANA timezone (where it physically happens). The calendar displays in the
10
+ * VIEWER's tz; when this differs, the UI surfaces both times. Absent ⇒ no cross-tz heads-up. */
11
+ tz?: string;
12
+ /** opaque category key (Serve passes the cause code) — for grouping/legends */
13
+ colorKey?: string;
14
+ /** display color, already resolved by the host — the FILL of the event. Serve passes the SEMANTIC color
15
+ * (cause-print for missions, type for events) so the color says WHAT the event is. */
16
+ color?: string;
17
+ /** a secondary accent color for the event's edge/marker — a different grouping than the fill. Serve
18
+ * passes the calendar LANE color here, so the fill = topic and the thin edge/dot = which calendar. */
19
+ accent?: string;
20
+ location?: string;
21
+ /** join URL for virtual/hybrid items — powers the popover's "Join" quick action */
22
+ virtualUrl?: string;
23
+ /** host-specific tag, e.g. 'mission' | 'event' — the engine treats it as opaque */
24
+ kind?: string;
25
+ /** Opaque resource projection keys used by the optional resource view. The host maps canonical people,
26
+ * rooms, equipment, roles, or other schedulable resources to these ids; the engine never owns them. */
27
+ resourceIds?: readonly string[];
28
+ /** true for a generated recurrence instance (vs the stored base) */
29
+ recurringInstance?: boolean;
30
+ /** host-computed attention marker — the engine renders a small dot on the card with `label` as its
31
+ * tooltip (Serve sets this for organizers when a shift has coverage gaps or dropouts). Engine-agnostic. */
32
+ alert?: {
33
+ tone: 'warn' | 'danger';
34
+ label: string;
35
+ };
36
+ /** arbitrary host payload (Serve attaches the source id / status) carried through untouched */
37
+ meta?: Record<string, unknown>;
38
+ }
39
+ /** Inclusive-start / exclusive-end window the calendar is showing. */
40
+ export interface CalRange {
41
+ start: Date;
42
+ end: Date;
43
+ }
44
+ /** Selection includes the semantic trigger so overlays can restore keyboard focus after closing. */
45
+ export type CalEventSelect = (event: CalEventData, x: number, y: number, trigger?: HTMLElement) => void;
46
+ /** A toggleable lane in a viewer's calendar (My commitments / Saved / Hosting / a team / an external link). */
47
+ export interface CalLane {
48
+ id: string;
49
+ name: string;
50
+ color: string;
51
+ /** how its events are sourced — commitments | saved | hosting | team | external | custom */
52
+ kind: string;
53
+ /** the on/off toggle */
54
+ visible: boolean;
55
+ /** opaque host key for team lanes (Serve: the Team id) */
56
+ sourceId?: string;
57
+ }
58
+ /** A render-ready schedulable resource column. This is a controlled projection, not a generic RDF Shape. */
59
+ export interface CalResource {
60
+ id: string;
61
+ name: string;
62
+ color?: string;
63
+ /** Opaque host category such as person, room, equipment, or role. */
64
+ kind?: string;
65
+ /** Arbitrary host payload carried through untouched. */
66
+ meta?: Record<string, unknown>;
67
+ }
68
+ /** A pending calendar invite the viewer can accept / reject. */
69
+ export interface CalInvite {
70
+ /** opaque id the host uses to accept/reject (Serve: the RSVP id) */
71
+ inviteId: string;
72
+ subjectId: string;
73
+ title: string;
74
+ when: Date | null;
75
+ kind?: string;
76
+ color: string;
77
+ }
78
+ /** A direction an external calendar can sync. */
79
+ export type CalSyncDirection = 'import' | 'export' | 'both';
80
+ /** A linked external calendar connection (Google / Outlook / Apple / Calendly / ICS), as the engine sees it.
81
+ * The host stores the real connection (+ secret tokens, server-side) and maps it to this. */
82
+ export interface CalConnection {
83
+ id: string;
84
+ provider: string;
85
+ label: string;
86
+ direction: CalSyncDirection | string;
87
+ lastSyncedAt?: string;
88
+ status?: string;
89
+ }
90
+ /** A provider the user can link, with the sync directions it actually supports (per provider capability). */
91
+ export interface CalProviderOption {
92
+ provider: string;
93
+ label: string;
94
+ directions: string[];
95
+ }
96
+ /** The default provider matrix (capabilities from the integration discovery). Hosts may override. */
97
+ export declare const CAL_PROVIDERS: CalProviderOption[];
@@ -0,0 +1,11 @@
1
+ // @_linked/calendar — shape-agnostic contracts. This package knows nothing of Serve Shapes, Causes, or
2
+ // sponsors. A host adapter maps its domain into CalEventData and passes change events back to Shape verbs.
3
+ /** The default provider matrix (capabilities from the integration discovery). Hosts may override. */
4
+ export const CAL_PROVIDERS = [
5
+ { provider: 'google', label: 'Google Calendar', directions: ['both', 'import', 'export'] },
6
+ { provider: 'outlook', label: 'Outlook / Microsoft', directions: ['both', 'import', 'export'] },
7
+ { provider: 'apple', label: 'Apple / iCloud', directions: ['both', 'import', 'export'] },
8
+ { provider: 'calendly', label: 'Calendly', directions: ['import'] }, // scheduling tool → bookings flow IN only
9
+ { provider: 'ics', label: 'ICS / subscription link', directions: ['import'] },
10
+ ];
11
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,uGAAuG;AACvG,2GAA2G;AAiH3G,qGAAqG;AACrG,MAAM,CAAC,MAAM,aAAa,GAAwB;IAChD,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE;IAC1F,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,qBAAqB,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE;IAC/F,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE;IACxF,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,0CAA0C;IAC/G,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,yBAAyB,EAAE,UAAU,EAAE,CAAC,QAAQ,CAAC,EAAE;CAC9E,CAAC"}
@@ -0,0 +1,30 @@
1
+ export interface ZonedParts {
2
+ y: number;
3
+ mo: number;
4
+ d: number;
5
+ hour: number;
6
+ minute: number;
7
+ weekday: number;
8
+ }
9
+ /** Wall-clock parts of an instant in the given tz (or the browser's if omitted). */
10
+ export declare function zonedParts(date: Date, tz?: string): ZonedParts;
11
+ export declare const dayKey: (y: number, mo: number, d: number) => string;
12
+ /** Calendar day (Y-M-D) of an instant, in the given tz. Use to bucket events into day cells. */
13
+ export declare function dayKeyTz(date: Date, tz?: string): string;
14
+ /** Minutes since local midnight (in tz) — for vertical positioning in a time grid. */
15
+ export declare function minutesIntoDay(date: Date, tz?: string): number;
16
+ /** "9:00 AM" in the given tz. */
17
+ export declare function formatTime(date: Date, tz?: string): string;
18
+ /** "9:00 AM PDT" — time + short zone name, for the cross-timezone heads-up. */
19
+ export declare function formatTimeZone(date: Date, tz?: string): string;
20
+ /** The viewer's current IANA tz (browser default). */
21
+ export declare function viewerTz(): string;
22
+ /** True when the event's location tz resolves to a different wall-clock than the viewer's tz for `date`. */
23
+ export declare function isCrossTz(date: Date, eventTz: string | undefined, viewer: string | undefined): boolean;
24
+ /** "YYYY-MM-DDTHH:MM" wall-clock in tz — value for an <input type="datetime-local">. */
25
+ export declare function inputValue(date: Date, tz?: string): string;
26
+ /** Parse an <input type="datetime-local"> value ("YYYY-MM-DDTHH:MM") as wall-clock in tz → instant. */
27
+ export declare function instantFromInput(value: string, tz?: string): Date | null;
28
+ /** Build an absolute instant from a tz day + minutes-into-day. Used when a drag/select produces a new
29
+ * wall-clock time in the display tz and we need the UTC instant to persist. Finds the offset by probing. */
30
+ export declare function instantFromZoned(y: number, mo: number, d: number, minutes: number, tz?: string): Date;
package/lib/esm/tz.js ADDED
@@ -0,0 +1,78 @@
1
+ // Timezone helpers (Intl-based, no deps) — render the calendar in a CHOSEN tz regardless of the
2
+ // browser's, so an LA event shows at 9am for everyone. Generic; → @_linked/calendar.
3
+ const WD = { Sun: 0, Mon: 1, Tue: 2, Wed: 3, Thu: 4, Fri: 5, Sat: 6 };
4
+ /** Wall-clock parts of an instant in the given tz (or the browser's if omitted). */
5
+ export function zonedParts(date, tz) {
6
+ var _a;
7
+ const fmt = new Intl.DateTimeFormat('en-US', { timeZone: tz, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', hour12: false, weekday: 'short' });
8
+ const p = {};
9
+ for (const part of fmt.formatToParts(date))
10
+ p[part.type] = part.value;
11
+ return { y: +p.year, mo: +p.month, d: +p.day, hour: p.hour === '24' ? 0 : +p.hour, minute: +p.minute, weekday: (_a = WD[p.weekday]) !== null && _a !== void 0 ? _a : 0 };
12
+ }
13
+ export const dayKey = (y, mo, d) => `${y}-${String(mo).padStart(2, '0')}-${String(d).padStart(2, '0')}`;
14
+ /** Calendar day (Y-M-D) of an instant, in the given tz. Use to bucket events into day cells. */
15
+ export function dayKeyTz(date, tz) {
16
+ const z = zonedParts(date, tz);
17
+ return dayKey(z.y, z.mo, z.d);
18
+ }
19
+ /** Minutes since local midnight (in tz) — for vertical positioning in a time grid. */
20
+ export function minutesIntoDay(date, tz) {
21
+ const z = zonedParts(date, tz);
22
+ return z.hour * 60 + z.minute;
23
+ }
24
+ /** "9:00 AM" in the given tz. */
25
+ export function formatTime(date, tz) {
26
+ return date.toLocaleTimeString('en-US', { timeZone: tz, hour: 'numeric', minute: '2-digit' });
27
+ }
28
+ /** "9:00 AM PDT" — time + short zone name, for the cross-timezone heads-up. */
29
+ export function formatTimeZone(date, tz) {
30
+ return date.toLocaleTimeString('en-US', { timeZone: tz, hour: 'numeric', minute: '2-digit', timeZoneName: 'short' });
31
+ }
32
+ /** The viewer's current IANA tz (browser default). */
33
+ export function viewerTz() {
34
+ try {
35
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
36
+ }
37
+ catch (_a) {
38
+ return 'UTC';
39
+ }
40
+ }
41
+ /** True when the event's location tz resolves to a different wall-clock than the viewer's tz for `date`. */
42
+ export function isCrossTz(date, eventTz, viewer) {
43
+ if (!eventTz || !viewer || eventTz === viewer)
44
+ return false;
45
+ return formatTime(date, eventTz) !== formatTime(date, viewer) || dayKeyTz(date, eventTz) !== dayKeyTz(date, viewer);
46
+ }
47
+ /** "YYYY-MM-DDTHH:MM" wall-clock in tz — value for an <input type="datetime-local">. */
48
+ export function inputValue(date, tz) {
49
+ const z = zonedParts(date, tz);
50
+ return `${dayKey(z.y, z.mo, z.d)}T${String(z.hour).padStart(2, '0')}:${String(z.minute).padStart(2, '0')}`;
51
+ }
52
+ /** Parse an <input type="datetime-local"> value ("YYYY-MM-DDTHH:MM") as wall-clock in tz → instant. */
53
+ export function instantFromInput(value, tz) {
54
+ const m = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/.exec(value);
55
+ if (!m)
56
+ return null;
57
+ return instantFromZoned(+m[1], +m[2], +m[3], +m[4] * 60 + +m[5], tz);
58
+ }
59
+ /** Build an absolute instant from a tz day + minutes-into-day. Used when a drag/select produces a new
60
+ * wall-clock time in the display tz and we need the UTC instant to persist. Finds the offset by probing. */
61
+ export function instantFromZoned(y, mo, d, minutes, tz) {
62
+ const hour = Math.floor(minutes / 60);
63
+ const minute = minutes % 60;
64
+ // start from a UTC guess, then correct by the tz offset at that moment (two passes handles DST edges)
65
+ let guess = new Date(Date.UTC(y, mo - 1, d, hour, minute));
66
+ for (let i = 0; i < 2; i++) {
67
+ const z = zonedParts(guess, tz);
68
+ const wantUTCminutes = hour * 60 + minute;
69
+ const gotUTCminutes = z.hour * 60 + z.minute;
70
+ const driftDays = (z.y - y) * 366 + (z.mo - mo) * 31 + (z.d - d); // rough sign of day drift
71
+ const deltaMin = (gotUTCminutes - wantUTCminutes) + driftDays * 24 * 60;
72
+ if (deltaMin === 0)
73
+ break;
74
+ guess = new Date(guess.getTime() - deltaMin * 60000);
75
+ }
76
+ return guess;
77
+ }
78
+ //# sourceMappingURL=tz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tz.js","sourceRoot":"","sources":["../../src/tz.ts"],"names":[],"mappings":"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"}