Skip to content

Commit 6d4f612

Browse files
authored
Merge pull request #6967 from nextcloud-libraries/chore/refactor-nc-icon
refactor(NcIconSvgWrapper): migrate component to Typescript and script-setup
2 parents 0514302 + 9ce3b19 commit 6d4f612

8 files changed

Lines changed: 80 additions & 100 deletions

File tree

src/components/NcAppContent/NcAppDetailsToggle.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { mdiArrowRight } from '@mdi/js'
88
import { emit } from '@nextcloud/event-bus'
99
import { onBeforeUnmount, watch } from 'vue'
1010
import NcButton from '../NcButton/index.ts'
11-
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.js'
11+
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.ts'
1212
import { useIsMobile } from '../../composables/useIsMobile/index.js'
1313
import { t } from '../../l10n.js'
1414

src/components/NcAvatar/NcAvatar.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ import NcActionLink from '../NcActionLink/index.js'
239239
import NcActionRouter from '../NcActionRouter/index.js'
240240
import NcActionText from '../NcActionText/index.js'
241241
import NcButton from '../NcButton/index.ts'
242-
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.js'
242+
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.ts'
243243
import NcLoadingIcon from '../NcLoadingIcon/index.js'
244244
import NcUserStatusIcon from '../NcUserStatusIcon/index.js'
245245
import NcActionButton from '../NcActionButton/index.js'

