contrib-graphs 0.0.0-stage → 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.
@@ -0,0 +1,344 @@
1
+
2
+ import { CSSProperties, ReactNode } from "react";
3
+ /** Colors of levels 0 to 4. */
4
+ type LevelColors = readonly [string, string, string, string, string];
5
+ /** Colors for one color mode. */
6
+ interface ThemePalette {
7
+ /** Colors of levels 0 to 4. */
8
+ levels: LevelColors;
9
+ text: string;
10
+ muted: string;
11
+ /** Background of variants with their own surface, such as Terminal. */
12
+ surface: string;
13
+ border: string;
14
+ }
15
+ /** A theme: a name plus a light and a dark palette. */
16
+ interface GraphTheme {
17
+ name: string;
18
+ light: ThemePalette;
19
+ dark: ThemePalette;
20
+ }
21
+ /** Built-in themes: `github`, `gitlab`, `frost`, `ember`, `violet` and `mono`. */
22
+ declare const themes: {
23
+ github: {
24
+ name: string;
25
+ light: {
26
+ levels: [string, string, string, string, string];
27
+ text: string;
28
+ muted: string;
29
+ surface: string;
30
+ border: string;
31
+ };
32
+ dark: {
33
+ levels: [string, string, string, string, string];
34
+ text: string;
35
+ muted: string;
36
+ surface: string;
37
+ border: string;
38
+ };
39
+ };
40
+ gitlab: {
41
+ name: string;
42
+ light: {
43
+ levels: [string, string, string, string, string];
44
+ text: string;
45
+ muted: string;
46
+ surface: string;
47
+ border: string;
48
+ };
49
+ dark: {
50
+ surface: string;
51
+ border: string;
52
+ levels: [string, string, string, string, string];
53
+ text: string;
54
+ muted: string;
55
+ };
56
+ };
57
+ frost: {
58
+ name: string;
59
+ light: {
60
+ levels: [string, string, string, string, string];
61
+ text: string;
62
+ muted: string;
63
+ surface: string;
64
+ border: string;
65
+ };
66
+ dark: {
67
+ surface: string;
68
+ border: string;
69
+ text: string;
70
+ muted: string;
71
+ levels: [string, string, string, string, string];
72
+ };
73
+ };
74
+ ember: {
75
+ name: string;
76
+ light: {
77
+ levels: [string, string, string, string, string];
78
+ text: string;
79
+ muted: string;
80
+ surface: string;
81
+ border: string;
82
+ };
83
+ dark: {
84
+ surface: string;
85
+ border: string;
86
+ levels: [string, string, string, string, string];
87
+ text: string;
88
+ muted: string;
89
+ };
90
+ };
91
+ violet: {
92
+ name: string;
93
+ light: {
94
+ levels: [string, string, string, string, string];
95
+ text: string;
96
+ muted: string;
97
+ surface: string;
98
+ border: string;
99
+ };
100
+ dark: {
101
+ surface: string;
102
+ border: string;
103
+ levels: [string, string, string, string, string];
104
+ text: string;
105
+ muted: string;
106
+ };
107
+ };
108
+ mono: {
109
+ name: string;
110
+ light: {
111
+ levels: [string, string, string, string, string];
112
+ text: string;
113
+ muted: string;
114
+ surface: string;
115
+ border: string;
116
+ };
117
+ dark: {
118
+ surface: string;
119
+ border: string;
120
+ levels: [string, string, string, string, string];
121
+ text: string;
122
+ muted: string;
123
+ };
124
+ };
125
+ };
126
+ /** Name of a built-in theme. */
127
+ type ThemeName = keyof typeof themes;
128
+ /** Names of the built-in themes. */
129
+ declare const themeNames: ThemeName[];
130
+ /** Returns the theme object for a preset name or a custom theme; unknown names fall back to `github`. */
131
+ declare function resolveTheme(theme: ThemeName | GraphTheme | undefined): GraphTheme;
132
+ /** Turns a theme into CSS variables (`--cg-l0-light`, `--cg-l0-dark`…); the stylesheet picks light or dark. */
133
+ declare function themeVars(theme: GraphTheme): CSSProperties;
134
+ /** One day of activity. `date` uses the ISO format `YYYY-MM-DD`. */
135
+ interface ContributionDay {
136
+ date: string;
137
+ count: number;
138
+ }
139
+ /** Intensity level from 0 (no activity) to 4 (busiest). */
140
+ type Level = 0 | 1 | 2 | 3 | 4;
141
+ /**
142
+ * How each count maps to a level from 0 to 4.
143
+ * - `quantile`: by quartiles of the active days (like GitHub)
144
+ * - `linear`: proportional to the maximum
145
+ * - `[a, b, c, d]`: minimum count for levels 1, 2, 3 and 4
146
+ */
147
+ type LevelScale = 'quantile' | 'linear' | readonly [number, number, number, number];
148
+ /** `auto` follows `prefers-color-scheme`, or `data-theme="light|dark"` on `<html>`. */
149
+ type ColorMode = 'auto' | 'light' | 'dark';
150
+ /** A day as laid out in the calendar, with its level and position. */
151
+ interface CalendarDay extends ContributionDay {
152
+ level: Level;
153
+ /** Flat index in `calendar.days`. */
154
+ index: number;
155
+ /** Column (week) in the calendar. */
156
+ weekIndex: number;
157
+ /** Row from 0 to 6, relative to `weekStart`. */
158
+ dayIndex: number;
159
+ /** Actual day of the week, 0 = Sunday. */
160
+ weekday: number;
161
+ }
162
+ /** A month label and the week column where it starts. */
163
+ interface MonthLabel {
164
+ label: string;
165
+ weekIndex: number;
166
+ month: number;
167
+ year: number;
168
+ }
169
+ /** The result of `buildCalendar`: a weeks × 7 grid plus totals and month labels. */
170
+ interface Calendar {
171
+ weeks: (CalendarDay | null)[][];
172
+ days: CalendarDay[];
173
+ months: MonthLabel[];
174
+ total: number;
175
+ max: number;
176
+ start: string;
177
+ end: string;
178
+ levelOf: (count: number) => Level;
179
+ }
180
+ /** Props shared by every graph. */
181
+ interface BaseGraphProps {
182
+ /** Days of activity. Missing days count as 0 and duplicate dates are added up. */
183
+ data: ContributionDay[];
184
+ /**
185
+ * A preset name or your own theme object.
186
+ * @default 'github'
187
+ */
188
+ theme?: ThemeName | GraphTheme;
189
+ /**
190
+ * `auto` follows `prefers-color-scheme`, or `data-theme="light|dark"` on `<html>`.
191
+ * @default 'auto'
192
+ */
193
+ colorMode?: ColorMode;
194
+ /**
195
+ * Number of weeks to show.
196
+ * @default 53
197
+ */
198
+ weeks?: number;
199
+ /**
200
+ * Last day of the calendar. When rendering on the server, always pass it:
201
+ * the server and the browser may be on different days.
202
+ * @default today
203
+ */
204
+ endDate?: string | Date;
205
+ /**
206
+ * First day of each column: 0 = Sunday, 1 = Monday.
207
+ * @default 0
208
+ */
209
+ weekStart?: 0 | 1;
210
+ /**
211
+ * How counts map to the five color levels.
212
+ * @default 'quantile'
213
+ */
214
+ scale?: LevelScale;
215
+ /**
216
+ * Locale for dates and numbers. Fixed by default so server and client HTML match.
217
+ * @default 'en'
218
+ */
219
+ locale?: string;
220
+ /**
221
+ * Staggered entry animation. Turned off with `prefers-reduced-motion`.
222
+ * @default false
223
+ */
224
+ animate?: boolean;
225
+ /**
226
+ * Show the Less–More legend.
227
+ * @default true
228
+ */
229
+ showLegend?: boolean;
230
+ /**
231
+ * Show the header with the total.
232
+ * @default true
233
+ */
234
+ showTotal?: boolean;
235
+ /**
236
+ * Replaces the whole header text.
237
+ * @default '{total} contributions in the last year'
238
+ */
239
+ title?: ReactNode;
240
+ /**
241
+ * Singular and plural of the unit being counted.
242
+ * @default ['contribution', 'contributions']
243
+ */
244
+ unit?: readonly [string, string];
245
+ /**
246
+ * Text after the total in the header. Can be a function of the weeks shown.
247
+ * @default 'in the last year' (52+ weeks), otherwise 'in the last {weeks} weeks'
248
+ */
249
+ periodLabel?: string | ((weeks: number) => string);
250
+ /**
251
+ * Labels at both ends of the legend.
252
+ * @default ['Less', 'More']
253
+ */
254
+ legendLabels?: readonly [string, string];
255
+ /** Called when a day is clicked, or with Enter or Space while it is focused. */
256
+ onDayClick?: (day: CalendarDay) => void;
257
+ /** Extra class name for the root element. */
258
+ className?: string;
259
+ /** Inline styles for the root element. Theme CSS variables can be overridden here. */
260
+ style?: CSSProperties;
261
+ /**
262
+ * Accessible name of the graph.
263
+ * @default a summary with the total and the date range
264
+ */
265
+ 'aria-label'?: string;
266
+ }
267
+ /** Returns a function that maps a count to a level from 0 to 4 for the given counts and scale. */
268
+ declare function makeLevelFn(counts: readonly number[], scale?: LevelScale): (n: number) => Level;
269
+ /** Options of `buildCalendar`. They match the graph props of the same name. */
270
+ interface CalendarOptions {
271
+ weeks?: number;
272
+ endDate?: string | Date;
273
+ weekStart?: 0 | 1;
274
+ scale?: LevelScale;
275
+ locale?: string;
276
+ }
277
+ /** Lays out days as a weeks × 7 grid with levels, totals and month labels. Dates are handled in UTC. */
278
+ declare function buildCalendar(data: readonly ContributionDay[], opts?: CalendarOptions): Calendar;
279
+ /** Keeps the last `n` weeks. Levels come from the full calendar, so cropping doesn't change colors. */
280
+ declare function cropCalendar(cal: Calendar, n: number, locale?: string): Calendar;
281
+ /** Totals and streaks of a list of days. */
282
+ interface GraphStats {
283
+ total: number;
284
+ activeDays: number;
285
+ best: CalendarDay | null;
286
+ longestStreak: number;
287
+ currentStreak: number;
288
+ }
289
+ /** Total, active days, best day, longest streak and current streak. A current streak isn't broken by a quiet today. */
290
+ declare function computeStats(days: readonly CalendarDay[]): GraphStats;
291
+ /** Formats an ISO date with `Intl`, in UTC so the day never shifts. */
292
+ declare function formatDate(iso: string, locale?: string, opts?: Intl.DateTimeFormatOptions): string;
293
+ /** Shape of the generated activity. */
294
+ type SampleProfile = 'steady' | 'burst' | 'weekend' | 'sparse';
295
+ /** Available sample profiles with a short English label. */
296
+ declare const sampleProfiles: Record<SampleProfile, string>;
297
+ /** Deterministic sample data: the same seed always gives the same days. Useful for demos and tests. */
298
+ declare function generateSampleData({ seed, profile, days, endDate }?: {
299
+ seed?: number;
300
+ profile?: SampleProfile;
301
+ days?: number;
302
+ endDate?: Date;
303
+ }): ContributionDay[];
304
+ /**
305
+ * GitHub GraphQL query for the contribution calendar. It needs a token even
306
+ * for public data, so run it on the server and never send the token to the browser.
307
+ */
308
+ declare const GITHUB_CONTRIBUTIONS_QUERY = "\n query ($login: String!, $from: DateTime, $to: DateTime) {\n user(login: $login) {\n contributionsCollection(from: $from, to: $to) {\n contributionCalendar {\n totalContributions\n weeks { contributionDays { date contributionCount } }\n }\n }\n }\n }\n";
309
+ /** Shape of the GraphQL response read by `fromGitHub`. */
310
+ interface GitHubCalendarResponse {
311
+ data?: {
312
+ user?: {
313
+ contributionsCollection?: {
314
+ contributionCalendar?: {
315
+ weeks: {
316
+ contributionDays: {
317
+ date: string;
318
+ contributionCount: number;
319
+ }[];
320
+ }[];
321
+ };
322
+ };
323
+ } | null;
324
+ };
325
+ }
326
+ /** Converts a GitHub GraphQL response into `{ date, count }` days. */
327
+ declare function fromGitHub(res: GitHubCalendarResponse): ContributionDay[];
328
+ /**
329
+ * Fetches the last year of contributions from GitHub's GraphQL API. Server only (Node 18+, Deno, Bun, edge runtimes).
330
+ * A classic token with `read:user` includes private contributions.
331
+ */
332
+ declare function fetchGitHubContributions(login: string, token: string): Promise<ContributionDay[]>;
333
+ /** Converts GitLab's `{ "2026-03-01": 4 }` calendar into `{ date, count }` days. */
334
+ declare function fromGitLab(json: Record<string, number>): ContributionDay[];
335
+ /**
336
+ * Fetches a GitLab user's calendar. The endpoint is public but sends no CORS headers,
337
+ * so call it from the server or at build time. Pass `baseUrl` for self-hosted instances.
338
+ */
339
+ declare function fetchGitLabContributions(username: string, baseUrl?: string): Promise<ContributionDay[]>;
340
+ /** Counts occurrences per day: blog posts, workouts, local commits… Strings are sliced to the date; `Date` objects use the local date. */
341
+ declare function fromDates(dates: readonly (string | Date)[]): ContributionDay[];
342
+ /** Adds several sources day by day (for example GitHub plus GitLab), sorted by date. */
343
+ declare function mergeSources(...sources: readonly ContributionDay[][]): ContributionDay[];
344
+ export { ThemePalette as A, ContributionDay as C, GraphTheme as D, MonthLabel as E, themeNames as M, themeVars as N, LevelColors as O, themes as P, ColorMode as S, LevelScale as T, formatDate as _, fromDates as a, Calendar as b, mergeSources as c, sampleProfiles as d, CalendarOptions as f, cropCalendar as g, computeStats as h, fetchGitLabContributions as i, resolveTheme as j, ThemeName as k, SampleProfile as l, buildCalendar as m, GitHubCalendarResponse as n, fromGitHub as o, GraphStats as p, fetchGitHubContributions as r, fromGitLab as s, GITHUB_CONTRIBUTIONS_QUERY as t, generateSampleData as u, makeLevelFn as v, Level as w, CalendarDay as x, BaseGraphProps as y };