@pearpages/heatmap 0.1.1 → 0.1.3

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.
package/README.md CHANGED
@@ -1,2 +1,11 @@
1
1
  # Heatmap
2
2
 
3
+ ## Getting started
4
+
5
+ When using the library, make sure to import the CSS file from the `dist` folder:
6
+
7
+ ```tsx
8
+ import '@pearpages/heatmap/dist/index.css';
9
+ ```
10
+
11
+ This ensures that all necessary styles are applied to the heatmap components.
package/dist/index.css CHANGED
@@ -1,11 +1,11 @@
1
1
  /* src/ContributionHeatmap/index.scss */
2
- // ContributionHeatmap.scss // GitHub-style contribution heatmap with BEM methodology .contribution-heatmap {
3
- // Component variables --day-size: 12px;
2
+ .contribution-heatmap {
3
+ --day-size: 12px;
4
4
  --day-gap: 2px;
5
5
  --border-radius: 6px;
6
6
  --transition: all 0.2s ease;
7
7
  --shadow-color: rgba(0, 0, 0, 0.1);
8
- // Color scheme - GitHub-inspired --color-bg: #ffffff;
8
+ --color-bg: #ffffff;
9
9
  --color-border: #e1e4e8;
10
10
  --color-text: #24292f;
11
11
  --color-text-muted: #656d76;
@@ -14,7 +14,9 @@
14
14
  --color-level-2: #40c463;
15
15
  --color-level-3: #30a14e;
16
16
  --color-level-4: #216e39;
17
- // Dark mode support @media (prefers-color-scheme: dark) {
17
+ }
18
+ @media (prefers-color-scheme: dark) {
19
+ .contribution-heatmap {
18
20
  --color-bg: #0d1117;
19
21
  --color-border: #30363d;
20
22
  --color-text: #f0f6fc;
@@ -25,6 +27,8 @@
25
27
  --color-level-3: #26a641;
26
28
  --color-level-4: #39d353;
27
29
  }
30
+ }
31
+ .contribution-heatmap {
28
32
  background: var(--color-bg);
29
33
  border-radius: var(--border-radius);
30
34
  padding: 20px;
@@ -33,256 +37,286 @@
33
37
  transition: var(--transition);
34
38
  max-width: 100%;
35
39
  overflow-x: auto;
36
- &__month-header {
37
- color: var(--color-text-muted);
38
- }
39
- // Hover effect for the entire component &:hover {
40
- box-shadow: 0 4px 16px var(--shadow-color);
41
- }
42
- // Mobile responsiveness @media (max-width: 768px) {
40
+ }
41
+ .contribution-heatmap__month-header {
42
+ color: var(--color-text-muted);
43
+ }
44
+ .contribution-heatmap:hover {
45
+ box-shadow: 0 4px 16px var(--shadow-color);
46
+ }
47
+ @media (max-width: 768px) {
48
+ .contribution-heatmap {
43
49
  --day-size: 10px;
44
50
  --day-gap: 1px;
45
51
  padding: 15px;
46
- // Reduce padding on mobile &__container {
47
- padding: 0;
48
- }
49
52
  }
