Skip to content

Commit

Permalink
#326 Finish base editor
Browse files Browse the repository at this point in the history
  • Loading branch information
wouter-adriaens committed Oct 4, 2024
1 parent 29f59d8 commit 17eb19f
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 40 deletions.
5 changes: 5 additions & 0 deletions .storybook/main.scss
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@
.vl-modal-backdrop {
display: none;
}

// Skip showing de default story a second time because an editor with duplicate id's will break
#stories + #anchor--dumb-components-editor--default {
display: none;
}
142 changes: 102 additions & 40 deletions src/components/dumb/OeEditor.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<template>
<div>
<div id="toolbar">
<div :id="props.id">
<div :id="`${props.id}-toolbar`">
<div class="toolbar-group">
<button class="ql-undo" title="Undo">
<button v-if="props.toolbar.undo" class="ql-undo" title="Undo">
<font-awesome-icon :icon="['fas', 'rotate-left']" />
</button>
<button class="ql-redo" title="Redo">
<button v-if="props.toolbar.redo" class="ql-redo" title="Redo">
<font-awesome-icon :icon="['fas', 'rotate-right']" />
</button>

<span class="ql-stroke" />
<span v-if="props.toolbar.undo || props.toolbar.redo" class="ql-stroke" />

<!-- Add headings dropdown -->
<select class="ql-header">
<select v-if="props.toolbar.header" class="ql-header">
<option value="">Paragraph</option>
<option value="1">Heading 1</option>
<option value="2">Heading 2</option>
Expand All @@ -22,26 +22,33 @@
<option value="6">Heading 6</option>
</select>

<span class="ql-stroke" />
<span v-if="props.toolbar.header" class="ql-stroke" />

<!-- Add a bold button -->
<button class="ql-bold"></button>
<button class="ql-italic"></button>
<button v-if="props.toolbar.bold" class="ql-bold"></button>
<button v-if="props.toolbar.italic" class="ql-italic"></button>

<span class="ql-stroke" />
<span v-if="props.toolbar.bold || props.toolbar.italic" class="ql-stroke" />

<button class="ql-list" value="ordered"></button>
<button class="ql-list" value="bullet"></button>
<button class="ql-indent" value="-1"></button>
<button class="ql-indent" value="+1"></button>
<button v-if="props.toolbar.numlist" class="ql-list" value="ordered"></button>
<button v-if="props.toolbar.bullist" class="ql-list" value="bullet"></button>
<button v-if="props.toolbar.outdent" class="ql-indent" value="-1"></button>
<button v-if="props.toolbar.indent" class="ql-indent" value="+1"></button>

<span class="ql-stroke" />
<span
v-if="props.toolbar.numlist || props.toolbar.bullist || props.toolbar.outdent || props.toolbar.indent"
class="ql-stroke"
/>

<button class="ql-clean"></button>
<button v-if="props.toolbar.removeformat" class="ql-clean"></button>

<span class="ql-stroke" />
<span v-if="props.toolbar.removeformat" class="ql-stroke" />

<button class="ql-private" title="Prive">
<button v-if="props.toolbar.biblio" class="ql-biblio" title="Bibliografie">
<font-awesome-icon :icon="['fas', 'bookmark']" />
</button>

