@stats-forge/github-stats-forge-core 0.0.2 → 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.
- package/README.md +0 -10
- package/build/api/api-result.d.ts +6 -7
- package/build/api/api-result.d.ts.map +1 -1
- package/build/api/api-result.js +4 -5
- package/build/api/gist.d.ts +3 -10
- package/build/api/gist.d.ts.map +1 -1
- package/build/api/gist.js +4 -11
- package/build/api/index.d.ts +12 -12
- package/build/api/params.d.ts +11 -8
- package/build/api/params.d.ts.map +1 -1
- package/build/api/params.js +16 -14
- package/build/api/pin.d.ts +3 -19
- package/build/api/pin.d.ts.map +1 -1
- package/build/api/pin.js +6 -22
- package/build/api/stats.d.ts +10 -4
- package/build/api/stats.d.ts.map +1 -1
- package/build/api/stats.js +6 -32
- package/build/api/top-langs.d.ts +12 -6
- package/build/api/top-langs.d.ts.map +1 -1
- package/build/api/top-langs.js +6 -26
- package/build/api/wakatime.d.ts +13 -5
- package/build/api/wakatime.d.ts.map +1 -1
- package/build/api/wakatime.js +4 -21
- package/build/calculateRank.d.ts +0 -9
- package/build/calculateRank.d.ts.map +1 -1
- package/build/calculateRank.js +12 -17
- package/build/cards/gist.d.ts +2 -4
- package/build/cards/gist.d.ts.map +1 -1
- package/build/cards/gist.js +27 -36
- package/build/cards/options.d.ts +1 -1
- package/build/cards/repo.d.ts +2 -4
- package/build/cards/repo.d.ts.map +1 -1
- package/build/cards/repo.js +61 -93
- package/build/cards/stats.d.ts +3 -8
- package/build/cards/stats.d.ts.map +1 -1
- package/build/cards/stats.js +119 -165
- package/build/cards/top-languages.d.ts +5 -31
- package/build/cards/top-languages.d.ts.map +1 -1
- package/build/cards/top-languages.js +176 -384
- package/build/cards/wakatime.d.ts +4 -6
- package/build/cards/wakatime.d.ts.map +1 -1
- package/build/cards/wakatime.js +118 -185
- package/build/common/Card.d.ts +14 -62
- package/build/common/Card.d.ts.map +1 -1
- package/build/common/Card.js +97 -199
- package/build/common/I18n.d.ts +0 -6
- package/build/common/I18n.d.ts.map +1 -1
- package/build/common/I18n.js +3 -6
- package/build/common/color.d.ts +4 -17
- package/build/common/color.d.ts.map +1 -1
- package/build/common/color.js +67 -49
- package/build/common/config.d.ts +4 -14
- package/build/common/config.d.ts.map +1 -1
- package/build/common/config.js +3 -16
- package/build/common/constants.d.ts +4 -2
- package/build/common/constants.d.ts.map +1 -1
- package/build/common/constants.js +3 -1
- package/build/common/date.d.ts +0 -2
- package/build/common/date.d.ts.map +1 -1
- package/build/common/date.js +0 -2
- package/build/common/emojiMap.d.ts +8 -0
- package/build/common/emojiMap.d.ts.map +1 -0
- package/build/common/emojiMap.js +10 -0
- package/build/common/emojiMap.json +1915 -0
- package/build/common/error.d.ts +1 -10
- package/build/common/error.d.ts.map +1 -1
- package/build/common/error.js +1 -10
- package/build/common/fmt.d.ts +3 -15
- package/build/common/fmt.d.ts.map +1 -1
- package/build/common/fmt.js +7 -35
- package/build/common/http.d.ts +2 -7
- package/build/common/http.d.ts.map +1 -1
- package/build/common/http.js +8 -17
- package/build/common/icons.d.ts +18 -20
- package/build/common/icons.d.ts.map +1 -1
- package/build/common/icons.js +103 -67
- package/build/common/languageColors.d.ts +0 -1
- package/build/common/languageColors.d.ts.map +1 -1
- package/build/common/languageColors.js +1 -4
- package/build/common/languageColors.json +18 -2
- package/build/common/ops.d.ts +3 -14
- package/build/common/ops.d.ts.map +1 -1
- package/build/common/ops.js +19 -30
- package/build/common/render.d.ts +28 -82
- package/build/common/render.d.ts.map +1 -1
- package/build/common/render.js +175 -211
- package/build/common/retryer.d.ts +2 -7
- package/build/common/retryer.d.ts.map +1 -1
- package/build/common/retryer.js +4 -11
- package/build/fetchers/gist.d.ts +2 -5
- package/build/fetchers/gist.d.ts.map +1 -1
- package/build/fetchers/gist.js +1 -5
- package/build/fetchers/index.d.ts +12 -12
- package/build/fetchers/repo.d.ts +2 -11
- package/build/fetchers/repo.d.ts.map +1 -1
- package/build/fetchers/repo.js +20 -33
- package/build/fetchers/stats.d.ts +2 -32
- package/build/fetchers/stats.d.ts.map +1 -1
- package/build/fetchers/stats.js +27 -86
- package/build/fetchers/top-languages.d.ts +2 -9
- package/build/fetchers/top-languages.d.ts.map +1 -1
- package/build/fetchers/top-languages.js +15 -31
- package/build/fetchers/types.d.ts +1 -1
- package/build/fetchers/wakatime.d.ts +2 -6
- package/build/fetchers/wakatime.d.ts.map +1 -1
- package/build/fetchers/wakatime.js +1 -5
- package/build/graphql/contributionsDocument.d.ts +3 -3
- package/build/graphql/contributionsDocument.d.ts.map +1 -1
- package/build/graphql/contributionsDocument.js +0 -1
- package/build/graphql/generated/gist.d.ts +1 -1
- package/build/graphql/generated/repo.d.ts +1 -1
- package/build/graphql/generated/stats.d.ts +3 -3
- package/build/graphql/generated/top-languages.d.ts +2 -2
- package/build/graphql/graphqlDocument.d.ts +0 -1
- package/build/graphql/graphqlDocument.d.ts.map +1 -1
- package/build/graphql/graphqlDocument.js +0 -1
- package/build/graphql/reposContributedToDocument.d.ts +4 -5
- package/build/graphql/reposContributedToDocument.d.ts.map +1 -1
- package/build/graphql/reposContributedToDocument.js +0 -2
- package/build/markup/css.d.ts +35 -0
- package/build/markup/css.d.ts.map +1 -0
- package/build/markup/css.js +64 -0
- package/build/markup/element.d.ts +41 -0
- package/build/markup/element.d.ts.map +1 -0
- package/build/markup/element.js +127 -0
- package/build/markup/html.d.ts +13 -0
- package/build/markup/html.d.ts.map +1 -0
- package/build/markup/html.js +27 -0
- package/build/markup/index.d.ts +9 -0
- package/build/markup/index.d.ts.map +1 -0
- package/build/markup/index.js +6 -0
- package/build/markup/serialize.d.ts +16 -0
- package/build/markup/serialize.d.ts.map +1 -0
- package/build/markup/serialize.js +17 -0
- package/build/themes/index.d.ts +332 -333
- package/build/themes/index.d.ts.map +1 -1
- package/build/themes/index.js +1 -1
- package/build/translations.d.ts +2 -6
- package/build/translations.d.ts.map +1 -1
- package/build/translations.js +621 -628
- package/package.json +17 -26
- package/src/api/api-result.ts +10 -9
- package/src/api/gist.ts +11 -18
- package/src/api/index.ts +12 -12
- package/src/api/params.ts +27 -21
- package/src/api/pin.ts +13 -28
- package/src/api/stats.ts +13 -39
- package/src/api/top-langs.ts +13 -33
- package/src/api/wakatime.ts +11 -28
- package/src/calculateRank.ts +12 -23
- package/src/cards/gist.ts +40 -43
- package/src/cards/options.ts +1 -1
- package/src/cards/repo.ts +97 -107
- package/src/cards/stats.ts +165 -184
- package/src/cards/top-languages.ts +297 -413
- package/src/cards/wakatime.ts +193 -221
- package/src/common/Card.ts +165 -217
- package/src/common/I18n.ts +3 -6
- package/src/common/color.ts +80 -57
- package/src/common/config.ts +5 -18
- package/src/common/constants.ts +5 -2
- package/src/common/date.ts +0 -2
- package/src/common/emojiMap.json +1915 -0
- package/src/common/emojiMap.ts +13 -0
- package/src/common/error.ts +2 -11
- package/src/common/fmt.ts +7 -44
- package/src/common/http.ts +9 -15
- package/src/common/icons.ts +117 -42
- package/src/common/languageColors.json +18 -2
- package/src/common/languageColors.ts +1 -4
- package/src/common/ops.ts +26 -34
- package/src/common/render.ts +279 -232
- package/src/common/retryer.ts +8 -15
- package/src/fetchers/gist.ts +8 -12
- package/src/fetchers/index.ts +12 -12
- package/src/fetchers/repo.ts +27 -40
- package/src/fetchers/stats.ts +44 -102
- package/src/fetchers/top-languages.ts +26 -40
- package/src/fetchers/types.ts +1 -1
- package/src/fetchers/wakatime.ts +5 -9
- package/src/graphql/contributionsDocument.ts +7 -5
- package/src/graphql/generated/gist.ts +1 -1
- package/src/graphql/generated/repo.ts +1 -1
- package/src/graphql/generated/stats.ts +2 -2
- package/src/graphql/generated/top-languages.ts +2 -2
- package/src/graphql/graphqlDocument.ts +0 -1
- package/src/graphql/reposContributedToDocument.ts +6 -7
- package/src/markup/css.ts +118 -0
- package/src/markup/element.ts +246 -0
- package/src/markup/html.ts +34 -0
- package/src/markup/index.ts +9 -0
- package/src/markup/serialize.ts +27 -0
- package/src/themes/index.ts +1 -1
- package/src/translations.ts +622 -629
- package/build/cards/index.d.ts +0 -11
- package/build/cards/index.d.ts.map +0 -1
- package/build/cards/index.js +0 -7
- package/build/common/html.d.ts +0 -8
- package/build/common/html.d.ts.map +0 -1
- package/build/common/html.js +0 -14
- package/build/index.d.ts +0 -15
- package/build/index.d.ts.map +0 -1
- package/build/index.js +0 -10
- package/src/_emoji-name-map.d.ts +0 -10
- package/src/_github-username-regex.d.ts +0 -4
- package/src/cards/index.ts +0 -21
- package/src/common/html.ts +0 -17
- package/src/index.ts +0 -18
package/src/common/Card.ts
CHANGED
|
@@ -1,12 +1,55 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import {
|
|
1
|
+
import type { Child, CssChild, MarkupElement } from '../markup/index.ts';
|
|
2
|
+
import { atRule, cssComment, el, renderMarkup, rule, style } from '../markup/index.ts';
|
|
3
|
+
|
|
4
|
+
import { getCardColors, isPrefixedHexColor, isValidGradient } from './color.ts';
|
|
5
|
+
import type { CardColors } from './color.ts';
|
|
6
|
+
import { flexLayout } from './render.ts';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Builds the card CSS for one color scheme from that scheme's resolved colors.
|
|
8
10
|
*/
|
|
9
|
-
type CardCSSBuilder = (colors: CardColors) =>
|
|
11
|
+
type CardCSSBuilder = (colors: CardColors) => Array<CssChild>;
|
|
12
|
+
|
|
13
|
+
/** Stops every animation, whether the reader asked or the card did. */
|
|
14
|
+
const NO_MOTION = {
|
|
15
|
+
'animation-duration': '0s !important',
|
|
16
|
+
'animation-delay': '0s !important',
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Retrieves css animations for a card.
|
|
21
|
+
*
|
|
22
|
+
* @returns Animation css.
|
|
23
|
+
*/
|
|
24
|
+
const getAnimations = (): Array<CssChild> => [
|
|
25
|
+
cssComment('Animations'),
|
|
26
|
+
atRule(
|
|
27
|
+
'@keyframes scaleInAnimation',
|
|
28
|
+
rule('from', { transform: 'translate(-5px, 5px) scale(0)' }),
|
|
29
|
+
rule('to', { transform: 'translate(-5px, 5px) scale(1)' }),
|
|
30
|
+
),
|
|
31
|
+
atRule('@keyframes fadeInAnimation', rule('from', { opacity: 0 }), rule('to', { opacity: 1 })),
|
|
32
|
+
atRule('@media (prefers-reduced-motion: reduce)', rule('*', NO_MOTION)),
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/** One `linearGradient` definition, built from an angle followed by its stops. */
|
|
36
|
+
const buildGradientDef = (id: string, bgColor: Array<string>): MarkupElement => {
|
|
37
|
+
const gradients = bgColor.slice(1);
|
|
38
|
+
return el(
|
|
39
|
+
'linearGradient',
|
|
40
|
+
{
|
|
41
|
+
id,
|
|
42
|
+
gradientTransform: `rotate(${String(bgColor[0])})`,
|
|
43
|
+
gradientUnits: 'userSpaceOnUse',
|
|
44
|
+
},
|
|
45
|
+
gradients.map((grad, index) =>
|
|
46
|
+
el('stop', {
|
|
47
|
+
offset: `${(index * 100) / (gradients.length - 1)}%`,
|
|
48
|
+
'stop-color': `#${grad}`,
|
|
49
|
+
}),
|
|
50
|
+
),
|
|
51
|
+
);
|
|
52
|
+
};
|
|
10
53
|
|
|
11
54
|
class Card {
|
|
12
55
|
width: number;
|
|
@@ -16,35 +59,22 @@ class Card {
|
|
|
16
59
|
border_radius: number;
|
|
17
60
|
colors: { light: CardColors; dark: CardColors | null };
|
|
18
61
|
title: string;
|
|
19
|
-
css:
|
|
20
|
-
darkCss:
|
|
62
|
+
css: Array<CssChild>;
|
|
63
|
+
darkCss: Array<CssChild>;
|
|
21
64
|
paddingX: number;
|
|
22
65
|
paddingY: number;
|
|
23
|
-
titlePrefixIcon:
|
|
66
|
+
titlePrefixIcon: Child;
|
|
24
67
|
animations: boolean;
|
|
25
68
|
a11yTitle: string;
|
|
26
69
|
a11yDesc: string;
|
|
27
70
|
|
|
28
71
|
/**
|
|
29
72
|
* Creates a new card instance.
|
|
30
|
-
*
|
|
31
|
-
* The caller must ensure that the passed `titlePrefixIcon` is properly sanitized!
|
|
32
|
-
*
|
|
33
|
-
* @param props Card arguments.
|
|
34
|
-
* @param props.width Card width.
|
|
35
|
-
* @param props.height Card height.
|
|
36
|
-
* @param props.border_radius Card border radius.
|
|
37
|
-
* @param props.colors Card colors for light and dark mode.
|
|
38
|
-
* @param props.colors.light Card colors for light mode.
|
|
39
|
-
* @param props.colors.dark Card colors for dark mode, or `null` when no dark-mode override is needed.
|
|
40
|
-
* @param props.customTitle Card custom title.
|
|
41
|
-
* @param props.defaultTitle Card default title.
|
|
42
|
-
* @param props.titlePrefixIcon Sanitized card title prefix icon.
|
|
43
73
|
*/
|
|
44
74
|
constructor({
|
|
45
75
|
width = 100,
|
|
46
76
|
height = 100,
|
|
47
|
-
border_radius =
|
|
77
|
+
border_radius = 8,
|
|
48
78
|
colors = { light: getCardColors({}), dark: null },
|
|
49
79
|
customTitle,
|
|
50
80
|
defaultTitle = '',
|
|
@@ -57,7 +87,7 @@ class Card {
|
|
|
57
87
|
colors?: { light: CardColors; dark: CardColors | null };
|
|
58
88
|
customTitle?: string | undefined;
|
|
59
89
|
defaultTitle?: string;
|
|
60
|
-
titlePrefixIcon?:
|
|
90
|
+
titlePrefixIcon?: Child;
|
|
61
91
|
}) {
|
|
62
92
|
this.width = width;
|
|
63
93
|
this.height = height;
|
|
@@ -65,13 +95,13 @@ class Card {
|
|
|
65
95
|
this.hideBorder = false;
|
|
66
96
|
this.hideTitle = false;
|
|
67
97
|
|
|
68
|
-
this.border_radius = parseFloat(String(border_radius));
|
|
98
|
+
this.border_radius = Number.parseFloat(String(border_radius));
|
|
69
99
|
|
|
70
100
|
this.colors = colors;
|
|
71
|
-
this.title = customTitle
|
|
101
|
+
this.title = customTitle ?? defaultTitle;
|
|
72
102
|
|
|
73
|
-
this.css =
|
|
74
|
-
this.darkCss =
|
|
103
|
+
this.css = [];
|
|
104
|
+
this.darkCss = [];
|
|
75
105
|
|
|
76
106
|
this.paddingX = 25;
|
|
77
107
|
this.paddingY = 35;
|
|
@@ -85,11 +115,6 @@ class Card {
|
|
|
85
115
|
this.animations = false;
|
|
86
116
|
}
|
|
87
117
|
|
|
88
|
-
/**
|
|
89
|
-
* @param props The props object.
|
|
90
|
-
* @param props.title Accessibility title.
|
|
91
|
-
* @param props.desc Accessibility description.
|
|
92
|
-
*/
|
|
93
118
|
setAccessibilityLabel({ title, desc }: { title: string; desc: string }): void {
|
|
94
119
|
this.a11yTitle = title;
|
|
95
120
|
this.a11yDesc = desc;
|
|
@@ -101,28 +126,16 @@ class Card {
|
|
|
101
126
|
* Each builder receives the colors of its own color scheme,
|
|
102
127
|
* so a card never handles a missing dark palette itself:
|
|
103
128
|
* `dark` runs only when the card has dark colors, and always with non-null ones.
|
|
104
|
-
*
|
|
105
|
-
* @warning The caller must ensure that the returned CSS strings are properly sanitized!
|
|
106
|
-
*
|
|
107
|
-
* @param props The props object.
|
|
108
|
-
* @param props.light Builds the CSS applied unconditionally (light/default mode).
|
|
109
|
-
* @param props.dark Builds the CSS placed inside a `@media (prefers-color-scheme: dark)` block.
|
|
110
129
|
*/
|
|
111
130
|
setCSS({ light, dark }: { light: CardCSSBuilder; dark: CardCSSBuilder }): void {
|
|
112
131
|
this.css = light(this.colors.light);
|
|
113
|
-
this.darkCss = this.colors.dark ? dark(this.colors.dark) :
|
|
132
|
+
this.darkCss = this.colors.dark ? dark(this.colors.dark) : [];
|
|
114
133
|
}
|
|
115
134
|
|
|
116
|
-
/**
|
|
117
|
-
* @param value Whether to hide the border or not.
|
|
118
|
-
*/
|
|
119
135
|
setHideBorder(value: boolean): void {
|
|
120
136
|
this.hideBorder = value;
|
|
121
137
|
}
|
|
122
138
|
|
|
123
|
-
/**
|
|
124
|
-
* @param value Whether to hide the title or not.
|
|
125
|
-
*/
|
|
126
139
|
setHideTitle(value: boolean): void {
|
|
127
140
|
if (value && !this.hideTitle) {
|
|
128
141
|
this.height -= 30;
|
|
@@ -133,73 +146,43 @@ class Card {
|
|
|
133
146
|
this.hideTitle = value;
|
|
134
147
|
}
|
|
135
148
|
|
|
136
|
-
/**
|
|
137
|
-
* @param text The title to set.
|
|
138
|
-
*/
|
|
139
149
|
setTitle(text: string): void {
|
|
140
150
|
this.title = text;
|
|
141
151
|
}
|
|
142
152
|
|
|
143
|
-
/**
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
transform="translate(${this.paddingX}, ${this.paddingY})"
|
|
173
|
-
>
|
|
174
|
-
${flexLayout({
|
|
175
|
-
items: [this.titlePrefixIcon ? prefixIcon : '', titleText],
|
|
176
|
-
gap: 25,
|
|
177
|
-
}).join('')}
|
|
178
|
-
</g>
|
|
179
|
-
`;
|
|
153
|
+
/** @returns The rendered card title. */
|
|
154
|
+
renderTitle(): MarkupElement {
|
|
155
|
+
return el(
|
|
156
|
+
'g',
|
|
157
|
+
{
|
|
158
|
+
'data-testid': 'card-title',
|
|
159
|
+
transform: `translate(${this.paddingX}, ${this.paddingY})`,
|
|
160
|
+
},
|
|
161
|
+
flexLayout({
|
|
162
|
+
items: [
|
|
163
|
+
this.titlePrefixIcon &&
|
|
164
|
+
el(
|
|
165
|
+
'svg',
|
|
166
|
+
{
|
|
167
|
+
class: 'icon',
|
|
168
|
+
x: 0,
|
|
169
|
+
y: -13,
|
|
170
|
+
viewBox: '0 0 16 16',
|
|
171
|
+
version: '1.1',
|
|
172
|
+
width: 16,
|
|
173
|
+
height: 16,
|
|
174
|
+
},
|
|
175
|
+
this.titlePrefixIcon,
|
|
176
|
+
),
|
|
177
|
+
el('text', { x: 0, y: 0, class: 'header', 'data-testid': 'header' }, this.title),
|
|
178
|
+
],
|
|
179
|
+
gap: 25,
|
|
180
|
+
}),
|
|
181
|
+
);
|
|
180
182
|
}
|
|
181
183
|
|
|
182
|
-
/**
|
|
183
|
-
|
|
184
|
-
*/
|
|
185
|
-
renderGradient(): string {
|
|
186
|
-
const buildGradientDef = (id: string, bgColor: Array<string>): string => {
|
|
187
|
-
const gradients = bgColor.slice(1);
|
|
188
|
-
return `
|
|
189
|
-
<linearGradient
|
|
190
|
-
id="${id}"
|
|
191
|
-
gradientTransform="rotate(${String(bgColor[0])})"
|
|
192
|
-
gradientUnits="userSpaceOnUse"
|
|
193
|
-
>
|
|
194
|
-
${gradients
|
|
195
|
-
.map((grad, index) => {
|
|
196
|
-
const offset = (index * 100) / (gradients.length - 1);
|
|
197
|
-
return `<stop offset="${offset}%" stop-color="#${grad}" />`;
|
|
198
|
-
})
|
|
199
|
-
.join(',')}
|
|
200
|
-
</linearGradient>`;
|
|
201
|
-
};
|
|
202
|
-
|
|
184
|
+
/** @returns The card's gradient definitions, or nothing when no color is a gradient. */
|
|
185
|
+
renderGradient(): Child {
|
|
203
186
|
if (
|
|
204
187
|
typeof this.colors.light.bgColor === 'object' &&
|
|
205
188
|
!isValidGradient(this.colors.light.bgColor)
|
|
@@ -214,48 +197,24 @@ class Card {
|
|
|
214
197
|
throw new Error(`Invalid dark gradient: ${this.colors.dark.bgColor.join(',')}`);
|
|
215
198
|
}
|
|
216
199
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
200
|
+
const defs = [
|
|
201
|
+
typeof this.colors.light.bgColor === 'object' &&
|
|
202
|
+
buildGradientDef('gradient', this.colors.light.bgColor),
|
|
203
|
+
this.colors.dark &&
|
|
204
|
+
typeof this.colors.dark.bgColor === 'object' &&
|
|
205
|
+
buildGradientDef('gradient-dark', this.colors.dark.bgColor),
|
|
206
|
+
].filter(Boolean);
|
|
224
207
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
*
|
|
228
|
-
* @returns Animation css.
|
|
229
|
-
*/
|
|
230
|
-
getAnimations = (): string => {
|
|
231
|
-
return `
|
|
232
|
-
/* Animations */
|
|
233
|
-
@keyframes scaleInAnimation {
|
|
234
|
-
from {
|
|
235
|
-
transform: translate(-5px, 5px) scale(0);
|
|
236
|
-
}
|
|
237
|
-
to {
|
|
238
|
-
transform: translate(-5px, 5px) scale(1);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
@keyframes fadeInAnimation {
|
|
242
|
-
from {
|
|
243
|
-
opacity: 0;
|
|
244
|
-
}
|
|
245
|
-
to {
|
|
246
|
-
opacity: 1;
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
`;
|
|
250
|
-
};
|
|
208
|
+
return defs.length === 0 ? undefined : el('defs', {}, defs);
|
|
209
|
+
}
|
|
251
210
|
|
|
252
211
|
/**
|
|
253
212
|
* Builds the @media (prefers-color-scheme: dark) CSS block for the card.
|
|
254
|
-
* Returns
|
|
213
|
+
* Returns nothing when no dark colors are set.
|
|
255
214
|
*/
|
|
256
|
-
private renderDarkMediaBlock():
|
|
215
|
+
private renderDarkMediaBlock(): CssChild {
|
|
257
216
|
if (!this.colors.dark) {
|
|
258
|
-
return
|
|
217
|
+
return undefined;
|
|
259
218
|
}
|
|
260
219
|
|
|
261
220
|
const bgFill =
|
|
@@ -263,23 +222,18 @@ class Card {
|
|
|
263
222
|
? 'url(#gradient-dark)'
|
|
264
223
|
: this.colors.dark.bgColor;
|
|
265
224
|
|
|
266
|
-
return
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
225
|
+
return atRule(
|
|
226
|
+
'@media (prefers-color-scheme: dark)',
|
|
227
|
+
rule('.header', { fill: this.colors.dark.titleColor }),
|
|
228
|
+
rule('.card-bg', { fill: bgFill, stroke: this.colors.dark.borderColor }),
|
|
229
|
+
this.darkCss,
|
|
230
|
+
);
|
|
272
231
|
}
|
|
273
232
|
|
|
274
|
-
/**
|
|
275
|
-
|
|
276
|
-
*
|
|
277
|
-
* @param body The sanitized inner body of the card.
|
|
278
|
-
* @returns The rendered card.
|
|
279
|
-
*/
|
|
280
|
-
render(body: string): string {
|
|
233
|
+
/** @returns The rendered card. */
|
|
234
|
+
render(body: Child): string {
|
|
281
235
|
if (!Number.isFinite(this.border_radius)) {
|
|
282
|
-
throw new
|
|
236
|
+
throw new TypeError(`Invalid border radius: "${this.border_radius}"`);
|
|
283
237
|
}
|
|
284
238
|
if (!isPrefixedHexColor(this.colors.light.titleColor)) {
|
|
285
239
|
throw new Error(`Invalid title color: "${this.colors.light.titleColor}"`);
|
|
@@ -295,70 +249,64 @@ class Card {
|
|
|
295
249
|
throw new Error(`Invalid background color: ${String(this.colors.light.bgColor)}`);
|
|
296
250
|
}
|
|
297
251
|
|
|
298
|
-
return
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
height="99%"
|
|
340
|
-
stroke="${this.colors.light.borderColor}"
|
|
341
|
-
width="${this.width - 1}"
|
|
342
|
-
fill="${
|
|
252
|
+
return renderMarkup(
|
|
253
|
+
el(
|
|
254
|
+
'svg',
|
|
255
|
+
{
|
|
256
|
+
width: this.width,
|
|
257
|
+
height: this.height,
|
|
258
|
+
viewBox: `0 0 ${this.width} ${this.height}`,
|
|
259
|
+
fill: 'none',
|
|
260
|
+
xmlns: 'http://www.w3.org/2000/svg',
|
|
261
|
+
role: 'img',
|
|
262
|
+
'aria-labelledby': 'titleId descId',
|
|
263
|
+
},
|
|
264
|
+
el('title', { id: 'titleId' }, this.a11yTitle),
|
|
265
|
+
el('desc', { id: 'descId' }, this.a11yDesc),
|
|
266
|
+
style(
|
|
267
|
+
rule('.header', {
|
|
268
|
+
font: "600 18px 'Segoe UI', Ubuntu, Sans-Serif",
|
|
269
|
+
fill: this.colors.light.titleColor,
|
|
270
|
+
animation: 'fadeInAnimation 0.8s ease-in-out forwards',
|
|
271
|
+
}),
|
|
272
|
+
atRule(
|
|
273
|
+
'@supports(-moz-appearance: auto)',
|
|
274
|
+
cssComment('Selector detects Firefox'),
|
|
275
|
+
rule('.header', { 'font-size': '15.5px' }),
|
|
276
|
+
),
|
|
277
|
+
this.css,
|
|
278
|
+
this.renderDarkMediaBlock(),
|
|
279
|
+
getAnimations(),
|
|
280
|
+
!this.animations && rule('*', NO_MOTION),
|
|
281
|
+
),
|
|
282
|
+
this.renderGradient(),
|
|
283
|
+
el('rect', {
|
|
284
|
+
'data-testid': 'card-bg',
|
|
285
|
+
class: 'card-bg',
|
|
286
|
+
x: 0.5,
|
|
287
|
+
y: 0.5,
|
|
288
|
+
rx: this.border_radius,
|
|
289
|
+
height: '99%',
|
|
290
|
+
stroke: this.colors.light.borderColor,
|
|
291
|
+
width: this.width - 1,
|
|
292
|
+
fill:
|
|
343
293
|
typeof this.colors.light.bgColor === 'object'
|
|
344
294
|
? 'url(#gradient)'
|
|
345
|
-
: this.colors.light.bgColor
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
`;
|
|
295
|
+
: this.colors.light.bgColor,
|
|
296
|
+
'stroke-opacity': this.hideBorder ? 0 : 1,
|
|
297
|
+
}),
|
|
298
|
+
!this.hideTitle && this.renderTitle(),
|
|
299
|
+
el(
|
|
300
|
+
'g',
|
|
301
|
+
{
|
|
302
|
+
'data-testid': 'main-card-body',
|
|
303
|
+
transform: `translate(0, ${this.hideTitle ? this.paddingX : this.paddingY + 20})`,
|
|
304
|
+
},
|
|
305
|
+
body,
|
|
306
|
+
),
|
|
307
|
+
),
|
|
308
|
+
);
|
|
360
309
|
}
|
|
361
310
|
}
|
|
362
311
|
|
|
363
312
|
export { Card };
|
|
364
|
-
export default Card;
|
package/src/common/I18n.ts
CHANGED
|
@@ -10,11 +10,6 @@ class I18n<Translations extends TranslationsMap = TranslationsMap> {
|
|
|
10
10
|
locale: string;
|
|
11
11
|
translations: Translations;
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* @param props Constructor arguments.
|
|
15
|
-
* @param props.locale Locale.
|
|
16
|
-
* @param props.translations Translations.
|
|
17
|
-
*/
|
|
18
13
|
constructor({
|
|
19
14
|
locale,
|
|
20
15
|
translations,
|
|
@@ -30,11 +25,13 @@ class I18n<Translations extends TranslationsMap = TranslationsMap> {
|
|
|
30
25
|
/**
|
|
31
26
|
* Get translation.
|
|
32
27
|
*
|
|
33
|
-
* @param str String to translate.
|
|
34
28
|
* @returns Translated string.
|
|
35
29
|
*/
|
|
36
30
|
t(str: keyof Translations & string): string {
|
|
37
31
|
const translation = this.translations[str];
|
|
32
|
+
// A key the type says is present can still be missing at runtime: a card passes
|
|
33
|
+
// a locale table it built, and `i18n.test.ts` covers exactly that.
|
|
34
|
+
// oxlint-disable-next-line typescript/no-unnecessary-condition
|
|
38
35
|
if (!translation) {
|
|
39
36
|
throw new Error(`${str} Translation string not found`);
|
|
40
37
|
}
|