Assess, plan, evolve.
Reusable compiler-aware skills that help coding agents understand, plan, and safely evolve your codebase.
7 packages
In Vue 3.x, h is now globally imported instead of being automatically passed as an argument. This codemod migrates the render function API to be compatible with Vue 3.x. ## Before ```ts export default { render(h) { return h("div"); }, }; ``` ## After ```ts import { h } from "vue"; export default { render() { return h("div"); }, }; ```
- vue
## Example This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { data: () => ({ message: 'Hello' }), }; ``` ### After ```ts const message = ref('Hello'); export default {}; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { data: () => ({ isActive: true }), }; ``` ### After ```ts const isActive = ref(true); export default {}; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { data: () => ({ items: [1, 2, 3] }), }; ``` ### After ```ts const items = ref([1, 2, 3]); export default {}; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { data: () => ({ count: 0, message: 'Hello', isActive: true, items: [1, 2, 3], }), }; ``` ### After ```ts const items = ref([1, 2, 3]); const isActive = ref(true); const message = ref('Hello'); const count = ref(0); export default {}; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { methods: { displayCoucou: function() { // the content isn't relevant console.log('coucou'); }, }, }; ``` ### After ```ts export default { methods: { displayCoucou: function() { // the content isn't relevant console.log('coucou'); }, }, }; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts // convert vue2 script component into vue 3 setup export default { methods: { fetchApi: async function() { const request = await fetch('/request/info'); }, }, }; ``` ### After ```ts // convert vue2 script component into vue 3 setup export default { methods: { fetchApi: async function() { const request = await fetch('/request/info'); }, }, }; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts export default { data: () => ({ count: 0 }), methods: { increment: function() { this.count += 1; }, }, }; ``` ### After ```ts const count = ref(0); export default { methods: { increment: function() { this.count += 1; }, }, }; ``` ,This codemod turns X into Y. It also does Z. Note: this is a contrived example. Please modify it. ### Before ```ts export default { data: () => ({ count: 0 }), methods: { increment: async function() { this.count = await (await fetch('/request')).json(); }, }, }; ``` ### After ```ts import { ref } from 'vue'; const count = ref(0); export default { data: () => ({ count: 0 }), methods: { increment: async function() { this.count = await (await fetch('/request')).json(); }, }, }; ```
- vue
- 3
- +1
When using `NavigationMenuLink` together with `NuxtLink` according to the documentation the menu does not dismiss when clicking on a link. ## Example ### Before ```ts < script lang = "ts" > import type { PrimitiveProps } from '@/Primitive' import { useForwardExpose } from '@/shared' export type NavigationMenuLinkEmits = { /** * Event handler called when the user selects a link (via mouse or keyboard). * * Calling `event.preventDefault` in this handler will prevent the navigation menu from closing when selecting that link. */ select: [payload: MouseEvent] } export interface NavigationMenuLinkProps extends PrimitiveProps { /** Used to identify the link as the currently active page. */ active ? : boolean } < /script> < script setup lang = "ts" > import { nextTick } from 'vue' import { Primitive } from '@/Primitive' import { EVENT_ROOT_CONTENT_DISMISS } from './utils' // const LINK_SELECT = "navigationMenu.linkSelect"; const props = withDefaults(defineProps < NavigationMenuLinkProps > (), { as: 'a', }) const emits = defineEmits < NavigationMenuLinkEmits > () useForwardExpose() async function handleClick(ev: MouseEvent) { emits('select', linkSelectEvent) await nextTick() if (!ev.defaultPrevented && !ev.metaKey) { const rootContentDismissEvent = new CustomEvent( EVENT_ROOT_CONTENT_DISMISS, { bubbles: true, cancelable: true, }, ) ev.target?.dispatchEvent(rootContentDismissEvent) } } < /script> < template > < Primitive: as = "as": data - active = "active ? '' : undefined": aria - current = "active ? 'page' : undefined": as - child = "props.asChild" data - radix - vue - collection - item @click = "handleClick" > < slot / > < /Primitive> < /template> ``` ### After ```ts < script lang = "ts" > import type { PrimitiveProps } from '@/Primitive' import { useForwardExpose } from '@/shared' export type NavigationMenuLinkEmits = { /** * Event handler called when the user selects a link (via mouse or keyboard). * * Calling `event.preventDefault` in this handler will prevent the navigation menu from closing when selecting that link. */ select: [payload: CustomEvent < { originalEvent: Event } > ] } export interface NavigationMenuLinkProps extends PrimitiveProps { /** Used to identify the link as the currently active page. */ active ? : boolean } < /script> < script setup lang = "ts" > import { Primitive } from '@/Primitive' import { EVENT_ROOT_CONTENT_DISMISS, LINK_SELECT } from './utils' const props = withDefaults(defineProps < NavigationMenuLinkProps > (), { as: 'a', }) const emits = defineEmits < NavigationMenuLinkEmits > () useForwardExpose() async function handleClick(ev: MouseEvent) { const linkSelectEvent = new CustomEvent(LINK_SELECT, { bubbles: true, cancelable: true, detail: { originalEvent: ev, }, }) emits('select', linkSelectEvent) if (!linkSelectEvent.defaultPrevented && !ev.metaKey) { const rootContentDismissEvent = new CustomEvent( EVENT_ROOT_CONTENT_DISMISS, { bubbles: true, cancelable: true, }, ) ev.target?.dispatchEvent(rootContentDismissEvent) } } < /script> < template > < Primitive: as = "as": data - active = "active ? '' : undefined": aria - current = "active ? 'page' : undefined": as - child = "props.asChild" data - radix - vue - collection - item @click = "handleClick" > < slot / > < /Primitive> < /template> ```
- radix
- vue
- +5
When floating-ui returned isPositioned=true, radix-vue immediately emitted an event to focus on the selected item in the Select component. However, at this point, the PopperContent element did not yet have the correct transform CSS property set, resulting in the Popper being positioned at coordinates (0, -200%). Credits to the contributor ## Example ### Before ```ts import { watchEffect } from 'vue'; watchEffect(() => {}); ``` ### After ```ts import { watchPostEffect } from 'vue'; watchPostEffect(() => {}); ```
- radix
- vue
- +4
Recalculates tabs indicator position on direction change in the Tab Component ## Example ### Before ```ts watch( () => context.modelValue.value, async (n) => { await nextTick(); updateIndicatorStyle(); }, { immediate: true }, ); ``` ### After ```ts watch( () => [context.modelValue.value, context?.dir.value], async () => { await nextTick(); updateIndicatorStyle(); }, { immediate: true }, ); ```
- radix
- vue
- +4
This codemod transforms the `data` object returned from `useAsyncData`, `useFetch`, `useLazyAsyncData` and `useLazyFetch` into a `shallowRef` When new data is fetched, anything depending on `data` will still be reactive because the entire object is replaced. But if your code changes a property within that data structure, this will not trigger any reactivity in your app. This brings a significant performance improvement for deeply nested objects and arrays because Vue does not need to watch every single property/array for modification. In most cases, data should also be immutable. ## Before ```jsx const { data } = useFetch("/api/test"); ``` > This can apply to all useAsyncData, useFetch, useLazyAsyncData and useLazyFetch. ## After ```jsx const { data } = useFetch("/api/test", { deep: true }); ``` ### Additional Feature This codemod ensures that any unique key of your data is always resolvable to the same data. For example, if you are using `useAsyncData` to fetch data related to a particular page, it should be changed to a key that uniquely matches that data. (`useFetch` should do this automatically for you.) ### Example Code before transformation: ```jsx const route = useRoute(); const { data } = await useAsyncData(async () => { return await $fetch(`/api/my-page/${route.params.slug}`); }); ``` Code after transformation: ```jsx const route = useRoute(); const { data } = await useAsyncData(route.params.slug, async () => { return await $fetch(`/api/my-page/${route.params.slug}`), { deep: true }; }); ```
- nuxt
- 4
- +1
The primary change in imports is replacing radix-vue with reka-ui. ### Before ```ts import { TooltipPortal, TooltipRoot, TooltipTrigger } from 'radix-vue'; ``` ### After ```ts import { TooltipPortal, TooltipRoot, TooltipTrigger } from 'reka-ui'; ```
- vue
- radix
- +2
Build your own codemod!
Describe the migration you need and Codemod Agent will create a codemod for you.
Ready to evolve your codebase?
Build tailored, compiler-aware skills to assess, plan, and automate complex codebase changes.