@cyberalien/svg-utils 1.1.4 → 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.
Files changed (123) hide show
  1. package/lib/components/export/merge.js +3 -1
  2. package/lib/components/helpers/content/stringify.d.ts +2 -2
  3. package/lib/components/helpers/content/stringify.js +4 -10
  4. package/lib/components/helpers/css/generate.d.ts +2 -1
  5. package/lib/components/helpers/css/generate.js +43 -46
  6. package/lib/components/helpers/filenames/css.d.ts +1 -1
  7. package/lib/components/helpers/filenames/css.js +2 -3
  8. package/lib/components/helpers/functions/custom.d.ts +14 -0
  9. package/lib/components/helpers/functions/custom.js +17 -0
  10. package/lib/components/helpers/functions/fallback.d.ts +8 -0
  11. package/lib/components/helpers/functions/fallback.js +53 -0
  12. package/lib/components/helpers/functions/innerhtml.d.ts +8 -0
  13. package/lib/components/helpers/functions/innerhtml.js +35 -0
  14. package/lib/components/helpers/functions/size.js +1 -1
  15. package/lib/components/helpers/imports/create.js +1 -2
  16. package/lib/components/helpers/imports/stringify.js +0 -2
  17. package/lib/components/helpers/imports/types.d.ts +0 -1
  18. package/lib/components/jsx.js +79 -8
  19. package/lib/components/prepare/iconify.d.ts +1 -1
  20. package/lib/components/prepare/iconify.js +6 -4
  21. package/lib/components/prepare/states.d.ts +8 -0
  22. package/lib/components/prepare/states.js +73 -0
  23. package/lib/components/raw.js +10 -7
  24. package/lib/components/svelte.js +73 -14
  25. package/lib/components/types/component.d.ts +2 -1
  26. package/lib/components/types/css.d.ts +1 -2
  27. package/lib/components/types/data.d.ts +0 -3
  28. package/lib/components/types/options.d.ts +9 -2
  29. package/lib/components/types/source.d.ts +21 -6
  30. package/lib/components/vue-func.js +71 -12
  31. package/lib/components/vue.js +70 -13
  32. package/lib/css/find/animations.d.ts +10 -0
  33. package/lib/css/find/animations.js +35 -0
  34. package/lib/css/find/classname.d.ts +5 -0
  35. package/lib/css/find/classname.js +14 -0
  36. package/lib/css/find/prop.d.ts +5 -0
  37. package/lib/css/find/prop.js +12 -0
  38. package/lib/css/minify.d.ts +2 -0
  39. package/lib/css/minify.js +5 -0
  40. package/lib/css/rules.d.ts +10 -0
  41. package/lib/css/rules.js +26 -0
  42. package/lib/css/stringify.d.ts +8 -2
  43. package/lib/css/stringify.js +16 -8
  44. package/lib/css/stylesheet.d.ts +0 -2
  45. package/lib/css/stylesheet.js +3 -3
  46. package/lib/css/types.d.ts +1 -1
  47. package/lib/helpers/data/compact.d.ts +20 -0
  48. package/lib/helpers/data/compact.js +38 -0
  49. package/lib/helpers/data/expand.d.ts +5 -0
  50. package/lib/helpers/data/expand.js +9 -0
  51. package/lib/helpers/reduce-motion.d.ts +2 -0
  52. package/lib/helpers/reduce-motion.js +3 -0
  53. package/lib/index.d.ts +15 -2
  54. package/lib/index.js +11 -2
  55. package/lib/svg-css/icon/css.d.ts +25 -0
  56. package/lib/svg-css/icon/css.js +57 -0
  57. package/lib/svg-css/icon/types.d.ts +45 -0
  58. package/lib/svg-css/icon/types.js +1 -0
  59. package/lib/svg-css/icon-set/add.d.ts +7 -0
  60. package/lib/svg-css/icon-set/add.js +52 -0
  61. package/lib/svg-css/icon-set/create.d.ts +6 -0
  62. package/lib/svg-css/icon-set/create.js +8 -0
  63. package/lib/svg-css/icon-set/get.d.ts +4 -0
  64. package/lib/svg-css/icon-set/get.js +92 -0
  65. package/lib/svg-css/icon-set/minify/expand.d.ts +10 -0
  66. package/lib/svg-css/icon-set/minify/expand.js +35 -0
  67. package/lib/svg-css/icon-set/minify/keys.d.ts +5 -0
  68. package/lib/svg-css/icon-set/minify/keys.js +9 -0
  69. package/lib/svg-css/icon-set/minify/minify.d.ts +19 -0
  70. package/lib/svg-css/icon-set/minify/minify.js +74 -0
  71. package/lib/svg-css/icon-set/types.d.ts +43 -0
  72. package/lib/svg-css/icon-set/types.js +1 -0
  73. package/lib/svg-css/states/cleanup-values.d.ts +6 -0
  74. package/lib/svg-css/states/cleanup-values.js +15 -0
  75. package/lib/svg-css/states/fallback/parse.d.ts +7 -0
  76. package/lib/svg-css/states/fallback/parse.js +46 -0
  77. package/lib/svg-css/states/fallback/stringify.d.ts +6 -0
  78. package/lib/svg-css/states/fallback/stringify.js +9 -0
  79. package/lib/svg-css/states/fallback/test.d.ts +9 -0
  80. package/lib/svg-css/states/fallback/test.js +21 -0
  81. package/lib/svg-css/states/fallback/types.d.ts +20 -0
  82. package/lib/svg-css/states/fallback/types.js +1 -0
  83. package/lib/svg-css/states/focus.d.ts +10 -0
  84. package/lib/svg-css/states/focus.js +14 -0
  85. package/lib/svg-css/states/generator.d.ts +19 -0
  86. package/lib/svg-css/states/generator.js +31 -0
  87. package/lib/svg-css/states/key.d.ts +6 -0
  88. package/lib/svg-css/states/key.js +22 -0
  89. package/lib/svg-css/states/object.d.ts +6 -0
  90. package/lib/svg-css/states/object.js +13 -0
  91. package/lib/svg-css/states/selector/helpers/iterate.d.ts +10 -0
  92. package/lib/svg-css/states/selector/helpers/iterate.js +71 -0
  93. package/lib/svg-css/states/selector/merge.d.ts +6 -0
  94. package/lib/svg-css/states/selector/merge.js +29 -0
  95. package/lib/svg-css/states/selector/parse.d.ts +13 -0
  96. package/lib/svg-css/states/selector/parse.js +74 -0
  97. package/lib/svg-css/states/selector/part/merge.d.ts +10 -0
  98. package/lib/svg-css/states/selector/part/merge.js +37 -0
  99. package/lib/svg-css/states/selector/part/split.d.ts +13 -0
  100. package/lib/svg-css/states/selector/part/split.js +60 -0
  101. package/lib/svg-css/states/selector/part/stringify.d.ts +9 -0
  102. package/lib/svg-css/states/selector/part/stringify.js +32 -0
  103. package/lib/svg-css/states/selector/split.d.ts +6 -0
  104. package/lib/svg-css/states/selector/split.js +29 -0
  105. package/lib/svg-css/states/selector/stringify.d.ts +8 -0
  106. package/lib/svg-css/states/selector/stringify.js +143 -0
  107. package/lib/svg-css/states/selector/sub/merge.d.ts +6 -0
  108. package/lib/svg-css/states/selector/sub/merge.js +36 -0
  109. package/lib/svg-css/states/selector/sub/split.d.ts +10 -0
  110. package/lib/svg-css/states/selector/sub/split.js +61 -0
  111. package/lib/svg-css/states/selector/sub/stringify.d.ts +6 -0
  112. package/lib/svg-css/states/selector/sub/stringify.js +17 -0
  113. package/lib/svg-css/states/selector/types.d.ts +37 -0
  114. package/lib/svg-css/states/selector/types.js +1 -0
  115. package/lib/svg-css/states/types.d.ts +9 -0
  116. package/lib/svg-css/states/types.js +1 -0
  117. package/lib/svg-css/states/validate.d.ts +6 -0
  118. package/lib/svg-css/states/validate.js +55 -0
  119. package/lib/svg-css/states/value.d.ts +10 -0
  120. package/lib/svg-css/states/value.js +15 -0
  121. package/package.json +8 -8
  122. package/lib/components/helpers/css/name.d.ts +0 -7
  123. package/lib/components/helpers/css/name.js +0 -12
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Find all values of a CSS property in content
3
+ */
4
+ function findCSSPropertyValues(content, property) {
5
+ const values = [];
6
+ content.matchAll(new RegExp(`${property}\\s*:\\s*([^;]+);`, "g")).forEach((match) => {
7
+ values.push(...match[1].split(",").map((part) => part.trim()));
8
+ });
9
+ return values;
10
+ }
11
+
12
+ export { findCSSPropertyValues };
@@ -0,0 +1,2 @@
1
+ declare function minifyCSS(value: string): string;
2
+ export { minifyCSS };
@@ -0,0 +1,5 @@
1
+ function minifyCSS(value) {
2
+ return value.replace(/\s+/g, " ").replace(/\s*([;:{}])\s*/g, "$1").replace(/;}/g, "}").trim();
3
+ }
4
+
5
+ export { minifyCSS };
@@ -0,0 +1,10 @@
1
+ import { CSSRules } from "./types.js";
2
+ /**
3
+ * Split rules string into object
4
+ */
5
+ declare function splitCSSRules(rules: CSSRules | string): CSSRules;
6
+ /**
7
+ * Merge rules
8
+ */
9
+ declare function mergeCSSRules(rules: CSSRules | string, oldRules?: CSSRules | string): CSSRules;
10
+ export { mergeCSSRules, splitCSSRules };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Split rules string into object
3
+ */
4
+ function splitCSSRules(rules) {
5
+ if (typeof rules === "string") {
6
+ const result = Object.create(null);
7
+ const parts = rules.split(";");
8
+ for (const part of parts) {
9
+ const [key, value] = part.split(":").map((s) => s.trim());
10
+ if (key && value) result[key] = value;
11
+ }
12
+ return result;
13
+ }
14
+ return rules;
15
+ }
16
+ /**
17
+ * Merge rules
18
+ */
19
+ function mergeCSSRules(rules, oldRules) {
20
+ return {
21
+ ...splitCSSRules(oldRules || {}),
22
+ ...splitCSSRules(rules)
23
+ };
24
+ }
25
+
26
+ export { mergeCSSRules, splitCSSRules };
@@ -7,8 +7,14 @@ declare function stringifyCSSRules(rules: CSSRules, depth?: number): string;
7
7
  * Stringify CSS selector with rules
