From 6336f2901c070f1868af4de9f153b0e3bc218be6 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Thu, 8 Jun 2023 16:56:58 +0700 Subject: [PATCH] UBER-433: Allow tabs within bullets. (#3399) Signed-off-by: Andrey Sobolev --- .../components/CollaborationDiffViewer.svelte | 6 --- .../src/components/CollaboratorEditor.svelte | 6 --- .../src/components/StyledTextBox.svelte | 8 +++- .../src/components/StyledTextEditor.svelte | 8 ++++ .../text-editor/src/components/extensions.ts | 39 +++++++++---------- packages/theme/styles/prose.scss | 8 ++++ packages/ui/src/focus.ts | 13 +++++-- 7 files changed, 51 insertions(+), 37 deletions(-) diff --git a/packages/text-editor/src/components/CollaborationDiffViewer.svelte b/packages/text-editor/src/components/CollaborationDiffViewer.svelte index 147c80c60d..84d13c9291 100644 --- a/packages/text-editor/src/components/CollaborationDiffViewer.svelte +++ b/packages/text-editor/src/components/CollaborationDiffViewer.svelte @@ -221,12 +221,6 @@ white-space: nowrap; } - .code-block { - border: 1px solid var(--theme-divider-color); - border-radius: 4px; - padding: 0.5rem; - } - cmark { border-top: 1px solid lightblue; border-bottom: 1px solid lightblue; diff --git a/packages/text-editor/src/components/CollaboratorEditor.svelte b/packages/text-editor/src/components/CollaboratorEditor.svelte index 38dd4d3226..8b63039cec 100644 --- a/packages/text-editor/src/components/CollaboratorEditor.svelte +++ b/packages/text-editor/src/components/CollaboratorEditor.svelte @@ -724,12 +724,6 @@ white-space: nowrap; } - .code-block { - border: 1px solid var(--divider-color); - border-radius: 4px; - padding: 0.5rem; - } - cmark { border-top: 1px solid lightblue; border-bottom: 1px solid lightblue; diff --git a/packages/text-editor/src/components/StyledTextBox.svelte b/packages/text-editor/src/components/StyledTextBox.svelte index 0e6ca20ca4..8561516254 100644 --- a/packages/text-editor/src/components/StyledTextBox.svelte +++ b/packages/text-editor/src/components/StyledTextBox.svelte @@ -120,7 +120,13 @@ } return editable }, - isFocus: () => focused + isFocus: () => focused, + canBlur: () => { + if (focused) { + return !textEditor.catHandleTab() + } + return true + } }) const updateFocus = () => { if (focusIndex !== -1) { diff --git a/packages/text-editor/src/components/StyledTextEditor.svelte b/packages/text-editor/src/components/StyledTextEditor.svelte index 0ff2d1b765..4cb12c1db2 100644 --- a/packages/text-editor/src/components/StyledTextEditor.svelte +++ b/packages/text-editor/src/components/StyledTextEditor.svelte @@ -107,6 +107,14 @@ export function insertText (text: string): void { textEditor.insertText(text) } + export function catHandleTab (): boolean { + return ( + textEditor.checkIsActive('bulletList') || + textEditor.checkIsActive('orderedList') || + textEditor.checkIsActive('code') || + textEditor.checkIsActive('codeBlock') + ) + } $: varsStyle = maxHeight === 'card' diff --git a/packages/text-editor/src/components/extensions.ts b/packages/text-editor/src/components/extensions.ts index cf5a88b44d..a248032681 100644 --- a/packages/text-editor/src/components/extensions.ts +++ b/packages/text-editor/src/components/extensions.ts @@ -6,12 +6,10 @@ import TableRow from '@tiptap/extension-table-row' import TaskItem from '@tiptap/extension-task-item' import TaskList from '@tiptap/extension-task-list' -import Heading, { Level } from '@tiptap/extension-heading' +import { Level } from '@tiptap/extension-heading' import Highlight from '@tiptap/extension-highlight' import StarterKit from '@tiptap/starter-kit' -import Code from '@tiptap/extension-code' -import TipTapCodeBlock from '@tiptap/extension-code-block' import Gapcursor from '@tiptap/extension-gapcursor' import { AnyExtension } from '@tiptap/core' @@ -46,28 +44,29 @@ export const taskListExtensions = [ export const headingLevels: Level[] = [1, 2, 3, 4, 5, 6] export const defaultExtensions: AnyExtension[] = [ - StarterKit, + StarterKit.configure({ + code: { + HTMLAttributes: { + class: 'proseCode' + } + }, + codeBlock: { + languageClassPrefix: 'language-', + exitOnArrowDown: true, + exitOnTripleEnter: true, + HTMLAttributes: { + class: 'proseCodeBlock' + } + }, + heading: { + levels: headingLevels + } + }), Highlight.configure({ multicolor: false }), - TipTapCodeBlock.configure({ - languageClassPrefix: 'language-', - exitOnArrowDown: true, - exitOnTripleEnter: true, - HTMLAttributes: { - class: 'code-block' - } - }), - Code.configure({ - HTMLAttributes: { - class: 'proseCode' - } - }), Typography.configure({}), Gapcursor, - Heading.configure({ - levels: headingLevels - }), Link.configure({ openOnClick: true, HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' } diff --git a/packages/theme/styles/prose.scss b/packages/theme/styles/prose.scss index ffd2ce8faf..f334cf4eee 100644 --- a/packages/theme/styles/prose.scss +++ b/packages/theme/styles/prose.scss @@ -54,3 +54,11 @@ table.proseTable { border: 1px solid var(--theme-button-border); border-radius: .25rem; } + +.proseCodeBlock { + font-family: var(--mono-font); + background-color: var(--theme-button-enabled); + border: 1px solid var(--theme-button-border); + border-radius: .25rem; + padding: 0.5rem; +} \ No newline at end of file diff --git a/packages/ui/src/focus.ts b/packages/ui/src/focus.ts index 37f9369145..297d7828d3 100644 --- a/packages/ui/src/focus.ts +++ b/packages/ui/src/focus.ts @@ -20,11 +20,12 @@ class FocusManagerImpl implements FocusManager { order: number focus: () => boolean isFocus: () => boolean + canBlur?: () => boolean }> = [] current = 0 - register (order: number, focus: () => boolean, isFocus: () => boolean): number { - const el = { id: this.counter++, order, focus, isFocus } + register (order: number, focus: () => boolean, isFocus: () => boolean, canBlur?: () => boolean): number { + const el = { id: this.counter++, order, focus, isFocus, canBlur } this.elements.push(el) this.sort() return el.id @@ -43,6 +44,10 @@ class FocusManagerImpl implements FocusManager { } next (inc?: 1 | -1): void { + const current = this.elements[this.current] + if (!(current?.canBlur?.() ?? false)) { + return + } while (true) { this.current = this.current + (inc ?? 1) if (this.elements[Math.abs(this.current) % this.elements.length].focus()) { @@ -116,13 +121,13 @@ export function getFocusManager (): FocusManager | undefined { */ export function registerFocus ( order: number, - item: { focus: () => boolean, isFocus: () => boolean } + item: { focus: () => boolean, isFocus: () => boolean, canBlur?: () => boolean } ): { idx: number, focusManager?: FocusManager } { const focusManager = getFocusManager() as FocusManagerImpl if (order === -1) { return { idx: -1, focusManager } } - const idx = focusManager?.register(order, item.focus, item.isFocus) ?? -1 + const idx = focusManager?.register(order, item.focus, item.isFocus, item.canBlur) ?? -1 if (idx !== -1) { onDestroy(() => { focusManager.unregister(idx)