paste/src/components/EditForm.svelte

131 lines
3.4 KiB
Svelte

<script lang="ts">
import { onMount, tick } from 'svelte'
import { shorten, getLangFromUrl } from '$lib/utils'
import type { Editor } from 'codemirror'
import { shareUrl, selectedLang } from '../store'
import ComboBox from './ComboBox.svelte'
import Icon from '@iconify/svelte'
type Language = {
text: string
value: string
data: { mime: string; mode: string }
}
let cssClass = ''
export { cssClass as class }
export let editor: Editor | null = null
export let updateShareUrl: () => Promise<void>
let languages: Language[] = []
let selectedLanguage: Language | null = null
let textWrap = false
let urlInput: HTMLInputElement
let isUrlInputVisible = false
onMount(() => {
$selectedLang = getLangFromUrl()
selectedLanguage = languages.find((e) => e.value === $selectedLang)!
})
selectedLang.subscribe((lang) => {
textWrap = lang === 'plt' || lang === 'md'
})
$: {
if (editor) {
// Line wrapping
editor.setOption('lineWrapping', textWrap)
}
}
$: {
if (editor) {
languages = CodeMirror.modeInfo
.map((e: any) => ({
text: e.name,
value: shorten(e.name),
data: { mime: e.mime, mode: e.mode },
}))
.filter((l: any) => l.value !== 'gflm') // Remove github flavored markdown, redundant with markdown
selectedLanguage =
selectedLanguage ??
languages.find((e) => e.value === $selectedLang) ??
languages.find((e) => e.value === 'plt')!
const langData = selectedLanguage?.data ?? { mime: null, mode: null }
// @ts-ignore
editor.setOption('mode', langData.mime)
CodeMirror.autoLoadMode(editor, langData.mode)
$selectedLang = selectedLanguage?.value ?? 'plt'
}
}
async function showUrlInput() {
// Make sure the url is up to date
await updateShareUrl()
isUrlInputVisible = true
await tick()
urlInput.select()
}
async function copyUrl() {
urlInput.select()
await navigator.clipboard.writeText(urlInput.value)
setTimeout(closeUrlInput, 500)
}
function closeUrlInput() {
isUrlInputVisible = false
}
</script>
<div class={cssClass}>
{#if isUrlInputVisible}
<div class="flex gap-2 grow">
<input
bind:this={urlInput}
type="text"
class="border border-gray-300 bg-transparent p-1 grow"
value={$shareUrl}
/>
<button class="button" on:click={copyUrl}>Copy</button>
<button class="button" on:click={closeUrlInput}>Close</button>
</div>
{:else}
<div class="flex justify-end gap-2">
<div>
<ComboBox
items={languages}
bind:value={selectedLanguage}
class="bg-gray-700 border border-gray-300 p-1"
/>
</div>
<!-- Show link input-->
<button class="button" on:click={showUrlInput}>Get Link</button>
<!-- Toggle text wrap -->
<button class="button" title="Toggle text wrap" on:click={() => (textWrap = !textWrap)}>
{#if textWrap}
<Icon class="text-xl" icon="fluent:text-wrap-24-filled" />
{:else}
<Icon class="text-xl" icon="fluent:text-wrap-off-24-filled" />
{/if}
</button>
<!-- Switch to readonly view -->
<a class="button" href={$shareUrl}>
<Icon class="text-xl" icon="fluent:eye-12-regular" />
</a>
</div>
{/if}
</div>
<style lang="scss">
.button {
@apply text-sm border border-gray-300 p-1 hover:bg-gray-600/50;
}
</style>