mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 12:28:42 +00:00
160 lines
4.3 KiB
Markdown
160 lines
4.3 KiB
Markdown
# @blocksuite/affine-ext-loader
|
|
|
|
Blocksuite extension loader system for AFFiNE, providing a structured way to manage and load extensions in different contexts.
|
|
|
|
## Usage
|
|
|
|
### Basic Extension Provider
|
|
|
|
```typescript
|
|
import { BaseExtensionProvider } from '@blocksuite/affine-ext-loader';
|
|
import { z } from 'zod';
|
|
|
|
// Create a custom provider with options
|
|
class MyProvider extends BaseExtensionProvider<'my-scope', { enabled: boolean }> {
|
|
name = 'MyProvider';
|
|
|
|
schema = z.object({
|
|
enabled: z.boolean(),
|
|
});
|
|
|
|
setup(context: Context<'my-scope'>, options?: { enabled: boolean }) {
|
|
super.setup(context, options);
|
|
// Custom setup logic
|
|
}
|
|
}
|
|
```
|
|
|
|
### Store Extensions
|
|
|
|
```typescript
|
|
import { StoreExtensionProvider, StoreExtensionManager } from '@blocksuite/affine-ext-loader';
|
|
import { z } from 'zod';
|
|
|
|
// Create a store provider with custom options
|
|
class MyStoreProvider extends StoreExtensionProvider<{ cacheSize: number }> {
|
|
override name = 'MyStoreProvider';
|
|
|
|
override schema = z.object({
|
|
cacheSize: z.number().min(0),
|
|
});
|
|
|
|
override setup(context: StoreExtensionContext, options?: { cacheSize: number }) {
|
|
super.setup(context, options);
|
|
context.register([Ext1, Ext2, Ext3]);
|
|
}
|
|
}
|
|
|
|
// Create and use the store extension manager
|
|
const manager = new StoreExtensionManager([MyStoreProvider]);
|
|
manager.configure(MyStoreProvider, { cacheSize: 100 });
|
|
const extensions = manager.get('store');
|
|
```
|
|
|
|
### View Extensions
|
|
|
|
```typescript
|
|
import { ViewExtensionProvider, ViewExtensionManager } from '@blocksuite/affine-ext-loader';
|
|
import { z } from 'zod';
|
|
|
|
// Create a view provider with custom options
|
|
class MyViewProvider extends ViewExtensionProvider<{ theme: string }> {
|
|
override name = 'MyViewProvider';
|
|
|
|
override schema = z.object({
|
|
theme: z.enum(['light', 'dark']),
|
|
});
|
|
|
|
override setup(context: ViewExtensionContext, options?: { theme: string }) {
|
|
super.setup(context, options);
|
|
|
|
context.register([CommonExt]);
|
|
if (context.scope === 'page') {
|
|
context.register([PageExt]);
|
|
} else if (context.scope === 'edgeless') {
|
|
context.register([EdgelessExt]);
|
|
}
|
|
if (options?.theme === 'dark') {
|
|
context.register([DarkModeExt]);
|
|
}
|
|
}
|
|
|
|
// Override effect to run one-time initialization logic
|
|
override effect() {
|
|
// This will only run once per provider class
|
|
console.log('Initializing MyViewProvider');
|
|
// Register lit elements
|
|
this.registerLitElements();
|
|
}
|
|
}
|
|
|
|
// Create and use the view extension manager
|
|
const manager = new ViewExtensionManager([MyViewProvider]);
|
|
manager.configure(MyViewProvider, { theme: 'dark' });
|
|
|
|
// Get extensions for different view scopes
|
|
const pageExtensions = manager.get('page');
|
|
const edgelessExtensions = manager.get('edgeless');
|
|
```
|
|
|
|
### One-time Initialization with Effect
|
|
|
|
View extensions support one-time initialization through the `effect` method. This method is called automatically during setup, but only once per provider class. It's useful for:
|
|
|
|
- Initializing global state
|
|
- Registering lit elements
|
|
- Setting up shared resources
|
|
|
|
```typescript
|
|
class MyViewProvider extends ViewExtensionProvider {
|
|
override effect() {
|
|
// This will only run once, even if multiple instances are created
|
|
initializeGlobalState();
|
|
registerLitElements();
|
|
setupGlobalEventListeners();
|
|
}
|
|
}
|
|
```
|
|
|
|
### Available View Scopes
|
|
|
|
The view extension system supports the following scopes:
|
|
|
|
- `page` - Standard page view
|
|
- `edgeless` - Edgeless (whiteboard) view
|
|
- `preview-page` - Page preview view
|
|
- `preview-edgeless` - Edgeless preview view
|
|
- `mobile-page` - Mobile page view
|
|
- `mobile-edgeless` - Mobile edgeless view
|
|
|
|
### Extension Configuration
|
|
|
|
Extensions can be configured using the `configure` method:
|
|
|
|
```typescript
|
|
// Set configuration directly
|
|
manager.configure(MyProvider, { enabled: true });
|
|
|
|
// Update configuration using a function
|
|
manager.configure(MyProvider, prev => {
|
|
if (!prev) return prev;
|
|
return {
|
|
...prev,
|
|
enabled: !prev.enabled,
|
|
};
|
|
});
|
|
|
|
// Remove configuration
|
|
manager.configure(MyProvider, undefined);
|
|
```
|
|
|
|
### Dependency Injection
|
|
|
|
Both store and view extension managers support dependency injection:
|
|
|
|
```typescript
|
|
// Access the manager through the di container
|
|
const viewManager = std.get(ViewExtensionManagerIdentifier);
|
|
const pagePreviewExtension = viewManager.get('preview-page');
|
|
```
|