@bit.rhplus/ui2.emoji-icons 0.0.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.
- package/dist/index.d.ts +13 -0
- package/dist/index.js +182 -0
- package/dist/index.js.map +1 -0
- package/dist/preview-1764590989376.js +7 -0
- package/index.jsx +213 -0
- package/package.json +25 -0
- package/types/asset.d.ts +43 -0
- package/types/style.d.ts +42 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function preloadIcons(iconNames: string[]): Promise<void>;
|
|
2
|
+
export function clearIconCache(): void;
|
|
3
|
+
export default EmojiIcon;
|
|
4
|
+
/**
|
|
5
|
+
* Komponenta pro zobrazení FluentEmoji ikon s automatickým cachováním
|
|
6
|
+
*
|
|
7
|
+
* @param {string} name - Název ikony (např. 'airplane', 'warning')
|
|
8
|
+
* @param {number} size - Velikost ikony v pixelech
|
|
9
|
+
*
|
|
10
|
+
* Příklad použití:
|
|
11
|
+
* <EmojiIcon name="airplane" size={20} />
|
|
12
|
+
*/
|
|
13
|
+
declare function EmojiIcon({ name, size }: string): import("react/jsx-runtime").JSX.Element;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
import React, { useState, useEffect } from 'react';
|
|
4
|
+
// Cache pro načtené ikony (in-memory)
|
|
5
|
+
const iconCache = new Map();
|
|
6
|
+
const loadingIcons = new Set();
|
|
7
|
+
// Lokální storage klíč pro persistentní cache
|
|
8
|
+
const CACHE_KEY = 'fluent-emoji-cache';
|
|
9
|
+
const CACHE_VERSION = '1.2';
|
|
10
|
+
// Načtení cache z localStorage při inicializaci
|
|
11
|
+
const loadCacheFromStorage = () => {
|
|
12
|
+
try {
|
|
13
|
+
const stored = localStorage.getItem(CACHE_KEY);
|
|
14
|
+
if (stored) {
|
|
15
|
+
const { version, data } = JSON.parse(stored);
|
|
16
|
+
if (version === CACHE_VERSION && data) {
|
|
17
|
+
Object.entries(data).forEach(([iconName, iconData]) => {
|
|
18
|
+
if (iconData && typeof iconData === 'object') {
|
|
19
|
+
iconCache.set(iconName, iconData);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
console.log(`Loaded ${Object.keys(data).length} icons from cache`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
console.warn('Failed to load icon cache from localStorage:', e);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
// Uložení cache do localStorage
|
|
31
|
+
const saveCacheToStorage = () => {
|
|
32
|
+
try {
|
|
33
|
+
const data = Object.fromEntries(iconCache);
|
|
34
|
+
localStorage.setItem(CACHE_KEY, JSON.stringify({
|
|
35
|
+
version: CACHE_VERSION,
|
|
36
|
+
data
|
|
37
|
+
}));
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
console.warn('Failed to save icon cache to localStorage:', e);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
// Inicializace cache při načtení modulu
|
|
44
|
+
loadCacheFromStorage();
|
|
45
|
+
/**
|
|
46
|
+
* Komponenta pro zobrazení FluentEmoji ikon s automatickým cachováním
|
|
47
|
+
*
|
|
48
|
+
* @param {string} name - Název ikony (např. 'airplane', 'warning')
|
|
49
|
+
* @param {number} size - Velikost ikony v pixelech
|
|
50
|
+
*
|
|
51
|
+
* Příklad použití:
|
|
52
|
+
* <EmojiIcon name="airplane" size={20} />
|
|
53
|
+
*/
|
|
54
|
+
const EmojiIcon = ({ name, size = 20 }) => {
|
|
55
|
+
const iconName = name; // Jen název bez prefixu
|
|
56
|
+
const [iconData, setIconData] = useState(iconCache.get(iconName) || null);
|
|
57
|
+
useEffect(() => {
|
|
58
|
+
// Pokud už je ikona v cache, použijeme ji okamžitě
|
|
59
|
+
if (iconCache.has(iconName)) {
|
|
60
|
+
setIconData(iconCache.get(iconName));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// Pokud se ikona již načítá, počkáme
|
|
64
|
+
if (loadingIcons.has(iconName)) {
|
|
65
|
+
const checkInterval = setInterval(() => {
|
|
66
|
+
if (iconCache.has(iconName)) {
|
|
67
|
+
setIconData(iconCache.get(iconName));
|
|
68
|
+
clearInterval(checkInterval);
|
|
69
|
+
}
|
|
70
|
+
}, 50);
|
|
71
|
+
const timeout = setTimeout(() => {
|
|
72
|
+
clearInterval(checkInterval);
|
|
73
|
+
}, 5000);
|
|
74
|
+
return () => {
|
|
75
|
+
clearInterval(checkInterval);
|
|
76
|
+
clearTimeout(timeout);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
// Označíme ikonu jako načítající se
|
|
80
|
+
loadingIcons.add(iconName);
|
|
81
|
+
// Načteme ikonu z Iconify API
|
|
82
|
+
fetch(`https://api.iconify.design/fluent-emoji-flat.json?icons=${iconName}`)
|
|
83
|
+
.then(res => res.json())
|
|
84
|
+
.then(data => {
|
|
85
|
+
if (data && data.icons && data.icons[iconName]) {
|
|
86
|
+
const newIconData = {
|
|
87
|
+
body: data.icons[iconName].body,
|
|
88
|
+
width: data.width || 32,
|
|
89
|
+
height: data.height || 32
|
|
90
|
+
};
|
|
91
|
+
// Uložíme do naší cache
|
|
92
|
+
iconCache.set(iconName, newIconData);
|
|
93
|
+
saveCacheToStorage();
|
|
94
|
+
setIconData(newIconData);
|
|
95
|
+
loadingIcons.delete(iconName);
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
.catch(e => {
|
|
99
|
+
console.warn(`Failed to load icon ${iconName}:`, e);
|
|
100
|
+
loadingIcons.delete(iconName);
|
|
101
|
+
});
|
|
102
|
+
}, [iconName]);
|
|
103
|
+
// Pokud nemáme data, zobrazíme placeholder
|
|
104
|
+
if (!iconData) {
|
|
105
|
+
return (_jsx("span", { style: {
|
|
106
|
+
display: 'inline-block',
|
|
107
|
+
width: size,
|
|
108
|
+
height: size,
|
|
109
|
+
opacity: 0.3
|
|
110
|
+
} }));
|
|
111
|
+
}
|
|
112
|
+
// Renderujeme SVG přímo z cache
|
|
113
|
+
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: `0 0 ${iconData.width} ${iconData.height}`, style: {
|
|
114
|
+
display: 'inline-block',
|
|
115
|
+
verticalAlign: 'middle'
|
|
116
|
+
}, dangerouslySetInnerHTML: { __html: iconData.body } }));
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* Funkce pro předběžné načtení ikon do cache
|
|
120
|
+
* Volej před prvním renderem pro načtení důležitých ikon
|
|
121
|
+
*
|
|
122
|
+
* @param {string[]} iconNames - Pole názvů ikon k načtení
|
|
123
|
+
*
|
|
124
|
+
* Příklad:
|
|
125
|
+
* preloadIcons(['airplane', 'warning', 'envelope']);
|
|
126
|
+
*/
|
|
127
|
+
export const preloadIcons = async (iconNames) => {
|
|
128
|
+
// Filtrujeme pouze ty, které ještě nejsou v cache
|
|
129
|
+
const iconsToLoad = iconNames.filter(name => {
|
|
130
|
+
return !iconCache.has(name) && !loadingIcons.has(name);
|
|
131
|
+
});
|
|
132
|
+
if (iconsToLoad.length === 0) {
|
|
133
|
+
console.log('All icons already cached');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Označíme všechny jako načítající se
|
|
137
|
+
iconsToLoad.forEach(name => {
|
|
138
|
+
loadingIcons.add(name);
|
|
139
|
+
});
|
|
140
|
+
try {
|
|
141
|
+
// Načteme všechny ikony najednou
|
|
142
|
+
const iconsParam = iconsToLoad.join(',');
|
|
143
|
+
const response = await fetch(`https://api.iconify.design/fluent-emoji-flat.json?icons=${iconsParam}`);
|
|
144
|
+
const data = await response.json();
|
|
145
|
+
if (data && data.icons) {
|
|
146
|
+
Object.entries(data.icons).forEach(([name, iconInfo]) => {
|
|
147
|
+
const iconData = {
|
|
148
|
+
body: iconInfo.body,
|
|
149
|
+
width: data.width || 32,
|
|
150
|
+
height: data.height || 32
|
|
151
|
+
};
|
|
152
|
+
// Uložíme do naší cache
|
|
153
|
+
iconCache.set(name, iconData);
|
|
154
|
+
loadingIcons.delete(name);
|
|
155
|
+
});
|
|
156
|
+
// Uložíme celou cache do localStorage
|
|
157
|
+
saveCacheToStorage();
|
|
158
|
+
console.log(`Preloaded ${Object.keys(data.icons).length} icons`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch (e) {
|
|
162
|
+
console.warn('Failed to preload icons:', e);
|
|
163
|
+
// Odstraníme z loading state
|
|
164
|
+
iconsToLoad.forEach(name => {
|
|
165
|
+
loadingIcons.delete(name);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
/**
|
|
170
|
+
* Vymazání cache ikon
|
|
171
|
+
*/
|
|
172
|
+
export const clearIconCache = () => {
|
|
173
|
+
iconCache.clear();
|
|
174
|
+
try {
|
|
175
|
+
localStorage.removeItem(CACHE_KEY);
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
console.warn('Failed to clear icon cache:', e);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
export default EmojiIcon;
|
|
182
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.jsx"],"names":[],"mappings":"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"}
|
package/index.jsx
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
import React, { useState, useEffect } from 'react';
|
|
3
|
+
|
|
4
|
+
// Cache pro načtené ikony (in-memory)
|
|
5
|
+
const iconCache = new Map();
|
|
6
|
+
const loadingIcons = new Set();
|
|
7
|
+
|
|
8
|
+
// Lokální storage klíč pro persistentní cache
|
|
9
|
+
const CACHE_KEY = 'fluent-emoji-cache';
|
|
10
|
+
const CACHE_VERSION = '1.2';
|
|
11
|
+
|
|
12
|
+
// Načtení cache z localStorage při inicializaci
|
|
13
|
+
const loadCacheFromStorage = () => {
|
|
14
|
+
try {
|
|
15
|
+
const stored = localStorage.getItem(CACHE_KEY);
|
|
16
|
+
if (stored) {
|
|
17
|
+
const { version, data } = JSON.parse(stored);
|
|
18
|
+
if (version === CACHE_VERSION && data) {
|
|
19
|
+
Object.entries(data).forEach(([iconName, iconData]) => {
|
|
20
|
+
if (iconData && typeof iconData === 'object') {
|
|
21
|
+
iconCache.set(iconName, iconData);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
console.log(`Loaded ${Object.keys(data).length} icons from cache`);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
} catch (e) {
|
|
28
|
+
console.warn('Failed to load icon cache from localStorage:', e);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Uložení cache do localStorage
|
|
33
|
+
const saveCacheToStorage = () => {
|
|
34
|
+
try {
|
|
35
|
+
const data = Object.fromEntries(iconCache);
|
|
36
|
+
localStorage.setItem(CACHE_KEY, JSON.stringify({
|
|
37
|
+
version: CACHE_VERSION,
|
|
38
|
+
data
|
|
39
|
+
}));
|
|
40
|
+
} catch (e) {
|
|
41
|
+
console.warn('Failed to save icon cache to localStorage:', e);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// Inicializace cache při načtení modulu
|
|
46
|
+
loadCacheFromStorage();
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Komponenta pro zobrazení FluentEmoji ikon s automatickým cachováním
|
|
50
|
+
*
|
|
51
|
+
* @param {string} name - Název ikony (např. 'airplane', 'warning')
|
|
52
|
+
* @param {number} size - Velikost ikony v pixelech
|
|
53
|
+
*
|
|
54
|
+
* Příklad použití:
|
|
55
|
+
* <EmojiIcon name="airplane" size={20} />
|
|
56
|
+
*/
|
|
57
|
+
const EmojiIcon = ({ name, size = 20 }) => {
|
|
58
|
+
const iconName = name; // Jen název bez prefixu
|
|
59
|
+
const [iconData, setIconData] = useState(iconCache.get(iconName) || null);
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
// Pokud už je ikona v cache, použijeme ji okamžitě
|
|
63
|
+
if (iconCache.has(iconName)) {
|
|
64
|
+
setIconData(iconCache.get(iconName));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Pokud se ikona již načítá, počkáme
|
|
69
|
+
if (loadingIcons.has(iconName)) {
|
|
70
|
+
const checkInterval = setInterval(() => {
|
|
71
|
+
if (iconCache.has(iconName)) {
|
|
72
|
+
setIconData(iconCache.get(iconName));
|
|
73
|
+
clearInterval(checkInterval);
|
|
74
|
+
}
|
|
75
|
+
}, 50);
|
|
76
|
+
|
|
77
|
+
const timeout = setTimeout(() => {
|
|
78
|
+
clearInterval(checkInterval);
|
|
79
|
+
}, 5000);
|
|
80
|
+
|
|
81
|
+
return () => {
|
|
82
|
+
clearInterval(checkInterval);
|
|
83
|
+
clearTimeout(timeout);
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Označíme ikonu jako načítající se
|
|
88
|
+
loadingIcons.add(iconName);
|
|
89
|
+
|
|
90
|
+
// Načteme ikonu z Iconify API
|
|
91
|
+
fetch(`https://api.iconify.design/fluent-emoji-flat.json?icons=${iconName}`)
|
|
92
|
+
.then(res => res.json())
|
|
93
|
+
.then(data => {
|
|
94
|
+
if (data && data.icons && data.icons[iconName]) {
|
|
95
|
+
const newIconData = {
|
|
96
|
+
body: data.icons[iconName].body,
|
|
97
|
+
width: data.width || 32,
|
|
98
|
+
height: data.height || 32
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Uložíme do naší cache
|
|
102
|
+
iconCache.set(iconName, newIconData);
|
|
103
|
+
saveCacheToStorage();
|
|
104
|
+
setIconData(newIconData);
|
|
105
|
+
loadingIcons.delete(iconName);
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
.catch(e => {
|
|
109
|
+
console.warn(`Failed to load icon ${iconName}:`, e);
|
|
110
|
+
loadingIcons.delete(iconName);
|
|
111
|
+
});
|
|
112
|
+
}, [iconName]);
|
|
113
|
+
|
|
114
|
+
// Pokud nemáme data, zobrazíme placeholder
|
|
115
|
+
if (!iconData) {
|
|
116
|
+
return (
|
|
117
|
+
<span
|
|
118
|
+
style={{
|
|
119
|
+
display: 'inline-block',
|
|
120
|
+
width: size,
|
|
121
|
+
height: size,
|
|
122
|
+
opacity: 0.3
|
|
123
|
+
}}
|
|
124
|
+
/>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Renderujeme SVG přímo z cache
|
|
129
|
+
return (
|
|
130
|
+
<svg
|
|
131
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
132
|
+
width={size}
|
|
133
|
+
height={size}
|
|
134
|
+
viewBox={`0 0 ${iconData.width} ${iconData.height}`}
|
|
135
|
+
style={{
|
|
136
|
+
display: 'inline-block',
|
|
137
|
+
verticalAlign: 'middle'
|
|
138
|
+
}}
|
|
139
|
+
dangerouslySetInnerHTML={{ __html: iconData.body }}
|
|
140
|
+
/>
|
|
141
|
+
);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Funkce pro předběžné načtení ikon do cache
|
|
146
|
+
* Volej před prvním renderem pro načtení důležitých ikon
|
|
147
|
+
*
|
|
148
|
+
* @param {string[]} iconNames - Pole názvů ikon k načtení
|
|
149
|
+
*
|
|
150
|
+
* Příklad:
|
|
151
|
+
* preloadIcons(['airplane', 'warning', 'envelope']);
|
|
152
|
+
*/
|
|
153
|
+
export const preloadIcons = async (iconNames) => {
|
|
154
|
+
// Filtrujeme pouze ty, které ještě nejsou v cache
|
|
155
|
+
const iconsToLoad = iconNames.filter(name => {
|
|
156
|
+
return !iconCache.has(name) && !loadingIcons.has(name);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (iconsToLoad.length === 0) {
|
|
160
|
+
console.log('All icons already cached');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Označíme všechny jako načítající se
|
|
165
|
+
iconsToLoad.forEach(name => {
|
|
166
|
+
loadingIcons.add(name);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
// Načteme všechny ikony najednou
|
|
171
|
+
const iconsParam = iconsToLoad.join(',');
|
|
172
|
+
const response = await fetch(`https://api.iconify.design/fluent-emoji-flat.json?icons=${iconsParam}`);
|
|
173
|
+
const data = await response.json();
|
|
174
|
+
|
|
175
|
+
if (data && data.icons) {
|
|
176
|
+
Object.entries(data.icons).forEach(([name, iconInfo]) => {
|
|
177
|
+
const iconData = {
|
|
178
|
+
body: iconInfo.body,
|
|
179
|
+
width: data.width || 32,
|
|
180
|
+
height: data.height || 32
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Uložíme do naší cache
|
|
184
|
+
iconCache.set(name, iconData);
|
|
185
|
+
loadingIcons.delete(name);
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// Uložíme celou cache do localStorage
|
|
189
|
+
saveCacheToStorage();
|
|
190
|
+
console.log(`Preloaded ${Object.keys(data.icons).length} icons`);
|
|
191
|
+
}
|
|
192
|
+
} catch (e) {
|
|
193
|
+
console.warn('Failed to preload icons:', e);
|
|
194
|
+
// Odstraníme z loading state
|
|
195
|
+
iconsToLoad.forEach(name => {
|
|
196
|
+
loadingIcons.delete(name);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Vymazání cache ikon
|
|
203
|
+
*/
|
|
204
|
+
export const clearIconCache = () => {
|
|
205
|
+
iconCache.clear();
|
|
206
|
+
try {
|
|
207
|
+
localStorage.removeItem(CACHE_KEY);
|
|
208
|
+
} catch (e) {
|
|
209
|
+
console.warn('Failed to clear icon cache:', e);
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export default EmojiIcon;
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bit.rhplus/ui2.emoji-icons",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "dist/index.js",
|
|
5
|
+
"componentId": {
|
|
6
|
+
"name": "ui2/emoji-icons",
|
|
7
|
+
"version": "0.0.1",
|
|
8
|
+
"scope": "remote-scope"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@teambit/react.react-env": "1.0.132"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"react": "^17.0.0 || ^18.0.0"
|
|
16
|
+
},
|
|
17
|
+
"license": "SEE LICENSE IN UNLICENSED",
|
|
18
|
+
"optionalDependencies": {},
|
|
19
|
+
"peerDependenciesMeta": {},
|
|
20
|
+
"private": false,
|
|
21
|
+
"publishConfig": {
|
|
22
|
+
"scope": "@bit.rhplus",
|
|
23
|
+
"registry": "https://registry.npmjs.org/"
|
|
24
|
+
}
|
|
25
|
+
}
|
package/types/asset.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
declare module '*.png' {
|
|
2
|
+
const value: any;
|
|
3
|
+
export = value;
|
|
4
|
+
}
|
|
5
|
+
declare module '*.svg' {
|
|
6
|
+
import type { FunctionComponent, SVGProps } from 'react';
|
|
7
|
+
|
|
8
|
+
export const ReactComponent: FunctionComponent<
|
|
9
|
+
SVGProps<SVGSVGElement> & { title?: string }
|
|
10
|
+
>;
|
|
11
|
+
const src: string;
|
|
12
|
+
export default src;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// @TODO Gilad
|
|
16
|
+
declare module '*.jpg' {
|
|
17
|
+
const value: any;
|
|
18
|
+
export = value;
|
|
19
|
+
}
|
|
20
|
+
declare module '*.jpeg' {
|
|
21
|
+
const value: any;
|
|
22
|
+
export = value;
|
|
23
|
+
}
|
|
24
|
+
declare module '*.gif' {
|
|
25
|
+
const value: any;
|
|
26
|
+
export = value;
|
|
27
|
+
}
|
|
28
|
+
declare module '*.bmp' {
|
|
29
|
+
const value: any;
|
|
30
|
+
export = value;
|
|
31
|
+
}
|
|
32
|
+
declare module '*.otf' {
|
|
33
|
+
const value: any;
|
|
34
|
+
export = value;
|
|
35
|
+
}
|
|
36
|
+
declare module '*.woff' {
|
|
37
|
+
const value: any;
|
|
38
|
+
export = value;
|
|
39
|
+
}
|
|
40
|
+
declare module '*.woff2' {
|
|
41
|
+
const value: any;
|
|
42
|
+
export = value;
|
|
43
|
+
}
|
package/types/style.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
declare module '*.module.css' {
|
|
2
|
+
const classes: { readonly [key: string]: string };
|
|
3
|
+
export default classes;
|
|
4
|
+
}
|
|
5
|
+
declare module '*.module.scss' {
|
|
6
|
+
const classes: { readonly [key: string]: string };
|
|
7
|
+
export default classes;
|
|
8
|
+
}
|
|
9
|
+
declare module '*.module.sass' {
|
|
10
|
+
const classes: { readonly [key: string]: string };
|
|
11
|
+
export default classes;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
declare module '*.module.less' {
|
|
15
|
+
const classes: { readonly [key: string]: string };
|
|
16
|
+
export default classes;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare module '*.less' {
|
|
20
|
+
const classes: { readonly [key: string]: string };
|
|
21
|
+
export default classes;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
declare module '*.css' {
|
|
25
|
+
const classes: { readonly [key: string]: string };
|
|
26
|
+
export default classes;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
declare module '*.sass' {
|
|
30
|
+
const classes: { readonly [key: string]: string };
|
|
31
|
+
export default classes;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
declare module '*.scss' {
|
|
35
|
+
const classes: { readonly [key: string]: string };
|
|
36
|
+
export default classes;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
declare module '*.mdx' {
|
|
40
|
+
const component: any;
|
|
41
|
+
export default component;
|
|
42
|
+
}
|