diff --git a/packages/nc-gui/components/cell/MultiSelect.vue b/packages/nc-gui/components/cell/MultiSelect.vue index 5b91e4dadb..10913279e9 100644 --- a/packages/nc-gui/components/cell/MultiSelect.vue +++ b/packages/nc-gui/components/cell/MultiSelect.vue @@ -10,6 +10,7 @@ import { EditColumnInj, EditModeInj, IsKanbanInj, + IsSurveyFormInj, ReadonlyInj, RowHeightInj, computed, @@ -64,6 +65,8 @@ const isEditColumn = inject(EditColumnInj, ref(false)) const rowHeight = inject(RowHeightInj, ref(undefined)) +const isSurveyForm = inject(IsSurveyFormInj, ref(false)) + const selectedIds = ref([]) const aselect = ref() @@ -386,6 +389,8 @@ const onFocus = () => { isFocusing.value = false }, 250) + if (isSurveyForm.value && vModel.value?.length) return + isOpen.value = true } diff --git a/packages/nc-gui/components/cell/RichText.vue b/packages/nc-gui/components/cell/RichText.vue index 422bea455f..4bc2c87660 100644 --- a/packages/nc-gui/components/cell/RichText.vue +++ b/packages/nc-gui/components/cell/RichText.vue @@ -9,22 +9,31 @@ import Underline from '@tiptap/extension-underline' import Placeholder from '@tiptap/extension-placeholder' import { TaskItem } from '@/helpers/dbTiptapExtensions/task-item' import { Link } from '@/helpers/dbTiptapExtensions/links' +import type { RichTextBubbleMenuOptions } from '#imports' import { IsExpandedFormOpenInj, IsFormInj, IsGridInj, ReadonlyInj, RowHeightInj } from '#imports' -const props = defineProps<{ - value?: string | null - readOnly?: boolean - syncValueChange?: boolean - showMenu?: boolean - fullMode?: boolean - isFormField?: boolean - autofocus?: boolean - placeholder?: string - renderAsText?: boolean -}>() +const props = withDefaults( + defineProps<{ + value?: string | null + readOnly?: boolean + syncValueChange?: boolean + showMenu?: boolean + fullMode?: boolean + isFormField?: boolean + autofocus?: boolean + placeholder?: string + renderAsText?: boolean + hiddenBubbleMenuOptions?: RichTextBubbleMenuOptions[] + }>(), + { + hiddenBubbleMenuOptions: () => [], + }, +) const emits = defineEmits(['update:value']) +const { hiddenBubbleMenuOptions } = toRefs(props) + const isExpandedFormOpen = inject(IsExpandedFormOpenInj, ref(false))! const rowHeight = inject(RowHeightInj, ref(1 as const)) @@ -208,7 +217,8 @@ useEventListener( editorDom, 'focusout', (e: FocusEvent) => { - if (!(e?.relatedTarget as HTMLElement)?.closest('.bubble-menu, .nc-textarea-rich-editor')) { + const targetEl = e?.relatedTarget as HTMLElement + if (targetEl?.classList?.contains('tiptap') || !targetEl?.closest('.bubble-menu, .nc-textarea-rich-editor')) { isFocused.value = false } }, @@ -223,7 +233,7 @@ useEventListener( 'flex flex-col flex-grow nc-rich-text-full': fullMode, 'nc-rich-text-embed flex flex-col pl-1 w-full': !fullMode, 'readonly': readOnly, - 'nc-form-rich-text-field !p-0': isFormField, + 'nc-form-rich-text-field !p-0 relative': isFormField, 'nc-rich-text-grid': isGrid, }" :tabindex="readOnlyCell || isFormField ? -1 : 0" @@ -251,21 +261,26 @@ useEventListener( class="flex flex-col nc-textarea-rich-editor w-full" :class="{ 'mt-2.5 flex-grow': fullMode, - 'nc-scrollbar-md': !fullMode || (!fullMode && isExpandedFormOpen), + 'scrollbar-thin scrollbar-thumb-gray-200 scrollbar-track-transparent': !fullMode || (!fullMode && isExpandedFormOpen), 'flex-grow': isExpandedFormOpen, [`!overflow-hidden children:line-clamp-${rowHeight}`]: !fullMode && readOnly && rowHeight && !isExpandedFormOpen && !isForm, }" /> -
+
- +
@@ -343,7 +358,7 @@ useEventListener( .nc-textarea-rich-editor { .tiptap p.is-editor-empty:first-child::before { - color: #6a7184; + color: #9aa2af; content: attr(data-placeholder); float: left; height: 0; @@ -462,4 +477,9 @@ useEventListener( height: fit-content; } } +.nc-form-field-bubble-menu-wrapper { + @apply absolute -bottom-9 left-1/2 z-50 rounded-lg; + transform: translateX(-50%); + box-shadow: 0px 8px 8px -4px rgba(0, 0, 0, 0.04), 0px 20px 24px -4px rgba(0, 0, 0, 0.1); +} diff --git a/packages/nc-gui/components/cell/RichText/SelectedBubbleMenu.vue b/packages/nc-gui/components/cell/RichText/SelectedBubbleMenu.vue index ed5048d9fd..7d48b3b472 100644 --- a/packages/nc-gui/components/cell/RichText/SelectedBubbleMenu.vue +++ b/packages/nc-gui/components/cell/RichText/SelectedBubbleMenu.vue @@ -10,16 +10,22 @@ import MsFormatH3 from '~icons/material-symbols/format-h3' import TablerBlockQuote from '~icons/tabler/blockquote' import MsCode from '~icons/material-symbols/code' import MsFormatQuote from '~icons/material-symbols/format-quote' +import { RichTextBubbleMenuOptions } from '#imports' interface Props { editor: Editor embedMode?: boolean isFormField?: boolean + hiddenOptions?: RichTextBubbleMenuOptions[] } -const props = defineProps() +const props = withDefaults(defineProps(), { + embedMode: false, + isFormField: false, + hiddenOptions: () => [], +}) -const { editor, embedMode } = toRefs(props) +const { editor, embedMode, isFormField, hiddenOptions } = toRefs(props) const cmdOrCtrlKey = computed(() => { return isMac() ? '⌘' : 'CTRL' @@ -33,6 +39,14 @@ const altKey = computed(() => { return isMac() ? '⌥' : 'Alt' }) +const tooltipPlacement = computed(() => { + if (isFormField.value) return 'bottom' +}) + +const tabIndex = computed(() => { + return isFormField.value ? -1 : 0 +}) + const onToggleLink = () => { const activeNode = editor.value?.state?.selection?.$from?.nodeBefore || editor.value?.state?.selection?.$from?.nodeAfter @@ -74,19 +88,29 @@ const onToggleLink = () => { }, 100) } } + +const isOptionVisible = (option: RichTextBubbleMenuOptions) => { + if (isFormField.value) return !hiddenOptions.value.includes(option) + + return true +} + +const showDivider = (options: RichTextBubbleMenuOptions[]) => { + return !isFormField.value || options.some((o) => !hiddenOptions.value.includes(o)) +}