Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
ARG PNPM_HOME="/root/.local/share/pnpm"
ARG PNPM_VERSION="8.8.0"
ARG PNPM_VERSION="10.12.3"

FROM node:20.10.0-alpine3.18
ARG PNPM_HOME
FROM node:24-alpine
ARG PNPM_VERSION
# github and ssh
RUN apk add openssh-client && apk add git
Expand Down
6 changes: 6 additions & 0 deletions packages/display/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @tailor-cms/ce-html-display

## 0.1.2

### Patch Changes

- Add option to add text tooltips.

## 0.1.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/display/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Tailor CMS HTML editor end-user component",
"author": "Studion <info@gostudion.com> (https://github.com/tailor-cms)",
"type": "module",
"version": "0.1.1",
"version": "0.1.2",
"exports": {
".": {
"import": "./dist/index.js",
Expand Down
50 changes: 50 additions & 0 deletions packages/display/src/components/Display.vue
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,55 @@ defineProps<{ element: Element }>();
}
}
}

:deep(.has-tooltip) {
$tooltip-color: rgba(33, 33, 33, 0.8);
$border-size: 6px;

position: relative;
display: inline-block;
background: rgb(205 215 220 / 70%);
text-decoration: underline dashed $tooltip-color;
cursor: help;

&::before {
content: '';
position: absolute;
bottom: 100%;
border-left: $border-size solid transparent;
border-right: $border-size solid transparent;
border-top: $border-size solid $tooltip-color;
}

&::after {
content: attr(data-tooltip);
position: absolute;
bottom: calc(100% + #{$border-size});
left: -0.625rem;
border-radius: 4px;
max-width: 14rem;
padding: 0.375rem 0.675rem;
background: $tooltip-color;
font-size: 0.875rem;
color: #fff;
font-weight: normal;
width: max-content;
}

&::before,
&::after {
text-decoration: none;
visibility: hidden;
opacity: 0;
transition: all 0.3s ease-out;
}

&:hover::after,
&:hover::before {
visibility: visible;
opacity: 1;
margin-bottom: 0.25rem;
}
}
}
</style>
6 changes: 6 additions & 0 deletions packages/edit/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# @tailor-cms/ce-html-edit

## 0.1.2

### Patch Changes

- Add option to add text tooltips.

## 0.1.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/edit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Tailor CMS HTML editor authoring component",
"author": "Studion <info@gostudion.com> (https://github.com/tailor-cms)",
"type": "module",
"version": "0.1.1",
"version": "0.1.2",
"exports": {
".": {
"import": "./dist/index.js",
Expand Down
50 changes: 50 additions & 0 deletions packages/edit/src/components/Edit.vue
Original file line number Diff line number Diff line change
Expand Up @@ -221,4 +221,54 @@ watch(
}
}
}

