Skip to content

Commit

Permalink
fix(createReusableTemplate): camelize props (#3253)
Browse files Browse the repository at this point in the history
Co-authored-by: Anthony Fu <anthonyfu117@hotmail.com>
Co-authored-by: Kasper Seweryn <github@wvffle.net>
  • Loading branch information
3 people committed Jul 30, 2023
1 parent d0fd3f0 commit d79e174
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 4 deletions.
17 changes: 17 additions & 0 deletions packages/core/createReusableTemplate/index.test.ts
Expand Up @@ -80,4 +80,21 @@ describe.skipIf(isVue2)('createReusableTemplate', () => {

expect(wrapper.text()).toBe('GoodbyeHi')
})

it('hyphen props', () => {
const [DefineFoo, ReuseFoo] = createReusableTemplate<{ myMsg: string }>()

const wrapper = mount({
render() {
return h(Fragment, null, [
h(DefineFoo, ({ $slots, ...args }: any) => h('pre', JSON.stringify(args))),
h(ReuseFoo, { myMsg: 'Foo' }),
// @ts-expect-error Vue automatically converts hyphenized props to camelCase
h(ReuseFoo, { 'my-msg': 'Bar' }),
])
},
})

expect(wrapper.text()).toBe('{"myMsg":"Foo"}{"myMsg":"Bar"}')
})
})
14 changes: 10 additions & 4 deletions packages/core/createReusableTemplate/index.ts
@@ -1,6 +1,6 @@
import type { DefineComponent, Slot } from 'vue-demi'
import { defineComponent, isVue3, shallowRef, version } from 'vue-demi'
import { makeDestructurable } from '@vueuse/shared'
import { camelize, makeDestructurable } from '@vueuse/shared'

export type DefineTemplateComponent<
Bindings extends object,
Expand Down Expand Up @@ -34,8 +34,7 @@ export type ReusableTemplatePair<
* @see https://vueuse.org/createReusableTemplate
*/
export function createReusableTemplate<
Bindings extends object,
Slots extends Record<string, Slot | undefined> = Record<string, Slot | undefined>,
Bindings extends object, Slots extends Record<string, Slot | undefined> = Record<string, Slot | undefined>,
>(): ReusableTemplatePair<Bindings, Slots> {
// compatibility: Vue 2.7 or above
if (!isVue3 && !version.startsWith('2.7.')) {
Expand All @@ -61,7 +60,7 @@ export function createReusableTemplate<
return () => {
if (!render.value && process.env.NODE_ENV !== 'production')
throw new Error('[VueUse] Failed to find the definition of reusable template')
return render.value?.({ ...attrs, $slots: slots })
return render.value?.({ ...keysToCamelKebabCase(attrs), $slots: slots })
}
},
}) as ReuseTemplateComponent<Bindings, Slots>
Expand All @@ -71,3 +70,10 @@ export function createReusableTemplate<
[define, reuse],
) as any
}

function keysToCamelKebabCase(obj: Record<string, any>) {
const newObj: typeof obj = {}
for (const key in obj)
newObj[camelize(key)] = obj[key]
return newObj
}
1 change: 1 addition & 0 deletions packages/shared/utils/index.ts
Expand Up @@ -2,6 +2,7 @@ export * from './is'
export * from './filters'
export * from './types'
export * from './compatibility'
export * from './port'

export function promiseTimeout(
ms: number,
Expand Down
18 changes: 18 additions & 0 deletions packages/shared/utils/port.ts
@@ -0,0 +1,18 @@
// copied from vue: https://github.com/vuejs/core/blob/3be4e3cbe34b394096210897c1be8deeb6d748d8/packages/shared/src/general.ts#L90-L112
function cacheStringFunction<T extends (str: string) => string>(fn: T): T {
const cache: Record<string, string> = Object.create(null)
return ((str: string) => {
const hit = cache[str]
return hit || (cache[str] = fn(str))
}) as T
}

const hyphenateRE = /\B([A-Z])/g
export const hyphenate = cacheStringFunction((str: string) =>
str.replace(hyphenateRE, '-$1').toLowerCase(),
)

const camelizeRE = /-(\w)/g
export const camelize = cacheStringFunction((str: string): string => {
return str.replace(camelizeRE, (_, c) => (c ? c.toUpperCase() : ''))
})
7 changes: 7 additions & 0 deletions playgrounds/nuxt/package.json
Expand Up @@ -13,5 +13,12 @@
"@vueuse/nuxt": "file:../../packages/nuxt/dist",
"@vueuse/shared": "file:../../packages/shared/dist",
"nuxt": "^3.6.5"
},
"resolutions": {
"@vueuse/core": "file:../../packages/core/dist",
"@vueuse/integrations": "file:../../packages/integrations/dist",
"@vueuse/metadata": "file:../../packages/metadata/dist",
"@vueuse/nuxt": "file:../../packages/nuxt/dist",
"@vueuse/shared": "file:../../packages/shared/dist"
}
}
5 changes: 5 additions & 0 deletions playgrounds/vite-vue2.7/package.json
Expand Up @@ -15,5 +15,10 @@
"eslint": "^8.45.0",
"vite": "^4.4.7",
"vue": "^2.7.14"
},
"resolutions": {
"@vueuse/core": "file:../../packages/core/dist",
"@vueuse/metadata": "file:../../packages/metadata/dist",
"@vueuse/shared": "file:../../packages/shared/dist"
}
}
5 changes: 5 additions & 0 deletions playgrounds/vite/package.json
Expand Up @@ -14,5 +14,10 @@
"@vueuse/metadata": "file:../../packages/metadata/dist",
"@vueuse/shared": "file:../../packages/shared/dist",
"vite": "^4.4.7"
},
"resolutions": {
"@vueuse/core": "file:../../packages/core/dist",
"@vueuse/metadata": "file:../../packages/metadata/dist",
"@vueuse/shared": "file:../../packages/shared/dist"
}
}

0 comments on commit d79e174

Please sign in to comment.