mirror of
https://github.com/Afilmory/afilmory
synced 2026-02-01 22:48:17 +00:00
chore: update package dependencies and improve documentation
- Updated `vite` to the beta version across multiple applications for enhanced features and performance. - Removed deprecated dependencies such as `@clack/prompts`, `consola`, and `opentype.js` from `devDependencies`. - Added new storage provider documentation in `routes.json` and updated last modified dates for existing entries. - Refactored route imports in `routes.ts` to streamline the structure and improve readability. - Enhanced the Table of Contents (TOC) data structure for better organization and accessibility. Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
@@ -34,6 +34,7 @@
|
||||
"@types/busboy": "1.5.4",
|
||||
"better-auth": "1.4.5",
|
||||
"busboy": "1.6.0",
|
||||
"consola": "3.4.2",
|
||||
"drizzle-orm": "^0.45.0",
|
||||
"ejs": "3.1.10",
|
||||
"hono": "4.10.7",
|
||||
@@ -54,7 +55,7 @@
|
||||
"@types/pg": "8.15.6",
|
||||
"nodemon": "3.1.11",
|
||||
"unplugin-swc": "1.5.9",
|
||||
"vite": "7.2.6",
|
||||
"vite": "8.0.0-beta.0",
|
||||
"vite-bundle-analyzer": "1.2.3",
|
||||
"vite-node": "5.2.0",
|
||||
"vite-tsconfig-paths": "5.1.4",
|
||||
|
||||
@@ -93,7 +93,7 @@
|
||||
"tailwindcss-safe-area": "catalog:",
|
||||
"tw-animate-css": "1.4.0",
|
||||
"typescript": "5.9.3",
|
||||
"vite": "7.2.6",
|
||||
"vite": "8.0.0-beta.0",
|
||||
"vite-plugin-checker": "0.11.0",
|
||||
"vite-plugin-route-builder": "0.4.1",
|
||||
"vite-tsconfig-paths": "5.1.4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Button, Prompt } from '@afilmory/ui'
|
||||
import { clsxm } from '@afilmory/utils'
|
||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||
import { DatabaseIcon, RadiationIcon, TriangleAlertIcon } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
@@ -220,8 +220,8 @@ export function DataManagementPanel() {
|
||||
<LinearBorderPanel className="bg-background-secondary/40 p-4 sm:p-6">
|
||||
<div className="flex flex-col gap-4 sm:gap-6 lg:flex-row lg:items-center lg:justify-between">
|
||||
<div className="space-y-3 sm:space-y-4">
|
||||
<span className="shape-squircle inline-flex items-center gap-2 bg-accent/10 px-2.5 sm:px-3 py-1 text-[11px] sm:text-xs font-medium text-accent">
|
||||
<DynamicIcon name="database" className="h-3.5 sm:h-4 w-3.5 sm:w-4" />
|
||||
<span className="inline-flex items-center gap-2 text-sm sm:text-xs font-semibold text-accent">
|
||||
<DatabaseIcon className="h-3.5 sm:h-4 w-3.5 sm:w-4" />
|
||||
{t(dataManagementKeys.summary.badge)}
|
||||
</span>
|
||||
<div className="space-y-1.5 sm:space-y-2">
|
||||
@@ -260,7 +260,7 @@ export function DataManagementPanel() {
|
||||
<div className="flex flex-col gap-3 sm:gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div className="space-y-1.5 sm:space-y-2">
|
||||
<div className="flex items-center gap-1.5 sm:gap-2 text-red">
|
||||
<DynamicIcon name="triangle-alert" className="h-3.5 sm:h-4 w-3.5 sm:w-4" />
|
||||
<TriangleAlertIcon className="h-3.5 sm:h-4 w-3.5 sm:w-4" />
|
||||
<span className="text-xs sm:text-sm font-semibold">{t(dataManagementKeys.truncate.badge)}</span>
|
||||
</div>
|
||||
<div>
|
||||
@@ -287,7 +287,7 @@ export function DataManagementPanel() {
|
||||
<div className="flex flex-col gap-3 sm:gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div className="space-y-1.5 sm:space-y-2">
|
||||
<div className="flex items-center gap-1.5 sm:gap-2 text-red">
|
||||
<DynamicIcon name="radiation" className="h-3.5 sm:h-4 w-3.5 sm:w-4" />
|
||||
<RadiationIcon className="h-3.5 sm:h-4 w-3.5 sm:w-4" />
|
||||
<span className="text-xs sm:text-sm font-semibold">{t(dataManagementKeys.delete.badge)}</span>
|
||||
</div>
|
||||
<div className="space-y-1">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Button, Modal } from '@afilmory/ui'
|
||||
import { clsxm } from '@afilmory/utils'
|
||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||
import { CheckSquare, Square, Tags, Trash2, X } from 'lucide-react'
|
||||
import type { ChangeEventHandler } from 'react'
|
||||
import { useMemo, useRef } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -152,7 +152,7 @@ export function PhotoLibraryActionBar() {
|
||||
onClick={handleEditSelectedTags}
|
||||
className="flex items-center gap-1 text-text-secondary hover:text-text"
|
||||
>
|
||||
<DynamicIcon name="tags" className="h-3.5 w-3.5" />
|
||||
<Tags className="h-3.5 w-3.5" />
|
||||
{t(photoLibraryActionKeys.editTags)}
|
||||
</Button>
|
||||
<Button
|
||||
@@ -163,11 +163,11 @@ export function PhotoLibraryActionBar() {
|
||||
onClick={deleteSelected}
|
||||
className="flex items-center gap-1 text-rose-400 hover:text-rose-300"
|
||||
>
|
||||
<DynamicIcon name="trash-2" className="h-3.5 w-3.5" />
|
||||
<Trash2 className="h-3.5 w-3.5" />
|
||||
{t(photoLibraryActionKeys.delete)}
|
||||
</Button>
|
||||
<Button type="button" className="gap-1" variant="ghost" size="sm" onClick={clearSelection}>
|
||||
<DynamicIcon name="x" className="h-3.5 w-3.5" />
|
||||
<X className="h-3.5 w-3.5" />
|
||||
{t(photoLibraryActionKeys.clear)}
|
||||
</Button>
|
||||
</div>
|
||||
@@ -179,7 +179,7 @@ export function PhotoLibraryActionBar() {
|
||||
onClick={selectAll}
|
||||
className="flex items-center gap-1 text-text-secondary hover:text-text"
|
||||
>
|
||||
<DynamicIcon name={canSelectAll ? 'square' : 'check-square'} className="size-4" />
|
||||
{canSelectAll ? <Square className="size-4" /> : <CheckSquare className="size-4" />}
|
||||
{selectAllLabel}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,22 @@ import {
|
||||
} from '@afilmory/ui'
|
||||
import { clsxm } from '@afilmory/utils'
|
||||
import { useAtomValue } from 'jotai'
|
||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||
import {
|
||||
ArrowDown,
|
||||
ArrowUp,
|
||||
Camera,
|
||||
Check,
|
||||
ChevronDown,
|
||||
Clock,
|
||||
ExternalLink,
|
||||
HardDrive,
|
||||
Info,
|
||||
MoreHorizontal,
|
||||
Square,
|
||||
Tags,
|
||||
Trash2,
|
||||
Upload,
|
||||
} from 'lucide-react'
|
||||
import type { ReactNode } from 'react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -31,15 +46,15 @@ import type { DeleteAssetOptions } from './types'
|
||||
type PhotoLibrarySortBy = 'uploadedAt' | 'capturedAt'
|
||||
type PhotoLibrarySortOrder = 'desc' | 'asc'
|
||||
|
||||
const SORT_BY_OPTIONS: { value: PhotoLibrarySortBy; labelKey: I18nKeys; icon: string }[] = [
|
||||
{ value: 'uploadedAt', labelKey: 'photos.library.sort.by-uploaded', icon: 'upload' },
|
||||
{ value: 'capturedAt', labelKey: 'photos.library.sort.by-captured', icon: 'camera' },
|
||||
]
|
||||
const SORT_BY_OPTIONS = [
|
||||
{ value: 'uploadedAt', labelKey: 'photos.library.sort.by-uploaded', Icon: Upload },
|
||||
{ value: 'capturedAt', labelKey: 'photos.library.sort.by-captured', Icon: Camera },
|
||||
] as const
|
||||
|
||||
const SORT_ORDER_OPTIONS: { value: PhotoLibrarySortOrder; labelKey: I18nKeys; icon: string }[] = [
|
||||
{ value: 'desc', labelKey: 'photos.library.sort.order-desc', icon: 'arrow-down' },
|
||||
{ value: 'asc', labelKey: 'photos.library.sort.order-asc', icon: 'arrow-up' },
|
||||
]
|
||||
const SORT_ORDER_OPTIONS = [
|
||||
{ value: 'desc', labelKey: 'photos.library.sort.order-desc', Icon: ArrowDown },
|
||||
{ value: 'asc', labelKey: 'photos.library.sort.order-asc', Icon: ArrowUp },
|
||||
] as const
|
||||
|
||||
const photoLibraryGridKeys = {
|
||||
card: {
|
||||
@@ -185,7 +200,7 @@ function PhotoGridItem({
|
||||
isSelected ? 'bg-accent text-white' : 'hover:bg-white/10',
|
||||
)}
|
||||
>
|
||||
<DynamicIcon name={isSelected ? 'check' : 'square'} className="mr-1 h-3 w-3" />
|
||||
{isSelected ? <Check className="mr-1 h-3 w-3" /> : <Square className="mr-1 h-3 w-3" />}
|
||||
<span>{isSelected ? t(photoLibraryGridKeys.card.selected) : t(photoLibraryGridKeys.card.select)}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -193,15 +208,15 @@ function PhotoGridItem({
|
||||
<div className="flex items-end justify-between gap-3 p-3">
|
||||
<div className="flex flex-col gap-1.5 min-w-0 flex-1">
|
||||
<div className="flex items-center gap-1.5 text-[10px] text-white/80">
|
||||
<DynamicIcon name="camera" className="h-3 w-3 shrink-0 text-white/60" />
|
||||
<Camera className="h-3 w-3 shrink-0 text-white/60" />
|
||||
<span className="truncate">{deviceLabel}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 text-[10px] text-white/80">
|
||||
<DynamicIcon name="clock" className="h-3 w-3 shrink-0 text-white/60" />
|
||||
<Clock className="h-3 w-3 shrink-0 text-white/60" />
|
||||
<span className="truncate">{updatedAtLabel}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5 text-[10px] text-white/80">
|
||||
<DynamicIcon name="hard-drive" className="h-3 w-3 shrink-0 text-white/60" />
|
||||
<HardDrive className="h-3 w-3 shrink-0 text-white/60" />
|
||||
<span className="truncate">{fileSizeLabel}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -213,7 +228,7 @@ function PhotoGridItem({
|
||||
className="bg-black/40 text-white hover:bg-black/60 h-7 px-2.5"
|
||||
onClick={() => onOpenAsset(asset)}
|
||||
>
|
||||
<DynamicIcon name="external-link" className="h-3.5 w-3.5" />
|
||||
<ExternalLink className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
@@ -223,26 +238,19 @@ function PhotoGridItem({
|
||||
size="xs"
|
||||
className="bg-black/40 text-white hover:bg-black/60 h-7 px-2.5"
|
||||
>
|
||||
<DynamicIcon name="more-horizontal" className="h-3.5 w-3.5" />
|
||||
<MoreHorizontal className="h-3.5 w-3.5" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="min-w-[140px]">
|
||||
<DropdownMenuItem
|
||||
icon={<DynamicIcon name="tags" className="size-4" />}
|
||||
onSelect={() => onEditTags(asset)}
|
||||
>
|
||||
<DropdownMenuItem icon={<Tags className="size-4" />} onSelect={() => onEditTags(asset)}>
|
||||
{t('photos.library.card.edit-tags')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
icon={<DynamicIcon name="info" className="size-4" />}
|
||||
disabled={!manifest}
|
||||
onSelect={handleViewExif}
|
||||
>
|
||||
<DropdownMenuItem icon={<Info className="size-4" />} disabled={!manifest} onSelect={handleViewExif}>
|
||||
{t('photos.library.card.view-exif')}
|
||||
</DropdownMenuItem>
|
||||
<div className="h-[0.5px] bg-border my-1" />
|
||||
<DropdownMenuItem
|
||||
icon={<DynamicIcon name="trash-2" className="size-4" />}
|
||||
icon={<Trash2 className="size-4" />}
|
||||
disabled={isDeleting}
|
||||
onSelect={handleDelete}
|
||||
className="text-red focus:text-red focus:bg-red/10"
|
||||
@@ -354,9 +362,9 @@ export function PhotoLibraryGrid() {
|
||||
size="sm"
|
||||
className="hover:bg-background-secondary/70 flex items-center gap-1.5 rounded-full border px-3 h-8 text-text"
|
||||
>
|
||||
<DynamicIcon name={currentSortBy.icon as any} className="size-4" />
|
||||
<currentSortBy.Icon className="size-4" />
|
||||
<span className="font-medium">{t(currentSortBy.labelKey)}</span>
|
||||
<DynamicIcon name="chevron-down" className="h-3 w-3 text-text-tertiary" />
|
||||
<ChevronDown className="h-3 w-3 text-text-tertiary" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="min-w-[180px]">
|
||||
@@ -364,7 +372,7 @@ export function PhotoLibraryGrid() {
|
||||
<DropdownMenuItem
|
||||
key={option.value}
|
||||
active={option.value === sortBy}
|
||||
icon={<DynamicIcon name={option.icon as any} className="size-4" />}
|
||||
icon={<option.Icon className="size-4" />}
|
||||
onSelect={() => setSortBy(option.value)}
|
||||
>
|
||||
{t(option.labelKey)}
|
||||
@@ -381,9 +389,9 @@ export function PhotoLibraryGrid() {
|
||||
size="sm"
|
||||
className="hover:bg-background-secondary/70 flex items-center gap-1.5 rounded-full border px-3 h-8 text-text"
|
||||
>
|
||||
<DynamicIcon name={currentSortOrder.icon as any} className="size-4" />
|
||||
<currentSortOrder.Icon className="size-4" />
|
||||
<span className="font-medium">{t(currentSortOrder.labelKey)}</span>
|
||||
<DynamicIcon name="chevron-down" className="h-3 w-3 text-text-tertiary" />
|
||||
<ChevronDown className="h-3 w-3 text-text-tertiary" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end" className="min-w-[180px]">
|
||||
@@ -391,7 +399,7 @@ export function PhotoLibraryGrid() {
|
||||
<DropdownMenuItem
|
||||
key={option.value}
|
||||
active={option.value === sortOrder}
|
||||
icon={<DynamicIcon name={option.icon as any} className="size-4" />}
|
||||
icon={<option.Icon className="size-4" />}
|
||||
onSelect={() => setSortOrder(option.value)}
|
||||
>
|
||||
{t(option.labelKey)}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Button, Modal } from '@afilmory/ui'
|
||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||
import { HardDrive } from 'lucide-react'
|
||||
import { m } from 'motion/react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -61,7 +61,7 @@ export function ManagedStorageEntryCard({
|
||||
|
||||
<div className="relative">
|
||||
<div className="bg-accent/15 inline-flex h-12 w-12 items-center justify-center rounded-lg">
|
||||
<DynamicIcon name="hard-drive" className="h-6 w-6 text-accent" />
|
||||
<HardDrive className="h-6 w-6 text-accent" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
import { Button } from '@afilmory/ui'
|
||||
import { clsxm } from '@afilmory/utils'
|
||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||
import type {LucideIcon} from 'lucide-react';
|
||||
import {
|
||||
Check,
|
||||
CheckCircle,
|
||||
Cloud,
|
||||
CloudDrizzle,
|
||||
CloudSnow,
|
||||
Database,
|
||||
Folder,
|
||||
Github,
|
||||
Image,
|
||||
Pencil,
|
||||
Server,
|
||||
XCircle
|
||||
} from 'lucide-react'
|
||||
import type { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
@@ -10,48 +24,48 @@ import type { StorageProvider } from '../types'
|
||||
const providerTypeConfig: Record<
|
||||
string,
|
||||
{
|
||||
icon: string
|
||||
Icon: LucideIcon
|
||||
color: string
|
||||
bgColor: string
|
||||
}
|
||||
> = {
|
||||
s3: {
|
||||
icon: 'database',
|
||||
Icon: Database,
|
||||
color: 'text-orange-500',
|
||||
bgColor: 'bg-orange-500/10',
|
||||
},
|
||||
oss: {
|
||||
icon: 'cloud-drizzle',
|
||||
Icon: CloudDrizzle,
|
||||
color: 'text-emerald-500',
|
||||
bgColor: 'bg-emerald-500/10',
|
||||
},
|
||||
cos: {
|
||||
icon: 'cloud-snow',
|
||||
Icon: CloudSnow,
|
||||
color: 'text-cyan-500',
|
||||
bgColor: 'bg-cyan-500/10',
|
||||
},
|
||||
b2: {
|
||||
icon: 'cloud',
|
||||
Icon: Cloud,
|
||||
color: 'text-sky-500',
|
||||
bgColor: 'bg-sky-500/10',
|
||||
},
|
||||
github: {
|
||||
icon: 'github',
|
||||
Icon: Github,
|
||||
color: 'text-purple-500',
|
||||
bgColor: 'bg-purple-500/10',
|
||||
},
|
||||
local: {
|
||||
icon: 'folder',
|
||||
Icon: Folder,
|
||||
color: 'text-blue-500',
|
||||
bgColor: 'bg-blue-500/10',
|
||||
},
|
||||
minio: {
|
||||
icon: 'server',
|
||||
Icon: Server,
|
||||
color: 'text-red-500',
|
||||
bgColor: 'bg-red-500/10',
|
||||
},
|
||||
eagle: {
|
||||
icon: 'image',
|
||||
Icon: Image,
|
||||
color: 'text-amber-500',
|
||||
bgColor: 'bg-amber-500/10',
|
||||
},
|
||||
@@ -110,7 +124,7 @@ export const ProviderCard: FC<ProviderCardProps> = ({ provider, isActive, onEdit
|
||||
{isActive && (
|
||||
<div className="absolute top-3 right-3">
|
||||
<span className="bg-accent inline-flex items-center gap-1 rounded px-2 py-0.5 text-[10px] font-semibold tracking-wide text-white uppercase">
|
||||
<DynamicIcon name="check-circle" className="h-3 w-3" />
|
||||
<CheckCircle className="h-3 w-3" />
|
||||
{t(storageProvidersI18nKeys.card.active)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -119,7 +133,7 @@ export const ProviderCard: FC<ProviderCardProps> = ({ provider, isActive, onEdit
|
||||
{/* Provider Icon */}
|
||||
<div className="relative">
|
||||
<div className={clsxm('inline-flex h-12 w-12 items-center justify-center rounded-lg', config.bgColor)}>
|
||||
<DynamicIcon name={config.icon as any} className={clsxm('h-6 w-6', config.color)} />
|
||||
<config.Icon className={clsxm('h-6 w-6', config.color)} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -142,17 +156,17 @@ export const ProviderCard: FC<ProviderCardProps> = ({ provider, isActive, onEdit
|
||||
className="text-text-secondary hover:text-text"
|
||||
onClick={onToggleActive}
|
||||
>
|
||||
<DynamicIcon name="x-circle" className="mr-1 h-3.5 w-3.5" />
|
||||
<XCircle className="mr-1 h-3.5 w-3.5" />
|
||||
<span>{t(storageProvidersI18nKeys.card.makeInactive)}</span>
|
||||
</Button>
|
||||
) : (
|
||||
<Button type="button" variant="ghost" size="sm" onClick={onToggleActive}>
|
||||
<DynamicIcon name="check" className="h-3.5 w-3.5 mr-1" />
|
||||
<Check className="h-3.5 w-3.5 mr-1" />
|
||||
<span>{t(storageProvidersI18nKeys.card.makeActive)}</span>
|
||||
</Button>
|
||||
)}
|
||||
<Button type="button" variant="ghost" size="sm" onClick={onEdit}>
|
||||
<DynamicIcon name="pencil" className="mr-1 h-3.5 w-3.5" />
|
||||
<Pencil className="mr-1 h-3.5 w-3.5" />
|
||||
<span>{t(storageProvidersI18nKeys.card.edit)}</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
Textarea,
|
||||
} from '@afilmory/ui'
|
||||
import { clsxm, Spring } from '@afilmory/utils'
|
||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||
import { Edit, Plus, PlusCircle, Save } from 'lucide-react'
|
||||
import { m } from 'motion/react'
|
||||
import { nanoid } from 'nanoid'
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
@@ -106,7 +106,7 @@ export function ProviderEditModal({
|
||||
isNewProvider ? 'bg-accent/10 text-accent' : 'bg-fill text-text',
|
||||
)}
|
||||
>
|
||||
<DynamicIcon name={isNewProvider ? 'plus-circle' : 'edit'} className="size-5" />
|
||||
{isNewProvider ? <PlusCircle className="size-5" /> : <Edit className="size-5" />}
|
||||
</div>
|
||||
<div className="flex-1 space-y-1">
|
||||
<h2 className="text-text text-xl font-semibold">
|
||||
@@ -248,7 +248,7 @@ export function ProviderEditModal({
|
||||
{t(storageProvidersI18nKeys.actions.cancel)}
|
||||
</Button>
|
||||
<Button type="button" onClick={handleSave} variant="primary" size="sm">
|
||||
<DynamicIcon name="plus" className="mr-2 h-3.5 w-3.5" />
|
||||
<Plus className="mr-2 h-3.5 w-3.5" />
|
||||
<span>{t(storageProvidersI18nKeys.actions.create)}</span>
|
||||
</Button>
|
||||
</div>
|
||||
@@ -256,7 +256,7 @@ export function ProviderEditModal({
|
||||
// Edit mode: Delete + cancel + set active + save
|
||||
<div className="flex items-center justify-end gap-3">
|
||||
<Button type="button" onClick={handleSave} disabled={!isDirty} variant="primary" size="sm">
|
||||
<DynamicIcon name="save" className="mr-2 h-3.5 w-3.5" />
|
||||
<Save className="mr-2 h-3.5 w-3.5" />
|
||||
<span>{t(storageProvidersI18nKeys.actions.save)}</span>
|
||||
</Button>
|
||||
</div>
|
||||
@@ -273,3 +273,11 @@ ProviderEditModal.contentProps = {
|
||||
maxHeight: '90vh',
|
||||
},
|
||||
}
|
||||
|
||||
// Configure modal content
|
||||
ProviderEditModal.contentClassName = 'max-w-2xl w-[95vw] max-h-[90vh] p-0'
|
||||
ProviderEditModal.contentProps = {
|
||||
style: {
|
||||
maxHeight: '90vh',
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Button, Modal, Prompt, Switch } from '@afilmory/ui'
|
||||
import { Spring } from '@afilmory/utils'
|
||||
import { DynamicIcon } from 'lucide-react/dynamic'
|
||||
import { ShieldCheck } from 'lucide-react'
|
||||
import { m } from 'motion/react'
|
||||
import { startTransition, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
@@ -356,7 +356,7 @@ export function StorageProvidersManager() {
|
||||
<div className="flex items-start gap-3 sm:gap-4">
|
||||
<div className="shrink-0">
|
||||
<div className="bg-accent/10 inline-flex h-8 w-8 items-center justify-center rounded-lg sm:h-10 sm:w-10">
|
||||
<DynamicIcon name="shield-check" className="h-4 w-4 text-accent sm:h-5 sm:w-5" />
|
||||
<ShieldCheck className="h-4 w-4 text-accent sm:h-5 sm:w-5" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 space-y-1.5 sm:space-y-2">
|
||||
|
||||
@@ -282,11 +282,7 @@ function PlanCard({
|
||||
disabled={!canCheckout || checkoutLoading}
|
||||
onClick={handleCheckout}
|
||||
>
|
||||
{checkoutLoading
|
||||
? t(planI18nKeys.checkoutLoading)
|
||||
: canCheckout
|
||||
? t(planI18nKeys.checkoutUpgrade)
|
||||
: t(planI18nKeys.checkoutComingSoon)}
|
||||
{checkoutLoading ? t(planI18nKeys.checkoutLoading) : t(planI18nKeys.checkoutUpgrade)}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"@types/node": "^24.10.1",
|
||||
"nodemon": "3.1.11",
|
||||
"typescript": "catalog:",
|
||||
"vite": "7.2.6",
|
||||
"vite": "8.0.0-beta.0",
|
||||
"vite-node": "5.2.0"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user