@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,74 @@
1
+ import { getStatesFromKey } from "../key.js";
2
+ import { mergeSelectorsForStates } from "./merge.js";
3
+ import { splitSelectorsForState } from "./split.js";
4
+ import { stringifySelectorsForState } from "./stringify.js";
5
+
6
+ /**
7
+ * Create context object from config
8
+ */
9
+ function createStatefulIconSelectorsContext(config, states) {
10
+ return {
11
+ config,
12
+ states,
13
+ data: Object.create(null),
14
+ parsed: Object.create(null)
15
+ };
16
+ }
17
+ /**
18
+ * Get selectors to render state values
19
+ *
20
+ * Does not include shape class name
21
+ */
22
+ function getSelectorsForStateValues(context, value) {
23
+ const dataToMerge = [];
24
+ let cacheKey = "";
25
+ const { config, states, data, parsed } = context;
26
+ const stateValues = typeof value === "string" ? getStatesFromKey(value, states) : value;
27
+ const add = (key, value) => {
28
+ cacheKey += `${key}:${value};`;
29
+ const baseStateItem = config[key];
30
+ const stateItem = typeof baseStateItem === "object" && !Array.isArray(baseStateItem) ? baseStateItem[value] : baseStateItem;
31
+ if (!stateItem) return false;
32
+ let selectorData;
33
+ if (typeof stateItem === "string") {
34
+ const selector = stateItem.replace("{state}", value);
35
+ if (data[selector]) selectorData = data[selector];
36
+ else if (data[selector] === null) return false;
37
+ else {
38
+ const split = splitSelectorsForState(selector);
39
+ data[selector] = split;
40
+ if (!split) return false;
41
+ selectorData = split;
42
+ }
43
+ } else selectorData = stateItem;
44
+ dataToMerge.push(selectorData);
45
+ return true;
46
+ };
47
+ for (const stateName in stateValues) {
48
+ const stateValue = stateValues[stateName];
49
+ const stateItem = states.find((s) => typeof s === "string" ? s === stateName : s[0] === stateName);
50
+ if (!stateItem) return null;
51
+ if (typeof stateItem === "string") {
52
+ if (stateValue && !add(stateName, stateName)) return null;
53
+ } else {
54
+ const allValues = stateItem[1];
55
+ if (typeof stateValue !== "string" || !allValues.includes(stateValue)) return null;
56
+ if (stateValue !== (stateItem[2] || allValues[0]) && !add(stateName, stateValue)) return null;
57
+ }
58
+ }
59
+ if (!dataToMerge.length) return [[]];
60
+ if (parsed[cacheKey] !== void 0) return parsed[cacheKey];
61
+ let merged = data[cacheKey];
62
+ if (!merged) {
63
+ if (merged !== null) {
64
+ merged = mergeSelectorsForStates(dataToMerge);
65
+ data[cacheKey] = merged;
66
+ }
67
+ if (!merged) return null;
68
+ }
69
+ const stringified = stringifySelectorsForState(merged);
70
+ parsed[cacheKey] = stringified;
71
+ return stringified;
72
+ }
73
+
74
+ export { createStatefulIconSelectorsContext, getSelectorsForStateValues };
@@ -0,0 +1,10 @@
1
+ import { StateSelectorParts } from "../types.js";
2
+ /**
3
+ * Merge all selectors
4
+ *
5
+ * Returns null if merge is not possible
6
+ *
7
+ * If multiple results are returned, all have identical at-rules and svg selectors, but different parent selectors.
8
+ */
9
+ declare function mergeSelectorParts(parts: StateSelectorParts[]): StateSelectorParts[] | null;
10
+ export { mergeSelectorParts };
@@ -0,0 +1,37 @@
1
+ import { mergeMultipleArrays } from "../helpers/iterate.js";
2
+ import { mergeMultipleSelectorSubParts } from "../sub/merge.js";
3
+
4
+ /**
5
+ * Merge all selectors
6
+ *
7
+ * Returns null if merge is not possible
8
+ *
9
+ * If multiple results are returned, all have identical at-rules and svg selectors, but different parent selectors.
10
+ */
11
+ function mergeSelectorParts(parts) {
12
+ const atRules = [];
13
+ let svgSelector = null;
14
+ for (const item of parts) {
15
+ if (item.at) {
16
+ for (const atRule of item.at) if (!atRules.includes(atRule)) atRules.push(atRule);
17
+ }
18
+ if (item.svg) if (!svgSelector) svgSelector = item.svg;
19
+ else {
20
+ svgSelector = mergeMultipleSelectorSubParts([svgSelector, item.svg]);
21
+ if (!svgSelector) return null;
22
+ }
23
+ }
24
+ const baseResult = {
25
+ at: atRules.length > 0 ? atRules : void 0,
26
+ svg: svgSelector || void 0
27
+ };
28
+ const allParentSelectors = parts.filter((item) => item.parents).map((item) => item.parents);
29
+ const mergedParentSelectors = allParentSelectors.length > 1 ? mergeMultipleArrays(allParentSelectors, (a, b) => mergeMultipleSelectorSubParts([a, b])) : allParentSelectors;
30
+ if (mergedParentSelectors.length) return mergedParentSelectors.map((parents) => ({
31
+ ...baseResult,
32
+ parents
33
+ }));
34
+ else return [baseResult];
35
+ }
36
+
37
+ export { mergeSelectorParts };
@@ -0,0 +1,13 @@
1
+ import { StateSelectorParts } from "../types.js";
2
+ /**
3
+ * Create selector parts from given parameters
4
+ *
5
+ * Should be used when selector is hard to parse from string, such as:
6
+ * - `@media (max-width: 600px) label:focus &` -> parser will not be able to tell if "label" is part of at-rule or parent selector
7
+ */
8
+ declare function createSelectorParts(atRules: string[] | null, parentSelectors: string | string[] | null, svgSelector: string | null): StateSelectorParts;
9
+ /**
10
+ * Split selector into parts
11
+ */
12
+ declare function splitSelectorToParts(selector: string): StateSelectorParts | null;
13
+ export { createSelectorParts, splitSelectorToParts };
@@ -0,0 +1,60 @@
1
+ import { splitSelectorToSubParts } from "../sub/split.js";
2
+
3
+ const charAfterAtRule = [
4
+ ".",
5
+ "&",
6
+ ":",
7
+ "[",
8
+ "#",
9
+ "*"
10
+ ];
11
+ /**
12
+ * Create selector parts from given parameters
13
+ *
14
+ * Should be used when selector is hard to parse from string, such as:
15
+ * - `@media (max-width: 600px) label:focus &` -> parser will not be able to tell if "label" is part of at-rule or parent selector
16
+ */
17
+ function createSelectorParts(atRules, parentSelectors, svgSelector) {
18
+ return {
19
+ at: atRules ? atRules : void 0,
20
+ parents: parentSelectors ? Array.isArray(parentSelectors) ? parentSelectors.map(splitSelectorToSubParts) : [splitSelectorToSubParts(parentSelectors)] : void 0,
21
+ svg: svgSelector ? splitSelectorToSubParts(svgSelector) : void 0
22
+ };
23
+ }
24
+ /**
25
+ * Split selector into parts
26
+ */
27
+ function splitSelectorToParts(selector) {
28
+ selector = selector.replace(/[\s]+/g, " ").trim();
29
+ const result = {};
30
+ if (selector.startsWith("@")) {
31
+ const chunks = selector.split(" ");
32
+ const atRule = [chunks.shift()];
33
+ let isAtRuleComplete = false;
34
+ while (chunks.length > 0) {
35
+ const firstChar = chunks[0][0];
36
+ if (charAfterAtRule.includes(firstChar)) {
37
+ isAtRuleComplete = true;
38
+ break;
39
+ }
40
+ atRule.push(chunks.shift());
41
+ }
42
+ if (!isAtRuleComplete) return { at: [selector] };
43
+ result.at = [atRule.join(" ")];
44
+ selector = chunks.join(" ");
45
+ }
46
+ selector = selector.replace(/\s*([>+~])\s*/g, " $1").trim();
47
+ const parents = [];
48
+ const chunks = selector.split(" ");
49
+ while (chunks.length > 0) {
50
+ const nextChunk = chunks.shift();
51
+ if (nextChunk.includes("&")) {
52
+ if (chunks.length) return null;
53
+ result.svg = splitSelectorToSubParts(nextChunk.replace("&", ""));
54
+ } else parents.push(splitSelectorToSubParts(nextChunk));
55
+ }
56
+ if (parents.length) result.parents = parents;
57
+ return result;
58
+ }
59
+
60
+ export { createSelectorParts, splitSelectorToParts };
@@ -0,0 +1,9 @@
1
+ import { StateSelectorParts } from "../types.js";
2
+ /**
3
+ * Convert selector parts to array of strings
4
+ *
5
+ * Assumes that all parts have identical at-rules and svg selectors, but different parent selectors,
6
+ * same as returned by mergeSelectorParts()
7
+ */
8
+ declare function stringifySelectorParts(parts: StateSelectorParts[]): string[] | null;
9
+ export { stringifySelectorParts };
@@ -0,0 +1,32 @@
1
+ import { stringifySelectorSubParts } from "../sub/stringify.js";
2
+
3
+ /**
4
+ * Join sub-parts of selector into one string
5
+ */
6
+ function joinSubParts(parts) {
7
+ return parts.map((item, index) => {
8
+ const chunk = stringifySelectorSubParts(item);
9
+ return index > 0 && chunk.startsWith("&") ? chunk.replace("&", "").trim() : chunk;
10
+ }).join(" ");
11
+ }
12
+ /**
13
+ * Convert selector parts to array of strings
14
+ *
15
+ * Assumes that all parts have identical at-rules and svg selectors, but different parent selectors,
16
+ * same as returned by mergeSelectorParts()
17
+ */
18
+ function stringifySelectorParts(parts) {
19
+ const firstItem = parts[0];
20
+ if (!firstItem) return null;
21
+ const results = [];
22
+ if (firstItem.at) results.push(...firstItem.at);
23
+ if (parts.length > 1) {
24
+ const parentSelectors = /* @__PURE__ */ new Set();
25
+ for (const item of parts) if (item.parents) parentSelectors.add(joinSubParts(item.parents));
26
+ if (parentSelectors.size) results.push(Array.from(parentSelectors).sort((a, b) => a.localeCompare(b)).join(", "));
27
+ } else if (firstItem.parents) results.push(...firstItem.parents.map((item) => stringifySelectorSubParts(item)));
28
+ if (firstItem.svg) results.push(stringifySelectorSubParts(firstItem.svg, true));
29
+ return results;
30
+ }
31
+
32
+ export { stringifySelectorParts };
@@ -0,0 +1,6 @@
1
+ import { StateSelectorData } from "./types.js";
2
+ /**
3
+ * Split comma separated selectors into parts, group by compatibility so later can be merged
4
+ */
5
+ declare function splitSelectorsForState(selectors: string): StateSelectorData | null;
6
+ export { splitSelectorsForState };
@@ -0,0 +1,29 @@
1
+ import { splitSelectorToParts } from "./part/split.js";
2
+ import { stringifySelectorSubParts } from "./sub/stringify.js";
3
+
4
+ /**
5
+ * Split comma separated selectors into parts, group by compatibility so later can be merged
6
+ */
7
+ function splitSelectorsForState(selectors) {
8
+ const groups = [];
9
+ const hashMap = /* @__PURE__ */ new Map();
10
+ const list = selectors.split(",").map((s) => s.trim());
11
+ for (const selector of list) {
12
+ const split = splitSelectorToParts(selector);
13
+ if (!split) return null;
14
+ const hash = JSON.stringify({
15
+ at: split.at,
16
+ svg: split.svg ? stringifySelectorSubParts(split.svg, true) : void 0
17
+ });
18
+ const group = hashMap.get(hash);
19
+ if (group) group.push(split);
20
+ else {
21
+ const newGroup = [split];
22
+ hashMap.set(hash, newGroup);
23
+ groups.push(newGroup);
24
+ }
25
+ }
26
+ return groups;
27
+ }
28
+
29
+ export { splitSelectorsForState };
@@ -0,0 +1,8 @@
1
+ import { StateSelectorData } from "./types.js";
2
+ /**
3
+ * Convert selector data to strings
4
+ *
5
+ * Returns sets of selector sequences
6
+ */
7
+ declare function stringifySelectorsForState(data: StateSelectorData): string[][] | null;
8
+ export { stringifySelectorsForState };
@@ -0,0 +1,143 @@
1
+ import { stringifySelectorParts } from "./part/stringify.js";
2
+
3
+ function joinSequence(parts) {
4
+ let selectors = [];
5
+ for (const part of parts) {
6
+ const chunks = part.split(",").map((s) => s.trim());
7
+ if (!selectors.length) {
8
+ selectors.push(...chunks);
9
+ continue;
10
+ }
11
+ const newSelectors = [];
12
+ for (const chunk of chunks) for (const selector of selectors) newSelectors.push(`${selector} ${chunk}`);
13
+ selectors = newSelectors;
14
+ }
15
+ const uniqueSelectors = new Set(selectors);
16
+ return Array.from(uniqueSelectors).sort((a, b) => a.localeCompare(b)).join(", ");
17
+ }
18
+ function mergeRules(rules) {
19
+ const results = /* @__PURE__ */ new Set();
20
+ for (const rule of rules) {
21
+ const chunks = rule.split(",").map((s) => s.trim());
22
+ for (const chunk of chunks) results.add(chunk);
23
+ }
24
+ return Array.from(results).sort((a, b) => a.localeCompare(b)).join(", ");
25
+ }
26
+ function mergeSequences(list1, list2) {
27
+ const max1 = list1.length - 1;
28
+ const max2 = list2.length - 1;
29
+ let match1 = -1;
30
+ let match2 = -1;
31
+ for (let i = 0; i <= max1; i++) {
32
+ const part1 = list1[i];
33
+ for (let j = 0; j <= max2; j++) if (part1 === list2[j]) {
34
+ if ((i === 0 || j === 0) && i !== j) continue;
35
+ if ((i === max1 || j === max2) && (i !== max1 || j !== max2)) continue;
36
+ match1 = i;
37
+ match2 = j;
38
+ break;
39
+ }
40
+ if (match1 !== -1) break;
41
+ }
42
+ if (match1 === -1) return [mergeRules([joinSequence(list1), joinSequence(list2)])];
43
+ const merged = [];
44
+ if (match1 > 0) merged.push(mergeRules([joinSequence(list1.slice(0, match1)), joinSequence(list2.slice(0, match2))]));
45
+ merged.push(mergeRules([list1[match1], list2[match2]]));
46
+ if (match1 < max1) merged.push(...mergeSequences(list1.slice(match1 + 1), list2.slice(match2 + 1)));
47
+ return merged;
48
+ }
49
+ function optimiseMerge(data) {
50
+ const result = [];
51
+ const atRules = /* @__PURE__ */ new Map();
52
+ const add = (sequence) => {
53
+ const atData = [];
54
+ let skipped = false;
55
+ for (let i = 0; i < sequence.length; i++) {
56
+ const part = sequence[i];
57
+ if (part.includes("@")) {
58
+ if (skipped) return false;
59
+ atData.push(`${i}:${part}`);
60
+ } else skipped = true;
61
+ }
62
+ const atKey = atData.join("|");
63
+ if (!skipped) {
64
+ result.push(sequence);
65
+ return true;
66
+ }
67
+ if (atRules.has(atKey)) {
68
+ const index = atRules.get(atKey);
69
+ const existing = result[index];
70
+ const merged = [];
71
+ const minLength = Math.min(existing.length, sequence.length);
72
+ for (let i = 0; i < minLength; i++) {
73
+ const part1 = existing[i];
74
+ const part2 = sequence[i];
75
+ if (part1 === part2) {
76
+ merged.push(part1);
77
+ continue;
78
+ }
79
+ if (part1.includes("@") || part2.includes("@")) return false;
80
+ merged.push(...mergeSequences(existing.slice(i), sequence.slice(i)));
81
+ break;
82
+ }
83
+ result[index] = merged;
84
+ return true;
85
+ }
86
+ atRules.set(atKey, result.length);
87
+ result.push(sequence);
88
+ return true;
89
+ };
90
+ for (const sequence of data) if (!add(sequence)) return data;
91
+ return result;
92
+ }
93
+ function optimise(data) {
94
+ let changed = false;
95
+ const result = [];
96
+ const add = (sequence) => {
97
+ if (!result.length) {
98
+ result.push([...sequence]);
99
+ return;
100
+ }
101
+ const length = sequence.length;
102
+ for (let i = 0; i < result.length; i++) {
103
+ const existing = result[i];
104
+ if (existing.length === length) {
105
+ let matches = 0;
106
+ let differentIndex = -1;
107
+ for (let j = 0; j < length; j++) if (existing[j] === sequence[j]) matches++;
108
+ else differentIndex = j;
109
+ if (matches === length) return;
110
+ if (matches === length - 1) {
111
+ const part1 = sequence[differentIndex];
112
+ const part2 = existing[differentIndex];
113
+ if (!part1.includes("@") && !part2.includes("@")) {
114
+ existing[differentIndex] = mergeRules([part1, part2]);
115
+ changed = true;
116
+ return;
117
+ }
118
+ }
119
+ }
120
+ }
121
+ result.push([...sequence]);
122
+ };
123
+ for (const sequence of data) add(sequence);
124
+ if (!changed && result.length > 1) return optimiseMerge(result);
125
+ return changed ? optimise(result) : result;
126
+ }
127
+ /**
128
+ * Convert selector data to strings
129
+ *
130
+ * Returns sets of selector sequences
131
+ */
132
+ function stringifySelectorsForState(data) {
133
+ const sequences = [];
134
+ for (const group of data) {
135
+ const sequence = stringifySelectorParts(group);
136
+ if (!sequence) return null;
137
+ sequences.push(sequence);
138
+ }
139
+ sequences.sort((a, b) => a.length - b.length);
140
+ return optimise(sequences);
141
+ }
142
+
143
+ export { stringifySelectorsForState };
@@ -0,0 +1,6 @@
1
+ import { StateSelectorSubParts } from "../types.js";
2
+ /**
3
+ * Merge multiple selector parts into one
4
+ */
5
+ declare function mergeMultipleSelectorSubParts(parts: StateSelectorSubParts[]): StateSelectorSubParts | null;
6
+ export { mergeMultipleSelectorSubParts };
@@ -0,0 +1,36 @@
1
+ const uniqueKeys = ["tag", "id"];
2
+ const mergeKeys = [
3
+ "name",
4
+ "attr",
5
+ "pseudo"
6
+ ];
7
+ /**
8
+ * Merge multiple selector parts into one
9
+ */
10
+ function mergeMultipleSelectorSubParts(parts) {
11
+ const result = {};
12
+ for (const part of parts) {
13
+ if (part.combinator) {
14
+ if (!result.combinator) result.combinator = part.combinator;
15
+ else if (result.combinator !== part.combinator) return null;
16
+ }
17
+ for (const key of uniqueKeys) {
18
+ const value = part[key];
19
+ if (value) {
20
+ if (result[key] && result[key] !== value) return null;
21
+ result[key] = value;
22
+ }
23
+ }
24
+ for (const key of mergeKeys) {
25
+ const values = part[key];
26
+ if (values) {
27
+ const list = result[key] || /* @__PURE__ */ new Set();
28
+ if (!result[key]) result[key] = list;
29
+ for (const value of values) list.add(value);
30
+ }
31
+ }
32
+ }
33
+ return result;
34
+ }
35
+
36
+ export { mergeMultipleSelectorSubParts };
@@ -0,0 +1,10 @@
1
+ import { StateSelectorSubParts } from "../types.js";
2
+ declare const combinators: Set<string>;
3
+ /**
4
+ * Split selector into smaller parts
5
+ *
6
+ * Assuming selector is in format: '.foo[bar="baz"]:hover:active'
7
+ * Class name should be before attribute selector, pseudo-classes should be last
8
+ */
9
+ declare function splitSelectorToSubParts(selector: string): StateSelectorSubParts;
10
+ export { combinators, splitSelectorToSubParts };
@@ -0,0 +1,61 @@
1
+ const combinators = new Set([
2
+ ">",
3
+ "+",
4
+ "~"
5
+ ]);
6
+ /**
7
+ * Split selector into smaller parts
8
+ *
9
+ * Assuming selector is in format: '.foo[bar="baz"]:hover:active'
10
+ * Class name should be before attribute selector, pseudo-classes should be last
11
+ */
12
+ function splitSelectorToSubParts(selector) {
13
+ const result = {};
14
+ const firstChar = selector[0];
15
+ if (combinators.has(firstChar)) {
16
+ result.combinator = firstChar;
17
+ selector = selector.slice(1).trim();
18
+ }
19
+ const pseudoSelectors = selector.split(":");
20
+ while (pseudoSelectors.length > 1) {
21
+ const list = result.pseudo || /* @__PURE__ */ new Set();
22
+ if (!result.pseudo) result.pseudo = list;
23
+ list.add(":" + pseudoSelectors.pop());
24
+ }
25
+ selector = pseudoSelectors[0];
26
+ let attrStart = selector.indexOf("[");
27
+ while (attrStart !== -1) {
28
+ const attrEnd = selector.indexOf("]", attrStart);
29
+ let attrValue;
30
+ if (attrEnd === -1) {
31
+ attrValue = selector.slice(attrStart);
32
+ selector = selector.slice(0, attrStart);
33
+ } else {
34
+ attrValue = selector.slice(attrStart, attrEnd + 1);
35
+ selector = selector.slice(0, attrStart) + selector.slice(attrEnd + 1);
36
+ }
37
+ const list = result.attr || /* @__PURE__ */ new Set();
38
+ if (!result.attr) result.attr = list;
39
+ list.add(attrValue);
40
+ attrStart = selector.indexOf("[");
41
+ }
42
+ const tagMatch = selector.match(/^[a-zA-Z][a-zA-Z0-9-]*/);
43
+ if (tagMatch) {
44
+ result.tag = tagMatch[0];
45
+ selector = selector.slice(result.tag.length);
46
+ }
47
+ const idMatch = selector.match(/^#[a-zA-Z0-9_-]+/);
48
+ if (idMatch) {
49
+ result.id = idMatch[0];
50
+ selector = selector.slice(result.id.length);
51
+ }
52
+ if (selector) {
53
+ const chunks = selector.split(".");
54
+ const list = /* @__PURE__ */ new Set();
55
+ for (let i = 1; i < chunks.length; i++) list.add((i === 1 ? `${chunks[0]}.` : ".") + chunks[i]);
56
+ result.name = list;
57
+ }
58
+ return result;
59
+ }
60
+
61
+ export { combinators, splitSelectorToSubParts };
@@ -0,0 +1,6 @@
1
+ import { StateSelectorSubParts } from "../types.js";
2
+ /**
3
+ * Convert selector parts to string
4
+ */
5
+ declare function stringifySelectorSubParts(selector: StateSelectorSubParts, isSVG?: boolean): string;
6
+ export { stringifySelectorSubParts };
@@ -0,0 +1,17 @@
1
+ function mergeSet(set) {
2
+ return set ? Array.from(set).sort((a, b) => a.localeCompare(b)).join("") : "";
3
+ }
4
+ /**
5
+ * Convert selector parts to string
6
+ */
7
+ function stringifySelectorSubParts(selector, isSVG = false) {
8
+ const combinator = selector.combinator ? `& ${selector.combinator} ` : "";
9
+ const tag = isSVG ? "" : `${selector.tag || ""}${selector.id || ""}`;
10
+ const attr = `${mergeSet(selector.name)}${mergeSet(selector.attr)}`;
11
+ const pseudo = mergeSet(selector.pseudo);
12
+ const full = `${tag}${attr}${pseudo}`;
13
+ if (isSVG) return full ? `${combinator}svg${full}` : combinator.trim();
14
+ return `${combinator}${pseudo && full === pseudo ? "*" : ""}${full}`;
15
+ }
16
+
17
+ export { stringifySelectorSubParts };
@@ -0,0 +1,37 @@
1
+ import { IconStatesList } from "../types.js";
2
+ /**
3
+ * Sub-parts of selector
4
+ */
5
+ interface StateSelectorSubParts {
6
+ tag?: string;
7
+ id?: string;
8
+ combinator?: string;
9
+ name?: Set<string>;
10
+ attr?: Set<string>;
11
+ pseudo?: Set<string>;
12
+ }
13
+ /**
14
+ * Parts of selector
15
+ */
16
+ interface StateSelectorParts {
17
+ at?: string[];
18
+ parents?: StateSelectorSubParts[];
19
+ svg?: StateSelectorSubParts;
20
+ }
21
+ type StateSelectorData = StateSelectorParts[][];
22
+ /**
23
+ * Class names config
24
+ */
25
+ type StatefulIconSelectorsConfig = Record<string, string | StateSelectorData | Record<string, string | StateSelectorData>>;
26
+ /**
27
+ * Data for generating selectors for states
28
+ *
29
+ * Includes config and cache
30
+ */
31
+ interface StatefulIconSelectorsContext {
32
+ config: StatefulIconSelectorsConfig;
33
+ states: IconStatesList;
34
+ data: Record<string, StateSelectorData | null>;
35
+ parsed: Record<string, string[][] | null>;
36
+ }
37
+ export { StateSelectorData, StateSelectorParts, StateSelectorSubParts, StatefulIconSelectorsConfig, StatefulIconSelectorsContext };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * States for stateful icons
3
+ */
4
+ type IconStatesSimpleState = Readonly<string>;
5
+ type IconStatesAdvancedStateValues = string[] | Readonly<string[]>;
6
+ type IconStatesAdvancedState = Readonly<[string, IconStatesAdvancedStateValues] | [string, IconStatesAdvancedStateValues, string]>;
7
+ type IconStatesState = IconStatesSimpleState | IconStatesAdvancedState;
8
+ type IconStatesList = IconStatesState[];
9
+ export { IconStatesAdvancedState, IconStatesAdvancedStateValues, IconStatesList, IconStatesSimpleState, IconStatesState };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,6 @@
1
+ import { IconStatesList } from "./types.js";
2
+ /**
3
+ * Validates states list to avoid issues when generating icons
4
+ */
5
+ declare function assertValidStatesList(list: IconStatesList): void;
6
+ export { assertValidStatesList };