@imposium-hub/components 1.55.0 → 1.57.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/dist/cjs/components/font-picker/FontPicker.d.ts +44 -0
- package/dist/cjs/components/font-picker/FontPicker.js +182 -0
- package/dist/cjs/components/font-picker/FontPicker.js.map +1 -0
- package/dist/cjs/components/font-picker/font-manager/FontManager.d.ts +26 -0
- package/dist/cjs/components/font-picker/font-manager/FontManager.js +209 -0
- package/dist/cjs/components/font-picker/font-manager/FontManager.js.map +1 -0
- package/dist/cjs/components/font-picker/font-manager/constants.d.ts +4 -0
- package/dist/cjs/components/font-picker/font-manager/constants.js +8 -0
- package/dist/cjs/components/font-picker/font-manager/constants.js.map +1 -0
- package/dist/cjs/components/font-picker/font-manager/fontStyle.d.ts +1 -0
- package/dist/cjs/components/font-picker/font-manager/fontStyle.js +61 -0
- package/dist/cjs/components/font-picker/font-manager/fontStyle.js.map +1 -0
- package/dist/cjs/components/font-picker/font-manager/types.d.ts +25 -0
- package/dist/cjs/components/font-picker/font-manager/types.js +12 -0
- package/dist/cjs/components/font-picker/font-manager/types.js.map +1 -0
- package/dist/cjs/components/font-picker/font-manager/utils.d.ts +3 -0
- package/dist/cjs/components/font-picker/font-manager/utils.js +42 -0
- package/dist/cjs/components/font-picker/font-manager/utils.js.map +1 -0
- package/dist/cjs/components/publish-wizard/EmailWorkflow.d.ts +2 -0
- package/dist/cjs/components/publish-wizard/EmailWorkflow.js +491 -0
- package/dist/cjs/components/publish-wizard/EmailWorkflow.js.map +1 -0
- package/dist/cjs/components/publish-wizard/copy.d.ts +186 -0
- package/dist/cjs/components/publish-wizard/copy.js +199 -0
- package/dist/cjs/components/publish-wizard/copy.js.map +1 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer.js +120 -9
- package/dist/cjs/components/story-previewer/StoryPreviewer.js.map +1 -1
- package/dist/cjs/components/story-previewer/StoryPreviewer_BACKUP_64741.d.ts +2 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_BACKUP_64741.js +670 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_BACKUP_64741.js.map +1 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_BASE_64741.d.ts +2 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_BASE_64741.js +553 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_BASE_64741.js.map +1 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_LOCAL_64741.d.ts +2 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_LOCAL_64741.js +650 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_LOCAL_64741.js.map +1 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_REMOTE_64741.d.ts +2 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_REMOTE_64741.js +639 -0
- package/dist/cjs/components/story-previewer/StoryPreviewer_REMOTE_64741.js.map +1 -0
- package/dist/cjs/constants/copy.d.ts +2 -0
- package/dist/cjs/constants/copy.js +6 -2
- package/dist/cjs/constants/copy.js.map +1 -1
- package/dist/cjs/index.d.ts +2 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/redux/actions/asset-list.js +5 -2
- package/dist/cjs/redux/actions/asset-list.js.map +1 -1
- package/dist/esm/components/font-picker/FontPicker.d.ts +44 -0
- package/dist/esm/components/font-picker/FontPicker.js +134 -0
- package/dist/esm/components/font-picker/FontPicker.js.map +1 -0
- package/dist/esm/components/font-picker/font-manager/FontManager.d.ts +26 -0
- package/dist/esm/components/font-picker/font-manager/FontManager.js +105 -0
- package/dist/esm/components/font-picker/font-manager/FontManager.js.map +1 -0
- package/dist/esm/components/font-picker/font-manager/constants.d.ts +4 -0
- package/dist/esm/components/font-picker/font-manager/constants.js +5 -0
- package/dist/esm/components/font-picker/font-manager/constants.js.map +1 -0
- package/dist/esm/components/font-picker/font-manager/fontStyle.d.ts +1 -0
- package/dist/esm/components/font-picker/font-manager/fontStyle.js +65 -0
- package/dist/esm/components/font-picker/font-manager/fontStyle.js.map +1 -0
- package/dist/esm/components/font-picker/font-manager/types.d.ts +25 -0
- package/dist/esm/components/font-picker/font-manager/types.js +9 -0
- package/dist/esm/components/font-picker/font-manager/types.js.map +1 -0
- package/dist/esm/components/font-picker/font-manager/utils.d.ts +3 -0
- package/dist/esm/components/font-picker/font-manager/utils.js +36 -0
- package/dist/esm/components/font-picker/font-manager/utils.js.map +1 -0
- package/dist/esm/components/publish-wizard/EmailWorkflow.d.ts +2 -0
- package/dist/esm/components/publish-wizard/EmailWorkflow.js +398 -0
- package/dist/esm/components/publish-wizard/EmailWorkflow.js.map +1 -0
- package/dist/esm/components/publish-wizard/copy.d.ts +186 -0
- package/dist/esm/components/publish-wizard/copy.js +196 -0
- package/dist/esm/components/publish-wizard/copy.js.map +1 -0
- package/dist/esm/components/story-previewer/StoryPreviewer.js +72 -10
- package/dist/esm/components/story-previewer/StoryPreviewer.js.map +1 -1
- package/dist/esm/components/story-previewer/StoryPreviewer_BACKUP_64741.d.ts +2 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_BACKUP_64741.js +554 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_BACKUP_64741.js.map +1 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_BASE_64741.d.ts +2 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_BASE_64741.js +489 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_BASE_64741.js.map +1 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_LOCAL_64741.d.ts +2 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_LOCAL_64741.js +537 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_LOCAL_64741.js.map +1 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_REMOTE_64741.d.ts +2 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_REMOTE_64741.js +526 -0
- package/dist/esm/components/story-previewer/StoryPreviewer_REMOTE_64741.js.map +1 -0
- package/dist/esm/constants/copy.d.ts +2 -0
- package/dist/esm/constants/copy.js +5 -1
- package/dist/esm/constants/copy.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +2 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/redux/actions/asset-list.js +5 -2
- package/dist/esm/redux/actions/asset-list.js.map +1 -1
- package/dist/styles.css +111 -0
- package/dist/styles.less +137 -0
- package/less/components/font-picker.less +131 -0
- package/less/components/story-previewer.less +5 -0
- package/less/entry.less +2 -1
- package/package.json +1 -1
- package/src/components/font-picker/FontPicker.tsx +222 -0
- package/src/components/font-picker/font-manager/FontManager.ts +138 -0
- package/src/components/font-picker/font-manager/constants.ts +7 -0
- package/src/components/font-picker/font-manager/fontStyle.ts +78 -0
- package/src/components/font-picker/font-manager/types.ts +83 -0
- package/src/components/font-picker/font-manager/utils.ts +36 -0
- package/src/components/story-previewer/StoryPreviewer.tsx +117 -24
- package/src/constants/copy.ts +6 -1
- package/src/index.ts +3 -1
- package/src/redux/actions/asset-list.ts +5 -3
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import FontManager from './font-manager/FontManager';
|
|
3
|
+
import {
|
|
4
|
+
Category,
|
|
5
|
+
Font,
|
|
6
|
+
Options,
|
|
7
|
+
Script,
|
|
8
|
+
Variant,
|
|
9
|
+
FontList,
|
|
10
|
+
OPTIONS_DEFAULTS
|
|
11
|
+
} from './font-manager/types';
|
|
12
|
+
import { FONT_FAMILY_DEFAULT } from './font-manager/constants';
|
|
13
|
+
import { createFontStyleSheets } from './font-manager/fontStyle';
|
|
14
|
+
|
|
15
|
+
interface IFontPickerProps {
|
|
16
|
+
apiKey: string;
|
|
17
|
+
activeFontFamily: string;
|
|
18
|
+
onChange: (font: string) => void;
|
|
19
|
+
families: string[];
|
|
20
|
+
categories: Category[];
|
|
21
|
+
scripts: Script[];
|
|
22
|
+
variants: Variant[];
|
|
23
|
+
filter: (font: Font) => boolean;
|
|
24
|
+
limit: number;
|
|
25
|
+
defaultFonts: any;
|
|
26
|
+
customFonts?: any;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
interface IFontPickerState {
|
|
30
|
+
expanded: boolean;
|
|
31
|
+
fonts: any;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default class FontPicker extends React.PureComponent<IFontPickerProps, IFontPickerState> {
|
|
35
|
+
fontManager: FontManager;
|
|
36
|
+
|
|
37
|
+
static defaultProps = {
|
|
38
|
+
activeFontFamily: FONT_FAMILY_DEFAULT,
|
|
39
|
+
families: OPTIONS_DEFAULTS.families,
|
|
40
|
+
categories: OPTIONS_DEFAULTS.categories,
|
|
41
|
+
scripts: OPTIONS_DEFAULTS.scripts,
|
|
42
|
+
variants: OPTIONS_DEFAULTS.variants,
|
|
43
|
+
filter: OPTIONS_DEFAULTS.filter,
|
|
44
|
+
limit: OPTIONS_DEFAULTS.limit
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
private clickOutsideHandler: any;
|
|
48
|
+
|
|
49
|
+
constructor(props: any) {
|
|
50
|
+
super(props);
|
|
51
|
+
|
|
52
|
+
const {
|
|
53
|
+
apiKey,
|
|
54
|
+
activeFontFamily,
|
|
55
|
+
families,
|
|
56
|
+
categories,
|
|
57
|
+
scripts,
|
|
58
|
+
variants,
|
|
59
|
+
filter,
|
|
60
|
+
limit,
|
|
61
|
+
onChange
|
|
62
|
+
} = this.props;
|
|
63
|
+
|
|
64
|
+
this.state = {
|
|
65
|
+
expanded: false,
|
|
66
|
+
fonts: null
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
const options: Options = {
|
|
70
|
+
families,
|
|
71
|
+
categories,
|
|
72
|
+
scripts,
|
|
73
|
+
variants,
|
|
74
|
+
filter,
|
|
75
|
+
limit
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
this.fontManager = new FontManager(apiKey, activeFontFamily, options, onChange);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
public compoenntDidMount(): void {
|
|
82
|
+
this.clickOutsideHandler = (e) => this.onClose(e);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
public componentWillUnmount(): void {
|
|
86
|
+
this.clickOutsideHandler = (e) => {
|
|
87
|
+
return;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public componentDidUpdate = (prevProps: any) => {
|
|
92
|
+
const { activeFontFamily, onChange, customFonts, defaultFonts } = this.props;
|
|
93
|
+
if (prevProps.customFonts !== customFonts) {
|
|
94
|
+
this.fontManager
|
|
95
|
+
.init()
|
|
96
|
+
.then((fontMap: FontList): void => {
|
|
97
|
+
const googleFonts = Array.from(fontMap.values()).filter((f) => f.files);
|
|
98
|
+
const updateDefaultFonts = defaultFonts.map(
|
|
99
|
+
(f: any) => googleFonts.find((o: any) => o.family === f.family) || f
|
|
100
|
+
);
|
|
101
|
+
const uniqueFontFamilies = new Set();
|
|
102
|
+
const uniqueFonts = updateDefaultFonts.filter((e: any) => {
|
|
103
|
+
const isDup = uniqueFontFamilies.has(e.family);
|
|
104
|
+
uniqueFontFamilies.add(e.family);
|
|
105
|
+
if (!isDup) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
return false;
|
|
109
|
+
});
|
|
110
|
+
this.setState({ fonts: uniqueFonts }, () =>
|
|
111
|
+
createFontStyleSheets(defaultFonts, uniqueFonts, customFonts)
|
|
112
|
+
);
|
|
113
|
+
})
|
|
114
|
+
.catch((err: Error): void => {
|
|
115
|
+
console.error('Error trying to fetch the list of available fonts');
|
|
116
|
+
console.error(err);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (activeFontFamily !== prevProps.activeFontFamily) {
|
|
121
|
+
this.setActiveFontFamily(activeFontFamily);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (onChange !== prevProps.onChange) {
|
|
125
|
+
this.fontManager.setOnChange(onChange);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
private onClose = (e) => {
|
|
130
|
+
let targetEl = e.target;
|
|
131
|
+
const fontPickerEl = document.getElementById(`font-picker`);
|
|
132
|
+
|
|
133
|
+
while (true) {
|
|
134
|
+
if (targetEl === fontPickerEl) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (targetEl.parentNode) {
|
|
138
|
+
targetEl = targetEl.parentNode;
|
|
139
|
+
} else {
|
|
140
|
+
this.toggleExpanded();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
private onSelection = (e): void => {
|
|
147
|
+
const activeFontFamily = e.target.textContent;
|
|
148
|
+
if (!activeFontFamily) {
|
|
149
|
+
throw Error(`Missing font family in clicked font button`);
|
|
150
|
+
}
|
|
151
|
+
this.setActiveFontFamily(activeFontFamily);
|
|
152
|
+
this.toggleExpanded();
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
private setActiveFontFamily = (activeFontFamily: string): void => {
|
|
156
|
+
this.fontManager.setActiveFont(activeFontFamily);
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
private generateFontList = () => {
|
|
160
|
+
const { activeFontFamily, families } = this.props;
|
|
161
|
+
|
|
162
|
+
return (
|
|
163
|
+
<ul className='font-list'>
|
|
164
|
+
{families.map((font) => {
|
|
165
|
+
const isActive = font === activeFontFamily;
|
|
166
|
+
return (
|
|
167
|
+
<li
|
|
168
|
+
key={font}
|
|
169
|
+
className='font-list-item'>
|
|
170
|
+
<button
|
|
171
|
+
type='button'
|
|
172
|
+
id={`font-button-${font}`}
|
|
173
|
+
className={`font-button ${isActive ? 'active-font' : ''}`}
|
|
174
|
+
onClick={this.onSelection}
|
|
175
|
+
onKeyDown={this.onSelection}
|
|
176
|
+
style={{ fontFamily: font }}>
|
|
177
|
+
{font}
|
|
178
|
+
</button>
|
|
179
|
+
</li>
|
|
180
|
+
);
|
|
181
|
+
})}
|
|
182
|
+
</ul>
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
private toggleExpanded = (): void => {
|
|
187
|
+
const { expanded } = this.state;
|
|
188
|
+
|
|
189
|
+
if (expanded) {
|
|
190
|
+
this.setState({
|
|
191
|
+
expanded: false
|
|
192
|
+
});
|
|
193
|
+
document.removeEventListener('click', this.clickOutsideHandler);
|
|
194
|
+
} else {
|
|
195
|
+
this.setState({
|
|
196
|
+
expanded: true
|
|
197
|
+
});
|
|
198
|
+
document.addEventListener('click', this.clickOutsideHandler);
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
public render = () => {
|
|
203
|
+
const { activeFontFamily } = this.props;
|
|
204
|
+
const { expanded } = this.state;
|
|
205
|
+
|
|
206
|
+
return (
|
|
207
|
+
<div
|
|
208
|
+
id={`font-picker`}
|
|
209
|
+
className={expanded ? 'expanded' : ''}>
|
|
210
|
+
<button
|
|
211
|
+
type='button'
|
|
212
|
+
className='dropdown-button'
|
|
213
|
+
onClick={this.toggleExpanded}
|
|
214
|
+
onKeyDown={this.toggleExpanded}>
|
|
215
|
+
<p className='dropdown-font-family'>{activeFontFamily}</p>
|
|
216
|
+
<p className='dropdown-icon finished' />
|
|
217
|
+
</button>
|
|
218
|
+
{this.generateFontList()}
|
|
219
|
+
</div>
|
|
220
|
+
);
|
|
221
|
+
};
|
|
222
|
+
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Font, FontList, Options, OPTIONS_DEFAULTS, Script } from './types';
|
|
2
|
+
import { FONT_FAMILY_DEFAULT, LIST_BASE_URL } from './constants';
|
|
3
|
+
import { getFontId, get } from './utils';
|
|
4
|
+
|
|
5
|
+
interface FontResponse extends Font {
|
|
6
|
+
subsets: Script[];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default class FontManager {
|
|
10
|
+
private readonly apiKey: string;
|
|
11
|
+
|
|
12
|
+
private readonly options: Options;
|
|
13
|
+
|
|
14
|
+
private onChange: (font: string) => void;
|
|
15
|
+
|
|
16
|
+
private fonts: FontList = new Map<string, Font>();
|
|
17
|
+
|
|
18
|
+
constructor(
|
|
19
|
+
apiKey: string,
|
|
20
|
+
defaultFamily: string = FONT_FAMILY_DEFAULT,
|
|
21
|
+
{
|
|
22
|
+
families = OPTIONS_DEFAULTS.families,
|
|
23
|
+
categories = OPTIONS_DEFAULTS.categories,
|
|
24
|
+
scripts = OPTIONS_DEFAULTS.scripts,
|
|
25
|
+
variants = OPTIONS_DEFAULTS.variants,
|
|
26
|
+
filter = OPTIONS_DEFAULTS.filter,
|
|
27
|
+
limit = OPTIONS_DEFAULTS.limit
|
|
28
|
+
}: Options,
|
|
29
|
+
|
|
30
|
+
onChange: (font: string) => void
|
|
31
|
+
) {
|
|
32
|
+
// Save parameters as class variables
|
|
33
|
+
this.apiKey = apiKey;
|
|
34
|
+
this.options = {
|
|
35
|
+
families,
|
|
36
|
+
categories,
|
|
37
|
+
scripts,
|
|
38
|
+
variants,
|
|
39
|
+
filter,
|
|
40
|
+
limit
|
|
41
|
+
};
|
|
42
|
+
this.onChange = onChange;
|
|
43
|
+
|
|
44
|
+
// Download default font and add it to the empty font list
|
|
45
|
+
this.addFont(defaultFamily);
|
|
46
|
+
this.setActiveFont(defaultFamily);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Fetch list of all fonts from Google Fonts API, filter it according to the class parameters and
|
|
51
|
+
* save them to the font map
|
|
52
|
+
*/
|
|
53
|
+
public async init(): Promise<FontList> {
|
|
54
|
+
// Get list of all fonts
|
|
55
|
+
const fonts = await this.getFontList(this.apiKey);
|
|
56
|
+
// Save desired fonts in the font map
|
|
57
|
+
for (const font of fonts) {
|
|
58
|
+
// const font = fonts[i];
|
|
59
|
+
// Exit once specified limit of number of fonts is reached
|
|
60
|
+
if (this.fonts.size >= this.options.limit) {
|
|
61
|
+
break;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (
|
|
65
|
+
// Skip default font if it is also contained in the list
|
|
66
|
+
!this.fonts.has(font.family) &&
|
|
67
|
+
// `families` parameter: Only keep fonts whose names are included in the provided array
|
|
68
|
+
(this.options.families.length === 0 ||
|
|
69
|
+
this.options.families.includes(font.family)) &&
|
|
70
|
+
// `categories` parameter: only keep fonts in categories from the provided array
|
|
71
|
+
(this.options.categories.length === 0 ||
|
|
72
|
+
this.options.categories.includes(font.category)) &&
|
|
73
|
+
// `scripts` parameter: Only keep fonts which are available in all specified scripts
|
|
74
|
+
this.options.scripts.every((script): boolean => font.scripts.includes(script)) &&
|
|
75
|
+
// `variants` parameter: Only keep fonts which contain all specified variants
|
|
76
|
+
this.options.variants.every((variant): boolean =>
|
|
77
|
+
font.variants.includes(variant)
|
|
78
|
+
) &&
|
|
79
|
+
// `filter` parameter: Only keep fonts for which the `filter` function evaluates to `true`
|
|
80
|
+
this.options.filter(font) === true
|
|
81
|
+
) {
|
|
82
|
+
// Font fulfils all requirements: Add it to font map
|
|
83
|
+
this.fonts.set(font.family, font);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return this.fonts;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private async getFontList(apiKey: string): Promise<Font[]> {
|
|
91
|
+
const url = new URL(LIST_BASE_URL);
|
|
92
|
+
url.searchParams.append('sort', 'popularity');
|
|
93
|
+
url.searchParams.append('key', apiKey);
|
|
94
|
+
const response = await get(url.href);
|
|
95
|
+
const fontsOriginal = JSON.parse(response).items;
|
|
96
|
+
return fontsOriginal.map((fontOriginal: FontResponse): Font => {
|
|
97
|
+
const { family, subsets, ...others } = fontOriginal;
|
|
98
|
+
return {
|
|
99
|
+
...others,
|
|
100
|
+
family,
|
|
101
|
+
id: getFontId(family),
|
|
102
|
+
scripts: subsets
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Add a new font to the font map and download its preview characters
|
|
109
|
+
*/
|
|
110
|
+
private addFont(fontFamily: string): void {
|
|
111
|
+
const font: Font = {
|
|
112
|
+
family: fontFamily,
|
|
113
|
+
id: getFontId(fontFamily),
|
|
114
|
+
variants: [],
|
|
115
|
+
category: 'display',
|
|
116
|
+
scripts: []
|
|
117
|
+
};
|
|
118
|
+
this.fonts.set(fontFamily, font);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Set the specified font as the active font and download it
|
|
123
|
+
*/
|
|
124
|
+
public setActiveFont(fontFamily: string): void {
|
|
125
|
+
const runOnChange = fontFamily !== 'Font not found';
|
|
126
|
+
|
|
127
|
+
if (runOnChange) {
|
|
128
|
+
this.onChange(fontFamily);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Update the onChange function (executed when changing the active font)
|
|
134
|
+
*/
|
|
135
|
+
public setOnChange(onChange: (font: string) => void): void {
|
|
136
|
+
this.onChange = onChange;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { FONT_BASE_URL, FONT_FACE_REGEX } from './constants';
|
|
2
|
+
import { get, getMatches } from './utils';
|
|
3
|
+
|
|
4
|
+
export const createFontStyleSheets = (
|
|
5
|
+
defaultFonts: any,
|
|
6
|
+
uniqueFonts: any,
|
|
7
|
+
availableFonts?: any
|
|
8
|
+
): void => {
|
|
9
|
+
defaultFonts.map((font: any) => {
|
|
10
|
+
const fonts = uniqueFonts.find((f: any) => f.family === font.family);
|
|
11
|
+
const fontId = font.name.toLowerCase().split(' ').join('-');
|
|
12
|
+
|
|
13
|
+
// non Google Font style
|
|
14
|
+
if (fonts?.file) {
|
|
15
|
+
fillFontStyleSheets(fontId, font);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// google font style
|
|
19
|
+
if (fonts?.files) {
|
|
20
|
+
const fontURL = new URL(FONT_BASE_URL);
|
|
21
|
+
fontURL.searchParams.append('family', `${font.family}:wght@${font.weight}`);
|
|
22
|
+
fontURL.searchParams.append('text', font.name);
|
|
23
|
+
fontURL.searchParams.append('font-display', 'swap');
|
|
24
|
+
get(fontURL.href)
|
|
25
|
+
.then((res) => {
|
|
26
|
+
const rule = getMatches(FONT_FACE_REGEX, res);
|
|
27
|
+
const updateFont = rule[rule.length - 1].replace(font.family, font.name);
|
|
28
|
+
fillFontStyleSheets(fontId, updateFont, font.name);
|
|
29
|
+
})
|
|
30
|
+
.catch((e) => console.error(e));
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
// custom font style
|
|
35
|
+
if (availableFonts) {
|
|
36
|
+
availableFonts.map((font: any) => {
|
|
37
|
+
const fontId = font.name.toLowerCase();
|
|
38
|
+
fillFontStyleSheets(fontId, font);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const fillFontStyleSheets = (fontId: string, font: any, fontName?: any) => {
|
|
44
|
+
let stylesheetNode = document.getElementById(`font-${fontId}`);
|
|
45
|
+
const { weight, file, url, name, family } = font;
|
|
46
|
+
|
|
47
|
+
const fontFamily = name !== family ? name : family;
|
|
48
|
+
const fontWeight = weight ? `font-weight: ${weight};` : '';
|
|
49
|
+
const fontUrl = file ? `fonts/${file}` : `${url}`;
|
|
50
|
+
|
|
51
|
+
if (stylesheetNode === null) {
|
|
52
|
+
stylesheetNode = stylesheetNode;
|
|
53
|
+
stylesheetNode = document.createElement('style');
|
|
54
|
+
if (stylesheetNode !== null) {
|
|
55
|
+
stylesheetNode.id = `font-${fontId}`;
|
|
56
|
+
stylesheetNode.setAttribute('data-is-preview', 'true');
|
|
57
|
+
|
|
58
|
+
// non-google and custom fonts style
|
|
59
|
+
if (fontFamily && fontFamily && fontUrl) {
|
|
60
|
+
stylesheetNode.textContent = `
|
|
61
|
+
@font-face {
|
|
62
|
+
font-family: ${fontFamily};
|
|
63
|
+
${fontWeight}
|
|
64
|
+
src: url(${fontUrl});
|
|
65
|
+
}`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (fontName) {
|
|
69
|
+
stylesheetNode.textContent = `
|
|
70
|
+
@font-face {
|
|
71
|
+
${font.replace(`'${fontName}'`, fontName)}
|
|
72
|
+
}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
document.head.appendChild(stylesheetNode);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export type Category = 'sans-serif' | 'serif' | 'display' | 'handwriting' | 'monospace';
|
|
2
|
+
|
|
3
|
+
export type Script =
|
|
4
|
+
| 'arabic'
|
|
5
|
+
| 'bengali'
|
|
6
|
+
| 'chinese-simplified'
|
|
7
|
+
| 'chinese-traditional'
|
|
8
|
+
| 'cyrillic'
|
|
9
|
+
| 'cyrillic-ext'
|
|
10
|
+
| 'devanagari'
|
|
11
|
+
| 'greek'
|
|
12
|
+
| 'greek-ext'
|
|
13
|
+
| 'gujarati'
|
|
14
|
+
| 'gurmukhi'
|
|
15
|
+
| 'hebrew'
|
|
16
|
+
| 'japanese'
|
|
17
|
+
| 'kannada'
|
|
18
|
+
| 'khmer'
|
|
19
|
+
| 'korean'
|
|
20
|
+
| 'latin'
|
|
21
|
+
| 'latin-ext'
|
|
22
|
+
| 'malayalam'
|
|
23
|
+
| 'myanmar'
|
|
24
|
+
| 'oriya'
|
|
25
|
+
| 'sinhala'
|
|
26
|
+
| 'tamil'
|
|
27
|
+
| 'telugu'
|
|
28
|
+
| 'thai'
|
|
29
|
+
| 'vietnamese';
|
|
30
|
+
|
|
31
|
+
export type SortOption = 'alphabet' | 'popularity';
|
|
32
|
+
|
|
33
|
+
export type Variant =
|
|
34
|
+
| '100'
|
|
35
|
+
| '100italic'
|
|
36
|
+
| '200'
|
|
37
|
+
| '200italic'
|
|
38
|
+
| '300'
|
|
39
|
+
| '300italic'
|
|
40
|
+
| 'regular'
|
|
41
|
+
| 'italic'
|
|
42
|
+
| '500'
|
|
43
|
+
| '500italic'
|
|
44
|
+
| '600'
|
|
45
|
+
| '600italic'
|
|
46
|
+
| '700'
|
|
47
|
+
| '700italic'
|
|
48
|
+
| '800'
|
|
49
|
+
| '800italic'
|
|
50
|
+
| '900'
|
|
51
|
+
| '900italic';
|
|
52
|
+
|
|
53
|
+
export interface Font {
|
|
54
|
+
family: string;
|
|
55
|
+
id: string;
|
|
56
|
+
category: Category;
|
|
57
|
+
scripts: Script[];
|
|
58
|
+
variants: Variant[];
|
|
59
|
+
kind?: string;
|
|
60
|
+
version?: string;
|
|
61
|
+
lastModified?: string;
|
|
62
|
+
files?: Record<Variant, string>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type FontList = Map<string, Font>;
|
|
66
|
+
|
|
67
|
+
export interface Options {
|
|
68
|
+
families: string[];
|
|
69
|
+
categories: Category[];
|
|
70
|
+
scripts: Script[];
|
|
71
|
+
variants: Variant[];
|
|
72
|
+
filter: (font: Font) => boolean;
|
|
73
|
+
limit: number;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export const OPTIONS_DEFAULTS: Options = {
|
|
77
|
+
families: [],
|
|
78
|
+
categories: [],
|
|
79
|
+
scripts: ['latin'],
|
|
80
|
+
variants: ['regular'],
|
|
81
|
+
filter: () => true,
|
|
82
|
+
limit: 50
|
|
83
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export const getFontId = (fontFamily: string): string => {
|
|
2
|
+
return fontFamily.replace(/\s+/g, '-').toLowerCase();
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export const get = (url: string): Promise<string> => {
|
|
6
|
+
return new Promise((resolve, reject): void => {
|
|
7
|
+
const request = new XMLHttpRequest();
|
|
8
|
+
request.overrideMimeType('application/json');
|
|
9
|
+
request.open('GET', url, true);
|
|
10
|
+
request.onreadystatechange = (): void => {
|
|
11
|
+
// Request has completed
|
|
12
|
+
if (request.readyState === 4) {
|
|
13
|
+
if (request.status !== 200) {
|
|
14
|
+
// On error
|
|
15
|
+
reject(new Error(`Response has status code ${request.status}`));
|
|
16
|
+
} else {
|
|
17
|
+
// On success
|
|
18
|
+
resolve(request.responseText);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
request.send();
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const getMatches = (regex: RegExp, str: string): string[] => {
|
|
27
|
+
const matches: string[] = [];
|
|
28
|
+
let match;
|
|
29
|
+
do {
|
|
30
|
+
match = regex.exec(str);
|
|
31
|
+
if (match) {
|
|
32
|
+
matches.push(match[1]);
|
|
33
|
+
}
|
|
34
|
+
} while (match);
|
|
35
|
+
return matches;
|
|
36
|
+
};
|