@vibe/icons 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (266) hide show
  1. package/.eslintrc.json +23 -0
  2. package/README.md +31 -0
  3. package/package.json +68 -0
  4. package/plop/icon/icon-metadata.txt +7 -0
  5. package/plop/icon/index.js +59 -0
  6. package/plopfile.js +5 -0
  7. package/rollup.config.js +19 -0
  8. package/scripts/__tests__/__snapshots__/validate-icons-colors.test.ts.snap +7 -0
  9. package/scripts/__tests__/validate-icons-colors.test.ts +129 -0
  10. package/scripts/generate-meta.js +20 -0
  11. package/scripts/generate-svg-index.js +18 -0
  12. package/scripts/metadata-util.js +28 -0
  13. package/scripts/utils.js +35 -0
  14. package/scripts/validate-icons-colors.js +25 -0
  15. package/scripts/validate-meta.js +10 -0
  16. package/src/iconsMetaData.ts +1838 -0
  17. package/src/svg/API.svg +3 -0
  18. package/src/svg/Academy.svg +3 -0
  19. package/src/svg/Activity.svg +3 -0
  20. package/src/svg/Add.svg +5 -0
  21. package/src/svg/AddNewDoc.svg +13 -0
  22. package/src/svg/AddSmall.svg +4 -0
  23. package/src/svg/AddToTeam.svg +6 -0
  24. package/src/svg/AddUpdate.svg +4 -0
  25. package/src/svg/Alert.svg +3 -0
  26. package/src/svg/Announcement.svg +3 -0
  27. package/src/svg/Apps.svg +3 -0
  28. package/src/svg/Archive.svg +3 -0
  29. package/src/svg/Attach.svg +3 -0
  30. package/src/svg/Baseline.svg +4 -0
  31. package/src/svg/Basic.svg +5 -0
  32. package/src/svg/Battery.svg +3 -0
  33. package/src/svg/BlockQuote.svg +8 -0
  34. package/src/svg/Board.svg +3 -0
  35. package/src/svg/BoardPrivate.svg +5 -0
  36. package/src/svg/BoardShareable.svg +5 -0
  37. package/src/svg/BoardTemplate.svg +5 -0
  38. package/src/svg/Bold.svg +11 -0
  39. package/src/svg/Bolt.svg +3 -0
  40. package/src/svg/Bookmark.svg +3 -0
  41. package/src/svg/Broadcast.svg +3 -0
  42. package/src/svg/Broom.svg +5 -0
  43. package/src/svg/Bug.svg +3 -0
  44. package/src/svg/Bullet.svg +3 -0
  45. package/src/svg/Bullets.svg +15 -0
  46. package/src/svg/Bulllet.svg +3 -0
  47. package/src/svg/Calendar.svg +3 -0
  48. package/src/svg/Chart.svg +3 -0
  49. package/src/svg/Check.svg +4 -0
  50. package/src/svg/CheckList.svg +7 -0
  51. package/src/svg/Checkbox.svg +6 -0
  52. package/src/svg/Clear.svg +3 -0
  53. package/src/svg/Close.svg +3 -0
  54. package/src/svg/CloseRound.svg +3 -0
  55. package/src/svg/CloseSmall.svg +4 -0
  56. package/src/svg/Code.svg +4 -0
  57. package/src/svg/Collapse.svg +5 -0
  58. package/src/svg/CollapseRound.svg +5 -0
  59. package/src/svg/Column.svg +3 -0
  60. package/src/svg/Comment.svg +3 -0
  61. package/src/svg/Completed.svg +3 -0
  62. package/src/svg/Connect.svg +4 -0
  63. package/src/svg/ConnectedDoc.svg +11 -0
  64. package/src/svg/ContentDirectory.svg +3 -0
  65. package/src/svg/ConvertToItem.svg +3 -0
  66. package/src/svg/ConvertToSubitem.svg +3 -0
  67. package/src/svg/Counter.svg +12 -0
  68. package/src/svg/Country.svg +3 -0
  69. package/src/svg/CreditCard.svg +3 -0
  70. package/src/svg/Custom.svg +5 -0
  71. package/src/svg/Cut.svg +6 -0
  72. package/src/svg/Dashboard.svg +3 -0
  73. package/src/svg/DashboardPrivate.svg +5 -0
  74. package/src/svg/Deactivate.svg +3 -0
  75. package/src/svg/Delete.svg +3 -0
  76. package/src/svg/Dependency.svg +3 -0
  77. package/src/svg/Description.svg +6 -0
  78. package/src/svg/DisabledUser.svg +11 -0
  79. package/src/svg/Divider.svg +3 -0
  80. package/src/svg/Doc.svg +5 -0
  81. package/src/svg/DocPrivate.svg +6 -0
  82. package/src/svg/DocShareable.svg +3 -0
  83. package/src/svg/DocTemplate.svg +3 -0
  84. package/src/svg/DoubleCheck.svg +3 -0
  85. package/src/svg/Download.svg +3 -0
  86. package/src/svg/Drag.svg +11 -0
  87. package/src/svg/Dropdown.svg +5 -0
  88. package/src/svg/DropdownChevronDown.svg +4 -0
  89. package/src/svg/DropdownChevronLeft.svg +4 -0
  90. package/src/svg/DropdownChevronRight.svg +4 -0
  91. package/src/svg/DropdownChevronUp.svg +4 -0
  92. package/src/svg/DueDate.svg +3 -0
  93. package/src/svg/Duplicate.svg +3 -0
  94. package/src/svg/Edit.svg +3 -0
  95. package/src/svg/Education.svg +3 -0
  96. package/src/svg/Email.svg +3 -0
  97. package/src/svg/Embed.svg +3 -0
  98. package/src/svg/Emoji.svg +6 -0
  99. package/src/svg/Enter.svg +3 -0
  100. package/src/svg/Erase.svg +3 -0
  101. package/src/svg/Event.svg +4 -0
  102. package/src/svg/Expand.svg +3 -0
  103. package/src/svg/ExternalPage.svg +3 -0
  104. package/src/svg/Favorite.svg +3 -0
  105. package/src/svg/Feedback.svg +3 -0
  106. package/src/svg/File.svg +4 -0
  107. package/src/svg/Filter.svg +5 -0
  108. package/src/svg/Folder.svg +5 -0
  109. package/src/svg/Form.svg +6 -0
  110. package/src/svg/Formula.svg +4 -0
  111. package/src/svg/Forum.svg +3 -0
  112. package/src/svg/Fullscreen.svg +3 -0
  113. package/src/svg/FullscreenClose.svg +3 -0
  114. package/src/svg/Gallery.svg +6 -0
  115. package/src/svg/Gantt.svg +5 -0
  116. package/src/svg/Gif.svg +5 -0
  117. package/src/svg/Globe.svg +5 -0
  118. package/src/svg/Graph.svg +3 -0
  119. package/src/svg/Group.svg +3 -0
  120. package/src/svg/Guest.svg +3 -0
  121. package/src/svg/Health.svg +3 -0
  122. package/src/svg/Heart.svg +3 -0
  123. package/src/svg/Help.svg +5 -0
  124. package/src/svg/Hide.svg +3 -0
  125. package/src/svg/Highlight.svg +4 -0
  126. package/src/svg/HighlightColorBucket.svg +3 -0
  127. package/src/svg/Home.svg +3 -0
  128. package/src/svg/IPRestrictions.svg +3 -0
  129. package/src/svg/Idea.svg +3 -0
  130. package/src/svg/Image.svg +5 -0
  131. package/src/svg/Inbox.svg +4 -0
  132. package/src/svg/Info.svg +3 -0
  133. package/src/svg/Integrations.svg +3 -0
  134. package/src/svg/Invite.svg +11 -0
  135. package/src/svg/Italic.svg +9 -0
  136. package/src/svg/Item.svg +3 -0
  137. package/src/svg/ItemDefaultValues.svg +3 -0
  138. package/src/svg/ItemHeightDouble.svg +3 -0
  139. package/src/svg/ItemHeightSingle.svg +3 -0
  140. package/src/svg/ItemHeightTriple.svg +8 -0
  141. package/src/svg/Keyboard.svg +3 -0
  142. package/src/svg/Labs.svg +3 -0
  143. package/src/svg/Launch.svg +10 -0
  144. package/src/svg/Layout.svg +3 -0
  145. package/src/svg/LearnMore.svg +5 -0
  146. package/src/svg/Lines.svg +5 -0
  147. package/src/svg/Link.svg +3 -0
  148. package/src/svg/Location.svg +3 -0
  149. package/src/svg/Locked.svg +3 -0
  150. package/src/svg/LogIn.svg +8 -0
  151. package/src/svg/LogOut.svg +8 -0
  152. package/src/svg/LongText.svg +3 -0
  153. package/src/svg/Mention.svg +4 -0
  154. package/src/svg/Menu.svg +6 -0
  155. package/src/svg/Microphone.svg +3 -0
  156. package/src/svg/Minimize.svg +4 -0
  157. package/src/svg/Mirror.svg +4 -0
  158. package/src/svg/Mobile.svg +3 -0
  159. package/src/svg/MondayDoc.svg +3 -0
  160. package/src/svg/MondayLogoOutline.svg +3 -0
  161. package/src/svg/Moon.svg +3 -0
  162. package/src/svg/MoreActions.svg +3 -0
  163. package/src/svg/MoreBelow.svg +5 -0
  164. package/src/svg/MoreBelowFilled.svg +3 -0
  165. package/src/svg/MoveArrowDown.svg +4 -0
  166. package/src/svg/MoveArrowLeft.svg +4 -0
  167. package/src/svg/MoveArrowLeftDouble.svg +10 -0
  168. package/src/svg/MoveArrowRight.svg +4 -0
  169. package/src/svg/MoveArrowUp.svg +4 -0
  170. package/src/svg/Mute.svg +4 -0
  171. package/src/svg/MyWeek.svg +5 -0
  172. package/src/svg/NavigationChevronDown.svg +4 -0
  173. package/src/svg/NavigationChevronLeft.svg +4 -0
  174. package/src/svg/NavigationChevronRight.svg +4 -0
  175. package/src/svg/NavigationChevronUp.svg +4 -0
  176. package/src/svg/NavigationDoubleChevronLeft.svg +4 -0
  177. package/src/svg/NewTab.svg +3 -0
  178. package/src/svg/Night.svg +5 -0
  179. package/src/svg/NoColor.svg +5 -0
  180. package/src/svg/Note.svg +3 -0
  181. package/src/svg/Notifications.svg +3 -0
  182. package/src/svg/NotificationsMuted.svg +4 -0
  183. package/src/svg/Numbers.svg +3 -0
  184. package/src/svg/Offline.svg +4 -0
  185. package/src/svg/Open.svg +4 -0
  186. package/src/svg/Page.svg +3 -0
  187. package/src/svg/Paste.svg +7 -0
  188. package/src/svg/Pause.svg +3 -0
  189. package/src/svg/Person.svg +4 -0
  190. package/src/svg/PersonRound.svg +4 -0
  191. package/src/svg/Pin.svg +3 -0
  192. package/src/svg/Placeholder.svg +3 -0
  193. package/src/svg/Play.svg +3 -0
  194. package/src/svg/Print.svg +3 -0
  195. package/src/svg/Prompt.svg +3 -0
  196. package/src/svg/PushNotification.svg +3 -0
  197. package/src/svg/Quote.svg +6 -0
  198. package/src/svg/Radio.svg +3 -0
  199. package/src/svg/Recurring.svg +3 -0
  200. package/src/svg/RecycleBin.svg +11 -0
  201. package/src/svg/Redo.svg +4 -0
  202. package/src/svg/Remove.svg +3 -0
  203. package/src/svg/Replay.svg +3 -0
  204. package/src/svg/ReplyAll.svg +4 -0
  205. package/src/svg/Retry.svg +3 -0
  206. package/src/svg/Robot.svg +3 -0
  207. package/src/svg/Rotate.svg +3 -0
  208. package/src/svg/Search.svg +3 -0
  209. package/src/svg/Security.svg +3 -0
  210. package/src/svg/Send.svg +3 -0
  211. package/src/svg/Settings.svg +3 -0
  212. package/src/svg/SettingsKnobs.svg +3 -0
  213. package/src/svg/Share.svg +3 -0
  214. package/src/svg/ShortText.svg +3 -0
  215. package/src/svg/Show.svg +3 -0
  216. package/src/svg/Shredder.svg +3 -0
  217. package/src/svg/Sort.svg +4 -0
  218. package/src/svg/SortAscending.svg +3 -0
  219. package/src/svg/SortDescending.svg +3 -0
  220. package/src/svg/Sound.svg +4 -0
  221. package/src/svg/Status.svg +5 -0
  222. package/src/svg/StrikethroughS.svg +12 -0
  223. package/src/svg/StrikethroughT.svg +11 -0
  224. package/src/svg/Subitems.svg +3 -0
  225. package/src/svg/Sun.svg +3 -0
  226. package/src/svg/Switch.svg +3 -0
  227. package/src/svg/Switcher.svg +18 -0
  228. package/src/svg/Table.svg +3 -0
  229. package/src/svg/Tags.svg +3 -0
  230. package/src/svg/Team.svg +3 -0
  231. package/src/svg/Text.svg +3 -0
  232. package/src/svg/TextBig.svg +3 -0
  233. package/src/svg/TextColorIndicator.svg +26 -0
  234. package/src/svg/TextCopy.svg +3 -0
  235. package/src/svg/TextHuge.svg +3 -0
  236. package/src/svg/TextMedium.svg +3 -0
  237. package/src/svg/TextSmall.svg +3 -0
  238. package/src/svg/Textcolor.svg +5 -0
  239. package/src/svg/ThumbsUp.svg +3 -0
  240. package/src/svg/Time.svg +3 -0
  241. package/src/svg/Timeline.svg +5 -0
  242. package/src/svg/Translation.svg +3 -0
  243. package/src/svg/TurnInto.svg +6 -0
  244. package/src/svg/Underline.svg +8 -0
  245. package/src/svg/Undo.svg +4 -0
  246. package/src/svg/Unlocked.svg +3 -0
  247. package/src/svg/Update.svg +3 -0
  248. package/src/svg/Upgrade.svg +3 -0
  249. package/src/svg/Upload.svg +3 -0
  250. package/src/svg/UserDomain.svg +4 -0
  251. package/src/svg/UserStatus.svg +4 -0
  252. package/src/svg/Versioning.svg +3 -0
  253. package/src/svg/Video.svg +6 -0
  254. package/src/svg/Wand.svg +3 -0
  255. package/src/svg/Warning.svg +5 -0
  256. package/src/svg/WhatsNew.svg +3 -0
  257. package/src/svg/Widgets.svg +3 -0
  258. package/src/svg/Work.svg +3 -0
  259. package/src/svg/Workflow.svg +7 -0
  260. package/src/svg/Workspace.svg +3 -0
  261. package/src/svg.d.ts +4 -0
  262. package/tsconfig.json +31 -0
  263. package/tsconfig.test.json +10 -0
  264. package/vibe-icons-v8.tgz +0 -0
  265. package/vibe-icons-v9.tgz +0 -0
  266. package/vitest.config.ts +13 -0
