Files
kycnotme/web/src/components/InputImageFile.astro

94 lines
2.9 KiB
Plaintext
Raw Normal View History

2025-05-19 10:23:36 +00:00
---
import { cn } from '../lib/cn'
import { ACCEPTED_IMAGE_TYPES } from '../lib/zodUtils'
2025-05-25 12:28:30 +00:00
import Button from './Button.astro'
2025-05-19 10:23:36 +00:00
import InputFile from './InputFile.astro'
2025-05-25 12:28:30 +00:00
import Tooltip from './Tooltip.astro'
2025-05-19 10:23:36 +00:00
import type { ComponentProps } from 'astro/types'
type Props = Omit<ComponentProps<typeof InputFile>, 'accept'> & {
square?: boolean
2025-05-19 11:22:11 +00:00
value?: string | null
2025-05-25 12:28:30 +00:00
downloadButton?: boolean
2025-05-19 10:23:36 +00:00
}
2025-05-25 12:28:30 +00:00
const { class: className, square, value, downloadButton, ...inputFileProps } = Astro.props
function makeDownloadFilename(value: string) {
const url = new URL(value, Astro.url.origin)
return url.pathname.split('/').pop() ?? 'service-image'
}
2025-05-19 10:23:36 +00:00
---
<div class={cn('flex flex-wrap items-center justify-center gap-4', className)} data-preview-image>
2025-05-19 11:22:11 +00:00
<InputFile
accept={ACCEPTED_IMAGE_TYPES.join(',')}
class="min-w-0 flex-1 basis-[calc(var(--spacing)*32)]"
{...inputFileProps}
/>
2025-05-19 10:23:36 +00:00
<img
2025-05-19 11:22:11 +00:00
src={value}
2025-05-19 10:23:36 +00:00
alt="Preview"
class={cn(
2025-05-19 11:22:11 +00:00
'block h-24 rounded object-cover',
square && 'aspect-square',
'no-js:hidden not-[[src]]:hidden [&[src=""]]:hidden',
'[&:is(:has([data-remove-checkbox]:checked)_~_*)]:hidden'
2025-05-19 10:23:36 +00:00
)}
/>
2025-05-25 12:28:30 +00:00
{
downloadButton && value && (
<Tooltip
text="Download"
classNames={{
tooltip: 'min-2xs:[&:is(:has([data-remove-checkbox]:checked)_~_*_*)]:hidden',
}}
>
<Button
as="a"
href={value}
download={makeDownloadFilename(value)}
icon="ri:download-line"
size="sm"
label="Download"
class={cn(
'bg-night-600 border-night-400 text-day-200 2xs:[&:is(:has([data-remove-checkbox]:not(:checked))_~_*_*)]:h-24 2xs:[&:is(:has([data-remove-checkbox]:not(:checked))_~_*_*)]:px-0 2xs:[&:is(:has([data-remove-checkbox]:not(:checked))_~_*_*)]:w-8 shrink-0 rounded-md border'
)}
classNames={{
label: '2xs:[&:is(:has([data-remove-checkbox]:not(:checked))_~_*_*)]:hidden block ',
}}
/>
</Tooltip>
)
}
2025-05-19 10:23:36 +00:00
</div>
<script>
////////////////////////////////////////////////////////////
// Optional script for image preview. //
// Shows a preview of the selected image before upload. //
////////////////////////////////////////////////////////////
document.addEventListener('astro:page-load', () => {
document.querySelectorAll('[data-preview-image]').forEach((wrapper) => {
const input = wrapper.querySelector<HTMLInputElement>('input[type="file"]')
if (!input) return
const previewImageElements = wrapper.querySelectorAll<HTMLImageElement>('img')
if (!previewImageElements.length) return
input.addEventListener('change', () => {
const file = input.files?.[0]
if (!file) return
const fileUrl = URL.createObjectURL(file)
previewImageElements.forEach((previewImage) => {
previewImage.src = fileUrl
})
})
})
})
</script>