<button v-if="props.toolbar.private" class="ql-private" title="Prive">
<font-awesome-icon :icon="['fas', 'lock']" />
</button>
</div>
Expand All @@ -50,7 +57,7 @@
<QuillyEditor
ref="editor"
v-model="model"
style="height: 400px"
:style="{ height: `${props.height}px` }"
:options="options"
@blur="model = quill?.getSemanticHTML()"
/>
Expand All @@ -63,33 +70,72 @@ import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import Quill from 'quill';
import { htmlEditButton } from 'quill-html-edit-button';
import QuillToggleFullscreenButton from 'quill-toggle-fullscreen-button';
import { onMounted, ref } from 'vue';
import { computed, onMounted, ref, watch } from 'vue';
import { QuillyEditor } from 'vue-quilly';
import { PrivateBlock } from '@models/editor';
import { BibliografieBlock, type OeEditorProps, PrivateBlock } from '@models/editor';
const props = withDefaults(defineProps<OeEditorProps>(), {
height: 400,
modDisabled: false,
toolbar: () => ({
undo: true,
redo: true,
header: true,
bold: true,
italic: true,
bullist: true,
numlist: true,
indent: true,
outdent: true,
removeformat: true,
biblio: false,
private: false,
code: false,
fullscreen: false,
}),
});
// Register custom blocks and modules
Quill.register(PrivateBlock, true);
Quill.register('modules/htmlEditButton', htmlEditButton);
Quill.register('modules/toggleFullscreen', QuillToggleFullscreenButton);
Quill.register(BibliografieBlock, true);
if (props.toolbar.code) {
Quill.register('modules/htmlEditButton', htmlEditButton);
}
if (props.toolbar.fullscreen) {
Quill.register('modules/toggleFullscreen', QuillToggleFullscreenButton);
}
// Quill config
let quill: Quill;
const editor = ref<InstanceType<typeof QuillyEditor>>();
const options = {
const options = computed(() => ({
theme: 'snow',
modules: {
toolbar: {
container: '#toolbar',
container: `#${props.id}-toolbar`,
handlers: {
private: (checked: boolean) => {
quill?.format('private', checked);
if (quill.isEnabled()) {
quill?.format('private', checked);
}
},
biblio: (checked: boolean) => {
if (quill.isEnabled()) {
quill?.format('biblio', checked);
}
},
undo: () => {
return quill?.history.undo();
if (quill.isEnabled()) {
return quill?.history.undo();
}
},
redo: () => {
return quill?.history.redo();
if (quill.isEnabled()) {
return quill?.history.redo();
}
},
},
},
Expand All @@ -98,26 +144,42 @@ const options = {
maxStack: 500,
userOnly: true,
},
htmlEditButton: {
buttonTitle: 'Source code',
msg: 'Source code',
okText: 'Opslaan',
cancelText: 'Annuleren',
},
toggleFullscreen: {
buttonTitle: 'Fullscreen',
},
...(props.toolbar.code && {
htmlEditButton: {
prependSelector: `#${props.id}`,
buttonTitle: 'Source code',
msg: 'Source code',
okText: 'Opslaan',
cancelText: 'Annuleren',
},
}),
...(props.toolbar.fullscreen && {
toggleFullscreen: {
buttonTitle: 'Fullscreen',
},
}),
},
placeholder: 'Compose an epic...',
readOnly: false,
};
placeholder: '',
readOnly: props.modDisabled,
}));
// Model
const model = defineModel({ type: String });
onMounted(() => {
quill = editor.value?.initialize(Quill) as Quill;
});
watch(
() => props.modDisabled,
() => {
if (props.modDisabled) {
quill.disable();
} else {
quill.enable();
}
}
);
</script>
<style lang="scss" scoped>
Expand Down
30 changes: 30 additions & 0 deletions src/models/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,33 @@ export class PrivateBlock extends Block {
static className = 'prive';
static blotName = 'private';
}

export class BibliografieBlock extends Block {
static tagName = 'DIV';
static className = 'biblio';
static blotName = 'biblio';
}

export interface OeEditorProps {
id: string;
height?: number;
modDisabled?: boolean;
toolbar?: OeEditorToolbarConfig;
}

export interface OeEditorToolbarConfig {
undo?: boolean;
redo?: boolean;
header?: boolean;
bold?: boolean;
italic?: boolean;
bullist?: boolean;
numlist?: boolean;
outdent?: boolean;
indent?: boolean;
removeformat?: boolean;
private?: boolean;
biblio?: boolean;
code?: boolean;
fullscreen?: boolean;
}
1 change: 1 addition & 0 deletions src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@ export * from './user';
export * from './wizard';
export * from './dossier';
export * from './workflow';
export * from './editor';
39 changes: 39 additions & 0 deletions src/stories/dumb-components/editor.stories.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import '@/scss/main.scss';
import { ref } from 'vue';
import OeEditor from '@components/dumb/OeEditor.vue';
import { type OeEditorToolbarConfig } from '@models/editor';
import type { Meta, StoryObj } from '@storybook/vue3';

// More on how to set up stories at: https://storybook.js.org/docs/vue/writing-stories/introduction
Expand Down Expand Up @@ -57,3 +58,41 @@ export const Default: Story = {
`,
}),
};

export const FulloptionToolbar: Story = {
parameters: {
docs: {
story: {
height: '500px',
},
},
},
render: () => ({
components: {
OeEditor,
},
setup() {
const model = ref('');
const toolbar = ref<OeEditorToolbarConfig>({
undo: true,
redo: true,
bold: true,
italic: true,
bullist: true,
numlist: true,
fullscreen: true,
indent: true,
outdent: true,
code: true,
private: true,
header: true,
removeformat: true,
biblio: true,
});
return { model, toolbar };
},
template: `
<oe-editor id="editor-2" v-model="model" :toolbar="toolbar" />
`,
}),
};

0 comments on commit 17eb19f

Please sign in to comment.