@poveste/vendors 0.14.0 → 0.15.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 (224) hide show
  1. package/dist/client/b-floating-vue.js +1 -1
  2. package/dist/client/b-iconify.js +1429 -1416
  3. package/dist/client/b-pinia.js +1359 -1936
  4. package/dist/client/b-vue-router.js +787 -502
  5. package/dist/client/b-vue-use.js +497 -367
  6. package/dist/client/b-vue.js +1 -1
  7. package/dist/client/devtools-api.js +6568 -0
  8. package/dist/client/index.js +178 -162
  9. package/dist/client/node_modules/@iconify/vue/dist/iconify.d.ts +17 -72
  10. package/dist/client/node_modules/@iconify/vue/dist/offline.d.ts +7 -12
  11. package/dist/client/node_modules/@iconify/vue/offline/package.json +2 -2
  12. package/dist/client/node_modules/@iconify/vue/package.json +13 -16
  13. package/dist/client/node_modules/@jridgewell/gen-mapping/dist/types/gen-mapping.d.ts +88 -0
  14. package/dist/client/node_modules/@jridgewell/gen-mapping/dist/types/set-array.d.ts +32 -0
  15. package/dist/client/node_modules/@jridgewell/gen-mapping/dist/types/sourcemap-segment.d.ts +12 -0
  16. package/dist/client/node_modules/@jridgewell/gen-mapping/dist/types/types.d.ts +43 -0
  17. package/dist/client/node_modules/@jridgewell/gen-mapping/package.json +67 -0
  18. package/dist/client/node_modules/@jridgewell/gen-mapping/types/gen-mapping.d.mts +89 -0
  19. package/dist/client/node_modules/@jridgewell/gen-mapping/types/set-array.d.mts +33 -0
  20. package/dist/client/node_modules/@jridgewell/gen-mapping/types/sourcemap-segment.d.mts +13 -0
  21. package/dist/client/node_modules/@jridgewell/gen-mapping/types/types.d.mts +44 -0
  22. package/dist/client/node_modules/@jridgewell/remapping/package.json +71 -0
  23. package/dist/client/node_modules/@jridgewell/remapping/types/build-source-map-tree.d.mts +15 -0
  24. package/dist/client/node_modules/@jridgewell/remapping/types/remapping.d.mts +21 -0
  25. package/dist/client/node_modules/@jridgewell/remapping/types/source-map-tree.d.mts +46 -0
  26. package/dist/client/node_modules/@jridgewell/remapping/types/source-map.d.mts +19 -0
  27. package/dist/client/node_modules/@jridgewell/remapping/types/types.d.mts +16 -0
  28. package/dist/client/node_modules/@jridgewell/resolve-uri/dist/types/resolve-uri.d.ts +4 -0
  29. package/dist/client/node_modules/@jridgewell/resolve-uri/package.json +69 -0
  30. package/dist/client/node_modules/@jridgewell/trace-mapping/package.json +67 -0
  31. package/dist/client/node_modules/@jridgewell/trace-mapping/types/binary-search.d.mts +33 -0
  32. package/dist/client/node_modules/@jridgewell/trace-mapping/types/by-source.d.mts +4 -0
  33. package/dist/client/node_modules/@jridgewell/trace-mapping/types/flatten-map.d.mts +9 -0
  34. package/dist/client/node_modules/@jridgewell/trace-mapping/types/resolve.d.mts +4 -0
  35. package/dist/client/node_modules/@jridgewell/trace-mapping/types/sort.d.mts +4 -0
  36. package/dist/client/node_modules/@jridgewell/trace-mapping/types/sourcemap-segment.d.mts +17 -0
  37. package/dist/client/node_modules/@jridgewell/trace-mapping/types/strip-filename.d.mts +5 -0
  38. package/dist/client/node_modules/@jridgewell/trace-mapping/types/trace-mapping.d.mts +80 -0
  39. package/dist/client/node_modules/@jridgewell/trace-mapping/types/types.d.mts +107 -0
  40. package/dist/client/node_modules/@vue/devtools-api/dist/index-node.d.ts +11 -0
  41. package/dist/client/node_modules/@vue/devtools-api/dist/index.d.ts +2 -0
  42. package/dist/client/node_modules/@vue/devtools-api/package.json +25 -24
  43. package/dist/client/node_modules/@vue/devtools-kit/dist/index.d.ts +1170 -0
  44. package/dist/client/node_modules/@vue/devtools-kit/global.d.ts +20 -0
  45. package/dist/client/node_modules/@vue/devtools-kit/package.json +44 -0
  46. package/dist/client/node_modules/@vue/devtools-kit/types.d.ts +2 -0
  47. package/dist/client/node_modules/@vue/devtools-shared/dist/index.d.ts +40 -0
  48. package/dist/client/node_modules/@vue/devtools-shared/package.json +33 -0
  49. package/dist/client/node_modules/@vue-macros/common/dist/index.d.ts +124 -0
  50. package/dist/client/node_modules/@vue-macros/common/package.json +63 -0
  51. package/dist/client/node_modules/@vueuse/core/dist/index.d.ts +223 -111
  52. package/dist/client/node_modules/@vueuse/core/package.json +10 -3
  53. package/dist/client/node_modules/@vueuse/metadata/package.json +4 -1
  54. package/dist/client/node_modules/@vueuse/shared/dist/index.d.ts +2 -2
  55. package/dist/client/node_modules/@vueuse/shared/package.json +4 -1
  56. package/dist/client/node_modules/acorn/dist/acorn.d.mts +897 -0
  57. package/dist/client/node_modules/acorn/dist/acorn.d.ts +897 -0
  58. package/dist/client/node_modules/acorn/package.json +50 -0
  59. package/dist/client/node_modules/ast-kit/dist/index.d.ts +380 -0
  60. package/dist/client/node_modules/ast-kit/package.json +63 -0
  61. package/dist/client/node_modules/ast-walker-scope/dist/index.d.mts +51 -0
  62. package/dist/client/node_modules/ast-walker-scope/package.json +60 -0
  63. package/dist/client/node_modules/birpc/dist/index.d.mts +215 -0
  64. package/dist/client/node_modules/birpc/dist/index.d.ts +215 -0
  65. package/dist/client/node_modules/birpc/package.json +57 -0
  66. package/dist/client/node_modules/chokidar/handler.d.ts +90 -0
  67. package/dist/client/node_modules/chokidar/index.d.ts +217 -0
  68. package/dist/client/node_modules/chokidar/package.json +63 -0
  69. package/dist/client/node_modules/confbox/dist/_chunks/_format.d.mts +25 -0
  70. package/dist/client/node_modules/confbox/dist/index.d.mts +34 -0
  71. package/dist/client/node_modules/confbox/dist/ini.d.mts +62 -0
  72. package/dist/client/node_modules/confbox/dist/json5.d.mts +59 -0
  73. package/dist/client/node_modules/confbox/dist/jsonc.d.mts +41 -0
  74. package/dist/client/node_modules/confbox/dist/toml.d.mts +23 -0
  75. package/dist/client/node_modules/confbox/dist/yaml.d.mts +96 -0
  76. package/dist/client/node_modules/confbox/package.json +67 -0
  77. package/dist/client/node_modules/exsolve/dist/index.d.mts +66 -0
  78. package/dist/client/node_modules/exsolve/package.json +42 -0
  79. package/dist/client/node_modules/fdir/dist/index.d.mts +155 -0
  80. package/dist/client/node_modules/fdir/package.json +103 -0
  81. package/dist/client/node_modules/hookable/dist/index.d.ts +103 -0
  82. package/dist/client/node_modules/hookable/package.json +49 -0
  83. package/dist/client/node_modules/local-pkg/dist/index.d.mts +42 -0
  84. package/dist/client/node_modules/local-pkg/dist/index.d.ts +42 -0
  85. package/dist/client/node_modules/local-pkg/package.json +65 -0
  86. package/dist/client/node_modules/magic-string-ast/dist/index.d.ts +67 -0
  87. package/dist/client/node_modules/magic-string-ast/package.json +64 -0
  88. package/dist/client/node_modules/mlly/dist/index.d.mts +564 -0
  89. package/dist/client/node_modules/mlly/dist/index.d.ts +564 -0
  90. package/dist/client/node_modules/mlly/node_modules/confbox/dist/index.d.mts +32 -0
  91. package/dist/client/node_modules/mlly/node_modules/confbox/dist/index.d.ts +32 -0
  92. package/dist/client/node_modules/mlly/node_modules/confbox/dist/json5.d.mts +58 -0
  93. package/dist/client/node_modules/mlly/node_modules/confbox/dist/json5.d.ts +58 -0
  94. package/dist/client/node_modules/mlly/node_modules/confbox/dist/jsonc.d.mts +41 -0
  95. package/dist/client/node_modules/mlly/node_modules/confbox/dist/jsonc.d.ts +41 -0
  96. package/dist/client/node_modules/mlly/node_modules/confbox/dist/shared/confbox.9745c98f.d.mts +24 -0
  97. package/dist/client/node_modules/mlly/node_modules/confbox/dist/shared/confbox.9745c98f.d.ts +24 -0
  98. package/dist/client/node_modules/mlly/node_modules/confbox/dist/toml.d.mts +22 -0
  99. package/dist/client/node_modules/mlly/node_modules/confbox/dist/toml.d.ts +22 -0
  100. package/dist/client/node_modules/mlly/node_modules/confbox/dist/yaml.d.mts +95 -0
  101. package/dist/client/node_modules/mlly/node_modules/confbox/dist/yaml.d.ts +95 -0
  102. package/dist/client/node_modules/mlly/node_modules/confbox/json5.d.ts +2 -0
  103. package/dist/client/node_modules/mlly/node_modules/confbox/jsonc.d.ts +2 -0
  104. package/dist/client/node_modules/mlly/node_modules/confbox/package.json +86 -0
  105. package/dist/client/node_modules/mlly/node_modules/confbox/toml.d.ts +2 -0
  106. package/dist/client/node_modules/mlly/node_modules/confbox/yaml.d.ts +2 -0
  107. package/dist/client/node_modules/mlly/node_modules/pkg-types/dist/index.d.mts +411 -0
  108. package/dist/client/node_modules/mlly/node_modules/pkg-types/dist/index.d.ts +411 -0
  109. package/dist/client/node_modules/mlly/node_modules/pkg-types/package.json +47 -0
  110. package/dist/client/node_modules/mlly/package.json +55 -0
  111. package/dist/client/node_modules/muggle-string/out/base.d.ts +6 -0
  112. package/dist/client/node_modules/muggle-string/out/basic.d.ts +6 -0
  113. package/dist/client/node_modules/muggle-string/out/binarySearch.d.ts +1 -0
  114. package/dist/client/node_modules/muggle-string/out/common.d.ts +9 -0
  115. package/dist/client/node_modules/muggle-string/out/getLength.d.ts +2 -0
  116. package/dist/client/node_modules/muggle-string/out/index.d.ts +10 -0
  117. package/dist/client/node_modules/muggle-string/out/map.d.ts +3 -0
  118. package/dist/client/node_modules/muggle-string/out/overwriteSource.d.ts +3 -0
  119. package/dist/client/node_modules/muggle-string/out/replace.d.ts +3 -0
  120. package/dist/client/node_modules/muggle-string/out/segment.d.ts +6 -0
  121. package/dist/client/node_modules/muggle-string/out/sourceBased.d.ts +3 -0
  122. package/dist/client/node_modules/muggle-string/out/toString.d.ts +2 -0
  123. package/dist/client/node_modules/muggle-string/out/track.d.ts +6 -0
  124. package/dist/client/node_modules/muggle-string/out/types.d.ts +16 -0
  125. package/dist/client/node_modules/muggle-string/package.json +22 -0
  126. package/dist/client/node_modules/nostics/dist/diagnostic-wduO7saY.d.mts +295 -0
  127. package/dist/client/node_modules/nostics/dist/formatters/ansi.d.mts +15 -0
  128. package/dist/client/node_modules/nostics/dist/formatters/json.d.mts +7 -0
  129. package/dist/client/node_modules/nostics/dist/index.d.mts +51 -0
  130. package/dist/client/node_modules/nostics/dist/reporters/dev.d.mts +13 -0
  131. package/dist/client/node_modules/nostics/dist/reporters/fetch.d.mts +11 -0
  132. package/dist/client/node_modules/nostics/dist/reporters/node.d.mts +43 -0
  133. package/dist/client/node_modules/nostics/package.json +125 -0
  134. package/dist/client/node_modules/pathe/dist/index.d.mts +47 -0
  135. package/dist/client/node_modules/pathe/dist/index.d.ts +47 -0
  136. package/dist/client/node_modules/pathe/dist/utils.d.mts +32 -0
  137. package/dist/client/node_modules/pathe/dist/utils.d.ts +32 -0
  138. package/dist/client/node_modules/pathe/package.json +61 -0
  139. package/dist/client/node_modules/pathe/utils.d.ts +1 -0
  140. package/dist/client/node_modules/perfect-debounce/dist/index.d.mts +49 -0
  141. package/dist/client/node_modules/perfect-debounce/package.json +41 -0
  142. package/dist/client/node_modules/picomatch/package.json +83 -0
  143. package/dist/client/node_modules/pinia/dist/pinia.d.ts +937 -1056
  144. package/dist/client/node_modules/pinia/package.json +53 -67
  145. package/dist/client/node_modules/pkg-types/dist/index.d.mts +695 -0
  146. package/dist/client/node_modules/pkg-types/node_modules/confbox/dist/_chunks/_format.d.mts +22 -0
  147. package/dist/client/node_modules/pkg-types/node_modules/confbox/dist/_chunks/libs/js-yaml.d.mts +33 -0
  148. package/dist/client/node_modules/pkg-types/node_modules/confbox/dist/index.d.mts +7 -0
  149. package/dist/client/node_modules/pkg-types/node_modules/confbox/dist/ini.d.mts +59 -0
  150. package/dist/client/node_modules/pkg-types/node_modules/confbox/dist/json.d.mts +25 -0
  151. package/dist/client/node_modules/pkg-types/node_modules/confbox/dist/json5.d.mts +55 -0
  152. package/dist/client/node_modules/pkg-types/node_modules/confbox/dist/jsonc.d.mts +29 -0
  153. package/dist/client/node_modules/pkg-types/node_modules/confbox/dist/toml.d.mts +20 -0
  154. package/dist/client/node_modules/pkg-types/node_modules/confbox/dist/yaml.d.mts +101 -0
  155. package/dist/client/node_modules/pkg-types/node_modules/confbox/package.json +68 -0
  156. package/dist/client/node_modules/pkg-types/package.json +47 -0
  157. package/dist/client/node_modules/quansync/dist/index.d.mts +22 -0
  158. package/dist/client/node_modules/quansync/dist/index.d.ts +22 -0
  159. package/dist/client/node_modules/quansync/dist/macro.d.mts +18 -0
  160. package/dist/client/node_modules/quansync/dist/macro.d.ts +18 -0
  161. package/dist/client/node_modules/quansync/dist/types.d.mts +27 -0
  162. package/dist/client/node_modules/quansync/dist/types.d.ts +27 -0
  163. package/dist/client/node_modules/quansync/package.json +95 -0
  164. package/dist/client/node_modules/readdirp/index.d.ts +117 -0
  165. package/dist/client/node_modules/readdirp/package.json +62 -0
  166. package/dist/client/node_modules/scule/dist/index.d.mts +57 -0
  167. package/dist/client/node_modules/scule/dist/index.d.ts +57 -0
  168. package/dist/client/node_modules/scule/package.json +43 -0
  169. package/dist/client/node_modules/tinyglobby/dist/index.d.mts +148 -0
  170. package/dist/client/node_modules/tinyglobby/package.json +70 -0
  171. package/dist/client/node_modules/ufo/dist/index.d.mts +714 -0
  172. package/dist/client/node_modules/ufo/dist/index.d.ts +714 -0
  173. package/dist/client/node_modules/ufo/package.json +48 -0
  174. package/dist/client/node_modules/unplugin/dist/index.d.mts +241 -0
  175. package/dist/client/node_modules/unplugin/dist/rspack/loaders/load.d.mts +4 -0
  176. package/dist/client/node_modules/unplugin/dist/rspack/loaders/transform.d.mts +4 -0
  177. package/dist/client/node_modules/unplugin/dist/webpack/loaders/load.d.mts +4 -0
  178. package/dist/client/node_modules/unplugin/dist/webpack/loaders/transform.d.mts +4 -0
  179. package/dist/client/node_modules/unplugin/package.json +146 -0
  180. package/dist/client/node_modules/unplugin-utils/dist/index.d.ts +31 -0
  181. package/dist/client/node_modules/unplugin-utils/package.json +61 -0
  182. package/dist/client/node_modules/vue-router/dist/experimental/index.d.ts +7 -0
  183. package/dist/client/node_modules/vue-router/dist/experimental/pinia-colada.d.ts +151 -0
  184. package/dist/client/node_modules/vue-router/dist/{router-CWoNjPRp.d.mts → index-D7ja2BKs.d.ts} +2480 -1160
  185. package/dist/client/node_modules/vue-router/dist/options-CwYZKRl4.d.mts +2923 -0
  186. package/dist/client/node_modules/vue-router/dist/unplugin/esbuild.d.mts +10 -0
  187. package/dist/client/node_modules/vue-router/dist/unplugin/index.d.mts +62 -0
  188. package/dist/client/node_modules/vue-router/dist/unplugin/options.d.mts +7 -0
  189. package/dist/client/node_modules/vue-router/dist/unplugin/rolldown.d.mts +10 -0
  190. package/dist/client/node_modules/vue-router/dist/unplugin/rollup.d.mts +10 -0
  191. package/dist/client/node_modules/vue-router/dist/unplugin/types.d.mts +7 -0
  192. package/dist/client/node_modules/vue-router/dist/unplugin/vite.d.mts +10 -0
  193. package/dist/client/node_modules/vue-router/dist/unplugin/webpack.d.mts +10 -0
  194. package/dist/client/node_modules/vue-router/dist/vue-router.d.ts +7 -0
  195. package/dist/client/node_modules/vue-router/package.json +153 -95
  196. package/dist/client/node_modules/vue-router/vue-router-auto-resolver.d.mts +22 -17
  197. package/dist/client/node_modules/vue-router/vue-router-auto-routes.d.mts +53 -0
  198. package/dist/client/node_modules/vue-router/vue-router-auto.d.ts +2 -1
  199. package/dist/client/node_modules/webpack-virtual-modules/lib/index.d.ts +15 -0
  200. package/dist/client/node_modules/webpack-virtual-modules/lib/virtual-stats.d.ts +11 -0
  201. package/dist/client/node_modules/webpack-virtual-modules/package.json +82 -0
  202. package/dist/client/vue.runtime.esm-bundler.js +1 -176
  203. package/package.json +8 -7
  204. package/dist/client/node_modules/@vue/devtools-api/lib/esm/api/api.d.ts +0 -108
  205. package/dist/client/node_modules/@vue/devtools-api/lib/esm/api/app.d.ts +0 -1
  206. package/dist/client/node_modules/@vue/devtools-api/lib/esm/api/component.d.ts +0 -78
  207. package/dist/client/node_modules/@vue/devtools-api/lib/esm/api/context.d.ts +0 -5
  208. package/dist/client/node_modules/@vue/devtools-api/lib/esm/api/hooks.d.ts +0 -180
  209. package/dist/client/node_modules/@vue/devtools-api/lib/esm/api/index.d.ts +0 -6
  210. package/dist/client/node_modules/@vue/devtools-api/lib/esm/api/util.d.ts +0 -4
  211. package/dist/client/node_modules/@vue/devtools-api/lib/esm/const.d.ts +0 -2
  212. package/dist/client/node_modules/@vue/devtools-api/lib/esm/env.d.ts +0 -15
  213. package/dist/client/node_modules/@vue/devtools-api/lib/esm/index.d.ts +0 -18
  214. package/dist/client/node_modules/@vue/devtools-api/lib/esm/plugin.d.ts +0 -47
  215. package/dist/client/node_modules/@vue/devtools-api/lib/esm/proxy.d.ts +0 -20
  216. package/dist/client/node_modules/@vue/devtools-api/lib/esm/time.d.ts +0 -2
  217. package/dist/client/node_modules/pinia/node_modules/vue-demi/lib/index.d.ts +0 -22
  218. package/dist/client/node_modules/pinia/node_modules/vue-demi/lib/v2/index.d.ts +0 -33
  219. package/dist/client/node_modules/pinia/node_modules/vue-demi/lib/v2.7/index.d.ts +0 -38
  220. package/dist/client/node_modules/pinia/node_modules/vue-demi/lib/v3/index.d.ts +0 -22
  221. package/dist/client/node_modules/pinia/node_modules/vue-demi/package.json +0 -47
  222. package/dist/client/node_modules/vue-router/dist/experimental/index.d.mts +0 -38
  223. package/dist/client/node_modules/vue-router/dist/vue-router.d.mts +0 -361
  224. package/dist/client/node_modules/vue-router/vue-router-auto-routes.d.ts +0 -4
