additons
This commit is contained in:
@@ -2,21 +2,8 @@
|
||||
<div class="sm-html">
|
||||
<div
|
||||
v-if="editor"
|
||||
class="flex bg-white border-t border-x border-gray rounded-t-2">
|
||||
<button
|
||||
@click.prevent="editor.chain().focus().toggleInfo().run()"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive('info')
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
III
|
||||
</button>
|
||||
<div class="flex px-1 border-r border-gray relative">
|
||||
class="flex flex-wrap bg-white border border-gray rounded-t-2">
|
||||
<div class="flex px-1 relative border-r">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
@@ -63,9 +50,27 @@
|
||||
:selected="editor.isActive('heading', { level: 6 })">
|
||||
Heading 6
|
||||
</option>
|
||||
<option value="info" :selected="editor.isActive('info')">
|
||||
Info
|
||||
</option>
|
||||
<option
|
||||
value="success"
|
||||
:selected="editor.isActive('success')">
|
||||
Success
|
||||
</option>
|
||||
<option
|
||||
value="warning"
|
||||
:selected="editor.isActive('warning')">
|
||||
Warning
|
||||
</option>
|
||||
<option
|
||||
value="danger"
|
||||
:selected="editor.isActive('danger')">
|
||||
Danger
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex p-1 border-r border-gray">
|
||||
<div class="flex p-1 border-r">
|
||||
<button
|
||||
@click.prevent="editor.chain().focus().toggleBold().run()"
|
||||
:disabled="!editor.can().chain().focus().toggleBold().run()"
|
||||
@@ -133,7 +138,6 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<title>format-underline</title>
|
||||
<path
|
||||
d="M5,21H19V19H5V21M12,17A6,6 0 0,0 18,11V3H15.5V11A3.5,3.5 0 0,1 12,14.5A3.5,3.5 0 0,1 8.5,11V3H6V11A6,6 0 0,0 12,17Z"
|
||||
fill="currentColor" />
|
||||
@@ -158,14 +162,220 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<title>format-strikethrough-variant</title>
|
||||
<path
|
||||
d="M23,12V14H18.61C19.61,16.14 19.56,22 12.38,22C4.05,22.05 4.37,15.5 4.37,15.5L8.34,15.55C8.37,18.92 11.5,18.92 12.12,18.88C12.76,18.83 15.15,18.84 15.34,16.5C15.42,15.41 14.32,14.58 13.12,14H1V12H23M19.41,7.89L15.43,7.86C15.43,7.86 15.6,5.09 12.15,5.08C8.7,5.06 9,7.28 9,7.56C9.04,7.84 9.34,9.22 12,9.88H5.71C5.71,9.88 2.22,3.15 10.74,2C19.45,0.8 19.43,7.91 19.41,7.89Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="
|
||||
editor.chain().focus().toggleHighlight().run()
|
||||
"
|
||||
:disabled="
|
||||
!editor.can().chain().focus().toggleHighlight().run()
|
||||
"
|
||||
title="highlight"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive('highlight')
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M18.5,1.15C17.97,1.15 17.46,1.34 17.07,1.73L11.26,7.55L16.91,13.2L22.73,7.39C23.5,6.61 23.5,5.35 22.73,4.56L19.89,1.73C19.5,1.34 19,1.15 18.5,1.15M10.3,8.5L4.34,14.46C3.56,15.24 3.56,16.5 4.36,17.31C3.14,18.54 1.9,19.77 0.67,21H6.33L7.19,20.14C7.97,20.9 9.22,20.89 10,20.12L15.95,14.16"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex p-1 border-r border-gray">
|
||||
<div class="flex p-1 border-r">
|
||||
<button
|
||||
@click.prevent="
|
||||
editor.chain().focus().setTextAlign('left').run()
|
||||
"
|
||||
title="align left"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive({ textAlign: 'left' })
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M3,3H21V5H3V3M3,7H15V9H3V7M3,11H21V13H3V11M3,15H15V17H3V15M3,19H21V21H3V19Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="
|
||||
editor.chain().focus().setTextAlign('center').run()
|
||||
"
|
||||
title="align center"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive({ textAlign: 'center' })
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M3,3H21V5H3V3M7,7H17V9H7V7M3,11H21V13H3V11M7,15H17V17H7V15M3,19H21V21H3V19Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="
|
||||
editor.chain().focus().setTextAlign('right').run()
|
||||
"
|
||||
title="align right"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive({ textAlign: 'right' })
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M3,3H21V5H3V3M9,7H21V9H9V7M3,11H21V13H3V11M9,15H21V17H9V15M3,19H21V21H3V19Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="
|
||||
editor.chain().focus().setTextAlign('justify').run()
|
||||
"
|
||||
title="align right"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive({ textAlign: 'justify' })
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M3,3H21V5H3V3M3,7H21V9H3V7M3,11H21V13H3V11M3,15H21V17H3V15M3,19H21V21H3V19Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex p-1 border-r">
|
||||
<button
|
||||
@click.prevent="setLink()"
|
||||
title="link"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive('link')
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M3.9,12C3.9,10.29 5.29,8.9 7,8.9H11V7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H11V15.1H7C5.29,15.1 3.9,13.71 3.9,12M8,13H16V11H8V13M17,7H13V8.9H17C18.71,8.9 20.1,10.29 20.1,12C20.1,13.71 18.71,15.1 17,15.1H13V17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="editor.chain().focus().unsetLink().run()"
|
||||
title="unlink"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
'bg-white',
|
||||
'text-gray-6',
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M17,7H13V8.9H17C18.71,8.9 20.1,10.29 20.1,12C20.1,13.43 19.12,14.63 17.79,15L19.25,16.44C20.88,15.61 22,13.95 22,12A5,5 0 0,0 17,7M16,11H13.81L15.81,13H16V11M2,4.27L5.11,7.38C3.29,8.12 2,9.91 2,12A5,5 0 0,0 7,17H11V15.1H7C5.29,15.1 3.9,13.71 3.9,12C3.9,10.41 5.11,9.1 6.66,8.93L8.73,11H8V13H10.73L13,15.27V17H14.73L18.74,21L20,19.74L3.27,3L2,4.27Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex p-1 border-r">
|
||||
<button
|
||||
@click.prevent="setImage()"
|
||||
title="image"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive('image')
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M19,19H5V5H19M19,3H5A2,2 0 0,0 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V5A2,2 0 0,0 19,3M13.96,12.29L11.21,15.83L9.25,13.47L6.5,17H17.5L13.96,12.29Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="setLink()"
|
||||
title="gallery"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive('gallery')
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M21,17H7V3H21M21,1H7A2,2 0 0,0 5,3V17A2,2 0 0,0 7,19H21A2,2 0 0,0 23,17V3A2,2 0 0,0 21,1M3,5H1V21A2,2 0 0,0 3,23H19V21H3M15.96,10.29L13.21,13.83L11.25,11.47L8.5,15H19.5L15.96,10.29Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex p-1 border-r">
|
||||
<button
|
||||
@click.prevent="
|
||||
editor.chain().focus().toggleBulletList().run()
|
||||
@@ -207,14 +417,13 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-4 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<title>format-list-numbered</title>
|
||||
<path
|
||||
d="M7,13V11H21V13H7M7,19V17H21V19H7M7,7V5H21V7H7M3,8V5H2V4H4V8H3M2,17V16H5V20H2V19H4V18.5H3V17.5H4V17H2M4.25,10A0.75,0.75 0 0,1 5,10.75C5,10.95 4.92,11.14 4.79,11.27L3.12,13H5V14H2V13.08L4,11H2V10H4.25Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex p-1 border-r border-gray">
|
||||
<div class="flex p-1 border-r">
|
||||
<button
|
||||
@click.prevent="
|
||||
editor.chain().focus().toggleCodeBlock().run()
|
||||
@@ -281,7 +490,57 @@
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex p-1 border-r border-gray">
|
||||
<div class="flex p-1 border-r">
|
||||
<button
|
||||
@click.prevent="
|
||||
editor.chain().focus().unsetSuperscript().run();
|
||||
editor.chain().focus().toggleSubscript().run();
|
||||
"
|
||||
title="subscript"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive('subscript')
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M16,7.41L11.41,12L16,16.59L14.59,18L10,13.41L5.41,18L4,16.59L8.59,12L4,7.41L5.41,6L10,10.59L14.59,6L16,7.41M21.85,21.03H16.97V20.03L17.86,19.23C18.62,18.58 19.18,18.04 19.56,17.6C19.93,17.16 20.12,16.75 20.13,16.36C20.14,16.08 20.05,15.85 19.86,15.66C19.68,15.5 19.39,15.38 19,15.38C18.69,15.38 18.42,15.44 18.16,15.56L17.5,15.94L17.05,14.77C17.32,14.56 17.64,14.38 18.03,14.24C18.42,14.1 18.85,14 19.32,14C20.1,14.04 20.7,14.25 21.1,14.66C21.5,15.07 21.72,15.59 21.72,16.23C21.71,16.79 21.53,17.31 21.18,17.78C20.84,18.25 20.42,18.7 19.91,19.14L19.27,19.66V19.68H21.85V21.03Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="
|
||||
editor.chain().focus().unsetSubscript().run();
|
||||
editor.chain().focus().toggleSuperscript().run();
|
||||
"
|
||||
title="Superscript"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-items-center',
|
||||
'p-1',
|
||||
'hover-bg-gray-3',
|
||||
editor.isActive('superscript')
|
||||
? ['bg-sky-6', 'text-white']
|
||||
: ['bg-white', 'text-gray-6'],
|
||||
]">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M16,7.41L11.41,12L16,16.59L14.59,18L10,13.41L5.41,18L4,16.59L8.59,12L4,7.41L5.41,6L10,10.59L14.59,6L16,7.41M21.85,9H16.97V8L17.86,7.18C18.62,6.54 19.18,6 19.56,5.55C19.93,5.11 20.12,4.7 20.13,4.32C20.14,4.04 20.05,3.8 19.86,3.62C19.68,3.43 19.39,3.34 19,3.33C18.69,3.34 18.42,3.4 18.16,3.5L17.5,3.89L17.05,2.72C17.32,2.5 17.64,2.33 18.03,2.19C18.42,2.05 18.85,2 19.32,2C20.1,2 20.7,2.2 21.1,2.61C21.5,3 21.72,3.54 21.72,4.18C21.71,4.74 21.53,5.26 21.18,5.73C20.84,6.21 20.42,6.66 19.91,7.09L19.27,7.61V7.63H21.85V9Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex p-1 border-r">
|
||||
<button
|
||||
@click.prevent="editor.chain().focus().setHardBreak().run()"
|
||||
title="hard break"
|
||||
@@ -324,7 +583,7 @@
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex p-1">
|
||||
<div class="flex p-1 border-r">
|
||||
<button
|
||||
@click.prevent="editor.chain().focus().undo().run()"
|
||||
title="Undo"
|
||||
@@ -345,7 +604,6 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<title>undo</title>
|
||||
<path
|
||||
d="M12.5,8C9.85,8 7.45,9 5.6,10.6L2,7V16H11L7.38,12.38C8.77,11.22 10.54,10.5 12.5,10.5C16.04,10.5 19.05,12.81 20.1,16L22.47,15.22C21.08,11.03 17.15,8 12.5,8Z"
|
||||
fill="currentColor" />
|
||||
@@ -371,7 +629,6 @@
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<title>redo</title>
|
||||
<path
|
||||
d="M18.4,10.6C16.55,9 14.15,8 11.5,8C6.85,8 2.92,11.03 1.54,15.22L3.9,16C4.95,12.81 7.95,10.5 11.5,10.5C13.45,10.5 15.23,11.22 16.62,12.38L13,16H22V7L18.4,10.6Z"
|
||||
fill="currentColor" />
|
||||
@@ -381,7 +638,7 @@
|
||||
</div>
|
||||
<EditorContent
|
||||
:editor="editor"
|
||||
class="rounded-b-2 bg-white p-4 border-1 border-gray h-128 overflow-auto sm-editor" />
|
||||
class="rounded-b-2 bg-white p-4 border-x border-b border-gray h-128 overflow-auto sm-editor" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -391,7 +648,18 @@ import { useEditor, EditorContent } from "@tiptap/vue-3";
|
||||
import StarterKit from "@tiptap/starter-kit";
|
||||
import Underline from "@tiptap/extension-underline";
|
||||
import TextAlign from "@tiptap/extension-text-align";
|
||||
import Highlight from "@tiptap/extension-highlight";
|
||||
import { Info } from "../extensions/info";
|
||||
import { Success } from "../extensions/success";
|
||||
import { Warning } from "../extensions/warning";
|
||||
import { Danger } from "../extensions/danger";
|
||||
import Subscript from "@tiptap/extension-subscript";
|
||||
import Superscript from "@tiptap/extension-superscript";
|
||||
import Link from "@tiptap/extension-link";
|
||||
import Image from "@tiptap/extension-image";
|
||||
import { openDialog } from "./SMDialog";
|
||||
import SMDialogMedia from "./dialogs/SMDialogMedia.vue";
|
||||
import { Media } from "../helpers/api.types";
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
@@ -404,7 +672,31 @@ const emits = defineEmits(["update:modelValue"]);
|
||||
|
||||
const editor = useEditor({
|
||||
content: props.modelValue,
|
||||
extensions: [StarterKit, Underline, TextAlign, Info],
|
||||
extensions: [
|
||||
StarterKit,
|
||||
Underline,
|
||||
TextAlign.configure({
|
||||
types: [
|
||||
"heading",
|
||||
"paragraph",
|
||||
"info",
|
||||
"success",
|
||||
"warning",
|
||||
"danger",
|
||||
],
|
||||
}),
|
||||
Highlight,
|
||||
Info,
|
||||
Success,
|
||||
Warning,
|
||||
Danger,
|
||||
Subscript,
|
||||
Superscript,
|
||||
Link.configure({
|
||||
openOnClick: false,
|
||||
}),
|
||||
Image,
|
||||
],
|
||||
onUpdate: () => {
|
||||
emits("update:modelValue", editor.value.getHTML());
|
||||
},
|
||||
@@ -434,10 +726,60 @@ const updateNode = (event) => {
|
||||
case "h6":
|
||||
editor.value.chain().focus().setHeading({ level: 6 }).run();
|
||||
break;
|
||||
case "info":
|
||||
editor.value.chain().focus().toggleInfo().run();
|
||||
break;
|
||||
case "success":
|
||||
editor.value.chain().focus().toggleSuccess().run();
|
||||
break;
|
||||
case "warning":
|
||||
editor.value.chain().focus().toggleWarning().run();
|
||||
break;
|
||||
case "danger":
|
||||
editor.value.chain().focus().toggleDanger().run();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const setLink = () => {
|
||||
const previousUrl = editor.value.getAttributes("link").href;
|
||||
const url = window.prompt("URL", previousUrl);
|
||||
|
||||
// cancelled
|
||||
if (url === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// empty
|
||||
if (url === "") {
|
||||
editor.value.chain().focus().extendMarkRange("link").unsetLink().run();
|
||||
return;
|
||||
}
|
||||
|
||||
// update link
|
||||
editor.value
|
||||
.chain()
|
||||
.focus()
|
||||
.extendMarkRange("link")
|
||||
.setLink({ href: url })
|
||||
.run();
|
||||
};
|
||||
|
||||
const setImage = async () => {
|
||||
let result = await openDialog(SMDialogMedia);
|
||||
if (result) {
|
||||
const mediaResult = result as Media;
|
||||
editor.value
|
||||
.chain()
|
||||
.focus()
|
||||
.setImage({
|
||||
src: mediaResult.url,
|
||||
})
|
||||
.run();
|
||||
}
|
||||
};
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
editor.value.destroy();
|
||||
});
|
||||
|
||||
@@ -18,6 +18,11 @@ defineProps({
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
hide: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
|
||||
const selectedTab = inject("selectedTab");
|
||||
|
||||
@@ -42,17 +42,22 @@ const emits = defineEmits(["tabChanged", "update:modelValue"]);
|
||||
const slots = useSlots();
|
||||
|
||||
const tabs = ref(
|
||||
slots.default().map((tab) => {
|
||||
const { label, id } = tab.props;
|
||||
return {
|
||||
label,
|
||||
id,
|
||||
};
|
||||
})
|
||||
slots
|
||||
.default()
|
||||
.map((tab) => {
|
||||
const { label, id, hide } = tab.props;
|
||||
if (hide !== true) {
|
||||
return {
|
||||
label,
|
||||
id,
|
||||
};
|
||||
}
|
||||
})
|
||||
.filter(Boolean),
|
||||
);
|
||||
|
||||
const selectedTab = ref(
|
||||
props.modelValue.length == 0 ? tabs.value[0].id : props.modelValue
|
||||
props.modelValue.length == 0 ? tabs.value[0].id : props.modelValue,
|
||||
);
|
||||
|
||||
if (props.modelValue.length == 0) {
|
||||
@@ -64,14 +69,14 @@ watch(
|
||||
(newValue) => {
|
||||
emits("tabChanged", newValue);
|
||||
emits("update:modelValue", newValue);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
(newValue) => {
|
||||
selectedTab.value = newValue;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
provide("selectedTab", selectedTab);
|
||||
|
||||
@@ -1,28 +1,76 @@
|
||||
<template>
|
||||
<div
|
||||
class="fixed top-0 left-0 w-full h-full z-2 bg-black bg-op-20 backdrop-blur"></div>
|
||||
<div class="fixed top-0 left-0 w-full h-full flex-justify-center flex z-3">
|
||||
<div
|
||||
class="fixed top-0 left-0 w-full flex-justify-center flex z-3 max-h-screen">
|
||||
<div
|
||||
class="m-4 border-1 bg-white rounded-xl text-gray-5 px-12 py-8 w-full">
|
||||
<div class="dialog-media">
|
||||
class="m-4 border-1 bg-white rounded-xl text-gray-5 px-12 py-8 w-full overflow-auto">
|
||||
<div>
|
||||
<SMLoading v-if="progressText" overlay :text="progressText" />
|
||||
<h2 class="mb-4">Insert Media</h2>
|
||||
<SMTabGroup v-model="selectedTab">
|
||||
<SMTab id="tab-browser" label="Media Browser">
|
||||
<div class="flex mb-4">
|
||||
<div
|
||||
:buttons="[
|
||||
{
|
||||
name: 'grid',
|
||||
icon: 'grid-outline',
|
||||
},
|
||||
{
|
||||
name: 'list',
|
||||
icon: 'list-outline',
|
||||
},
|
||||
<button
|
||||
title="View as grid"
|
||||
:class="[
|
||||
'p-2',
|
||||
'rounded-l-2',
|
||||
'hover:shadow-md',
|
||||
'transition',
|
||||
'border-1',
|
||||
'border-sky-600',
|
||||
'cursor-pointer',
|
||||
listActive != 'grid'
|
||||
? [
|
||||
'text-sky-600',
|
||||
'bg-white',
|
||||
'hover:bg-sky-500',
|
||||
'hover:text-white',
|
||||
]
|
||||
: ['text-white', 'bg-sky-600'],
|
||||
]"
|
||||
:active="listActive"
|
||||
@click="handleClickLayout"></div>
|
||||
@click="handleClickLayout('grid')">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M3,11H11V3H3M3,21H11V13H3M13,21H21V13H13M13,3V11H21V3"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
title="View as list"
|
||||
:class="[
|
||||
'p-2',
|
||||
'rounded-r-2',
|
||||
'hover:shadow-md',
|
||||
'transition',
|
||||
'hover:bg-sky-500',
|
||||
'border-1',
|
||||
'border-sky-600',
|
||||
'cursor-pointer',
|
||||
'mr-4',
|
||||
listActive != 'list'
|
||||
? [
|
||||
'text-sky-600',
|
||||
'bg-white',
|
||||
'hover:bg-sky-500',
|
||||
'hover:text-white',
|
||||
]
|
||||
: ['text-white', 'bg-sky-600'],
|
||||
]"
|
||||
@click="handleClickLayout('list')">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
class="h-5 w-5"
|
||||
viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M9,5V9H21V5M9,19H21V15H9M9,14H21V10H9M4,9H8V5H4M4,19H8V15H4M4,14H8V10H4V14Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
</button>
|
||||
<SMInput
|
||||
v-model="itemSearch"
|
||||
label="Search"
|
||||
@@ -47,40 +95,81 @@
|
||||
</template>
|
||||
</SMInput>
|
||||
</div>
|
||||
<div class="media-browser" :class="mediaBrowserClasses">
|
||||
<div class="media-browser-content">
|
||||
<div class="flex">
|
||||
<div
|
||||
class="flex flex-justify-center overflow-auto w-full">
|
||||
<SMLoading v-if="mediaLoading" />
|
||||
<div
|
||||
v-if="
|
||||
v-else-if="
|
||||
!mediaLoading && mediaItems.length == 0
|
||||
"
|
||||
class="media-none">
|
||||
<ion-icon name="sad-outline"></ion-icon>
|
||||
<p>No media found</p>
|
||||
class="py-12 text-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 -960 960 960"
|
||||
class="h-24 text-gray-5">
|
||||
<path
|
||||
d="M453-280h60v-240h-60v240Zm26.982-314q14.018 0 23.518-9.2T513-626q0-14.45-9.482-24.225-9.483-9.775-23.5-9.775-14.018 0-23.518 9.775T447-626q0 13.6 9.482 22.8 9.483 9.2 23.5 9.2Zm.284 514q-82.734 0-155.5-31.5t-127.266-86q-54.5-54.5-86-127.341Q80-397.681 80-480.5q0-82.819 31.5-155.659Q143-709 197.5-763t127.341-85.5Q397.681-880 480.5-880q82.819 0 155.659 31.5Q709-817 763-763t85.5 127Q880-563 880-480.266q0 82.734-31.5 155.5T763-197.684q-54 54.316-127 86Q563-80 480.266-80Zm.234-60Q622-140 721-239.5t99-241Q820-622 721.188-721 622.375-820 480-820q-141 0-240.5 98.812Q140-622.375 140-480q0 141 99.5 240.5t241 99.5Zm-.5-340Z"
|
||||
fill="currentColor" />
|
||||
</svg>
|
||||
<p class="text-lg text-gray-5">
|
||||
No media found
|
||||
</p>
|
||||
</div>
|
||||
<ul
|
||||
v-if="
|
||||
!mediaLoading && mediaItems.length > 0
|
||||
">
|
||||
"
|
||||
:class="[
|
||||
'flex',
|
||||
'flex-1',
|
||||
'gap-4',
|
||||
'border-1',
|
||||
'mb-4',
|
||||
'p-3',
|
||||
'overflow-auto',
|
||||
'flex-justify-center',
|
||||
listActive == 'grid'
|
||||
? ['flex-row', 'flex-wrap']
|
||||
: ['flex-col', 'flex-nowrap'],
|
||||
]">
|
||||
<li
|
||||
v-for="item in mediaItems"
|
||||
:key="item.id"
|
||||
:class="[
|
||||
{ selected: item.id == selected },
|
||||
'flex',
|
||||
'text-center',
|
||||
'border-3',
|
||||
'p-1px',
|
||||
'flex-items-center',
|
||||
listActive == 'grid'
|
||||
? ['h-50', 'w-60', 'flex-col']
|
||||
: ['ha', 'w-full', 'flex-row'],
|
||||
item.id == selected
|
||||
? 'border-sky-600'
|
||||
: 'border-white',
|
||||
]"
|
||||
@click="handleClickItem(item.id)"
|
||||
@dblclick="handleDblClickItem(item.id)">
|
||||
<div
|
||||
:class="[
|
||||
listActive == 'grid'
|
||||
? ['h-40', 'w-60', 'mr-0']
|
||||
: ['h-20', 'w-20', 'mr-2'],
|
||||
'bg-contain',
|
||||
'bg-center',
|
||||
'bg-no-repeat',
|
||||
]"
|
||||
:style="{
|
||||
backgroundImage: `url('${mediaGetVariantUrl(
|
||||
item,
|
||||
'small'
|
||||
'small',
|
||||
)}')`,
|
||||
}"
|
||||
class="media-image"></div>
|
||||
<span class="media-title">{{
|
||||
item.title
|
||||
}}</span>
|
||||
}"></div>
|
||||
<span
|
||||
class="text-sm whitespace-nowrap overflow-hidden text-ellipsis block p-2"
|
||||
>{{ item.title }}</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -98,22 +187,26 @@
|
||||
<SMForm v-model="uploadForm" form-id="upload-form">
|
||||
<SMFormError v-model="uploadForm" />
|
||||
<div class="flex">
|
||||
<div width="250px">
|
||||
<div class="text-center mr-4 w-60">
|
||||
<div
|
||||
class="upload-preview mb-4"
|
||||
class="mb-4 h-34 border rounded-2 bg-cover bg-center bg-no-repeat"
|
||||
:style="{
|
||||
backgroundImage: `url(${uploadPreview})`,
|
||||
backgroundImage:
|
||||
uploadPreview.length > 0
|
||||
? `url(${uploadPreview})`
|
||||
: `url(\'${uploadPreviewMissing}\')`,
|
||||
}"></div>
|
||||
<button
|
||||
type="button"
|
||||
v-if="props.allowUpload"
|
||||
class="font-medium px-6 py-1.5 rounded-md hover:shadow-md transition text-sm bg-sky-600 hover:bg-sky-500 text-white cursor-pointer"
|
||||
@click="handleClickSelectFile">
|
||||
Select File
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex-1">
|
||||
<SMInput
|
||||
label="Title"
|
||||
class="mb-4"
|
||||
control="title"
|
||||
form-id="upload-form"
|
||||
:disabled="uploadPreview.length == 0" />
|
||||
@@ -195,7 +288,7 @@ const props = defineProps({
|
||||
},
|
||||
allowUpload: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
default: false,
|
||||
required: false,
|
||||
},
|
||||
});
|
||||
@@ -217,11 +310,13 @@ let uploadForm = reactive(
|
||||
Form({
|
||||
title: FormControl("", And([Required(), Min(4)])),
|
||||
description: FormControl(""),
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
const uploadPreview = ref("");
|
||||
|
||||
const uploadPreviewMissing = ref(
|
||||
'data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="-20 -20 64 64"%3E%3Cpath d="M22 20.7L3.3 2L2 3.3L3 4.3V19C3 20.1 3.9 21 5 21H19.7L20.7 22L22 20.7M5 19V6.3L12.6 13.9L11.1 15.8L9 13.1L6 17H15.7L17.7 19H5M8.8 5L6.8 3H19C20.1 3 21 3.9 21 5V17.2L19 15.2V5H8.8" /%3E%3C/svg%3E',
|
||||
);
|
||||
/**
|
||||
* Is the media loading/busy
|
||||
*/
|
||||
@@ -326,7 +421,7 @@ const handleClickInsert = async () => {
|
||||
submitFormData.append("title", uploadForm.controls.title.value);
|
||||
submitFormData.append(
|
||||
"description",
|
||||
uploadForm.controls.description.value
|
||||
uploadForm.controls.description.value,
|
||||
);
|
||||
try {
|
||||
let result = await api.post({
|
||||
@@ -337,7 +432,8 @@ const handleClickInsert = async () => {
|
||||
},
|
||||
progress: (progressData) =>
|
||||
(progressText.value = `Uploading File: ${Math.floor(
|
||||
(progressData.loaded / progressData.total) * 100
|
||||
(progressData.loaded / progressData.total) *
|
||||
100,
|
||||
)}%`),
|
||||
});
|
||||
if (result.data) {
|
||||
@@ -357,7 +453,7 @@ const handleClickInsert = async () => {
|
||||
"The server is taking longer then expected to process the file.\nOnce the file has been processed, select it from the media browser.";
|
||||
} else {
|
||||
await new Promise((resolve) =>
|
||||
setTimeout(resolve, 500)
|
||||
setTimeout(resolve, 500),
|
||||
);
|
||||
try {
|
||||
let updateResult = await api.get({
|
||||
@@ -377,7 +473,7 @@ const handleClickInsert = async () => {
|
||||
mediaProcessed = true;
|
||||
} else if (
|
||||
updateData.medium.status.startsWith(
|
||||
"Failed"
|
||||
"Failed",
|
||||
) == true
|
||||
) {
|
||||
throw "error";
|
||||
@@ -481,7 +577,7 @@ const handleChangeSelectFile = async () => {
|
||||
if (firstFile != null) {
|
||||
if (uploadForm.controls.title.value.length == 0) {
|
||||
uploadForm.controls.title.value = convertFileNameToTitle(
|
||||
firstFile.name
|
||||
firstFile.name,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -595,131 +691,3 @@ const computedInsertDisabled = computed(() => {
|
||||
|
||||
handleLoad();
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.dialog-media {
|
||||
width: 100%;
|
||||
|
||||
h3 {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.media-browser {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.media-browser-content {
|
||||
display: flex;
|
||||
height: 40vh;
|
||||
border: 1px solid var(--base-color-border);
|
||||
background-color: var(--base-color-light);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 0 16px 0;
|
||||
|
||||
.media-none {
|
||||
font-size: 150%;
|
||||
text-align: center;
|
||||
|
||||
ion-icon {
|
||||
font-size: 200%;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
display: block;
|
||||
list-style-type: none;
|
||||
overflow: auto;
|
||||
max-height: 40vh;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 3px solid transparent;
|
||||
box-sizing: content-box;
|
||||
padding: 2px;
|
||||
|
||||
&.selected,
|
||||
&:hover {
|
||||
border-color: var(--primary-color);
|
||||
}
|
||||
|
||||
.media-image {
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.media-browser-list {
|
||||
ul {
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
li {
|
||||
height: auto;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.media-image {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.media-title {
|
||||
flex: 1;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
&.media-browser-grid {
|
||||
ul {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
li {
|
||||
flex-direction: column;
|
||||
height: 160px;
|
||||
width: 220px;
|
||||
|
||||
.media-image {
|
||||
min-height: 132px;
|
||||
min-width: 220px;
|
||||
}
|
||||
|
||||
.media-title {
|
||||
text-align: center;
|
||||
padding: 4px;
|
||||
font-size: 80%;
|
||||
width: 224px;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.upload-preview {
|
||||
width: 250px;
|
||||
height: 140px;
|
||||
border: 1px solid var(--base-color-dark);
|
||||
border-radius: 8px;
|
||||
background-position: center;
|
||||
background-size: cover;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
60
resources/js/extensions/danger.ts
Normal file
60
resources/js/extensions/danger.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { mergeAttributes, Node } from "@tiptap/core";
|
||||
|
||||
export interface DangerOptions {
|
||||
HTMLAttributes: Record<string, any>;
|
||||
}
|
||||
|
||||
declare module "@tiptap/core" {
|
||||
interface Commands<ReturnType> {
|
||||
danger: {
|
||||
/**
|
||||
* Toggle a paragraph
|
||||
*/
|
||||
setDanger: () => ReturnType;
|
||||
toggleDanger: () => ReturnType;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const Danger = Node.create<DangerOptions>({
|
||||
name: "danger",
|
||||
|
||||
priority: 1000,
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
HTMLAttributes: { class: "danger" },
|
||||
};
|
||||
},
|
||||
|
||||
group: "block",
|
||||
|
||||
content: "inline*",
|
||||
|
||||
parseHTML() {
|
||||
return [{ tag: "p", class: "danger" }];
|
||||
},
|
||||
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
return [
|
||||
"p",
|
||||
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
|
||||
0,
|
||||
];
|
||||
},
|
||||
|
||||
addCommands() {
|
||||
return {
|
||||
setDanger:
|
||||
() =>
|
||||
({ commands }) => {
|
||||
return commands.setNode(this.name);
|
||||
},
|
||||
toggleDanger:
|
||||
() =>
|
||||
({ commands }) => {
|
||||
return commands.toggleNode(this.name, "paragraph");
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
60
resources/js/extensions/success.ts
Normal file
60
resources/js/extensions/success.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { mergeAttributes, Node } from "@tiptap/core";
|
||||
|
||||
export interface SuccessOptions {
|
||||
HTMLAttributes: Record<string, any>;
|
||||
}
|
||||
|
||||
declare module "@tiptap/core" {
|
||||
interface Commands<ReturnType> {
|
||||
success: {
|
||||
/**
|
||||
* Toggle a paragraph
|
||||
*/
|
||||
setSuccess: () => ReturnType;
|
||||
toggleSuccess: () => ReturnType;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const Success = Node.create<SuccessOptions>({
|
||||
name: "success",
|
||||
|
||||
priority: 1000,
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
HTMLAttributes: { class: "success" },
|
||||
};
|
||||
},
|
||||
|
||||
group: "block",
|
||||
|
||||
content: "inline*",
|
||||
|
||||
parseHTML() {
|
||||
return [{ tag: "p", class: "success" }];
|
||||
},
|
||||
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
return [
|
||||
"p",
|
||||
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
|
||||
0,
|
||||
];
|
||||
},
|
||||
|
||||
addCommands() {
|
||||
return {
|
||||
setSuccess:
|
||||
() =>
|
||||
({ commands }) => {
|
||||
return commands.setNode(this.name);
|
||||
},
|
||||
toggleSuccess:
|
||||
() =>
|
||||
({ commands }) => {
|
||||
return commands.toggleNode(this.name, "paragraph");
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
60
resources/js/extensions/warning.ts
Normal file
60
resources/js/extensions/warning.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { mergeAttributes, Node } from "@tiptap/core";
|
||||
|
||||
export interface WarningOptions {
|
||||
HTMLAttributes: Record<string, any>;
|
||||
}
|
||||
|
||||
declare module "@tiptap/core" {
|
||||
interface Commands<ReturnType> {
|
||||
warning: {
|
||||
/**
|
||||
* Toggle a paragraph
|
||||
*/
|
||||
setWarning: () => ReturnType;
|
||||
toggleWarning: () => ReturnType;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const Warning = Node.create<WarningOptions>({
|
||||
name: "warning",
|
||||
|
||||
priority: 1000,
|
||||
|
||||
addOptions() {
|
||||
return {
|
||||
HTMLAttributes: { class: "warning" },
|
||||
};
|
||||
},
|
||||
|
||||
group: "block",
|
||||
|
||||
content: "inline*",
|
||||
|
||||
parseHTML() {
|
||||
return [{ tag: "p", class: "warning" }];
|
||||
},
|
||||
|
||||
renderHTML({ HTMLAttributes }) {
|
||||
return [
|
||||
"p",
|
||||
mergeAttributes(this.options.HTMLAttributes, HTMLAttributes),
|
||||
0,
|
||||
];
|
||||
},
|
||||
|
||||
addCommands() {
|
||||
return {
|
||||
setWarning:
|
||||
() =>
|
||||
({ commands }) => {
|
||||
return commands.setNode(this.name);
|
||||
},
|
||||
toggleWarning:
|
||||
() =>
|
||||
({ commands }) => {
|
||||
return commands.toggleNode(this.name, "paragraph");
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -37,59 +37,25 @@
|
||||
input { font-family: Poppins, Roboto, "Open Sans", ui-sans-serif, system-ui, sans-serif; }
|
||||
.scrollbar-width-none { scrollbar-width: none; }
|
||||
.scrollbar-width-none::-webkit-scrollbar { display: none; }
|
||||
.bg-center { background-position: center; }
|
||||
.whitespace-nowrap {white-space: nowrap; }
|
||||
.spin{animation:rotate 1s infinite linear}
|
||||
.sm-html .ProseMirror {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.sm-html hr {
|
||||
border-top: 1px solid #aaa;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
.sm-html pre {
|
||||
padding: 0 1rem;
|
||||
line-height: 1rem;
|
||||
}
|
||||
|
||||
.sm-html blockquote {
|
||||
border-left: 4px solid #ddd;
|
||||
margin-left: 1rem;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.sm-html p.info {
|
||||
display: flex;
|
||||
border: 1px solid rgba(14,165,233,1);
|
||||
background-color: rgba(14,165,233,0.25);
|
||||
border-radius: 0.5rem;
|
||||
padding: 0.5rem 1rem 0.5rem 0.75rem;
|
||||
margin: 0.5rem;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.sm-html p.info::before {
|
||||
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z' fill='currentColor' /%3E%3C/svg%3E");
|
||||
display: inline-block;
|
||||
color: rgba(14,165,233,1);
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
margin-right: 0.5rem;
|
||||
margin-top: 0.1rem;
|
||||
}
|
||||
|
||||
.sm-editor::-webkit-scrollbar {
|
||||
background-color: transparent;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
.sm-editor::-webkit-scrollbar-thumb {
|
||||
background-color: #aaa;
|
||||
border: 4px solid transparent;
|
||||
border-radius: 8px;
|
||||
background-clip: padding-box;
|
||||
}
|
||||
|
||||
.sm-html .ProseMirror { outline: none; }
|
||||
.sm-html hr { border-top: 1px solid #aaa; margin: 1.5rem 0; }
|
||||
.sm-html pre { padding: 0 1rem; line-height: 1rem; }
|
||||
.sm-html blockquote { border-left: 4px solid #ddd; margin-left: 1rem; padding-left: 1rem; }
|
||||
.sm-html p.info, .sm-html p.success, .sm-html p.warning, .sm-html p.danger { display: flex; border-radius: 0.5rem; padding: 0.5rem 1rem 0.5rem 0.75rem; margin: 0.5rem; font-size: 80%; }
|
||||
.sm-html p.info::before, .sm-html p.success::before, .sm-html p.warning::before, .sm-html p.danger::before { display: inline-block; width: 1.5rem; height: 1.5rem; margin-right: 0.5rem; margin-top: 0.1rem; }
|
||||
.sm-html p.info { border: 1px solid rgba(14,165,233,1); background-color: rgba(14,165,233,0.25); }
|
||||
.sm-html p.info::before { color: rgba(14,165,233,1); content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z' fill='rgba(14,165,233,1)' /%3E%3C/svg%3E"); }
|
||||
.sm-html p.success { border: 1px solid rgba(22,163,74,1); background-color: rgba(22,163,74,0.25); }
|
||||
.sm-html p.success::before { color: rgba(22,163,74,1); content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M12 2C6.5 2 2 6.5 2 12S6.5 22 12 22 22 17.5 22 12 17.5 2 12 2M12 20C7.59 20 4 16.41 4 12S7.59 4 12 4 20 7.59 20 12 16.41 20 12 20M16.59 7.58L10 14.17L7.41 11.59L6 13L10 17L18 9L16.59 7.58Z' fill='rgba(22,163,74,1)' /%3E%3C/svg%3E"); }
|
||||
.sm-html p.warning { border: 1px solid rgba(202,138,4,1); background-color: rgba(250,204,21,0.25); }
|
||||
.sm-html p.warning::before { color: rgba(202,138,4,1); content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M12,2L1,21H23M12,6L19.53,19H4.47M11,10V14H13V10M11,16V18H13V16' fill='rgba(202,138,4,1)' /%3E%3C/svg%3E"); }
|
||||
.sm-html p.danger { border: 1px solid rgba(220,38,38,1); background-color: rgba(220,38,38,0.25); }
|
||||
.sm-html p.danger::before { color: rgba(220,38,38,1); content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M8.27,3L3,8.27V15.73L8.27,21H15.73L21,15.73V8.27L15.73,3M8.41,7L12,10.59L15.59,7L17,8.41L13.41,12L17,15.59L15.59,17L12,13.41L8.41,17L7,15.59L10.59,12L7,8.41' fill='rgba(220,38,38,1)' /%3E%3C/svg%3E"); }
|
||||
.sm-editor::-webkit-scrollbar { background-color: transparent; width: 16px; }
|
||||
.sm-editor::-webkit-scrollbar-thumb { background-color: #aaa; border: 4px solid transparent; border-radius: 8px; background-clip: padding-box; }
|
||||
@keyframes rotate{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
Reference in New Issue
Block a user