Skip to content

Fix various TypeScript issues, simplify ziggy-js integration and shared props usage #127

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
1,354 changes: 735 additions & 619 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"concurrently": "^9.0.1",
"laravel-vite-plugin": "^1.0",
"laravel-vite-plugin": "^1.2",
"lucide": "^0.468.0",
"lucide-vue-next": "^0.468.0",
"reka-ui": "^2.2.0",
"tailwind-merge": "^3.2.0",
"tailwindcss": "^4.1.1",
"tw-animate-css": "^1.2.5",
"typescript": "^5.2.2",
"vite": "^6.2.0",
"vite": "^6.3.0",
"vue": "^3.5.13",
"ziggy-js": "^2.4.2"
},
Expand Down
13 changes: 0 additions & 13 deletions resources/js/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,6 @@ import { createApp, h } from 'vue';
import { ZiggyVue } from 'ziggy-js';
import { initializeTheme } from './composables/useAppearance';

// Extend ImportMeta interface for Vite...
declare module 'vite/client' {
interface ImportMetaEnv {
readonly VITE_APP_NAME: string;
[key: string]: string | boolean | undefined;
}

interface ImportMeta {
readonly env: ImportMetaEnv;
readonly glob: <T>(pattern: string) => Record<string, () => Promise<T>>;
}
}

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

