This commit is contained in:
Ludvík Prokopec 2022-12-03 18:37:32 +01:00
parent ae91149a67
commit 4c4447a41e
12 changed files with 2809 additions and 11 deletions

2630
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -12,6 +12,7 @@
"devDependencies": { "devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.1.0", "@sveltejs/vite-plugin-svelte": "^1.1.0",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"flowbite-svelte": "^0.28.4",
"postcss": "^8.4.19", "postcss": "^8.4.19",
"sass": "^1.56.1", "sass": "^1.56.1",
"svelte": "^3.52.0", "svelte": "^3.52.0",
@ -21,8 +22,10 @@
"vite": "^3.2.3" "vite": "^3.2.3"
}, },
"dependencies": { "dependencies": {
"@bytemd/plugin-gfm": "^1.17.4",
"@icons-pack/svelte-simple-icons": "^3.0.0", "@icons-pack/svelte-simple-icons": "^3.0.0",
"appwrite": "^10.1.0", "appwrite": "^10.1.0",
"bytemd": "^1.17.4",
"svelte-i18n": "^3.6.0", "svelte-i18n": "^3.6.0",
"svelte-routing": "^1.6.0" "svelte-routing": "^1.6.0"
} }

View File

@ -0,0 +1,9 @@
<script>
import { Blockquote, P } from 'flowbite-svelte'
</script>
<Blockquote border bg class="p-4 my-4">
<P height="relaxed">
<slot />
</P>
</Blockquote>

13
src/cms/FileDrop.svelte Normal file
View File

@ -0,0 +1,13 @@
<script lang="ts">
import { Dropzone } from 'flowbite-svelte'
export let rules = []
</script>
<Dropzone on:blur on:change on:click on:focus on:mouseenter on:mouseleave on:mouseover>
<svg aria-hidden="true" class="mb-3 w-10 h-10 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" />
</svg>
<p class="mb-2 text-sm text-gray-500 dark:text-gray-400"><span class="font-semibold">Click to upload</span> or drag and drop</p>
<p class="text-xs text-gray-500 dark:text-gray-400">{rules.join(', ')}</p>
</Dropzone>

45
src/cms/Input.svelte Normal file
View File

@ -0,0 +1,45 @@
<script lang="ts">
import { Input, Label, Helper } from 'flowbite-svelte'
import id from './idGenerator'
const elementId = id('input-')
export let label = ''
export let value = ''
export let error: string = null
export let type:
| 'color'
| 'date'
| 'datetime-local'
| 'email'
| 'file'
| 'hidden'
| 'image'
| 'month'
| 'number'
| 'password'
| 'reset'
| 'submit'
| 'tel'
| 'text'
| 'time'
| 'url'
| 'week'
| 'search' = 'text'
</script>
<div class="mb-6">
<Label for={elementId} color={error ? 'red' : null} class="mb-2">{label}</Label>
<Input bind:value {type} color={error ? 'red' : null} id={elementId} {...$$props}>
<slot />
</Input>
{#if error}
<Helper class="mt-2" color="red">
<span class="font-medium">Error!</span>
{error}
</Helper>
{/if}
</div>

5
src/cms/Loading.svelte Normal file
View File

@ -0,0 +1,5 @@
<div class="h-full w-full top-0 left-0 flex justify-center items-center">
<div class="animate-spin inline-block w-6 h-6 border-[3px] border-current border-t-transparent text-current rounded-full" role="status" aria-label="loading">
<span class="sr-only">Loading...</span>
</div>
</div>

View File

@ -0,0 +1,15 @@
<script>
import 'bytemd/dist/index.css'
import { Editor } from 'bytemd'
import gfm from '@bytemd/plugin-gfm'
const plugins = [gfm()]
export let value = ''
</script>
<div>
<template>
<Editor {value} {plugins} on:change={(e) => (value = e.detail.value)} />
</template>
</div>

View File

@ -0,0 +1,15 @@
<script>
import 'bytemd/dist/index.css'
import { Viewer } from 'bytemd'
import gfm from '@bytemd/plugin-gfm'
const plugins = [gfm()]
export let value = ''
</script>
<div>
<template>
<Viewer {value} {plugins} />
</template>
</div>

60
src/cms/Sortable.svelte Normal file
View File

@ -0,0 +1,60 @@
<script>
import { createEventDispatcher } from 'svelte'
import { flip } from 'svelte/animate'
export let list
export let key = 'id'
export let element = 'div'
export let active = true
const dispatch = createEventDispatcher()
let source = null
let isOver = false
const start = (e, id) => {
e.dataTransfer.clearData()
e.dataTransfer.setData('text/plain', id)
}
const over = (target) => isOver !== target.id && (isOver = target.id)
const leave = () => isOver === source?.id && (isOver = false)
const reorder = (source, target) => {
if (!active || !source || !target) return
if (source.id === target.id) return
const { order: sourceIndex } = source
const { order: targetIndex } = target
isOver = false
list[sourceIndex] = [list[targetIndex], (list[targetIndex] = list[sourceIndex])][0]
list = list
dispatch('reorder', { source, target })
source = null
}
</script>
{#each list as item, order (item[key])}
<svelte:element
this={element}
draggable={active}
on:dragstart={(e) => (source = { order, id: item[key] }) && start(e, source.id)}
on:dragover|preventDefault={() => over({ order, id: item[key] })}
on:dragleave={leave}
on:dragenter|preventDefault={() => null}
on:drop|preventDefault={() => reorder(source, { order, id: item[key] })}
animate:flip={{ duration: source !== null ? 300 : 0 }}
class:over={item[key] === isOver}
>
<slot {item} {order} index={order} />
</svelte:element>
{/each}
<style>
.over {
border-color: rgba(48, 12, 200, 0.2);
}
</style>

10
src/cms/components.ts Normal file
View File

@ -0,0 +1,10 @@
import FileDrop from './FileDrop.svelte'
import Input from './Input.svelte'
import Sortable from './Sortable.svelte'
import BlockQuote from './BlockQuote.svelte'
import MarkdownEditor from './MarkdownEditor.svelte'
import MarkdownRenderer from './MarkdownRenderer.svelte'
import { Radio, Checkbox, Fileupload as FileUpload, Range, Select, Textarea, Toggle, Hr as HorizontalRule, Button, ButtonGroup } from 'flowbite-svelte'
export { FileDrop, Input, Radio, Checkbox, FileUpload, Range, Select, Textarea, Toggle, Sortable, BlockQuote, HorizontalRule, MarkdownEditor, MarkdownRenderer, Button, ButtonGroup }

6
src/cms/idGenerator.ts Normal file
View File

@ -0,0 +1,6 @@
const gen = (function* () {
let index = -1
while (true) yield index++
})()
export default (pre: string = '') => `${pre}${gen.next().value}`

View File

@ -1,9 +1,14 @@
/** @type {import('tailwindcss').Config} */ /** @type {import('tailwindcss').Config} */
module.exports = { module.exports = {
content: ['./src/**/*.{html,js,svelte,ts}'], content: [
'./src/**/*.{html,js,svelte,ts}',
'./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}',
],
theme: { theme: {
extend: {} extend: {}
}, },
plugins: [], plugins: [
require('flowbite/plugin')
],
darkMode: 'class' darkMode: 'class'
} }