gitalk-react 1.0.0-beta.1

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 (47) hide show
  1. package/LICENSE +9 -0
  2. package/README-zh-CN.md +257 -0
  3. package/README.md +257 -0
  4. package/dist/gitalk-dark.css +1 -0
  5. package/dist/gitalk-light.css +1 -0
  6. package/dist/gitalk.d.ts +445 -0
  7. package/dist/gitalk.js +12560 -0
  8. package/dist/gitalk.umd.cjs +121 -0
  9. package/lib/assets/arrow-down.svg +1 -0
  10. package/lib/assets/edit.svg +3 -0
  11. package/lib/assets/github.svg +3 -0
  12. package/lib/assets/heart-filled.svg +3 -0
  13. package/lib/assets/heart.svg +3 -0
  14. package/lib/assets/reply.svg +3 -0
  15. package/lib/assets/tip.svg +8 -0
  16. package/lib/components/action.tsx +21 -0
  17. package/lib/components/avatar.tsx +42 -0
  18. package/lib/components/button.tsx +35 -0
  19. package/lib/components/comment.tsx +153 -0
  20. package/lib/components/svg.tsx +29 -0
  21. package/lib/constants/index.ts +43 -0
  22. package/lib/contexts/I18nContext.ts +18 -0
  23. package/lib/gitalk.tsx +1231 -0
  24. package/lib/i18n/de.json +20 -0
  25. package/lib/i18n/en.json +20 -0
  26. package/lib/i18n/es-ES.json +20 -0
  27. package/lib/i18n/fa.json +20 -0
  28. package/lib/i18n/fr.json +20 -0
  29. package/lib/i18n/index.ts +40 -0
  30. package/lib/i18n/ja.json +20 -0
  31. package/lib/i18n/ko.json +20 -0
  32. package/lib/i18n/pl.json +21 -0
  33. package/lib/i18n/ru.json +20 -0
  34. package/lib/i18n/zh-CN.json +20 -0
  35. package/lib/i18n/zh-TW.json +20 -0
  36. package/lib/interfaces/index.ts +30 -0
  37. package/lib/services/graphql/comment.ts +85 -0
  38. package/lib/services/request.ts +24 -0
  39. package/lib/services/user.ts +40 -0
  40. package/lib/themes/base.scss +592 -0
  41. package/lib/themes/gitalk-dark.scss +24 -0
  42. package/lib/themes/gitalk-light.scss +24 -0
  43. package/lib/utils/compatibility.ts +35 -0
  44. package/lib/utils/dom.ts +15 -0
  45. package/lib/utils/logger.ts +56 -0
  46. package/lib/utils/query.ts +19 -0
  47. package/package.json +83 -0