package/.eslintrc.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "parser": "@typescript-eslint/parser",
3
+ "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
4
+ "ignorePatterns": ["dist", ".eslintrc.json"],
5
+ "plugins": ["@typescript-eslint"],
6
+ "rules": {
7
+ "no-unused-vars": "off",
8
+ "@typescript-eslint/no-var-requires": "off",
9
+ "@typescript-eslint/no-unused-vars": [
10
+ "warn",
11
+ {
12
+ "argsIgnorePattern": "^_",
13
+ "varsIgnorePattern": "^_",
14
+ "caughtErrorsIgnorePattern": "^_"
15
+ }
16
+ ],
17
+ "no-empty-function": "off",
18
+ "@typescript-eslint/no-empty-function": ["error", { "allow": ["arrowFunctions"] }]
19
+ },
20
+ "env": {
21
+ "node": true
22
+ }
23
+ }
package/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # @vibe/icons
2
+
3
+ This package includes all of the icons of monday.com's [Vibe Design System](https://vibe.monday.com/?path=/story/media-icon--icons-list-story), available as React components and raw SVGs for flexible usage in your projects.
4
+
5
+
6
+ ## Installation
7
+
8
+ To install, use the following command:
9
+
10
+ ```bash
11
+ npm install @vibe/icons
12
+ ```
13
+
14
+ ## Usage
15
+
16
+ #### Using React Components
17
+
18
+ ```javascript
19
+ import { Close } from "@vibe/icons";
20
+ ```
21
+
22
+ #### Using Raw SVG Files
23
+
24
+ ```javascript
25
+ import { Close as CloseSvg } from "@vibe/icons/raw";
26
+ ```
27
+
28
+
29
+ ## Peer dependencies
30
+
31
+ We are reliant on React and React DOM, we are using them as externals, and we don't package them to the package, so you must have them in your project
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@vibe/icons",
3
+ "version": "0.0.1",
4
+ "description": "Vibe's icon library",
5
+ "repository": "git+https://github.com/mondaycom/vibe.git",
6
+ "author": "monday.com",
7
+ "license": "MIT",
8
+ "main": "./dist/index.js",
9
+ "type": "module",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/react/index.d.ts",
13
+ "import": "./dist/react/index.js",
14
+ "default": "./dist/react/index.js"
15
+ },
16
+ "./meta": {
17
+ "types": "./dist/iconsMetaData.d.ts",
18
+ "import": "./dist/iconsMetaData.js",
19
+ "default": "./dist/iconsMetaData.js"
20
+ },
21
+ "./raw": {
22
+ "types": "./dist/svg/index.d.ts",
23
+ "import": "./dist/svg/index.js",
24
+ "default": "./dist/svg/index.js"
25
+ }
26
+ },
27
+ "typesVersions": {
28
+ "*": {
29
+ "meta": [
30
+ "./dist/iconsMetaData.d.ts"
31
+ ],
32
+ "raw": [
33
+ "./dist/svg/index.d.ts"
34
+ ]
35
+ }
36
+ },
37
+ "scripts": {
38
+ "plop": "plop",
39
+ "build": "yarn clean && yarn build:react-icons && yarn generate-svg-index && rollup -c",
40
+ "build:react-icons": "svg2react-icon --typescript --keep-colors src/svg/ src/react/ --no-sub-dir",
41
+ "clean": "rm -rf dist",
42
+ "test": "vitest",
43
+ "lint": "eslint . --max-warnings 0 && yarn validate-icons",
44
+ "lint:fix": "yarn lint -- --fix",
45
+ "validate-icons": "node scripts/validate-meta.js && node scripts/validate-icons-colors.js",
46
+ "generate-meta": "node scripts/generate-meta.js",
47
+ "generate-svg-index": "node scripts/generate-svg-index.js"
48
+ },
49
+ "devDependencies": {
50
+ "@rollup/plugin-node-resolve": "^15.0.1",
51
+ "@typescript-eslint/eslint-plugin": "^6.21.0",
52
+ "@typescript-eslint/parser": "^6.21.0",
53
+ "eslint": "^8.57.0",
54
+ "plop": "4.0.1",
55
+ "rollup": "^2.79.1",
56
+ "rollup-plugin-copy": "^3.5.0",
57
+ "rollup-plugin-svg": "^2.0.0",
58
+ "rollup-plugin-terser": "^7.0.2",
59
+ "rollup-plugin-typescript2": "^0.34.1",
60
+ "svg2react-icon": "^3.1.178",
61
+ "typescript": "^4.7.3",
62
+ "vitest": "^1.6.0"
63
+ },
64
+ "peerDependencies": {
65
+ "react": ">=16.9.0",
66
+ "react-dom": ">=16.9.0"
67
+ }
68
+ }
@@ -0,0 +1,7 @@
1
+ $1
2
+ {
3
+ name: "{{iconName}}",
4
+ file: "{{fileName}}",
5
+ description: "{{description}}",
6
+ tags: "{{tags}}"
7
+ },
@@ -0,0 +1,59 @@
1
+ import { exec } from "child_process";
2
+ export default {
3
+ description: "Adding a new icon",
4
+ prompts: [
5
+ {
6
+ type: "input",
7
+ name: "iconName",
8
+ message: "What is the name of the icon"
9
+ },
10
+ {
11
+ type: "input",
12
+ name: "fileName",
13
+ message: "FileName including the suffix (including '.svg') suffix",
14
+ validate: input => input.endsWith(".svg") || "FileName must end with .svg"
15
+ },
16
+ {
17
+ type: "input",
18
+ name: "description",
19
+ message: "Enter the icon description"
20
+ },
21
+ {
22
+ type: "input",
23
+ name: "tags",
24
+ message: "Enter tags for the icon (separate with ',')"
25
+ }
26
+ ],
27
+ actions: () => {
28
+ return [
29
+ {
30
+ type: "modify",
31
+ path: "src/iconsMetaData.ts",
32
+ templateFile: "plop/icon/icon-metadata.txt",
33
+ pattern: /(\/\/ plop_marker:icon_metadata)/g
34
+ },
35
+ () =>
36
+ new Promise((resolve, reject) => {
37
+ console.log("Adding icon...");
38
+ exec("yarn validate-icons", (lintErr, lintStdout) => {
39
+ if (lintErr) {
40
+ console.error(lintErr);
41
+ reject(lintErr);
42
+ return;
43
+ }
44
+ console.log(lintStdout);
45
+
46
+ exec("yarn build:react-icons", (buildErr, buildStdout) => {
47
+ if (buildErr) {
48
+ console.error(buildErr);
49
+ reject(buildErr);
50
+ return;
51
+ }
52
+ console.log(buildStdout);
53
+ resolve("Icon added and icons built successfully!");
54
+ });
55
+ });
56
+ })
57
+ ];
58
+ }
59
+ };
package/plopfile.js ADDED
@@ -0,0 +1,5 @@
1
+ import icon from "./plop/icon/index.js";
2
+
3
+ export default function (plop) {
4
+ plop.setGenerator("Icon", icon);
5
+ }
@@ -0,0 +1,19 @@
1
+ import resolve from "@rollup/plugin-node-resolve";
2
+ import typescript from "rollup-plugin-typescript2";
3
+ import { terser } from "rollup-plugin-terser";
4
+ import svg from "rollup-plugin-svg";
5
+
6
+ export default {
7
+ input: ["src/react/index.ts", "src/svg/index.ts", "src/iconsMetaData.ts"],
8
+ output: {
9
+ dir: "dist",
10
+ indent: false,
11
+ strict: false,
12
+ exports: "named",
13
+ preserveModules: true,
14
+ preserveModulesRoot: "./src",
15
+ format: "esm"
16
+ },
17
+ external: [/node_modules/],
18
+ plugins: [resolve(), typescript(), terser(), svg()]
19
+ };
@@ -0,0 +1,7 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`validate-icons-colors > validateColors > should throw an error for disallowed colors 1`] = `
4
+ [Error: validate-icons-colors: Invalid color - fill="#123456" used in 'invalid-icon.svg'.
5
+ Should be one of the folowing values for outlined icons: ["currentColor","none"].
6
+ If color='white' and it's declared in <rect> (when using <clipPath> element), delete it and check if the icon looks fine]
7
+ `;
@@ -0,0 +1,129 @@
1
+ import {
2
+ ALLOWED_COLORS,
3
+ EXCEPTIONAL_ICONS,
4
+ extractColorsFromSvg,
5
+ isEligibleForValidation,
6
+ validateColors
7
+ } from "../utils";
8
+
9
+ const mockRealSVGInvalid = `
10
+ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
11
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M11.6413 4.31058C11.6411 4.31074 11.6414 4.31043 11.6413 4.31058L10.1221 5.82974L14.5799 10.2875L16.0991 8.76837C16.0992 8.76824 16.0989 8.7685 16.0991 8.76837C16.1376 8.72937 16.1597 8.67635 16.1597 8.62149C16.1597 8.56664 16.138 8.514 16.0995 8.47501C16.0993 8.47488 16.0996 8.47514 16.0995 8.47501L11.935 4.31058C11.9349 4.31045 11.9352 4.31071 11.935 4.31058C11.896 4.27202 11.843 4.25 11.7882 4.25C11.7333 4.25 11.6803 4.27207 11.6413 4.31058ZM13.696 11.1714L9.23825 6.71362L3.31058 12.6413C3.31043 12.6414 3.31074 12.6411 3.31058 12.6413C3.27207 12.6803 3.25 12.7333 3.25 12.7882C3.25 12.843 3.27164 12.8957 3.3102 12.9346C3.31033 12.9348 3.31007 12.9345 3.3102 12.9346L6.45954 16.084H8.78344L13.696 11.1714ZM10.5512 16.084L16.9843 9.65094L16.9856 9.64962C17.2572 9.37638 17.4097 9.00676 17.4097 8.62149C17.4097 8.23622 17.2572 7.86661 16.9856 7.59337L12.8176 3.42538L12.8163 3.42407C12.543 3.15246 12.1734 3 11.7882 3C11.4029 3 11.0333 3.15246 10.76 3.42407L10.7587 3.42539L2.42539 11.7587L2.42407 11.76C2.15246 12.0333 2 12.4029 2 12.7882C2 13.1734 2.15246 13.543 2.42407 13.8163L2.42539 13.8176L5.75872 17.1509C5.87593 17.2681 6.0349 17.334 6.20066 17.334H15.3673C15.7125 17.334 15.9923 17.0542 15.9923 16.709C15.9923 16.3638 15.7125 16.084 15.3673 16.084H10.5512Z" fill="#676879"/>
12
+ </svg>
13
+ `;
14
+
15
+ const mockSVGInvalid = `
16
+ <svg fill="currentColor" stroke="none">
17
+ <rect fill="currentColor" stroke="blue"/>
18
+ <circle fill="none" stroke="#123456"/>
19
+ <path fill="green" stroke="none"/>
20
+ </svg>
21
+ `;
22
+
23
+ const mockSVGValid = `
24
+ <svg fill="none" stroke="currentColor">
25
+ <path stroke="none"/>
26
+ <rect fill="currentColor" stroke="currentColor"/>
27
+ <circle fill="none" stroke="currentColor"/>
28
+ </svg>
29
+ `;
30
+
31
+ const mockSVGWithoutColors = `
32
+ <svg>
33
+ <path />
34
+ <circle />
35
+ </svg>
36
+ `;
37
+
38
+ describe("validate-icons-colors", () => {
39
+ describe("isEligibleForValidation", () => {
40
+ it("should return true for a valid svg file", () => {
41
+ expect(isEligibleForValidation("valid-icon.svg")).toBe(true);
42
+ });
43
+
44
+ it("should return false for an svg file in the EXCEPTIONAL_ICONS list", () => {
45
+ expect(isEligibleForValidation(EXCEPTIONAL_ICONS[0])).toBe(false);
46
+ });
47
+
48
+ it("should return false for a non-svg file", () => {
49
+ expect(isEligibleForValidation("not-an-svg.png")).toBe(false);
50
+ });
51
+ });
52
+
53
+ describe("validateColors", () => {
54
+ const disallowedColors = ["red", "#123456", "helloworld"];
55
+ disallowedColors.forEach(color => {
56
+ it(`should throw an error for disallowed color ${disallowedColors}`, () => {
57
+ const colors = [
58
+ { attribute: "fill", color: "currentColor" },
59
+ { attribute: "stroke", color }
60
+ ];
61
+ const svgFileName = "valid-icon.svg";
62
+ expect(() => validateColors(colors, svgFileName)).toThrow();
63
+ });
64
+ });
65
+
66
+ const allowedColors = ALLOWED_COLORS;
67
+ allowedColors.forEach(color => {
68
+ it(`should not throw an error for allowed color ${color}`, () => {
69
+ const colors = [
70
+ { attribute: "fill", color },
71
+ { attribute: "stroke", color: "none" }
72
+ ];
73
+ const svgFileName = "valid-icon.svg";
74
+ expect(() => validateColors(colors, svgFileName)).not.toThrow();
75
+ });
76
+ });
77
+
78
+ it("should throw an error for disallowed colors", () => {
79
+ const colors = [{ attribute: "fill", color: "#123456" }];
80
+ const svgFileName = "invalid-icon.svg";
81
+ expect(() => validateColors(colors, svgFileName)).toThrowErrorMatchingSnapshot();
82
+ });
83
+ });
84
+
85
+ describe("extractColorsFromSvg", () => {
86
+ it("should extract colors from an invalid svg", () => {
87
+ const colors = extractColorsFromSvg(mockSVGInvalid);
88
+ const expectedColors = [
89
+ { attribute: "fill", color: "currentColor" },
90
+ { attribute: "stroke", color: "none" },
91
+ { attribute: "fill", color: "currentColor" },
92
+ { attribute: "stroke", color: "blue" },
93
+ { attribute: "fill", color: "none" },
94
+ { attribute: "stroke", color: "#123456" },
95
+ { attribute: "fill", color: "green" },
96
+ { attribute: "stroke", color: "none" }
97
+ ];
98
+ expect(colors).toEqual(expectedColors);
99
+ });
100
+
101
+ it("should extract colors from a valid svg", () => {
102
+ const colors = extractColorsFromSvg(mockSVGValid);
103
+ const expectedColors = [
104
+ { attribute: "fill", color: "none" },
105
+ { attribute: "stroke", color: "currentColor" },
106
+ { attribute: "stroke", color: "none" },
107
+ { attribute: "fill", color: "currentColor" },
108
+ { attribute: "stroke", color: "currentColor" },
109
+ { attribute: "fill", color: "none" },
110
+ { attribute: "stroke", color: "currentColor" }
111
+ ];
112
+ expect(colors).toEqual(expectedColors);
113
+ });
114
+
115
+ it("should extract colors from a real invalid svg", () => {
116
+ const colors = extractColorsFromSvg(mockRealSVGInvalid);
117
+ const expectedColors = [
118
+ { attribute: "fill", color: "none" },
119
+ { attribute: "fill", color: "#676879" }
120
+ ];
121
+ expect(colors).toEqual(expectedColors);
122
+ });
123
+
124
+ it("should handle SVG without color attributes", () => {
125
+ const colors = extractColorsFromSvg(mockSVGWithoutColors);
126
+ expect(colors).toEqual([]);
127
+ });
128
+ });
129
+ });
@@ -0,0 +1,20 @@
1
+ const nodePlop = require("node-plop");
2
+ const { getFilesWithNoMetadata } = require("./metadata-util");
3
+
4
+ const plop = nodePlop(`./plopfile.js`);
5
+ const IconGenerator = plop.getGenerator("Icon");
6
+
7
+ const { fileWithNoMeta } = getFilesWithNoMetadata();
8
+
9
+ async function addFiles() {
10
+ if (fileWithNoMeta && fileWithNoMeta.length > 0) {
11
+ for (const file of fileWithNoMeta) {
12
+ console.log(`generating meta for file: ${file}`);
13
+ const iconName = file.substr(0, file.indexOf("."));
14
+ const answers = await IconGenerator.runPrompts([iconName, file]);
15
+ await IconGenerator.runActions(answers);
16
+ }
17
+ }
18
+ }
19
+
20
+ addFiles();
@@ -0,0 +1,18 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+
4
+ const SVG_FOLDER = "./src/svg";
5
+ const INDEX_FILE = `${SVG_FOLDER}/index.ts`;
6
+
7
+ const svgFiles = fs.readdirSync(SVG_FOLDER).filter(file => file.endsWith(".svg"));
8
+
9
+ const svgExports = svgFiles
10
+ .map(file => {
11
+ const fileNameWithoutExtension = path.basename(file, ".svg");
12
+ return `export { default as ${fileNameWithoutExtension} } from './${file}';`;
13
+ })
14
+ .join("\n");
15
+
16
+ fs.writeFileSync(INDEX_FILE, svgExports);
17
+
18
+ console.log(`Generated index.ts for SVG exports in ${SVG_FOLDER}`);
@@ -0,0 +1,28 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ const ICONS_FOLDERS = path.resolve("./src/svg/");
4
+ const METADATA_FILENAME = "iconsMetaData.ts";
5
+ const METADATA_FILE_PATH = path.resolve("./src") + "/" + METADATA_FILENAME;
6
+
7
+ function getIconsFiles() {
8
+ return fs.readdirSync(ICONS_FOLDERS);
9
+ }
10
+
11
+ function getIconsMetaFiles() {
12
+ let file = fs.readFileSync(METADATA_FILE_PATH, { encoding: "utf-8" });
13
+ file.substr(file.indexOf("iconsMetaData"));
14
+ return [...file.matchAll(/file: "(?<name>.*?)"/g)].map(f => f.groups.name);
15
+ }
16
+
17
+ function getFilesWithNoMetadata() {
18
+ const actualFiles = getIconsFiles().filter(f => f.endsWith(".svg"));
19
+ const actualFilesSet = new Set(actualFiles);
20
+ const metaFiles = getIconsMetaFiles();
21
+ const metaFilesSet = new Set(metaFiles);
22
+
23
+ const metaBadReferences = metaFiles.filter(f => !actualFilesSet.has(f));
24
+ const fileWithNoMeta = actualFiles.filter(f => !metaFilesSet.has(f));
25
+ return { metaBadReferences, fileWithNoMeta };
26
+ }
27
+
28
+ export default getFilesWithNoMetadata;
@@ -0,0 +1,35 @@
1
+ // Files on which the rule doesn't apply
2
+ const EXCEPTIONAL_ICONS = ["ConnectedDoc.svg"];
3
+ const ALLOWED_COLORS = ["currentColor", "none"];
4
+
5
+ function isEligibleForValidation(svgFile) {
6
+ return svgFile.endsWith(".svg") && !EXCEPTIONAL_ICONS.includes(svgFile);
7
+ }
8
+
9
+ function validateColors(colors, svgFileName, allowedColors = ALLOWED_COLORS) {
10
+ colors.forEach(({ attribute, color }) => {
11
+ if (!allowedColors.includes(color)) {
12
+ throw Error(generateErrorMessage(attribute, color, svgFileName));
13
+ }
14
+ });
15
+ }
16
+
17
+ function extractColorsFromSvg(content) {
18
+ const colorMatches = content.match(/(fill|stroke)=["']([\w#]+)["']/g) || [];
19
+ return colorMatches.map(match => {
20
+ const [, attribute, color] = match.match(/(fill|stroke)=["']([\w#]+)["']/) || [];
21
+ return { attribute, color };
22
+ });
23
+ }
24
+
25
+ function colorErrorMessage(message) {
26
+ return `\x1b[31m${message}\x1b[0m`;
27
+ }
28
+
29
+ function generateErrorMessage(attribute, color, svgFileName) {
30
+ return colorErrorMessage(`validate-icons-colors: Invalid color - ${attribute}="${color}" used in '${svgFileName}'.
31
+ Should be one of the folowing values for outlined icons: ${JSON.stringify(ALLOWED_COLORS)}.
32
+ If color='white' and it's declared in <rect> (when using <clipPath> element), delete it and check if the icon looks fine`);
33
+ }
34
+
35
+ export { EXCEPTIONAL_ICONS, ALLOWED_COLORS, isEligibleForValidation, validateColors, extractColorsFromSvg };
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Validation rule for icons svg files, to make sure they use only allowed fill/stroke colors
4
+ // Usage: node scripts/validate-icons-colors.js
5
+
6
+ import { extractColorsFromSvg, isEligibleForValidation, validateColors } from "./utils.js";
7
+ import fs from "fs";
8
+
9
+ const SVGS_PATH = "src/svg";
10
+
11
+ function validateSvgFile(name, content) {
12
+ const colors = extractColorsFromSvg(content);
13
+ validateColors(colors, name);
14
+ }
15
+
16
+ function readSvgFileContent(svgFilePath) {
17
+ return fs.readFileSync(svgFilePath, "utf8").toString();
18
+ }
19
+
20
+ function validateAllSvgsInPath(path) {
21
+ const svgFiles = fs.readdirSync(path).filter(isEligibleForValidation);
22
+ svgFiles.forEach(svgFileName => validateSvgFile(svgFileName, readSvgFileContent(`${path}/${svgFileName}`)));
23
+ }
24
+
25
+ validateAllSvgsInPath(SVGS_PATH);
@@ -0,0 +1,10 @@
1
+ import getFilesWithNoMetadata from "./metadata-util.js";
2
+
3
+ const { metaBadReferences, fileWithNoMeta } = getFilesWithNoMetadata();
4
+
5
+ if (metaBadReferences && metaBadReferences.length > 0) {
6
+ throw new Error("No matching file for metas: " + metaBadReferences.join(", "));
7
+ }
8
+ if (fileWithNoMeta && fileWithNoMeta.length > 0) {
9
+ throw new Error("No matching meta for files: " + fileWithNoMeta.join(", "));
10
+ }