@@ -1,1463 +1,1471 @@
1
- import { x as h, d as defineComponent } from './vue.runtime.esm-bundler.js';
1
+ import { h, defineComponent, ref, shallowRef, nextTick, onMounted, watch, onUnmounted } from './vue.runtime.esm-bundler.js';
2
2
 
3
+ /**
4
+ * Expression to test part of icon name.
5
+ *
6
+ * Used when loading icons from Iconify API due to project naming convension.
7
+ * Ignored when using custom icon sets - convension does not apply.
8
+ */
3
9
  const matchIconName = /^[a-z0-9]+(-[a-z0-9]+)*$/;
10
+ /**
11
+ * Convert string icon name to IconifyIconName object.
12
+ */
4
13
  const stringToIcon = (value, validate, allowSimpleName, provider = "") => {
5
- const colonSeparated = value.split(":");
6
- if (value.slice(0, 1) === "@") {
7
- if (colonSeparated.length < 2 || colonSeparated.length > 3) {
8
- return null;
9
- }
10
- provider = colonSeparated.shift().slice(1);
11
- }
12
- if (colonSeparated.length > 3 || !colonSeparated.length) {
13
- return null;
14
- }
15
- if (colonSeparated.length > 1) {
16
- const name2 = colonSeparated.pop();
17
- const prefix = colonSeparated.pop();
18
- const result = {
19
- // Allow provider without '@': "provider:prefix:name"
20
- provider: colonSeparated.length > 0 ? colonSeparated[0] : provider,
21
- prefix,
22
- name: name2
23
- };
24
- return validate && !validateIconName(result) ? null : result;
25
- }
26
- const name = colonSeparated[0];
27
- const dashSeparated = name.split("-");
28
- if (dashSeparated.length > 1) {
29
- const result = {
30
- provider,
31
- prefix: dashSeparated.shift(),
32
- name: dashSeparated.join("-")
33
- };
34
- return validate && !validateIconName(result) ? null : result;
35
- }
36
- if (allowSimpleName && provider === "") {
37
- const result = {
38
- provider,
39
- prefix: "",
40
- name
41
- };
42
- return validate && !validateIconName(result, allowSimpleName) ? null : result;
43
- }
44
- return null;
14
+ const colonSeparated = value.split(":");
15
+ if (value.slice(0, 1) === "@") {
16
+ if (colonSeparated.length < 2 || colonSeparated.length > 3) return null;
17
+ provider = colonSeparated.shift().slice(1);
18
+ }
19
+ if (colonSeparated.length > 3 || !colonSeparated.length) return null;
20
+ if (colonSeparated.length > 1) {
21
+ const name = colonSeparated.pop();
22
+ const prefix = colonSeparated.pop();
23
+ const result = {
24
+ provider: colonSeparated.length > 0 ? colonSeparated[0] : provider,
25
+ prefix,
26
+ name
27
+ };
28
+ return validate && !validateIconName(result) ? null : result;
29
+ }
30
+ const name = colonSeparated[0];
31
+ const dashSeparated = name.split("-");
32
+ if (dashSeparated.length > 1) {
33
+ const result = {
34
+ provider,
35
+ prefix: dashSeparated.shift(),
36
+ name: dashSeparated.join("-")
37
+ };
38
+ return validate && !validateIconName(result) ? null : result;
39
+ }
40
+ if (allowSimpleName && provider === "") {
41
+ const result = {
42
+ provider,
43
+ prefix: "",
44
+ name
45
+ };
46
+ return validate && !validateIconName(result, allowSimpleName) ? null : result;
47
+ }
48
+ return null;
45
49
  };
50
+ /**
51
+ * Check if icon is valid.
52
+ *
53
+ * This function is not part of stringToIcon because validation is not needed for most code.
54
+ */
46
55
  const validateIconName = (icon, allowSimpleName) => {
47
- if (!icon) {
48
- return false;
49
- }
50
- return !!// Check prefix: cannot be empty, unless allowSimpleName is enabled
51
- // Check name: cannot be empty
52
- ((allowSimpleName && icon.prefix === "" || !!icon.prefix) && !!icon.name);
56
+ if (!icon) return false;
57
+ return !!((allowSimpleName && icon.prefix === "" || !!icon.prefix) && !!icon.name);
53
58
  };
54
59
 
55
- const defaultIconDimensions = Object.freeze(
56
- {
57
- left: 0,
58
- top: 0,
59
- width: 16,
60
- height: 16
61
- }
62
- );
60
+ /**
61
+ * Resolve icon set icons
62
+ *
63
+ * Returns parent icon for each icon
64
+ */
65
+ function getIconsTree(data, names) {
66
+ const icons = data.icons;
67
+ const aliases = data.aliases || Object.create(null);
68
+ const resolved = Object.create(null);
69
+ function resolve(name) {
70
+ if (icons[name]) return resolved[name] = [];
71
+ if (!(name in resolved)) {
72
+ resolved[name] = null;
73
+ const parent = aliases[name] && aliases[name].parent;
74
+ const value = parent && resolve(parent);
75
+ if (value) resolved[name] = [parent].concat(value);
76
+ }
77
+ return resolved[name];
78
+ }
79
+ (Object.keys(icons).concat(Object.keys(aliases))).forEach(resolve);
80
+ return resolved;
81
+ }
82
+
83
+ /** Default values for dimensions */
84
+ const defaultIconDimensions = Object.freeze({
85
+ left: 0,
86
+ top: 0,
87
+ width: 16,
88
+ height: 16
89
+ });
90
+ /** Default values for transformations */
63
91
  const defaultIconTransformations = Object.freeze({
64
- rotate: 0,
65
- vFlip: false,
66
- hFlip: false
92
+ rotate: 0,
93
+ vFlip: false,
94
+ hFlip: false
67
95
  });
96
+ /** Default values for all optional IconifyIcon properties */
68
97
  const defaultIconProps = Object.freeze({
69
- ...defaultIconDimensions,
70
- ...defaultIconTransformations
98
+ ...defaultIconDimensions,
99
+ ...defaultIconTransformations
71
100
  });
101
+ /** Default values for all properties used in ExtendedIconifyIcon */
72
102
  const defaultExtendedIconProps = Object.freeze({
73
- ...defaultIconProps,
74
- body: "",
75
- hidden: false
103
+ ...defaultIconProps,
104
+ body: "",
105
+ hidden: false
76
106
  });
77
107
 
108
+ /**
109
+ * Merge transformations
110
+ */
78
111
  function mergeIconTransformations(obj1, obj2) {
79
- const result = {};
80
- if (!obj1.hFlip !== !obj2.hFlip) {
81
- result.hFlip = true;
82
- }
83
- if (!obj1.vFlip !== !obj2.vFlip) {
84
- result.vFlip = true;
85
- }
86
- const rotate = ((obj1.rotate || 0) + (obj2.rotate || 0)) % 4;
87
- if (rotate) {
88
- result.rotate = rotate;
89
- }
90
- return result;
112
+ const result = {};
113
+ if (!obj1.hFlip !== !obj2.hFlip) result.hFlip = true;
114
+ if (!obj1.vFlip !== !obj2.vFlip) result.vFlip = true;
115
+ const rotate = ((obj1.rotate || 0) + (obj2.rotate || 0)) % 4;
116
+ if (rotate) result.rotate = rotate;
117
+ return result;
91
118
  }
92
119
 
120
+ /**
121
+ * Merge icon and alias
122
+ *
123
+ * Can also be used to merge default values and icon
124
+ */
93
125
  function mergeIconData(parent, child) {
94
- const result = mergeIconTransformations(parent, child);
95
- for (const key in defaultExtendedIconProps) {
96
- if (key in defaultIconTransformations) {
97
- if (key in parent && !(key in result)) {
98
- result[key] = defaultIconTransformations[key];
99
- }
100
- } else if (key in child) {
101
- result[key] = child[key];
102
- } else if (key in parent) {
103
- result[key] = parent[key];
104
- }
105
- }
106
- return result;
107
- }
108
-
109
- function getIconsTree(data, names) {
110
- const icons = data.icons;
111
- const aliases = data.aliases || /* @__PURE__ */ Object.create(null);
112
- const resolved = /* @__PURE__ */ Object.create(null);
113
- function resolve(name) {
114
- if (icons[name]) {
115
- return resolved[name] = [];
116
- }
117
- if (!(name in resolved)) {
118
- resolved[name] = null;
119
- const parent = aliases[name] && aliases[name].parent;
120
- const value = parent && resolve(parent);
121
- if (value) {
122
- resolved[name] = [parent].concat(value);
123
- }
124
- }
125
- return resolved[name];
126
- }
127
- (Object.keys(icons).concat(Object.keys(aliases))).forEach(resolve);
128
- return resolved;
126
+ const result = mergeIconTransformations(parent, child);
127
+ for (const key in defaultExtendedIconProps) if (key in defaultIconTransformations) {
128
+ if (key in parent && !(key in result)) result[key] = defaultIconTransformations[key];
129
+ } else if (key in child) result[key] = child[key];
130
+ else if (key in parent) result[key] = parent[key];
131
+ return result;
129
132
  }
130
133
 
134
+ /**
135
+ * Get icon data, using prepared aliases tree
136
+ */
131
137
  function internalGetIconData(data, name, tree) {
132
- const icons = data.icons;
133
- const aliases = data.aliases || /* @__PURE__ */ Object.create(null);
134
- let currentProps = {};
135
- function parse(name2) {
136
- currentProps = mergeIconData(
137
- icons[name2] || aliases[name2],
138
- currentProps
139
- );
140
- }
141
- parse(name);
142
- tree.forEach(parse);
143
- return mergeIconData(data, currentProps);
138
+ const icons = data.icons;
139
+ const aliases = data.aliases || Object.create(null);
140
+ let currentProps = {};
141
+ function parse(name) {
142
+ currentProps = mergeIconData(icons[name] || aliases[name], currentProps);
143
+ }
144
+ parse(name);
145
+ tree.forEach(parse);
146
+ return mergeIconData(data, currentProps);
144
147
  }
145
148
 
149
+ /**
150
+ * Extract icons from an icon set
151
+ *
152
+ * Returns list of icons that were found in icon set
153
+ */
146
154
  function parseIconSet(data, callback) {
147
- const names = [];
148
- if (typeof data !== "object" || typeof data.icons !== "object") {
149
- return names;
150
- }
151
- if (data.not_found instanceof Array) {
152
- data.not_found.forEach((name) => {
153
- callback(name, null);
154
- names.push(name);
155
- });
156
- }
157
- const tree = getIconsTree(data);
158
- for (const name in tree) {
159
- const item = tree[name];
160
- if (item) {
161
- callback(name, internalGetIconData(data, name, item));
162
- names.push(name);
163
- }
164
- }
165
- return names;
155
+ const names = [];
156
+ if (typeof data !== "object" || typeof data.icons !== "object") return names;
157
+ if (data.not_found instanceof Array) data.not_found.forEach((name) => {
158
+ callback(name, null);
159
+ names.push(name);
160
+ });
161
+ const tree = getIconsTree(data);
162
+ for (const name in tree) {
163
+ const item = tree[name];
164
+ if (item) {
165
+ callback(name, internalGetIconData(data, name, item));
166
+ names.push(name);
167
+ }
168
+ }
169
+ return names;
166
170
  }
