@cyberalien/svg-utils 1.1.5 → 1.2.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/lib/components/export/merge.js +3 -1
- package/lib/components/helpers/content/stringify.d.ts +2 -2
- package/lib/components/helpers/content/stringify.js +4 -10
- package/lib/components/helpers/css/generate.d.ts +2 -1
- package/lib/components/helpers/css/generate.js +43 -46
- package/lib/components/helpers/filenames/css.d.ts +1 -1
- package/lib/components/helpers/filenames/css.js +2 -3
- package/lib/components/helpers/functions/custom.d.ts +14 -0
- package/lib/components/helpers/functions/custom.js +17 -0
- package/lib/components/helpers/functions/fallback.d.ts +8 -0
- package/lib/components/helpers/functions/fallback.js +53 -0
- package/lib/components/helpers/functions/innerhtml.d.ts +8 -0
- package/lib/components/helpers/functions/innerhtml.js +35 -0
- package/lib/components/helpers/functions/size.js +1 -1
- package/lib/components/helpers/imports/create.js +1 -2
- package/lib/components/helpers/imports/stringify.js +0 -2
- package/lib/components/helpers/imports/types.d.ts +0 -1
- package/lib/components/jsx.js +79 -8
- package/lib/components/prepare/iconify.d.ts +1 -1
- package/lib/components/prepare/iconify.js +6 -4
- package/lib/components/prepare/states.d.ts +8 -0
- package/lib/components/prepare/states.js +73 -0
- package/lib/components/raw.js +10 -7
- package/lib/components/svelte.js +73 -14
- package/lib/components/types/component.d.ts +2 -1
- package/lib/components/types/css.d.ts +1 -2
- package/lib/components/types/data.d.ts +0 -3
- package/lib/components/types/options.d.ts +9 -2
- package/lib/components/types/source.d.ts +21 -6
- package/lib/components/vue-func.js +71 -12
- package/lib/components/vue.js +70 -13
- package/lib/css/find/animations.d.ts +10 -0
- package/lib/css/find/animations.js +35 -0
- package/lib/css/find/classname.d.ts +5 -0
- package/lib/css/find/classname.js +14 -0
- package/lib/css/find/prop.d.ts +5 -0
- package/lib/css/find/prop.js +12 -0
- package/lib/css/minify.d.ts +2 -0
- package/lib/css/minify.js +5 -0
- package/lib/helpers/data/compact.d.ts +20 -0
- package/lib/helpers/data/compact.js +38 -0
- package/lib/helpers/data/expand.d.ts +5 -0
- package/lib/helpers/data/expand.js +9 -0
- package/lib/index.d.ts +9 -4
- package/lib/index.js +5 -1
- package/lib/svg-css/icon/css.d.ts +25 -0
- package/lib/svg-css/icon/{css/stateful.js → css.js} +17 -5
- package/lib/svg-css/icon/types.d.ts +3 -3
- package/lib/svg-css/icon-set/add.d.ts +7 -0
- package/lib/svg-css/icon-set/add.js +52 -0
- package/lib/svg-css/icon-set/create.d.ts +6 -0
- package/lib/svg-css/icon-set/create.js +8 -0
- package/lib/svg-css/icon-set/get.d.ts +4 -0
- package/lib/svg-css/icon-set/get.js +92 -0
- package/lib/svg-css/icon-set/minify/expand.d.ts +10 -0
- package/lib/svg-css/icon-set/minify/expand.js +35 -0
- package/lib/svg-css/icon-set/minify/keys.d.ts +5 -0
- package/lib/svg-css/icon-set/minify/keys.js +9 -0
- package/lib/svg-css/icon-set/minify/minify.d.ts +19 -0
- package/lib/svg-css/icon-set/minify/minify.js +74 -0
- package/lib/svg-css/icon-set/types.d.ts +43 -0
- package/lib/svg-css/icon-set/types.js +1 -0
- package/lib/svg-css/states/fallback/parse.d.ts +1 -1
- package/lib/svg-css/states/fallback/stringify.d.ts +1 -1
- package/lib/svg-css/states/fallback/stringify.js +3 -2
- package/lib/svg-css/states/fallback/test.d.ts +1 -1
- package/lib/svg-css/states/validate.d.ts +6 -0
- package/lib/svg-css/states/validate.js +55 -0
- package/package.json +8 -8
- package/lib/components/helpers/css/name.d.ts +0 -7
- package/lib/components/helpers/css/name.js +0 -12
- package/lib/svg-css/icon/css/basic.d.ts +0 -13
- package/lib/svg-css/icon/css/basic.js +0 -26
- package/lib/svg-css/icon/css/stateful.d.ts +0 -14
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { stringifyStylesheet } from "../../css/stylesheet.js";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Merge exported component files into single array
|
|
3
5
|
*/
|
|
@@ -18,7 +20,7 @@ function mergeExportedComponentFiles(items, files) {
|
|
|
18
20
|
add(item);
|
|
19
21
|
if (item.css && item.style) add({
|
|
20
22
|
filename: item.css,
|
|
21
|
-
content: item.style
|
|
23
|
+
content: stringifyStylesheet(item.style)
|
|
22
24
|
});
|
|
23
25
|
}
|
|
24
26
|
return files;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { CSSGeneratedStylesheet } from "../../../css/types.js";
|
|
1
2
|
import { ComponentFactorySource } from "../../types/source.js";
|
|
2
|
-
import { ComponentFactoryRenderingOptions } from "../../types/options.js";
|
|
3
3
|
/**
|
|
4
4
|
* Convert icon content to a string literal
|
|
5
5
|
*/
|
|
6
|
-
declare function stringifyFactoryIconContent(icon: ComponentFactorySource,
|
|
6
|
+
declare function stringifyFactoryIconContent(icon: Omit<ComponentFactorySource, 'viewBox' | 'fallback' | 'states'>, embedCSS?: CSSGeneratedStylesheet): string;
|
|
7
7
|
export { stringifyFactoryIconContent };
|
|
@@ -1,17 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { stringifyStylesheet } from "../../../css/stylesheet.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Convert icon content to a string literal
|
|
5
5
|
*/
|
|
6
|
-
function stringifyFactoryIconContent(icon,
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
switch (cssMode) {
|
|
10
|
-
case "module":
|
|
11
|
-
for (const className in icon.classes) content = content.replace(new RegExp("([\" ])(" + className + ")([\" ])", "g"), `$1\${${mergeCSS ? "css" : generateCSSDefaultImportName(className)}['${className}']}$3`);
|
|
12
|
-
return content;
|
|
13
|
-
default: return content;
|
|
14
|
-
}
|
|
6
|
+
function stringifyFactoryIconContent(icon, embedCSS) {
|
|
7
|
+
const style = embedCSS ? stringifyStylesheet(embedCSS) : "";
|
|
8
|
+
return "`" + (style ? `<style>${style}</style>${icon.content}` : icon.content).replace(/`/g, "\\`") + "`";
|
|
15
9
|
}
|
|
16
10
|
|
|
17
11
|
export { stringifyFactoryIconContent };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { CSSGeneratedStylesheet } from "../../../css/types.js";
|
|
1
2
|
import { GeneratedAssetFile } from "../../types/component.js";
|
|
2
3
|
import { ComponentFactorySource } from "../../types/source.js";
|
|
3
4
|
import { ComponentFactoryOptions } from "../../types/options.js";
|
|
@@ -10,5 +11,5 @@ interface Options extends Pick<ComponentFactoryOptions, 'cssMode' | 'cssPath' |
|
|
|
10
11
|
*
|
|
11
12
|
* Adds imports to imports object, adds assets
|
|
12
13
|
*/
|
|
13
|
-
declare function generateCSSFilesForComponent(content: ComponentFactorySource, imports: FactoryComponentImports, assets: GeneratedAssetFile[], options: Options):
|
|
14
|
+
declare function generateCSSFilesForComponent(content: Omit<ComponentFactorySource, 'viewBox'>, imports: FactoryComponentImports, assets: GeneratedAssetFile[], options: Options): CSSGeneratedStylesheet | undefined;
|
|
14
15
|
export { generateCSSFilesForComponent };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { generateCSSDefaultImportName } from "./name.js";
|
|
1
|
+
import { createEmptyStylesheet, stringifyStylesheet } from "../../../css/stylesheet.js";
|
|
3
2
|
import { getGeneratedCSSFilename } from "../filenames/css.js";
|
|
3
|
+
import { renderStatefulSVGCSSIconStyle } from "../../../svg-css/icon/css.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Generate CSS files for component
|
|
@@ -8,65 +8,62 @@ import { getGeneratedCSSFilename } from "../filenames/css.js";
|
|
|
8
8
|
* Adds imports to imports object, adds assets
|
|
9
9
|
*/
|
|
10
10
|
function generateCSSFilesForComponent(content, imports, assets, options) {
|
|
11
|
-
|
|
12
|
-
if (!classes) return;
|
|
11
|
+
if (!content.classes) return;
|
|
13
12
|
const { cssMode, componentType } = options;
|
|
14
13
|
const isComponent = cssMode === "embed";
|
|
15
14
|
const returnCSS = isComponent || cssMode === "prop";
|
|
16
|
-
const isModule = cssMode === "module";
|
|
17
15
|
const mergeCSS = (returnCSS || options.mergeCSS) ?? false;
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
16
|
+
const commonStylesheet = mergeCSS ? createEmptyStylesheet() : void 0;
|
|
17
|
+
const statefulData = content.statefulData;
|
|
18
|
+
const stylesheets = renderStatefulSVGCSSIconStyle(content, statefulData?.context ?? null, commonStylesheet);
|
|
19
|
+
if (isComponent && componentType === "svelte") {
|
|
20
|
+
const list = commonStylesheet ? [commonStylesheet] : Object.values(stylesheets);
|
|
21
|
+
const wrapSelectors = (selectors) => {
|
|
22
|
+
const keys = Object.keys(selectors);
|
|
23
|
+
for (const selector of keys) {
|
|
24
|
+
const value = selectors[selector];
|
|
25
|
+
if (!selector.startsWith("@")) {
|
|
26
|
+
delete selectors[selector];
|
|
27
|
+
const newSelector = selector.split(",").map((item) => `:global(${item.trim()})`).join(", ");
|
|
28
|
+
selectors[newSelector] = value;
|
|
29
|
+
}
|
|
30
|
+
if (value.nested) wrapSelectors(value.nested);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
for (const stylesheet of list) {
|
|
34
|
+
wrapSelectors(stylesheet.selectors);
|
|
35
|
+
const keyframes = stylesheet.keyframes;
|
|
36
|
+
const animations = Object.keys(keyframes);
|
|
37
|
+
for (const animationName of animations) {
|
|
38
|
+
const animation = keyframes[animationName];
|
|
39
|
+
delete keyframes[animationName];
|
|
40
|
+
keyframes["-global-" + animationName] = animation;
|
|
29
41
|
}
|
|
30
42
|
}
|
|
31
|
-
if (mergeCSS) {
|
|
32
|
-
mergedContent.push(content);
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
const filename = getGeneratedCSSFilename(className, options);
|
|
36
|
-
assets.push({
|
|
37
|
-
...filename,
|
|
38
|
-
content
|
|
39
|
-
});
|
|
40
|
-
if (isModule) imports.modules[filename.import] = generateCSSDefaultImportName(className);
|
|
41
|
-
else imports.css.add(filename.import);
|
|
42
43
|
}
|
|
43
|
-
if (!
|
|
44
|
-
const
|
|
45
|
-
const content =
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
if (!mergeCSS) for (const className in stylesheets) {
|
|
45
|
+
const stylesheet = stylesheets[className];
|
|
46
|
+
const content = stringifyStylesheet(stylesheet);
|
|
47
|
+
if (content) {
|
|
48
|
+
const filename = getGeneratedCSSFilename(className, options);
|
|
49
|
+
assets.push({
|
|
50
|
+
...filename,
|
|
51
|
+
content
|
|
52
|
+
});
|
|
53
|
+
imports.css.add(filename.import);
|
|
49
54
|
}
|
|
50
|
-
const filename = getGeneratedCSSFilename(animationName, options);
|
|
51
|
-
assets.push({
|
|
52
|
-
...filename,
|
|
53
|
-
content
|
|
54
|
-
});
|
|
55
|
-
if (isModule) imports.modules[filename.import] = generateCSSDefaultImportName(animationName);
|
|
56
|
-
else imports.css.add(filename.import);
|
|
57
55
|
}
|
|
58
|
-
if (mergeCSS
|
|
59
|
-
const content =
|
|
60
|
-
if (
|
|
56
|
+
else if (typeof mergeCSS == "object") {
|
|
57
|
+
const content = stringifyStylesheet(commonStylesheet);
|
|
58
|
+
if (content) {
|
|
61
59
|
assets.push({
|
|
62
60
|
...mergeCSS,
|
|
63
61
|
content
|
|
64
62
|
});
|
|
65
|
-
|
|
66
|
-
else if (!returnCSS) imports.css.add(mergeCSS.import);
|
|
63
|
+
imports.css.add(mergeCSS.import);
|
|
67
64
|
}
|
|
68
|
-
return returnCSS ? content : void 0;
|
|
69
65
|
}
|
|
66
|
+
return returnCSS ? commonStylesheet : void 0;
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
export { generateCSSFilesForComponent };
|
|
@@ -2,5 +2,5 @@ import { ComponentFactoryOptions, GeneratedAssetPath } from "../../types/options
|
|
|
2
2
|
/**
|
|
3
3
|
* Generate CSS filename based on options
|
|
4
4
|
*/
|
|
5
|
-
declare function getGeneratedCSSFilename(name: string, options: Pick<ComponentFactoryOptions, '
|
|
5
|
+
declare function getGeneratedCSSFilename(name: string, options: Pick<ComponentFactoryOptions, 'cssPath' | 'doubleDirsForCSS'>): GeneratedAssetPath;
|
|
6
6
|
export { getGeneratedCSSFilename };
|
|
@@ -4,9 +4,8 @@ import { getGeneratedAssetFilename } from "./asset.js";
|
|
|
4
4
|
* Generate CSS filename based on options
|
|
5
5
|
*/
|
|
6
6
|
function getGeneratedCSSFilename(name, options) {
|
|
7
|
-
const { cssPath, doubleDirsForCSS
|
|
8
|
-
|
|
9
|
-
return getGeneratedAssetFilename(cssMode === "module" ? `${baseName}.module.css` : `${baseName}.css`, cssPath);
|
|
7
|
+
const { cssPath, doubleDirsForCSS } = options;
|
|
8
|
+
return getGeneratedAssetFilename(`${doubleDirsForCSS ? `${name.slice(0, 1).toLowerCase()}/${name}` : name}.css`, cssPath);
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
export { getGeneratedCSSFilename };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { GeneratedAssetFile } from "../../types/component.js";
|
|
2
|
+
import { ComponentFactoryOptions } from "../../types/options.js";
|
|
3
|
+
import { FactoryComponentImports } from "../imports/types.js";
|
|
4
|
+
interface Data {
|
|
5
|
+
functionName: string;
|
|
6
|
+
content: string;
|
|
7
|
+
exportNames?: Set<string>;
|
|
8
|
+
jsName?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Adds a custom function to assets
|
|
12
|
+
*/
|
|
13
|
+
declare function addCustomFunctionAsset(imports: FactoryComponentImports, assets: GeneratedAssetFile[], options: Pick<ComponentFactoryOptions, 'rootPath' | 'helpersDirectory'>, data: Data): void;
|
|
14
|
+
export { addCustomFunctionAsset };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { defaultHelpersDirectory, getGeneratedAssetFilename } from "../filenames/asset.js";
|
|
2
|
+
import { camelToKebab } from "../../../helpers/misc/strings.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Adds a custom function to assets
|
|
6
|
+
*/
|
|
7
|
+
function addCustomFunctionAsset(imports, assets, options, data) {
|
|
8
|
+
const { functionName, content, exportNames } = data;
|
|
9
|
+
const filename = getGeneratedAssetFilename(`${options.helpersDirectory ?? defaultHelpersDirectory}/${data.jsName ?? camelToKebab(functionName)}.js`, options.rootPath);
|
|
10
|
+
assets.push({
|
|
11
|
+
...filename,
|
|
12
|
+
content
|
|
13
|
+
});
|
|
14
|
+
imports.named[filename.import] = exportNames ?? new Set([functionName]);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { addCustomFunctionAsset };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GeneratedAssetFile } from "../../types/component.js";
|
|
2
|
+
import { ComponentFactoryOptions } from "../../types/options.js";
|
|
3
|
+
import { FactoryComponentImports } from "../imports/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Adds getFallback() function to assets
|
|
6
|
+
*/
|
|
7
|
+
declare function addFallbackFunctionAsset(imports: FactoryComponentImports, assets: GeneratedAssetFile[], options: Pick<ComponentFactoryOptions, 'rootPath' | 'helpersDirectory'>, defaultValues: Record<string, boolean | string>): string;
|
|
8
|
+
export { addFallbackFunctionAsset };
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { createUniqueHashContext } from "../../../helpers/hash/context.js";
|
|
2
|
+
import { getUniqueHash } from "../../../helpers/hash/unique.js";
|
|
3
|
+
import { defaultHelpersDirectory, getGeneratedAssetFilename } from "../filenames/asset.js";
|
|
4
|
+
|
|
5
|
+
const sharedFunctionName = "getIconFallback";
|
|
6
|
+
const hashedFunctionName = "getFallback";
|
|
7
|
+
const functionContent = `
|
|
8
|
+
export function ${sharedFunctionName}(
|
|
9
|
+
defaultValues,
|
|
10
|
+
template,
|
|
11
|
+
values,
|
|
12
|
+
) {
|
|
13
|
+
const stateValue = (state) =>
|
|
14
|
+
values[state] ?? defaultValues?.[state];
|
|
15
|
+
return template
|
|
16
|
+
.map((chunk) =>
|
|
17
|
+
typeof chunk === 'string'
|
|
18
|
+
? chunk
|
|
19
|
+
: 'values' in chunk
|
|
20
|
+
? chunk.values[+!!stateValue(chunk.state)]
|
|
21
|
+
: stateValue(chunk.state)
|
|
22
|
+
)
|
|
23
|
+
.join('');
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
/**
|
|
27
|
+
* Adds getFallback() function to assets
|
|
28
|
+
*/
|
|
29
|
+
function addFallbackFunctionAsset(imports, assets, options, defaultValues) {
|
|
30
|
+
const hash = getUniqueHash(defaultValues, {
|
|
31
|
+
context: createUniqueHashContext(),
|
|
32
|
+
css: true,
|
|
33
|
+
length: 10
|
|
34
|
+
});
|
|
35
|
+
const assetDirectory = options.helpersDirectory ?? defaultHelpersDirectory;
|
|
36
|
+
const sharedFilename = getGeneratedAssetFilename(`${assetDirectory}/fallback.js`, options.rootPath);
|
|
37
|
+
assets.push({
|
|
38
|
+
...sharedFilename,
|
|
39
|
+
content: functionContent
|
|
40
|
+
});
|
|
41
|
+
const hashedFilename = getGeneratedAssetFilename(`${assetDirectory}/fallback-${hash}.js`, options.rootPath);
|
|
42
|
+
assets.push({
|
|
43
|
+
...hashedFilename,
|
|
44
|
+
content: `import { ${sharedFunctionName} } from './fallback.js';
|
|
45
|
+
|
|
46
|
+
export const ${hashedFunctionName} = ${sharedFunctionName}.bind(null, ${JSON.stringify(defaultValues)});
|
|
47
|
+
`
|
|
48
|
+
});
|
|
49
|
+
imports.named[hashedFilename.import] = new Set([hashedFunctionName]);
|
|
50
|
+
return hashedFunctionName;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { addFallbackFunctionAsset };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GeneratedAssetFile } from "../../types/component.js";
|
|
2
|
+
import { ComponentFactoryOptions } from "../../types/options.js";
|
|
3
|
+
import { FactoryComponentImports } from "../imports/types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Adds cleanUpInnerHTML() function to assets
|
|
6
|
+
*/
|
|
7
|
+
declare function addInnerHTMLFunctionAsset(imports: FactoryComponentImports, assets: GeneratedAssetFile[], options: Pick<ComponentFactoryOptions, 'rootPath' | 'helpersDirectory'>): string;
|
|
8
|
+
export { addInnerHTMLFunctionAsset };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { addCustomFunctionAsset } from "./custom.js";
|
|
2
|
+
|
|
3
|
+
const functionName = "cleanupHTML";
|
|
4
|
+
/**
|
|
5
|
+
* Adds cleanUpInnerHTML() function to assets
|
|
6
|
+
*/
|
|
7
|
+
function addInnerHTMLFunctionAsset(imports, assets, options) {
|
|
8
|
+
addCustomFunctionAsset(imports, assets, options, {
|
|
9
|
+
functionName,
|
|
10
|
+
content: `let policy;
|
|
11
|
+
|
|
12
|
+
function createPolicy() {
|
|
13
|
+
try {
|
|
14
|
+
policy = window.trustedTypes.createPolicy('iconify', {
|
|
15
|
+
createHTML: (s) => s,
|
|
16
|
+
});
|
|
17
|
+
} catch (err) {
|
|
18
|
+
policy = null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function ${functionName}(html) {
|
|
23
|
+
if (policy === undefined) {
|
|
24
|
+
createPolicy();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return policy ? policy.createHTML(html) : html;
|
|
28
|
+
}
|
|
29
|
+
`,
|
|
30
|
+
jsName: "innerhtml"
|
|
31
|
+
});
|
|
32
|
+
return functionName;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { addInnerHTMLFunctionAsset };
|
|
@@ -68,11 +68,11 @@ export { ${functionName} };
|
|
|
68
68
|
*/
|
|
69
69
|
function addSizeFunctionAsset(imports, assets, options) {
|
|
70
70
|
const filename = getGeneratedAssetFilename(`${options.helpersDirectory ?? defaultHelpersDirectory}/size.js`, options.rootPath);
|
|
71
|
-
imports.named[filename.import] = new Set([functionName]);
|
|
72
71
|
assets.push({
|
|
73
72
|
...filename,
|
|
74
73
|
content: functionContent
|
|
75
74
|
});
|
|
75
|
+
imports.named[filename.import] = new Set([functionName]);
|
|
76
76
|
return functionName;
|
|
77
77
|
}
|
|
78
78
|
|
|
@@ -15,7 +15,6 @@ function split(imports, relative) {
|
|
|
15
15
|
default: filterObject(imports.default),
|
|
16
16
|
named: filterObject(imports.named),
|
|
17
17
|
types: filterObject(imports.types),
|
|
18
|
-
modules: filterObject(imports.modules),
|
|
19
18
|
full: new Set([...imports.full].filter(shouldInclude)),
|
|
20
19
|
css: new Set([...imports.css].filter(shouldInclude))
|
|
21
20
|
};
|
|
@@ -38,7 +37,6 @@ function stringifyFactoryImports(imports, includeTypes = true) {
|
|
|
38
37
|
if (items) lines.push(`import type { ${items} } from '${source}';`);
|
|
39
38
|
}
|
|
40
39
|
for (const source of data.css) lines.push(`import '${source}';`);
|
|
41
|
-
for (const source in data.modules) lines.push(`import ${data.modules[source]} from '${source}';`);
|
|
42
40
|
}
|
|
43
41
|
if (lines.length) lines.push("");
|
|
44
42
|
return lines.join("\n");
|
package/lib/components/jsx.js
CHANGED
|
@@ -11,11 +11,18 @@ import { getUsedFactoryProps, stringifyFactoryPropTypes } from "./helpers/props/
|
|
|
11
11
|
import { minifyViewBox } from "../svg/viewbox/minify.js";
|
|
12
12
|
import { getViewBoxRatio } from "./helpers/content/ratio.js";
|
|
13
13
|
import { addJSXComponentTypes } from "./helpers/ts/jsx.js";
|
|
14
|
+
import { addCustomFunctionAsset } from "./helpers/functions/custom.js";
|
|
15
|
+
import { addFallbackFunctionAsset } from "./helpers/functions/fallback.js";
|
|
16
|
+
import { addInnerHTMLFunctionAsset } from "./helpers/functions/innerhtml.js";
|
|
14
17
|
|
|
15
18
|
/**
|
|
16
19
|
* Create functional Vue component code
|
|
17
20
|
*/
|
|
18
21
|
function createJSXComponent(data, options) {
|
|
22
|
+
const icon = data.icon;
|
|
23
|
+
const viewBox = icon.viewBox;
|
|
24
|
+
const defaultFallback = icon.defaultFallback;
|
|
25
|
+
const statefulData = icon.statefulData;
|
|
19
26
|
const useTS = options.ts ?? false;
|
|
20
27
|
const assets = [];
|
|
21
28
|
const imports = createFactoryImports();
|
|
@@ -29,17 +36,16 @@ function createJSXComponent(data, options) {
|
|
|
29
36
|
break;
|
|
30
37
|
}
|
|
31
38
|
const fallbackPackage = options.fallbackPackage || null;
|
|
32
|
-
const hasFallback = !!(fallbackPackage &&
|
|
39
|
+
const hasFallback = !!(fallbackPackage && defaultFallback);
|
|
33
40
|
if (hasFallback) {
|
|
34
41
|
imports.named[fallbackPackage] = new Set(["Icon"]);
|
|
35
42
|
dependencies.add(fallbackPackage);
|
|
36
43
|
}
|
|
37
44
|
const reactNamedImports = new Set([createElement]);
|
|
38
45
|
imports.named[importPackage] = reactNamedImports;
|
|
39
|
-
const style = generateCSSFilesForComponent(
|
|
46
|
+
const style = generateCSSFilesForComponent(icon, imports, assets, options);
|
|
40
47
|
const isEmbeddedCSS = options.cssMode === "embed";
|
|
41
48
|
let hasFixedSize = !!options.width && !!options.height;
|
|
42
|
-
const viewBox = data.viewBox;
|
|
43
49
|
const hasComputedViewbox = options.square && !hasFixedSize && viewBox.width !== viewBox.height;
|
|
44
50
|
const isStringViewBox = !hasFallback;
|
|
45
51
|
const hasComputedRatio = hasComputedViewbox && isStringViewBox;
|
|
@@ -52,6 +58,61 @@ function createJSXComponent(data, options) {
|
|
|
52
58
|
value: "props",
|
|
53
59
|
template: "...props,"
|
|
54
60
|
};
|
|
61
|
+
let computedFallback = false;
|
|
62
|
+
if (statefulData) {
|
|
63
|
+
const { supportedStates, allStates } = statefulData;
|
|
64
|
+
if (supportedStates.size) {
|
|
65
|
+
const computedStates = [];
|
|
66
|
+
const computedStateNames = [];
|
|
67
|
+
let addedStateFunc = false;
|
|
68
|
+
for (const state of allStates) if (typeof state === "string") {
|
|
69
|
+
if (supportedStates.has(state)) {
|
|
70
|
+
props[state] = {
|
|
71
|
+
type: "boolean",
|
|
72
|
+
value: state,
|
|
73
|
+
template: ""
|
|
74
|
+
};
|
|
75
|
+
computedStates.push(`'${state}': ${state}`);
|
|
76
|
+
computedStateNames.push(state);
|
|
77
|
+
}
|
|
78
|
+
} else {
|
|
79
|
+
const stateName = state[0];
|
|
80
|
+
if (supportedStates.has(stateName)) {
|
|
81
|
+
const stateValues = state[1];
|
|
82
|
+
const defaultStateValue = state[2] ?? stateValues[0];
|
|
83
|
+
props[stateName] = {
|
|
84
|
+
type: stateValues.map((value) => `'${value}'`).join(" | "),
|
|
85
|
+
value: stateName,
|
|
86
|
+
template: ""
|
|
87
|
+
};
|
|
88
|
+
computedStates.push(`'${stateName}': namedStateValue(${stateName}, '${defaultStateValue}')`);
|
|
89
|
+
computedStateNames.push(stateName);
|
|
90
|
+
if (!addedStateFunc) {
|
|
91
|
+
addedStateFunc = true;
|
|
92
|
+
addCustomFunctionAsset(imports, assets, options, {
|
|
93
|
+
functionName: "namedStateValue",
|
|
94
|
+
content: `export function namedStateValue(value, defaultValue) {
|
|
95
|
+
return value && value !== defaultValue ? value : undefined;
|
|
96
|
+
}`
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (computedStates.length) {
|
|
102
|
+
componentInternalCode.push(`const states = useMemo(() => ({ ${computedStates.join(", ")} }), [${computedStateNames.join(", ")}]);`);
|
|
103
|
+
if (hasFallback && statefulData.fallback) {
|
|
104
|
+
computedFallback = true;
|
|
105
|
+
const func = addFallbackFunctionAsset(imports, assets, options, statefulData.defaultStateValues);
|
|
106
|
+
componentInternalCode.push(`const fallback = useMemo(() => ${func}(${JSON.stringify(statefulData.fallback)}, states), [states]);`);
|
|
107
|
+
}
|
|
108
|
+
componentInternalCode.push(`const className = useMemo(() => Object.entries(states).map(([key, value]) => value ? \`state-\${value === true ? key : value}\` : '').join(' ').trim() || undefined, [states]);`);
|
|
109
|
+
props["className"] = {
|
|
110
|
+
value: "className",
|
|
111
|
+
template: `className,`
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
55
116
|
const getViewBox = (viewBox) => isStringViewBox ? `'${stringifyIconViewBox(viewBox)}'` : JSON.stringify(minifyViewBox(viewBox));
|
|
56
117
|
if (hasComputedViewbox) {
|
|
57
118
|
componentExternalCode.push(`const baseViewBox = ${getViewBox(viewBox)};`, `const squareViewBox = ${getViewBox(makeSquareViewBox(viewBox))};`);
|
|
@@ -60,7 +121,7 @@ function createJSXComponent(data, options) {
|
|
|
60
121
|
const ratioValue = getViewBoxRatio(viewBox);
|
|
61
122
|
if (hasComputedRatio) componentInternalCode.push(`const ratio = useMemo(() => square ? 1 : ${ratioValue}, [square]);`);
|
|
62
123
|
if (hasFixedSize) {
|
|
63
|
-
const sizeProps = getComponentSizeValues(options,
|
|
124
|
+
const sizeProps = getComponentSizeValues(options, viewBox);
|
|
64
125
|
if (!sizeProps) throw new Error("Fixed size expected, but could not be determined");
|
|
65
126
|
props.width = sizeProps.width;
|
|
66
127
|
props.height = sizeProps.height;
|
|
@@ -78,7 +139,6 @@ function createJSXComponent(data, options) {
|
|
|
78
139
|
} else {
|
|
79
140
|
const getSizeProps = addSizeFunctionAsset(imports, assets, options);
|
|
80
141
|
componentInternalCode.push(`const size = useMemo(() => ${getSizeProps}(width, height, ${hasComputedRatio ? "ratio" : ratioValue}), [width, height${hasComputedRatio ? ", ratio" : ""}]);`);
|
|
81
|
-
reactNamedImports.add("useMemo");
|
|
82
142
|
props.width = {
|
|
83
143
|
type: "string",
|
|
84
144
|
value: "width",
|
|
@@ -90,16 +150,27 @@ function createJSXComponent(data, options) {
|
|
|
90
150
|
template: ""
|
|
91
151
|
};
|
|
92
152
|
}
|
|
153
|
+
if (componentInternalCode.some((line) => line.includes("useMemo"))) reactNamedImports.add("useMemo");
|
|
93
154
|
if (options.square) props.square = { type: "boolean" };
|
|
94
155
|
props.viewBox = {
|
|
95
156
|
value: "viewBox",
|
|
96
157
|
template: "viewBox,"
|
|
97
158
|
};
|
|
159
|
+
let contentTemplate;
|
|
160
|
+
const contentValue = stringifyFactoryIconContent(data.icon, isEmbeddedCSS ? style : void 0);
|
|
161
|
+
if (!hasFallback) {
|
|
162
|
+
const funcName = addInnerHTMLFunctionAsset(imports, assets, options);
|
|
163
|
+
componentExternalCode.push(`const content = {__html: ${funcName}(${contentValue})};`);
|
|
164
|
+
contentTemplate = `dangerouslySetInnerHTML: content,`;
|
|
165
|
+
}
|
|
98
166
|
props.content = {
|
|
99
|
-
value:
|
|
100
|
-
template:
|
|
167
|
+
value: contentValue,
|
|
168
|
+
template: contentTemplate
|
|
101
169
|
};
|
|
102
|
-
if (hasFallback &&
|
|
170
|
+
if (hasFallback && defaultFallback) props.fallback = computedFallback ? {
|
|
171
|
+
value: "fallback",
|
|
172
|
+
template: "fallback,"
|
|
173
|
+
} : defaultFallback;
|
|
103
174
|
componentInternalCode.push(`return ${createElement}(${hasFallback ? "Icon" : "'svg'"}, {
|
|
104
175
|
\t\t${stringifyFactoryPropsAsJSON(props, "\n ")}
|
|
105
176
|
\t});`);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { GeneratedAssetFile } from "../types/component.js";
|
|
2
|
-
import { ConvertSVGContentOptions } from "../../svg-css/types.js";
|
|
3
2
|
import { FactoryIconData } from "../types/data.js";
|
|
4
3
|
import { GeneratedAssetPath } from "../types/options.js";
|
|
4
|
+
import { ConvertSVGContentOptions } from "../../svg-css/types.js";
|
|
5
5
|
import { IconifyIcon, IconifyJSON } from "@iconify/types";
|
|
6
6
|
interface Options extends ConvertSVGContentOptions {
|
|
7
7
|
fallback?: string | boolean;
|
|
@@ -8,13 +8,15 @@ import { normaliseIconifyIcon } from "../../iconify/icon/nornalise.js";
|
|
|
8
8
|
function convertIconifyIconToFactoryContent(icon, prefix, name, options) {
|
|
9
9
|
const { body, viewBox } = normaliseIconifyIcon(icon);
|
|
10
10
|
const fallbackOption = options?.fallback ?? true;
|
|
11
|
-
const
|
|
11
|
+
const defaultFallback = typeof fallbackOption === "string" ? fallbackOption : fallbackOption ? `${prefix}:${name}` : void 0;
|
|
12
12
|
return {
|
|
13
13
|
prefix,
|
|
14
14
|
name,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
icon: {
|
|
16
|
+
...convertSVGContentToCSSRules(body, options),
|
|
17
|
+
viewBox,
|
|
18
|
+
defaultFallback
|
|
19
|
+
}
|
|
18
20
|
};
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { SVGCSSStatefulIcon } from "../../svg-css/icon/types.js";
|
|
2
|
+
import { ComponentFactorySource } from "../types/source.js";
|
|
3
|
+
import { ComponentFactoryStatefulIconRenderingOptions } from "../types/options.js";
|
|
4
|
+
/**
|
|
5
|
+
* Check states for stateful icon
|
|
6
|
+
*/
|
|
7
|
+
declare function prepareComponentFactoryStatefulIcon(icon: SVGCSSStatefulIcon, options?: ComponentFactoryStatefulIconRenderingOptions): ComponentFactorySource | undefined;
|
|
8
|
+
export { prepareComponentFactoryStatefulIcon };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { getStateValue } from "../../svg-css/states/value.js";
|
|
2
|
+
import { createStatefulIconSelectorsContext } from "../../svg-css/states/selector/parse.js";
|
|
3
|
+
import { parseIconFallbackTemplate } from "../../svg-css/states/fallback/parse.js";
|
|
4
|
+
import { parseViewBox } from "../../svg/viewbox/parse.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check states for stateful icon
|
|
8
|
+
*/
|
|
9
|
+
function prepareComponentFactoryStatefulIcon(icon, options) {
|
|
10
|
+
const viewBox = typeof icon.viewBox === "string" ? parseViewBox(icon.viewBox) : icon.viewBox;
|
|
11
|
+
if (!viewBox) return;
|
|
12
|
+
const newIcon = {
|
|
13
|
+
...icon,
|
|
14
|
+
viewBox
|
|
15
|
+
};
|
|
16
|
+
const fallback = icon.fallback;
|
|
17
|
+
const isStatefulFallback = fallback?.includes("{");
|
|
18
|
+
if (!isStatefulFallback && fallback) newIcon.defaultFallback = fallback;
|
|
19
|
+
const allStates = icon.states;
|
|
20
|
+
if (!allStates) return newIcon;
|
|
21
|
+
const config = Object.create(null);
|
|
22
|
+
const customConfig = options?.stateSelectors;
|
|
23
|
+
const supportedStates = /* @__PURE__ */ new Set();
|
|
24
|
+
const defaultStateValues = Object.create(null);
|
|
25
|
+
const supportedStateValues = Object.create(null);
|
|
26
|
+
for (const state of allStates) {
|
|
27
|
+
const stateName = typeof state === "string" ? state : state[0];
|
|
28
|
+
const defaultValue = getStateValue(state);
|
|
29
|
+
defaultStateValues[stateName] = defaultValue;
|
|
30
|
+
if (customConfig?.[stateName]) config[stateName] = customConfig[stateName];
|
|
31
|
+
else {
|
|
32
|
+
if (state === "focus") config[stateName] = ".svg-focus-anchor:focus-within, .svg-hover-anchor:hover, &.state-focus";
|
|
33
|
+
else config[stateName] = `&.state-{state}`;
|
|
34
|
+
supportedStates.add(stateName);
|
|
35
|
+
supportedStateValues[stateName] = defaultValue;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const statefulData = {
|
|
39
|
+
allStates,
|
|
40
|
+
supportedStates,
|
|
41
|
+
defaultStateValues,
|
|
42
|
+
supportedStateValues,
|
|
43
|
+
context: createStatefulIconSelectorsContext(config, allStates)
|
|
44
|
+
};
|
|
45
|
+
if (isStatefulFallback) {
|
|
46
|
+
let fallbackTemplate = parseIconFallbackTemplate(fallback, allStates);
|
|
47
|
+
if (!fallbackTemplate) return newIcon;
|
|
48
|
+
let defaultFallback = "";
|
|
49
|
+
let hasStatefulFallback = false;
|
|
50
|
+
fallbackTemplate = fallbackTemplate.map((item) => {
|
|
51
|
+
if (typeof item === "string") {
|
|
52
|
+
defaultFallback += item;
|
|
53
|
+
return item;
|
|
54
|
+
}
|
|
55
|
+
const stateName = item.state;
|
|
56
|
+
const defaultValue = defaultStateValues[stateName] || stateName;
|
|
57
|
+
defaultFallback += defaultValue;
|
|
58
|
+
if (supportedStates.has(stateName)) {
|
|
59
|
+
hasStatefulFallback = true;
|
|
60
|
+
return item;
|
|
61
|
+
}
|
|
62
|
+
return defaultValue;
|
|
63
|
+
});
|
|
64
|
+
if (hasStatefulFallback) statefulData.fallback = fallbackTemplate;
|
|
65
|
+
newIcon.defaultFallback = defaultFallback;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
...newIcon,
|
|
69
|
+
statefulData
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export { prepareComponentFactoryStatefulIcon };
|