@@ -0,0 +1,592 @@
1
+ @function em($px, $base-size: $gt-size-base) {
2
+ @return calc($px / $base-size * 1em);
3
+ }
4
+
5
+ @mixin clearfix() {
6
+ &::before,
7
+ &::after {
8
+ display: table;
9
+ content: '';
10
+ }
11
+
12
+ &::after {
13
+ clear: both;
14
+ }
15
+ }
16
+
17
+ @mixin mobile() {
18
+ @media (max-width: $gt-breakpoint-mobile) {
19
+ @content;
20
+ }
21
+ }
22
+
23
+ @keyframes gt-kf-rotate {
24
+ 0% {
25
+ transform: rotate(0);
26
+ }
27
+
28
+ 100% {
29
+ transform: rotate(360deg);
30
+ }
31
+ }
32
+
33
+ $gt-size-base: 16px;
34
+ $gt-size-border-radius: em(5px);
35
+ $gt-size-loader-dot: em(6px);
36
+ $gt-size-loader: em(28px);
37
+ $gt-size-avatar: em(50px);
38
+ $gt-size-avatar-mobi: em(32px);
39
+ $gt-size-textarea-min-height: em(82px);
40
+ $gt-mask-z-index: 9999;
41
+ $gt-breakpoint-mobile: 479px;
42
+
43
+ .gt-container {
44
+ box-sizing: border-box;
45
+ font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
46
+ font-size: $gt-size-base;
47
+ font-weight: 400;
48
+ line-height: 1.5;
49
+ color: var(--gt-color-text);
50
+ font-synthesis: none;
51
+ text-rendering: optimizelegibility;
52
+ -webkit-font-smoothing: antialiased;
53
+ -moz-osx-font-smoothing: grayscale;
54
+
55
+ * {
56
+ box-sizing: border-box;
57
+ }
58
+
59
+ a {
60
+ color: var(--gt-color-main);
61
+
62
+ &:hover {
63
+ color: var(--gt-color-main-lighter);
64
+ border-color: var(--gt-color-main-lighter);
65
+ }
66
+
67
+ &.is--active {
68
+ color: var(--gt-color-link-active);
69
+ cursor: default;
70
+
71
+ &:hover {
72
+ color: var(--gt-color-link-active);
73
+ }
74
+ }
75
+ }
76
+
77
+ .hide {
78
+ display: none;
79
+ }
80
+
81
+ .gt {
82
+ &-svg {
83
+ display: inline-block;
84
+ width: em(16px);
85
+ height: em(16px);
86
+ vertical-align: sub;
87
+
88
+ svg {
89
+ width: 100%;
90
+ height: 100%;
91
+ fill: var(--gt-color-main);
92
+ }
93
+ }
94
+
95
+ &-ico {
96
+ display: inline-block;
97
+
98
+ &-text {
99
+ margin-left: em(5px);
100
+ }
101
+
102
+ &-github {
103
+ width: 100%;
104
+ height: 100%;
105
+
106
+ .gt-svg {
107
+ width: 100%;
108
+ height: 100%;
109
+ }
110
+
111
+ svg {
112
+ fill: var(--gt-color-text);
113
+ }
114
+ }
115
+ }
116
+
117
+ &-spinner {
118
+ position: relative;
119
+
120
+ &::before {
121
+ position: absolute;
122
+ top: em(3px);
123
+ box-sizing: border-box;
124
+ width: em(12px);
125
+ height: em(12px);
126
+ margin-top: em(-3px);
127
+ margin-left: em(-6px);
128
+ content: '';
129
+ border: 1px solid var(--gt-color-btn);
130
+ border-top-color: var(--gt-color-main);
131
+ border-radius: 50%;
132
+ animation: gt-kf-rotate 0.6s linear infinite;
133
+ }
134
+ }
135
+
136
+ &-loader {
137
+ position: relative;
138
+ display: inline-block;
139
+ width: $gt-size-loader;
140
+ height: $gt-size-loader;
141
+ font-style: normal;
142
+ line-height: $gt-size-loader;
143
+ border: 1px solid var(--gt-color-loader);
144
+ border-radius: 50%;
145
+ animation: ease gt-kf-rotate 1.5s infinite;
146
+
147
+ &::before {
148
+ position: absolute;
149
+ top: 0;
150
+ left: 50%;
151
+ display: block;
152
+ width: $gt-size-loader-dot;
153
+ height: $gt-size-loader-dot;
154
+ margin-top: -(calc($gt-size-loader-dot / 2));
155
+ margin-left: -(calc($gt-size-loader-dot / 2));
156
+ content: '';
157
+ background-color: var(--gt-color-loader);
158
+ border-radius: 50%;
159
+ }
160
+ }
161
+
162
+ &-avatar {
163
+ display: inline-block;
164
+ width: $gt-size-avatar;
165
+ height: $gt-size-avatar;
166
+
167
+ @include mobile {
168
+ width: $gt-size-avatar-mobi;
169
+ height: $gt-size-avatar-mobi;
170
+ }
171
+
172
+ img {
173
+ width: 100%;
174
+ height: auto;
175
+ border-radius: em(3px);
176
+ }
177
+
178
+ &-github {
179
+ width: $gt-size-avatar - em(2px);
180
+ height: $gt-size-avatar - em(2px);
181
+ cursor: pointer;
182
+
183
+ @include mobile {
184
+ width: $gt-size-avatar-mobi - em(2px);
185
+ height: $gt-size-avatar-mobi - em(2px);
186
+ }
187
+ }
188
+ }
189
+
190
+ &-btn {
191
+ display: inline-block;
192
+ padding: em(12px) em(20px);
193
+ font-size: em(12px);
194
+ line-height: 1;
195
+ color: var(--gt-color-btn);
196
+ white-space: nowrap;
197
+ text-decoration: none;
198
+ cursor: pointer;
199
+ outline: none;
200
+ background-color: var(--gt-color-main);
201
+ border: 1px solid var(--gt-color-main);
202
+ border-radius: $gt-size-border-radius;
203
+ transition: all ease 0.25s;
204
+
205
+ &:hover {
206
+ background-color: var(--gt-color-main-lighter);
207
+ border-color: var(--gt-color-main-lighter);
208
+ }
209
+
210
+ &--secondary {
211
+ color: var(--gt-color-main-lighter);
212
+ background-color: transparent;
213
+ border-color: var(--gt-color-main-lighter);
214
+
215
+ &:hover {
216
+ color: var(--gt-color-main);
217
+ background-color: transparent;
218
+ border-color: var(--gt-color-main);
219
+ }
220
+ }
221
+
222
+ &-text {
223
+ font-weight: 400;
224
+ }
225
+
226
+ &-loading {
227
+ position: relative;
228
+ display: inline-block;
229
+ width: em(12px);
230
+ height: em(16px);
231
+ margin-left: em(8px);
232
+ vertical-align: top;
233
+ }
234
+
235
+ &.is--disable {
236
+ cursor: not-allowed;
237
+ opacity: 0.5;
238
+ }
239
+
240
+ &-login {
241
+ margin-right: 0;
242
+ }
243
+ }
244
+
245
+ &-error {
246
+ margin: em(10px);
247
+ color: var(--gt-color-error);
248
+ text-align: center;
249
+ }
250
+
251
+ &-initing {
252
+ padding: em(20px) 0;
253
+ text-align: center;
254
+
255
+ &-text {
256
+ margin: em(10px) auto;
257
+ font-size: 92%;
258
+ }
259
+ }
260
+
261
+ &-no-init {
262
+ padding: em(20px) 0;
263
+ text-align: center;
264
+ }
265
+
266
+ &-link {
267
+ border-bottom: 1px dotted var(--gt-color-main);
268
+
269
+ &-counts,
270
+ &-project {
271
+ text-decoration: none;
272
+ }
273
+ }
274
+
275
+ &-meta {
276
+ position: relative;
277
+ z-index: 10;
278
+ padding: em(16px) 0;
279
+ margin: em(20px) 0;
280
+ font-size: em(16px);
281
+ border-bottom: 1px solid var(--gt-color-hr);
282
+
283
+ @include clearfix;
284
+ }
285
+
286
+ &-counts {
287
+ margin: 0 em(10px) 0 0;
288
+ }
289
+
290
+ &-user {
291
+ float: right;
292
+ margin: 0;
293
+ font-size: 92%;
294
+
295
+ &-pic {
296
+ width: em(16px);
297
+ height: em(16px);
298
+ margin-right: em(8px);
299
+ vertical-align: top;
300
+ }
301
+
302
+ &-inner {
303
+ display: inline-block;
304
+ cursor: pointer;
305
+ }
306
+
307
+ .gt-ico {
308
+ margin: 0 0 0 em(5px);
309
+
310
+ svg {
311
+ fill: var(--gt-color-text);
312
+ }
313
+ }
314
+
315
+ .is--poping {
316
+ .gt-ico {
317
+ svg {
318
+ fill: var(--gt-color-main);
319
+ }
320
+ }
321
+ }
322
+ }
323
+
324
+ &-version {
325
+ margin-left: em(6px);
326
+ color: var(--gt-color-sub);
327
+ }
328
+
329
+ &-copyright {
330
+ padding-top: em(8px);
331
+ margin: 0 em(15px) em(8px);
332
+ border-top: 1px solid var(--gt-color-hr);
333
+ }
334
+
335
+ &-popup {
336
+ position: absolute;
337
+ top: em(38px);
338
+ right: 0;
339
+ display: inline-block;
340
+ padding: em(10px) 0;
341
+ font-size: em(14px);
342
+ letter-spacing: 0.5px;
343
+ background: var(--gt-color-popbg);
344
+ border: 1px solid var(--gt-color-hr);
345
+
346
+ .gt-action {
347
+ position: relative;
348
+ display: block;
349
+ padding: 0 em(18px);
350
+ margin: em(8px) 0;
351
+ text-decoration: none;
352
+ cursor: pointer;
353
+
354
+ &.is--active {
355
+ &::before {
356
+ position: absolute;
357
+ top: em(7px);
358
+ left: em(8px);
359
+ width: em(4px);
360
+ height: em(4px);
361
+ content: '';
362
+ background: var(--gt-color-main);
363
+ }
364
+ }
365
+ }
366
+ }
367
+
368
+ &-header {
369
+ position: relative;
370
+ display: flex;
371
+
372
+ &-comment {
373
+ flex: 1;
374
+ margin-left: em(20px);
375
+
376
+ @include mobile {
377
+ margin-left: em(14px);
378
+ }
379
+ }
380
+
381
+ &-textarea {
382
+ box-sizing: border-box;
383
+ display: block;
384
+ width: 100%;
385
+ min-height: $gt-size-textarea-min-height;
386
+ max-height: em(240px);
387
+ padding: em(12px);
388
+ font-size: em(14px);
389
+ color: inherit;
390
+ word-wrap: break-word;
391
+ resize: vertical;
392
+ outline: none;
393
+ background-color: var(--gt-color-input-bg);
394
+ border: 1px solid var(--gt-color-input-border);
395
+ border-radius: $gt-size-border-radius;
396
+ transition: all ease 0.25s;
397
+
398
+ &:hover,
399
+ &:focus {
400
+ background-color: var(--gt-color-input-bg-lighter);
401
+ }
402
+ }
403
+
404
+ &-preview {
405
+ min-height: $gt-size-textarea-min-height;
406
+ padding: em(12px);
407
+ background-color: var(--gt-color-input-bg);
408
+ border: 1px solid var(--gt-color-input-border);
409
+ border-radius: $gt-size-border-radius;
410
+ }
411
+
412
+ &-controls {
413
+ position: relative;
414
+ display: flex;
415
+ align-items: center;
416
+ margin: em(12px) 0 0;
417
+
418
+ &-tip {
419
+ margin-right: auto;
420
+ font-size: em(14px);
421
+ color: var(--gt-color-main);
422
+ text-decoration: none;
423
+
424
+ @include mobile {
425
+ display: none;
426
+ }
427
+ }
428
+
429
+ .gt-btn {
430
+ margin-left: em(12px);
431
+
432
+ @include mobile {
433
+ width: 100%;
434
+
435
+ &:first-of-type {
436
+ margin-left: 0;
437
+ }
438
+ }
439
+ }
440
+ }
441
+ }
442
+
443
+ &-comments {
444
+ padding-top: em(20px);
445
+
446
+ &-null {
447
+ text-align: center;
448
+ }
449
+
450
+ &-controls {
451
+ margin: em(20px) 0;
452
+ text-align: center;
453
+ }
454
+ }
455
+
456
+ &-comment {
457
+ position: relative;
458
+ display: flex;
459
+ padding: em(10px) 0;
460
+
461
+ &-content {
462
+ flex: 1;
463
+ padding: em(12px) em(16px);
464
+ margin-left: em(20px);
465
+ overflow: auto;
466
+ background-color: var(--gt-color-comment-bg);
467
+ transition: all ease 0.25s;
468
+
469
+ &:hover {
470
+ box-shadow: 0 em(2px) em(24px) 0 var(--gt-color-comment-shadow);
471
+ }
472
+
473
+ @include mobile {
474
+ padding: em(10px) em(12px);
475
+ margin-left: em(14px);
476
+ }
477
+ }
478
+
479
+ &-header {
480
+ position: relative;
481
+ display: flex;
482
+ margin-bottom: em(8px);
483
+ font-size: em(14px);
484
+ }
485
+
486
+ &-username {
487
+ font-weight: 500;
488
+ color: var(--gt-color-main);
489
+ text-decoration: none;
490
+
491
+ &:hover {
492
+ text-decoration: underline;
493
+ }
494
+ }
495
+
496
+ &-date {
497
+ margin-left: em(8px);
498
+ color: var(--gt-color-sub);
499
+ }
500
+
501
+ &-actions {
502
+ display: flex;
503
+ gap: em(12px);
504
+ margin-left: auto;
505
+ }
506
+
507
+ &-like,
508
+ &-edit,
509
+ &-reply {
510
+ height: em(22px);
511
+
512
+ &:hover {
513
+ cursor: pointer;
514
+ }
515
+ }
516
+
517
+ &-body {
518
+ color: var(--gt-color-comment-txt);
519
+ background-color: inherit;
520
+
521
+ .email-hidden-toggle a {
522
+ display: inline-block;
523
+ height: em(12px);
524
+ padding: 0 em(9px);
525
+ font-size: em(12px);
526
+ font-weight: 600;
527
+ line-height: em(6px);
528
+ vertical-align: middle;
529
+ color: #444d56;
530
+ text-decoration: none;
531
+ background: #dfe2e5;
532
+ border-radius: 1px;
533
+
534
+ &:hover {
535
+ background-color: #c6cbd1;
536
+ }
537
+ }
538
+
539
+ .email-hidden-reply {
540
+ display: none;
541
+ white-space: pre-wrap;
542
+
543
+ &.expanded {
544
+ display: block;
545
+ }
546
+
547
+ .email-signature-reply {
548
+ padding: 0 em(15px);
549
+ margin: em(15px) 0;
550
+ color: #586069;
551
+ border-left: em(4px) solid #dfe2e5;
552
+ }
553
+ }
554
+ }
555
+
556
+ &-admin {
557
+ .gt-comment-content {
558
+ box-shadow: 0 em(2px) em(12px) 0 var(--gt-color-comment-shadow);
559
+
560
+ &:hover {
561
+ box-shadow: 0 em(2px) em(24px) 0
562
+ var(--gt-color-comment-shadow-admin);
563
+ }
564
+ }
565
+ }
566
+ }
567
+ }
568
+
569
+ &::after {
570
+ position: fixed;
571
+ inset: 0 0 100%;
572
+ content: '';
573
+ opacity: 0;
574
+ }
575
+
576
+ &.gt-input-focused {
577
+ position: relative;
578
+
579
+ &::after {
580
+ z-index: $gt-mask-z-index;
581
+ background: #000;
582
+ opacity: 0.6;
583
+ transition:
584
+ opacity 0.3s,
585
+ bottom 0s;
586
+ }
587
+
588
+ .gt-header-comment {
589
+ z-index: $gt-mask-z-index + 1;
590
+ }
591
+ }
592
+ }
@@ -0,0 +1,24 @@
1
+ @use 'sass:color';
2
+ @use './base';
3
+ @import 'github-markdown-css/github-markdown-dark.css';
4
+
5
+ .gt-container {
6
+ --gt-theme-mode: dark;
7
+ --gt-color-text: #e9e9e9;
8
+ --gt-color-main: #6366f1;
9
+ --gt-color-main-lighter: #{color.adjust(#6366f1, $lightness: 5%)};
10
+ --gt-color-sub: #9e9e9e;
11
+ --gt-color-loader: #777;
12
+ --gt-color-error: #ef4444;
13
+ --gt-color-hr: #555;
14
+ --gt-color-input-border: rgb(255 255 255 / 10%);
15
+ --gt-color-input-bg: #212121;
16
+ --gt-color-input-bg-lighter: #{color.adjust(#212121, $lightness: 6%)};
17
+ --gt-color-comment-bg: #212121;
18
+ --gt-color-comment-shadow: #{color.adjust(#212121, $lightness: 18%)};
19
+ --gt-color-comment-shadow-admin: #{color.adjust(#212121, $lightness: 24%)};
20
+ --gt-color-comment-txt: #fafafa;
21
+ --gt-color-link-active: #fafafa;
22
+ --gt-color-btn: #eee;
23
+ --gt-color-popbg: #171717;
24
+ }
@@ -0,0 +1,24 @@
1
+ @use 'sass:color';
2
+ @use './base';
3
+ @import 'github-markdown-css/github-markdown-light.css';
4
+
5
+ .gt-container {
6
+ --gt-theme-mode: light;
7
+ --gt-color-text: #171717;
8
+ --gt-color-main: #3b82f6;
9
+ --gt-color-main-lighter: #{color.adjust(#3b82f6, $lightness: 10%)};
10
+ --gt-color-sub: #a1a1a1;
11
+ --gt-color-loader: #999;
12
+ --gt-color-error: #ff3860;
13
+ --gt-color-hr: #e9e9e9;
14
+ --gt-color-input-border: rgb(0 0 0 / 10%);
15
+ --gt-color-input-bg: #f6f6f6;
16
+ --gt-color-input-bg-lighter: #{color.adjust(#f6f6f6, $lightness: 50%)};
17
+ --gt-color-comment-bg: #f9f9f9;
18
+ --gt-color-comment-shadow: #{color.adjust(#f9f9f9, $lightness: -12%)};
19
+ --gt-color-comment-shadow-admin: #{color.adjust(#f9f9f9, $lightness: -18%)};
20
+ --gt-color-comment-txt: #333;
21
+ --gt-color-link-active: #333;
22
+ --gt-color-btn: #fff;
23
+ --gt-color-popbg: #fff;
24
+ }
@@ -0,0 +1,35 @@
1
+ import logger from "./logger";
2
+
3
+ export const supportsCSSVariables = () => {
4
+ const testKey = "--supports-css-variables";
5
+ const testValue = "1rem";
6
+
7
+ try {
8
+ const testElement = document.createElement("div");
9
+ testElement.style.setProperty(testKey, testValue);
10
+
11
+ return testElement.style.getPropertyValue(testKey) === testValue;
12
+ } catch (error) {
13
+ logger.e(
14
+ `An error occurred while checking browser compatibility with CSS variables:`,
15
+ error,
16
+ );
17
+ return false;
18
+ }
19
+ };
20
+
21
+ export const supportsES2020 = () => {
22
+ try {
23
+ return (
24
+ typeof BigInt !== "undefined" &&
25
+ typeof Promise.allSettled === "function" &&
26
+ typeof String.prototype.matchAll === "function"
27
+ );
28
+ } catch (error) {
29
+ logger.e(
30
+ `An error occurred while checking browser compatibility with ES2020:`,
31
+ error,
32
+ );
33
+ return false;
34
+ }
35
+ };
@@ -0,0 +1,15 @@
1
+ export const hasClassInParent = (
2
+ element: HTMLElement,
3
+ ...className: string[]
4
+ ): boolean => {
5
+ if (!element || typeof element.className === "undefined") return false;
6
+
7
+ let yes = false;
8
+ const classes = element.className.split(" ");
9
+ className.forEach((c) => {
10
+ yes = yes || classes.indexOf(c) >= 0;
11
+ });
12
+ if (yes) return yes;
13
+
14
+ return hasClassInParent(element.parentNode as HTMLElement, ...className);
15
+ };