167
171
 
172
+ /**
173
+ * Optional properties
174
+ */
168
175
  const optionalPropertyDefaults = {
169
- provider: "",
170
- aliases: {},
171
- not_found: {},
172
- ...defaultIconDimensions
176
+ provider: "",
177
+ aliases: {},
178
+ not_found: {},
179
+ ...defaultIconDimensions
173
180
  };
181
+ /**
182
+ * Check props
183
+ */
174
184
  function checkOptionalProps(item, defaults) {
175
- for (const prop in defaults) {
176
- if (prop in item && typeof item[prop] !== typeof defaults[prop]) {
177
- return false;
178
- }
179
- }
180
- return true;
185
+ for (const prop in defaults) if (prop in item && typeof item[prop] !== typeof defaults[prop]) return false;
186
+ return true;
181
187
  }
188
+ /**
189
+ * Validate icon set, return it as IconifyJSON on success, null on failure
190
+ *
191
+ * Unlike validateIconSet(), this function is very basic.
192
+ * It does not throw exceptions, it does not check metadata, it does not fix stuff.
193
+ */
182
194
  function quicklyValidateIconSet(obj) {
183
- if (typeof obj !== "object" || obj === null) {
184
- return null;
185
- }
186
- const data = obj;
187
- if (typeof data.prefix !== "string" || !obj.icons || typeof obj.icons !== "object") {
188
- return null;
189
- }
190
- if (!checkOptionalProps(obj, optionalPropertyDefaults)) {
191
- return null;
192
- }
193
- const icons = data.icons;
194
- for (const name in icons) {
195
- const icon = icons[name];
196
- if (
197
- // Name cannot be empty
198
- !name || // Must have body
199
- typeof icon.body !== "string" || // Check other props
200
- !checkOptionalProps(
201
- icon,
202
- defaultExtendedIconProps
203
- )
204
- ) {
205
- return null;
206
- }
207
- }
208
- const aliases = data.aliases || /* @__PURE__ */ Object.create(null);
209
- for (const name in aliases) {
210
- const icon = aliases[name];
211
- const parent = icon.parent;
212
- if (
213
- // Name cannot be empty
214
- !name || // Parent must be set and point to existing icon
215
- typeof parent !== "string" || !icons[parent] && !aliases[parent] || // Check other props
216
- !checkOptionalProps(
217
- icon,
218
- defaultExtendedIconProps
219
- )
220
- ) {
221
- return null;
222
- }
223
- }
224
- return data;
195
+ if (typeof obj !== "object" || obj === null) return null;
196
+ const data = obj;
197
+ if (typeof data.prefix !== "string" || !obj.icons || typeof obj.icons !== "object") return null;
198
+ if (!checkOptionalProps(obj, optionalPropertyDefaults)) return null;
199
+ const icons = data.icons;
200
+ for (const name in icons) {
201
+ const icon = icons[name];
202
+ if (!name || typeof icon.body !== "string" || !checkOptionalProps(icon, defaultExtendedIconProps)) return null;
203
+ }
204
+ const aliases = data.aliases || Object.create(null);
205
+ for (const name in aliases) {
206
+ const icon = aliases[name];
207
+ const parent = icon.parent;
208
+ if (!name || typeof parent !== "string" || !icons[parent] && !aliases[parent] || !checkOptionalProps(icon, defaultExtendedIconProps)) return null;
209
+ }
210
+ return data;
225
211
  }
226
212
 
227
- const dataStorage = /* @__PURE__ */ Object.create(null);
213
+ /**
214
+ * Storage by provider and prefix
215
+ */
216
+ const dataStorage = Object.create(null);
217
+ /**
218
+ * Create new storage
219
+ */
228
220
  function newStorage(provider, prefix) {
229
- return {
230
- provider,
231
- prefix,
232
- icons: /* @__PURE__ */ Object.create(null),
233
- missing: /* @__PURE__ */ new Set()
234
- };
221
+ return {
222
+ provider,
223
+ prefix,
224
+ icons: Object.create(null),
225
+ missing: /* @__PURE__ */ new Set()
226
+ };
235
227
  }
228
+ /**
229
+ * Get storage for provider and prefix
230
+ */
236
231
  function getStorage(provider, prefix) {
237
- const providerStorage = dataStorage[provider] || (dataStorage[provider] = /* @__PURE__ */ Object.create(null));
238
- return providerStorage[prefix] || (providerStorage[prefix] = newStorage(provider, prefix));
232
+ const providerStorage = dataStorage[provider] || (dataStorage[provider] = Object.create(null));
233
+ return providerStorage[prefix] || (providerStorage[prefix] = newStorage(provider, prefix));
239
234
  }
235
+ /**
236
+ * Add icon set to storage
237
+ *
238
+ * Returns array of added icons
239
+ */
240
240
  function addIconSet(storage, data) {
241
- if (!quicklyValidateIconSet(data)) {
242
- return [];
243
- }
244
- return parseIconSet(data, (name, icon) => {
245
- if (icon) {
246
- storage.icons[name] = icon;
247
- } else {
248
- storage.missing.add(name);
249
- }
250
- });
241
+ if (!quicklyValidateIconSet(data)) return [];
242
+ return parseIconSet(data, (name, icon) => {
243
+ if (icon) storage.icons[name] = icon;
244
+ else storage.missing.add(name);
245
+ });
251
246
  }
247
+ /**
248
+ * Add icon to storage
249
+ */
252
250
  function addIconToStorage(storage, name, icon) {
253
- try {
254
- if (typeof icon.body === "string") {
255
- storage.icons[name] = { ...icon };
256
- return true;
257
- }
258
- } catch (err) {
259
- }
260
- return false;
251
+ try {
252
+ if (typeof icon.body === "string") {
253
+ storage.icons[name] = { ...icon };
254
+ return true;
255
+ }
256
+ } catch (err) {}
257
+ return false;
261
258
  }
259
+ /**
260
+ * List available icons
261
+ */
262
262
  function listIcons(provider, prefix) {
263
- let allIcons = [];
264
- const providers = typeof provider === "string" ? [provider] : Object.keys(dataStorage);
265
- providers.forEach((provider2) => {
266
- const prefixes = typeof provider2 === "string" && typeof prefix === "string" ? [prefix] : Object.keys(dataStorage[provider2] || {});
267
- prefixes.forEach((prefix2) => {
268
- const storage = getStorage(provider2, prefix2);
269
- allIcons = allIcons.concat(
270
- Object.keys(storage.icons).map(
271
- (name) => (provider2 !== "" ? "@" + provider2 + ":" : "") + prefix2 + ":" + name
272
- )
273
- );
274
- });
275
- });
276
- return allIcons;
263
+ let allIcons = [];
264
+ (typeof provider === "string" ? [provider] : Object.keys(dataStorage)).forEach((provider) => {
265
+ (typeof provider === "string" && typeof prefix === "string" ? [prefix] : Object.keys(dataStorage[provider] || {})).forEach((prefix) => {
266
+ const storage = getStorage(provider, prefix);
267
+ allIcons = allIcons.concat(Object.keys(storage.icons).map((name) => (provider !== "" ? "@" + provider + ":" : "") + prefix + ":" + name));
268
+ });
269
+ });
270
+ return allIcons;
277
271
  }
278
272
 
273
+ /**
274
+ * Allow storing icons without provider or prefix, making it possible to store icons like "home"
275
+ */
279
276
  let simpleNames = false;
280
277
  function allowSimpleNames(allow) {
281
- if (typeof allow === "boolean") {
282
- simpleNames = allow;
283
- }
284
- return simpleNames;
278
+ if (typeof allow === "boolean") simpleNames = allow;
279
+ return simpleNames;
285
280
  }
281
+ /**
282
+ * Get icon data
283
+ *
284
+ * Returns:
285
+ * - IconifyIcon on success, object directly from storage so don't modify it
286
+ * - null if icon is marked as missing (returned in `not_found` property from API, so don't bother sending API requests)
287
+ * - undefined if icon is missing in storage
288
+ */
286
289
  function getIconData(name) {
287
- const icon = typeof name === "string" ? stringToIcon(name, true, simpleNames) : name;
288
- if (icon) {
289
- const storage = getStorage(icon.provider, icon.prefix);
290
- const iconName = icon.name;
291
- return storage.icons[iconName] || (storage.missing.has(iconName) ? null : void 0);
292
- }
290
+ const icon = typeof name === "string" ? stringToIcon(name, true, simpleNames) : name;
291
+ if (icon) {
292
+ const storage = getStorage(icon.provider, icon.prefix);
293
+ const iconName = icon.name;
294
+ return storage.icons[iconName] || (storage.missing.has(iconName) ? null : void 0);
295
+ }
293
296
  }
297
+ /**
298
+ * Add one icon
299
+ */
294
300
  function addIcon(name, data) {
295
- const icon = stringToIcon(name, true, simpleNames);
296
- if (!icon) {
297
- return false;
298
- }
299
- const storage = getStorage(icon.provider, icon.prefix);
300
- if (data) {
301
- return addIconToStorage(storage, icon.name, data);
302
- } else {
303
- storage.missing.add(icon.name);
304
- return true;
305
- }
301
+ const icon = stringToIcon(name, true, simpleNames);
302
+ if (!icon) return false;
303
+ const storage = getStorage(icon.provider, icon.prefix);
304
+ if (data) return addIconToStorage(storage, icon.name, data);
305
+ else {
306
+ storage.missing.add(icon.name);
307
+ return true;
308
+ }
306
309
  }
310
+ /**
311
+ * Add icon set
312
+ */
307
313
  function addCollection(data, provider) {
308
- if (typeof data !== "object") {
309
- return false;
310
- }
311
- if (typeof provider !== "string") {
312
- provider = data.provider || "";
313
- }
314
- if (simpleNames && !provider && !data.prefix) {
315
- let added = false;
316
- if (quicklyValidateIconSet(data)) {
317
- data.prefix = "";
318
- parseIconSet(data, (name, icon) => {
319
- if (addIcon(name, icon)) {
320
- added = true;
321
- }
322
- });
323
- }
324
- return added;
325
- }
326
- const prefix = data.prefix;
327
- if (!validateIconName({
328
- provider,
329
- prefix,
330
- name: "a"
331
- })) {
332
- return false;
333
- }
334
- const storage = getStorage(provider, prefix);
335
- return !!addIconSet(storage, data);
314
+ if (typeof data !== "object") return false;
315
+ if (typeof provider !== "string") provider = data.provider || "";
316
+ if (simpleNames && !provider && !data.prefix) {
317
+ let added = false;
318
+ if (quicklyValidateIconSet(data)) {
319
+ data.prefix = "";
320
+ parseIconSet(data, (name, icon) => {
321
+ if (addIcon(name, icon)) added = true;
322
+ });
323
+ }
324
+ return added;
325
+ }
326
+ const prefix = data.prefix;
327
+ if (!validateIconName({
328
+ prefix,
329
+ name: "a"
330
+ })) return false;
331
+ return !!addIconSet(getStorage(provider, prefix), data);
336
332
  }
333
+ /**
334
+ * Check if icon data is available
335
+ */
337
336
  function iconLoaded(name) {
338
- return !!getIconData(name);
337
+ return !!getIconData(name);
339
338
  }
339
+ /**
340
+ * Get full icon
341
+ */
340
342
  function getIcon(name) {
341
- const result = getIconData(name);
342
- return result ? {
343
- ...defaultIconProps,
344
- ...result
345
- } : result;
343
+ const result = getIconData(name);
344
+ return result ? {
345
+ ...defaultIconProps,
346
+ ...result
347
+ } : result;
346
348
  }
347
349
 
350
+ /**
351
+ * Default icon customisations values
352
+ */
348
353
  const defaultIconSizeCustomisations = Object.freeze({
349
- width: null,
350
- height: null
354
+ width: null,
355
+ height: null
351
356
  });
352
357
  const defaultIconCustomisations = Object.freeze({
353
- // Dimensions
354
- ...defaultIconSizeCustomisations,
355
- // Transformations
356
- ...defaultIconTransformations
358
+ ...defaultIconSizeCustomisations,
359
+ ...defaultIconTransformations
357
360
  });
358
361
 
362
+ /**
363
+ * Regular expressions for calculating dimensions
364
+ */
359
365
  const unitsSplit = /(-?[0-9.]*[0-9]+[0-9.]*)/g;
360
366
  const unitsTest = /^-?[0-9.]*[0-9]+[0-9.]*$/g;
361
367
  function calculateSize(size, ratio, precision) {
362
- if (ratio === 1) {
363
- return size;
364
- }
365
- precision = precision || 100;
366
- if (typeof size === "number") {
367
- return Math.ceil(size * ratio * precision) / precision;
368
- }
369
- if (typeof size !== "string") {
370
- return size;
371
- }
372
- const oldParts = size.split(unitsSplit);
373
- if (oldParts === null || !oldParts.length) {
374
- return size;
375
- }
376
- const newParts = [];
377
- let code = oldParts.shift();
378
- let isNumber = unitsTest.test(code);
379
- while (true) {
380
- if (isNumber) {
381
- const num = parseFloat(code);
382
- if (isNaN(num)) {
383
- newParts.push(code);
384
- } else {
385
- newParts.push(Math.ceil(num * ratio * precision) / precision);
386
- }
387
- } else {
388
- newParts.push(code);
389
- }
390
- code = oldParts.shift();
391
- if (code === void 0) {
392
- return newParts.join("");
393
- }
394
- isNumber = !isNumber;
395
- }
368
+ if (ratio === 1) return size;
369
+ precision = precision || 100;
370
+ if (typeof size === "number") return Math.ceil(size * ratio * precision) / precision;
371
+ if (typeof size !== "string") return size;
372
+ const oldParts = size.split(unitsSplit);
373
+ if (oldParts === null || !oldParts.length) return size;
374
+ const newParts = [];
375
+ let code = oldParts.shift();
376
+ let isNumber = unitsTest.test(code);
377
+ while (true) {
378
+ if (isNumber) {
379
+ const num = parseFloat(code);
380
+ if (isNaN(num)) newParts.push(code);
381
+ else newParts.push(Math.ceil(num * ratio * precision) / precision);
382
+ } else newParts.push(code);
383
+ code = oldParts.shift();
384
+ if (code === void 0) return newParts.join("");
385
+ isNumber = !isNumber;
386
+ }
396
387
  }
397
388
 
398
389
  function splitSVGDefs(content, tag = "defs") {
399
- let defs = "";
400
- const index = content.indexOf("<" + tag);
401
- while (index >= 0) {
402
- const start = content.indexOf(">", index);
403
- const end = content.indexOf("</" + tag);
404
- if (start === -1 || end === -1) {
405
- break;
406
- }
407
- const endEnd = content.indexOf(">", end);
408
- if (endEnd === -1) {
409
- break;
410
- }
411
- defs += content.slice(start + 1, end).trim();
412
- content = content.slice(0, index).trim() + content.slice(endEnd + 1);
413
- }
414
- return {
415
- defs,
416
- content
417
- };
390
+ let defs = "";
391
+ const index = content.indexOf("<" + tag);
392
+ while (index >= 0) {
393
+ const start = content.indexOf(">", index);
394
+ const end = content.indexOf("</" + tag);
395
+ if (start === -1 || end === -1) break;
396
+ const endEnd = content.indexOf(">", end);
397
+ if (endEnd === -1) break;
398
+ defs += content.slice(start + 1, end).trim();
399
+ content = content.slice(0, index).trim() + content.slice(endEnd + 1);
400
+ }
401
+ return {
402
+ defs,
403
+ content
404
+ };
418
405
  }