:deep(.has-tooltip) {
$tooltip-color: rgba(33, 33, 33, 0.8);
$border-size: 6px;

position: relative;
display: inline-block;
background: rgb(205 215 220 / 70%);
text-decoration: underline dashed $tooltip-color;
cursor: help;

&::before {
content: '';
position: absolute;
bottom: 100%;
border-left: $border-size solid transparent;
border-right: $border-size solid transparent;
border-top: $border-size solid $tooltip-color;
}

&::after {
content: attr(data-tooltip);
position: absolute;
bottom: calc(100% + #{$border-size});
left: -0.625rem;
border-radius: 4px;
max-width: 14rem;
padding: 0.375rem 0.675rem;
background: $tooltip-color;
font-size: 0.875rem;
color: #fff;
font-weight: normal;
width: max-content;
}

&::before,
&::after {
text-decoration: none;
visibility: hidden;
opacity: 0;
transition: all 0.3s ease-out;
}

&:hover::after,
&:hover::before {
visibility: visible;
opacity: 1;
margin-bottom: 0.25rem;
}
}
</style>
2 changes: 2 additions & 0 deletions packages/edit/src/components/EditorToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { Component as VueComponent } from 'vue';
import AddImage from './actions/AddImage.vue';
import AddLink from './actions/AddLink.vue';
import AddTable from './actions/AddTable.vue';
import AddTooltip from './actions/AddTooltip.vue';
import FontFamily from './actions/FontFamily.vue';
import FontSize from './actions/FontSize.vue';
import IconButton from './IconButton.vue';
Expand Down Expand Up @@ -91,6 +92,7 @@ const toolbarItems: (Action | Component)[][] = [
{ component: AddLink },
{ component: AddTable },
{ component: AddImage },
{ component: AddTooltip },
{
label: 'Horizontal line',
action: ['setHorizontalRule'],
Expand Down
9 changes: 6 additions & 3 deletions packages/edit/src/components/actions/AddLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
size="32"
v-bind="mergeProps(menu, tooltip)"
>
<VIcon size="24">mdi-link</VIcon>
<VIcon size="24">mdi-link-variant-plus</VIcon>
</VBtn>
</template>
Add link
Expand Down Expand Up @@ -39,12 +39,15 @@
<VBtn
v-if="editor.isActive('link')"
class="mr-2"
variant="plain"
color="primary-darken-3"
variant="text"
@click="unlink"
>
Unlink
</VBtn>
<VBtn color="primary" type="submit" variant="tonal">Confirm</VBtn>
<VBtn color="primary-darken-3" type="submit" variant="tonal">
Confirm
</VBtn>
</div>
</VSheet>
</VForm>
Expand Down
107 changes: 107 additions & 0 deletions packages/edit/src/components/actions/AddTooltip.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<template>
<VMenu v-model="show" :close-on-content-click="false">
<template #activator="{ props: menu }">
<VTooltip location="bottom">
<template #activator="{ props: tooltipProps }">
<VBtn
:active="editor.isActive('tooltip')"
:disabled="!editor.can().chain().focus().setTooltip().run()"
aria-label="Add tooltip"
rounded="lg"
size="32"
v-bind="mergeProps(menu, tooltipProps)"
>
<VIcon size="24">mdi-tooltip-text</VIcon>
</VBtn>
</template>
Add tooltip
</VTooltip>
</template>
<VForm ref="form" @submit.prevent="setTooltip">
<VSheet class="pa-3" elevation="8" width="240" rounded>
<VTextField
v-model="text"
:rules="[rules.required]"
density="compact"
hide-details="auto"
label="Text"
variant="outlined"
/>
<VTextField
v-model="tooltip"
:rules="[rules.required]"
density="compact"
hide-details="auto"
label="Tooltip"
variant="outlined"
/>
<div class="actions d-flex justify-end">
<VBtn
v-if="editor.isActive('tooltip')"
class="mr-2"
variant="plain"
@click="unset"
>
Remove
</VBtn>
<VBtn color="primary" type="submit" variant="tonal">Confirm</VBtn>
</div>
</VSheet>
</VForm>
</VMenu>
</template>

<script setup lang="ts">
import { mergeProps, ref, watch } from 'vue';

const rules = {
required: (val: string) => !!val || 'The field is required',
};

const props = defineProps<{ editor: any }>();

const form = ref();

const getText = () => {
const { view, state } = props.editor;
const { from, to } = view.state.selection;
return state.doc.textBetween(from, to, ' ');
};

const tooltip = ref<string>('');
const text = ref<string>('');
const show = ref<boolean>(false);

function unset() {
props.editor.chain().focus().unsetTooltip().run();
tooltip.value = '';
show.value = false;
}

async function setTooltip() {
const { valid } = await form.value.validate();
if (!valid) return;
if (tooltip.value) {
const attributes = { tooltip: tooltip.value, text: text.value };
console.log('Setting tooltip with attributes:', attributes);
props.editor.chain().focus().setTooltip(attributes).run();
} else props.editor.chain().focus().unsetTooltip().run();
show.value = false;
form.value.resetValidation();
}

watch(show, (val: boolean) => {
if (!val) return;
tooltip.value = props.editor.getAttributes('tooltip')['data-tooltip'] ?? '';
text.value = getText() ?? '';
form.value?.resetValidation();
});
</script>

<style lang="scss" scoped>
.v-sheet {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
</style>
2 changes: 2 additions & 0 deletions packages/edit/src/components/extensions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ import FontSize from './font-size.ts';
import Image from './image.ts';
import Link from './link.ts';
import Paragraph from './paragraph.ts';
import Tooltip from './tooltip.ts';

export default [
Color,
FontFamily,
FontSize,
Image,
Link.configure({ openOnClick: false }),
Tooltip,
StarterKit.configure({ paragraph: false }),
Subscript,
Superscript,
Expand Down
62 changes: 62 additions & 0 deletions packages/edit/src/components/extensions/tooltip.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Mark, mergeAttributes } from '@tiptap/vue-3';

declare module '@tiptap/vue-3' {
interface Commands<ReturnType> {
tooltip: {
setTooltip: (attributes: {
tooltip?: string;
text?: string;
}) => ReturnType;
unsetTooltip: () => ReturnType;
};
}
}

export default Mark.create({
name: 'tooltip',

addAttributes() {
return {
'data-tooltip': {
default: null,
parseHTML: (element) => element.getAttribute('data-tooltip'),
renderHTML: (attributes) => ({
'data-tooltip': attributes['data-tooltip'],
}),
},
};
},

parseHTML() {
return [{ tag: 'span[data-tooltip]' }];
},

renderHTML({ HTMLAttributes }) {
return [
'span',
mergeAttributes({ class: 'has-tooltip' }, HTMLAttributes),
0,
];
},

addCommands() {
return {
setTooltip:
({ tooltip, text } = {}) =>
({ chain }) => {
return chain()
.setMark(this.name, { 'data-tooltip': tooltip })
.command(({ tr }: any) => {
tr.insertText(text);
return true;
})
.run();
},
unsetTooltip:
() =>
({ chain }) => {
return chain().unsetMark(this.name).run();
},
};
},
});
Loading
Loading