├── .eslintignore ├── .gitattributes ├── .gitignore ├── src ├── index.ts ├── __tests__ │ └── CIcon.spec.ts ├── CIconSvg.ts └── CIcon.ts ├── jest.config.js ├── tsconfig.json ├── LICENSE ├── rollup.config.mjs ├── package.json └── README.md /.eslintignore: -------------------------------------------------------------------------------- 1 | /dist/** 2 | .eslintrc.js -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Enforce Unix newlines 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .git 3 | .vscode 4 | _old 5 | node_modules 6 | test 7 | .cache 8 | coverage/ 9 | dist/ 10 | public/ 11 | yarn.lock -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { CIcon } from './CIcon' 2 | import { CIconSvg } from './CIconSvg' 3 | export { CIcon, CIconSvg } 4 | export default CIcon 5 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-present, creativeLabs Lukasz Holeczek. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | 'use strict' 9 | 10 | module.exports = { 11 | moduleFileExtensions: ['tsx', 'js', 'ts', 'json', 'vue'], 12 | preset: 'ts-jest', 13 | testEnvironment: 'jsdom', 14 | testEnvironmentOptions: { 15 | customExportConditions: ['node', 'node-addons'], 16 | }, 17 | testPathIgnorePatterns: ['dist/'], 18 | transform: { 19 | '.*\\.(ts)$': 'ts-jest', 20 | '.*\\.(vue)$': '@vue/vue3-jest', 21 | }, 22 | } 23 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "preserve", 4 | "outDir": "dist", 5 | "module": "esnext", 6 | "target": "esnext", 7 | "strict": true, 8 | "lib": ["es6", "dom", "es2016", "es2017"], 9 | "sourceMap": true, 10 | "allowJs": false, 11 | "declaration": true, 12 | "declarationDir": ".", 13 | "moduleResolution": "node", 14 | "forceConsistentCasingInFileNames": true, 15 | "noImplicitReturns": true, 16 | "noImplicitThis": true, 17 | "noImplicitAny": true, 18 | "strictNullChecks": true, 19 | "noUnusedLocals": true, 20 | "noUnusedParameters": true, 21 | "esModuleInterop": true, 22 | "resolveJsonModule": true 23 | }, 24 | "include": ["src"], 25 | "exclude": ["node_modules", "dist"] 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 creativeLabs Łukasz Holeczek 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /rollup.config.mjs: -------------------------------------------------------------------------------- 1 | import commonjs from '@rollup/plugin-commonjs' 2 | import typescript from '@rollup/plugin-typescript' 3 | import external from 'rollup-plugin-peer-deps-external' 4 | import resolve from '@rollup/plugin-node-resolve' 5 | import vue from 'rollup-plugin-vue' 6 | import { readFileSync } from 'node:fs' 7 | 8 | const pkg = JSON.parse(readFileSync(new URL('package.json', import.meta.url))) 9 | 10 | const plugins = [ 11 | external(), 12 | resolve({ 13 | dedupe: ['vue'], 14 | extensions: ['.ts', '.json', '.vue'], 15 | }), 16 | typescript({ 17 | exclude: ['**/__tests__/**'], 18 | tsconfig: './tsconfig.json', 19 | }), 20 | commonjs({ 21 | include: ['node_modules/**'], 22 | }), 23 | ] 24 | 25 | export default [ 26 | // ESM build to be used with webpack/rollup. 27 | { 28 | input: 'src/index.ts', 29 | output: { 30 | format: 'es', 31 | file: pkg.module, 32 | exports: 'named', 33 | sourcemap: true, 34 | }, 35 | plugins: [...plugins, vue()], 36 | }, 37 | // SSR build. 38 | { 39 | input: 'src/index.ts', 40 | output: { 41 | format: 'cjs', 42 | file: pkg.main, 43 | exports: 'named', 44 | sourcemap: true, 45 | }, 46 | plugins: [...plugins, vue({ template: { optimizeSSR: true } })], 47 | }, 48 | ] 49 | -------------------------------------------------------------------------------- /src/__tests__/CIcon.spec.ts: -------------------------------------------------------------------------------- 1 | import { mount } from '@vue/test-utils' 2 | import { CIcon } from './../' 3 | 4 | describe('CIcon', () => { 5 | it('renders svg with class="icon"', () => { 6 | const container = mount(CIcon) 7 | expect(container.find('svg').classes('icon')).toBe(true) 8 | }) 9 | 10 | // it('renders svg with icon', () => { 11 | // const { container } = mount() 12 | // expect(container.firstChild).toContain(cifAu[1]) 13 | // // expect(render()).toContain(cifAu) 14 | // }) 15 | 16 | it('renders svg with size', () => { 17 | const container = mount(CIcon, { props: { size: 'xl' } }) 18 | expect(container.find('svg').classes('icon-xl')).toBe(true) 19 | }) 20 | 21 | it('renders svg with custom size', () => { 22 | const container = mount(CIcon, { props: { height: 20 } }) 23 | expect(container.find('svg').classes('icon-custom-size')).toBe(true) 24 | }) 25 | 26 | it('renders svg with className', () => { 27 | const container = mount(CIcon, { props: { class: 'icon-test' } }) 28 | expect(container.find('svg').classes('icon-test')).toBe(true) 29 | }) 30 | 31 | // it('renders with ', () => { 32 | // const { container } = mount() 33 | // expect(container.firstChild?.firstChild).toContain('') 34 | // }) 35 | }) 36 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@coreui/icons-vue", 3 | "version": "2.2.0", 4 | "description": "Official Vue component for CoreUI Icons", 5 | "keywords": [ 6 | "coreui", 7 | "coreui-icons", 8 | "coreui-vue", 9 | "icons", 10 | "svg", 11 | "svg-icons", 12 | "layout", 13 | "component", 14 | "vue" 15 | ], 16 | "homepage": "https://icons.coreui.io", 17 | "bugs": { 18 | "url": "https://github.com/coreui/coreui-icons/issues" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "https://github.com/coreui/coreui-icons.git" 23 | }, 24 | "license": "MIT", 25 | "author": "The CoreUI Team (https://github.com/orgs/coreui/people)", 26 | "main": "dist/index.js", 27 | "module": "dist/index.es.js", 28 | "jsnext:main": "dist/index.es.js", 29 | "types": "dist/index.d.ts", 30 | "files": [ 31 | "dist/", 32 | "src/" 33 | ], 34 | "scripts": { 35 | "build": "rollup --config", 36 | "test": "jest --coverage", 37 | "test:clear": "jest --clearCache", 38 | "test:update": "jest --coverage --updateSnapshot" 39 | }, 40 | "devDependencies": { 41 | "@rollup/plugin-commonjs": "^26.0.1", 42 | "@rollup/plugin-node-resolve": "^15.2.3", 43 | "@rollup/plugin-typescript": "^11.1.6", 44 | "@types/jest": "^29.5.13", 45 | "@vue/compiler-sfc": "^3.5.5", 46 | "@vue/test-utils": "^2.4.6", 47 | "@vue/vue3-jest": "29.2.6", 48 | "jest": "^29.7.0", 49 | "jest-environment-jsdom": "^29.7.0", 50 | "rollup": "^4.21.3", 51 | "rollup-plugin-peer-deps-external": "^2.2.4", 52 | "rollup-plugin-vue": "^6.0.0", 53 | "ts-jest": "^29.2.5", 54 | "typescript": "^5.6.2", 55 | "vue": "^3.5.5", 56 | "vue-types": "^5.1.3" 57 | }, 58 | "peerDependencies": { 59 | "vue": "^3.2.20" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/CIconSvg.ts: -------------------------------------------------------------------------------- 1 | import { cloneVNode, defineComponent } from 'vue' 2 | 3 | const CIconSvg = defineComponent({ 4 | name: 'CIconSvg', 5 | props: { 6 | /** 7 | * Use for replacing default CIconSvg component classes. Prop is overriding the 'size' prop. 8 | */ 9 | customClassName: [String, Array, Object], 10 | /** 11 | * The height attribute defines the vertical length of an icon. 12 | */ 13 | height: Number, 14 | /** 15 | * Size of the icon. Available sizes: 'sm', 'lg', 'xl', 'xxl', '3xl...9xl', 'custom', 'custom-size'. 16 | */ 17 | size: { 18 | type: String, 19 | validator: (value: string) => { 20 | return [ 21 | 'custom', 22 | 'custom-size', 23 | 'sm', 24 | 'lg', 25 | 'xl', 26 | 'xxl', 27 | '3xl', 28 | '4xl', 29 | '5xl', 30 | '6xl', 31 | '7xl', 32 | '8xl', 33 | '9xl', 34 | ].includes(value) 35 | }, 36 | }, 37 | /** 38 | * Title tag content. 39 | */ 40 | title: String, 41 | /** 42 | * The width attribute defines the horizontal length of an icon. 43 | */ 44 | width: Number, 45 | }, 46 | setup(props, { attrs, slots }) { 47 | return () => 48 | slots.default && 49 | slots.default().map((slot) => 50 | cloneVNode(slot, { 51 | 'aria-hidden': true, 52 | class: [ 53 | props.customClassName || [ 54 | 'icon', 55 | { 56 | [`icon-${props.size}`]: props.size, 57 | [`icon-custom-size`]: props.height || props.width, 58 | }, 59 | attrs.class, 60 | ], 61 | ], 62 | height: props.height, 63 | focusable: 'false', 64 | role: 'img', 65 | width: props.width, 66 | ...attrs, 67 | }), 68 | ) 69 | }, 70 | }) 71 | export { CIconSvg } 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Official Vue.js component for CoreUI Icons and CoreUI Icons PRO. 9 | 10 | Explore CoreUI Icons for Vue docs » 11 | 12 | 13 | Report bug 14 | · 15 | Request feature 16 | · 17 | Blog 18 | 19 | 20 | 21 | 22 | ## Status 23 | 24 | [][coreui] 25 | [][coreui] 26 | [][coreui] 27 | 28 | [coreui]: https://coreui.io/icons 29 | 30 | 31 | ## Installation 32 | 33 | ```bash 34 | npm install @coreui/icons 35 | npm install @coreui/icons-vue 36 | ``` 37 | 38 | or 39 | 40 | ```bash 41 | yarn add @coreui/icons 42 | yarn add @coreui/icons-vue 43 | ``` 44 | 45 | ## Use 46 | 47 | ### Single icon 48 | 49 | ```jsx 50 | import { CIcon } from '@coreui/icons-vue'; 51 | import { cifAu } from '@coreui/icons'; 52 | 53 | ... 54 | 55 | ... 56 | ``` 57 | 58 | ### All icons 59 | 60 | ```jsx 61 | import { CIcon } from '@coreui/icons-vue'; 62 | import * as icon from '@coreui/icons'; 63 | 64 | ... 65 | 66 | ... 67 | ``` 68 | 69 | ## API 70 | 71 | | property | type | description | 72 | | --- | --- | --- | 73 | | customClassName | `string` \| `object` \| `string[]` | Use for replacing default CIcon component classes. Prop is overriding the 'size' prop. | 74 | | icon | `string` \| `string[]` | Name of the icon placed in React object or SVG content. | 75 | | height | `number` | The height attribute defines the vertical length of an icon. | 76 | | size | `sm` \| `md` \|`lg` \| `xl` \| `xxl` \| `3xl` \| `4xl` \| `5xl` \| `6xl` \| `7xl` \| `8xl` \| `9xl` | Size of the icon. | 77 | | use | `string` | If defined component will be rendered using `use` tag. | 78 | | title | `string` | Title tag content. | 79 | | width | `number` | The width attribute defines the horizontal length of an icon. | 80 | -------------------------------------------------------------------------------- /src/CIcon.ts: -------------------------------------------------------------------------------- 1 | import { computed, defineComponent, h, inject, PropType, ref, watch } from 'vue' 2 | 3 | const CIcon = defineComponent({ 4 | name: 'CIcon', 5 | props: { 6 | /** 7 | * Use `:icon="..."` instead of 8 | * 9 | * @deprecated since version 3.0 10 | */ 11 | content: { 12 | type: [String, Array], 13 | default: undefined, 14 | required: false, 15 | }, 16 | /** 17 | * Use for replacing default CIcon component classes. Prop is overriding the 'size' prop. 18 | */ 19 | customClassName: { 20 | type: [String, Array, Object], 21 | default: undefined, 22 | required: false, 23 | }, 24 | /** 25 | * Name of the icon placed in React object or SVG content. 26 | */ 27 | icon: { 28 | type: [String, Array] as PropType, 29 | default: undefined, 30 | required: false, 31 | }, 32 | /** 33 | * Use `icon="..."` instead of 34 | * 35 | * @deprecated since version 3.0 36 | */ 37 | name: { 38 | type: String, 39 | default: undefined, 40 | required: false, 41 | }, 42 | /** 43 | * Size of the icon. Available sizes: 'sm', 'lg', 'xl', 'xxl', '3xl...9xl', 'custom', 'custom-size'. 44 | */ 45 | size: { 46 | type: String, 47 | default: undefined, 48 | required: false, 49 | validator: (value: string) => { 50 | return [ 51 | 'custom', 52 | 'custom-size', 53 | 'sm', 54 | 'lg', 55 | 'xl', 56 | 'xxl', 57 | '3xl', 58 | '4xl', 59 | '5xl', 60 | '6xl', 61 | '7xl', 62 | '8xl', 63 | '9xl', 64 | ].includes(value) 65 | }, 66 | }, 67 | /** 68 | * Title tag content. 69 | */ 70 | title: { 71 | type: String, 72 | default: undefined, 73 | required: false, 74 | }, 75 | /** 76 | * If defined component will be rendered using 'use' tag. 77 | */ 78 | use: { 79 | type: String, 80 | default: undefined, 81 | required: false, 82 | }, 83 | }, 84 | setup(props, { attrs }) { 85 | const icons: any = inject('icons') 86 | const _icon = ref(props.icon || props.content || props.name) 87 | 88 | watch( 89 | () => props.icon, 90 | () => { 91 | _icon.value = props.icon 92 | }, 93 | ) 94 | 95 | const toCamelCase = (str: string) => { 96 | return str 97 | .replace(/([-_][a-z0-9])/gi, ($1) => { 98 | return $1.toUpperCase() 99 | }) 100 | .replace(/-/gi, '') 101 | } 102 | 103 | const iconName = computed(() => 104 | _icon.value && typeof _icon.value === 'string' 105 | ? _icon.value.includes('-') 106 | ? toCamelCase(_icon.value) 107 | : _icon.value 108 | : '', 109 | ) 110 | 111 | const titleCode = props.title ? `${props.title}` : 'undefined' 112 | 113 | const code = computed(() => 114 | Array.isArray(_icon.value) 115 | ? _icon.value 116 | : typeof _icon.value === 'string' && iconName.value && icons[iconName.value] 117 | ? icons[iconName.value] 118 | : 'undefined', 119 | ) 120 | 121 | const iconCode = computed(() => 122 | Array.isArray(code.value) ? code.value[1] || code.value[0] : code.value, 123 | ) 124 | 125 | const scale = Array.isArray(code.value) && code.value.length > 1 ? code.value[0] : '64 64' 126 | 127 | const viewBox = attrs.viewBox || `0 0 ${scale}` 128 | 129 | const size = () => { 130 | const addCustom = !props.size && (attrs.width || attrs.height) 131 | return props.size === 'custom' || addCustom ? 'custom-size' : props.size 132 | } 133 | 134 | const classNames = (() => { 135 | return [props.customClassName || ['icon', { [`icon-${size()}`]: size() }], attrs.class] 136 | })() 137 | 138 | return () => 139 | props.use 140 | ? h( 141 | 'svg', 142 | { 143 | ...attrs, 144 | xmlns: 'http://www.w3.org/2000/svg', 145 | class: classNames, 146 | role: 'img', 147 | }, 148 | h('use', { href: props.use }), 149 | ) 150 | : h('svg', { 151 | ...attrs, 152 | xmlns: 'http://www.w3.org/2000/svg', 153 | class: classNames, 154 | viewBox: viewBox, 155 | innerHTML: `${titleCode}${iconCode.value}`, 156 | role: 'img', 157 | }) 158 | }, 159 | }) 160 | export { CIcon } 161 | --------------------------------------------------------------------------------
2 | 3 | 4 | 5 |
8 | Official Vue.js component for CoreUI Icons and CoreUI Icons PRO. 9 | 10 | Explore CoreUI Icons for Vue docs » 11 | 12 | 13 | Report bug 14 | · 15 | Request feature 16 | · 17 | Blog 18 |