@blocksuite/store
Advanced tools
Comparing version 0.4.0-20230110192220-0bac914 to 0.4.0-20230111121357-6129124
@@ -0,1 +1,2 @@ | ||
/// <reference types="blocksuite__global-types" /> | ||
import type { RelativePosition } from 'yjs'; | ||
@@ -15,19 +16,26 @@ import type { Awareness } from 'y-protocols/awareness.js'; | ||
} | ||
interface AwarenessState { | ||
interface AwarenessState<Flags extends Record<string, boolean> = BlockSuiteFlags> { | ||
cursor?: SelectionRange; | ||
user: UserInfo; | ||
user?: UserInfo; | ||
flags: Flags; | ||
} | ||
interface AwarenessMessage { | ||
interface AwarenessMessage<Flags extends Record<string, boolean> = BlockSuiteFlags> { | ||
id: number; | ||
type: 'add' | 'update' | 'remove'; | ||
state?: AwarenessState; | ||
state?: AwarenessState<Flags>; | ||
} | ||
export declare class AwarenessAdapter { | ||
readonly space: Space; | ||
export interface AwarenessMetadataMessage<Flags extends Record<string, boolean> = BlockSuiteFlags, Key extends keyof Flags = keyof Flags> { | ||
field: Key; | ||
value: Flags[Key]; | ||
} | ||
export declare class AwarenessAdapter<Flags extends Record<string, boolean> = BlockSuiteFlags> { | ||
readonly space: Space<any, Flags>; | ||
readonly awareness: Awareness; | ||
readonly signals: { | ||
update: Signal<AwarenessMessage>; | ||
update: Signal<AwarenessMessage<Flags>>; | ||
}; | ||
constructor(space: Space, awareness: Awareness); | ||
constructor(space: Space<any, Flags>, awareness: Awareness, defaultFlags?: Partial<Flags>); | ||
setLocalCursor(range: SelectionRange): void; | ||
setFlag<Key extends keyof Flags>(field: Key, value: Flags[Key]): void; | ||
getFlag<Key extends keyof Flags>(field: Key): any; | ||
getLocalCursor(): SelectionRange | undefined; | ||
@@ -34,0 +42,0 @@ getStates(): Map<number, AwarenessState>; |
import * as Y from 'yjs'; | ||
import { Signal } from './utils/signal.js'; | ||
import { assertExists } from './utils/utils.js'; | ||
export class AwarenessAdapter { | ||
constructor(space, awareness) { | ||
constructor( | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
space, awareness, defaultFlags = {}) { | ||
this.signals = { | ||
@@ -44,2 +47,12 @@ update: new Signal(), | ||
this.signals.update.on(this._onAwarenessMessage); | ||
const upstreamFlags = awareness.getLocalState()?.flags; | ||
if (upstreamFlags) { | ||
this.awareness.setLocalStateField('flags', { | ||
...defaultFlags, | ||
...upstreamFlags, | ||
}); | ||
} | ||
else { | ||
this.awareness.setLocalStateField('flags', { ...defaultFlags }); | ||
} | ||
} | ||
@@ -49,2 +62,11 @@ setLocalCursor(range) { | ||
} | ||
setFlag(field, value) { | ||
const oldFlags = this.awareness.getLocalState()?.flags ?? {}; | ||
this.awareness.setLocalStateField('flags', { ...oldFlags, [field]: value }); | ||
} | ||
getFlag(field) { | ||
const flags = this.awareness.getLocalState()?.flags; | ||
assertExists(flags); | ||
return flags[field]; | ||
} | ||
getLocalCursor() { | ||
@@ -79,3 +101,3 @@ const states = this.awareness.getStates(); | ||
updateLocalCursor() { | ||
const localCursor = this.space.awareness.getLocalCursor(); | ||
const localCursor = this.getLocalCursor(); | ||
if (!localCursor) { | ||
@@ -82,0 +104,0 @@ return; |
@@ -5,2 +5,3 @@ /// <reference types="blocksuite__global-types" /> | ||
import { Signal } from './utils/signal.js'; | ||
import type { DeltaOperation } from 'quill'; | ||
interface StaticValue { | ||
@@ -28,3 +29,3 @@ _$litStatic$: string; | ||
block2Text(childText: string, begin?: number, end?: number): string; | ||
_deltaLeaf2Html(deltaLeaf: Record<string, unknown>): unknown; | ||
_deltaLeaf2Html(deltaLeaf: DeltaOperation): string; | ||
dispose(): void; | ||
@@ -31,0 +32,0 @@ } |
@@ -25,3 +25,3 @@ import { Signal } from './utils/signal.js'; | ||
block2html(childText, _previousSiblingId, _nextSiblingId, begin, end) { | ||
const delta = this.text?.sliceToDelta(begin || 0, end); | ||
const delta = this.text?.sliceToDelta(begin || 0, end) || []; | ||
const text = delta.reduce((html, item) => { | ||
@@ -28,0 +28,0 @@ return html + this._deltaLeaf2Html(item); |
@@ -0,1 +1,2 @@ | ||
/// <reference types="blocksuite__global-types" /> | ||
import type * as Y from 'yjs'; | ||
@@ -11,3 +12,3 @@ import { Awareness } from 'y-protocols/awareness.js'; | ||
} | ||
export declare class Space<Data extends Record<string, unknown> = Record<string, any>> { | ||
export declare class Space<Data extends Record<string, unknown> = Record<string, any>, Flags extends Record<string, boolean> = BlockSuiteFlags> { | ||
/** unprefixed id */ | ||
@@ -22,6 +23,7 @@ readonly id: string; | ||
protected readonly origin: Y.Map<Data[keyof Data]>; | ||
readonly awareness: AwarenessAdapter; | ||
readonly awareness: AwarenessAdapter<Flags>; | ||
readonly richTextAdapters: Map<string, RichTextAdapter>; | ||
constructor(id: string, doc: BlockSuiteDoc, awareness: Awareness, options?: { | ||
valueInitializer?: DataInitializer<Partial<Data>>; | ||
defaultFlags?: Partial<Flags>; | ||
}); | ||
@@ -28,0 +30,0 @@ get prefixedId(): string; |
import { Awareness } from 'y-protocols/awareness.js'; | ||
import { AwarenessAdapter } from './awareness.js'; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export class Space { | ||
@@ -15,3 +14,3 @@ constructor(id, doc, awareness, options) { | ||
const aware = awareness ?? new Awareness(this.doc); | ||
this.awareness = new AwarenessAdapter(this, aware); | ||
this.awareness = new AwarenessAdapter(this, aware, options?.defaultFlags); | ||
} | ||
@@ -18,0 +17,0 @@ get prefixedId() { |
@@ -0,1 +1,2 @@ | ||
/// <reference types="blocksuite__global-types" /> | ||
import type { Space } from './space.js'; | ||
@@ -38,3 +39,3 @@ import type { IdGenerator } from './utils/id-generator.js'; | ||
} | ||
export interface StoreOptions extends SSROptions { | ||
export interface StoreOptions<Flags extends Record<string, boolean> = BlockSuiteFlags> extends SSROptions { | ||
room?: string; | ||
@@ -44,2 +45,3 @@ providers?: DocProviderConstructor[]; | ||
idGenerator?: Generator; | ||
defaultFlags?: Flags; | ||
} | ||
@@ -49,3 +51,3 @@ export declare class Store { | ||
readonly providers: DocProvider[]; | ||
readonly spaces: Map<string, Space<Record<string, any>>>; | ||
readonly spaces: Map<string, Space<Record<string, any>, BlockSuiteFlags>>; | ||
readonly awareness: Awareness; | ||
@@ -52,0 +54,0 @@ readonly idGenerator: IdGenerator; |
@@ -62,3 +62,3 @@ import * as Y from 'yjs'; | ||
insert(content: string, index: number, attributes?: Record<string, unknown>): void; | ||
insertList(insertTexts: Record<string, unknown>[], index: number): void; | ||
insertList(insertTexts: DeltaOperation[], index: number): void; | ||
join(other: Text): void; | ||
@@ -70,4 +70,4 @@ format(index: number, length: number, format: any): void; | ||
applyDelta(delta: any): void; | ||
toDelta(): any; | ||
sliceToDelta(begin: number, end?: number): any; | ||
toDelta(): DeltaOperation[]; | ||
sliceToDelta(begin: number, end?: number): DeltaOperation[]; | ||
toString(): string; | ||
@@ -74,0 +74,0 @@ } |
@@ -29,3 +29,3 @@ import * as Y from 'yjs'; | ||
commonFieldsUpdated: Signal<void>; | ||
constructor(id: string, doc: BlockSuiteDoc, awareness: Awareness); | ||
constructor(id: string, doc: BlockSuiteDoc, awareness: Awareness, defaultFlags?: Record<string, boolean>); | ||
get pages(): Y.Array<unknown>; | ||
@@ -32,0 +32,0 @@ get name(): string; |
@@ -9,3 +9,3 @@ import * as Y from 'yjs'; | ||
class WorkspaceMeta extends Space { | ||
constructor(id, doc, awareness) { | ||
constructor(id, doc, awareness, defaultFlags) { | ||
super(id, doc, awareness, { | ||
@@ -18,2 +18,3 @@ valueInitializer: { | ||
}, | ||
defaultFlags, | ||
}); | ||
@@ -171,3 +172,3 @@ this._prevPages = new Set(); | ||
this.room = options.room; | ||
this.meta = new WorkspaceMeta('space:meta', this.doc, this._store.awareness); | ||
this.meta = new WorkspaceMeta('space:meta', this.doc, this._store.awareness, options.defaultFlags); | ||
this.signals = { | ||
@@ -174,0 +175,0 @@ pagesUpdated: this.meta.pagesUpdated, |
{ | ||
"name": "@blocksuite/store", | ||
"version": "0.4.0-20230110192220-0bac914", | ||
"version": "0.4.0-20230111121357-6129124", | ||
"description": "BlockSuite data store built for general purpose state management.", | ||
@@ -23,3 +23,3 @@ "main": "dist/index.js", | ||
"cross-env": "^7.0.3", | ||
"lit": "^2.5.0", | ||
"lit": "^2.6.0", | ||
"yjs": "^13.5.44" | ||
@@ -26,0 +26,0 @@ }, |
@@ -6,2 +6,3 @@ import * as Y from 'yjs'; | ||
import { Signal } from './utils/signal.js'; | ||
import { assertExists } from './utils/utils.js'; | ||
@@ -20,22 +21,43 @@ export interface SelectionRange { | ||
interface AwarenessState { | ||
interface AwarenessState< | ||
Flags extends Record<string, boolean> = BlockSuiteFlags | ||
> { | ||
cursor?: SelectionRange; | ||
user: UserInfo; | ||
user?: UserInfo; | ||
flags: Flags; | ||
} | ||
interface AwarenessMessage { | ||
interface AwarenessMessage< | ||
Flags extends Record<string, boolean> = BlockSuiteFlags | ||
> { | ||
id: number; | ||
type: 'add' | 'update' | 'remove'; | ||
state?: AwarenessState; | ||
state?: AwarenessState<Flags>; | ||
} | ||
export class AwarenessAdapter { | ||
readonly space: Space; | ||
export interface AwarenessMetadataMessage< | ||
Flags extends Record<string, boolean> = BlockSuiteFlags, | ||
Key extends keyof Flags = keyof Flags | ||
> { | ||
field: Key; | ||
value: Flags[Key]; | ||
} | ||
export class AwarenessAdapter< | ||
Flags extends Record<string, boolean> = BlockSuiteFlags | ||
> { | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
readonly space: Space<any, Flags>; | ||
readonly awareness: Awareness; | ||
readonly signals = { | ||
update: new Signal<AwarenessMessage>(), | ||
update: new Signal<AwarenessMessage<Flags>>(), | ||
}; | ||
constructor(space: Space, awareness: Awareness) { | ||
constructor( | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
space: Space<any, Flags>, | ||
awareness: Awareness, | ||
defaultFlags: Partial<Flags> = {} | ||
) { | ||
this.space = space; | ||
@@ -45,2 +67,11 @@ this.awareness = awareness; | ||
this.signals.update.on(this._onAwarenessMessage); | ||
const upstreamFlags = awareness.getLocalState()?.flags; | ||
if (upstreamFlags) { | ||
this.awareness.setLocalStateField('flags', { | ||
...defaultFlags, | ||
...upstreamFlags, | ||
}); | ||
} else { | ||
this.awareness.setLocalStateField('flags', { ...defaultFlags }); | ||
} | ||
} | ||
@@ -52,2 +83,13 @@ | ||
public setFlag<Key extends keyof Flags>(field: Key, value: Flags[Key]) { | ||
const oldFlags = this.awareness.getLocalState()?.flags ?? {}; | ||
this.awareness.setLocalStateField('flags', { ...oldFlags, [field]: value }); | ||
} | ||
public getFlag<Key extends keyof Flags>(field: Key) { | ||
const flags = this.awareness.getLocalState()?.flags; | ||
assertExists(flags); | ||
return flags[field]; | ||
} | ||
public getLocalCursor(): SelectionRange | undefined { | ||
@@ -75,3 +117,3 @@ const states = this.awareness.getStates(); | ||
type: 'add', | ||
state: states.get(id) as AwarenessState, | ||
state: states.get(id) as AwarenessState<Flags>, | ||
}); | ||
@@ -83,3 +125,3 @@ }); | ||
type: 'update', | ||
state: states.get(id) as AwarenessState, | ||
state: states.get(id) as AwarenessState<Flags>, | ||
}); | ||
@@ -95,3 +137,3 @@ }); | ||
private _onAwarenessMessage = (awMsg: AwarenessMessage) => { | ||
private _onAwarenessMessage = (awMsg: AwarenessMessage<Flags>) => { | ||
if (awMsg.id === this.awareness.clientID) { | ||
@@ -122,3 +164,3 @@ this.updateLocalCursor(); | ||
if (anchor && focus && textAdapter) { | ||
const user = awState.user || {}; | ||
const user: Partial<UserInfo> = awState.user || {}; | ||
const color = user.color || '#ffa500'; | ||
@@ -141,3 +183,3 @@ const name = user.name || 'other'; | ||
public updateLocalCursor() { | ||
const localCursor = this.space.awareness.getLocalCursor(); | ||
const localCursor = this.getLocalCursor(); | ||
if (!localCursor) { | ||
@@ -144,0 +186,0 @@ return; |
import type { Page } from './workspace/index.js'; | ||
import type { TextType } from './text-adapter.js'; | ||
import { Signal } from './utils/signal.js'; | ||
import type { DeltaOperation } from 'quill'; | ||
@@ -61,4 +62,4 @@ // ported from lit | ||
) { | ||
const delta = this.text?.sliceToDelta(begin || 0, end); | ||
const text = delta.reduce((html: string, item: Record<string, unknown>) => { | ||
const delta = this.text?.sliceToDelta(begin || 0, end) || []; | ||
const text = delta.reduce((html: string, item: DeltaOperation) => { | ||
return html + this._deltaLeaf2Html(item); | ||
@@ -74,8 +75,5 @@ }, ''); | ||
_deltaLeaf2Html(deltaLeaf: Record<string, unknown>) { | ||
let text = deltaLeaf.insert; | ||
const attributes: Record<string, boolean> = deltaLeaf.attributes as Record< | ||
string, | ||
boolean | ||
>; | ||
_deltaLeaf2Html(deltaLeaf: DeltaOperation) { | ||
let text: string = deltaLeaf.insert; | ||
const attributes = deltaLeaf.attributes; | ||
if (!attributes) { | ||
@@ -82,0 +80,0 @@ return text; |
@@ -13,4 +13,7 @@ import type * as Y from 'yjs'; | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
export class Space<Data extends Record<string, unknown> = Record<string, any>> { | ||
export class Space< | ||
// eslint-disable-next-line @typescript-eslint/no-explicit-any | ||
Data extends Record<string, unknown> = Record<string, any>, | ||
Flags extends Record<string, boolean> = BlockSuiteFlags | ||
> { | ||
/** unprefixed id */ | ||
@@ -25,3 +28,3 @@ readonly id: string; | ||
protected readonly origin: Y.Map<Data[keyof Data]>; | ||
readonly awareness!: AwarenessAdapter; | ||
readonly awareness!: AwarenessAdapter<Flags>; | ||
readonly richTextAdapters = new Map<string, RichTextAdapter>(); | ||
@@ -35,2 +38,3 @@ | ||
valueInitializer?: DataInitializer<Partial<Data>>; | ||
defaultFlags?: Partial<Flags>; | ||
} | ||
@@ -47,3 +51,3 @@ ) { | ||
const aware = awareness ?? new Awareness(this.doc); | ||
this.awareness = new AwarenessAdapter(this as Space, aware); | ||
this.awareness = new AwarenessAdapter(this, aware, options?.defaultFlags); | ||
} | ||
@@ -50,0 +54,0 @@ |
@@ -48,3 +48,5 @@ import type { Space } from './space.js'; | ||
export interface StoreOptions extends SSROptions { | ||
export interface StoreOptions< | ||
Flags extends Record<string, boolean> = BlockSuiteFlags | ||
> extends SSROptions { | ||
room?: string; | ||
@@ -54,2 +56,3 @@ providers?: DocProviderConstructor[]; | ||
idGenerator?: Generator; | ||
defaultFlags?: Flags; | ||
} | ||
@@ -56,0 +59,0 @@ |
@@ -165,3 +165,3 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ | ||
insertList(insertTexts: Record<string, unknown>[], index: number) { | ||
insertList(insertTexts: DeltaOperation[], index: number) { | ||
this._transact(() => { | ||
@@ -230,7 +230,7 @@ for (let i = insertTexts.length - 1; i >= 0; i--) { | ||
toDelta() { | ||
toDelta(): DeltaOperation[] { | ||
return this._yText?.toDelta() || []; | ||
} | ||
sliceToDelta(begin: number, end?: number) { | ||
sliceToDelta(begin: number, end?: number): DeltaOperation[] { | ||
const result: DeltaOperation[] = []; | ||
@@ -249,3 +249,3 @@ if (end && begin >= end) { | ||
for (let i = 0; i < delta.length; i++) { | ||
const content: DeltaOperation = delta[i]; | ||
const content = delta[i]; | ||
let contentText: string = content.insert || ''; | ||
@@ -252,0 +252,0 @@ const contentLen = contentText.length; |
@@ -33,3 +33,8 @@ import * as Y from 'yjs'; | ||
constructor(id: string, doc: BlockSuiteDoc, awareness: Awareness) { | ||
constructor( | ||
id: string, | ||
doc: BlockSuiteDoc, | ||
awareness: Awareness, | ||
defaultFlags?: Record<string, boolean> | ||
) { | ||
super(id, doc, awareness, { | ||
@@ -42,2 +47,3 @@ valueInitializer: { | ||
}, | ||
defaultFlags, | ||
}); | ||
@@ -244,3 +250,4 @@ this.origin.observeDeep(this._handleEvents); | ||
this.doc, | ||
this._store.awareness | ||
this._store.awareness, | ||
options.defaultFlags | ||
); | ||
@@ -247,0 +254,0 @@ |
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
453279
7691