50
- @media (max-width: 480px) {
53
+ .contribution-heatmap__container {
54
+ padding: 0;
55
+ }
56
+ }
57
+ @media (max-width: 480px) {
58
+ .contribution-heatmap {
51
59
  --day-size: 8px;
52
60
  --day-gap: 1px;
53
61
  padding: 10px;
54
62
  }
55
- // Header section &__header {
56
- margin-bottom: 16px;
57
- text-align: center;
58
- @media (max-width: 768px) {
59
- margin-bottom: 12px;
60
- }
61
- }
62
- &__title {
63
- color: var(--color-text);
64
- font-size: 18px;
65
- font-weight: 600;
66
- margin: 0 0 4px 0;
67
- letter-spacing: -0.2px;
68
- @media (max-width: 768px) {
69
- font-size: 16px;
70
- }
71
- }
72
- &__subtitle {
73
- color: var(--color-text-muted);
74
- font-size: 14px;
75
- margin: 0;
76
- font-weight: 400;
77
- @media (max-width: 768px) {
78
- font-size: 12px;
79
- }
80
- }
81
- // Main container &__container {
82
- display: grid;
83
- gap: 8px;
84
- padding: 16px;
85
- background: var(--color-bg);
86
- border-radius: calc(var(--border-radius) - 2px);
87
- position: relative;
88
- grid-template-areas: ". months" "days grid";
89
- grid-template-columns: 30px 1fr;
90
- grid-template-rows: auto 1fr;
91
- @media (max-width: 768px) {
92
- padding: 8px;
93
- gap: 6px;
94
- grid-template-columns: 20px 1fr;
95
- }
63
+ }
64
+ .contribution-heatmap__header {
65
+ margin-bottom: 16px;
66
+ text-align: center;
67
+ }
68
+ @media (max-width: 768px) {
69
+ .contribution-heatmap__header {
70
+ margin-bottom: 12px;
96
71
  }
97
- // Month labels &__months {
98
- grid-area: months;
99
- display: flex;
100
- gap: var(--day-gap);
101
- margin-bottom: 4px;
102
- @media (max-width: 768px) {
103
- margin-bottom: 2px;
104
- }
72
+ }
73
+ .contribution-heatmap__title {
74
+ color: var(--color-text);
75
+ font-size: 18px;
76
+ font-weight: 600;
77
+ margin: 0 0 4px 0;
78
+ letter-spacing: -0.2px;
79
+ }
80
+ @media (max-width: 768px) {
81
+ .contribution-heatmap__title {
82
+ font-size: 16px;
105
83
  }
106
- &__month {
107
- color: var(--color-text-muted);
84
+ }
85
+ .contribution-heatmap__subtitle {
86
+ color: var(--color-text-muted);
87
+ font-size: 14px;
88
+ margin: 0;
89
+ font-weight: 400;
90
+ }
91
+ @media (max-width: 768px) {
92
+ .contribution-heatmap__subtitle {
108
93
  font-size: 12px;
109
- font-weight: 500;
110
- text-align: left;
111
- padding: 0 2px;
112
- flex-grow: 0;
113
- flex-shrink: 0;
114
- @media (max-width: 768px) {
115
- font-size: 10px;
116
- }
117
- @media (max-width: 480px) {
118
- font-size: 8px;
119
- }
120
94
  }
121
- // Day labels (Mon, Tue, etc.) &__days {
122
- grid-area: days;
123
- display: flex;
124
- flex-direction: column;
125
- gap: var(--day-gap);
126
- align-items: flex-end;
127
- justify-content: flex-start;
128
- padding-right: 4px;
129
- @media (max-width: 768px) {
130
- padding-right: 2px;
131
- }
95
+ }
96
+ .contribution-heatmap__container {
97
+ display: grid;
98
+ gap: 8px;
99
+ padding: 16px;
100
+ background: var(--color-bg);
101
+ border-radius: calc(var(--border-radius) - 2px);
102
+ position: relative;
103
+ grid-template-areas: ". months" "days grid";
104
+ grid-template-columns: 30px 1fr;
105
+ grid-template-rows: auto 1fr;
106
+ }
107
+ @media (max-width: 768px) {
108
+ .contribution-heatmap__container {
109
+ padding: 8px;
110
+ gap: 6px;
111
+ grid-template-columns: 20px 1fr;
132
112
  }
133
- &__day-label {
134
- color: var(--color-text-muted);
113
+ }
114
+ .contribution-heatmap__months {
115
+ grid-area: months;
116
+ display: flex;
117
+ gap: var(--day-gap);
118
+ margin-bottom: 4px;
119
+ }
120
+ @media (max-width: 768px) {
121
+ .contribution-heatmap__months {
122
+ margin-bottom: 2px;
123
+ }
124
+ }
125
+ .contribution-heatmap__month {
126
+ color: var(--color-text-muted);
127
+ font-size: 12px;
128
+ font-weight: 500;
129
+ text-align: left;
130
+ padding: 0 2px;
131
+ flex-grow: 0;
132
+ flex-shrink: 0;
133
+ }
134
+ @media (max-width: 768px) {
135
+ .contribution-heatmap__month {
135
136
  font-size: 10px;
136
- font-weight: 500;
137
- height: var(--day-size);
138
- display: flex;
139
- align-items: center;
140
- width: 24px;
141
- @media (max-width: 768px) {
142
- font-size: 8px;
143
- width: 16px;
144
- }
145
- @media (max-width: 480px) {
146
- font-size: 7px;
147
- width: 12px;
148
- }
149
137
  }
150
- // Main grid &__grid {
151
- grid-area: grid;
152
- display: flex;
153
- gap: var(--day-gap);
154
- overflow-x: auto;
155
- scroll-behavior: smooth;
156
- // Custom scrollbar &::-webkit-scrollbar {
157
- height: 4px;
158
- }
159
- &::-webkit-scrollbar-track {
160
- background: var(--color-border);
161
- border-radius: 2px;
162
- }
163
- &::-webkit-scrollbar-thumb {
164
- background: var(--color-level-2);
165
- border-radius: 2px;
166
- &:hover {
167
- background: var(--color-level-3);
168
- }
169
- }
138
+ }
139
+ @media (max-width: 480px) {
140
+ .contribution-heatmap__month {
141
+ font-size: 8px;
170
142
  }
171
- // Week column &__week {
172
- display: flex;
173
- flex-direction: column;
174
- gap: var(--day-gap);
175
- min-width: var(--day-size);
143
+ }
144
+ .contribution-heatmap__days {
145
+ grid-area: days;
146
+ display: flex;
147
+ flex-direction: column;
148
+ gap: var(--day-gap);
149
+ align-items: flex-end;
150
+ justify-content: flex-start;
151
+ padding-right: 4px;
152
+ }
153
+ @media (max-width: 768px) {
154
+ .contribution-heatmap__days {
155
+ padding-right: 2px;
176
156
  }
177
- // Individual day square &__day {
178
- width: var(--day-size);
179
- height: var(--day-size);
180
- border-radius: 2px;
181
- cursor: pointer;
182
- transition: var(--transition);
183
- position: relative;
184
- border: 1px solid transparent;
185
- // Contribution levels &--level-0 {
186
- background-color: var(--color-level-0);
187
- &:hover {
188
- background-color: var(--color-level-1);
189
- border-color: var(--color-level-2);
190
- }
191
- }
192
- &--level-1 {
193
- background-color: var(--color-level-1);
194
- &:hover {
195
- background-color: var(--color-level-2);
196
- border-color: var(--color-level-3);
197
- }
198
- }
199
- &--level-2 {
200
- background-color: var(--color-level-2);
201
- &:hover {
202
- background-color: var(--color-level-3);
203
- border-color: var(--color-level-4);
204
- }
205
- }
206
- &--level-3 {
207
- background-color: var(--color-level-3);
208
- &:hover {
209
- background-color: var(--color-level-4);
210
- border-color: var(--color-level-4);
211
- }
212
- }
213
- &--level-4 {
214
- background-color: var(--color-level-4);
215
- &:hover {
216
- filter: brightness(1.1);
217
- border-color: var(--color-level-4);
218
- }
219
- }
220
- // Hover effects &:hover {
221
- transform: scale(1.2);
222
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
223
- z-index: 10;
224
- border-radius: 3px;
225
- }
226
- // Focus styles for accessibility &:focus-visible {
227
- outline: 2px solid var(--color-level-3);
228
- outline-offset: 2px;
229
- }
157
+ }
158
+ .contribution-heatmap__day-label {
159
+ color: var(--color-text-muted);
160
+ font-size: 10px;
161
+ font-weight: 500;
162
+ height: var(--day-size);
163
+ display: flex;
164
+ align-items: center;
165
+ width: 24px;
166
+ }
167
+ @media (max-width: 768px) {
168
+ .contribution-heatmap__day-label {
169
+ font-size: 8px;
170
+ width: 16px;
230
171
  }
231
- // Legend &__legend {
232
- display: flex;
233
- align-items: center;
234
- justify-content: center;
235
- gap: 4px;
236
- margin-top: 12px;
237
- flex-wrap: wrap;
238
- @media (max-width: 768px) {
239
- gap: 3px;
240
- margin-top: 8px;
241
- }
172
+ }
173
+ @media (max-width: 480px) {
174
+ .contribution-heatmap__day-label {
175
+ font-size: 7px;
176
+ width: 12px;
242
177
  }
243
- &__legend-text {
244
- color: var(--color-text-muted);
245
- font-size: 12px;
246
- font-weight: 500;
247
- margin: 0 4px;
248
- @media (max-width: 768px) {
249
- font-size: 10px;
250
- margin: 0 2px;
251
- }
178
+ }
179
+ .contribution-heatmap__grid {
180
+ grid-area: grid;
181
+ display: flex;
182
+ gap: var(--day-gap);
183
+ overflow-x: auto;
184
+ scroll-behavior: smooth;
185
+ }
186
+ .contribution-heatmap__grid::-webkit-scrollbar {
187
+ height: 4px;
188
+ }
189
+ .contribution-heatmap__grid::-webkit-scrollbar-track {
190
+ background: var(--color-border);
191
+ border-radius: 2px;
192
+ }
193
+ .contribution-heatmap__grid::-webkit-scrollbar-thumb {
194
+ background: var(--color-level-2);
195
+ border-radius: 2px;
196
+ }
197
+ .contribution-heatmap__grid::-webkit-scrollbar-thumb:hover {
198
+ background: var(--color-level-3);
199
+ }
200
+ .contribution-heatmap__week {
201
+ display: flex;
202
+ flex-direction: column;
203
+ gap: var(--day-gap);
204
+ min-width: var(--day-size);
205
+ }
206
+ .contribution-heatmap__day {
207
+ width: var(--day-size);
208
+ height: var(--day-size);
209
+ border-radius: 2px;
210
+ cursor: pointer;
211
+ transition: var(--transition);
212
+ position: relative;
213
+ border: 1px solid transparent;
214
+ }
215
+ .contribution-heatmap__day--level-0 {
216
+ background-color: var(--color-level-0);
217
+ }
218
+ .contribution-heatmap__day--level-0:hover {
219
+ background-color: var(--color-level-1);
220
+ border-color: var(--color-level-2);
221
+ }
222
+ .contribution-heatmap__day--level-1 {
223
+ background-color: var(--color-level-1);
224
+ }
225
+ .contribution-heatmap__day--level-1:hover {
226
+ background-color: var(--color-level-2);
227
+ border-color: var(--color-level-3);
228
+ }
229
+ .contribution-heatmap__day--level-2 {
230
+ background-color: var(--color-level-2);
231
+ }
232
+ .contribution-heatmap__day--level-2:hover {
233
+ background-color: var(--color-level-3);
234
+ border-color: var(--color-level-4);
235
+ }
236
+ .contribution-heatmap__day--level-3 {
237
+ background-color: var(--color-level-3);
238
+ }
239
+ .contribution-heatmap__day--level-3:hover {
240
+ background-color: var(--color-level-4);
241
+ border-color: var(--color-level-4);
242
+ }
243
+ .contribution-heatmap__day--level-4 {
244
+ background-color: var(--color-level-4);
245
+ }
246
+ .contribution-heatmap__day--level-4:hover {
247
+ filter: brightness(1.1);
248
+ border-color: var(--color-level-4);
249
+ }
250
+ .contribution-heatmap__day:hover {
251
+ transform: scale(1.2);
252
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
253
+ z-index: 10;
254
+ border-radius: 3px;
255
+ }
256
+ .contribution-heatmap__day:focus-visible {
257
+ outline: 2px solid var(--color-level-3);
258
+ outline-offset: 2px;
259
+ }
260
+ .contribution-heatmap__legend {
261
+ display: flex;
262
+ align-items: center;
263
+ justify-content: center;
264
+ gap: 4px;
265
+ margin-top: 12px;
266
+ flex-wrap: wrap;
267
+ }
268
+ @media (max-width: 768px) {
269
+ .contribution-heatmap__legend {
270
+ gap: 3px;
271
+ margin-top: 8px;
252
272
  }
253
- &__legend-item {
254
- width: 12px;
255
- height: 12px;
256
- border-radius: 2px;
257
- cursor: help;
258
- transition: var(--transition);
259
- border: 1px solid var(--color-border);
260
- @media (max-width: 768px) {
261
- width: 10px;
262
- height: 10px;
263
- }
264
- &:hover {
265
- transform: scale(1.2);
266
- border-color: var(--color-text-muted);
267
- }
268
- &--level-0 {
269
- background-color: var(--color-level-0);
270
- }
271
- &--level-1 {
272
- background-color: var(--color-level-1);
273
- }
274
- &--level-2 {
275
- background-color: var(--color-level-2);
276
- }
277
- &--level-3 {
278
- background-color: var(--color-level-3);
279
- }
280
- &--level-4 {
281
- background-color: var(--color-level-4);
282
- }
273
+ }
274
+ .contribution-heatmap__legend-text {
275
+ color: var(--color-text-muted);
276
+ font-size: 12px;
277
+ font-weight: 500;
278
+ margin: 0 4px;
279
+ }
280
+ @media (max-width: 768px) {
281
+ .contribution-heatmap__legend-text {
282
+ font-size: 10px;
283
+ margin: 0 2px;
284
+ }
285
+ }
286
+ .contribution-heatmap__legend-item {
287
+ width: 12px;
288
+ height: 12px;
289
+ border-radius: 2px;
290
+ cursor: help;
291
+ transition: var(--transition);
292
+ border: 1px solid var(--color-border);
293
+ }
294
+ @media (max-width: 768px) {
295
+ .contribution-heatmap__legend-item {
296
+ width: 10px;
297
+ height: 10px;
283
298
  }
284
299
  }
285
- // Animation for initial load @keyframes fadeInUp {
300
+ .contribution-heatmap__legend-item:hover {
301
+ transform: scale(1.2);
302
+ border-color: var(--color-text-muted);
303
+ }
304
+ .contribution-heatmap__legend-item--level-0 {
305
+ background-color: var(--color-level-0);
306
+ }
307
+ .contribution-heatmap__legend-item--level-1 {
308
+ background-color: var(--color-level-1);
309
+ }
310
+ .contribution-heatmap__legend-item--level-2 {
311
+ background-color: var(--color-level-2);
312
+ }
313
+ .contribution-heatmap__legend-item--level-3 {
314
+ background-color: var(--color-level-3);
315
+ }
316
+ .contribution-heatmap__legend-item--level-4 {
317
+ background-color: var(--color-level-4);
318
+ }
319
+ @keyframes fadeInUp {
286
320
  from {
287
321
  opacity: 0;
288
322
  transform: translateY(20px);
@@ -294,109 +328,117 @@
294
328
  }
295
329
  .contribution-heatmap {
296
330
  animation: fadeInUp 0.6s ease-out;
297
- &__day {
298
- animation: fadeInUp 0.3s ease-out;
299
- animation-delay: var(--animation-delay, 0s);
300
- animation-fill-mode: both;
301
- }
302
331
  }
303
- // Utilities for different themes .contribution-heatmap {
304
- // Ocean theme &--ocean {
305
- --color-level-0: #e6f3ff;
306
- --color-level-1: #b3daff;
307
- --color-level-2: #66b3ff;
308
- --color-level-3: #1a8cff;
309
- --color-level-4: #0066cc;
310
- }
311
- // Sunset theme &--sunset {
312
- --color-level-0: #fff2e6;
313
- --color-level-1: #ffcc99;
314
- --color-level-2: #ff9933;
315
- --color-level-3: #ff6600;
316
- --color-level-4: #cc3300;
317
- }
318
- // Purple theme &--purple {
319
- --color-level-0: #f3e6ff;
320
- --color-level-1: #d9b3ff;
321
- --color-level-2: #b366ff;
322
- --color-level-3: #8a1aff;
323
- --color-level-4: #6600cc;
324
- }
332
+ .contribution-heatmap__day {
333
+ animation: fadeInUp 0.3s ease-out;
334
+ animation-delay: var(--animation-delay, 0s);
335
+ animation-fill-mode: both;
336
+ }
337
+ .contribution-heatmap--ocean {
338
+ --color-level-0: #e6f3ff;
339
+ --color-level-1: #b3daff;
340
+ --color-level-2: #66b3ff;
341
+ --color-level-3: #1a8cff;
342
+ --color-level-4: #0066cc;
343
+ }
344
+ .contribution-heatmap--sunset {
345
+ --color-level-0: #fff2e6;
346
+ --color-level-1: #ffcc99;
347
+ --color-level-2: #ff9933;
348
+ --color-level-3: #ff6600;
349
+ --color-level-4: #cc3300;
350
+ }
351
+ .contribution-heatmap--purple {
352
+ --color-level-0: #f3e6ff;
353
+ --color-level-1: #d9b3ff;
354
+ --color-level-2: #b366ff;
355
+ --color-level-3: #8a1aff;
356
+ --color-level-4: #6600cc;
325
357
  }