src/components/NcDialogButton/NcDialogButton.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import { ref } from 'vue'
3131
import { t } from '../../l10n.js'
3232
3333
import NcButton from '../NcButton/index'
34-
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.js'
34+
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.ts'
3535
import NcLoadingIcon from '../NcLoadingIcon/index.js'
3636
3737
const props = withDefaults(defineProps<{

src/components/NcIconSvgWrapper/NcIconSvgWrapper.vue

Lines changed: 74 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,80 @@ export default {
158158
```
159159
</docs>
160160

161+
<script setup lang="ts">
162+
import { computed, warn } from 'vue'
163+
import DOMPurify from 'dompurify'
164+
165+
const props = withDefaults(defineProps<{
166+
/**
167+
* Make the icon directional, meaning it is langauge direction aware.
168+
* If the icon is placed in a right-to-left context it will be mirrored vertically.
169+
*/
170+
directional?: boolean
171+
172+
/**
173+
* Set if the icon should be used as inline content e.g. within text.
174+
* By default the icon is made a block element for use inside `icon`-slots.
175+
*/
176+
inline?: boolean
177+
178+
/**
179+
* Raw SVG string to render
180+
*/
181+
svg?: string
182+
183+
/**
184+
* Label of the icon, used in aria-label
185+
*/
186+
name?: string
187+
188+
/**
189+
* Raw SVG path to render. Takes precedence over the SVG string in the `svg` prop.
190+
*/
191+
path?: string
192+
193+
/**
194+
* Size of the icon to show. Only use if not using within an icon slot.
195+
* Defaults to 20px which is the Nextcloud icon size for all icon slots.
196+
*/
197+
size?: number | 'auto'
198+
}>(), {
199+
name: undefined,
200+
path: '',
201+
size: 20,
202+
svg: '',
203+
})
204+
205+
/**
206+
* Icon size used in CSS
207+
*/
208+
const iconSize = computed(() => typeof props.size === 'number' ? `${props.size}px` : props.size)
209+
210+
/**
211+
* The sanitized SVG or undefined if path shall be used
212+
*/
213+
const cleanSvg = computed(() => {
214+
if (!props.svg || props.path) {
215+
return
216+
}
217+
218+
const svg = DOMPurify.sanitize(props.svg)
219+
220+
const svgDocument = new DOMParser().parseFromString(svg, 'image/svg+xml')
221+
222+
if (svgDocument.querySelector('parsererror')) {
223+
warn('SVG is not valid')
224+
return ''
225+
}
226+
227+
if (svgDocument.documentElement.id) {
228+
svgDocument.documentElement.removeAttribute('id')
229+
}
230+
231+
return svgDocument.documentElement.outerHTML
232+
})
233+
</script>
234+
161235
<template>
162236
<span :aria-hidden="name ? undefined : 'true'"
163237
:aria-label="name || undefined"
@@ -175,100 +249,6 @@ export default {
175249
</span>
176250
</template>
177251

178-
<script>
179-
import { warn } from 'vue'
180-
import DOMPurify from 'dompurify'
181-
182-
export default {
183-
name: 'NcIconSvgWrapper',
184-
185-
props: {
186-
/**
187-
* Make the icon directional, meaning it is langauge direction aware.
188-
* If the icon is placed in a right-to-left context it will be mirrored vertically.
189-
*/
190-
directional: {
191-
type: Boolean,
192-
default: false,
193-
},
194-
195-
/**
196-
* Set if the icon should be used as inline content e.g. within text.
197-
* By default the icon is made a block element for use inside `icon`-slots.
198-
*/
199-
inline: {
200-
type: Boolean,
201-
default: false,
202-
},
203-
204-
/**
205-
* Raw SVG string to render
206-
*/
207-
svg: {
208-
type: String,
209-
default: '',
210-
},
211-
212-
/**
213-
* Label of the icon, used in aria-label
214-
*/
215-
name: {
216-
type: String,
217-
default: '',
218-
},
219-
220-
/**
221-
* Raw SVG path to render. Takes precedence over the SVG string in the `svg` prop.
222-
*/
223-
path: {
224-
type: String,
225-
default: '',
226-
},
227-
228-
/**
229-
* Size of the icon to show. Only use if not using within an icon slot.
230-
* Defaults to 20px which is the Nextcloud icon size for all icon slots.
231-
* @default 20
232-
*/
233-
size: {
234-
type: [Number, String],
235-
default: 20,
236-
validator: (value) => typeof value === 'number' || value === 'auto',
237-
},
238-
},
239-
240-
computed: {
241-
/**
242-
* Icon size used in CSS
243-
*/
244-
iconSize() {
245-
return typeof this.size === 'number' ? `${this.size}px` : this.size
246-
},
247-
248-
cleanSvg() {
249-
if (!this.svg || this.path) {
250-
return
251-
}
252-
253-
const svg = DOMPurify.sanitize(this.svg)
254-
255-
const svgDocument = new DOMParser().parseFromString(svg, 'image/svg+xml')
256-
257-
if (svgDocument.querySelector('parsererror')) {
258-
warn('SVG is not valid')
259-
return ''
260-
}
261-
262-
if (svgDocument.documentElement.id) {
263-
svgDocument.documentElement.removeAttribute('id')
264-
}
265-
266-
return svgDocument.documentElement.outerHTML
267-
},
268-
},
269-
}
270-
</script>
271-
272252
<style lang="scss" scoped>
273253
.icon-vue {
274254
display: flex;

src/components/NcListItemIcon/NcListItemIcon.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ It might be used for list rendering or within the multiselect for example
145145
<script>
146146
import NcAvatar from '../NcAvatar/index.js'
147147
import NcHighlight from '../NcHighlight/index.js'
148-
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.js'
148+
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.ts'
149149
150150
import { userStatus } from '../../mixins/index.js'
151151

src/components/NcModal/NcModal.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ import { t } from '../../l10n.js'
339339
340340
import NcActions from '../NcActions/index.js'
341341
import NcButton from '../NcButton/index.ts'
342-
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.js'
342+
import NcIconSvgWrapper from '../NcIconSvgWrapper/index.ts'
343343
import Timer from '../../utils/Timer.js'
344344
345345
import Close from 'vue-material-design-icons/Close.vue'

src/components/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export { default as NcGuestContent } from './NcGuestContent/index.ts'
5858
export { default as NcHeaderButton } from './NcHeaderButton/index.ts'
5959
export { default as NcHeaderMenu } from './NcHeaderMenu/index.js'
6060
export { default as NcHighlight } from './NcHighlight/index.js'
61-
export { default as NcIconSvgWrapper } from './NcIconSvgWrapper/index.js'
61+
export { default as NcIconSvgWrapper } from './NcIconSvgWrapper/index.ts'
6262
export { default as NcInputField } from './NcInputField/index.js'
6363
export { default as NcListItem } from './NcListItem/index.js'
6464
export { default as NcListItemIcon } from './NcListItemIcon/index.js'

0 commit comments

Comments
 (0)