UBER-433: Allow tabs within bullets. (#3399)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2023-06-08 16:56:58 +07:00 committed by GitHub
parent d4136569ad
commit 6336f2901c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 51 additions and 37 deletions

View File

@ -221,12 +221,6 @@
white-space: nowrap; white-space: nowrap;
} }
.code-block {
border: 1px solid var(--theme-divider-color);
border-radius: 4px;
padding: 0.5rem;
}
cmark { cmark {
border-top: 1px solid lightblue; border-top: 1px solid lightblue;
border-bottom: 1px solid lightblue; border-bottom: 1px solid lightblue;

View File

@ -724,12 +724,6 @@
white-space: nowrap; white-space: nowrap;
} }
.code-block {
border: 1px solid var(--divider-color);
border-radius: 4px;
padding: 0.5rem;
}
cmark { cmark {
border-top: 1px solid lightblue; border-top: 1px solid lightblue;
border-bottom: 1px solid lightblue; border-bottom: 1px solid lightblue;

View File

@ -120,7 +120,13 @@
} }
return editable return editable
}, },
isFocus: () => focused isFocus: () => focused,
canBlur: () => {
if (focused) {
return !textEditor.catHandleTab()
}
return true
}
}) })
const updateFocus = () => { const updateFocus = () => {
if (focusIndex !== -1) { if (focusIndex !== -1) {

View File

@ -107,6 +107,14 @@
export function insertText (text: string): void { export function insertText (text: string): void {
textEditor.insertText(text) textEditor.insertText(text)
} }
export function catHandleTab (): boolean {
return (
textEditor.checkIsActive('bulletList') ||
textEditor.checkIsActive('orderedList') ||
textEditor.checkIsActive('code') ||
textEditor.checkIsActive('codeBlock')
)
}
$: varsStyle = $: varsStyle =
maxHeight === 'card' maxHeight === 'card'

View File

@ -6,12 +6,10 @@ import TableRow from '@tiptap/extension-table-row'
import TaskItem from '@tiptap/extension-task-item' import TaskItem from '@tiptap/extension-task-item'
import TaskList from '@tiptap/extension-task-list' 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 Highlight from '@tiptap/extension-highlight'
import StarterKit from '@tiptap/starter-kit' 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 Gapcursor from '@tiptap/extension-gapcursor'
import { AnyExtension } from '@tiptap/core' import { AnyExtension } from '@tiptap/core'
@ -46,28 +44,29 @@ export const taskListExtensions = [
export const headingLevels: Level[] = [1, 2, 3, 4, 5, 6] export const headingLevels: Level[] = [1, 2, 3, 4, 5, 6]
export const defaultExtensions: AnyExtension[] = [ export const defaultExtensions: AnyExtension[] = [
StarterKit, StarterKit.configure({
Highlight.configure({ code: {
multicolor: false HTMLAttributes: {
}), class: 'proseCode'
TipTapCodeBlock.configure({ }
},
codeBlock: {
languageClassPrefix: 'language-', languageClassPrefix: 'language-',
exitOnArrowDown: true, exitOnArrowDown: true,
exitOnTripleEnter: true, exitOnTripleEnter: true,
HTMLAttributes: { HTMLAttributes: {
class: 'code-block' class: 'proseCodeBlock'
}
},
heading: {
levels: headingLevels
} }
}), }),
Code.configure({ Highlight.configure({
HTMLAttributes: { multicolor: false
class: 'proseCode'
}
}), }),
Typography.configure({}), Typography.configure({}),
Gapcursor, Gapcursor,
Heading.configure({
levels: headingLevels
}),
Link.configure({ Link.configure({
openOnClick: true, openOnClick: true,
HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' } HTMLAttributes: { class: 'cursor-pointer', rel: 'noopener noreferrer', target: '_blank' }

View File

@ -54,3 +54,11 @@ table.proseTable {
border: 1px solid var(--theme-button-border); border: 1px solid var(--theme-button-border);
border-radius: .25rem; 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;
}

View File

@ -20,11 +20,12 @@ class FocusManagerImpl implements FocusManager {
order: number order: number
focus: () => boolean focus: () => boolean
isFocus: () => boolean isFocus: () => boolean
canBlur?: () => boolean
}> = [] }> = []
current = 0 current = 0
register (order: number, focus: () => boolean, isFocus: () => boolean): number { register (order: number, focus: () => boolean, isFocus: () => boolean, canBlur?: () => boolean): number {
const el = { id: this.counter++, order, focus, isFocus } const el = { id: this.counter++, order, focus, isFocus, canBlur }
this.elements.push(el) this.elements.push(el)
this.sort() this.sort()
return el.id return el.id
@ -43,6 +44,10 @@ class FocusManagerImpl implements FocusManager {
} }
next (inc?: 1 | -1): void { next (inc?: 1 | -1): void {
const current = this.elements[this.current]
if (!(current?.canBlur?.() ?? false)) {
return
}
while (true) { while (true) {
this.current = this.current + (inc ?? 1) this.current = this.current + (inc ?? 1)
if (this.elements[Math.abs(this.current) % this.elements.length].focus()) { if (this.elements[Math.abs(this.current) % this.elements.length].focus()) {
@ -116,13 +121,13 @@ export function getFocusManager (): FocusManager | undefined {
*/ */
export function registerFocus ( export function registerFocus (
order: number, order: number,
item: { focus: () => boolean, isFocus: () => boolean } item: { focus: () => boolean, isFocus: () => boolean, canBlur?: () => boolean }
): { idx: number, focusManager?: FocusManager } { ): { idx: number, focusManager?: FocusManager } {
const focusManager = getFocusManager() as FocusManagerImpl const focusManager = getFocusManager() as FocusManagerImpl
if (order === -1) { if (order === -1) {
return { idx: -1, focusManager } 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) { if (idx !== -1) {
onDestroy(() => { onDestroy(() => {
focusManager.unregister(idx) focusManager.unregister(idx)