createInertiaApp({
Expand Down
4 changes: 1 addition & 3 deletions resources/js/components/AppShell.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
<script setup lang="ts">
import { SidebarProvider } from '@/components/ui/sidebar';
import { usePage } from '@inertiajs/vue3';
import { SharedData } from '@/types';

interface Props {
variant?: 'header' | 'sidebar';
}

defineProps<Props>();

const isOpen = usePage<SharedData>().props.sidebarOpen;
const isOpen = usePage().props.sidebarOpen;
</script>

<template>
Expand Down
6 changes: 3 additions & 3 deletions resources/js/components/NavMain.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<script setup lang="ts">
import { SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar';
import { type NavItem, type SharedData } from '@/types';
import { type NavItem } from '@/types';
import { Link, usePage } from '@inertiajs/vue3';

defineProps<{
items: NavItem[];
}>();

const page = usePage<SharedData>();
const page = usePage();
</script>

<template>
<SidebarGroup class="px-2 py-0">
<SidebarGroupLabel>Platform</SidebarGroupLabel>
<SidebarMenu>
<SidebarMenuItem v-for="item in items" :key="item.title">
<SidebarMenuButton
<SidebarMenuButton
as-child :is-active="item.href === page.url"
:tooltip="item.title"
>
Expand Down
8 changes: 4 additions & 4 deletions resources/js/components/NavUser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import UserInfo from '@/components/UserInfo.vue';
import { DropdownMenu, DropdownMenuContent, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
import { SidebarMenu, SidebarMenuButton, SidebarMenuItem, useSidebar } from '@/components/ui/sidebar';
import { type SharedData, type User } from '@/types';
import { type User } from '@/types';
import { usePage } from '@inertiajs/vue3';
import { ChevronsUpDown } from 'lucide-vue-next';
import UserMenuContent from './UserMenuContent.vue';

const page = usePage<SharedData>();
const page = usePage();
const user = page.props.auth.user as User;
const { isMobile, state } = useSidebar();
</script>
Expand All @@ -22,10 +22,10 @@ const { isMobile, state } = useSidebar();
<ChevronsUpDown class="ml-auto size-4" />
</SidebarMenuButton>
</DropdownMenuTrigger>
<DropdownMenuContent
<DropdownMenuContent
class="w-(--reka-dropdown-menu-trigger-width) min-w-56 rounded-lg"
:side="isMobile ? 'bottom' : state === 'collapsed' ? 'left' : 'bottom'"
align="end"
align="end"
:side-offset="4"
>
<UserMenuContent :user="user" />
Expand Down
2 changes: 1 addition & 1 deletion resources/js/components/UserInfo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const showAvatar = computed(() => props.user.avatar && props.user.avatar !== '')

<template>
<Avatar class="h-8 w-8 overflow-hidden rounded-lg">
<AvatarImage v-if="showAvatar" :src="user.avatar" :alt="user.name" />
<AvatarImage v-if="showAvatar" :src="user.avatar!" :alt="user.name" />
<AvatarFallback class="rounded-lg text-black dark:text-white">
{{ getInitials(user.name) }}
</AvatarFallback>
Expand Down
2 changes: 1 addition & 1 deletion resources/js/pages/Welcome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ import { Head, Link } from '@inertiajs/vue3';
/>
</g>
<g
:style="{ mixBlendMode: 'plus-darker' }"
:style="`mixBlendMode: 'plus-darker'`"
class="duration-750 starting:translate-y-4 starting:opacity-0 translate-y-0 opacity-100 transition-all delay-300"
>
<path
Expand Down
4 changes: 2 additions & 2 deletions resources/js/pages/settings/Profile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import AppLayout from '@/layouts/AppLayout.vue';
import SettingsLayout from '@/layouts/settings/Layout.vue';
import { type BreadcrumbItem, type SharedData, type User } from '@/types';
import { type BreadcrumbItem, type User } from '@/types';

interface Props {
mustVerifyEmail: boolean;
Expand All @@ -25,7 +25,7 @@ const breadcrumbs: BreadcrumbItem[] = [
},
];

const page = usePage<SharedData>();
const page = usePage();
const user = page.props.auth.user as User;

const form = useForm({
Expand Down
44 changes: 17 additions & 27 deletions resources/js/ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { createInertiaApp } from '@inertiajs/vue3';
import createServer from '@inertiajs/vue3/server';
import { renderToString } from '@vue/server-renderer';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createSSRApp, h } from 'vue';
import { route as ziggyRoute } from 'ziggy-js';
import { createSSRApp, DefineComponent, h } from 'vue';
import { ZiggyVue } from 'ziggy-js';

const appName = import.meta.env.VITE_APP_NAME || 'Laravel';

Expand All @@ -12,30 +12,20 @@ createServer((page) =>
page,
render: renderToString,
title: (title) => `${title} - ${appName}`,
resolve: (name) => resolvePageComponent(`./pages/${name}.vue`, import.meta.glob('./pages/**/*.vue')),
setup({ App, props, plugin }) {
const app = createSSRApp({ render: () => h(App, props) });

// Configure Ziggy for SSR...
const ziggyConfig = {
...page.props.ziggy,
location: new URL(page.props.ziggy.location),
};

// Create route function...
const route = (name: string, params?: any, absolute?: boolean) => ziggyRoute(name, params, absolute, ziggyConfig);

// Make route function available globally...
app.config.globalProperties.route = route;

// Make route function available globally for SSR...
if (typeof window === 'undefined') {
global.route = route;
}

app.use(plugin);

return app;
},
resolve: resolvePage,
setup: ({ App, props, plugin }) =>
createSSRApp({ render: () => h(App, props) })
.use(plugin)
.use(ZiggyVue, {
...page.props.ziggy,
location: new URL(page.props.ziggy.location),
}),
}),
{ cluster: true },
);

function resolvePage(name: string) {
const pages = import.meta.glob<DefineComponent>('./pages/**/*.vue');

return resolvePageComponent<DefineComponent>(`./pages/${name}.vue`, pages);
}
27 changes: 24 additions & 3 deletions resources/js/types/globals.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
import type { route as routeFn } from 'ziggy-js';
import { AppPageProps } from '@/types/index';

declare global {
const route: typeof routeFn;
// Extend ImportMeta interface for Vite...
declare module 'vite/client' {
interface ImportMetaEnv {
readonly VITE_APP_NAME: string;
[key: string]: string | boolean | undefined;
}

interface ImportMeta {
readonly env: ImportMetaEnv;
readonly glob: <T>(pattern: string) => Record<string, () => Promise<T>>;
}
}

declare module '@inertiajs/core' {
interface PageProps extends InertiaPageProps, AppPageProps {}
}

declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$inertia: typeof Router;
$page: Page;
$headManager: ReturnType<typeof createHeadManager>;
}
}
5 changes: 2 additions & 3 deletions resources/js/types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import type { PageProps } from '@inertiajs/core';
import type { LucideIcon } from 'lucide-vue-next';
import type { Config } from 'ziggy-js';

Expand All @@ -18,13 +17,13 @@ export interface NavItem {
isActive?: boolean;
}

export interface SharedData extends PageProps {
export type AppPageProps<T extends Record<string, unknown> = Record<string, unknown>> = T & {
name: string;
quote: { message: string; author: string };
auth: Auth;
ziggy: Config & { location: string };
sidebarOpen: boolean;
}
};

export interface User {
id: number;
Expand Down
5 changes: 2 additions & 3 deletions resources/js/types/ziggy.d.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { RouteParams, Router } from 'ziggy-js';
import { route } from 'ziggy-js';

declare global {
function route(): Router;
function route(name: string, params?: RouteParams<typeof name> | undefined, absolute?: boolean): string;
let route: typeof route;
}

declare module '@vue/runtime-core' {
Expand Down
2 changes: 0 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,11 @@
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
"paths": {
/* Specify a set of entries that re-map imports to additional lookup locations. */ "@/*": ["./resources/js/*"],
"ziggy-js": ["./vendor/tightenco/ziggy"]
},
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
"types": [
"vite/client",
"vue/tsx",
"./resources/js/types"
] /* Specify type package names to be included without being referenced in a source file. */,
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
Expand Down
4 changes: 1 addition & 3 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import vue from '@vitejs/plugin-vue';
import laravel from 'laravel-vite-plugin';
import path from 'path';
import tailwindcss from "@tailwindcss/vite";
import { resolve } from 'node:path';
import tailwindcss from '@tailwindcss/vite';
import { defineConfig } from 'vite';

export default defineConfig({
Expand All @@ -25,7 +24,6 @@ export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, './resources/js'),
'ziggy-js': resolve(__dirname, 'vendor/tightenco/ziggy'),
},
},
});