@blocksuite/virgo
Advanced tools
Comparing version 0.0.0-20230907222710-102d1e99-nightly to 0.0.0-20230908185655-61117b50-nightly
@@ -11,3 +11,3 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { | ||
import { styleMap } from 'lit/directives/style-map.js'; | ||
import { ZERO_WIDTH_SPACE } from '../consts.js'; | ||
import { VIRGO_ROOT_ATTR, ZERO_WIDTH_SPACE } from '../consts.js'; | ||
import { EmbedGap } from './embed-gap.js'; | ||
@@ -40,3 +40,3 @@ let VirgoLine = class VirgoLine extends LitElement { | ||
} | ||
const rootElement = this.closest('[data-virgo-root="true"]'); | ||
const rootElement = this.closest(`[${VIRGO_ROOT_ATTR}]`); | ||
assertExists(rootElement, 'v-line must be inside a v-root'); | ||
@@ -43,0 +43,0 @@ const virgoEditor = rootElement.virgoEditor; |
export declare const ZERO_WIDTH_SPACE = "\u200B"; | ||
export declare const ZERO_WIDTH_NON_JOINER = "\u200C"; | ||
export declare const VIRGO_ROOT_ATTR = "data-virgo-root"; | ||
//# sourceMappingURL=consts.d.ts.map |
export const ZERO_WIDTH_SPACE = '\u200B'; | ||
// see https://en.wikipedia.org/wiki/Zero-width_non-joiner | ||
export const ZERO_WIDTH_NON_JOINER = '\u200C'; | ||
export const VIRGO_ROOT_ATTR = 'data-virgo-root'; | ||
//# sourceMappingURL=consts.js.map |
@@ -7,3 +7,3 @@ import type { z, ZodTypeDef } from 'zod'; | ||
export declare class VirgoAttributeService<TextAttributes extends BaseTextAttributes> { | ||
private readonly _editor; | ||
readonly editor: VEditor<TextAttributes>; | ||
private _marks; | ||
@@ -10,0 +10,0 @@ private _attributeRenderer; |
import { baseTextAttributes, getDefaultAttributeRenderer, } from '../utils/index.js'; | ||
export class VirgoAttributeService { | ||
constructor(editor) { | ||
this.editor = editor; | ||
this._marks = null; | ||
@@ -20,3 +21,3 @@ this._attributeRenderer = getDefaultAttributeRenderer(); | ||
this.getFormat = (vRange, loose = false) => { | ||
const deltas = this._editor.deltaService | ||
const deltas = this.editor.deltaService | ||
.getDeltasByVRange(vRange) | ||
@@ -64,3 +65,2 @@ .filter(([_, position]) => position.index + position.length > vRange.index && | ||
}; | ||
this._editor = editor; | ||
} | ||
@@ -67,0 +67,0 @@ get marks() { |
@@ -6,3 +6,3 @@ import type { DeltaInsert } from '../types.js'; | ||
export declare class VirgoDeltaService<TextAttributes extends BaseTextAttributes> { | ||
private readonly _editor; | ||
readonly editor: VEditor<TextAttributes>; | ||
constructor(editor: VEditor<TextAttributes>); | ||
@@ -9,0 +9,0 @@ get deltas(): DeltaInsert<TextAttributes>[]; |
@@ -6,2 +6,3 @@ import { html, render } from 'lit'; | ||
constructor(editor) { | ||
this.editor = editor; | ||
this.mapDeltasInVRange = (vRange, callback, normalize = false) => { | ||
@@ -125,3 +126,3 @@ const deltas = normalize ? this.normalizedDeltas : this.deltas; | ||
this.render = async (syncVRange = true) => { | ||
const rootElement = this._editor.rootElement; | ||
const rootElement = this.editor.rootElement; | ||
const normalizedDeltas = this.normalizedDeltas; | ||
@@ -140,3 +141,3 @@ const chunks = deltaInsertsToChunks(normalizedDeltas); | ||
let selected = false; | ||
const vRange = this._editor.getVRange(); | ||
const vRange = this.editor.getVRange(); | ||
if (vRange) { | ||
@@ -146,3 +147,3 @@ selected = this.isNormalizedDeltaSelected(normalizedDeltaIndex, vRange); | ||
return [ | ||
renderElement(delta, this._editor.attributeService.normalizeAttributes, selected), | ||
renderElement(delta, this.editor.attributeService.normalizeAttributes, selected), | ||
delta, | ||
@@ -162,17 +163,16 @@ ]; | ||
// Lit may be crashed by IME input and we need to rerender whole editor for it | ||
this._editor.rerenderWholeEditor(); | ||
await this._editor.waitForUpdate(); | ||
this.editor.rerenderWholeEditor(); | ||
await this.editor.waitForUpdate(); | ||
} | ||
await this._editor.waitForUpdate(); | ||
await this.editor.waitForUpdate(); | ||
if (syncVRange) { | ||
// We need to synchronize the selection immediately after rendering is completed, | ||
// otherwise there is a possibility of an error in the cursor position | ||
this._editor.rangeService.syncVRange(); | ||
this.editor.rangeService.syncVRange(); | ||
} | ||
this._editor.slots.updated.emit(); | ||
this.editor.slots.updated.emit(); | ||
}; | ||
this._editor = editor; | ||
} | ||
get deltas() { | ||
return this._editor.yText.toDelta(); | ||
return this.editor.yText.toDelta(); | ||
} | ||
@@ -185,3 +185,3 @@ get normalizedDeltas() { | ||
for (const delta of this.deltas) { | ||
if (this._editor.isEmbed(delta)) { | ||
if (this.editor.isEmbed(delta)) { | ||
const dividedDeltas = [...delta.insert].map(subInsert => ({ | ||
@@ -202,3 +202,3 @@ insert: subInsert, | ||
if (vRange.length >= 1) { | ||
this._editor.mapDeltasInVRange(vRange, (_, rangeIndex, deltaIndex) => { | ||
this.editor.mapDeltasInVRange(vRange, (_, rangeIndex, deltaIndex) => { | ||
if (deltaIndex === normalizedDeltaIndex && | ||
@@ -205,0 +205,0 @@ rangeIndex >= vRange.index) { |
@@ -9,7 +9,8 @@ import { type BaseTextAttributes } from '../utils/index.js'; | ||
constructor(editor: VEditor<TextAttributes>); | ||
get vRangeProvider(): import("../virgo.js").VRangeProvider | null; | ||
mount: () => void; | ||
private _isRangeCompletelyInRoot; | ||
private _onSelectionChange; | ||
private _onCompositionStart; | ||
private _onCompositionEnd; | ||
private _firstRecomputeInFrame; | ||
private _onBeforeInput; | ||
@@ -16,0 +17,0 @@ private _onScroll; |
@@ -14,3 +14,5 @@ import { assertExists } from '@blocksuite/global/utils'; | ||
const rootElement = this.editor.rootElement; | ||
this.editor.disposables.addFromEvent(document, 'selectionchange', this._onSelectionChange); | ||
if (!this.vRangeProvider) { | ||
this.editor.disposables.addFromEvent(document, 'selectionchange', this._onSelectionChange); | ||
} | ||
this.editor.disposables.addFromEvent(rootElement, 'beforeinput', this._onBeforeInput); | ||
@@ -23,2 +25,21 @@ this.editor.disposables.addFromEvent(rootElement, 'compositionstart', this._onCompositionStart); | ||
}; | ||
this._isRangeCompletelyInRoot = () => { | ||
const selectionRoot = findDocumentOrShadowRoot(this.editor); | ||
const selection = selectionRoot.getSelection(); | ||
if (!selection || selection.rangeCount === 0) | ||
return false; | ||
const range = selection.getRangeAt(0); | ||
const rootElement = this.editor.rootElement; | ||
const rootRange = document.createRange(); | ||
rootRange.selectNode(rootElement); | ||
if (range.startContainer.compareDocumentPosition(range.endContainer) & | ||
Node.DOCUMENT_POSITION_FOLLOWING) { | ||
return (rootRange.comparePoint(range.startContainer, range.startOffset) >= 0 && | ||
rootRange.comparePoint(range.endContainer, range.endOffset) <= 0); | ||
} | ||
else { | ||
return (rootRange.comparePoint(range.endContainer, range.startOffset) >= 0 && | ||
rootRange.comparePoint(range.startContainer, range.endOffset) <= 0); | ||
} | ||
}; | ||
this._onSelectionChange = () => { | ||
@@ -36,3 +57,3 @@ const rootElement = this.editor.rootElement; | ||
if (previousVRange !== null) { | ||
this.editor.slots.vRangeUpdated.emit([null, 'native']); | ||
this.editor.setVRange(null, false); | ||
} | ||
@@ -62,3 +83,3 @@ return; | ||
if (previousVRange !== null) { | ||
this.editor.slots.vRangeUpdated.emit([null, 'native']); | ||
this.editor.setVRange(null, false); | ||
} | ||
@@ -72,3 +93,3 @@ return; | ||
if (!isMaybeVRangeEqual(previousVRange, vRange)) { | ||
this.editor.slots.vRangeUpdated.emit([vRange, 'native']); | ||
this.editor.setVRange(vRange, false); | ||
} | ||
@@ -99,3 +120,3 @@ // avoid infinite syncVRange | ||
await this.editor.waitForUpdate(); | ||
if (this.editor.isReadonly) | ||
if (this.editor.isReadonly || !this._isRangeCompletelyInRoot()) | ||
return; | ||
@@ -163,23 +184,29 @@ const vRange = this.editor.getVRange(); | ||
this.editor.insertText(newVRange, newData, ctx.attributes); | ||
this.editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: newVRange.index + newData.length, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
this.editor.setVRange({ | ||
index: newVRange.index + newData.length, | ||
length: 0, | ||
}, false); | ||
} | ||
} | ||
}; | ||
this._firstRecomputeInFrame = true; | ||
this._onBeforeInput = (event) => { | ||
event.preventDefault(); | ||
if (this.editor.isReadonly || this._isComposing) | ||
if (this.editor.isReadonly || | ||
this._isComposing || | ||
!this._isRangeCompletelyInRoot()) | ||
return; | ||
if (this._firstRecomputeInFrame) { | ||
this._firstRecomputeInFrame = false; | ||
this._onSelectionChange(); | ||
requestAnimationFrame(() => { | ||
this._firstRecomputeInFrame = true; | ||
}); | ||
if (!this.editor.getVRange()) | ||
return; | ||
// Sometimes input event will directly come from some scripts (e.g. browser extension), | ||
// so we need to resync the vRange. | ||
const targetRanges = event.getTargetRanges(); | ||
if (targetRanges.length > 0) { | ||
const staticRange = targetRanges[0]; | ||
const range = document.createRange(); | ||
range.setStart(staticRange.startContainer, staticRange.startOffset); | ||
range.setEnd(staticRange.endContainer, staticRange.endOffset); | ||
const vRange = this.editor.toVRange(range); | ||
if (!isMaybeVRangeEqual(this.editor.getVRange(), vRange)) { | ||
this.editor.setVRange(vRange, false); | ||
} | ||
} | ||
@@ -280,3 +307,6 @@ const vRange = this.editor.getVRange(); | ||
} | ||
get vRangeProvider() { | ||
return this.editor.vRangeProvider; | ||
} | ||
} | ||
//# sourceMappingURL=event.js.map |
@@ -6,3 +6,3 @@ import type { VRange } from '../types.js'; | ||
export declare class VirgoRangeService<TextAttributes extends BaseTextAttributes> { | ||
private readonly _editor; | ||
readonly editor: VEditor<TextAttributes>; | ||
private _prevVRange; | ||
@@ -12,3 +12,4 @@ private _vRange; | ||
constructor(editor: VEditor<TextAttributes>); | ||
onVRangeUpdated: ([newVRange, origin]: VRangeUpdatedProp) => void; | ||
get vRangeProvider(): import("../virgo.js").VRangeProvider | null; | ||
onVRangeUpdated: ([newVRange, sync]: VRangeUpdatedProp) => void; | ||
getVRange: () => VRange | null; | ||
@@ -15,0 +16,0 @@ /** |
@@ -7,8 +7,9 @@ import { VirgoLine } from '../components/index.js'; | ||
constructor(editor) { | ||
this.editor = editor; | ||
this._prevVRange = null; | ||
this._vRange = null; | ||
this._lastScrollLeft = 0; | ||
this.onVRangeUpdated = ([newVRange, origin]) => { | ||
this.onVRangeUpdated = ([newVRange, sync]) => { | ||
this._vRange = newVRange; | ||
if (this._editor.mounted && | ||
if (this.editor.mounted && | ||
newVRange && | ||
@@ -18,14 +19,18 @@ !isMaybeVRangeEqual(this._prevVRange, newVRange)) { | ||
// be broken if we sync | ||
this._editor.requestUpdate(false); | ||
this.editor.requestUpdate(false); | ||
} | ||
this._prevVRange = newVRange; | ||
if (origin !== 'other') { | ||
if (this.vRangeProvider) { | ||
this.vRangeProvider.setVRange(newVRange); | ||
return; | ||
} | ||
if (!sync) { | ||
return; | ||
} | ||
if (this._vRange === null) { | ||
const selectionRoot = findDocumentOrShadowRoot(this._editor); | ||
const selectionRoot = findDocumentOrShadowRoot(this.editor); | ||
const selection = selectionRoot.getSelection(); | ||
if (selection && selection.rangeCount > 0) { | ||
const range = selection.getRangeAt(0); | ||
if (range.intersectsNode(this._editor.rootElement)) { | ||
if (range.intersectsNode(this.editor.rootElement)) { | ||
selection.removeAllRanges(); | ||
@@ -48,2 +53,5 @@ } | ||
this.getVRange = () => { | ||
if (this.vRangeProvider) { | ||
return this.vRangeProvider.getVRange(); | ||
} | ||
return this._vRange; | ||
@@ -58,6 +66,6 @@ }; | ||
(vRange.index < 0 || | ||
vRange.index + vRange.length > this._editor.yText.length)) { | ||
vRange.index + vRange.length > this.editor.yText.length)) { | ||
throw new Error('invalid vRange'); | ||
} | ||
this._editor.slots.vRangeUpdated.emit([vRange, sync ? 'other' : 'silent']); | ||
this.editor.slots.vRangeUpdated.emit([vRange, sync]); | ||
}; | ||
@@ -68,4 +76,5 @@ /** | ||
this.syncVRange = () => { | ||
if (this._vRange && this._editor.mounted) { | ||
this._applyVRange(this._vRange); | ||
const vRange = this.getVRange(); | ||
if (vRange && this.editor.mounted) { | ||
this._applyVRange(vRange); | ||
} | ||
@@ -77,3 +86,3 @@ }; | ||
this.toDomRange = (vRange) => { | ||
const rootElement = this._editor.rootElement; | ||
const rootElement = this.editor.rootElement; | ||
return virgoRangeToDomRange(rootElement, vRange); | ||
@@ -108,3 +117,3 @@ }; | ||
this.toVRange = (range) => { | ||
const { rootElement, yText } = this._editor; | ||
const { rootElement, yText } = this.editor; | ||
return domRangeToVirgoRange(range, rootElement, yText); | ||
@@ -116,3 +125,3 @@ }; | ||
this._applyVRange = (vRange) => { | ||
const selectionRoot = findDocumentOrShadowRoot(this._editor); | ||
const selectionRoot = findDocumentOrShadowRoot(this.editor); | ||
const selection = selectionRoot.getSelection(); | ||
@@ -130,6 +139,6 @@ if (!selection) { | ||
this._scrollCursorIntoViewIfNeeded(newRange); | ||
this._editor.slots.rangeUpdated.emit(newRange); | ||
this.editor.slots.rangeUpdated.emit(newRange); | ||
}; | ||
this._scrollLineIntoViewIfNeeded = (range) => { | ||
if (this._editor.shouldLineScrollIntoView) { | ||
if (this.editor.shouldLineScrollIntoView) { | ||
let lineElement = range.endContainer.parentElement; | ||
@@ -145,4 +154,4 @@ while (!(lineElement instanceof VirgoLine)) { | ||
this._scrollCursorIntoViewIfNeeded = (range) => { | ||
if (this._editor.shouldCursorScrollIntoView) { | ||
const root = this._editor.rootElement; | ||
if (this.editor.shouldCursorScrollIntoView) { | ||
const root = this.editor.rootElement; | ||
const rootRect = root.getBoundingClientRect(); | ||
@@ -158,5 +167,7 @@ const rangeRect = range.getBoundingClientRect(); | ||
}; | ||
this._editor = editor; | ||
} | ||
get vRangeProvider() { | ||
return this.editor.vRangeProvider; | ||
} | ||
} | ||
//# sourceMappingURL=range.js.map |
@@ -12,6 +12,3 @@ import type { TemplateResult } from 'lit'; | ||
} | ||
export type VRangeUpdatedProp = [ | ||
range: VRange | null, | ||
type: 'native' | 'input' | 'other' | 'silent' | ||
]; | ||
export type VRangeUpdatedProp = [range: VRange | null, sync: boolean]; | ||
export type DeltaEntry<TextAttributes extends BaseTextAttributes = BaseTextAttributes> = [delta: DeltaInsert<TextAttributes>, range: VRange]; | ||
@@ -18,0 +15,0 @@ export type NativePoint = readonly [node: Node, offset: number]; |
@@ -1,2 +0,2 @@ | ||
import { ZERO_WIDTH_SPACE } from '../consts.js'; | ||
import { VIRGO_ROOT_ATTR, ZERO_WIDTH_SPACE } from '../consts.js'; | ||
import { isNativeTextInVText, isVElement, isVLine, isVRoot } from './guard.js'; | ||
@@ -64,4 +64,4 @@ import { calculateTextLength, getTextNodesFromElement } from './text.js'; | ||
const container = node instanceof Element | ||
? node.closest('[data-virgo-root="true"]') | ||
: node.parentElement?.closest('[data-virgo-root="true"]'); | ||
? node.closest(`[${VIRGO_ROOT_ATTR}]`) | ||
: node.parentElement?.closest(`[${VIRGO_ROOT_ATTR}]`); | ||
if (container) { | ||
@@ -68,0 +68,0 @@ return Array.from(container.querySelectorAll('v-line')); |
import { assertExists } from '@blocksuite/global/utils'; | ||
import { VIRGO_ROOT_ATTR } from '../consts.js'; | ||
export function findDocumentOrShadowRoot(editor) { | ||
@@ -15,3 +16,3 @@ const el = editor.rootElement; | ||
export function getVEditorInsideRoot(element) { | ||
const rootElement = element.closest('[data-virgo-root="true"]'); | ||
const rootElement = element.closest(`[${VIRGO_ROOT_ATTR}]`); | ||
assertExists(rootElement, 'element must be inside a v-root'); | ||
@@ -18,0 +19,0 @@ const virgoEditor = rootElement.virgoEditor; |
function handleInsertText(vRange, data, editor, attributes) { | ||
if (vRange.index >= 0 && data) { | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index + data.length, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.insertText(vRange, data, attributes); | ||
editor.setVRange({ | ||
index: vRange.index + data.length, | ||
length: 0, | ||
}, false); | ||
} | ||
@@ -15,10 +12,7 @@ } | ||
if (vRange.index >= 0) { | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index + 1, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.insertLineBreak(vRange); | ||
editor.setVRange({ | ||
index: vRange.index + 1, | ||
length: 0, | ||
}, false); | ||
} | ||
@@ -29,10 +23,7 @@ } | ||
if (vRange.length > 0) { | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText(vRange); | ||
editor.setVRange({ | ||
index: vRange.index, | ||
length: 0, | ||
}, false); | ||
return; | ||
@@ -44,9 +35,2 @@ } | ||
const deletedLength = segments[segments.length - 1].segment.length; | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index - deletedLength, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
@@ -56,2 +40,6 @@ index: vRange.index - deletedLength, | ||
}); | ||
editor.setVRange({ | ||
index: vRange.index - deletedLength, | ||
length: 0, | ||
}, false); | ||
} | ||
@@ -63,10 +51,7 @@ } | ||
if (vRange.length > 0) { | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText(vRange); | ||
editor.setVRange({ | ||
index: vRange.index, | ||
length: 0, | ||
}, false); | ||
} | ||
@@ -79,9 +64,2 @@ else { | ||
const deletedLength = segments[slicedSegments.length].segment.length; | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
@@ -91,2 +69,6 @@ index: vRange.index, | ||
}); | ||
editor.setVRange({ | ||
index: vRange.index, | ||
length: 0, | ||
}, false); | ||
} | ||
@@ -99,9 +81,2 @@ } | ||
const deleteLength = matches[0].length; | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index - deleteLength, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
@@ -111,2 +86,6 @@ index: vRange.index - deleteLength, | ||
}); | ||
editor.setVRange({ | ||
index: vRange.index - deleteLength, | ||
length: 0, | ||
}, false); | ||
} | ||
@@ -118,9 +97,2 @@ } | ||
const deleteLength = matches[0].length; | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
@@ -130,2 +102,6 @@ index: vRange.index, | ||
}); | ||
editor.setVRange({ | ||
index: vRange.index, | ||
length: 0, | ||
}, false); | ||
} | ||
@@ -135,10 +111,7 @@ } | ||
if (vRange.length > 0) { | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText(vRange); | ||
editor.setVRange({ | ||
index: vRange.index, | ||
length: 0, | ||
}, false); | ||
return; | ||
@@ -149,9 +122,2 @@ } | ||
const deleteLength = vRange.index - Math.max(0, str.slice(0, vRange.index).lastIndexOf('\n')); | ||
editor.slots.vRangeUpdated.emit([ | ||
{ | ||
index: vRange.index - deleteLength, | ||
length: 0, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
@@ -161,2 +127,6 @@ index: vRange.index - deleteLength, | ||
}); | ||
editor.setVRange({ | ||
index: vRange.index - deleteLength, | ||
length: 0, | ||
}, false); | ||
} | ||
@@ -163,0 +133,0 @@ } |
@@ -13,2 +13,6 @@ import type { NullablePartial } from '@blocksuite/global/utils'; | ||
}; | ||
export interface VRangeProvider { | ||
getVRange(): VRange | null; | ||
setVRange(vRange: VRange | null): void; | ||
} | ||
export declare class VEditor<TextAttributes extends BaseTextAttributes = BaseTextAttributes> { | ||
@@ -32,2 +36,3 @@ static nativePointToTextPoint: typeof nativePointToTextPoint; | ||
readonly isEmbed: (delta: DeltaInsert<TextAttributes>) => boolean; | ||
readonly vRangeProvider: VRangeProvider | null; | ||
slots: { | ||
@@ -73,2 +78,3 @@ mounted: Slot; | ||
hooks?: VirgoHookService<TextAttributes>['hooks']; | ||
vRangeProvider?: VRangeProvider; | ||
}); | ||
@@ -75,0 +81,0 @@ mount(rootElement: HTMLElement): void; |
import { assertExists, DisposableGroup, Slot } from '@blocksuite/global/utils'; | ||
import { nothing, render } from 'lit'; | ||
import { VIRGO_ROOT_ATTR } from './consts.js'; | ||
import { VirgoHookService } from './services/hook.js'; | ||
@@ -93,6 +94,7 @@ import { VirgoAttributeService, VirgoDeltaService, VirgoEventService, VirgoRangeService, } from './services/index.js'; | ||
} | ||
const { isEmbed = () => false, hooks = {} } = ops; | ||
const { isEmbed = () => false, hooks = {}, vRangeProvider = null } = ops; | ||
this._yText = yText; | ||
this.isEmbed = isEmbed; | ||
this._hooksService = new VirgoHookService(this, hooks); | ||
this.vRangeProvider = vRangeProvider; | ||
this.slots = { | ||
@@ -124,2 +126,3 @@ mounted: new Slot(), | ||
render(nothing, this.rootElement); | ||
this.rootElement.removeAttribute(VIRGO_ROOT_ATTR); | ||
this._rootElement = null; | ||
@@ -126,0 +129,0 @@ this._mounted = false; |
{ | ||
"name": "@blocksuite/virgo", | ||
"version": "0.0.0-20230907222710-102d1e99-nightly", | ||
"version": "0.0.0-20230908185655-61117b50-nightly", | ||
"description": "A micro editor.", | ||
@@ -27,3 +27,3 @@ "type": "module", | ||
"zod": "^3.22.2", | ||
"@blocksuite/global": "0.0.0-20230907222710-102d1e99-nightly" | ||
"@blocksuite/global": "0.0.0-20230908185655-61117b50-nightly" | ||
}, | ||
@@ -30,0 +30,0 @@ "scripts": { |
@@ -6,3 +6,3 @@ import { assertExists } from '@blocksuite/global/utils'; | ||
import { ZERO_WIDTH_SPACE } from '../consts.js'; | ||
import { VIRGO_ROOT_ATTR, ZERO_WIDTH_SPACE } from '../consts.js'; | ||
import type { DeltaInsert } from '../types.js'; | ||
@@ -45,3 +45,3 @@ import type { VirgoRootElement } from '../virgo.js'; | ||
const rootElement = this.closest( | ||
'[data-virgo-root="true"]' | ||
`[${VIRGO_ROOT_ATTR}]` | ||
) as VirgoRootElement; | ||
@@ -48,0 +48,0 @@ assertExists(rootElement, 'v-line must be inside a v-root'); |
export const ZERO_WIDTH_SPACE = '\u200B'; | ||
// see https://en.wikipedia.org/wiki/Zero-width_non-joiner | ||
export const ZERO_WIDTH_NON_JOINER = '\u200C'; | ||
export const VIRGO_ROOT_ATTR = 'data-virgo-root'; |
@@ -13,4 +13,2 @@ import type { z, ZodTypeDef } from 'zod'; | ||
export class VirgoAttributeService<TextAttributes extends BaseTextAttributes> { | ||
private readonly _editor: VEditor<TextAttributes>; | ||
private _marks: TextAttributes | null = null; | ||
@@ -24,5 +22,3 @@ | ||
constructor(editor: VEditor<TextAttributes>) { | ||
this._editor = editor; | ||
} | ||
constructor(public readonly editor: VEditor<TextAttributes>) {} | ||
@@ -56,3 +52,3 @@ get marks() { | ||
getFormat = (vRange: VRange, loose = false): TextAttributes => { | ||
const deltas = this._editor.deltaService | ||
const deltas = this.editor.deltaService | ||
.getDeltasByVRange(vRange) | ||
@@ -59,0 +55,0 @@ .filter( |
@@ -12,10 +12,6 @@ import { html, render } from 'lit'; | ||
export class VirgoDeltaService<TextAttributes extends BaseTextAttributes> { | ||
private readonly _editor: VEditor<TextAttributes>; | ||
constructor(public readonly editor: VEditor<TextAttributes>) {} | ||
constructor(editor: VEditor<TextAttributes>) { | ||
this._editor = editor; | ||
} | ||
get deltas() { | ||
return this._editor.yText.toDelta() as DeltaInsert<TextAttributes>[]; | ||
return this.editor.yText.toDelta() as DeltaInsert<TextAttributes>[]; | ||
} | ||
@@ -29,3 +25,3 @@ | ||
for (const delta of this.deltas) { | ||
if (this._editor.isEmbed(delta)) { | ||
if (this.editor.isEmbed(delta)) { | ||
const dividedDeltas = [...delta.insert].map(subInsert => ({ | ||
@@ -82,3 +78,3 @@ insert: subInsert, | ||
if (vRange.length >= 1) { | ||
this._editor.mapDeltasInVRange( | ||
this.editor.mapDeltasInVRange( | ||
vRange, | ||
@@ -208,3 +204,3 @@ (_, rangeIndex, deltaIndex) => { | ||
render = async (syncVRange = true) => { | ||
const rootElement = this._editor.rootElement; | ||
const rootElement = this.editor.rootElement; | ||
@@ -227,3 +223,3 @@ const normalizedDeltas = this.normalizedDeltas; | ||
let selected = false; | ||
const vRange = this._editor.getVRange(); | ||
const vRange = this.editor.getVRange(); | ||
if (vRange) { | ||
@@ -239,3 +235,3 @@ selected = this.isNormalizedDeltaSelected( | ||
delta, | ||
this._editor.attributeService.normalizeAttributes, | ||
this.editor.attributeService.normalizeAttributes, | ||
selected | ||
@@ -265,7 +261,7 @@ ), | ||
// Lit may be crashed by IME input and we need to rerender whole editor for it | ||
this._editor.rerenderWholeEditor(); | ||
await this._editor.waitForUpdate(); | ||
this.editor.rerenderWholeEditor(); | ||
await this.editor.waitForUpdate(); | ||
} | ||
await this._editor.waitForUpdate(); | ||
await this.editor.waitForUpdate(); | ||
@@ -275,7 +271,7 @@ if (syncVRange) { | ||
// otherwise there is a possibility of an error in the cursor position | ||
this._editor.rangeService.syncVRange(); | ||
this.editor.rangeService.syncVRange(); | ||
} | ||
this._editor.slots.updated.emit(); | ||
this.editor.slots.updated.emit(); | ||
}; | ||
} |
@@ -23,11 +23,18 @@ import { assertExists } from '@blocksuite/global/utils'; | ||
get vRangeProvider() { | ||
return this.editor.vRangeProvider; | ||
} | ||
mount = () => { | ||
const rootElement = this.editor.rootElement; | ||
if (!this.vRangeProvider) { | ||
this.editor.disposables.addFromEvent( | ||
document, | ||
'selectionchange', | ||
this._onSelectionChange | ||
); | ||
} | ||
this.editor.disposables.addFromEvent( | ||
document, | ||
'selectionchange', | ||
this._onSelectionChange | ||
); | ||
this.editor.disposables.addFromEvent( | ||
rootElement, | ||
@@ -56,2 +63,28 @@ 'beforeinput', | ||
private _isRangeCompletelyInRoot = () => { | ||
const selectionRoot = findDocumentOrShadowRoot(this.editor); | ||
const selection = selectionRoot.getSelection(); | ||
if (!selection || selection.rangeCount === 0) return false; | ||
const range = selection.getRangeAt(0); | ||
const rootElement = this.editor.rootElement; | ||
const rootRange = document.createRange(); | ||
rootRange.selectNode(rootElement); | ||
if ( | ||
range.startContainer.compareDocumentPosition(range.endContainer) & | ||
Node.DOCUMENT_POSITION_FOLLOWING | ||
) { | ||
return ( | ||
rootRange.comparePoint(range.startContainer, range.startOffset) >= 0 && | ||
rootRange.comparePoint(range.endContainer, range.endOffset) <= 0 | ||
); | ||
} else { | ||
return ( | ||
rootRange.comparePoint(range.endContainer, range.startOffset) >= 0 && | ||
rootRange.comparePoint(range.startContainer, range.endOffset) <= 0 | ||
); | ||
} | ||
}; | ||
private _onSelectionChange = () => { | ||
@@ -69,3 +102,3 @@ const rootElement = this.editor.rootElement; | ||
if (previousVRange !== null) { | ||
this.editor.slots.vRangeUpdated.emit([null, 'native']); | ||
this.editor.setVRange(null, false); | ||
} | ||
@@ -105,3 +138,3 @@ | ||
if (previousVRange !== null) { | ||
this.editor.slots.vRangeUpdated.emit([null, 'native']); | ||
this.editor.setVRange(null, false); | ||
} | ||
@@ -117,3 +150,3 @@ return; | ||
if (!isMaybeVRangeEqual(previousVRange, vRange)) { | ||
this.editor.slots.vRangeUpdated.emit([vRange, 'native']); | ||
this.editor.setVRange(vRange, false); | ||
} | ||
@@ -152,3 +185,3 @@ | ||
if (this.editor.isReadonly) return; | ||
if (this.editor.isReadonly || !this._isRangeCompletelyInRoot()) return; | ||
@@ -221,3 +254,3 @@ const vRange = this.editor.getVRange(); | ||
this.editor.slots.vRangeUpdated.emit([ | ||
this.editor.setVRange( | ||
{ | ||
@@ -227,4 +260,4 @@ index: newVRange.index + newData.length, | ||
}, | ||
'input', | ||
]); | ||
false | ||
); | ||
} | ||
@@ -234,14 +267,29 @@ } | ||
private _firstRecomputeInFrame = true; | ||
private _onBeforeInput = (event: InputEvent) => { | ||
event.preventDefault(); | ||
if (this.editor.isReadonly || this._isComposing) return; | ||
if (this._firstRecomputeInFrame) { | ||
this._firstRecomputeInFrame = false; | ||
this._onSelectionChange(); | ||
requestAnimationFrame(() => { | ||
this._firstRecomputeInFrame = true; | ||
}); | ||
if ( | ||
this.editor.isReadonly || | ||
this._isComposing || | ||
!this._isRangeCompletelyInRoot() | ||
) | ||
return; | ||
if (!this.editor.getVRange()) return; | ||
// Sometimes input event will directly come from some scripts (e.g. browser extension), | ||
// so we need to resync the vRange. | ||
const targetRanges = event.getTargetRanges(); | ||
if (targetRanges.length > 0) { | ||
const staticRange = targetRanges[0]; | ||
const range = document.createRange(); | ||
range.setStart(staticRange.startContainer, staticRange.startOffset); | ||
range.setEnd(staticRange.endContainer, staticRange.endOffset); | ||
const vRange = this.editor.toVRange(range); | ||
if (!isMaybeVRangeEqual(this.editor.getVRange(), vRange)) { | ||
this.editor.setVRange(vRange, false); | ||
} | ||
} | ||
const vRange = this.editor.getVRange(); | ||
@@ -248,0 +296,0 @@ if (!vRange) return; |
@@ -14,4 +14,2 @@ import { VirgoLine } from '../components/index.js'; | ||
export class VirgoRangeService<TextAttributes extends BaseTextAttributes> { | ||
private readonly _editor: VEditor<TextAttributes>; | ||
private _prevVRange: VRange | null = null; | ||
@@ -21,11 +19,13 @@ private _vRange: VRange | null = null; | ||
constructor(editor: VEditor<TextAttributes>) { | ||
this._editor = editor; | ||
constructor(public readonly editor: VEditor<TextAttributes>) {} | ||
get vRangeProvider() { | ||
return this.editor.vRangeProvider; | ||
} | ||
onVRangeUpdated = ([newVRange, origin]: VRangeUpdatedProp) => { | ||
onVRangeUpdated = ([newVRange, sync]: VRangeUpdatedProp) => { | ||
this._vRange = newVRange; | ||
if ( | ||
this._editor.mounted && | ||
this.editor.mounted && | ||
newVRange && | ||
@@ -36,16 +36,21 @@ !isMaybeVRangeEqual(this._prevVRange, newVRange) | ||
// be broken if we sync | ||
this._editor.requestUpdate(false); | ||
this.editor.requestUpdate(false); | ||
} | ||
this._prevVRange = newVRange; | ||
if (origin !== 'other') { | ||
if (this.vRangeProvider) { | ||
this.vRangeProvider.setVRange(newVRange); | ||
return; | ||
} | ||
if (!sync) { | ||
return; | ||
} | ||
if (this._vRange === null) { | ||
const selectionRoot = findDocumentOrShadowRoot(this._editor); | ||
const selectionRoot = findDocumentOrShadowRoot(this.editor); | ||
const selection = selectionRoot.getSelection(); | ||
if (selection && selection.rangeCount > 0) { | ||
const range = selection.getRangeAt(0); | ||
if (range.intersectsNode(this._editor.rootElement)) { | ||
if (range.intersectsNode(this.editor.rootElement)) { | ||
selection.removeAllRanges(); | ||
@@ -71,2 +76,6 @@ } | ||
getVRange = (): VRange | null => { | ||
if (this.vRangeProvider) { | ||
return this.vRangeProvider.getVRange(); | ||
} | ||
return this._vRange; | ||
@@ -83,3 +92,3 @@ }; | ||
(vRange.index < 0 || | ||
vRange.index + vRange.length > this._editor.yText.length) | ||
vRange.index + vRange.length > this.editor.yText.length) | ||
) { | ||
@@ -89,3 +98,3 @@ throw new Error('invalid vRange'); | ||
this._editor.slots.vRangeUpdated.emit([vRange, sync ? 'other' : 'silent']); | ||
this.editor.slots.vRangeUpdated.emit([vRange, sync]); | ||
}; | ||
@@ -97,4 +106,5 @@ | ||
syncVRange = (): void => { | ||
if (this._vRange && this._editor.mounted) { | ||
this._applyVRange(this._vRange); | ||
const vRange = this.getVRange(); | ||
if (vRange && this.editor.mounted) { | ||
this._applyVRange(vRange); | ||
} | ||
@@ -107,3 +117,3 @@ }; | ||
toDomRange = (vRange: VRange): Range | null => { | ||
const rootElement = this._editor.rootElement; | ||
const rootElement = this.editor.rootElement; | ||
return virgoRangeToDomRange(rootElement, vRange); | ||
@@ -139,3 +149,3 @@ }; | ||
toVRange = (range: Range): VRange | null => { | ||
const { rootElement, yText } = this._editor; | ||
const { rootElement, yText } = this.editor; | ||
@@ -150,3 +160,3 @@ return domRangeToVirgoRange(range, rootElement, yText); | ||
private _applyVRange = (vRange: VRange): void => { | ||
const selectionRoot = findDocumentOrShadowRoot(this._editor); | ||
const selectionRoot = findDocumentOrShadowRoot(this.editor); | ||
const selection = selectionRoot.getSelection(); | ||
@@ -168,7 +178,7 @@ if (!selection) { | ||
this._editor.slots.rangeUpdated.emit(newRange); | ||
this.editor.slots.rangeUpdated.emit(newRange); | ||
}; | ||
private _scrollLineIntoViewIfNeeded = (range: Range) => { | ||
if (this._editor.shouldLineScrollIntoView) { | ||
if (this.editor.shouldLineScrollIntoView) { | ||
let lineElement: HTMLElement | null = range.endContainer.parentElement; | ||
@@ -185,4 +195,4 @@ while (!(lineElement instanceof VirgoLine)) { | ||
private _scrollCursorIntoViewIfNeeded = (range: Range) => { | ||
if (this._editor.shouldCursorScrollIntoView) { | ||
const root = this._editor.rootElement; | ||
if (this.editor.shouldCursorScrollIntoView) { | ||
const root = this.editor.rootElement; | ||
@@ -189,0 +199,0 @@ const rootRect = root.getBoundingClientRect(); |
@@ -24,6 +24,3 @@ import type { TemplateResult } from 'lit'; | ||
export type VRangeUpdatedProp = [ | ||
range: VRange | null, | ||
type: 'native' | 'input' | 'other' | 'silent', | ||
]; | ||
export type VRangeUpdatedProp = [range: VRange | null, sync: boolean]; | ||
@@ -30,0 +27,0 @@ export type DeltaEntry< |
@@ -11,4 +11,3 @@ import { z } from 'zod'; | ||
}); | ||
// .partial(); | ||
export type BaseTextAttributes = z.infer<typeof baseTextAttributes>; |
import type { VirgoElement, VirgoLine } from '../components/index.js'; | ||
import { ZERO_WIDTH_SPACE } from '../consts.js'; | ||
import { VIRGO_ROOT_ATTR, ZERO_WIDTH_SPACE } from '../consts.js'; | ||
import type { DomPoint, TextPoint } from '../types.js'; | ||
@@ -101,4 +101,4 @@ import { isNativeTextInVText, isVElement, isVLine, isVRoot } from './guard.js'; | ||
node instanceof Element | ||
? node.closest('[data-virgo-root="true"]') | ||
: node.parentElement?.closest('[data-virgo-root="true"]'); | ||
? node.closest(`[${VIRGO_ROOT_ATTR}]`) | ||
: node.parentElement?.closest(`[${VIRGO_ROOT_ATTR}]`); | ||
@@ -105,0 +105,0 @@ if (container) { |
import { assertExists } from '@blocksuite/global/utils'; | ||
import { VIRGO_ROOT_ATTR } from '../consts.js'; | ||
import type { VEditor, VirgoRootElement } from '../virgo.js'; | ||
@@ -29,3 +30,3 @@ import type { BaseTextAttributes } from './base-attributes.js'; | ||
const rootElement = element.closest( | ||
'[data-virgo-root="true"]' | ||
`[${VIRGO_ROOT_ATTR}]` | ||
) as VirgoRootElement; | ||
@@ -32,0 +33,0 @@ assertExists(rootElement, 'element must be inside a v-root'); |
@@ -12,3 +12,4 @@ import type { VRange } from '../types.js'; | ||
if (vRange.index >= 0 && data) { | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.insertText(vRange, data, attributes); | ||
editor.setVRange( | ||
{ | ||
@@ -18,5 +19,4 @@ index: vRange.index + data.length, | ||
}, | ||
'input', | ||
]); | ||
editor.insertText(vRange, data, attributes); | ||
false | ||
); | ||
} | ||
@@ -27,3 +27,4 @@ } | ||
if (vRange.index >= 0) { | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.insertLineBreak(vRange); | ||
editor.setVRange( | ||
{ | ||
@@ -33,5 +34,4 @@ index: vRange.index + 1, | ||
}, | ||
'input', | ||
]); | ||
editor.insertLineBreak(vRange); | ||
false | ||
); | ||
} | ||
@@ -43,3 +43,4 @@ } | ||
if (vRange.length > 0) { | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.deleteText(vRange); | ||
editor.setVRange( | ||
{ | ||
@@ -49,5 +50,4 @@ index: vRange.index, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText(vRange); | ||
false | ||
); | ||
return; | ||
@@ -60,3 +60,7 @@ } | ||
const deletedLength = segments[segments.length - 1].segment.length; | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.deleteText({ | ||
index: vRange.index - deletedLength, | ||
length: deletedLength, | ||
}); | ||
editor.setVRange( | ||
{ | ||
@@ -66,8 +70,4 @@ index: vRange.index - deletedLength, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
index: vRange.index - deletedLength, | ||
length: deletedLength, | ||
}); | ||
false | ||
); | ||
} | ||
@@ -80,3 +80,4 @@ } | ||
if (vRange.length > 0) { | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.deleteText(vRange); | ||
editor.setVRange( | ||
{ | ||
@@ -86,5 +87,4 @@ index: vRange.index, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText(vRange); | ||
false | ||
); | ||
} else { | ||
@@ -96,3 +96,7 @@ const originalString = editor.yText.toString(); | ||
const deletedLength = segments[slicedSegments.length].segment.length; | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.deleteText({ | ||
index: vRange.index, | ||
length: deletedLength, | ||
}); | ||
editor.setVRange( | ||
{ | ||
@@ -102,8 +106,4 @@ index: vRange.index, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
index: vRange.index, | ||
length: deletedLength, | ||
}); | ||
false | ||
); | ||
} | ||
@@ -120,3 +120,7 @@ } | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.deleteText({ | ||
index: vRange.index - deleteLength, | ||
length: deleteLength, | ||
}); | ||
editor.setVRange( | ||
{ | ||
@@ -126,8 +130,4 @@ index: vRange.index - deleteLength, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
index: vRange.index - deleteLength, | ||
length: deleteLength, | ||
}); | ||
false | ||
); | ||
} | ||
@@ -141,3 +141,7 @@ } | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.deleteText({ | ||
index: vRange.index, | ||
length: deleteLength, | ||
}); | ||
editor.setVRange( | ||
{ | ||
@@ -147,8 +151,4 @@ index: vRange.index, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
index: vRange.index, | ||
length: deleteLength, | ||
}); | ||
false | ||
); | ||
} | ||
@@ -159,3 +159,4 @@ } | ||
if (vRange.length > 0) { | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.deleteText(vRange); | ||
editor.setVRange( | ||
{ | ||
@@ -165,5 +166,5 @@ index: vRange.index, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText(vRange); | ||
false | ||
); | ||
return; | ||
@@ -177,3 +178,7 @@ } | ||
editor.slots.vRangeUpdated.emit([ | ||
editor.deleteText({ | ||
index: vRange.index - deleteLength, | ||
length: deleteLength, | ||
}); | ||
editor.setVRange( | ||
{ | ||
@@ -183,8 +188,4 @@ index: vRange.index - deleteLength, | ||
}, | ||
'input', | ||
]); | ||
editor.deleteText({ | ||
index: vRange.index - deleteLength, | ||
length: deleteLength, | ||
}); | ||
false | ||
); | ||
} | ||
@@ -191,0 +192,0 @@ } |
@@ -7,2 +7,3 @@ import type { NullablePartial } from '@blocksuite/global/utils'; | ||
import type { VirgoLine } from './components/index.js'; | ||
import { VIRGO_ROOT_ATTR } from './consts.js'; | ||
import { VirgoHookService } from './services/hook.js'; | ||
@@ -36,2 +37,7 @@ import { | ||
export interface VRangeProvider { | ||
getVRange(): VRange | null; | ||
setVRange(vRange: VRange | null): void; | ||
} | ||
export class VEditor< | ||
@@ -73,2 +79,3 @@ TextAttributes extends BaseTextAttributes = BaseTextAttributes, | ||
readonly isEmbed: (delta: DeltaInsert<TextAttributes>) => boolean; | ||
readonly vRangeProvider: VRangeProvider | null; | ||
@@ -158,2 +165,3 @@ slots: { | ||
hooks?: VirgoHookService<TextAttributes>['hooks']; | ||
vRangeProvider?: VRangeProvider; | ||
} = {} | ||
@@ -171,6 +179,7 @@ ) { | ||
const { isEmbed = () => false, hooks = {} } = ops; | ||
const { isEmbed = () => false, hooks = {}, vRangeProvider = null } = ops; | ||
this._yText = yText; | ||
this.isEmbed = isEmbed; | ||
this._hooksService = new VirgoHookService(this, hooks); | ||
this.vRangeProvider = vRangeProvider; | ||
@@ -210,2 +219,3 @@ this.slots = { | ||
render(nothing, this.rootElement); | ||
this.rootElement.removeAttribute(VIRGO_ROOT_ATTR); | ||
this._rootElement = null; | ||
@@ -212,0 +222,0 @@ this._mounted = false; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
524501
8678
+ Added@blocksuite/global@0.0.0-20230908185655-61117b50-nightly(transitive)
- Removed@blocksuite/global@0.0.0-20230907222710-102d1e99-nightly(transitive)
Updated@blocksuite/global@0.0.0-20230908185655-61117b50-nightly