Skip to content

Instantly share code, notes, and snippets.

@nurdism
Created February 5, 2023 08:34
Show Gist options
  • Save nurdism/cd162c5413de7f38d939ff4cba308b4e to your computer and use it in GitHub Desktop.
Save nurdism/cd162c5413de7f38d939ff4cba308b4e to your computer and use it in GitHub Desktop.
example of how a reactive might be used for the page obejct
import type { UnwrapNestedRefs } from 'vue'
import { createHeadManager, Page, PageProps, router } from '@inertiajs/core'
import { DefineComponent, defineComponent, h, markRaw, Plugin, PropType, ref, reactive, shallowRef } from 'vue'
import remember from './remember'
import { VuePageHandlerArgs } from './types'
import useForm from './useForm'
export interface InertiaAppProps {
initialPage: Page
initialComponent?: object
resolveComponent?: (name: string) => DefineComponent | Promise<DefineComponent>
titleCallback?: (title: string) => string
onHeadUpdate?: (elements: string[]) => void
}
export type InertiaApp = DefineComponent<InertiaAppProps>
const component = ref(null)
const page = reactive<Page<any>>({
component: '',
props: null,
url: '',
version: null,
scrollRegions: [],
rememberedState: {},
resolvedErrors: {}
})
const layout = shallowRef(null)
const key = ref(null)
let headManager = null
const App: InertiaApp = defineComponent({
name: 'Inertia',
props: {
initialPage: {
type: Object as PropType<Page>,
required: true,
},
initialComponent: {
type: Object,
required: false,
},
resolveComponent: {
type: Function as PropType<(name: string) => DefineComponent | Promise<DefineComponent>>,
required: false,
},
titleCallback: {
type: Function as PropType<(title: string) => string>,
required: false,
default: (title) => title,
},
onHeadUpdate: {
type: Function as PropType<(elements: string[]) => void>,
required: false,
default: () => () => {},
},
},
setup({ initialPage, initialComponent, resolveComponent, titleCallback, onHeadUpdate }) {
component.value = initialComponent ? markRaw(initialComponent) : null
Object.assign(page, initialPage)
key.value = null
const isServer = typeof window === 'undefined'
headManager = createHeadManager(isServer, titleCallback, onHeadUpdate)
if (!isServer) {
router.init({
initialPage,
resolveComponent,
swapComponent: async (args: VuePageHandlerArgs) => {
component.value = markRaw(args.component)
Object.assign(page, args.page)
key.value = args.preserveState ? key.value : Date.now()
},
})
router.on('navigate', () => headManager.forceUpdate())
}
return () => {
if (component.value) {
component.value.inheritAttrs = !!component.value.inheritAttrs
const child = h(component.value, {
...page.props,
key: key.value,
})
if (layout.value) {
component.value.layout = layout.value
layout.value = null
}
if (component.value.layout) {
if (typeof component.value.layout === 'function') {
return component.value.layout(h, child)
}
return (Array.isArray(component.value.layout) ? component.value.layout : [component.value.layout])
.concat(child)
.reverse()
.reduce((child, layout) => {
layout.inheritAttrs = !!layout.inheritAttrs
return h(layout, { ...page.props }, () => child)
})
}
return child
}
}
},
})
export default App
export const plugin: Plugin = {
install(app) {
router.form = useForm
Object.defineProperty(app.config.globalProperties, '$inertia', { get: () => router })
Object.defineProperty(app.config.globalProperties, '$page', { get: () => page })
Object.defineProperty(app.config.globalProperties, '$headManager', { get: () => headManager })
app.mixin(remember)
},
}
export function usePage<SharedProps extends PageProps>(): UnwrapNestedRefs<Page<SharedProps>> {
return page
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment