@blocksuite/block-std
Advanced tools
Comparing version
@@ -5,4 +5,4 @@ import { DisposableGroup } from '@blocksuite/global/utils'; | ||
import { UIEventStateContext } from './base.js'; | ||
import { BlockEventState } from './state.js'; | ||
declare const eventNames: readonly ["click", "doubleClick", "tripleClick", "pointerDown", "pointerMove", "pointerUp", "pointerOut", "dragStart", "dragMove", "dragEnd", "keyDown", "keyUp", "beforeInput", "compositionStart", "compositionUpdate", "compositionEnd", "paste", "copy", "blur", "focus", "drop", "contextMenu", "wheel", "selectionChange"]; | ||
import { BlockEventState } from './state/index.js'; | ||
declare const eventNames: readonly ["click", "doubleClick", "tripleClick", "pointerDown", "pointerMove", "pointerUp", "pointerOut", "dragStart", "dragMove", "dragEnd", "keyDown", "keyUp", "selectionChange", "beforeInput", "compositionStart", "compositionUpdate", "compositionEnd", "paste", "copy", "blur", "focus", "drop", "contextMenu", "wheel"]; | ||
export type EventName = (typeof eventNames)[number]; | ||
@@ -18,2 +18,7 @@ export type EventOptions = { | ||
}; | ||
export type EventScope = { | ||
runners: EventHandlerRunner[]; | ||
flavours: string[]; | ||
paths: string[][]; | ||
}; | ||
export declare class UIEventDispatcher { | ||
@@ -25,2 +30,3 @@ blockStore: BlockStore; | ||
private _keyboardControl; | ||
private _rangeControl; | ||
constructor(blockStore: BlockStore); | ||
@@ -30,9 +36,9 @@ mount(): void; | ||
get root(): HTMLElement; | ||
run(name: EventName, context: UIEventStateContext): void; | ||
run(name: EventName, context: UIEventStateContext, scope?: EventScope): void; | ||
add(name: EventName, handler: UIEventHandler, options?: EventOptions): () => void; | ||
bindHotkey(keymap: Record<string, UIEventHandler>, options?: EventOptions): () => void; | ||
private get _currentSelections(); | ||
getEventScope(name: EventName, event: Event): EventHandlerRunner[] | undefined; | ||
createEventBlockState(event: Event): BlockEventState; | ||
private _buildEventScope; | ||
private _getEventScope; | ||
createEventState(event: Event, scope: EventScope): BlockEventState; | ||
buildEventScope(name: EventName, flavours: string[], paths: string[][]): EventScope | undefined; | ||
private _buildEventScopeByTarget; | ||
@@ -39,0 +45,0 @@ private _buildEventScopeBySelection; |
@@ -5,6 +5,7 @@ import { DisposableGroup } from '@blocksuite/global/utils'; | ||
import { UIEventState } from './base.js'; | ||
import { KeyboardControl } from './keyboard.js'; | ||
import { KeyboardControl } from './control/keyboard.js'; | ||
import { PointerControl } from './control/pointer.js'; | ||
import { RangeControl } from './control/range.js'; | ||
import { bindKeymap } from './keymap.js'; | ||
import { PointerControl } from './pointer.js'; | ||
import { BlockEventState } from './state.js'; | ||
import { BlockEventState } from './state/index.js'; | ||
import { toLowerCase } from './utils.js'; | ||
@@ -24,3 +25,2 @@ const bypassEventNames = [ | ||
]; | ||
const globalEventNames = ['selectionChange']; | ||
const eventNames = [ | ||
@@ -39,4 +39,4 @@ 'click', | ||
'keyUp', | ||
'selectionChange', | ||
...bypassEventNames, | ||
...globalEventNames, | ||
]; | ||
@@ -50,2 +50,3 @@ export class UIEventDispatcher { | ||
this._keyboardControl = new KeyboardControl(this); | ||
this._rangeControl = new RangeControl(this); | ||
} | ||
@@ -64,8 +65,15 @@ mount() { | ||
} | ||
run(name, context) { | ||
const runners = this.getEventScope(name, context.get('defaultState').event); | ||
if (!runners) { | ||
return; | ||
run(name, context, scope) { | ||
const event = context.get('defaultState').event; | ||
if (!scope) { | ||
scope = this._getEventScope(name, event); | ||
if (!scope) { | ||
return; | ||
} | ||
} | ||
for (const runner of runners) { | ||
if (!context.has('blockState')) { | ||
const blockState = this.createEventState(event, scope); | ||
context.add(blockState); | ||
} | ||
for (const runner of scope.runners) { | ||
const { fn } = runner; | ||
@@ -97,23 +105,21 @@ const result = fn(context); | ||
} | ||
getEventScope(name, event) { | ||
_getEventScope(name, event) { | ||
const handlers = this._handlersMap[name]; | ||
if (!handlers) | ||
return; | ||
if (!event.target || | ||
event.target === this.root || | ||
event.target === document || | ||
event.target === window || | ||
event.target === document.body || | ||
!(event.target instanceof Node)) { | ||
return this._buildEventScopeBySelection(name); | ||
let output; | ||
if (event.target && event.target instanceof Node) { | ||
output = this._buildEventScopeByTarget(name, event.target); | ||
} | ||
return this._buildEventScopeByTarget(name, event.target); | ||
if (!output) { | ||
output = this._buildEventScopeBySelection(name); | ||
} | ||
return output; | ||
} | ||
createEventBlockState(event) { | ||
createEventState(event, scope) { | ||
const targetMap = new PathMap(); | ||
this._currentSelections.forEach(selection => { | ||
const _path = selection.path; | ||
const instance = this.blockStore.viewStore.blockViewMap.get(_path); | ||
scope.paths.forEach(path => { | ||
const instance = this.blockStore.viewStore.blockViewMap.get(path); | ||
if (instance) { | ||
targetMap.set(_path, instance); | ||
targetMap.set(path, instance); | ||
} | ||
@@ -126,3 +132,3 @@ }); | ||
} | ||
_buildEventScope(name, flavours, paths) { | ||
buildEventScope(name, flavours, paths) { | ||
const handlers = this._handlersMap[name]; | ||
@@ -142,3 +148,7 @@ if (!handlers) | ||
}); | ||
return pathEvents.concat(flavourEvents).concat(globalEvents); | ||
return { | ||
runners: pathEvents.concat(flavourEvents).concat(globalEvents), | ||
flavours, | ||
paths, | ||
}; | ||
} | ||
@@ -159,4 +169,5 @@ _buildEventScopeByTarget(name, target) { | ||
return !!flavour; | ||
}); | ||
return this._buildEventScope(name, flavours, [path]); | ||
}) | ||
.reverse(); | ||
return this.buildEventScope(name, flavours, [path]); | ||
} | ||
@@ -186,3 +197,3 @@ _buildEventScopeBySelection(name) { | ||
const paths = selections.map(selection => selection.path); | ||
return this._buildEventScope(name, flavours, paths); | ||
return this.buildEventScope(name, flavours, paths); | ||
} | ||
@@ -192,14 +203,10 @@ _bindEvents() { | ||
this.disposables.addFromEvent(this.root, toLowerCase(eventName), event => { | ||
this.run(eventName, UIEventStateContext.from(new UIEventState(event), this.createEventBlockState(event))); | ||
this.run(eventName, UIEventStateContext.from(new UIEventState(event))); | ||
}); | ||
}); | ||
globalEventNames.forEach(eventName => { | ||
this.disposables.addFromEvent(document, toLowerCase(eventName), event => { | ||
this.run(eventName, UIEventStateContext.from(new UIEventState(event), this.createEventBlockState(event))); | ||
}); | ||
}); | ||
this._pointerControl.listen(); | ||
this._keyboardControl.listen(); | ||
this._rangeControl.listen(); | ||
} | ||
} | ||
//# sourceMappingURL=dispatcher.js.map |
export * from './base.js'; | ||
export * from './dispatcher.js'; | ||
export * from './state.js'; | ||
export * from './state/index.js'; | ||
//# sourceMappingURL=index.d.ts.map |
export * from './base.js'; | ||
export * from './dispatcher.js'; | ||
export * from './state.js'; | ||
export * from './state/index.js'; | ||
//# sourceMappingURL=index.js.map |
export type BaseSelectionOptions = { | ||
blockId: string; | ||
path: readonly string[]; | ||
path: string[]; | ||
}; | ||
@@ -8,3 +8,3 @@ export declare abstract class BaseSelection { | ||
readonly blockId: string; | ||
readonly path: readonly string[]; | ||
readonly path: string[]; | ||
constructor({ blockId, path }: BaseSelectionOptions); | ||
@@ -11,0 +11,0 @@ is<T extends BlockSuiteSelectionType>(type: T): this is BlockSuiteSelectionInstance[T]; |
import type { Page, Workspace } from '@blocksuite/store'; | ||
import { UIEventDispatcher } from '../event/index.js'; | ||
import { SelectionManager } from '../selection/index.js'; | ||
import type { BlockService } from '../service/index.js'; | ||
import type { BlockSpec } from '../spec/index.js'; | ||
import { SpecStore } from './spec-store.js'; | ||
import { ViewStore } from './view-store.js'; | ||
@@ -22,16 +21,9 @@ export interface BlockStoreConfig<BlockViewType = unknown> { | ||
readonly root: HTMLElement; | ||
readonly specStore: SpecStore<ComponentType>; | ||
readonly viewStore: ViewStore<BlockViewType, WidgetViewType>; | ||
readonly config: BlockStoreConfig<BlockViewType>; | ||
private _specs; | ||
private _services; | ||
constructor(options: BlockStoreOptions<BlockViewType>); | ||
applySpecs(specs: Array<BlockSpec<ComponentType>>): void; | ||
mount(): void; | ||
unmount(): void; | ||
dispose(): void; | ||
getView(flavour: string): import("../spec/index.js").BlockView<ComponentType, string> | null; | ||
getService(flavour: string): BlockService<import("@blocksuite/store").BaseBlockModel<object>> | undefined; | ||
private _diffServices; | ||
private _buildSpecMap; | ||
} | ||
//# sourceMappingURL=block-store.d.ts.map |
import { UIEventDispatcher } from '../event/index.js'; | ||
import { SelectionManager } from '../selection/index.js'; | ||
import { SpecStore } from './spec-store.js'; | ||
import { ViewStore } from './view-store.js'; | ||
export class BlockStore { | ||
constructor(options) { | ||
this._specs = new Map(); | ||
this._services = new Map(); | ||
this.root = options.root; | ||
@@ -14,10 +13,5 @@ this.workspace = options.workspace; | ||
this.selectionManager = new SelectionManager(this); | ||
this.specStore = new SpecStore(this); | ||
this.viewStore = new ViewStore(); | ||
} | ||
applySpecs(specs) { | ||
const oldSpecs = this._specs; | ||
const newSpecs = this._buildSpecMap(specs); | ||
this._diffServices(oldSpecs, newSpecs); | ||
this._specs = newSpecs; | ||
} | ||
mount() { | ||
@@ -31,57 +25,5 @@ this.selectionManager.mount(); | ||
this.viewStore.clear(); | ||
this.dispose(); | ||
this.specStore.dispose(); | ||
} | ||
dispose() { | ||
this._services.forEach(service => { | ||
service.dispose(); | ||
service.unmounted(); | ||
}); | ||
this._services.clear(); | ||
} | ||
getView(flavour) { | ||
const spec = this._specs.get(flavour); | ||
if (!spec) { | ||
return null; | ||
} | ||
return spec.view; | ||
} | ||
getService(flavour) { | ||
return this._services.get(flavour); | ||
} | ||
_diffServices(oldSpecs, newSpecs) { | ||
oldSpecs.forEach((oldSpec, flavour) => { | ||
if (newSpecs.has(flavour) && | ||
newSpecs.get(flavour)?.service === oldSpec.service) { | ||
return; | ||
} | ||
const service = this._services.get(flavour); | ||
if (service) { | ||
service.dispose(); | ||
service.unmounted(); | ||
} | ||
this._services.delete(flavour); | ||
}); | ||
newSpecs.forEach((newSpec, flavour) => { | ||
if (this._services.has(flavour)) { | ||
return; | ||
} | ||
if (!newSpec.service) { | ||
return; | ||
} | ||
const service = new newSpec.service({ | ||
flavour, | ||
store: this, | ||
}); | ||
this._services.set(flavour, service); | ||
service.mounted(); | ||
}); | ||
} | ||
_buildSpecMap(specs) { | ||
const specMap = new Map(); | ||
specs.forEach(spec => { | ||
specMap.set(spec.schema.model.flavour, spec); | ||
}); | ||
return specMap; | ||
} | ||
} | ||
//# sourceMappingURL=block-store.js.map |
{ | ||
"name": "@blocksuite/block-std", | ||
"version": "0.0.0-20230725170625-d6366e35-nightly", | ||
"version": "0.0.0-20230726225156-e7b23c54-nightly", | ||
"description": "Std for blocksuite blocks", | ||
@@ -12,10 +12,10 @@ "main": "dist/index.js", | ||
"peerDependencies": { | ||
"@blocksuite/store": "0.0.0-20230725170625-d6366e35-nightly" | ||
"@blocksuite/store": "0.0.0-20230726225156-e7b23c54-nightly" | ||
}, | ||
"dependencies": { | ||
"w3c-keyname": "^2.2.8", | ||
"@blocksuite/global": "0.0.0-20230725170625-d6366e35-nightly" | ||
"@blocksuite/global": "0.0.0-20230726225156-e7b23c54-nightly" | ||
}, | ||
"devDependencies": { | ||
"@blocksuite/store": "0.0.0-20230725170625-d6366e35-nightly" | ||
"@blocksuite/store": "0.0.0-20230726225156-e7b23c54-nightly" | ||
}, | ||
@@ -22,0 +22,0 @@ "exports": { |
@@ -8,6 +8,7 @@ import { DisposableGroup } from '@blocksuite/global/utils'; | ||
import { UIEventState } from './base.js'; | ||
import { KeyboardControl } from './keyboard.js'; | ||
import { KeyboardControl } from './control/keyboard.js'; | ||
import { PointerControl } from './control/pointer.js'; | ||
import { RangeControl } from './control/range.js'; | ||
import { bindKeymap } from './keymap.js'; | ||
import { PointerControl } from './pointer.js'; | ||
import { BlockEventState } from './state.js'; | ||
import { BlockEventState } from './state/index.js'; | ||
import { toLowerCase } from './utils.js'; | ||
@@ -30,4 +31,2 @@ | ||
const globalEventNames = ['selectionChange'] as const; | ||
const eventNames = [ | ||
@@ -50,4 +49,5 @@ 'click', | ||
'selectionChange', | ||
...bypassEventNames, | ||
...globalEventNames, | ||
] as const; | ||
@@ -66,2 +66,8 @@ | ||
export type EventScope = { | ||
runners: EventHandlerRunner[]; | ||
flavours: string[]; | ||
paths: string[][]; | ||
}; | ||
export class UIEventDispatcher { | ||
@@ -76,2 +82,3 @@ disposables = new DisposableGroup(); | ||
private _keyboardControl: KeyboardControl; | ||
private _rangeControl: RangeControl; | ||
@@ -81,2 +88,3 @@ constructor(public blockStore: BlockStore) { | ||
this._keyboardControl = new KeyboardControl(this); | ||
this._rangeControl = new RangeControl(this); | ||
} | ||
@@ -99,9 +107,17 @@ | ||
run(name: EventName, context: UIEventStateContext) { | ||
const runners = this.getEventScope(name, context.get('defaultState').event); | ||
if (!runners) { | ||
return; | ||
run(name: EventName, context: UIEventStateContext, scope?: EventScope) { | ||
const event = context.get('defaultState').event; | ||
if (!scope) { | ||
scope = this._getEventScope(name, event); | ||
if (!scope) { | ||
return; | ||
} | ||
} | ||
for (const runner of runners) { | ||
if (!context.has('blockState')) { | ||
const blockState = this.createEventState(event, scope); | ||
context.add(blockState); | ||
} | ||
for (const runner of scope.runners) { | ||
const { fn } = runner; | ||
@@ -139,27 +155,25 @@ const result = fn(context); | ||
getEventScope(name: EventName, event: Event) { | ||
private _getEventScope(name: EventName, event: Event) { | ||
const handlers = this._handlersMap[name]; | ||
if (!handlers) return; | ||
if ( | ||
!event.target || | ||
event.target === this.root || | ||
event.target === document || | ||
event.target === window || | ||
event.target === document.body || | ||
!(event.target instanceof Node) | ||
) { | ||
return this._buildEventScopeBySelection(name); | ||
let output: EventScope | undefined; | ||
if (event.target && event.target instanceof Node) { | ||
output = this._buildEventScopeByTarget(name, event.target); | ||
} | ||
return this._buildEventScopeByTarget(name, event.target); | ||
if (!output) { | ||
output = this._buildEventScopeBySelection(name); | ||
} | ||
return output; | ||
} | ||
createEventBlockState(event: Event) { | ||
createEventState(event: Event, scope: EventScope) { | ||
const targetMap = new PathMap(); | ||
this._currentSelections.forEach(selection => { | ||
const _path = selection.path as string[]; | ||
const instance = this.blockStore.viewStore.blockViewMap.get(_path); | ||
scope.paths.forEach(path => { | ||
const instance = this.blockStore.viewStore.blockViewMap.get(path); | ||
if (instance) { | ||
targetMap.set(_path, instance); | ||
targetMap.set(path, instance); | ||
} | ||
@@ -174,7 +188,7 @@ }); | ||
private _buildEventScope( | ||
buildEventScope( | ||
name: EventName, | ||
flavours: string[], | ||
paths: string[][] | ||
) { | ||
): EventScope | undefined { | ||
const handlers = this._handlersMap[name]; | ||
@@ -190,3 +204,3 @@ if (!handlers) return; | ||
if (handler.path === undefined) return false; | ||
return PathMap.includes(path as string[], handler.path); | ||
return PathMap.includes(path, handler.path); | ||
}); | ||
@@ -199,3 +213,7 @@ }); | ||
return pathEvents.concat(flavourEvents).concat(globalEvents); | ||
return { | ||
runners: pathEvents.concat(flavourEvents).concat(globalEvents), | ||
flavours, | ||
paths, | ||
}; | ||
} | ||
@@ -217,5 +235,6 @@ | ||
return !!flavour; | ||
}); | ||
}) | ||
.reverse(); | ||
return this._buildEventScope(name, flavours, [path]); | ||
return this.buildEventScope(name, flavours, [path]); | ||
} | ||
@@ -247,3 +266,3 @@ | ||
return this._buildEventScope(name, flavours, paths as string[][]); | ||
return this.buildEventScope(name, flavours, paths); | ||
} | ||
@@ -259,6 +278,3 @@ | ||
eventName, | ||
UIEventStateContext.from( | ||
new UIEventState(event), | ||
this.createEventBlockState(event) | ||
) | ||
UIEventStateContext.from(new UIEventState(event)) | ||
); | ||
@@ -268,16 +284,7 @@ } | ||
}); | ||
globalEventNames.forEach(eventName => { | ||
this.disposables.addFromEvent(document, toLowerCase(eventName), event => { | ||
this.run( | ||
eventName, | ||
UIEventStateContext.from( | ||
new UIEventState(event), | ||
this.createEventBlockState(event) | ||
) | ||
); | ||
}); | ||
}); | ||
this._pointerControl.listen(); | ||
this._keyboardControl.listen(); | ||
this._rangeControl.listen(); | ||
} | ||
} |
export * from './base.js'; | ||
export * from './dispatcher.js'; | ||
export * from './state.js'; | ||
export * from './state/index.js'; |
@@ -8,3 +8,3 @@ type SelectionConstructor<T = unknown> = { | ||
blockId: string; | ||
path: readonly string[]; | ||
path: string[]; | ||
}; | ||
@@ -15,3 +15,3 @@ | ||
readonly blockId: string; | ||
readonly path: readonly string[]; | ||
readonly path: string[]; | ||
constructor({ blockId, path }: BaseSelectionOptions) { | ||
@@ -18,0 +18,0 @@ this.blockId = blockId; |
@@ -24,3 +24,3 @@ import { BaseSelection } from '../base.js'; | ||
blockId: json.blockId as string, | ||
path: json.path as readonly string[], | ||
path: json.path as string[], | ||
}); | ||
@@ -27,0 +27,0 @@ } |
@@ -5,4 +5,3 @@ import type { Page, Workspace } from '@blocksuite/store'; | ||
import { SelectionManager } from '../selection/index.js'; | ||
import type { BlockService } from '../service/index.js'; | ||
import type { BlockSpec } from '../spec/index.js'; | ||
import { SpecStore } from './spec-store.js'; | ||
import { ViewStore } from './view-store.js'; | ||
@@ -31,7 +30,6 @@ | ||
readonly root: HTMLElement; | ||
readonly specStore: SpecStore<ComponentType>; | ||
readonly viewStore: ViewStore<BlockViewType, WidgetViewType>; | ||
readonly config: BlockStoreConfig<BlockViewType>; | ||
private _specs: Map<string, BlockSpec<ComponentType>> = new Map(); | ||
private _services: Map<string, BlockService> = new Map(); | ||
constructor(options: BlockStoreOptions<BlockViewType>) { | ||
@@ -44,12 +42,6 @@ this.root = options.root; | ||
this.selectionManager = new SelectionManager(this); | ||
this.specStore = new SpecStore<ComponentType>(this); | ||
this.viewStore = new ViewStore<BlockViewType, WidgetViewType>(); | ||
} | ||
applySpecs(specs: Array<BlockSpec<ComponentType>>) { | ||
const oldSpecs = this._specs; | ||
const newSpecs = this._buildSpecMap(specs); | ||
this._diffServices(oldSpecs, newSpecs); | ||
this._specs = newSpecs; | ||
} | ||
mount() { | ||
@@ -64,70 +56,4 @@ this.selectionManager.mount(); | ||
this.viewStore.clear(); | ||
this.dispose(); | ||
this.specStore.dispose(); | ||
} | ||
dispose() { | ||
this._services.forEach(service => { | ||
service.dispose(); | ||
service.unmounted(); | ||
}); | ||
this._services.clear(); | ||
} | ||
getView(flavour: string) { | ||
const spec = this._specs.get(flavour); | ||
if (!spec) { | ||
return null; | ||
} | ||
return spec.view; | ||
} | ||
getService(flavour: string) { | ||
return this._services.get(flavour); | ||
} | ||
private _diffServices( | ||
oldSpecs: Map<string, BlockSpec<ComponentType>>, | ||
newSpecs: Map<string, BlockSpec<ComponentType>> | ||
) { | ||
oldSpecs.forEach((oldSpec, flavour) => { | ||
if ( | ||
newSpecs.has(flavour) && | ||
newSpecs.get(flavour)?.service === oldSpec.service | ||
) { | ||
return; | ||
} | ||
const service = this._services.get(flavour); | ||
if (service) { | ||
service.dispose(); | ||
service.unmounted(); | ||
} | ||
this._services.delete(flavour); | ||
}); | ||
newSpecs.forEach((newSpec, flavour) => { | ||
if (this._services.has(flavour)) { | ||
return; | ||
} | ||
if (!newSpec.service) { | ||
return; | ||
} | ||
const service = new newSpec.service({ | ||
flavour, | ||
store: this, | ||
}); | ||
this._services.set(flavour, service); | ||
service.mounted(); | ||
}); | ||
} | ||
private _buildSpecMap(specs: Array<BlockSpec<ComponentType>>) { | ||
const specMap = new Map<string, BlockSpec<ComponentType>>(); | ||
specs.forEach(spec => { | ||
specMap.set(spec.schema.model.flavour, spec); | ||
}); | ||
return specMap; | ||
} | ||
} |
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
339996
7.06%134
22.94%2676
11.41%+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
Updated