406
+ /**
407
+ * Merge defs and content
408
+ */
419
409
  function mergeDefsAndContent(defs, content) {
420
- return defs ? "<defs>" + defs + "</defs>" + content : content;
410
+ return defs ? "<defs>" + defs + "</defs>" + content : content;
421
411
  }
412
+ /**
413
+ * Wrap SVG content, without wrapping definitions
414
+ */
422
415
  function wrapSVGContent(body, start, end) {
423
- const split = splitSVGDefs(body);
424
- return mergeDefsAndContent(split.defs, start + split.content + end);
416
+ const split = splitSVGDefs(body);
417
+ return mergeDefsAndContent(split.defs, start + split.content + end);
425
418
  }
426
419
 
420
+ /**
421
+ * Check if value should be unset. Allows multiple keywords
422
+ */
427
423
  const isUnsetKeyword = (value) => value === "unset" || value === "undefined" || value === "none";
424
+ /**
425
+ * Get SVG attributes and content from icon + customisations
426
+ *
427
+ * Does not generate style to make it compatible with frameworks that use objects for style, such as React.
428
+ * Instead, it generates 'inline' value. If true, rendering engine should add verticalAlign: -0.125em to icon.
429
+ *
430
+ * Customisations should be normalised by platform specific parser.
431
+ * Result should be converted to <svg> by platform specific parser.
432
+ * Use replaceIDs to generate unique IDs for body.
433
+ */
428
434
  function iconToSVG(icon, customisations) {
429
- const fullIcon = {
430
- ...defaultIconProps,
431
- ...icon
432
- };
433
- const fullCustomisations = {
434
- ...defaultIconCustomisations,
435
- ...customisations
436
- };
437
- const box = {
438
- left: fullIcon.left,
439
- top: fullIcon.top,
440
- width: fullIcon.width,
441
- height: fullIcon.height
442
- };
443
- let body = fullIcon.body;
444
- [fullIcon, fullCustomisations].forEach((props) => {
445
- const transformations = [];
446
- const hFlip = props.hFlip;
447
- const vFlip = props.vFlip;
448
- let rotation = props.rotate;
449
- if (hFlip) {
450
- if (vFlip) {
451
- rotation += 2;
452
- } else {
453
- transformations.push(
454
- "translate(" + (box.width + box.left).toString() + " " + (0 - box.top).toString() + ")"
455
- );
456
- transformations.push("scale(-1 1)");
457
- box.top = box.left = 0;
458
- }
459
- } else if (vFlip) {
460
- transformations.push(
461
- "translate(" + (0 - box.left).toString() + " " + (box.height + box.top).toString() + ")"
462
- );
463
- transformations.push("scale(1 -1)");
464
- box.top = box.left = 0;
465
- }
466
- let tempValue;
467
- if (rotation < 0) {
468
- rotation -= Math.floor(rotation / 4) * 4;
469
- }
470
- rotation = rotation % 4;
471
- switch (rotation) {
472
- case 1:
473
- tempValue = box.height / 2 + box.top;
474
- transformations.unshift(
475
- "rotate(90 " + tempValue.toString() + " " + tempValue.toString() + ")"
476
- );
477
- break;
478
- case 2:
479
- transformations.unshift(
480
- "rotate(180 " + (box.width / 2 + box.left).toString() + " " + (box.height / 2 + box.top).toString() + ")"
481
- );
482
- break;
483
- case 3:
484
- tempValue = box.width / 2 + box.left;
485
- transformations.unshift(
486
- "rotate(-90 " + tempValue.toString() + " " + tempValue.toString() + ")"
487
- );
488
- break;
489
- }
490
- if (rotation % 2 === 1) {
491
- if (box.left !== box.top) {
492
- tempValue = box.left;
493
- box.left = box.top;
494
- box.top = tempValue;
495
- }
496
- if (box.width !== box.height) {
497
- tempValue = box.width;
498
- box.width = box.height;
499
- box.height = tempValue;
500
- }
501
- }
502
- if (transformations.length) {
503
- body = wrapSVGContent(
504
- body,
505
- '<g transform="' + transformations.join(" ") + '">',
506
- "</g>"
507
- );
508
- }
509
- });
510
- const customisationsWidth = fullCustomisations.width;
511
- const customisationsHeight = fullCustomisations.height;
512
- const boxWidth = box.width;
513
- const boxHeight = box.height;
514
- let width;
515
- let height;
516
- if (customisationsWidth === null) {
517
- height = customisationsHeight === null ? "1em" : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
518
- width = calculateSize(height, boxWidth / boxHeight);
519
- } else {
520
- width = customisationsWidth === "auto" ? boxWidth : customisationsWidth;
521
- height = customisationsHeight === null ? calculateSize(width, boxHeight / boxWidth) : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
522
- }
523
- const attributes = {};
524
- const setAttr = (prop, value) => {
525
- if (!isUnsetKeyword(value)) {
526
- attributes[prop] = value.toString();
527
- }
528
- };
529
- setAttr("width", width);
530
- setAttr("height", height);
531
- const viewBox = [box.left, box.top, boxWidth, boxHeight];
532
- attributes.viewBox = viewBox.join(" ");
533
- return {
534
- attributes,
535
- viewBox,
536
- body
537
- };
435
+ const fullIcon = {
436
+ ...defaultIconProps,
437
+ ...icon
438
+ };
439
+ const fullCustomisations = {
440
+ ...defaultIconCustomisations,
441
+ ...customisations
442
+ };
443
+ const box = {
444
+ left: fullIcon.left,
445
+ top: fullIcon.top,
446
+ width: fullIcon.width,
447
+ height: fullIcon.height
448
+ };
449
+ let body = fullIcon.body;
450
+ [fullIcon, fullCustomisations].forEach((props) => {
451
+ const transformations = [];
452
+ const hFlip = props.hFlip;
453
+ const vFlip = props.vFlip;
454
+ let rotation = props.rotate;
455
+ if (hFlip) if (vFlip) rotation += 2;
456
+ else {
457
+ transformations.push("translate(" + (box.width + box.left).toString() + " " + (0 - box.top).toString() + ")");
458
+ transformations.push("scale(-1 1)");
459
+ box.top = box.left = 0;
460
+ }
461
+ else if (vFlip) {
462
+ transformations.push("translate(" + (0 - box.left).toString() + " " + (box.height + box.top).toString() + ")");
463
+ transformations.push("scale(1 -1)");
464
+ box.top = box.left = 0;
465
+ }
466
+ let tempValue;
467
+ if (rotation < 0) rotation -= Math.floor(rotation / 4) * 4;
468
+ rotation = rotation % 4;
469
+ switch (rotation) {
470
+ case 1:
471
+ tempValue = box.height / 2 + box.top;
472
+ transformations.unshift("rotate(90 " + tempValue.toString() + " " + tempValue.toString() + ")");
473
+ break;
474
+ case 2:
475
+ transformations.unshift("rotate(180 " + (box.width / 2 + box.left).toString() + " " + (box.height / 2 + box.top).toString() + ")");
476
+ break;
477
+ case 3:
478
+ tempValue = box.width / 2 + box.left;
479
+ transformations.unshift("rotate(-90 " + tempValue.toString() + " " + tempValue.toString() + ")");
480
+ break;
481
+ }
482
+ if (rotation % 2 === 1) {
483
+ if (box.left !== box.top) {
484
+ tempValue = box.left;
485
+ box.left = box.top;
486
+ box.top = tempValue;
487
+ }
488
+ if (box.width !== box.height) {
489
+ tempValue = box.width;
490
+ box.width = box.height;
491
+ box.height = tempValue;
492
+ }
493
+ }
494
+ if (transformations.length) body = wrapSVGContent(body, "<g transform=\"" + transformations.join(" ") + "\">", "</g>");
495
+ });
496
+ const customisationsWidth = fullCustomisations.width;
497
+ const customisationsHeight = fullCustomisations.height;
498
+ const boxWidth = box.width;
499
+ const boxHeight = box.height;
500
+ let width;
501
+ let height;
502
+ if (customisationsWidth === null) {
503
+ height = customisationsHeight === null ? "1em" : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
504
+ width = calculateSize(height, boxWidth / boxHeight);
505
+ } else {
506
+ width = customisationsWidth === "auto" ? boxWidth : customisationsWidth;
507
+ height = customisationsHeight === null ? calculateSize(width, boxHeight / boxWidth) : customisationsHeight === "auto" ? boxHeight : customisationsHeight;
508
+ }
509
+ const attributes = {};
510
+ const setAttr = (prop, value) => {
511
+ if (!isUnsetKeyword(value)) attributes[prop] = value.toString();
512
+ };
513
+ setAttr("width", width);
514
+ setAttr("height", height);
515
+ const viewBox = [
516
+ box.left,
517
+ box.top,
518
+ boxWidth,
519
+ boxHeight
520
+ ];
521
+ attributes.viewBox = viewBox.join(" ");
522
+ return {
523
+ attributes,
524
+ viewBox,
525
+ body
526
+ };
538
527
  }
539
528
 
529
+ /**
530
+ * Regular expression for finding ids
531
+ */
540
532
  const regex = /\sid="(\S+)"/g;
