mirror of
https://github.com/transloadit/uppy.git
synced 2026-01-23 02:25:07 +00:00
@uppy/vue: support kebab-case props in generated components (#6125)
## Summary
- Fix Vue components to work with kebab-case props (`:edit-file` instead
of `:editFile`)
- Update `migrate.mjs` to parse prop names from TypeScript source files
and generate explicit `props` arrays
## Problem
The generated Vue components didn't work correctly with Vue's standard
kebab-case prop convention:
```vue
<!-- This didn't work -->
<FilesList :edit-file="handleEdit" />
<!-- Only this worked (non-standard) -->
<FilesList :editFile="handleEdit" />
```
## Root Cause
The original Vue template used `attrs` to pass props to Preact:
```ts
setup(props, { attrs }) {
preactRender(preactH(PreactComponent, {
...(attrs as Props), // attrs preserves kebab-case!
ctx,
}), container)
}
```
When using `:edit-file` in a Vue template, Vue passes
`attrs['edit-file']` (kebab-case preserved), but Preact expects
`editFile` (camelCase).
## Solution
Generate Vue components with explicit `props` declarations:
```ts
defineComponent({
props: ['editFile', 'columns', 'imageThumbnail'],
setup(props) {
preactRender(preactH(PreactComponent, {
...props, // Vue already converted kebab → camelCase
ctx,
}), container)
}
})
```
When Vue components declare their props, Vue automatically converts
kebab-case template usage to camelCase in the `props` object. This is
standard Vue behavior.
## Why Simpler Alternatives Don't Work
### "Just use `props` instead of `attrs`"
Without a `props` declaration, Vue doesn't know which attributes are
props. The `props` object will be empty and everything goes to `attrs`:
```ts
// Without props declaration
defineComponent({
setup(props, { attrs }) {
// props = {} (empty!)
// attrs = { 'edit-file': fn } (kebab-case preserved)
}
})
```
### "Accept all props dynamically"
Vue doesn't have a "accept all props and convert casing" option. You
must explicitly declare which props you expect for Vue to handle the
conversion.
### "Just document to use camelCase"
This works but violates Vue conventions. Every Vue developer expects
`:edit-file` to work.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Prakash <qxprakash@gmail.com>
This commit is contained in:
parent
8912bafaf4
commit
fa23832f6a
8 changed files with 96 additions and 58 deletions
6
.changeset/clean-monkeys-smoke.md
Normal file
6
.changeset/clean-monkeys-smoke.md
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
"@uppy/components": patch
|
||||||
|
"@uppy/vue": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
- Fix Vue components to work with kebab-case props (`:edit-file` instead of `:editFile`)
|
||||||
|
|
@ -25,6 +25,37 @@ const SVELTE_DIR = path.join(
|
||||||
'packages/@uppy/svelte/src/lib/components/headless/generated',
|
'packages/@uppy/svelte/src/lib/components/headless/generated',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse prop names from a TypeScript component file
|
||||||
|
* Extracts property names from the Props type definition, excluding 'ctx'
|
||||||
|
*/
|
||||||
|
async function parsePropsFromFile(filePath) {
|
||||||
|
const content = await fs.readFile(filePath, 'utf-8')
|
||||||
|
|
||||||
|
// Match the Props type definition: export type ComponentNameProps = { ... }
|
||||||
|
const propsMatch = content.match(
|
||||||
|
/export\s+type\s+\w+Props\s*=\s*\{([^}]+)\}/s,
|
||||||
|
)
|
||||||
|
if (!propsMatch) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
const propsBlock = propsMatch[1]
|
||||||
|
|
||||||
|
// Extract property names (handle optional ? and required properties)
|
||||||
|
const propNames = []
|
||||||
|
const propRegex = /^\s*(\w+)\??:/gm
|
||||||
|
for (const match of propsBlock.matchAll(propRegex)) {
|
||||||
|
const propName = match[1]
|
||||||
|
// Exclude 'ctx' as it's provided by the context
|
||||||
|
if (propName !== 'ctx') {
|
||||||
|
propNames.push(propName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return propNames
|
||||||
|
}
|
||||||
|
|
||||||
// Templates
|
// Templates
|
||||||
const REACT_TEMPLATE = `\
|
const REACT_TEMPLATE = `\
|
||||||
// This file was generated by build-components.mjs
|
// This file was generated by build-components.mjs
|
||||||
|
|
@ -60,18 +91,18 @@ export default function %%ComponentName%%(props: Omit<%%PropsTypeName%%, 'ctx'>)
|
||||||
const VUE_TEMPLATE = `\
|
const VUE_TEMPLATE = `\
|
||||||
// This file was generated by build-components.mjs
|
// This file was generated by build-components.mjs
|
||||||
// ANY EDITS WILL BE OVERWRITTEN!
|
// ANY EDITS WILL BE OVERWRITTEN!
|
||||||
import { defineComponent, ref, watch, onMounted, h } from 'vue'
|
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
||||||
import {
|
import {
|
||||||
%%ComponentName%% as %%PreactComponentName%%,
|
%%ComponentName%% as %%PreactComponentName%%,
|
||||||
type %%PropsTypeName%%,
|
type %%PropsTypeName%%,
|
||||||
} from '@uppy/components'
|
} from '@uppy/components'
|
||||||
import { h as preactH, render as preactRender } from 'preact'
|
import { h as preactH, render as preactRender } from 'preact'
|
||||||
import { shallowEqualObjects } from 'shallow-equal'
|
|
||||||
import { useUppyContext } from '../useUppyContext.js'
|
import { useUppyContext } from '../useUppyContext.js'
|
||||||
|
|
||||||
export default defineComponent<Omit<%%PropsTypeName%%, 'ctx'>>({
|
export default defineComponent({
|
||||||
name: '%%ComponentName%%',
|
name: '%%ComponentName%%',
|
||||||
setup(props, { attrs }) {
|
props: %%PropsArray%%,
|
||||||
|
setup(props) {
|
||||||
const containerRef = ref<HTMLElement | null>(null)
|
const containerRef = ref<HTMLElement | null>(null)
|
||||||
const ctx = useUppyContext()
|
const ctx = useUppyContext()
|
||||||
|
|
||||||
|
|
@ -79,7 +110,7 @@ export default defineComponent<Omit<%%PropsTypeName%%, 'ctx'>>({
|
||||||
if (containerRef.value) {
|
if (containerRef.value) {
|
||||||
preactRender(
|
preactRender(
|
||||||
preactH(%%PreactComponentName%%, {
|
preactH(%%PreactComponentName%%, {
|
||||||
...(attrs as %%PropsTypeName%%),
|
...props,
|
||||||
ctx,
|
ctx,
|
||||||
} satisfies %%PropsTypeName%%),
|
} satisfies %%PropsTypeName%%),
|
||||||
containerRef.value,
|
containerRef.value,
|
||||||
|
|
@ -97,11 +128,10 @@ export default defineComponent<Omit<%%PropsTypeName%%, 'ctx'>>({
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props,
|
() => props,
|
||||||
(current, old) => {
|
() => {
|
||||||
if (!shallowEqualObjects(current, old)) {
|
render%%ComponentName%%()
|
||||||
render%%ComponentName%%()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => h('div', { ref: containerRef })
|
return () => h('div', { ref: containerRef })
|
||||||
|
|
@ -174,6 +204,11 @@ try {
|
||||||
const componentName = path.basename(file, '.tsx')
|
const componentName = path.basename(file, '.tsx')
|
||||||
const propsTypeName = `${componentName}Props`
|
const propsTypeName = `${componentName}Props`
|
||||||
const preactComponentName = `Preact${componentName}`
|
const preactComponentName = `Preact${componentName}`
|
||||||
|
const filePath = path.join(COMPONENTS_DIR, file)
|
||||||
|
|
||||||
|
// Parse props from the source file
|
||||||
|
const propNames = await parsePropsFromFile(filePath)
|
||||||
|
const propsArray = JSON.stringify(propNames)
|
||||||
|
|
||||||
// Generate React wrapper
|
// Generate React wrapper
|
||||||
const reactContent = REACT_TEMPLATE.replace(
|
const reactContent = REACT_TEMPLATE.replace(
|
||||||
|
|
@ -190,6 +225,7 @@ try {
|
||||||
)
|
)
|
||||||
.replace(/%%PreactComponentName%%/g, preactComponentName)
|
.replace(/%%PreactComponentName%%/g, preactComponentName)
|
||||||
.replace(/%%PropsTypeName%%/g, propsTypeName)
|
.replace(/%%PropsTypeName%%/g, propsTypeName)
|
||||||
|
.replace(/%%PropsArray%%/g, propsArray)
|
||||||
|
|
||||||
// Generate Svelte wrapper
|
// Generate Svelte wrapper
|
||||||
const svelteContent = SVELTE_TEMPLATE.replace(
|
const svelteContent = SVELTE_TEMPLATE.replace(
|
||||||
|
|
@ -213,7 +249,9 @@ try {
|
||||||
vueComponents.push(componentName)
|
vueComponents.push(componentName)
|
||||||
svelteComponents.push(componentName)
|
svelteComponents.push(componentName)
|
||||||
|
|
||||||
console.log(`√ ${componentName}`)
|
console.log(
|
||||||
|
`√ ${componentName} (props: ${propNames.join(', ') || 'none'})`,
|
||||||
|
)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Error processing component ${file}:`, error)
|
console.error(`Error processing component ${file}:`, error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import {
|
||||||
Dropzone as PreactDropzone,
|
Dropzone as PreactDropzone,
|
||||||
} from '@uppy/components'
|
} from '@uppy/components'
|
||||||
import { h as preactH, render as preactRender } from 'preact'
|
import { h as preactH, render as preactRender } from 'preact'
|
||||||
import { shallowEqualObjects } from 'shallow-equal'
|
|
||||||
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
||||||
import { useUppyContext } from '../useUppyContext.js'
|
import { useUppyContext } from '../useUppyContext.js'
|
||||||
|
|
||||||
export default defineComponent<Omit<DropzoneProps, 'ctx'>>({
|
export default defineComponent({
|
||||||
name: 'Dropzone',
|
name: 'Dropzone',
|
||||||
setup(props, { attrs }) {
|
props: ['width', 'height', 'note', 'noClick'],
|
||||||
|
setup(props) {
|
||||||
const containerRef = ref<HTMLElement | null>(null)
|
const containerRef = ref<HTMLElement | null>(null)
|
||||||
const ctx = useUppyContext()
|
const ctx = useUppyContext()
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ export default defineComponent<Omit<DropzoneProps, 'ctx'>>({
|
||||||
if (containerRef.value) {
|
if (containerRef.value) {
|
||||||
preactRender(
|
preactRender(
|
||||||
preactH(PreactDropzone, {
|
preactH(PreactDropzone, {
|
||||||
...(attrs as DropzoneProps),
|
...props,
|
||||||
ctx,
|
ctx,
|
||||||
} satisfies DropzoneProps),
|
} satisfies DropzoneProps),
|
||||||
containerRef.value,
|
containerRef.value,
|
||||||
|
|
@ -38,11 +38,10 @@ export default defineComponent<Omit<DropzoneProps, 'ctx'>>({
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props,
|
() => props,
|
||||||
(current, old) => {
|
() => {
|
||||||
if (!shallowEqualObjects(current, old)) {
|
renderDropzone()
|
||||||
renderDropzone()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => h('div', { ref: containerRef })
|
return () => h('div', { ref: containerRef })
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import {
|
||||||
FilesGrid as PreactFilesGrid,
|
FilesGrid as PreactFilesGrid,
|
||||||
} from '@uppy/components'
|
} from '@uppy/components'
|
||||||
import { h as preactH, render as preactRender } from 'preact'
|
import { h as preactH, render as preactRender } from 'preact'
|
||||||
import { shallowEqualObjects } from 'shallow-equal'
|
|
||||||
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
||||||
import { useUppyContext } from '../useUppyContext.js'
|
import { useUppyContext } from '../useUppyContext.js'
|
||||||
|
|
||||||
export default defineComponent<Omit<FilesGridProps, 'ctx'>>({
|
export default defineComponent({
|
||||||
name: 'FilesGrid',
|
name: 'FilesGrid',
|
||||||
setup(props, { attrs }) {
|
props: ['editFile', 'columns', 'imageThumbnail'],
|
||||||
|
setup(props) {
|
||||||
const containerRef = ref<HTMLElement | null>(null)
|
const containerRef = ref<HTMLElement | null>(null)
|
||||||
const ctx = useUppyContext()
|
const ctx = useUppyContext()
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ export default defineComponent<Omit<FilesGridProps, 'ctx'>>({
|
||||||
if (containerRef.value) {
|
if (containerRef.value) {
|
||||||
preactRender(
|
preactRender(
|
||||||
preactH(PreactFilesGrid, {
|
preactH(PreactFilesGrid, {
|
||||||
...(attrs as FilesGridProps),
|
...props,
|
||||||
ctx,
|
ctx,
|
||||||
} satisfies FilesGridProps),
|
} satisfies FilesGridProps),
|
||||||
containerRef.value,
|
containerRef.value,
|
||||||
|
|
@ -38,11 +38,10 @@ export default defineComponent<Omit<FilesGridProps, 'ctx'>>({
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props,
|
() => props,
|
||||||
(current, old) => {
|
() => {
|
||||||
if (!shallowEqualObjects(current, old)) {
|
renderFilesGrid()
|
||||||
renderFilesGrid()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => h('div', { ref: containerRef })
|
return () => h('div', { ref: containerRef })
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import {
|
||||||
FilesList as PreactFilesList,
|
FilesList as PreactFilesList,
|
||||||
} from '@uppy/components'
|
} from '@uppy/components'
|
||||||
import { h as preactH, render as preactRender } from 'preact'
|
import { h as preactH, render as preactRender } from 'preact'
|
||||||
import { shallowEqualObjects } from 'shallow-equal'
|
|
||||||
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
||||||
import { useUppyContext } from '../useUppyContext.js'
|
import { useUppyContext } from '../useUppyContext.js'
|
||||||
|
|
||||||
export default defineComponent<Omit<FilesListProps, 'ctx'>>({
|
export default defineComponent({
|
||||||
name: 'FilesList',
|
name: 'FilesList',
|
||||||
setup(props, { attrs }) {
|
props: ['editFile', 'imageThumbnail'],
|
||||||
|
setup(props) {
|
||||||
const containerRef = ref<HTMLElement | null>(null)
|
const containerRef = ref<HTMLElement | null>(null)
|
||||||
const ctx = useUppyContext()
|
const ctx = useUppyContext()
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ export default defineComponent<Omit<FilesListProps, 'ctx'>>({
|
||||||
if (containerRef.value) {
|
if (containerRef.value) {
|
||||||
preactRender(
|
preactRender(
|
||||||
preactH(PreactFilesList, {
|
preactH(PreactFilesList, {
|
||||||
...(attrs as FilesListProps),
|
...props,
|
||||||
ctx,
|
ctx,
|
||||||
} satisfies FilesListProps),
|
} satisfies FilesListProps),
|
||||||
containerRef.value,
|
containerRef.value,
|
||||||
|
|
@ -38,11 +38,10 @@ export default defineComponent<Omit<FilesListProps, 'ctx'>>({
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props,
|
() => props,
|
||||||
(current, old) => {
|
() => {
|
||||||
if (!shallowEqualObjects(current, old)) {
|
renderFilesList()
|
||||||
renderFilesList()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => h('div', { ref: containerRef })
|
return () => h('div', { ref: containerRef })
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import {
|
||||||
type ProviderIconProps,
|
type ProviderIconProps,
|
||||||
} from '@uppy/components'
|
} from '@uppy/components'
|
||||||
import { h as preactH, render as preactRender } from 'preact'
|
import { h as preactH, render as preactRender } from 'preact'
|
||||||
import { shallowEqualObjects } from 'shallow-equal'
|
|
||||||
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
||||||
import { useUppyContext } from '../useUppyContext.js'
|
import { useUppyContext } from '../useUppyContext.js'
|
||||||
|
|
||||||
export default defineComponent<Omit<ProviderIconProps, 'ctx'>>({
|
export default defineComponent({
|
||||||
name: 'ProviderIcon',
|
name: 'ProviderIcon',
|
||||||
setup(props, { attrs }) {
|
props: ['provider', 'fill'],
|
||||||
|
setup(props) {
|
||||||
const containerRef = ref<HTMLElement | null>(null)
|
const containerRef = ref<HTMLElement | null>(null)
|
||||||
const ctx = useUppyContext()
|
const ctx = useUppyContext()
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ export default defineComponent<Omit<ProviderIconProps, 'ctx'>>({
|
||||||
if (containerRef.value) {
|
if (containerRef.value) {
|
||||||
preactRender(
|
preactRender(
|
||||||
preactH(PreactProviderIcon, {
|
preactH(PreactProviderIcon, {
|
||||||
...(attrs as ProviderIconProps),
|
...props,
|
||||||
ctx,
|
ctx,
|
||||||
} satisfies ProviderIconProps),
|
} satisfies ProviderIconProps),
|
||||||
containerRef.value,
|
containerRef.value,
|
||||||
|
|
@ -38,11 +38,10 @@ export default defineComponent<Omit<ProviderIconProps, 'ctx'>>({
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props,
|
() => props,
|
||||||
(current, old) => {
|
() => {
|
||||||
if (!shallowEqualObjects(current, old)) {
|
renderProviderIcon()
|
||||||
renderProviderIcon()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => h('div', { ref: containerRef })
|
return () => h('div', { ref: containerRef })
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import {
|
||||||
type ThumbnailProps,
|
type ThumbnailProps,
|
||||||
} from '@uppy/components'
|
} from '@uppy/components'
|
||||||
import { h as preactH, render as preactRender } from 'preact'
|
import { h as preactH, render as preactRender } from 'preact'
|
||||||
import { shallowEqualObjects } from 'shallow-equal'
|
|
||||||
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
||||||
import { useUppyContext } from '../useUppyContext.js'
|
import { useUppyContext } from '../useUppyContext.js'
|
||||||
|
|
||||||
export default defineComponent<Omit<ThumbnailProps, 'ctx'>>({
|
export default defineComponent({
|
||||||
name: 'Thumbnail',
|
name: 'Thumbnail',
|
||||||
setup(props, { attrs }) {
|
props: ['file', 'width', 'height', 'images'],
|
||||||
|
setup(props) {
|
||||||
const containerRef = ref<HTMLElement | null>(null)
|
const containerRef = ref<HTMLElement | null>(null)
|
||||||
const ctx = useUppyContext()
|
const ctx = useUppyContext()
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ export default defineComponent<Omit<ThumbnailProps, 'ctx'>>({
|
||||||
if (containerRef.value) {
|
if (containerRef.value) {
|
||||||
preactRender(
|
preactRender(
|
||||||
preactH(PreactThumbnail, {
|
preactH(PreactThumbnail, {
|
||||||
...(attrs as ThumbnailProps),
|
...props,
|
||||||
ctx,
|
ctx,
|
||||||
} satisfies ThumbnailProps),
|
} satisfies ThumbnailProps),
|
||||||
containerRef.value,
|
containerRef.value,
|
||||||
|
|
@ -38,11 +38,10 @@ export default defineComponent<Omit<ThumbnailProps, 'ctx'>>({
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props,
|
() => props,
|
||||||
(current, old) => {
|
() => {
|
||||||
if (!shallowEqualObjects(current, old)) {
|
renderThumbnail()
|
||||||
renderThumbnail()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => h('div', { ref: containerRef })
|
return () => h('div', { ref: containerRef })
|
||||||
|
|
|
||||||
|
|
@ -6,13 +6,13 @@ import {
|
||||||
type UploadButtonProps,
|
type UploadButtonProps,
|
||||||
} from '@uppy/components'
|
} from '@uppy/components'
|
||||||
import { h as preactH, render as preactRender } from 'preact'
|
import { h as preactH, render as preactRender } from 'preact'
|
||||||
import { shallowEqualObjects } from 'shallow-equal'
|
|
||||||
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
import { defineComponent, h, onMounted, ref, watch } from 'vue'
|
||||||
import { useUppyContext } from '../useUppyContext.js'
|
import { useUppyContext } from '../useUppyContext.js'
|
||||||
|
|
||||||
export default defineComponent<Omit<UploadButtonProps, 'ctx'>>({
|
export default defineComponent({
|
||||||
name: 'UploadButton',
|
name: 'UploadButton',
|
||||||
setup(props, { attrs }) {
|
props: [],
|
||||||
|
setup(props) {
|
||||||
const containerRef = ref<HTMLElement | null>(null)
|
const containerRef = ref<HTMLElement | null>(null)
|
||||||
const ctx = useUppyContext()
|
const ctx = useUppyContext()
|
||||||
|
|
||||||
|
|
@ -20,7 +20,7 @@ export default defineComponent<Omit<UploadButtonProps, 'ctx'>>({
|
||||||
if (containerRef.value) {
|
if (containerRef.value) {
|
||||||
preactRender(
|
preactRender(
|
||||||
preactH(PreactUploadButton, {
|
preactH(PreactUploadButton, {
|
||||||
...(attrs as UploadButtonProps),
|
...props,
|
||||||
ctx,
|
ctx,
|
||||||
} satisfies UploadButtonProps),
|
} satisfies UploadButtonProps),
|
||||||
containerRef.value,
|
containerRef.value,
|
||||||
|
|
@ -38,11 +38,10 @@ export default defineComponent<Omit<UploadButtonProps, 'ctx'>>({
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props,
|
() => props,
|
||||||
(current, old) => {
|
() => {
|
||||||
if (!shallowEqualObjects(current, old)) {
|
renderUploadButton()
|
||||||
renderUploadButton()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
{ deep: true },
|
||||||
)
|
)
|
||||||
|
|
||||||
return () => h('div', { ref: containerRef })
|
return () => h('div', { ref: containerRef })
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue