Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"autoprefixer": "^10.4.21",
"postcss": "^8.5.6",
"tailwindcss": "3.4.15",
"terser": "^5.44.0",
"typescript": "^5.9.2",
"vite": "^7.1.4",
"vue-tsc": "^3.0.6"
Expand Down
12 changes: 9 additions & 3 deletions src/App.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
<template>
<div id="app" class="transition-colors duration-200">
<router-view v-slot="{ Component, route }">
<transition
:name="route.meta.transition || 'slide-left'"
<transition
:name="(route.meta?.transition as string) || 'slide-left'"
mode="out-in"
>
<component :is="Component" :key="route.path" />
<Suspense>
<component :is="Component" :key="route.path" />
<template #fallback>
<LoadingSpinner />
</template>
</Suspense>
</transition>
</router-view>
</div>
Expand All @@ -14,6 +19,7 @@
<script setup lang="ts">
import { onMounted } from 'vue'
import { useTheme } from '@/composables/useTheme'
import LoadingSpinner from '@/components/LoadingSpinner.vue'

// Initialize theme on app start
const { initTheme } = useTheme()
Expand Down
6 changes: 4 additions & 2 deletions src/components/BaseCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { computed, useSlots } from 'vue'

interface Props {
variant?: 'default' | 'elevated' | 'outlined' | 'ghost'
Expand All @@ -58,6 +58,8 @@ const props = withDefaults(defineProps<Props>(), {
padding: 'md'
})

const slots = useSlots()

// Base classes
const baseClasses = 'relative transition-all duration-300'

Expand Down Expand Up @@ -143,7 +145,7 @@ const headerClasses = computed(() => [
const contentClasses = computed(() => [
{
[paddingClasses[props.padding]]: props.padding !== 'none',
'pt-0': (props.$slots.header || props.title) && props.padding !== 'none'
'pt-0': (slots.header || props.title) && props.padding !== 'none'
}
])

Expand Down
6 changes: 3 additions & 3 deletions src/components/CodeBlock.vue
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ const formatLanguageName = (lang: string): string => {
}

// Get badge variant based on language
const getBadgeVariant = (lang: string) => {
const variantMap: Record<string, string> = {
const getBadgeVariant = (lang: string): 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' => {
const variantMap: Record<string, 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info'> = {
'javascript': 'warning',
'typescript': 'primary',
'python': 'success',
Expand All @@ -218,7 +218,7 @@ const getBadgeVariant = (lang: string) => {
'html': 'danger',
'sql': 'success'
}

return variantMap[lang] || 'default'
}

Expand Down
12 changes: 12 additions & 0 deletions src/components/LoadingSpinner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<template>
<div class="flex items-center justify-center min-h-screen bg-gray-50 dark:bg-gray-900">
<div class="text-center">
<div class="inline-block animate-spin rounded-full h-12 w-12 border-b-2 border-pico-sky"></div>
<p class="mt-4 text-gray-600 dark:text-gray-400">{{ $t('loading') || 'Loading...' }}</p>
</div>
</div>
</template>

<script setup lang="ts">
// Simple loading component for route transitions
</script>
27 changes: 21 additions & 6 deletions src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,35 @@
import { createI18n } from 'vue-i18n'
import en from './locales/en.json'
import id from './locales/id.json'

const messages = {
en,
id
// Lazy load locale messages
const loadLocaleMessages = async () => {
const modules = import.meta.glob('./locales/*.json')
const messages: Record<string, any> = {}

for (const path in modules) {
const mod = await modules[path]() as { default: any }
const locale = path.replace('./locales/', '').replace('.json', '')
messages[locale] = mod.default
}

return messages
}

// Get saved language or default to English
const savedLanguage = localStorage.getItem('pico-language') || 'en'

// Create i18n instance with lazy loading
const i18n = createI18n({
legacy: false,
locale: savedLanguage,
fallbackLocale: 'en',
messages
messages: {}
})

// Load messages asynchronously
loadLocaleMessages().then(messages => {
Object.keys(messages).forEach(locale => {
i18n.global.setLocaleMessage(locale, messages[locale])
})
})

export default i18n
9 changes: 3 additions & 6 deletions src/router/index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import Documentation from '@/views/Documentation.vue'
import ApiReference from '@/views/ApiReference.vue'

const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/',
name: 'home',
component: Home
component: () => import('@/views/Home.vue')
},
{
path: '/docs',
name: 'documentation',
component: Documentation
component: () => import('@/views/Documentation.vue')
},
{
path: '/api',
name: 'api-reference',
component: ApiReference
component: () => import('@/views/ApiReference.vue')
}
]
})
Expand Down
2 changes: 1 addition & 1 deletion src/views/Documentation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ import AuthenticationSection from '@/components/documentation/AuthenticationSect
import ErrorHandlingSection from '@/components/documentation/ErrorHandlingSection.vue'
import GlossarySection from '@/components/documentation/GlossarySection.vue'

const { t, locale } = useI18n()
const { locale } = useI18n()

// Version from package.json
const version = packageJson.version
Expand Down
66 changes: 66 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,76 @@ export default defineConfig({
build: {
outDir: 'dist',
assetsDir: 'assets',
sourcemap: false,
minify: 'terser',
target: 'esnext',
reportCompressedSize: false,
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
rollupOptions: {
input: {
main: resolve(__dirname, 'index.html'),
},
output: {
chunkFileNames: 'assets/js/[name]-[hash].js',
entryFileNames: 'assets/js/[name]-[hash].js',
assetFileNames: 'assets/[ext]/[name]-[hash].[ext]',
manualChunks: (id) => {
// Node modules vendor chunks
if (id.includes('node_modules')) {
// Vue core
if (id.includes('vue/') && !id.includes('vue-router') && !id.includes('vue-i18n')) {
return 'vue-vendor'
}
// Vue ecosystem
if (id.includes('vue-router') || id.includes('vue-i18n')) {
return 'vue-ecosystem'
}
// Code syntax highlighting and math
if (id.includes('prismjs') || id.includes('vue-prism-component') || id.includes('katex')) {
return 'syntax-vendor'
}
// Animation and UI libraries
if (id.includes('aos')) {
return 'ui-vendor'
}
// Other vendor libraries
return 'vendor'
}

// Components chunks
if (id.includes('src/components/documentation/')) {
return 'docs-components'
}
if (id.includes('src/components/')) {
return 'components'
}

// Locale chunks
if (id.includes('src/locales/')) {
return 'locales'
}
},
},
},
// Increase chunk size warning limit to 1000kB for vendor chunks
chunkSizeWarningLimit: 1000,
// Split chunks more aggressively
cssCodeSplit: true,
},
// Performance optimizations
optimizeDeps: {
include: [
'vue',
'vue-router',
'vue-i18n',
'prismjs',
'katex',
'aos'
],
},
})