541
- const randomPrefix = "IconifyId" + Date.now().toString(16) + (Math.random() * 16777216 | 0).toString(16);
542
- let counter = 0;
543
- function replaceIDs(body, prefix = randomPrefix) {
544
- const ids = [];
545
- let match;
546
- while (match = regex.exec(body)) {
547
- ids.push(match[1]);
548
- }
549
- if (!ids.length) {
550
- return body;
551
- }
552
- const suffix = "suffix" + (Math.random() * 16777216 | Date.now()).toString(16);
553
- ids.forEach((id) => {
554
- const newID = typeof prefix === "function" ? prefix(id) : prefix + (counter++).toString();
555
- const escapedID = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
556
- body = body.replace(
557
- // Allowed characters before id: [#;"]
558
- // Allowed characters after id: [)"], .[a-z]
559
- new RegExp('([#;"])(' + escapedID + ')([")]|\\.[a-z])', "g"),
560
- "$1" + newID + suffix + "$3"
561
- );
562
- });
563
- body = body.replace(new RegExp(suffix, "g"), "");
564
- return body;
533
+ /**
534
+ * Counters
535
+ */
536
+ const counters = /* @__PURE__ */ new Map();
537
+ /**
538
+ * Get unique new ID
539
+ */
540
+ function nextID(id) {
541
+ id = id.replace(/[0-9]+$/, "") || "a";
542
+ const count = counters.get(id) || 0;
543
+ counters.set(id, count + 1);
544
+ return count ? `${id}${count}` : id;
545
+ }
546
+ /**
547
+ * Replace IDs in SVG output with unique IDs
548
+ */
549
+ function replaceIDs(body) {
550
+ const ids = [];
551
+ let match;
552
+ while (match = regex.exec(body)) ids.push(match[1]);
553
+ if (!ids.length) return body;
554
+ const suffix = "suffix" + (Math.random() * 16777216 | Date.now()).toString(16);
555
+ ids.forEach((id) => {
556
+ const newID = nextID(id);
557
+ const escapedID = id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
558
+ body = body.replace(new RegExp("([#;\"])(" + escapedID + ")([\")]|\\.[a-z])", "g"), "$1" + newID + suffix + "$3");
559
+ });
560
+ body = body.replace(new RegExp(suffix, "g"), "");
561
+ return body;
562
+ }
563
+ /**
564
+ * Clear ID cache
565
+ */
566
+ function clearIDCache() {
567
+ counters.clear();
565
568
  }
566
569
 
567
- const storage = /* @__PURE__ */ Object.create(null);
570
+ /**
571
+ * Local storate types and entries
572
+ */
573
+ const storage = Object.create(null);
574
+ /**
575
+ * Set API module
576
+ */
568
577
  function setAPIModule(provider, item) {
569
- storage[provider] = item;
578
+ storage[provider] = item;
570
579
  }
580
+ /**
581
+ * Get API module
582
+ */
571
583
  function getAPIModule(provider) {
572
- return storage[provider] || storage[""];
584
+ return storage[provider] || storage[""];
573
585
  }
574
586
 
587
+ /**
588
+ * Create full API configuration from partial data
589
+ */
575
590
  function createAPIConfig(source) {
576
- let resources;
577
- if (typeof source.resources === "string") {
578
- resources = [source.resources];
579
- } else {
580
- resources = source.resources;
581
- if (!(resources instanceof Array) || !resources.length) {
582
- return null;
583
- }
584
- }
585
- const result = {
586
- // API hosts
587
- resources,
588
- // Root path
589
- path: source.path || "/",
590
- // URL length limit
591
- maxURL: source.maxURL || 500,
592
- // Timeout before next host is used.
593
- rotate: source.rotate || 750,
594
- // Timeout before failing query.
595
- timeout: source.timeout || 5e3,
596
- // Randomise default API end point.
597
- random: source.random === true,
598
- // Start index
599
- index: source.index || 0,
600
- // Receive data after time out (used if time out kicks in first, then API module sends data anyway).
601
- dataAfterTimeout: source.dataAfterTimeout !== false
602
- };
603
- return result;
591
+ let resources;
592
+ if (typeof source.resources === "string") resources = [source.resources];
593
+ else {
594
+ resources = source.resources;
595
+ if (!(resources instanceof Array) || !resources.length) return null;
596
+ }
597
+ return {
598
+ resources,
599
+ path: source.path || "/",
600
+ maxURL: source.maxURL || 500,
601
+ rotate: source.rotate || 750,
602
+ timeout: source.timeout || 5e3,
603
+ random: source.random === true,
604
+ index: source.index || 0,
605
+ dataAfterTimeout: source.dataAfterTimeout !== false
606
+ };
604
607
  }
605
- const configStorage = /* @__PURE__ */ Object.create(null);
606
- const fallBackAPISources = [
607
- "https://api.simplesvg.com",
608
- "https://api.unisvg.com"
609
- ];
608
+ /**
609
+ * Local storage
610
+ */
611
+ const configStorage = Object.create(null);
612
+ /**
613
+ * Redundancy for API servers.
614
+ *
615
+ * API should have very high uptime because of implemented redundancy at server level, but
616
+ * sometimes bad things happen. On internet 100% uptime is not possible.
617
+ *
618
+ * There could be routing problems. Server might go down for whatever reason, but it takes
619
+ * few minutes to detect that downtime, so during those few minutes API might not be accessible.
620
+ *
621
+ * This script has some redundancy to mitigate possible network issues.
622
+ *
623
+ * If one host cannot be reached in 'rotate' (750 by default) ms, script will try to retrieve
624
+ * data from different host. Hosts have different configurations, pointing to different
625
+ * API servers hosted at different providers.
626
+ */
627
+ const fallBackAPISources = ["https://api.simplesvg.com", "https://api.unisvg.com"];
610
628
  const fallBackAPI = [];
611
- while (fallBackAPISources.length > 0) {
612
- if (fallBackAPISources.length === 1) {
613
- fallBackAPI.push(fallBackAPISources.shift());
614
- } else {
615
- if (Math.random() > 0.5) {
616
- fallBackAPI.push(fallBackAPISources.shift());
617
- } else {
618
- fallBackAPI.push(fallBackAPISources.pop());
619
- }
620
- }
621
- }
622
- configStorage[""] = createAPIConfig({
623
- resources: ["https://api.iconify.design"].concat(fallBackAPI)
624
- });
629
+ while (fallBackAPISources.length > 0) if (fallBackAPISources.length === 1) fallBackAPI.push(fallBackAPISources.shift());
630
+ else if (Math.random() > .5) fallBackAPI.push(fallBackAPISources.shift());
631
+ else fallBackAPI.push(fallBackAPISources.pop());
632
+ configStorage[""] = createAPIConfig({ resources: ["https://api.iconify.design"].concat(fallBackAPI) });
633
+ /**
634
+ * Add custom config for provider
635
+ */
625
636
  function addAPIProvider(provider, customConfig) {
626
- const config = createAPIConfig(customConfig);
627
- if (config === null) {
628
- return false;
629
- }
630
- configStorage[provider] = config;
631
- return true;
637
+ const config = createAPIConfig(customConfig);
638
+ if (config === null) return false;
639
+ configStorage[provider] = config;
640
+ return true;
632
641
  }
642
+ /**
643
+ * Get API configuration
644
+ */
633
645
  function getAPIConfig(provider) {
634
- return configStorage[provider];
646
+ return configStorage[provider];
635
647
  }
648
+ /**
649
+ * List API providers
650
+ */
636
651
  function listAPIProviders() {
637
- return Object.keys(configStorage);
652
+ return Object.keys(configStorage);
638
653
  }
639
654
 
640
655
  const detectFetch = () => {
641
- let callback;
642
- try {
643
- callback = fetch;
644
- if (typeof callback === "function") {
645
- return callback;
646
- }
647
- } catch (err) {
648
- }
656
+ let callback;
657
+ try {
658
+ callback = fetch;
659
+ if (typeof callback === "function") return callback;
660
+ } catch (err) {}
649
661
  };
662
+ /**
663
+ * Fetch function
664
+ */
650
665
  let fetchModule = detectFetch();
651
- function setFetch(fetch2) {
652
- fetchModule = fetch2;
666
+ /**
667
+ * Set custom fetch() function
668
+ */
669
+ function setFetch(fetch) {
670
+ fetchModule = fetch;
653
671
  }
672
+ /**
673
+ * Get fetch() function. Used by Icon Finder Core
674
+ */
654
675
  function getFetch() {
655
- return fetchModule;
676
+ return fetchModule;
656
677
  }
678
+ /**
679
+ * Calculate maximum icons list length for prefix
680
+ */
657
681
  function calculateMaxLength(provider, prefix) {
658
- const config = getAPIConfig(provider);
659
- if (!config) {
660
- return 0;
661
- }
662
- let result;
663
- if (!config.maxURL) {
664
- result = 0;
665
- } else {
666
- let maxHostLength = 0;
667
- config.resources.forEach((item) => {
668
- const host = item;
669
- maxHostLength = Math.max(maxHostLength, host.length);
670
- });
671
- const url = prefix + ".json?icons=";
672
- result = config.maxURL - maxHostLength - config.path.length - url.length;
673
- }
674
- return result;
682
+ const config = getAPIConfig(provider);
683
+ if (!config) return 0;
684
+ let result;
685
+ if (!config.maxURL) result = 0;
686
+ else {
687
+ let maxHostLength = 0;
688
+ config.resources.forEach((item) => {
689
+ maxHostLength = Math.max(maxHostLength, item.length);
690
+ });
691
+ const url = prefix + ".json?icons=";
692
+ result = config.maxURL - maxHostLength - config.path.length - url.length;
693
+ }
694
+ return result;
675
695
  }
696
+ /**
697
+ * Should query be aborted, based on last HTTP status
698
+ */
676
699
  function shouldAbort(status) {
677
- return status === 404;
700
+ return status === 404;
678
701
  }
702
+ /**
703
+ * Prepare params
704
+ */
679
705
  const prepare = (provider, prefix, icons) => {
680
- const results = [];
681
- const maxLength = calculateMaxLength(provider, prefix);
682
- const type = "icons";
683
- let item = {
684
- type,
685
- provider,
686
- prefix,
687
- icons: []
688
- };
689
- let length = 0;
690
- icons.forEach((name, index) => {
691
- length += name.length + 1;
692
- if (length >= maxLength && index > 0) {
693
- results.push(item);
694
- item = {
695
- type,
696
- provider,
697
- prefix,
698
- icons: []
699
- };
700
- length = name.length;
701
- }
702
- item.icons.push(name);
703
- });
704
- results.push(item);
705
- return results;
706
+ const results = [];
707
+ const maxLength = calculateMaxLength(provider, prefix);
708
+ const type = "icons";
709
+ let item = {
710
+ type,
711
+ provider,
712
+ prefix,
713
+ icons: []
714
+ };
715
+ let length = 0;
716
+ icons.forEach((name, index) => {
717
+ length += name.length + 1;
718
+ if (length >= maxLength && index > 0) {
719
+ results.push(item);
720
+ item = {
721
+ type,
722
+ provider,
723
+ prefix,
724
+ icons: []
725
+ };
726
+ length = name.length;
727
+ }
728
+ item.icons.push(name);
729
+ });
730
+ results.push(item);
731
+ return results;
706
732
  };
733
+ /**
734
+ * Get path
735
+ */
707
736
  function getPath(provider) {
708
- if (typeof provider === "string") {
709
- const config = getAPIConfig(provider);
710
- if (config) {
711
- return config.path;
712
- }
713
- }
714
- return "/";
737
+ if (typeof provider === "string") {
738
+ const config = getAPIConfig(provider);
739
+ if (config) return config.path;
740
+ }
741
+ return "/";
715
742
  }
743
+ /**
744
+ * Load icons
745
+ */
716
746
  const send = (host, params, callback) => {
717
- if (!fetchModule) {
718
- callback("abort", 424);
719
- return;
720
- }
721
- let path = getPath(params.provider);
722
- switch (params.type) {
723
- case "icons": {
724
- const prefix = params.prefix;
725
- const icons = params.icons;
726
- const iconsList = icons.join(",");
727
- const urlParams = new URLSearchParams({
728
- icons: iconsList
729
- });
730
- path += prefix + ".json?" + urlParams.toString();
731
- break;
732
- }
733
- case "custom": {
734
- const uri = params.uri;
735
- path += uri.slice(0, 1) === "/" ? uri.slice(1) : uri;
736
- break;
737
- }
738
- default:
739
- callback("abort", 400);
740
- return;
741
- }
742
- let defaultError = 503;
743
- fetchModule(host + path).then((response) => {
744
- const status = response.status;
745
- if (status !== 200) {
746
- setTimeout(() => {
747
- callback(shouldAbort(status) ? "abort" : "next", status);
748
- });
749
- return;
750
- }
751
- defaultError = 501;
752
- return response.json();
753
- }).then((data) => {
754
- if (typeof data !== "object" || data === null) {
755
- setTimeout(() => {
756
- if (data === 404) {
757
- callback("abort", data);
758
- } else {
759
- callback("next", defaultError);
760
- }
761
- });
762
- return;
763
- }
764
- setTimeout(() => {
765
- callback("success", data);
766
- });
767
- }).catch(() => {
768
- callback("next", defaultError);
769
- });
747
+ if (!fetchModule) {
748
+ callback("abort", 424);
749
+ return;
750
+ }
751
+ let path = getPath(params.provider);
752
+ switch (params.type) {
753
+ case "icons": {
754
+ const prefix = params.prefix;
755
+ const iconsList = params.icons.join(",");
756
+ const urlParams = new URLSearchParams({ icons: iconsList });
757
+ path += prefix + ".json?" + urlParams.toString();
758
+ break;
759
+ }
760
+ case "custom": {
761
+ const uri = params.uri;
762
+ path += uri.slice(0, 1) === "/" ? uri.slice(1) : uri;
763
+ break;
764
+ }
765
+ default:
766
+ callback("abort", 400);
767
+ return;
768
+ }
769
+ let defaultError = 503;
770
+ fetchModule(host + path).then((response) => {
771
+ const status = response.status;
772
+ if (status !== 200) {
773
+ setTimeout(() => {
774
+ callback(shouldAbort(status) ? "abort" : "next", status);
775
+ });
776
+ return;
777
+ }
778
+ defaultError = 501;
779
+ return response.json();
780
+ }).then((data) => {
781
+ if (typeof data !== "object" || data === null) {
782
+ setTimeout(() => {
783
+ if (data === 404) callback("abort", data);
784
+ else callback("next", defaultError);
785
+ });
786
+ return;
787
+ }
788
+ setTimeout(() => {
789
+ callback("success", data);
790
+ });
791
+ }).catch(() => {
792
+ callback("next", defaultError);
793
+ });
770
794
  };
795
+ /**
796
+ * Export module
797
+ */
771
798
  const fetchAPIModule = {
772
- prepare,
773
- send
799
+ prepare,
800
+ send
774
801
  };
775
802
 
776
- function sortIcons(icons) {
777
- const result = {
778
- loaded: [],
779
- missing: [],
780
- pending: []
781
- };
782
- const storage = /* @__PURE__ */ Object.create(null);
783
- icons.sort((a, b) => {
784
- if (a.provider !== b.provider) {
785
- return a.provider.localeCompare(b.provider);
786
- }
787
- if (a.prefix !== b.prefix) {
788
- return a.prefix.localeCompare(b.prefix);
789
- }
790
- return a.name.localeCompare(b.name);
791
- });
792
- let lastIcon = {
793
- provider: "",
794
- prefix: "",
795
- name: ""
796
- };
797
- icons.forEach((icon) => {
798
- if (lastIcon.name === icon.name && lastIcon.prefix === icon.prefix && lastIcon.provider === icon.provider) {
799
- return;
800
- }
801
- lastIcon = icon;
802
- const provider = icon.provider;
803
- const prefix = icon.prefix;
804
- const name = icon.name;
805
- const providerStorage = storage[provider] || (storage[provider] = /* @__PURE__ */ Object.create(null));
806
- const localStorage = providerStorage[prefix] || (providerStorage[prefix] = getStorage(provider, prefix));
807
- let list;
808
- if (name in localStorage.icons) {
809
- list = result.loaded;
810
- } else if (prefix === "" || localStorage.missing.has(name)) {
811
- list = result.missing;
812
- } else {
813
- list = result.pending;
814
- }
815
- const item = {
816
- provider,
817
- prefix,
818
- name
819
- };
820
- list.push(item);
821
- });
822
- return result;
823
- }
824
-
803
+ /**
804
+ * Remove callback
805
+ */
825
806
  function removeCallback(storages, id) {
826
- storages.forEach((storage) => {
827
- const items = storage.loaderCallbacks;
828
- if (items) {
829
- storage.loaderCallbacks = items.filter((row) => row.id !== id);
830
- }
831
- });
807
+ storages.forEach((storage) => {
808
+ const items = storage.loaderCallbacks;
809
+ if (items) storage.loaderCallbacks = items.filter((row) => row.id !== id);
810
+ });
832
811
  }
812
+ /**
813
+ * Update all callbacks for provider and prefix
814
+ */
833
815
  function updateCallbacks(storage) {
834
- if (!storage.pendingCallbacksFlag) {
835
- storage.pendingCallbacksFlag = true;
836
- setTimeout(() => {
837
- storage.pendingCallbacksFlag = false;
838
- const items = storage.loaderCallbacks ? storage.loaderCallbacks.slice(0) : [];
839
- if (!items.length) {
840
- return;
841
- }
842
- let hasPending = false;
843
- const provider = storage.provider;
844
- const prefix = storage.prefix;
845
- items.forEach((item) => {
846
- const icons = item.icons;
847
- const oldLength = icons.pending.length;
848
- icons.pending = icons.pending.filter((icon) => {
849
- if (icon.prefix !== prefix) {
850
- return true;
851
- }
852
- const name = icon.name;
853
- if (storage.icons[name]) {
854
- icons.loaded.push({
855
- provider,
856
- prefix,
857
- name
858
- });
859
- } else if (storage.missing.has(name)) {
860
- icons.missing.push({
861
- provider,
862
- prefix,
863
- name
864
- });
865
- } else {
866
- hasPending = true;
867
- return true;
868
- }
869
- return false;
870
- });
871
- if (icons.pending.length !== oldLength) {
872
- if (!hasPending) {
873
- removeCallback([storage], item.id);
874
- }
875
- item.callback(
876
- icons.loaded.slice(0),
877
- icons.missing.slice(0),
878
- icons.pending.slice(0),
879
- item.abort
880
- );
881
- }
882
- });
883
- });
884
- }
816
+ if (!storage.pendingCallbacksFlag) {
817
+ storage.pendingCallbacksFlag = true;
818
+ setTimeout(() => {
819
+ storage.pendingCallbacksFlag = false;
820
+ const items = storage.loaderCallbacks ? storage.loaderCallbacks.slice(0) : [];
821
+ if (!items.length) return;
822
+ let hasPending = false;
823
+ const provider = storage.provider;
824
+ const prefix = storage.prefix;
825
+ items.forEach((item) => {
826
+ const icons = item.icons;
827
+ const oldLength = icons.pending.length;
828
+ icons.pending = icons.pending.filter((icon) => {
829
+ if (icon.prefix !== prefix) return true;
830
+ const name = icon.name;
831
+ if (storage.icons[name]) icons.loaded.push({
832
+ provider,
833
+ prefix,
834
+ name
835
+ });
836
+ else if (storage.missing.has(name)) icons.missing.push({
837
+ provider,
838
+ prefix,
839
+ name
840
+ });
841
+ else {
842
+ hasPending = true;
843
+ return true;
844
+ }
845
+ return false;
846
+ });
847
+ if (icons.pending.length !== oldLength) {
848
+ if (!hasPending) removeCallback([storage], item.id);
849
+ item.callback(icons.loaded.slice(0), icons.missing.slice(0), icons.pending.slice(0), item.abort);
850
+ }
851
+ });
852
+ });
853
+ }
885
854
  }
855
+ /**
856
+ * Unique id counter for callbacks
857
+ */
886
858
  let idCounter = 0;
859
+ /**
860
+ * Add callback
861
+ */
887
862
  function storeCallback(callback, icons, pendingSources) {
888
- const id = idCounter++;
889
- const abort = removeCallback.bind(null, pendingSources, id);
890
- if (!icons.pending.length) {
891
- return abort;
892
- }
893
- const item = {
894
- id,
895
- icons,
896
- callback,
897
- abort
898
- };
899
- pendingSources.forEach((storage) => {
900
- (storage.loaderCallbacks || (storage.loaderCallbacks = [])).push(item);
901
- });
902
- return abort;
863
+ const id = idCounter++;
864
+ const abort = removeCallback.bind(null, pendingSources, id);
865
+ if (!icons.pending.length) return abort;
866
+ const item = {
867
+ id,
868
+ icons,
869
+ callback,
870
+ abort
871
+ };
872
+ pendingSources.forEach((storage) => {
873
+ (storage.loaderCallbacks || (storage.loaderCallbacks = [])).push(item);
874
+ });
875
+ return abort;
876
+ }
877
+
878
+ /**
879
+ * Check if icons have been loaded
880
+ */
881
+ function sortIcons(icons) {
882
+ const result = {
883
+ loaded: [],
884
+ missing: [],
885
+ pending: []
886
+ };
887
+ const storage = Object.create(null);
888
+ icons.sort((a, b) => {
889
+ if (a.provider !== b.provider) return a.provider.localeCompare(b.provider);
890
+ if (a.prefix !== b.prefix) return a.prefix.localeCompare(b.prefix);
891
+ return a.name.localeCompare(b.name);
892
+ });
893
+ let lastIcon = {
894
+ provider: "",
895
+ prefix: "",
896
+ name: ""
897
+ };
898
+ icons.forEach((icon) => {
899
+ if (lastIcon.name === icon.name && lastIcon.prefix === icon.prefix && lastIcon.provider === icon.provider) return;
900
+ lastIcon = icon;
901
+ const provider = icon.provider;
902
+ const prefix = icon.prefix;
903
+ const name = icon.name;
904
+ const providerStorage = storage[provider] || (storage[provider] = Object.create(null));
905
+ const localStorage = providerStorage[prefix] || (providerStorage[prefix] = getStorage(provider, prefix));
906
+ let list;
907
+ if (name in localStorage.icons) list = result.loaded;
908
+ else if (prefix === "" || localStorage.missing.has(name)) list = result.missing;
909
+ else list = result.pending;
910
+ const item = {
911
+ provider,
912
+ prefix,
913
+ name
914
+ };
915
+ list.push(item);
916
+ });
917
+ return result;
903
918
  }
904
919
 
920
+ /**
921
+ * Convert icons list from string/icon mix to icons and validate them
922
+ */
905
923
  function listToIcons(list, validate = true, simpleNames = false) {
906
- const result = [];
907
- list.forEach((item) => {
908
- const icon = typeof item === "string" ? stringToIcon(item, validate, simpleNames) : item;
909
- if (icon) {
910
- result.push(icon);
911
- }
912
- });
913
- return result;
924
+ const result = [];
925
+ list.forEach((item) => {
926
+ const icon = typeof item === "string" ? stringToIcon(item, validate, simpleNames) : item;
927
+ if (icon) result.push(icon);
928
+ });
929
+ return result;
914
930
  }
915
931
 
916
- // src/config.ts
917
- var defaultConfig = {
918
- resources: [],
919
- index: 0,
920
- timeout: 2e3,
921
- rotate: 750,
922
- random: false,
923
- dataAfterTimeout: false
932
+ /**
933
+ * Default RedundancyConfig for API calls
934
+ */
935
+ const defaultConfig = {
936
+ resources: [],
937
+ index: 0,
938
+ timeout: 2e3,
939
+ rotate: 750,
940
+ random: false,
941
+ dataAfterTimeout: false
924
942
  };
925
-
926
- // src/query.ts
943
+ /**
944
+ * Send query
945
+ */
927
946
  function sendQuery(config, payload, query, done) {
928
- const resourcesCount = config.resources.length;
929
- const startIndex = config.random ? Math.floor(Math.random() * resourcesCount) : config.index;
930
- let resources;
931
- if (config.random) {
932
- let list = config.resources.slice(0);
933
- resources = [];
934
- while (list.length > 1) {
935
- const nextIndex = Math.floor(Math.random() * list.length);
936
- resources.push(list[nextIndex]);
937
- list = list.slice(0, nextIndex).concat(list.slice(nextIndex + 1));
938
- }
939
- resources = resources.concat(list);
940
- } else {
941
- resources = config.resources.slice(startIndex).concat(config.resources.slice(0, startIndex));
942
- }
943
- const startTime = Date.now();
944
- let status = "pending";
945
- let queriesSent = 0;
946
- let lastError;
947
- let timer = null;
948
- let queue = [];
949
- let doneCallbacks = [];
950
- if (typeof done === "function") {
951
- doneCallbacks.push(done);
952
- }
953
- function resetTimer() {
954
- if (timer) {
955
- clearTimeout(timer);
956
- timer = null;
957
- }
958
- }
959
- function abort() {
960
- if (status === "pending") {
961
- status = "aborted";
962
- }
963
- resetTimer();
964
- queue.forEach((item) => {
965
- if (item.status === "pending") {
966
- item.status = "aborted";
967
- }
968
- });
969
- queue = [];
970
- }
971
- function subscribe(callback, overwrite) {
972
- if (overwrite) {
973
- doneCallbacks = [];
974
- }
975
- if (typeof callback === "function") {
976
- doneCallbacks.push(callback);
977
- }
978
- }
979
- function getQueryStatus() {
980
- return {
981
- startTime,
982
- payload,
983
- status,
984
- queriesSent,
985
- queriesPending: queue.length,
986
- subscribe,
987
- abort
988
- };
989
- }
990
- function failQuery() {
991
- status = "failed";
992
- doneCallbacks.forEach((callback) => {
993
- callback(void 0, lastError);
994
- });
995
- }
996
- function clearQueue() {
997
- queue.forEach((item) => {
998
- if (item.status === "pending") {
999
- item.status = "aborted";
1000
- }
1001
- });
1002
- queue = [];
1003
- }
1004
- function moduleResponse(item, response, data) {
1005
- const isError = response !== "success";
1006
- queue = queue.filter((queued) => queued !== item);
1007
- switch (status) {
1008
- case "pending":
1009
- break;
1010
- case "failed":
1011
- if (isError || !config.dataAfterTimeout) {
1012
- return;
1013
- }
1014
- break;
1015
- default:
1016
- return;
1017
- }
1018
- if (response === "abort") {
1019
- lastError = data;
1020
- failQuery();
1021
- return;
1022
- }
1023
- if (isError) {
1024
- lastError = data;
1025
- if (!queue.length) {
1026
- if (!resources.length) {
1027
- failQuery();
1028
- } else {
1029
- execNext();
1030
- }
1031
- }
1032
- return;
1033
- }
1034
- resetTimer();
1035
- clearQueue();
1036
- if (!config.random) {
1037
- const index = config.resources.indexOf(item.resource);
1038
- if (index !== -1 && index !== config.index) {
1039
- config.index = index;
1040
- }
1041
- }
1042
- status = "completed";
1043
- doneCallbacks.forEach((callback) => {
1044
- callback(data);
1045
- });
1046
- }
1047
- function execNext() {
1048
- if (status !== "pending") {
1049
- return;
1050
- }
1051
- resetTimer();
1052
- const resource = resources.shift();
1053
- if (resource === void 0) {
1054
- if (queue.length) {
1055
- timer = setTimeout(() => {
1056
- resetTimer();
1057
- if (status === "pending") {
1058
- clearQueue();
1059
- failQuery();
1060
- }
1061
- }, config.timeout);
1062
- return;
1063
- }
1064
- failQuery();
1065
- return;
1066
- }
1067
- const item = {
1068
- status: "pending",
1069
- resource,
1070
- callback: (status2, data) => {
1071
- moduleResponse(item, status2, data);
1072
- }
1073
- };
1074
- queue.push(item);
1075
- queriesSent++;
1076
- timer = setTimeout(execNext, config.rotate);
1077
- query(resource, payload, item.callback);
1078
- }
1079
- setTimeout(execNext);
1080
- return getQueryStatus;
947
+ const resourcesCount = config.resources.length;
948
+ const startIndex = config.random ? Math.floor(Math.random() * resourcesCount) : config.index;
949
+ let resources;
950
+ if (config.random) {
951
+ let list = config.resources.slice(0);
952
+ resources = [];
953
+ while (list.length > 1) {
954
+ const nextIndex = Math.floor(Math.random() * list.length);
955
+ resources.push(list[nextIndex]);
956
+ list = list.slice(0, nextIndex).concat(list.slice(nextIndex + 1));
957
+ }
958
+ resources = resources.concat(list);
959
+ } else resources = config.resources.slice(startIndex).concat(config.resources.slice(0, startIndex));
960
+ const startTime = Date.now();
961
+ let status = "pending";
962
+ let queriesSent = 0;
963
+ let lastError;
964
+ let timer = null;
965
+ let queue = [];
966
+ let doneCallbacks = [];
967
+ if (typeof done === "function") doneCallbacks.push(done);
968
+ /**
969
+ * Reset timer
970
+ */
971
+ function resetTimer() {
972
+ if (timer) {
973
+ clearTimeout(timer);
974
+ timer = null;
975
+ }
976
+ }
977
+ /**
978
+ * Abort everything
979
+ */
980
+ function abort() {
981
+ if (status === "pending") status = "aborted";
982
+ resetTimer();
983
+ queue.forEach((item) => {
984
+ if (item.status === "pending") item.status = "aborted";
985
+ });
986
+ queue = [];
987
+ }
988
+ /**
989
+ * Add / replace callback to call when execution is complete.
990
+ * This can be used to abort pending query implementations when query is complete or aborted.
991
+ */
992
+ function subscribe(callback, overwrite) {
993
+ if (overwrite) doneCallbacks = [];
994
+ if (typeof callback === "function") doneCallbacks.push(callback);
995
+ }
996
+ /**
997
+ * Get query status
998
+ */
999
+ function getQueryStatus() {
1000
+ return {
1001
+ startTime,
1002
+ payload,
1003
+ status,
1004
+ queriesSent,
1005
+ queriesPending: queue.length,
1006
+ subscribe,
1007
+ abort
1008
+ };
1009
+ }
1010
+ /**
1011
+ * Fail query
1012
+ */
1013
+ function failQuery() {
1014
+ status = "failed";
1015
+ doneCallbacks.forEach((callback) => {
1016
+ callback(void 0, lastError);
1017
+ });
1018
+ }
1019
+ /**
1020
+ * Clear queue
1021
+ */
1022
+ function clearQueue() {
1023
+ queue.forEach((item) => {
1024
+ if (item.status === "pending") item.status = "aborted";
1025
+ });
1026
+ queue = [];
1027
+ }
1028
+ /**
1029
+ * Got response from module
1030
+ */
1031
+ function moduleResponse(item, response, data) {
1032
+ const isError = response !== "success";
1033
+ queue = queue.filter((queued) => queued !== item);
1034
+ switch (status) {
1035
+ case "pending": break;
1036
+ case "failed":
1037
+ if (isError || !config.dataAfterTimeout) return;
1038
+ break;
1039
+ default: return;
1040
+ }
1041
+ if (response === "abort") {
1042
+ lastError = data;
1043
+ failQuery();
1044
+ return;
1045
+ }
1046
+ if (isError) {
1047
+ lastError = data;
1048
+ if (!queue.length) if (!resources.length) failQuery();
1049
+ else execNext();
1050
+ return;
1051
+ }
1052
+ resetTimer();
1053
+ clearQueue();
1054
+ if (!config.random) {
1055
+ const index = config.resources.indexOf(item.resource);
1056
+ if (index !== -1 && index !== config.index) config.index = index;
1057
+ }
1058
+ status = "completed";
1059
+ doneCallbacks.forEach((callback) => {
1060
+ callback(data);
1061
+ });
1062
+ }
1063
+ /**
1064
+ * Execute next query
1065
+ */
1066
+ function execNext() {
1067
+ if (status !== "pending") return;
1068
+ resetTimer();
1069
+ const resource = resources.shift();
1070
+ if (resource === void 0) {
1071
+ if (queue.length) {
1072
+ timer = setTimeout(() => {
1073
+ resetTimer();
1074
+ if (status === "pending") {
1075
+ clearQueue();
1076
+ failQuery();
1077
+ }
1078
+ }, config.timeout);
1079
+ return;
1080
+ }
1081
+ failQuery();
1082
+ return;
1083
+ }
1084
+ const item = {
1085
+ status: "pending",
1086
+ resource,
1087
+ callback: (status, data) => {
1088
+ moduleResponse(item, status, data);
1089
+ }
1090
+ };
1091
+ queue.push(item);
1092
+ queriesSent++;
1093
+ timer = setTimeout(execNext, config.rotate);
1094
+ query(resource, payload, item.callback);
1095
+ }
1096
+ setTimeout(execNext);
1097
+ return getQueryStatus;
1081
1098
  }
1082
-
1083
- // src/index.ts
1099
+ /**
1100
+ * Redundancy instance
1101
+ */
1084
1102
  function initRedundancy(cfg) {
1085
- const config = {
1086
- ...defaultConfig,
1087
- ...cfg
1088
- };
1089
- let queries = [];
1090
- function cleanup() {
1091
- queries = queries.filter((item) => item().status === "pending");
1092
- }
1093
- function query(payload, queryCallback, doneCallback) {
1094
- const query2 = sendQuery(
1095
- config,
1096
- payload,
1097
- queryCallback,
1098
- (data, error) => {
1099
- cleanup();
1100
- if (doneCallback) {
1101
- doneCallback(data, error);
1102
- }
1103
- }
1104
- );
1105
- queries.push(query2);
1106
- return query2;
1107
- }
1108
- function find(callback) {
1109
- return queries.find((value) => {
1110
- return callback(value);
1111
- }) || null;
1112
- }
1113
- const instance = {
1114
- query,
1115
- find,
1116
- setIndex: (index) => {
1117
- config.index = index;
1118
- },
1119
- getIndex: () => config.index,
1120
- cleanup
1121
- };
1122
- return instance;
1103
+ const config = {
1104
+ ...defaultConfig,
1105
+ ...cfg
1106
+ };
1107
+ let queries = [];
1108
+ /**
1109
+ * Remove aborted and completed queries
1110
+ */
1111
+ function cleanup() {
1112
+ queries = queries.filter((item) => item().status === "pending");
1113
+ }
1114
+ /**
1115
+ * Send query
1116
+ */
1117
+ function query(payload, queryCallback, doneCallback) {
1118
+ const query = sendQuery(config, payload, queryCallback, (data, error) => {
1119
+ cleanup();
1120
+ if (doneCallback) doneCallback(data, error);
1121
+ });
1122
+ queries.push(query);
1123
+ return query;
1124
+ }
1125
+ /**
1126
+ * Find instance
1127
+ */
1128
+ function find(callback) {
1129
+ return queries.find((value) => {
1130
+ return callback(value);
1131
+ }) || null;
1132
+ }
1133
+ return {
1134
+ query,
1135
+ find,
1136
+ setIndex: (index) => {
1137
+ config.index = index;
1138
+ },
1139
+ getIndex: () => config.index,
1140
+ cleanup
1141
+ };
1123
1142
  }
1124
1143
 
1125
- function emptyCallback$1() {
1126
- }
1127
- const redundancyCache = /* @__PURE__ */ Object.create(null);
1144
+ function emptyCallback$1() {}
1145
+ const redundancyCache = Object.create(null);
1146
+ /**
1147
+ * Get Redundancy instance for provider
1148
+ */
1128
1149
  function getRedundancyCache(provider) {
1129
- if (!redundancyCache[provider]) {
1130
- const config = getAPIConfig(provider);
1131
- if (!config) {
1132
- return;
1133
- }
1134
- const redundancy = initRedundancy(config);
1135
- const cachedReundancy = {
1136
- config,
1137
- redundancy
1138
- };
1139
- redundancyCache[provider] = cachedReundancy;
1140
- }
1141
- return redundancyCache[provider];
1150
+ if (!redundancyCache[provider]) {
1151
+ const config = getAPIConfig(provider);
1152
+ if (!config) return;
1153
+ redundancyCache[provider] = {
1154
+ config,
1155
+ redundancy: initRedundancy(config)
1156
+ };
1157
+ }
1158
+ return redundancyCache[provider];
1142
1159
  }
1160
+ /**
1161
+ * Send API query
1162
+ */
1143
1163
  function sendAPIQuery(target, query, callback) {
1144
- let redundancy;
1145
- let send;
1146
- if (typeof target === "string") {
1147
- const api = getAPIModule(target);
1148
- if (!api) {
1149
- callback(void 0, 424);
1150
- return emptyCallback$1;
1151
- }
1152
- send = api.send;
1153
- const cached = getRedundancyCache(target);
1154
- if (cached) {
1155
- redundancy = cached.redundancy;
1156
- }
1157
- } else {
1158
- const config = createAPIConfig(target);
1159
- if (config) {
1160
- redundancy = initRedundancy(config);
1161
- const moduleKey = target.resources ? target.resources[0] : "";
1162
- const api = getAPIModule(moduleKey);
1163
- if (api) {
1164
- send = api.send;
1165
- }
1166
- }
1167
- }
1168
- if (!redundancy || !send) {
1169
- callback(void 0, 424);
1170
- return emptyCallback$1;
1171
- }
1172
- return redundancy.query(query, send, callback)().abort;
1164
+ let redundancy;
1165
+ let send;
1166
+ if (typeof target === "string") {
1167
+ const api = getAPIModule(target);
1168
+ if (!api) {
1169
+ callback(void 0, 424);
1170
+ return emptyCallback$1;
1171
+ }
1172
+ send = api.send;
1173
+ const cached = getRedundancyCache(target);
1174
+ if (cached) redundancy = cached.redundancy;
1175
+ } else {
1176
+ const config = createAPIConfig(target);
1177
+ if (config) {
1178
+ redundancy = initRedundancy(config);
1179
+ const api = getAPIModule(target.resources ? target.resources[0] : "");
1180
+ if (api) send = api.send;
1181
+ }
1182
+ }
1183
+ if (!redundancy || !send) {
1184
+ callback(void 0, 424);
1185
+ return emptyCallback$1;
1186
+ }
1187
+ return redundancy.query(query, send, callback)().abort;
1173
1188
  }
1174
1189
 
1175
- function emptyCallback() {
1176
- }
1190
+ function emptyCallback() {}
1191
+ /**
1192
+ * Function called when new icons have been loaded
1193
+ */
1177
1194
  function loadedNewIcons(storage) {
1178
- if (!storage.iconsLoaderFlag) {
1179
- storage.iconsLoaderFlag = true;
1180
- setTimeout(() => {
1181
- storage.iconsLoaderFlag = false;
1182
- updateCallbacks(storage);
1183
- });
1184
- }
1195
+ if (!storage.iconsLoaderFlag) {
1196
+ storage.iconsLoaderFlag = true;
1197
+ setTimeout(() => {
1198
+ storage.iconsLoaderFlag = false;
1199
+ updateCallbacks(storage);
1200
+ });
1201
+ }
1185
1202
  }
1203
+ /**
1204
+ * Check icon names for API
1205
+ */
1186
1206
  function checkIconNamesForAPI(icons) {
1187
- const valid = [];
1188
- const invalid = [];
1189
- icons.forEach((name) => {
1190
- (name.match(matchIconName) ? valid : invalid).push(name);
1191
- });
1192
- return {
1193
- valid,
1194
- invalid
1195
- };
1207
+ const valid = [];
1208
+ const invalid = [];
1209
+ icons.forEach((name) => {
1210
+ (name.match(matchIconName) ? valid : invalid).push(name);
1211
+ });
1212
+ return {
1213
+ valid,
1214
+ invalid
1215
+ };
1196
1216
  }
1217
+ /**
1218
+ * Parse loader response
1219
+ */
1197
1220
  function parseLoaderResponse(storage, icons, data) {
1198
- function checkMissing() {
1199
- const pending = storage.pendingIcons;
1200
- icons.forEach((name) => {
1201
- if (pending) {
1202
- pending.delete(name);
1203
- }
1204
- if (!storage.icons[name]) {
1205
- storage.missing.add(name);
1206
- }
1207
- });
1208
- }
1209
- if (data && typeof data === "object") {
1210
- try {
1211
- const parsed = addIconSet(storage, data);
1212
- if (!parsed.length) {
1213
- checkMissing();
1214
- return;
1215
- }
1216
- } catch (err) {
1217
- console.error(err);
1218
- }
1219
- }
1220
- checkMissing();
1221
- loadedNewIcons(storage);
1221
+ function checkMissing() {
1222
+ const pending = storage.pendingIcons;
1223
+ icons.forEach((name) => {
1224
+ if (pending) pending.delete(name);
1225
+ if (!storage.icons[name]) storage.missing.add(name);
1226
+ });
1227
+ }
1228
+ if (data && typeof data === "object") try {
1229
+ if (!addIconSet(storage, data).length) {
1230
+ checkMissing();
1231
+ return;
1232
+ }
1233
+ } catch (err) {
1234
+ console.error(err);
1235
+ }
1236
+ checkMissing();
1237
+ loadedNewIcons(storage);
1222
1238
  }
1239
+ /**
1240
+ * Handle response that can be async
1241
+ */
1223
1242
  function parsePossiblyAsyncResponse(response, callback) {
1224
- if (response instanceof Promise) {
1225
- response.then((data) => {
1226
- callback(data);
1227
- }).catch(() => {
1228
- callback(null);
1229
- });
1230
- } else {
1231
- callback(response);
1232
- }
1243
+ if (response instanceof Promise) response.then((data) => {
1244
+ callback(data);
1245
+ }).catch(() => {
1246
+ callback(null);
1247
+ });
1248
+ else callback(response);
1233
1249
  }
1250
+ /**
1251
+ * Load icons
1252
+ */
1234
1253
  function loadNewIcons(storage, icons) {
1235
- if (!storage.iconsToLoad) {
1236
- storage.iconsToLoad = icons;
1237
- } else {
1238
- storage.iconsToLoad = storage.iconsToLoad.concat(icons).sort();
1239
- }
1240
- if (!storage.iconsQueueFlag) {
1241
- storage.iconsQueueFlag = true;
1242
- setTimeout(() => {
1243
- storage.iconsQueueFlag = false;
1244
- const { provider, prefix } = storage;
1245
- const icons2 = storage.iconsToLoad;
1246
- delete storage.iconsToLoad;
1247
- if (!icons2 || !icons2.length) {
1248
- return;
1249
- }
1250
- const customIconLoader = storage.loadIcon;
1251
- if (storage.loadIcons && (icons2.length > 1 || !customIconLoader)) {
1252
- parsePossiblyAsyncResponse(
1253
- storage.loadIcons(icons2, prefix, provider),
1254
- (data) => {
1255
- parseLoaderResponse(storage, icons2, data);
1256
- }
1257
- );
1258
- return;
1259
- }
1260
- if (customIconLoader) {
1261
- icons2.forEach((name) => {
1262
- const response = customIconLoader(name, prefix, provider);
1263
- parsePossiblyAsyncResponse(response, (data) => {
1264
- const iconSet = data ? {
1265
- prefix,
1266
- icons: {
1267
- [name]: data
1268
- }
1269
- } : null;
1270
- parseLoaderResponse(storage, [name], iconSet);
1271
- });
1272
- });
1273
- return;
1274
- }
1275
- const { valid, invalid } = checkIconNamesForAPI(icons2);
1276
- if (invalid.length) {
1277
- parseLoaderResponse(storage, invalid, null);
1278
- }
1279
- if (!valid.length) {
1280
- return;
1281
- }
1282
- const api = prefix.match(matchIconName) ? getAPIModule(provider) : null;
1283
- if (!api) {
1284
- parseLoaderResponse(storage, valid, null);
1285
- return;
1286
- }
1287
- const params = api.prepare(provider, prefix, valid);
1288
- params.forEach((item) => {
1289
- sendAPIQuery(provider, item, (data) => {
1290
- parseLoaderResponse(storage, item.icons, data);
1291
- });
1292
- });
1293
- });
1294
- }
1254
+ if (!storage.iconsToLoad) storage.iconsToLoad = icons;
1255
+ else storage.iconsToLoad = storage.iconsToLoad.concat(icons).sort();
1256
+ if (!storage.iconsQueueFlag) {
1257
+ storage.iconsQueueFlag = true;
1258
+ setTimeout(() => {
1259
+ storage.iconsQueueFlag = false;
1260
+ const { provider, prefix } = storage;
1261
+ const icons = storage.iconsToLoad;
1262
+ delete storage.iconsToLoad;
1263
+ if (!icons || !icons.length) return;
1264
+ const customIconLoader = storage.loadIcon;
1265
+ if (storage.loadIcons && (icons.length > 1 || !customIconLoader)) {
1266
+ parsePossiblyAsyncResponse(storage.loadIcons(icons, prefix, provider), (data) => {
1267
+ parseLoaderResponse(storage, icons, data);
1268
+ });
1269
+ return;
1270
+ }
1271
+ if (customIconLoader) {
1272
+ icons.forEach((name) => {
1273
+ parsePossiblyAsyncResponse(customIconLoader(name, prefix, provider), (data) => {
1274
+ parseLoaderResponse(storage, [name], data ? {
1275
+ prefix,
1276
+ icons: { [name]: data }
1277
+ } : null);
1278
+ });
1279
+ });
1280
+ return;
1281
+ }
1282
+ const { valid, invalid } = checkIconNamesForAPI(icons);
1283
+ if (invalid.length) parseLoaderResponse(storage, invalid, null);
1284
+ if (!valid.length) return;
1285
+ const api = prefix.match(matchIconName) ? getAPIModule(provider) : null;
1286
+ if (!api) {
1287
+ parseLoaderResponse(storage, valid, null);
1288
+ return;
1289
+ }
1290
+ api.prepare(provider, prefix, valid).forEach((item) => {
1291
+ sendAPIQuery(provider, item, (data) => {
1292
+ parseLoaderResponse(storage, item.icons, data);
1293
+ });
1294
+ });
1295
+ });
1296
+ }
1295
1297
  }
1298
+ /**
1299
+ * Load icons
1300
+ */
1296
1301
  const loadIcons = (icons, callback) => {
1297
- const cleanedIcons = listToIcons(icons, true, allowSimpleNames());
1298
- const sortedIcons = sortIcons(cleanedIcons);
1299
- if (!sortedIcons.pending.length) {
1300
- let callCallback = true;
1301
- if (callback) {
1302
- setTimeout(() => {
1303
- if (callCallback) {
1304
- callback(
1305
- sortedIcons.loaded,
1306
- sortedIcons.missing,
1307
- sortedIcons.pending,
1308
- emptyCallback
1309
- );
1310
- }
1311
- });
1312
- }
1313
- return () => {
1314
- callCallback = false;
1315
- };
1316
- }
1317
- const newIcons = /* @__PURE__ */ Object.create(null);
1318
- const sources = [];
1319
- let lastProvider, lastPrefix;
1320
- sortedIcons.pending.forEach((icon) => {
1321
- const { provider, prefix } = icon;
1322
- if (prefix === lastPrefix && provider === lastProvider) {
1323
- return;
1324
- }
1325
- lastProvider = provider;
1326
- lastPrefix = prefix;
1327
- sources.push(getStorage(provider, prefix));
1328
- const providerNewIcons = newIcons[provider] || (newIcons[provider] = /* @__PURE__ */ Object.create(null));
1329
- if (!providerNewIcons[prefix]) {
1330
- providerNewIcons[prefix] = [];
1331
- }
1332
- });
1333
- sortedIcons.pending.forEach((icon) => {
1334
- const { provider, prefix, name } = icon;
1335
- const storage = getStorage(provider, prefix);
1336
- const pendingQueue = storage.pendingIcons || (storage.pendingIcons = /* @__PURE__ */ new Set());
1337
- if (!pendingQueue.has(name)) {
1338
- pendingQueue.add(name);
1339
- newIcons[provider][prefix].push(name);
1340
- }
1341
- });
1342
- sources.forEach((storage) => {
1343
- const list = newIcons[storage.provider][storage.prefix];
1344
- if (list.length) {
1345
- loadNewIcons(storage, list);
1346
- }
1347
- });
1348
- return callback ? storeCallback(callback, sortedIcons, sources) : emptyCallback;
1302
+ const sortedIcons = sortIcons(listToIcons(icons, true, allowSimpleNames()));
1303
+ if (!sortedIcons.pending.length) {
1304
+ let callCallback = true;
1305
+ if (callback) setTimeout(() => {
1306
+ if (callCallback) callback(sortedIcons.loaded, sortedIcons.missing, sortedIcons.pending, emptyCallback);
1307
+ });
1308
+ return () => {
1309
+ callCallback = false;
1310
+ };
1311
+ }
1312
+ const newIcons = Object.create(null);
1313
+ const sources = [];
1314
+ let lastProvider, lastPrefix;
1315
+ sortedIcons.pending.forEach((icon) => {
1316
+ const { provider, prefix } = icon;
1317
+ if (prefix === lastPrefix && provider === lastProvider) return;
1318
+ lastProvider = provider;
1319
+ lastPrefix = prefix;
1320
+ sources.push(getStorage(provider, prefix));
1321
+ const providerNewIcons = newIcons[provider] || (newIcons[provider] = Object.create(null));
1322
+ if (!providerNewIcons[prefix]) providerNewIcons[prefix] = [];
1323
+ });
1324
+ sortedIcons.pending.forEach((icon) => {
1325
+ const { provider, prefix, name } = icon;
1326
+ const storage = getStorage(provider, prefix);
1327
+ const pendingQueue = storage.pendingIcons || (storage.pendingIcons = /* @__PURE__ */ new Set());
1328
+ if (!pendingQueue.has(name)) {
1329
+ pendingQueue.add(name);
1330
+ newIcons[provider][prefix].push(name);
1331
+ }
1332
+ });
1333
+ sources.forEach((storage) => {
1334
+ const list = newIcons[storage.provider][storage.prefix];
1335
+ if (list.length) loadNewIcons(storage, list);
1336
+ });
1337
+ return callback ? storeCallback(callback, sortedIcons, sources) : emptyCallback;
1349
1338
  };
1339
+ /**
1340
+ * Load one icon using Promise
1341
+ */
1350
1342
  const loadIcon = (icon) => {
1351
- return new Promise((fulfill, reject) => {
1352
- const iconObj = typeof icon === "string" ? stringToIcon(icon, true) : icon;
1353
- if (!iconObj) {
1354
- reject(icon);
1355
- return;
1356
- }
1357
- loadIcons([iconObj || icon], (loaded) => {
1358
- if (loaded.length && iconObj) {
1359
- const data = getIconData(iconObj);
1360
- if (data) {
1361
- fulfill({
1362
- ...defaultIconProps,
1363
- ...data
1364
- });
1365
- return;
1366
- }
1367
- }
1368
- reject(icon);
1369
- });
1370
- });
1343
+ return new Promise((fulfill, reject) => {
1344
+ const iconObj = typeof icon === "string" ? stringToIcon(icon, true) : icon;
1345
+ if (!iconObj) {
1346
+ reject(icon);
1347
+ return;
1348
+ }
1349
+ loadIcons([iconObj || icon], (loaded) => {
1350
+ if (loaded.length && iconObj) {
1351
+ const data = getIconData(iconObj);
1352
+ if (data) {
1353
+ fulfill({
1354
+ ...defaultIconProps,
1355
+ ...data
1356
+ });
1357
+ return;
1358
+ }
1359
+ }
1360
+ reject(icon);
1361
+ });
1362
+ });
1371
1363
  };
1372
1364
 
1365
+ /**
1366
+ * Set custom loader for multiple icons
1367
+ */
1373
1368
  function setCustomIconsLoader(loader, prefix, provider) {
1374
- getStorage(provider || "", prefix).loadIcons = loader;
1369
+ getStorage(provider || "", prefix).loadIcons = loader;
1375
1370
  }
1371
+ /**
1372
+ * Set custom loader for one icon
1373
+ */
1376
1374
  function setCustomIconLoader(loader, prefix, provider) {
1377
- getStorage(provider || "", prefix).loadIcon = loader;
1375
+ getStorage(provider || "", prefix).loadIcon = loader;
1378
1376
  }
1379
1377
 
1378
+ /**
1379
+ * Convert IconifyIconCustomisations to FullIconCustomisations, checking value types
1380
+ */
1380
1381
  function mergeCustomisations(defaults, item) {
1381
- const result = {
1382
- ...defaults
1383
- };
1384
- for (const key in item) {
1385
- const value = item[key];
1386
- const valueType = typeof value;
1387
- if (key in defaultIconSizeCustomisations) {
1388
- if (value === null || value && (valueType === "string" || valueType === "number")) {
1389
- result[key] = value;
1390
- }
1391
- } else if (valueType === typeof result[key]) {
1392
- result[key] = key === "rotate" ? value % 4 : value;
1393
- }
1394
- }
1395
- return result;
1382
+ const result = { ...defaults };
1383
+ for (const key in item) {
1384
+ const value = item[key];
1385
+ const valueType = typeof value;
1386
+ if (key in defaultIconSizeCustomisations) {
1387
+ if (value === null || value && (valueType === "string" || valueType === "number")) result[key] = value;
1388
+ } else if (valueType === typeof result[key]) result[key] = key === "rotate" ? value % 4 : value;
1389
+ }
1390
+ return result;
1396
1391
  }
1397
1392
 
1398
1393
  const separator = /[\s,]+/;
1394
+ /**
1395
+ * Apply "flip" string to icon customisations
1396
+ */
1399
1397
  function flipFromString(custom, flip) {
1400
- flip.split(separator).forEach((str) => {
1401
- const value = str.trim();
1402
- switch (value) {
1403
- case "horizontal":
1404
- custom.hFlip = true;
1405
- break;
1406
- case "vertical":
1407
- custom.vFlip = true;
1408
- break;
1409
- }
1410
- });
1398
+ flip.split(separator).forEach((str) => {
1399
+ switch (str.trim()) {
1400
+ case "horizontal":
1401
+ custom.hFlip = true;
1402
+ break;
1403
+ case "vertical":
1404
+ custom.vFlip = true;
1405
+ break;
1406
+ }
1407
+ });
1411
1408
  }
1412
1409
 
1410
+ /**
1411
+ * Get rotation value
1412
+ */
1413
1413
  function rotateFromString(value, defaultValue = 0) {
1414
- const units = value.replace(/^-?[0-9.]*/, "");
1415
- function cleanup(value2) {
1416
- while (value2 < 0) {
1417
- value2 += 4;
1418
- }
1419
- return value2 % 4;
1420
- }
1421
- if (units === "") {
1422
- const num = parseInt(value);
1423
- return isNaN(num) ? 0 : cleanup(num);
1424
- } else if (units !== value) {
1425
- let split = 0;
1426
- switch (units) {
1427
- case "%":
1428
- split = 25;
1429
- break;
1430
- case "deg":
1431
- split = 90;
1432
- }
1433
- if (split) {
1434
- let num = parseFloat(value.slice(0, value.length - units.length));
1435
- if (isNaN(num)) {
1436
- return 0;
1437
- }
1438
- num = num / split;
1439
- return num % 1 === 0 ? cleanup(num) : 0;
1440
- }
1441
- }
1442
- return defaultValue;
1414
+ const units = value.replace(/^-?[0-9.]*/, "");
1415
+ function cleanup(value) {
1416
+ while (value < 0) value += 4;
1417
+ return value % 4;
1418
+ }
1419
+ if (units === "") {
1420
+ const num = parseInt(value);
1421
+ return isNaN(num) ? 0 : cleanup(num);
1422
+ } else if (units !== value) {
1423
+ let split = 0;
1424
+ switch (units) {
1425
+ case "%":
1426
+ split = 25;
1427
+ break;
1428
+ case "deg": split = 90;
1429
+ }
1430
+ if (split) {
1431
+ let num = parseFloat(value.slice(0, value.length - units.length));
1432
+ if (isNaN(num)) return 0;
1433
+ num = num / split;
1434
+ return num % 1 === 0 ? cleanup(num) : 0;
1435
+ }
1436
+ }
1437
+ return defaultValue;
1443
1438
  }
1444
1439
 
1440
+ /**
1441
+ * Generate <svg>
1442
+ */
1445
1443
  function iconToHTML(body, attributes) {
1446
- let renderAttribsHTML = body.indexOf("xlink:") === -1 ? "" : ' xmlns:xlink="http://www.w3.org/1999/xlink"';
1447
- for (const attr in attributes) {
1448
- renderAttribsHTML += " " + attr + '="' + attributes[attr] + '"';
1449
- }
1450
- return '<svg xmlns="http://www.w3.org/2000/svg"' + renderAttribsHTML + ">" + body + "</svg>";
1444
+ let renderAttribsHTML = body.indexOf("xlink:") === -1 ? "" : " xmlns:xlink=\"http://www.w3.org/1999/xlink\"";
1445
+ for (const attr in attributes) renderAttribsHTML += " " + attr + "=\"" + attributes[attr] + "\"";
1446
+ return "<svg xmlns=\"http://www.w3.org/2000/svg\"" + renderAttribsHTML + ">" + body + "</svg>";
1451
1447
  }
1452
1448
 
1449
+ /**
1450
+ * Encode SVG for use in url()
1451
+ *
1452
+ * Short alternative to encodeURIComponent() that encodes only stuff used in SVG, generating
1453
+ * smaller code.
1454
+ */
1453
1455
  function encodeSVGforURL(svg) {
1454
- return svg.replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ");
1456
+ return svg.replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ");
1455
1457
  }
1458
+ /**
1459
+ * Generate data: URL from SVG
1460
+ */
1456
1461
  function svgToData(svg) {
1457
- return "data:image/svg+xml," + encodeSVGforURL(svg);
1462
+ return "data:image/svg+xml," + encodeSVGforURL(svg);
1458
1463
  }
1464
+ /**
1465
+ * Generate url() from SVG
1466
+ */
1459
1467
  function svgToURL(svg) {
1460
- return 'url("' + svgToData(svg) + '")';
1468
+ return "url(\"" + svgToData(svg) + "\")";
1461
1469
  }
1462
1470
 
1463
1471
  const defaultExtendedIconCustomisations = {
@@ -1555,6 +1563,7 @@ props) => {
1555
1563
  case 'onLoad':
1556
1564
  case 'mode':
1557
1565
  case 'ssr':
1566
+ case 'customise':
1558
1567
  break;
1559
1568
  // Boolean attributes
1560
1569
  case 'inline':
@@ -1620,15 +1629,8 @@ props) => {
1620
1629
  };
1621
1630
  // Add icon stuff
1622
1631
  Object.assign(componentProps, renderAttribs);
1623
- // Counter for ids based on "id" property to render icons consistently on server and client
1624
- let localCounter = 0;
1625
- let id = props.id;
1626
- if (typeof id === 'string') {
1627
- // Convert '-' to '_' to avoid errors in animations
1628
- id = id.replace(/-/g, '_');
1629
- }
1630
1632
  // Add innerHTML and style to props
1631
- componentProps['innerHTML'] = replaceIDs(item.body, id ? () => id + 'ID' + localCounter++ : 'iconifyVue');
1633
+ componentProps['innerHTML'] = replaceIDs(item.body);
1632
1634
  // Render icon
1633
1635
  return h('svg', componentProps);
1634
1636
  }
@@ -1655,22 +1657,6 @@ props) => {
1655
1657
  return h('span', componentProps);
1656
1658
  };
1657
1659
 
1658
- /**
1659
- * Enable cache
1660
- *
1661
- * @deprecated No longer used
1662
- */
1663
- function enableCache(storage) {
1664
- //
1665
- }
1666
- /**
1667
- * Disable cache
1668
- *
1669
- * @deprecated No longer used
1670
- */
1671
- function disableCache(storage) {
1672
- //
1673
- }
1674
1660
  /**
1675
1661
  * Initialise stuff
1676
1662
  */
@@ -1740,115 +1726,118 @@ const emptyIcon = {
1740
1726
  ...defaultIconProps,
1741
1727
  body: '',
1742
1728
  };
1743
- const Icon = defineComponent({
1744
- // Do not inherit other attributes: it is handled by render()
1745
- inheritAttrs: false,
1746
- // Set initial data
1747
- data() {
1748
- return {
1749
- // Current icon name
1750
- _name: '',
1751
- // Loading
1752
- _loadingIcon: null,
1753
- // Mounted status
1754
- iconMounted: false,
1755
- // Callback counter to trigger re-render
1756
- counter: 0,
1757
- };
1758
- },
1759
- mounted() {
1760
- // Mark as mounted
1761
- this.iconMounted = true;
1762
- },
1763
- unmounted() {
1764
- this.abortLoading();
1765
- },
1766
- methods: {
1767
- abortLoading() {
1768
- if (this._loadingIcon) {
1769
- this._loadingIcon.abort();
1770
- this._loadingIcon = null;
1771
- }
1772
- },
1773
- // Get data for icon to render or null
1774
- getIcon(icon, onload, customise) {
1775
- // Icon is an object
1776
- if (typeof icon === 'object' &&
1777
- icon !== null &&
1778
- typeof icon.body === 'string') {
1779
- // Stop loading
1780
- this._name = '';
1781
- this.abortLoading();
1782
- return {
1783
- data: icon,
1784
- };
1785
- }
1786
- // Invalid icon?
1787
- let iconName;
1788
- if (typeof icon !== 'string' ||
1789
- (iconName = stringToIcon(icon, false, true)) === null) {
1790
- this.abortLoading();
1791
- return null;
1792
- }
1793
- // Load icon
1794
- let data = getIconData(iconName);
1795
- if (!data) {
1796
- // Icon data is not available
1797
- if (!this._loadingIcon || this._loadingIcon.name !== icon) {
1798
- // New icon to load
1799
- this.abortLoading();
1800
- this._name = '';
1801
- if (data !== null) {
1802
- // Icon was not loaded
1803
- this._loadingIcon = {
1804
- name: icon,
1805
- abort: loadIcons([iconName], () => {
1806
- this.counter++;
1807
- }),
1808
- };
1809
- }
1810
- }
1811
- return null;
1812
- }
1813
- // Icon data is available
1814
- this.abortLoading();
1815
- if (this._name !== icon) {
1816
- this._name = icon;
1817
- if (onload) {
1818
- onload(icon);
1729
+ /**
1730
+ * Component
1731
+ */
1732
+ const Icon = defineComponent((props, { emit }) => {
1733
+ const loader = ref(null);
1734
+ function abortLoading() {
1735
+ if (loader.value) {
1736
+ loader.value.abort?.();
1737
+ loader.value = null;
1738
+ }
1739
+ }
1740
+ // Render state
1741
+ const rendering = ref(!!props.ssr);
1742
+ const lastRenderedIconName = ref('');
1743
+ const iconData = shallowRef(null);
1744
+ // Update icon data
1745
+ function getIcon() {
1746
+ const icon = props.icon;
1747
+ // Icon is an object
1748
+ if (typeof icon === 'object' &&
1749
+ icon !== null &&
1750
+ typeof icon.body === 'string') {
1751
+ lastRenderedIconName.value = '';
1752
+ return {
1753
+ data: icon,
1754
+ };
1755
+ }
1756
+ // Check for valid icon name
1757
+ let iconName;
1758
+ if (typeof icon !== 'string' ||
1759
+ (iconName = stringToIcon(icon, false, true)) === null) {
1760
+ return null;
1761
+ }
1762
+ // Load icon
1763
+ let data = getIconData(iconName);
1764
+ if (!data) {
1765
+ // Icon data is not available
1766
+ const oldState = loader.value;
1767
+ if (!oldState || oldState.name !== icon) {
1768
+ // Icon name does not match old loader state
1769
+ if (data === null) {
1770
+ // Failed to load
1771
+ loader.value = {
1772
+ name: icon,
1773
+ };
1819
1774
  }
1820
- }
1821
- // Customise icon
1822
- if (customise) {
1823
- // Clone data and customise it
1824
- data = Object.assign({}, data);
1825
- const customised = customise(data.body, iconName.name, iconName.prefix, iconName.provider);
1826
- if (typeof customised === 'string') {
1827
- data.body = customised;
1775
+ else {
1776
+ loader.value = {
1777
+ name: icon,
1778
+ abort: loadIcons([iconName], updateIconData),
1779
+ };
1828
1780
  }
1829
1781
  }
1830
- // Add classes
1831
- const classes = ['iconify'];
1832
- if (iconName.prefix !== '') {
1833
- classes.push('iconify--' + iconName.prefix);
1834
- }
1835
- if (iconName.provider !== '') {
1836
- classes.push('iconify--' + iconName.provider);
1782
+ return null;
1783
+ }
1784
+ // Icon data is available
1785
+ abortLoading();
1786
+ if (lastRenderedIconName.value !== icon) {
1787
+ lastRenderedIconName.value = icon;
1788
+ // Emit on next tick because render will be called on next tick
1789
+ nextTick(() => {
1790
+ emit('load', icon);
1791
+ });
1792
+ }
1793
+ // Customise icon
1794
+ const customise = props.customise;
1795
+ if (customise) {
1796
+ // Clone data and customise it
1797
+ data = Object.assign({}, data);
1798
+ const customised = customise(data.body, iconName.name, iconName.prefix, iconName.provider);
1799
+ if (typeof customised === 'string') {
1800
+ data.body = customised;
1837
1801
  }
1838
- return { data, classes };
1839
- },
1840
- },
1841
- // Render icon
1842
- render() {
1843
- // Re-render when counter changes
1844
- this.counter;
1845
- const props = this.$attrs;
1802
+ }
1803
+ // Add classes
1804
+ const classes = ['iconify'];
1805
+ if (iconName.prefix !== '') {
1806
+ classes.push('iconify--' + iconName.prefix);
1807
+ }
1808
+ if (iconName.provider !== '') {
1809
+ classes.push('iconify--' + iconName.provider);
1810
+ }
1811
+ return { data, classes };
1812
+ }
1813
+ function updateIconData() {
1814
+ const icon = getIcon();
1815
+ if (!icon) {
1816
+ iconData.value = null;
1817
+ }
1818
+ else if (icon.data !== iconData.value?.data) {
1819
+ iconData.value = icon;
1820
+ }
1821
+ }
1822
+ // Set icon data
1823
+ if (rendering.value) {
1824
+ updateIconData();
1825
+ }
1826
+ else {
1827
+ onMounted(() => {
1828
+ rendering.value = true;
1829
+ updateIconData();
1830
+ });
1831
+ }
1832
+ watch(() => props.icon, updateIconData);
1833
+ // Abort loading on unmount
1834
+ onUnmounted(abortLoading);
1835
+ // Render function
1836
+ return () => {
1846
1837
  // Get icon data
1847
- const icon = this.iconMounted || props.ssr
1848
- ? this.getIcon(props.icon, props.onLoad, props.customise)
1849
- : null;
1850
- // Validate icon object
1838
+ const icon = iconData.value;
1851
1839
  if (!icon) {
1840
+ // Icon is not available
1852
1841
  return render(emptyIcon, props);
1853
1842
  }
1854
1843
  // Add classes
@@ -1856,9 +1845,7 @@ const Icon = defineComponent({
1856
1845
  if (icon.classes) {
1857
1846
  newProps = {
1858
1847
  ...props,
1859
- class: (typeof props['class'] === 'string'
1860
- ? props['class'] + ' '
1861
- : '') + icon.classes.join(' '),
1848
+ class: icon.classes.join(' '),
1862
1849
  };
1863
1850
  }
1864
1851
  // Render icon
@@ -1866,7 +1853,33 @@ const Icon = defineComponent({
1866
1853
  ...defaultIconProps,
1867
1854
  ...icon.data,
1868
1855
  }, newProps);
1869
- },
1856
+ };
1857
+ }, {
1858
+ props: [
1859
+ // Icon and render mode
1860
+ 'icon',
1861
+ 'mode',
1862
+ 'ssr',
1863
+ // Layout and style
1864
+ 'width',
1865
+ 'height',
1866
+ 'style',
1867
+ 'color',
1868
+ 'inline',
1869
+ // Transformations
1870
+ 'rotate',
1871
+ 'hFlip',
1872
+ 'horizontalFlip',
1873
+ 'vFlip',
1874
+ 'verticalFlip',
1875
+ 'flip',
1876
+ // Misc
1877
+ 'id',
1878
+ 'ariaHidden',
1879
+ 'customise',
1880
+ 'title',
1881
+ ],
1882
+ emits: ['load'],
1870
1883
  });
1871
1884
  /**
1872
1885
  * Internal API
@@ -1880,4 +1893,4 @@ const _api = {
1880
1893
  listAPIProviders,
1881
1894
  };
1882
1895
 
1883
- export { Icon, _api, addAPIProvider, addCollection, addIcon, iconToSVG as buildIcon, calculateSize, disableCache, enableCache, getIcon, iconLoaded as iconExists, iconLoaded, listIcons, loadIcon, loadIcons, replaceIDs, setCustomIconLoader, setCustomIconsLoader };
1896
+ export { Icon, _api, addAPIProvider, addCollection, addIcon, iconToSVG as buildIcon, calculateSize, clearIDCache, getIcon, iconLoaded, listIcons, loadIcon, loadIcons, replaceIDs, setCustomIconLoader, setCustomIconsLoader };