8
8
  */
9
9
  declare function stringifyCSSSelector(selector: string, rules: string | CSSRules, depth?: number): string;
10
+ /**
11
+ * Convert animation frames to CSS string
12
+ *
13
+ * Does not include @keyframes block, only the content
14
+ */
15
+ declare function stringifyCSSAnimationFrames(keyframes: CSSKeyframes, depth?: number): string;
10
16
  /**
11
17
  * Stringify CSS keyframes
12
18
  */
13
- declare function stringifyCSSKeyframes(animationName: string, keyframes: CSSKeyframes, depth?: number): string;
14
- export { stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector };
19
+ declare function stringifyCSSKeyframes(animationName: string, keyframes: CSSKeyframes | string, depth?: number): string;
20
+ export { stringifyCSSAnimationFrames, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector };
@@ -17,15 +17,18 @@ function stringifyCSSRules(rules, depth = 1) {
17
17
  * Stringify CSS selector with rules
18
18
  */
19
19
  function stringifyCSSSelector(selector, rules, depth = 0) {
20
- const content = typeof rules === "string" ? rules : stringifyCSSRules(rules, depth + 1);
20
+ const content = typeof rules === "string" ? indent(depth + 1) + rules + "\n" : stringifyCSSRules(rules, depth + 1);
21
21
  if (!content.length) return "";
22
22
  const tab = indent(depth);
23
23
  return `${tab}${selector} {\n${content}${tab}}\n`;
24
24
  }
25
25
  /**
26
- * Stringify CSS keyframes
26
+ * Convert animation frames to CSS string
27
+ *
28
+ * Does not include @keyframes block, only the content
27
29
  */
28
- function stringifyCSSKeyframes(animationName, keyframes, depth = 0) {
30
+ function stringifyCSSAnimationFrames(keyframes, depth = 0) {
31
+ const lines = [];
29
32
  const prop = keyframes.prop;
30
33
  const values = /* @__PURE__ */ new Map();
31
34
  keyframes.frames.forEach((frame) => {
@@ -34,13 +37,18 @@ function stringifyCSSKeyframes(animationName, keyframes, depth = 0) {
34
37
  if (item) item.push(frame.time);
35
38
  else values.set(css, [frame.time]);
36
39
  });
37
- const lines = [];
38
- lines.push(`${indent(depth)}@keyframes ${animationName} {\n`);
39
40
  values.forEach((times, css) => {
40
41
  lines.push(`${indent(depth + 1)}${times.map((time) => `${(time * 100).toFixed(2).replace(/\.?0+$/, "")}%`).join(", ")} {\n${css}${indent(depth + 1)}}\n`);
41
42
  });
42
- lines.push("}\n");
43
- return lines.join("");
43
+ return lines.join("").trim();
44
+ }
45
+ /**
46
+ * Stringify CSS keyframes
47
+ */
48
+ function stringifyCSSKeyframes(animationName, keyframes, depth = 0) {
49
+ const content = typeof keyframes === "string" ? keyframes : stringifyCSSAnimationFrames(keyframes, depth);
50
+ if (content.includes("@keyframes")) return content;
51
+ return `${indent(depth)}@keyframes ${animationName} {\n${indent(depth + 1)}${content}\n}\n`;
44
52
  }
45
53
 
46
- export { stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector };
54
+ export { stringifyCSSAnimationFrames, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector };
@@ -5,8 +5,6 @@ import { CSSGeneratedStylesheet, CSSRules } from "./types.js";
5
5
  declare function createEmptyStylesheet(): CSSGeneratedStylesheet;
6
6
  /**
7
7
  * Add generated selector to stylesheet
8
- *
9
- * If item exists, it will be overwritten. Class names should be hashed to avoid conflicts, so this should not cause issues.
10
8
  */
11
9
  declare function addGeneratedSelector(stylesheet: CSSGeneratedStylesheet, tree: string[], rules: CSSRules | string): void;
12
10
  /**
@@ -1,4 +1,5 @@
1
1
  import { stringifyCSSKeyframes, stringifyCSSSelector } from "./stringify.js";
2
+ import { mergeCSSRules } from "./rules.js";
2
3
 
3
4
  /**
4
5
  * Create empty stylesheet
@@ -11,17 +12,16 @@ function createEmptyStylesheet() {
11
12
  }
12
13
  /**
13
14
  * Add generated selector to stylesheet
14
- *
15
- * If item exists, it will be overwritten. Class names should be hashed to avoid conflicts, so this should not cause issues.
16
15
  */
17
16
  function addGeneratedSelector(stylesheet, tree, rules) {
17
+ tree = tree.filter((item, index) => item.startsWith("@") ? tree.indexOf(item) === index : true);
18
18
  let parent = stylesheet.selectors;
19
19
  for (let i = 0; i < tree.length; i++) {
20
20
  const selector = tree[i];
21
21
  if (!parent[selector]) parent[selector] = {};
22
22
  const parentItem = parent[selector];
23
23
  if (i === tree.length - 1) {
24
- parentItem.rules = rules;
24
+ parentItem.rules = mergeCSSRules(rules, parentItem.rules);
25
25
  return;
26
26
  }
27
27
  if (!parentItem.nested) parentItem.nested = Object.create(null);
@@ -28,6 +28,6 @@ interface CSSGeneratedSelector {
28
28
  type CSSGeneratedSelectors = Record<string, CSSGeneratedSelector>;
29
29
  interface CSSGeneratedStylesheet {
30
30
  selectors: CSSGeneratedSelectors;
31
- keyframes: Record<string, CSSKeyframes>;
31
+ keyframes: Record<string, CSSKeyframes | string>;
32
32
  }
33
33
  export { CSSGeneratedSelector, CSSGeneratedSelectors, CSSGeneratedStylesheet, CSSHashOptions, CSSKeyframe, CSSKeyframes, CSSRules };
@@ -0,0 +1,20 @@
1
+ interface ContextItemData<T> {
2
+ parent: Record<string, unknown>;
3
+ key: string;
4
+ actualValue?: T;
5
+ }
6
+ interface ContextItem<T> {
7
+ map: Map<string, ContextItemData<T> | number>;
8
+ data: T[];
9
+ }
10
+ /**
11
+ * Create context item for minification
12
+ */
13
+ declare function createCompactContext<T>(): ContextItem<T>;
14
+ /**
15
+ * Minify item
16
+ *
17
+ * If value is not a string, set it in `actualValue` and string `value` for comparison
18
+ */
19
+ declare function compactItem<T>(context: ContextItem<T>, stringifiedValue: string, parent: Record<string, unknown>, key: string, actualValue?: T): void;
20
+ export { compactItem, createCompactContext };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Create context item for minification
3
+ */
4
+ function createCompactContext() {
5
+ return {
6
+ map: /* @__PURE__ */ new Map(),
7
+ data: []
8
+ };
9
+ }
10
+ /**
11
+ * Minify item
12
+ *
13
+ * If value is not a string, set it in `actualValue` and string `value` for comparison
14
+ */
15
+ function compactItem(context, stringifiedValue, parent, key, actualValue) {
16
+ const { map, data } = context;
17
+ const existing = map.get(stringifiedValue);
18
+ if (typeof existing === "number") {
19
+ parent[key] = existing;
20
+ return;
21
+ }
22
+ const value = actualValue ?? stringifiedValue;
23
+ if (existing) {
24
+ const index = data.length;
25
+ data.push(value);
26
+ map.set(stringifiedValue, index);
27
+ parent[key] = index;
28
+ existing.parent[existing.key] = index;
29
+ return;
30
+ }
31
+ map.set(stringifiedValue, {
32
+ parent,
33
+ key
34
+ });
35
+ parent[key] = value;
36
+ }
37
+
38
+ export { compactItem, createCompactContext };
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Expand minified item
3
+ */
4
+ declare function expandItem<T>(list: T[], parent: Record<string, unknown>, key: string): void;
5
+ export { expandItem };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Expand minified item
3
+ */
4
+ function expandItem(list, parent, key) {
5
+ const index = parent[key];
6
+ if (typeof index === "number" && list[index]) parent[key] = list[index];
7
+ }
8
+
9
+ export { expandItem };
@@ -0,0 +1,2 @@
1
+ declare const prefersReduceMotion = "@media not (prefers-reduced-motion)";
2
+ export { prefersReduceMotion };
@@ -0,0 +1,3 @@
1
+ const prefersReduceMotion = "@media not (prefers-reduced-motion)";
2
+
3
+ export { prefersReduceMotion };
package/lib/index.d.ts CHANGED
@@ -2,10 +2,15 @@ import { ClassProp, classProps, defaultClassProp } from "./classname/const.js";
2
2
  import { splitClassName, toggleClassName } from "./classname/toggle.js";
3
3
  import { HashContext, UniqueHashOptions, UniqueHashPartialOptions } from "./helpers/hash/types.js";
4
4
  import { CSSGeneratedSelector, CSSGeneratedSelectors, CSSGeneratedStylesheet, CSSHashOptions, CSSKeyframe, CSSKeyframes, CSSRules } from "./css/types.js";
5
+ import { IconStatesAdvancedState, IconStatesAdvancedStateValues, IconStatesList, IconStatesSimpleState, IconStatesState } from "./svg-css/states/types.js";
6
+ import { ExtendedSVGCSSIconClass, SVGCSSIcon, SVGCSSIconRules, SVGCSSStatefulIcon, SVGCSSStatefulIconRules } from "./svg-css/icon/types.js";
7
+ import { IconFallbackAdvancedState, IconFallbackBooleanState, IconFallbackTemplate } from "./svg-css/states/fallback/types.js";
5
8
  import { ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, StringifyXMLOptions } from "./xml/types.js";
6
9
  import { BaseConvertSVGContentOptions, ConvertSVGContentOptions, ConvertedSVGContent } from "./svg-css/types.js";
7
10
  import { createCSSClassName } from "./css/hash.js";
8
- import { stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector } from "./css/stringify.js";
11
+ import { minifyCSS } from "./css/minify.js";
12
+ import { mergeCSSRules, splitCSSRules } from "./css/rules.js";
13
+ import { stringifyCSSAnimationFrames, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector } from "./css/stringify.js";
9
14
  import { addGeneratedSelector, createEmptyStylesheet, stringifyStylesheet } from "./css/stylesheet.js";
10
15
  import { createUniqueHashContext } from "./helpers/hash/context.js";
11
16
  import { hashString } from "./helpers/hash/hash.js";
@@ -27,4 +32,12 @@ import { changeSVGIDs } from "./svg/ids/change.js";
27
32
  import { createUniqueIDs } from "./svg/ids/unique.js";
28
33
  import { convertSVGRootToCSS } from "./svg-css/root.js";
29
34
  import { convertSVGContentToCSSRules } from "./svg-css/content.js";
30
- export { BaseConvertSVGContentOptions, CSSGeneratedSelector, CSSGeneratedSelectors, CSSGeneratedStylesheet, CSSHashOptions, CSSKeyframe, CSSKeyframes, CSSRules, ChangeIDResult, ClassProp, ComparisonKey, ConvertSVGContentOptions, ConvertedSVGContent, HashContext, ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, StringifyXMLOptions, UniqueHashOptions, UniqueHashPartialOptions, UniqueIDOptions, addGeneratedSelector, changeIDInString, changeSVGIDs, classProps, cloneObject, compareKeys, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createEmptyStylesheet, createUniqueHashContext, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyStylesheet, stringifyXMLContent, toggleClassName, uniquePromise };
35
+ import { getIconFallback } from "./svg-css/states/fallback/stringify.js";
36
+ import { getStatesFromKey } from "./svg-css/states/key.js";
37
+ import { getObjectFromStates } from "./svg-css/states/object.js";
38
+ import { getAdvancedStateDefaultValue, getStateValue } from "./svg-css/states/value.js";
39
+ import { SVGCSSIconSet, SVGCSSIconSetClassData, SVGCSSIconSetIcon, SVGCSSIconSetSharedData } from "./svg-css/icon-set/types.js";
40
+ import { getSVGCSSIconFromIconSet } from "./svg-css/icon-set/get.js";
41
+ import { addIconToSVGCSSIconSet } from "./svg-css/icon-set/add.js";
42
+ import { createEmptySVGCSSIconSet } from "./svg-css/icon-set/create.js";
43
+ export { BaseConvertSVGContentOptions, CSSGeneratedSelector, CSSGeneratedSelectors, CSSGeneratedStylesheet, CSSHashOptions, CSSKeyframe, CSSKeyframes, CSSRules, ChangeIDResult, ClassProp, ComparisonKey, ConvertSVGContentOptions, ConvertedSVGContent, ExtendedSVGCSSIconClass, HashContext, IconFallbackAdvancedState, IconFallbackBooleanState, IconFallbackTemplate, IconStatesAdvancedState, IconStatesAdvancedStateValues, IconStatesList, IconStatesSimpleState, IconStatesState, ParsedXMLNode, ParsedXMLTagElement, ParsedXMLTextElement, SVGCSSIcon, SVGCSSIconRules, SVGCSSIconSet, SVGCSSIconSetClassData, SVGCSSIconSetIcon, SVGCSSIconSetSharedData, SVGCSSStatefulIcon, SVGCSSStatefulIconRules, StringifyXMLOptions, UniqueHashOptions, UniqueHashPartialOptions, UniqueIDOptions, addGeneratedSelector, addIconToSVGCSSIconSet, changeIDInString, changeSVGIDs, classProps, cloneObject, compareKeys, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createEmptySVGCSSIconSet, createEmptyStylesheet, createUniqueHashContext, createUniqueIDs, defaultClassProp, getAdvancedStateDefaultValue, getIconFallback, getObjectFromStates, getSVGCSSIconFromIconSet, getStateValue, getStatesFromKey, getUniqueHash, hashString, hashToString, iterateXMLContent, mergeCSSRules, minifyCSS, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitCSSRules, splitClassName, stringifyCSSAnimationFrames, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyStylesheet, stringifyXMLContent, toggleClassName, uniquePromise };
package/lib/index.js CHANGED
@@ -11,7 +11,9 @@ import { iterateXMLContent } from "./xml/iterate.js";
11
11
  import { parseXMLContent } from "./xml/parse.js";
12
12
  import { stringifyXMLContent } from "./xml/stringify.js";
13
13
  import { createCSSClassName } from "./css/hash.js";
14
- import { stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector } from "./css/stringify.js";
14
+ import { stringifyCSSAnimationFrames, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector } from "./css/stringify.js";
15
+ import { mergeCSSRules, splitCSSRules } from "./css/rules.js";
16
+ import { minifyCSS } from "./css/minify.js";
15
17
  import { addGeneratedSelector, createEmptyStylesheet, stringifyStylesheet } from "./css/stylesheet.js";
16
18
  import { classProps, defaultClassProp } from "./classname/const.js";
17
19
  import { splitClassName, toggleClassName } from "./classname/toggle.js";
@@ -22,5 +24,12 @@ import { changeSVGIDs } from "./svg/ids/change.js";
22
24
  import { createUniqueIDs } from "./svg/ids/unique.js";
23
25
  import { convertSVGRootToCSS } from "./svg-css/root.js";
24
26
  import { convertSVGContentToCSSRules } from "./svg-css/content.js";
27
+ import { getIconFallback } from "./svg-css/states/fallback/stringify.js";
28
+ import { getStatesFromKey } from "./svg-css/states/key.js";
29
+ import { getAdvancedStateDefaultValue, getStateValue } from "./svg-css/states/value.js";
30
+ import { getObjectFromStates } from "./svg-css/states/object.js";
31
+ import { getSVGCSSIconFromIconSet } from "./svg-css/icon-set/get.js";
32
+ import { addIconToSVGCSSIconSet } from "./svg-css/icon-set/add.js";
33
+ import { createEmptySVGCSSIconSet } from "./svg-css/icon-set/create.js";
25
34
 
26
- export { addGeneratedSelector, changeIDInString, changeSVGIDs, classProps, cloneObject, compareKeys, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createEmptyStylesheet, createUniqueHashContext, createUniqueIDs, defaultClassProp, getUniqueHash, hashString, hashToString, iterateXMLContent, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitClassName, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyStylesheet, stringifyXMLContent, toggleClassName, uniquePromise };
35
+ export { addGeneratedSelector, addIconToSVGCSSIconSet, changeIDInString, changeSVGIDs, classProps, cloneObject, compareKeys, compareSets, compareValues, convertSVGContentToCSSRules, convertSVGRootToCSS, createCSSClassName, createEmptySVGCSSIconSet, createEmptyStylesheet, createUniqueHashContext, createUniqueIDs, defaultClassProp, getAdvancedStateDefaultValue, getIconFallback, getObjectFromStates, getSVGCSSIconFromIconSet, getStateValue, getStatesFromKey, getUniqueHash, hashString, hashToString, iterateXMLContent, mergeCSSRules, minifyCSS, parseXMLContent, removeDuplicateIDs, removeUnusedIDs, sortObject, splitCSSRules, splitClassName, stringifyCSSAnimationFrames, stringifyCSSKeyframes, stringifyCSSRules, stringifyCSSSelector, stringifyStylesheet, stringifyXMLContent, toggleClassName, uniquePromise };
@@ -0,0 +1,25 @@
1
+ import { CSSGeneratedStylesheet } from "../../css/types.js";
2
+ import { SVGCSSIconRules, SVGCSSStatefulIconRules } from "./types.js";
3
+ import { StatefulIconSelectorsContext } from "../states/selector/types.js";
4
+ type StylesheetParam = CSSGeneratedStylesheet | ((selector: string) => CSSGeneratedStylesheet);
5
+ /**
6
+ * Add styles for stateful icon to stylesheet
7
+ *
8
+ * If commonStylesheet is an object, all styles will be added to it and result
9
+ * will contain the same stylesheet for all classes.
10
+ *
11
+ * If commonStylesheet is not an object, styles will be separated into different
12
+ * stylesheets for classes and keyframes, which can be reused across icons.
13
+ */
14
+ declare function renderStatefulSVGCSSIconStyle(icon: SVGCSSStatefulIconRules, context: StatefulIconSelectorsContext | null, commonStylesheet?: StylesheetParam): Record<string, CSSGeneratedStylesheet>;
15
+ /**
16
+ * Add styles for icon to stylesheet
17
+ *
18
+ * If commonStylesheet is an object, all styles will be added to it and result
19
+ * will contain the same stylesheet for all classes.
20
+ *
21
+ * If commonStylesheet is not an object, styles will be separated into different
22
+ * stylesheets for classes and keyframes, which can be reused across icons.
23
+ */
24
+ declare function renderSVGCSSIconStyle(icon: SVGCSSIconRules, commonStylesheet?: StylesheetParam): Record<string, CSSGeneratedStylesheet>;
25
+ export { renderSVGCSSIconStyle, renderStatefulSVGCSSIconStyle };
@@ -0,0 +1,57 @@
1
+ import { addGeneratedSelector, createEmptyStylesheet } from "../../css/stylesheet.js";
2
+ import { prefersReduceMotion } from "../../helpers/reduce-motion.js";
3
+ import { getSelectorsForStateValues } from "../states/selector/parse.js";
4
+
5
+ /**
6
+ * Add styles for stateful icon to stylesheet
7
+ *
8
+ * If commonStylesheet is an object, all styles will be added to it and result
9
+ * will contain the same stylesheet for all classes.
10
+ *
11
+ * If commonStylesheet is not an object, styles will be separated into different
12
+ * stylesheets for classes and keyframes, which can be reused across icons.
13
+ */
14
+ function renderStatefulSVGCSSIconStyle(icon, context, commonStylesheet = createEmptyStylesheet) {
15
+ const stylesheets = Object.create(null);
16
+ const getStylesheet = (className) => {
17
+ if (typeof commonStylesheet === "object") return commonStylesheet;
18
+ if (!stylesheets[className]) stylesheets[className] = commonStylesheet(className);
19
+ return stylesheets[className];
20
+ };
21
+ for (const className in icon.classes) addGeneratedSelector(getStylesheet(className), [`.${className}`], icon.classes[className]);
22
+ for (const className in icon.animations) addGeneratedSelector(getStylesheet(className), [prefersReduceMotion, `.${className}`], icon.animations[className]);
23
+ for (const keyframeName in icon.keyframes) getStylesheet(keyframeName).keyframes[keyframeName] = icon.keyframes[keyframeName];
24
+ if (context) for (const className in icon.statefulClasses) {
25
+ const baseClassName = `.${className}`;
26
+ const stylesheet = getStylesheet(className);
27
+ const classData = icon.statefulClasses[className];
28
+ if (classData.transition) addGeneratedSelector(getStylesheet(className), [prefersReduceMotion, baseClassName], classData.transition);
29
+ for (const stateKey in classData.stateRules) {
30
+ const selectors = getSelectorsForStateValues(context, stateKey);
31
+ if (selectors) for (const tree of selectors) addGeneratedSelector(stylesheet, [...tree, baseClassName], classData.stateRules[stateKey]);
32
+ }
33
+ for (const stateKey in classData.stateTransition) {
34
+ const selectors = getSelectorsForStateValues(context, stateKey);
35
+ if (selectors) for (const tree of selectors) addGeneratedSelector(stylesheet, [
36
+ prefersReduceMotion,
37
+ ...tree,
38
+ baseClassName
39
+ ], classData.stateTransition[stateKey]);
40
+ }
41
+ }
42
+ return stylesheets;
43
+ }
44
+ /**
45
+ * Add styles for icon to stylesheet
46
+ *
47
+ * If commonStylesheet is an object, all styles will be added to it and result
48
+ * will contain the same stylesheet for all classes.
49
+ *
50
+ * If commonStylesheet is not an object, styles will be separated into different
51
+ * stylesheets for classes and keyframes, which can be reused across icons.
52
+ */
53
+ function renderSVGCSSIconStyle(icon, commonStylesheet) {
54
+ return renderStatefulSVGCSSIconStyle(icon, null, commonStylesheet);
55
+ }
56
+
57
+ export { renderSVGCSSIconStyle, renderStatefulSVGCSSIconStyle };
@@ -0,0 +1,45 @@
1
+ import { CSSKeyframes, CSSRules } from "../../css/types.js";
2
+ import { IconViewBox } from "../../svg/viewbox/types.js";
3
+ import { IconStatesList } from "../states/types.js";
4
+ /**
5
+ * Main properties
6
+ */
7
+ interface MainProps {
8
+ viewBox: IconViewBox | string;
9
+ fallback?: string;
10
+ content: string;
11
+ }
12
+ interface StatefulMainProps extends MainProps {
13
+ states?: IconStatesList;
14
+ }
15
+ /**
16
+ * CSS data
17
+ */
18
+ interface SVGCSSIconRules {
19
+ classes?: Record<string, CSSRules | string>;
20
+ animations?: Record<string, CSSRules | string>;
21
+ keyframes?: Record<string, CSSKeyframes | string>;
22
+ }
23
+ /**
24
+ * Extended class interface for stateful icons
25
+ */
26
+ interface ExtendedSVGCSSIconClass {
27
+ stateRules?: Record<string, CSSRules | string>;
28
+ transition?: CSSRules | string;
29
+ stateTransition?: Record<string, CSSRules | string>;
30
+ }
31
+ /**
32
+ * Stateful CSS data
33
+ */
34
+ interface SVGCSSStatefulIconRules extends SVGCSSIconRules {
35
+ statefulClasses?: Record<string, ExtendedSVGCSSIconClass>;
36
+ }
37
+ /**
38
+ * Icon data
39
+ */
40
+ interface SVGCSSIcon extends MainProps, SVGCSSIconRules {}
41
+ /**
42
+ * Icon with states
43
+ */
44
+ interface SVGCSSStatefulIcon extends StatefulMainProps, SVGCSSStatefulIconRules {}
45
+ export { ExtendedSVGCSSIconClass, SVGCSSIcon, SVGCSSIconRules, SVGCSSStatefulIcon, SVGCSSStatefulIconRules };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,7 @@
1
+ import { SVGCSSIcon, SVGCSSStatefulIcon } from "../icon/types.js";
2
+ import { SVGCSSIconSet } from "./types.js";
3
+ /**
4
+ * Add icon to an icon set
5
+ */
6
+ declare function addIconToSVGCSSIconSet(iconSet: SVGCSSIconSet, iconName: string, icon: SVGCSSIcon | SVGCSSStatefulIcon): void;
7
+ export { addIconToSVGCSSIconSet };
@@ -0,0 +1,52 @@
1
+ import { stringifyCSSAnimationFrames, stringifyCSSRules } from "../../css/stringify.js";
2
+ import { minifyCSS } from "../../css/minify.js";
3
+
4
+ function minifyRules(value) {
5
+ return (value ? minifyCSS(typeof value === "string" ? value : stringifyCSSRules(value)) : void 0) || void 0;
6
+ }
7
+ function stringifyObject(data) {
8
+ if (data) {
9
+ const result = Object.create(null);
10
+ for (const key in data) result[key] = minifyCSS(typeof data[key] === "string" ? data[key] : stringifyCSSRules(data[key]));
11
+ return result;
12
+ }
13
+ }
14
+ /**
15
+ * Add icon to an icon set
16
+ */
17
+ function addIconToSVGCSSIconSet(iconSet, iconName, icon) {
18
+ iconSet.icons[iconName] = {
19
+ content: icon.content,
20
+ fallback: icon.fallback,
21
+ states: icon.states,
22
+ viewBox: icon.viewBox
23
+ };
24
+ const { classes, animations, statefulClasses, keyframes } = icon;
25
+ const classNames = new Set([...Object.keys(classes || {}), ...Object.keys(statefulClasses || {})]);
26
+ for (const className of classNames) if (!iconSet.classes?.[className]) {
27
+ const classData = {};
28
+ iconSet.classes = iconSet.classes || Object.create(null);
29
+ iconSet.classes[className] = classData;
30
+ const r = classes?.[className];
31
+ if (r) classData.r = minifyRules(r);
32
+ const a = animations?.[className];
33
+ if (a) classData.a = minifyRules(a);
34
+ const statefulClass = statefulClasses?.[className];
35
+ if (statefulClass) {
36
+ const { stateRules, transition, stateTransition } = statefulClass;
37
+ if (stateRules) classData.sr = stringifyObject(stateRules);
38
+ if (transition) classData.t = minifyRules(transition);
39
+ if (stateTransition) classData.st = stringifyObject(stateTransition);
40
+ }
41
+ }
42
+ if (keyframes) {
43
+ iconSet.keyframes = iconSet.keyframes || Object.create(null);
44
+ const iconSetKeyframes = iconSet.keyframes;
45
+ for (const keyframeName in keyframes) if (!iconSetKeyframes[keyframeName]) {
46
+ const value = keyframes[keyframeName];
47
+ iconSetKeyframes[keyframeName] = typeof value === "string" ? value : minifyCSS(stringifyCSSAnimationFrames(value));
48
+ }
49
+ }
50
+ }
51
+
52
+ export { addIconToSVGCSSIconSet };
@@ -0,0 +1,6 @@
1
+ import { SVGCSSIconSet } from "./types.js";
2
+ /**
3
+ * Create an empty icon set
4
+ */
5
+ declare function createEmptySVGCSSIconSet(): SVGCSSIconSet;
6
+ export { createEmptySVGCSSIconSet };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Create an empty icon set
3
+ */
4
+ function createEmptySVGCSSIconSet() {
5
+ return { icons: Object.create(null) };
6
+ }
7
+
8
+ export { createEmptySVGCSSIconSet };
@@ -0,0 +1,4 @@
1
+ import { SVGCSSIcon, SVGCSSStatefulIcon } from "../icon/types.js";
2
+ import { SVGCSSIconSet } from "./types.js";
3
+ declare function getSVGCSSIconFromIconSet(iconSet: SVGCSSIconSet, name: string): SVGCSSIcon | SVGCSSStatefulIcon | undefined;
4
+ export { getSVGCSSIconFromIconSet };
@@ -0,0 +1,92 @@
1
+ import { findUsedKeyframes } from "../../css/find/animations.js";
2
+ import { findUsedClassNames } from "../../css/find/classname.js";
3
+ import { expandSVGCSSIconSetClass } from "./minify/expand.js";
4
+
5
+ function getSVGCSSIconFromIconSet(iconSet, name) {
6
+ const fullName = iconSet.aliases?.[name] || name;
7
+ const data = iconSet.icons[fullName];
8
+ if (!data) return;
9
+ const { viewBoxes, css, fallbackPrefix = "", fallbackSuffix = "" } = iconSet;
10
+ let viewBox = data.viewBox;
11
+ if (typeof viewBox === "number") viewBox = viewBoxes?.[viewBox];
12
+ if (!viewBox) return;
13
+ let states = data.states;
14
+ if (typeof states === "number") states = iconSet.statesList?.[states];
15
+ const content = data.content;
16
+ const classNames = findUsedClassNames(content);
17
+ const classes = Object.create(null);
18
+ const animations = Object.create(null);
19
+ const statefulClasses = Object.create(null);
20
+ const cssLines = [];
21
+ classNames.forEach((className) => {
22
+ const classContent = iconSet.classes?.[className];
23
+ if (classContent) {
24
+ if (css) expandSVGCSSIconSetClass(css, classContent);
25
+ const { r, a, t, sr, st } = classContent;
26
+ const statefulClass = Object.create(null);
27
+ if (r) {
28
+ classes[className] = r;
29
+ cssLines.push(r);
30
+ }
31
+ if (a) {
32
+ animations[className] = a;
33
+ cssLines.push(a);
34
+ }
35
+ if (sr) {
36
+ const stateRules = Object.create(null);
37
+ statefulClass.stateRules = stateRules;
38
+ for (const state in sr) {
39
+ stateRules[state] = sr[state];
40
+ cssLines.push(sr[state]);
41
+ }
42
+ }
43
+ if (t) {
44
+ statefulClass.transition = t;
45
+ cssLines.push(t);
46
+ }
47
+ if (st) {
48
+ const stateTransition = Object.create(null);
49
+ statefulClass.stateTransition = stateTransition;
50
+ for (const state in st) {
51
+ stateTransition[state] = st[state];
52
+ cssLines.push(st[state]);
53
+ }
54
+ }
55
+ for (const key in statefulClass) {
56
+ statefulClasses[className] = statefulClass;
57
+ break;
58
+ }
59
+ }
60
+ });
61
+ const keyframes = Object.create(null);
62
+ if (iconSet.keyframes) findUsedKeyframes(cssLines.join(";")).forEach((animationName) => {
63
+ const keyframeContent = iconSet.keyframes[animationName];
64
+ if (keyframeContent) keyframes[animationName] = keyframeContent;
65
+ });
66
+ const result = {
67
+ content,
68
+ viewBox,
69
+ states,
70
+ fallback: typeof data.fallback === "string" ? `${fallbackPrefix}${data.fallback}${fallbackSuffix}` : void 0
71
+ };
72
+ let _key;
73
+ for (_key in classes) {
74
+ result.classes = classes;
75
+ break;
76
+ }
77
+ for (_key in animations) {
78
+ result.animations = animations;
79
+ break;
80
+ }
81
+ for (_key in keyframes) {
82
+ result.keyframes = keyframes;
83
+ break;
84
+ }
85
+ for (_key in statefulClasses) {
86
+ result.statefulClasses = statefulClasses;
87
+ break;
88
+ }
89
+ return result;
90
+ }
91
+
92
+ export { getSVGCSSIconFromIconSet };
@@ -0,0 +1,10 @@
1
+ import { SVGCSSIconSet, SVGCSSIconSetClassData } from "../types.js";
2
+ /**
3
+ * Expand class content from icon set
4
+ */
5
+ declare function expandSVGCSSIconSetClass(css: Required<SVGCSSIconSet>['css'], classContent: SVGCSSIconSetClassData): void;
6
+ /**
7
+ * Unminify icon set
8
+ */
9
+ declare function expandSVGCSSIconSet(iconSet: SVGCSSIconSet): void;
10
+ export { expandSVGCSSIconSet, expandSVGCSSIconSetClass };