326
358
 
327
359
  /* src/Example/index.scss */
328
- .example {
329
- &__controls {
330
- background: rgba(255, 255, 255, 0.95);
331
- backdrop-filter: blur(10px);
332
- padding: 24px;
333
- border-radius: 16px;
334
- margin-bottom: 30px;
335
- box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
336
- border: 1px solid rgba(255, 255, 255, 0.2);
337
- @media (max-width: 768px) {
338
- padding: 20px;
339
- margin-bottom: 20px;
340
- border-radius: 12px;
341
- }
360
+ .example__controls {
361
+ background: rgba(255, 255, 255, 0.95);
362
+ backdrop-filter: blur(10px);
363
+ padding: 24px;
364
+ border-radius: 16px;
365
+ margin-bottom: 30px;
366
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
367
+ border: 1px solid rgba(255, 255, 255, 0.2);
368
+ }
369
+ @media (max-width: 768px) {
370
+ .example__controls {
371
+ padding: 20px;
372
+ margin-bottom: 20px;
373
+ border-radius: 12px;
342
374
  }
343
- &__heatmap {
344
- margin-bottom: 40px;
345
- @media (max-width: 768px) {
346
- margin-bottom: 30px;
347
- }
375
+ }
376
+ .example__heatmap {
377
+ margin-bottom: 40px;
378
+ }
379
+ @media (max-width: 768px) {
380
+ .example__heatmap {
381
+ margin-bottom: 30px;
348
382
  }
349
383
  }
350
384
 
351
385
  /* src/Example/controlGroups.scss */
352
- // Control groups .control-group {
386
+ .control-group {
353
387
  margin-bottom: 24px;
354
- &:last-child {
355
- margin-bottom: 0;
388
+ }
389
+ .control-group:last-child {
390
+ margin-bottom: 0;
391
+ }
392
+ .control-group__label {
393
+ display: block;
394
+ font-weight: 600;
395
+ color: #333;
396
+ margin-bottom: 12px;
397
+ font-size: 1rem;
398
+ }
399
+ @media (max-width: 768px) {
400
+ .control-group__label {
401
+ font-size: 0.9rem;
402
+ margin-bottom: 10px;
356
403
  }
357
- &__label {
358
- display: block;
359
- font-weight: 600;
360
- color: #333;
361
- margin-bottom: 12px;
362
- font-size: 1rem;
363
- @media (max-width: 768px) {
364
- font-size: 0.9rem;
365
- margin-bottom: 10px;
366
- }
404
+ }
405
+ .control-group__buttons {
406
+ display: flex;
407
+ gap: 12px;
408
+ flex-wrap: wrap;
409
+ }
410
+ @media (max-width: 768px) {
411
+ .control-group__buttons {
412
+ gap: 8px;
367
413
  }
368
- &__buttons {
369
- display: flex;
370
- gap: 12px;
371
- flex-wrap: wrap;
372
- @media (max-width: 768px) {
373
- gap: 8px;
374
- }
414
+ }
415
+ .control-group__checkbox {
416
+ display: flex;
417
+ align-items: center;
418
+ gap: 8px;
419
+ cursor: pointer;
420
+ font-size: 1rem;
421
+ color: #555;
422
+ margin: 0;
423
+ }
424
+ @media (max-width: 768px) {
425
+ .control-group__checkbox {
426
+ font-size: 0.9rem;
375
427
  }
376
- &__checkbox {
377
- display: flex;
378
- align-items: center;
379
- gap: 8px;
380
- cursor: pointer;
381
- font-size: 1rem;
382
- color: #555;
383
- margin: 0;
384
- @media (max-width: 768px) {
385
- font-size: 0.9rem;
386
- }
387
- input[type=checkbox] {
388
- width: 18px;
389
- height: 18px;
390
- accent-color: #667eea;
391
- cursor: pointer;
392
- @media (max-width: 768px) {
393
- width: 16px;
394
- height: 16px;
395
- }
396
- }
397
- &:hover {
398
- color: #333;
399
- }
428
+ }
429
+ .control-group__checkbox input[type=checkbox] {
430
+ width: 18px;
431
+ height: 18px;
432
+ accent-color: #667eea;
433
+ cursor: pointer;
434
+ }
435
+ @media (max-width: 768px) {
436
+ .control-group__checkbox input[type=checkbox] {
437
+ width: 16px;
438
+ height: 16px;
400
439
  }
401
440
  }
441
+ .control-group__checkbox:hover {
442
+ color: #333;
443
+ }
402
444
  /*# sourceMappingURL=index.css.map */
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ContributionHeatmap/index.scss","../src/Example/index.scss","../src/Example/controlGroups.scss"],"sourcesContent":["// ContributionHeatmap.scss\n// GitHub-style contribution heatmap with BEM methodology\n\n.contribution-heatmap {\n // Component variables\n --day-size: 12px;\n --day-gap: 2px;\n --border-radius: 6px;\n --transition: all 0.2s ease;\n --shadow-color: rgba(0, 0, 0, 0.1);\n \n // Color scheme - GitHub-inspired\n --color-bg: #ffffff;\n --color-border: #e1e4e8;\n --color-text: #24292f;\n --color-text-muted: #656d76;\n --color-level-0: #ebedf0;\n --color-level-1: #9be9a8;\n --color-level-2: #40c463;\n --color-level-3: #30a14e;\n --color-level-4: #216e39;\n \n // Dark mode support\n @media (prefers-color-scheme: dark) {\n --color-bg: #0d1117;\n --color-border: #30363d;\n --color-text: #f0f6fc;\n --color-text-muted: #8b949e;\n --color-level-0: #161b22;\n --color-level-1: #0e4429;\n --color-level-2: #006d32;\n --color-level-3: #26a641;\n --color-level-4: #39d353;\n }\n \n background: var(--color-bg);\n border-radius: var(--border-radius);\n padding: 20px;\n box-shadow: 0 2px 8px var(--shadow-color);\n border: 1px solid var(--color-border);\n transition: var(--transition);\n max-width: 100%;\n overflow-x: auto;\n\n &__month-header {\n color: var(--color-text-muted);\n }\n\n // Hover effect for the entire component\n &:hover {\n box-shadow: 0 4px 16px var(--shadow-color);\n }\n\n // Mobile responsiveness\n @media (max-width: 768px) {\n --day-size: 10px;\n --day-gap: 1px;\n padding: 15px;\n \n // Reduce padding on mobile\n &__container {\n padding: 0;\n }\n }\n\n @media (max-width: 480px) {\n --day-size: 8px;\n --day-gap: 1px;\n padding: 10px;\n }\n\n // Header section\n &__header {\n margin-bottom: 16px;\n text-align: center;\n \n @media (max-width: 768px) {\n margin-bottom: 12px;\n }\n }\n\n &__title {\n color: var(--color-text);\n font-size: 18px;\n font-weight: 600;\n margin: 0 0 4px 0;\n letter-spacing: -0.2px;\n \n @media (max-width: 768px) {\n font-size: 16px;\n }\n }\n\n &__subtitle {\n color: var(--color-text-muted);\n font-size: 14px;\n margin: 0;\n font-weight: 400;\n \n @media (max-width: 768px) {\n font-size: 12px;\n }\n }\n\n // Main container\n &__container {\n display: grid;\n gap: 8px;\n padding: 16px;\n background: var(--color-bg);\n border-radius: calc(var(--border-radius) - 2px);\n position: relative;\n grid-template-areas: \n \". months\"\n \"days grid\";\n grid-template-columns: 30px 1fr;\n grid-template-rows: auto 1fr;\n \n @media (max-width: 768px) {\n padding: 8px;\n gap: 6px;\n grid-template-columns: 20px 1fr;\n }\n }\n\n // Month labels\n &__months {\n grid-area: months;\n display: flex;\n gap: var(--day-gap);\n margin-bottom: 4px;\n \n @media (max-width: 768px) {\n margin-bottom: 2px;\n }\n }\n\n &__month {\n color: var(--color-text-muted);\n font-size: 12px;\n font-weight: 500;\n text-align: left;\n padding: 0 2px;\n flex-grow: 0;\n flex-shrink: 0;\n \n @media (max-width: 768px) {\n font-size: 10px;\n }\n \n @media (max-width: 480px) {\n font-size: 8px;\n }\n }\n\n // Day labels (Mon, Tue, etc.)\n &__days {\n grid-area: days;\n display: flex;\n flex-direction: column;\n gap: var(--day-gap);\n align-items: flex-end;\n justify-content: flex-start;\n padding-right: 4px;\n \n @media (max-width: 768px) {\n padding-right: 2px;\n }\n }\n\n &__day-label {\n color: var(--color-text-muted);\n font-size: 10px;\n font-weight: 500;\n height: var(--day-size);\n display: flex;\n align-items: center;\n width: 24px;\n \n @media (max-width: 768px) {\n font-size: 8px;\n width: 16px;\n }\n \n @media (max-width: 480px) {\n font-size: 7px;\n width: 12px;\n }\n }\n\n // Main grid\n &__grid {\n grid-area: grid;\n display: flex;\n gap: var(--day-gap);\n overflow-x: auto;\n scroll-behavior: smooth;\n \n // Custom scrollbar\n &::-webkit-scrollbar {\n height: 4px;\n }\n \n &::-webkit-scrollbar-track {\n background: var(--color-border);\n border-radius: 2px;\n }\n \n &::-webkit-scrollbar-thumb {\n background: var(--color-level-2);\n border-radius: 2px;\n \n &:hover {\n background: var(--color-level-3);\n }\n }\n }\n\n // Week column\n &__week {\n display: flex;\n flex-direction: column;\n gap: var(--day-gap);\n min-width: var(--day-size);\n }\n\n // Individual day square\n &__day {\n width: var(--day-size);\n height: var(--day-size);\n border-radius: 2px;\n cursor: pointer;\n transition: var(--transition);\n position: relative;\n border: 1px solid transparent;\n \n // Contribution levels\n &--level-0 {\n background-color: var(--color-level-0);\n \n &:hover {\n background-color: var(--color-level-1);\n border-color: var(--color-level-2);\n }\n }\n \n &--level-1 {\n background-color: var(--color-level-1);\n \n &:hover {\n background-color: var(--color-level-2);\n border-color: var(--color-level-3);\n }\n }\n \n &--level-2 {\n background-color: var(--color-level-2);\n \n &:hover {\n background-color: var(--color-level-3);\n border-color: var(--color-level-4);\n }\n }\n \n &--level-3 {\n background-color: var(--color-level-3);\n \n &:hover {\n background-color: var(--color-level-4);\n border-color: var(--color-level-4);\n }\n }\n \n &--level-4 {\n background-color: var(--color-level-4);\n \n &:hover {\n filter: brightness(1.1);\n border-color: var(--color-level-4);\n }\n }\n \n // Hover effects\n &:hover {\n transform: scale(1.2);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n z-index: 10;\n border-radius: 3px;\n }\n \n // Focus styles for accessibility\n &:focus-visible {\n outline: 2px solid var(--color-level-3);\n outline-offset: 2px;\n }\n }\n\n // Legend\n &__legend {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n margin-top: 12px;\n flex-wrap: wrap;\n \n @media (max-width: 768px) {\n gap: 3px;\n margin-top: 8px;\n }\n }\n\n &__legend-text {\n color: var(--color-text-muted);\n font-size: 12px;\n font-weight: 500;\n margin: 0 4px;\n \n @media (max-width: 768px) {\n font-size: 10px;\n margin: 0 2px;\n }\n }\n\n &__legend-item {\n width: 12px;\n height: 12px;\n border-radius: 2px;\n cursor: help;\n transition: var(--transition);\n border: 1px solid var(--color-border);\n \n @media (max-width: 768px) {\n width: 10px;\n height: 10px;\n }\n \n &:hover {\n transform: scale(1.2);\n border-color: var(--color-text-muted);\n }\n \n &--level-0 { background-color: var(--color-level-0); }\n &--level-1 { background-color: var(--color-level-1); }\n &--level-2 { background-color: var(--color-level-2); }\n &--level-3 { background-color: var(--color-level-3); }\n &--level-4 { background-color: var(--color-level-4); }\n }\n}\n\n// Animation for initial load\n@keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.contribution-heatmap {\n animation: fadeInUp 0.6s ease-out;\n \n &__day {\n animation: fadeInUp 0.3s ease-out;\n animation-delay: var(--animation-delay, 0s);\n animation-fill-mode: both;\n }\n}\n\n// Utilities for different themes\n.contribution-heatmap {\n // Ocean theme\n &--ocean {\n --color-level-0: #e6f3ff;\n --color-level-1: #b3daff;\n --color-level-2: #66b3ff;\n --color-level-3: #1a8cff;\n --color-level-4: #0066cc;\n }\n \n // Sunset theme\n &--sunset {\n --color-level-0: #fff2e6;\n --color-level-1: #ffcc99;\n --color-level-2: #ff9933;\n --color-level-3: #ff6600;\n --color-level-4: #cc3300;\n }\n \n // Purple theme\n &--purple {\n --color-level-0: #f3e6ff;\n --color-level-1: #d9b3ff;\n --color-level-2: #b366ff;\n --color-level-3: #8a1aff;\n --color-level-4: #6600cc;\n }\n}\n",".example {\n &__controls {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n padding: 24px;\n border-radius: 16px;\n margin-bottom: 30px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);\n border: 1px solid rgba(255, 255, 255, 0.2);\n\n @media (max-width: 768px) {\n padding: 20px;\n margin-bottom: 20px;\n border-radius: 12px;\n }\n }\n\n &__heatmap {\n margin-bottom: 40px;\n\n @media (max-width: 768px) {\n margin-bottom: 30px;\n }\n }\n}\n","// Control groups\n.control-group {\n margin-bottom: 24px;\n\n &:last-child {\n margin-bottom: 0;\n }\n\n &__label {\n display: block;\n font-weight: 600;\n color: #333;\n margin-bottom: 12px;\n font-size: 1rem;\n\n @media (max-width: 768px) {\n font-size: 0.9rem;\n margin-bottom: 10px;\n }\n }\n\n &__buttons {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n\n @media (max-width: 768px) {\n gap: 8px;\n }\n }\n\n &__checkbox {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 1rem;\n color: #555;\n margin: 0;\n\n @media (max-width: 768px) {\n font-size: 0.9rem;\n }\n\n input[type='checkbox'] {\n width: 18px;\n height: 18px;\n accent-color: #667eea;\n cursor: pointer;\n\n @media (max-width: 768px) {\n width: 16px;\n height: 16px;\n }\n }\n\n &:hover {\n color: #333;\n }\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.scss","../src/index.scss","../src/controlGroups.scss"],"sourcesContent":["// ContributionHeatmap.scss\n// GitHub-style contribution heatmap with BEM methodology\n\n.contribution-heatmap {\n // Component variables\n --day-size: 12px;\n --day-gap: 2px;\n --border-radius: 6px;\n --transition: all 0.2s ease;\n --shadow-color: rgba(0, 0, 0, 0.1);\n \n // Color scheme - GitHub-inspired\n --color-bg: #ffffff;\n --color-border: #e1e4e8;\n --color-text: #24292f;\n --color-text-muted: #656d76;\n --color-level-0: #ebedf0;\n --color-level-1: #9be9a8;\n --color-level-2: #40c463;\n --color-level-3: #30a14e;\n --color-level-4: #216e39;\n \n // Dark mode support\n @media (prefers-color-scheme: dark) {\n --color-bg: #0d1117;\n --color-border: #30363d;\n --color-text: #f0f6fc;\n --color-text-muted: #8b949e;\n --color-level-0: #161b22;\n --color-level-1: #0e4429;\n --color-level-2: #006d32;\n --color-level-3: #26a641;\n --color-level-4: #39d353;\n }\n \n background: var(--color-bg);\n border-radius: var(--border-radius);\n padding: 20px;\n box-shadow: 0 2px 8px var(--shadow-color);\n border: 1px solid var(--color-border);\n transition: var(--transition);\n max-width: 100%;\n overflow-x: auto;\n\n &__month-header {\n color: var(--color-text-muted);\n }\n\n // Hover effect for the entire component\n &:hover {\n box-shadow: 0 4px 16px var(--shadow-color);\n }\n\n // Mobile responsiveness\n @media (max-width: 768px) {\n --day-size: 10px;\n --day-gap: 1px;\n padding: 15px;\n \n // Reduce padding on mobile\n &__container {\n padding: 0;\n }\n }\n\n @media (max-width: 480px) {\n --day-size: 8px;\n --day-gap: 1px;\n padding: 10px;\n }\n\n // Header section\n &__header {\n margin-bottom: 16px;\n text-align: center;\n \n @media (max-width: 768px) {\n margin-bottom: 12px;\n }\n }\n\n &__title {\n color: var(--color-text);\n font-size: 18px;\n font-weight: 600;\n margin: 0 0 4px 0;\n letter-spacing: -0.2px;\n \n @media (max-width: 768px) {\n font-size: 16px;\n }\n }\n\n &__subtitle {\n color: var(--color-text-muted);\n font-size: 14px;\n margin: 0;\n font-weight: 400;\n \n @media (max-width: 768px) {\n font-size: 12px;\n }\n }\n\n // Main container\n &__container {\n display: grid;\n gap: 8px;\n padding: 16px;\n background: var(--color-bg);\n border-radius: calc(var(--border-radius) - 2px);\n position: relative;\n grid-template-areas: \n \". months\"\n \"days grid\";\n grid-template-columns: 30px 1fr;\n grid-template-rows: auto 1fr;\n \n @media (max-width: 768px) {\n padding: 8px;\n gap: 6px;\n grid-template-columns: 20px 1fr;\n }\n }\n\n // Month labels\n &__months {\n grid-area: months;\n display: flex;\n gap: var(--day-gap);\n margin-bottom: 4px;\n \n @media (max-width: 768px) {\n margin-bottom: 2px;\n }\n }\n\n &__month {\n color: var(--color-text-muted);\n font-size: 12px;\n font-weight: 500;\n text-align: left;\n padding: 0 2px;\n flex-grow: 0;\n flex-shrink: 0;\n \n @media (max-width: 768px) {\n font-size: 10px;\n }\n \n @media (max-width: 480px) {\n font-size: 8px;\n }\n }\n\n // Day labels (Mon, Tue, etc.)\n &__days {\n grid-area: days;\n display: flex;\n flex-direction: column;\n gap: var(--day-gap);\n align-items: flex-end;\n justify-content: flex-start;\n padding-right: 4px;\n \n @media (max-width: 768px) {\n padding-right: 2px;\n }\n }\n\n &__day-label {\n color: var(--color-text-muted);\n font-size: 10px;\n font-weight: 500;\n height: var(--day-size);\n display: flex;\n align-items: center;\n width: 24px;\n \n @media (max-width: 768px) {\n font-size: 8px;\n width: 16px;\n }\n \n @media (max-width: 480px) {\n font-size: 7px;\n width: 12px;\n }\n }\n\n // Main grid\n &__grid {\n grid-area: grid;\n display: flex;\n gap: var(--day-gap);\n overflow-x: auto;\n scroll-behavior: smooth;\n \n // Custom scrollbar\n &::-webkit-scrollbar {\n height: 4px;\n }\n \n &::-webkit-scrollbar-track {\n background: var(--color-border);\n border-radius: 2px;\n }\n \n &::-webkit-scrollbar-thumb {\n background: var(--color-level-2);\n border-radius: 2px;\n \n &:hover {\n background: var(--color-level-3);\n }\n }\n }\n\n // Week column\n &__week {\n display: flex;\n flex-direction: column;\n gap: var(--day-gap);\n min-width: var(--day-size);\n }\n\n // Individual day square\n &__day {\n width: var(--day-size);\n height: var(--day-size);\n border-radius: 2px;\n cursor: pointer;\n transition: var(--transition);\n position: relative;\n border: 1px solid transparent;\n \n // Contribution levels\n &--level-0 {\n background-color: var(--color-level-0);\n \n &:hover {\n background-color: var(--color-level-1);\n border-color: var(--color-level-2);\n }\n }\n \n &--level-1 {\n background-color: var(--color-level-1);\n \n &:hover {\n background-color: var(--color-level-2);\n border-color: var(--color-level-3);\n }\n }\n \n &--level-2 {\n background-color: var(--color-level-2);\n \n &:hover {\n background-color: var(--color-level-3);\n border-color: var(--color-level-4);\n }\n }\n \n &--level-3 {\n background-color: var(--color-level-3);\n \n &:hover {\n background-color: var(--color-level-4);\n border-color: var(--color-level-4);\n }\n }\n \n &--level-4 {\n background-color: var(--color-level-4);\n \n &:hover {\n filter: brightness(1.1);\n border-color: var(--color-level-4);\n }\n }\n \n // Hover effects\n &:hover {\n transform: scale(1.2);\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);\n z-index: 10;\n border-radius: 3px;\n }\n \n // Focus styles for accessibility\n &:focus-visible {\n outline: 2px solid var(--color-level-3);\n outline-offset: 2px;\n }\n }\n\n // Legend\n &__legend {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n margin-top: 12px;\n flex-wrap: wrap;\n \n @media (max-width: 768px) {\n gap: 3px;\n margin-top: 8px;\n }\n }\n\n &__legend-text {\n color: var(--color-text-muted);\n font-size: 12px;\n font-weight: 500;\n margin: 0 4px;\n \n @media (max-width: 768px) {\n font-size: 10px;\n margin: 0 2px;\n }\n }\n\n &__legend-item {\n width: 12px;\n height: 12px;\n border-radius: 2px;\n cursor: help;\n transition: var(--transition);\n border: 1px solid var(--color-border);\n \n @media (max-width: 768px) {\n width: 10px;\n height: 10px;\n }\n \n &:hover {\n transform: scale(1.2);\n border-color: var(--color-text-muted);\n }\n \n &--level-0 { background-color: var(--color-level-0); }\n &--level-1 { background-color: var(--color-level-1); }\n &--level-2 { background-color: var(--color-level-2); }\n &--level-3 { background-color: var(--color-level-3); }\n &--level-4 { background-color: var(--color-level-4); }\n }\n}\n\n// Animation for initial load\n@keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(20px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n.contribution-heatmap {\n animation: fadeInUp 0.6s ease-out;\n \n &__day {\n animation: fadeInUp 0.3s ease-out;\n animation-delay: var(--animation-delay, 0s);\n animation-fill-mode: both;\n }\n}\n\n// Utilities for different themes\n.contribution-heatmap {\n // Ocean theme\n &--ocean {\n --color-level-0: #e6f3ff;\n --color-level-1: #b3daff;\n --color-level-2: #66b3ff;\n --color-level-3: #1a8cff;\n --color-level-4: #0066cc;\n }\n \n // Sunset theme\n &--sunset {\n --color-level-0: #fff2e6;\n --color-level-1: #ffcc99;\n --color-level-2: #ff9933;\n --color-level-3: #ff6600;\n --color-level-4: #cc3300;\n }\n \n // Purple theme\n &--purple {\n --color-level-0: #f3e6ff;\n --color-level-1: #d9b3ff;\n --color-level-2: #b366ff;\n --color-level-3: #8a1aff;\n --color-level-4: #6600cc;\n }\n}\n",".example {\n &__controls {\n background: rgba(255, 255, 255, 0.95);\n backdrop-filter: blur(10px);\n padding: 24px;\n border-radius: 16px;\n margin-bottom: 30px;\n box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);\n border: 1px solid rgba(255, 255, 255, 0.2);\n\n @media (max-width: 768px) {\n padding: 20px;\n margin-bottom: 20px;\n border-radius: 12px;\n }\n }\n\n &__heatmap {\n margin-bottom: 40px;\n\n @media (max-width: 768px) {\n margin-bottom: 30px;\n }\n }\n}\n","// Control groups\n.control-group {\n margin-bottom: 24px;\n\n &:last-child {\n margin-bottom: 0;\n }\n\n &__label {\n display: block;\n font-weight: 600;\n color: #333;\n margin-bottom: 12px;\n font-size: 1rem;\n\n @media (max-width: 768px) {\n font-size: 0.9rem;\n margin-bottom: 10px;\n }\n }\n\n &__buttons {\n display: flex;\n gap: 12px;\n flex-wrap: wrap;\n\n @media (max-width: 768px) {\n gap: 8px;\n }\n }\n\n &__checkbox {\n display: flex;\n align-items: center;\n gap: 8px;\n cursor: pointer;\n font-size: 1rem;\n color: #555;\n margin: 0;\n\n @media (max-width: 768px) {\n font-size: 0.9rem;\n }\n\n input[type='checkbox'] {\n width: 18px;\n height: 18px;\n accent-color: #667eea;\n cursor: pointer;\n\n @media (max-width: 768px) {\n width: 16px;\n height: 16px;\n }\n }\n\n &:hover {\n color: #333;\n }\n }\n}\n"],"mappings":"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","names":[]}
package/dist/index.js CHANGED
@@ -135,7 +135,7 @@ var createEmptyWeek = (startDate) => {
135
135
  }
136
136
  return week;
137
137
  };
138
- function addExtraWeekIfNeeded(weeks, period2) {
138
+ function addExtraWeekIfNeeded(weeks) {
139
139
  if (weeks.length === 0) return weeks;
140
140
  const lastWeek = weeks[weeks.length - 1];
141
141
  const lastDate = new Date(lastWeek[6].date);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ContributionHeatmap/models.tsx","../src/ContributionHeatmap/getMonthsForHeader.ts","../src/ContributionHeatmap/Legend.tsx","../src/ContributionHeatmap/Header.tsx","../src/ContributionHeatmap/formatTooltip.tsx","../src/ContributionHeatmap/addExtraWeekIfNeeded.ts","../src/ContributionHeatmap/index.tsx","../src/ContributionHeatmap/createRealisticMockedCount.ts","../src/ContributionHeatmap/getLevel.ts","../src/ContributionHeatmap/generateMockData.tsx","../src/ContributionHeatmap/groupByWeeks.ts","../src/Example/ControlGroups.tsx","../src/Example/index.tsx"],"names":["period","jsxs","jsx","contribution","Fragment"],"mappings":"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","file":"index.js","sourcesContent":["type Theme = '' | 'ocean' | 'sunset' | 'purple';\n\ninterface ContributionData {\n date: string;\n count: number;\n level: 0 | 1 | 2 | 3 | 4;\n}\n\ntype Week = [\n ContributionData,\n ContributionData,\n ContributionData,\n ContributionData,\n ContributionData,\n ContributionData,\n ContributionData,\n];\n\ntype Period = { start: Date; end: Date };\n\nconst monthNames = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec',\n] as const;\nconst dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] as const;\n\nfunction getLastYearPeriod(): Period {\n const start = new Date(\n new Date().setFullYear(\n new Date().getFullYear() - 1,\n new Date().getMonth(),\n new Date().getDate() + 1,\n ),\n );\n const end = new Date();\n return { start, end };\n}\n\nconst createDateString = (date: Date): string =>\n date.toISOString().split('T')[0];\n\nexport type { ContributionData, Week, Period, Theme };\nexport { monthNames, dayNames, createDateString, getLastYearPeriod };\n","import { monthNames, type Period, type Week } from './models';\n\nfunction getMonthsForHeader({\n weeks,\n period,\n}: {\n weeks: Week[];\n period: Period;\n}): {\n name: string;\n span: number;\n}[] {\n const months: { name: string; span: number }[] = [];\n const { start, end } = period;\n let currentMonth = -1;\n let currentSpan = 0;\n\n weeks.forEach((week) => {\n if (week.length > 0) {\n // Find the first day in the week that falls within our actual data range\n let monthToUse = -1;\n const actualStartDate = new Date(start);\n const actualEndDate = new Date(end);\n\n for (const day of week) {\n const dayDate = new Date(day.date);\n if (dayDate >= actualStartDate && dayDate <= actualEndDate) {\n monthToUse = dayDate.getMonth();\n break;\n }\n }\n\n // If no day in the week is in our actual range, use the middle day (Wednesday)\n if (monthToUse === -1) {\n const middleDay = week[3]; // Wednesday (index 3)\n monthToUse = new Date(middleDay.date).getMonth();\n }\n\n if (monthToUse !== currentMonth) {\n if (currentMonth !== -1) {\n months.push({ name: monthNames[currentMonth], span: currentSpan });\n }\n currentMonth = monthToUse;\n currentSpan = 1;\n } else {\n currentSpan++;\n }\n }\n });\n\n if (currentMonth !== -1) {\n months.push({ name: monthNames[currentMonth], span: currentSpan });\n }\n\n // If the last month only has one week, add an extra week for better visual balance\n if (months.length > 0 && months[months.length - 1].span === 1) {\n months[months.length - 1].span = 2;\n }\n\n return months;\n}\n\nexport { getMonthsForHeader };\n","function Legend(): React.ReactNode {\n return (\n <div className=\"contribution-heatmap__legend\">\n <span className=\"contribution-heatmap__legend-text\">Less</span>\n {[0, 1, 2, 3, 4].map((level) => (\n <div\n key={level}\n className={`contribution-heatmap__legend-item contribution-heatmap__legend-item--level-${level}`}\n title={`Level ${level}`}\n ></div>\n ))}\n <span className=\"contribution-heatmap__legend-text\">More</span>\n </div>\n );\n}\n\nexport { Legend };\n","function Header({ contributions }: { contributions: number }): React.ReactNode {\n return (\n <div className=\"contribution-heatmap__header\">\n <h3 className=\"contribution-heatmap__title\">Activity Overview</h3>\n <p className=\"contribution-heatmap__subtitle\">\n {contributions} \"healthy\" days in the last year\n </p>\n </div>\n );\n}\n\nexport { Header };\n","import type { ContributionData, Period } from './models';\n\nfunction isInRange(date: Date, { start, end }: Period): boolean {\n const actualStartDate = new Date(start);\n const actualEndDate = new Date(end);\n const contributionDate = new Date(date);\n\n return contributionDate > actualStartDate && contributionDate < actualEndDate;\n}\n\nconst formatTooltip = (\n contribution: ContributionData,\n { start, end }: Period,\n): string => {\n const date = new Date(contribution.date);\n const formattedDate = date.toLocaleDateString('en-US', {\n weekday: 'short',\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n\n if (\n !isInRange(new Date(contribution.date), { start, end }) ||\n contribution.count === 0\n ) {\n return `${formattedDate}: No contributions`;\n }\n\n return `${formattedDate}: ${contribution.count} contribution${contribution.count !== 1 ? 's' : ''}`;\n};\n\nexport { formatTooltip };\n","import { createDateString, type ContributionData, type Week, type Period } from './models';\n\nconst createEmptyContribution = (date: string): ContributionData => ({\n date,\n count: 0,\n level: 0,\n});\n\nconst createEmptyWeek = (startDate: Date): Week => {\n const week: ContributionData[] = [];\n const currentDate = new Date(startDate);\n \n for (let day = 0; day < 7; day++) {\n const dateString = createDateString(currentDate);\n week.push(createEmptyContribution(dateString));\n currentDate.setDate(currentDate.getDate() + 1);\n }\n\n return week as Week;\n};\n\n/**\n * Adds an extra empty week if the last month only has one week\n * to match the header span and improve visual balance\n */\nexport function addExtraWeekIfNeeded(weeks: Week[], period: Period): Week[] {\n if (weeks.length === 0) return weeks;\n\n // Simple approach: always add an extra week at the end for better balance\n // This ensures the table has an extra column to match the header span\n const lastWeek = weeks[weeks.length - 1];\n const lastDate = new Date(lastWeek[6].date); // Saturday of last week\n const nextWeekStart = new Date(lastDate);\n nextWeekStart.setDate(lastDate.getDate() + 1); // Next Sunday\n \n const extraWeek = createEmptyWeek(nextWeekStart);\n return [...weeks, extraWeek];\n}","import './index.scss';\nimport type { ContributionData, Period, Week as WeekType } from './models';\nimport { getMonthsForHeader } from './getMonthsForHeader';\nimport { Legend } from './Legend';\nimport { Header } from './Header';\nimport { formatTooltip } from './formatTooltip';\nimport { dayNames } from './models';\nimport { addExtraWeekIfNeeded } from './addExtraWeekIfNeeded';\n\ninterface ContributionHeatmapProps {\n data: { contribution: ContributionData[]; period: Period; weeks: WeekType[] };\n className?: string;\n}\n\nfunction ContributionHeatmap({\n data: { contribution, period, weeks },\n className = '',\n}: ContributionHeatmapProps) {\n // Add extra week if needed to match header span\n const adjustedWeeks = addExtraWeekIfNeeded(weeks, period);\n const months = getMonthsForHeader({ weeks: adjustedWeeks, period });\n\n return (\n <div className={`contribution-heatmap ${className}`}>\n <Header contributions={contribution.filter((d) => d.count > 0).length} />\n\n <table className=\"contribution-heatmap__table\">\n <thead>\n <tr>\n <th className=\"contribution-heatmap__day-header\"></th>\n {months.map((month, index) => (\n <th\n key={index}\n className=\"contribution-heatmap__month-header\"\n colSpan={month.span}\n >\n {month.name}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {dayNames.map((dayName, dayIndex) => (\n <tr key={dayIndex}>\n <td className=\"contribution-heatmap__day-label\">\n {window.innerWidth > 768 ? dayName : dayName.charAt(0)}\n </td>\n {adjustedWeeks.map((week, weekIndex) => {\n const contribution = week[dayIndex];\n return (\n <td\n key={weekIndex}\n className={`contribution-heatmap__day contribution-heatmap__day--level-${contribution.level}`}\n title={formatTooltip(contribution, period)}\n aria-label={formatTooltip(contribution, period)}\n role=\"button\"\n tabIndex={0}\n data-count={contribution.count}\n data-date={contribution.date}\n style={{ \n '--animation-delay': `${(weekIndex * 7 + dayIndex) * 0.005}s` \n } as React.CSSProperties}\n ></td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n\n <Legend />\n </div>\n );\n}\n\nexport { ContributionHeatmap };\n","import type { ContributionData } from './models';\n\nconst isSummerMonth = (month: number) => {\n return month >= 5 && month <= 7;\n};\n\nexport function createRealisticMockedCount(\n date: Date,\n): ContributionData['count'] {\n // Create realistic patterns\n const dayOfWeek = date.getDay();\n const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\n const month = date.getMonth();\n\n let baseCount = isWeekend ? 2 : 8;\n\n // Lower activity in summer months (June, July, August)\n if (isSummerMonth(month)) {\n baseCount = Math.max(0, baseCount - 3);\n }\n\n // Add some randomness\n const randomFactor = Math.random();\n let count = 0;\n\n if (randomFactor > 0.3) {\n count = Math.floor(Math.random() * baseCount);\n }\n\n // Occasional high activity days\n if (randomFactor > 0.95) {\n count += Math.floor(Math.random() * 10);\n }\n\n return count;\n}\n","import type { ContributionData } from './models';\n\nconst getLevel = (count: number): ContributionData['level'] => {\n let level: 0 | 1 | 2 | 3 | 4 = 0;\n if (count === 0) level = 0;\n else if (count <= 2) level = 1;\n else if (count <= 5) level = 2;\n else if (count <= 8) level = 3;\n else level = 4;\n\n return level;\n};\n\nexport { getLevel };\n","import { createDateString, type ContributionData, type Period } from './models';\nimport { createRealisticMockedCount } from './createRealisticMockedCount';\nimport { getLevel } from './getLevel';\n\nconst getRandomCount = () => Math.floor(Math.random() * 15);\n\nfunction getRange(period: Period | 'lastYear') {\n if (period !== 'lastYear') {\n return period;\n }\n const end = new Date(); // Today\n const start = new Date();\n start.setFullYear(start.getFullYear() - 1); // One year ago\n return { start, end };\n}\n\nfunction generateMockData({\n period,\n isRealistic,\n}: {\n period: Period | 'lastYear';\n isRealistic: boolean;\n}): ContributionData[] {\n const data: ContributionData[] = [];\n const { start, end } = getRange(period);\n\n for (\n let date = new Date(start);\n date <= end;\n date.setDate(date.getDate() + 1)\n ) {\n const count = isRealistic\n ? createRealisticMockedCount(date)\n : getRandomCount();\n data.push({\n date: createDateString(date),\n count,\n level: getLevel(count),\n });\n }\n\n return data;\n}\n\nexport { generateMockData };\n","import { createDateString, type ContributionData, type Week } from './models';\n\nconst createEmpyContribution = (date: string): ContributionData => ({\n date,\n count: 0,\n level: 0,\n});\n\nconst createContributionMap = (\n contributions: ContributionData[],\n): Map<string, ContributionData> => {\n const contributionMap = new Map<string, ContributionData>();\n contributions.forEach((contribution) => {\n contributionMap.set(contribution.date, contribution);\n });\n return contributionMap;\n};\n\nconst getFirstSunday: (firstDate: Date) => Date = (firstDate) => {\n const startOfWeek = new Date(firstDate);\n startOfWeek.setDate(firstDate.getDate() - firstDate.getDay());\n return startOfWeek;\n};\n\nconst getLastSaturday: (lastDate: Date) => Date = (lastDate) => {\n const endOfWeek = new Date(lastDate);\n endOfWeek.setDate(lastDate.getDate() + (6 - lastDate.getDay()));\n return endOfWeek;\n};\n\nconst createWeek = (\n startDate: Date,\n contributionMap: Map<string, ContributionData>,\n): Week => {\n const week: ContributionData[] = [];\n const currentDate = new Date(startDate);\n for (let day = 0; day < 7; day++) {\n const dateString = createDateString(currentDate);\n const contribution = contributionMap.get(dateString);\n\n if (contribution) {\n week.push(contribution);\n } else {\n week.push(createEmpyContribution(dateString));\n }\n currentDate.setDate(currentDate.getDate() + 1);\n }\n\n return week as Week;\n};\n\nconst groupByWeeks: (contributions: ContributionData[]) => Week[] = (\n contributions,\n) => {\n const weeks: Week[] = [];\n const contributionMap = createContributionMap(contributions);\n\n const firstDay = getFirstSunday(new Date(contributions[0].date));\n const lastDate = getLastSaturday(\n new Date(contributions[contributions.length - 1].date),\n );\n\n const currentDate = new Date(firstDay);\n while (currentDate <= lastDate) {\n weeks.push(createWeek(currentDate, contributionMap));\n currentDate.setDate(currentDate.getDate() + 7);\n }\n\n return weeks;\n};\n\nexport { groupByWeeks };\n","import './controlGroups.scss';\nimport type { Theme } from '@pearpages/heatmap/ContributionHeatmap/models';\n\nexport function ControlGroups({\n actions: { theme, setTheme, hasRealisticData, setHasRealisticData },\n}: {\n actions: {\n theme: Theme;\n setTheme: (theme: Theme) => void;\n hasRealisticData: boolean;\n setHasRealisticData: (use: boolean) => void;\n };\n}) {\n return (\n <>\n <div className=\"control-group\">\n <label className=\"control-group__label\">Theme:</label>\n <div className=\"control-group__buttons\">\n <button\n className={`theme-button ${theme === '' ? 'theme-button--active' : ''}`}\n onClick={() => setTheme('')}\n >\n GitHub\n </button>\n <button\n className={`theme-button ${theme === 'ocean' ? 'theme-button--active' : ''}`}\n onClick={() => setTheme('ocean')}\n >\n Ocean\n </button>\n <button\n className={`theme-button ${theme === 'sunset' ? 'theme-button--active' : ''}`}\n onClick={() => setTheme('sunset')}\n >\n Sunset\n </button>\n <button\n className={`theme-button ${theme === 'purple' ? 'theme-button--active' : ''}`}\n onClick={() => setTheme('purple')}\n >\n Purple\n </button>\n </div>\n </div>\n <div className=\"control-group\">\n <label className=\"control-group__checkbox\">\n <input\n type=\"checkbox\"\n checked={hasRealisticData}\n onChange={(e) => setHasRealisticData(e.target.checked)}\n />\n Use realistic sample data\n </label>\n </div>\n </>\n );\n}\n","import { useState } from 'react';\nimport { ContributionHeatmap } from '@pearpages/heatmap/ContributionHeatmap';\nimport { generateMockData } from '@pearpages/heatmap/ContributionHeatmap/generateMockData';\nimport { getLastYearPeriod, type Theme } from '@pearpages/heatmap/ContributionHeatmap/models';\nimport { groupByWeeks } from '@pearpages/heatmap/ContributionHeatmap/groupByWeeks';\nimport './index.scss';\nimport { ControlGroups } from './ControlGroups';\n\nconst sampleData = generateMockData({ period: 'lastYear', isRealistic: true });\nconst period = getLastYearPeriod();\n\nfunction ContributionHeatmapExample() {\n const [theme, setTheme] = useState<Theme>('');\n const [hasRealisticData, setHasRealisticData] = useState(false);\n\n const contribution = hasRealisticData\n ? sampleData\n : generateMockData({\n period,\n isRealistic: false,\n });\n\n return (\n <>\n <div className=\"example__controls\">\n <ControlGroups\n actions={{ theme, setTheme, hasRealisticData, setHasRealisticData }}\n />\n </div>\n\n <div className=\"example__heatmap\">\n <ContributionHeatmap\n className={theme ? `contribution-heatmap--${theme}` : ''}\n data={{\n weeks: groupByWeeks(contribution),\n contribution,\n period,\n }}\n />\n </div>\n </>\n );\n}\n\nexport { ContributionHeatmapExample };\n"]}
1
+ {"version":3,"sources":["../src/ContributionHeatmap/models.tsx","../src/ContributionHeatmap/getMonthsForHeader.ts","../src/ContributionHeatmap/Legend.tsx","../src/ContributionHeatmap/Header.tsx","../src/ContributionHeatmap/formatTooltip.tsx","../src/ContributionHeatmap/addExtraWeekIfNeeded.ts","../src/ContributionHeatmap/index.tsx","../src/ContributionHeatmap/createRealisticMockedCount.ts","../src/ContributionHeatmap/getLevel.ts","../src/ContributionHeatmap/generateMockData.tsx","../src/ContributionHeatmap/groupByWeeks.ts","../src/Example/ControlGroups.tsx","../src/Example/index.tsx"],"names":["period","jsxs","jsx","contribution","Fragment"],"mappings":"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","file":"index.js","sourcesContent":["type Theme = '' | 'ocean' | 'sunset' | 'purple';\n\ninterface ContributionData {\n date: string;\n count: number;\n level: 0 | 1 | 2 | 3 | 4;\n}\n\ntype Week = [\n ContributionData,\n ContributionData,\n ContributionData,\n ContributionData,\n ContributionData,\n ContributionData,\n ContributionData,\n];\n\ntype Period = { start: Date; end: Date };\n\nconst monthNames = [\n 'Jan',\n 'Feb',\n 'Mar',\n 'Apr',\n 'May',\n 'Jun',\n 'Jul',\n 'Aug',\n 'Sep',\n 'Oct',\n 'Nov',\n 'Dec',\n] as const;\nconst dayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'] as const;\n\nfunction getLastYearPeriod(): Period {\n const start = new Date(\n new Date().setFullYear(\n new Date().getFullYear() - 1,\n new Date().getMonth(),\n new Date().getDate() + 1,\n ),\n );\n const end = new Date();\n return { start, end };\n}\n\nconst createDateString = (date: Date): string =>\n date.toISOString().split('T')[0];\n\nexport type { ContributionData, Week, Period, Theme };\nexport { monthNames, dayNames, createDateString, getLastYearPeriod };\n","import { monthNames, type Period, type Week } from './models';\n\nfunction getMonthsForHeader({\n weeks,\n period,\n}: {\n weeks: Week[];\n period: Period;\n}): {\n name: string;\n span: number;\n}[] {\n const months: { name: string; span: number }[] = [];\n const { start, end } = period;\n let currentMonth = -1;\n let currentSpan = 0;\n\n weeks.forEach((week) => {\n if (week.length > 0) {\n // Find the first day in the week that falls within our actual data range\n let monthToUse = -1;\n const actualStartDate = new Date(start);\n const actualEndDate = new Date(end);\n\n for (const day of week) {\n const dayDate = new Date(day.date);\n if (dayDate >= actualStartDate && dayDate <= actualEndDate) {\n monthToUse = dayDate.getMonth();\n break;\n }\n }\n\n // If no day in the week is in our actual range, use the middle day (Wednesday)\n if (monthToUse === -1) {\n const middleDay = week[3]; // Wednesday (index 3)\n monthToUse = new Date(middleDay.date).getMonth();\n }\n\n if (monthToUse !== currentMonth) {\n if (currentMonth !== -1) {\n months.push({ name: monthNames[currentMonth], span: currentSpan });\n }\n currentMonth = monthToUse;\n currentSpan = 1;\n } else {\n currentSpan++;\n }\n }\n });\n\n if (currentMonth !== -1) {\n months.push({ name: monthNames[currentMonth], span: currentSpan });\n }\n\n // If the last month only has one week, add an extra week for better visual balance\n if (months.length > 0 && months[months.length - 1].span === 1) {\n months[months.length - 1].span = 2;\n }\n\n return months;\n}\n\nexport { getMonthsForHeader };\n","function Legend(): React.ReactNode {\n return (\n <div className=\"contribution-heatmap__legend\">\n <span className=\"contribution-heatmap__legend-text\">Less</span>\n {[0, 1, 2, 3, 4].map((level) => (\n <div\n key={level}\n className={`contribution-heatmap__legend-item contribution-heatmap__legend-item--level-${level}`}\n title={`Level ${level}`}\n ></div>\n ))}\n <span className=\"contribution-heatmap__legend-text\">More</span>\n </div>\n );\n}\n\nexport { Legend };\n","function Header({ contributions }: { contributions: number }): React.ReactNode {\n return (\n <div className=\"contribution-heatmap__header\">\n <h3 className=\"contribution-heatmap__title\">Activity Overview</h3>\n <p className=\"contribution-heatmap__subtitle\">\n {contributions} \"healthy\" days in the last year\n </p>\n </div>\n );\n}\n\nexport { Header };\n","import type { ContributionData, Period } from './models';\n\nfunction isInRange(date: Date, { start, end }: Period): boolean {\n const actualStartDate = new Date(start);\n const actualEndDate = new Date(end);\n const contributionDate = new Date(date);\n\n return contributionDate > actualStartDate && contributionDate < actualEndDate;\n}\n\nconst formatTooltip = (\n contribution: ContributionData,\n { start, end }: Period,\n): string => {\n const date = new Date(contribution.date);\n const formattedDate = date.toLocaleDateString('en-US', {\n weekday: 'short',\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n\n if (\n !isInRange(new Date(contribution.date), { start, end }) ||\n contribution.count === 0\n ) {\n return `${formattedDate}: No contributions`;\n }\n\n return `${formattedDate}: ${contribution.count} contribution${contribution.count !== 1 ? 's' : ''}`;\n};\n\nexport { formatTooltip };\n","import { createDateString, type ContributionData, type Week } from './models';\n\nconst createEmptyContribution = (date: string): ContributionData => ({\n date,\n count: 0,\n level: 0,\n});\n\nconst createEmptyWeek = (startDate: Date): Week => {\n const week: ContributionData[] = [];\n const currentDate = new Date(startDate);\n \n for (let day = 0; day < 7; day++) {\n const dateString = createDateString(currentDate);\n week.push(createEmptyContribution(dateString));\n currentDate.setDate(currentDate.getDate() + 1);\n }\n\n return week as Week;\n};\n\n/**\n * Adds an extra empty week if the last month only has one week\n * to match the header span and improve visual balance\n */\nexport function addExtraWeekIfNeeded(weeks: Week[]): Week[] {\n if (weeks.length === 0) return weeks;\n\n // Simple approach: always add an extra week at the end for better balance\n // This ensures the table has an extra column to match the header span\n const lastWeek = weeks[weeks.length - 1];\n const lastDate = new Date(lastWeek[6].date); // Saturday of last week\n const nextWeekStart = new Date(lastDate);\n nextWeekStart.setDate(lastDate.getDate() + 1); // Next Sunday\n \n const extraWeek = createEmptyWeek(nextWeekStart);\n return [...weeks, extraWeek];\n}","import './index.scss';\nimport type { ContributionData, Period, Week as WeekType } from './models';\nimport { getMonthsForHeader } from './getMonthsForHeader';\nimport { Legend } from './Legend';\nimport { Header } from './Header';\nimport { formatTooltip } from './formatTooltip';\nimport { dayNames } from './models';\nimport { addExtraWeekIfNeeded } from './addExtraWeekIfNeeded';\n\ninterface ContributionHeatmapProps {\n data: { contribution: ContributionData[]; period: Period; weeks: WeekType[] };\n className?: string;\n}\n\nfunction ContributionHeatmap({\n data: { contribution, period, weeks },\n className = '',\n}: ContributionHeatmapProps) {\n // Add extra week if needed to match header span\n const adjustedWeeks = addExtraWeekIfNeeded(weeks);\n const months = getMonthsForHeader({ weeks: adjustedWeeks, period });\n\n return (\n <div className={`contribution-heatmap ${className}`}>\n <Header contributions={contribution.filter((d) => d.count > 0).length} />\n\n <table className=\"contribution-heatmap__table\">\n <thead>\n <tr>\n <th className=\"contribution-heatmap__day-header\"></th>\n {months.map((month, index) => (\n <th\n key={index}\n className=\"contribution-heatmap__month-header\"\n colSpan={month.span}\n >\n {month.name}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {dayNames.map((dayName, dayIndex) => (\n <tr key={dayIndex}>\n <td className=\"contribution-heatmap__day-label\">\n {window.innerWidth > 768 ? dayName : dayName.charAt(0)}\n </td>\n {adjustedWeeks.map((week, weekIndex) => {\n const contribution = week[dayIndex];\n return (\n <td\n key={weekIndex}\n className={`contribution-heatmap__day contribution-heatmap__day--level-${contribution.level}`}\n title={formatTooltip(contribution, period)}\n aria-label={formatTooltip(contribution, period)}\n role=\"button\"\n tabIndex={0}\n data-count={contribution.count}\n data-date={contribution.date}\n style={{ \n '--animation-delay': `${(weekIndex * 7 + dayIndex) * 0.005}s` \n } as React.CSSProperties}\n ></td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n\n <Legend />\n </div>\n );\n}\n\nexport { ContributionHeatmap };\n","import type { ContributionData } from './models';\n\nconst isSummerMonth = (month: number) => {\n return month >= 5 && month <= 7;\n};\n\nexport function createRealisticMockedCount(\n date: Date,\n): ContributionData['count'] {\n // Create realistic patterns\n const dayOfWeek = date.getDay();\n const isWeekend = dayOfWeek === 0 || dayOfWeek === 6;\n const month = date.getMonth();\n\n let baseCount = isWeekend ? 2 : 8;\n\n // Lower activity in summer months (June, July, August)\n if (isSummerMonth(month)) {\n baseCount = Math.max(0, baseCount - 3);\n }\n\n // Add some randomness\n const randomFactor = Math.random();\n let count = 0;\n\n if (randomFactor > 0.3) {\n count = Math.floor(Math.random() * baseCount);\n }\n\n // Occasional high activity days\n if (randomFactor > 0.95) {\n count += Math.floor(Math.random() * 10);\n }\n\n return count;\n}\n","import type { ContributionData } from './models';\n\nconst getLevel = (count: number): ContributionData['level'] => {\n let level: 0 | 1 | 2 | 3 | 4 = 0;\n if (count === 0) level = 0;\n else if (count <= 2) level = 1;\n else if (count <= 5) level = 2;\n else if (count <= 8) level = 3;\n else level = 4;\n\n return level;\n};\n\nexport { getLevel };\n","import { createDateString, type ContributionData, type Period } from './models';\nimport { createRealisticMockedCount } from './createRealisticMockedCount';\nimport { getLevel } from './getLevel';\n\nconst getRandomCount = () => Math.floor(Math.random() * 15);\n\nfunction getRange(period: Period | 'lastYear') {\n if (period !== 'lastYear') {\n return period;\n }\n const end = new Date(); // Today\n const start = new Date();\n start.setFullYear(start.getFullYear() - 1); // One year ago\n return { start, end };\n}\n\nfunction generateMockData({\n period,\n isRealistic,\n}: {\n period: Period | 'lastYear';\n isRealistic: boolean;\n}): ContributionData[] {\n const data: ContributionData[] = [];\n const { start, end } = getRange(period);\n\n for (\n let date = new Date(start);\n date <= end;\n date.setDate(date.getDate() + 1)\n ) {\n const count = isRealistic\n ? createRealisticMockedCount(date)\n : getRandomCount();\n data.push({\n date: createDateString(date),\n count,\n level: getLevel(count),\n });\n }\n\n return data;\n}\n\nexport { generateMockData };\n","import { createDateString, type ContributionData, type Week } from './models';\n\nconst createEmpyContribution = (date: string): ContributionData => ({\n date,\n count: 0,\n level: 0,\n});\n\nconst createContributionMap = (\n contributions: ContributionData[],\n): Map<string, ContributionData> => {\n const contributionMap = new Map<string, ContributionData>();\n contributions.forEach((contribution) => {\n contributionMap.set(contribution.date, contribution);\n });\n return contributionMap;\n};\n\nconst getFirstSunday: (firstDate: Date) => Date = (firstDate) => {\n const startOfWeek = new Date(firstDate);\n startOfWeek.setDate(firstDate.getDate() - firstDate.getDay());\n return startOfWeek;\n};\n\nconst getLastSaturday: (lastDate: Date) => Date = (lastDate) => {\n const endOfWeek = new Date(lastDate);\n endOfWeek.setDate(lastDate.getDate() + (6 - lastDate.getDay()));\n return endOfWeek;\n};\n\nconst createWeek = (\n startDate: Date,\n contributionMap: Map<string, ContributionData>,\n): Week => {\n const week: ContributionData[] = [];\n const currentDate = new Date(startDate);\n for (let day = 0; day < 7; day++) {\n const dateString = createDateString(currentDate);\n const contribution = contributionMap.get(dateString);\n\n if (contribution) {\n week.push(contribution);\n } else {\n week.push(createEmpyContribution(dateString));\n }\n currentDate.setDate(currentDate.getDate() + 1);\n }\n\n return week as Week;\n};\n\nconst groupByWeeks: (contributions: ContributionData[]) => Week[] = (\n contributions,\n) => {\n const weeks: Week[] = [];\n const contributionMap = createContributionMap(contributions);\n\n const firstDay = getFirstSunday(new Date(contributions[0].date));\n const lastDate = getLastSaturday(\n new Date(contributions[contributions.length - 1].date),\n );\n\n const currentDate = new Date(firstDay);\n while (currentDate <= lastDate) {\n weeks.push(createWeek(currentDate, contributionMap));\n currentDate.setDate(currentDate.getDate() + 7);\n }\n\n return weeks;\n};\n\nexport { groupByWeeks };\n","import './controlGroups.scss';\nimport type { Theme } from '@pearpages/heatmap/ContributionHeatmap/models';\n\nexport function ControlGroups({\n actions: { theme, setTheme, hasRealisticData, setHasRealisticData },\n}: {\n actions: {\n theme: Theme;\n setTheme: (theme: Theme) => void;\n hasRealisticData: boolean;\n setHasRealisticData: (use: boolean) => void;\n };\n}) {\n return (\n <>\n <div className=\"control-group\">\n <label className=\"control-group__label\">Theme:</label>\n <div className=\"control-group__buttons\">\n <button\n className={`theme-button ${theme === '' ? 'theme-button--active' : ''}`}\n onClick={() => setTheme('')}\n >\n GitHub\n </button>\n <button\n className={`theme-button ${theme === 'ocean' ? 'theme-button--active' : ''}`}\n onClick={() => setTheme('ocean')}\n >\n Ocean\n </button>\n <button\n className={`theme-button ${theme === 'sunset' ? 'theme-button--active' : ''}`}\n onClick={() => setTheme('sunset')}\n >\n Sunset\n </button>\n <button\n className={`theme-button ${theme === 'purple' ? 'theme-button--active' : ''}`}\n onClick={() => setTheme('purple')}\n >\n Purple\n </button>\n </div>\n </div>\n <div className=\"control-group\">\n <label className=\"control-group__checkbox\">\n <input\n type=\"checkbox\"\n checked={hasRealisticData}\n onChange={(e) => setHasRealisticData(e.target.checked)}\n />\n Use realistic sample data\n </label>\n </div>\n </>\n );\n}\n","import { useState } from 'react';\nimport { ContributionHeatmap } from '@pearpages/heatmap/ContributionHeatmap';\nimport { generateMockData } from '@pearpages/heatmap/ContributionHeatmap/generateMockData';\nimport { getLastYearPeriod, type Theme } from '@pearpages/heatmap/ContributionHeatmap/models';\nimport { groupByWeeks } from '@pearpages/heatmap/ContributionHeatmap/groupByWeeks';\nimport './index.scss';\nimport { ControlGroups } from './ControlGroups';\n\nconst sampleData = generateMockData({ period: 'lastYear', isRealistic: true });\nconst period = getLastYearPeriod();\n\nfunction ContributionHeatmapExample() {\n const [theme, setTheme] = useState<Theme>('');\n const [hasRealisticData, setHasRealisticData] = useState(false);\n\n const contribution = hasRealisticData\n ? sampleData\n : generateMockData({\n period,\n isRealistic: false,\n });\n\n return (\n <>\n <div className=\"example__controls\">\n <ControlGroups\n actions={{ theme, setTheme, hasRealisticData, setHasRealisticData }}\n />\n </div>\n\n <div className=\"example__heatmap\">\n <ContributionHeatmap\n className={theme ? `contribution-heatmap--${theme}` : ''}\n data={{\n weeks: groupByWeeks(contribution),\n contribution,\n period,\n }}\n />\n </div>\n </>\n );\n}\n\nexport { ContributionHeatmapExample };\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pearpages/heatmap",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/pearpages/heatmap"
@@ -34,6 +34,7 @@
34
34
  "@testing-library/react": "^16",
35
35
  "@types/react": "^19.1.12",
36
36
  "@types/react-dom": "^19.1.9",
37
+ "esbuild-sass-plugin": "^3.3.1",
37
38
  "sass": "^1.92.1",
38
39
  "tsup": "^8",
39
40
  "typescript": "^5",