kakidash 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +30 -7
- package/README.md +30 -7
- package/dist/index.d.ts +74 -3
- package/dist/kakidash.cjs +9 -9
- package/dist/kakidash.es.js +2031 -1812
- package/dist/kakidash.umd.js +9 -9
- package/package.json +1 -1
package/README.ja.md
CHANGED
|
@@ -92,13 +92,12 @@ pnpm add kakidash
|
|
|
92
92
|
pnpm add kakidash
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
```typescript
|
|
96
96
|
import { Kakidash } from 'kakidash';
|
|
97
97
|
|
|
98
98
|
// コンテナ取得
|
|
99
99
|
const container = document.getElementById('mindmap-container');
|
|
100
100
|
|
|
101
|
-
// インスタンス化
|
|
102
101
|
// インスタンス化 (オプション指定可能)
|
|
103
102
|
const kakidash = new Kakidash(container, {
|
|
104
103
|
locale: 'ja', // オプション: 'en' | 'ja' (デフォルト: 'en')
|
|
@@ -106,11 +105,13 @@ const kakidash = new Kakidash(container, {
|
|
|
106
105
|
customStyles: { // オプション: 初期のカスタムスタイル
|
|
107
106
|
rootNode: { border: '2px solid red' }
|
|
108
107
|
},
|
|
109
|
-
disabledCommandPaletteFeatures: ['import'] // オプション: 特定の機能を無効化
|
|
108
|
+
disabledCommandPaletteFeatures: ['import'], // オプション: 特定の機能を無効化
|
|
109
|
+
//getImage: (ref) => myImageMap[ref] // オプション: 拡大表示用にオリジナル画像を取得するコールバック
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
// 必要に応じて初期データをロードしたり、ノードを追加したりします
|
|
113
113
|
kakidash.addNode(kakidash.getRootId(), 'Hello World');
|
|
114
|
+
```
|
|
114
115
|
|
|
115
116
|
### 3. テーマの切り替え
|
|
116
117
|
|
|
@@ -118,9 +119,7 @@ kakidash.addNode(kakidash.getRootId(), 'Hello World');
|
|
|
118
119
|
|
|
119
120
|
```typescript
|
|
120
121
|
kakidash.setTheme('dark'); // 'default', 'simple', 'colorful', 'dark'
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
````
|
|
122
|
+
```
|
|
124
123
|
|
|
125
124
|
#### B. ブラウザ直接読み込み (Script Tag / CDN)
|
|
126
125
|
|
|
@@ -209,7 +208,9 @@ kakidash.setTheme('custom');
|
|
|
209
208
|
- `options.disabledCommandPaletteFeatures`: コマンドパレットの特定の機能を無効化 ('search' | 'icon' | 'import' | 'export')。
|
|
210
209
|
- **`kakidash.addNode(parentId, topic)`**: 指定した親ノードに新しい子ノードを追加します。
|
|
211
210
|
- **`kakidash.getData()`**: 現在のマインドマップデータをJSONオブジェクトとして取得します。
|
|
212
|
-
- **`kakidash.loadData(data)`**: JSON
|
|
211
|
+
- **`kakidash.loadData(data)`**: JSONデータを読み込み、マインドマップを描画します。画像埋め込み済みの旧形式データも自動移行して読み込めます。
|
|
212
|
+
- **`kakidash.getImages()`**: 現在メモリ(ImageStore)に保持されているすべてのオリジナル画像を取得します。
|
|
213
|
+
- **`kakidash.gcImages()`**: 使用されていない画像をメモリから削除します。
|
|
213
214
|
- **`kakidash.updateGlobalStyles(styles)`**: グローバルスタイルを更新します ('custom' テーマ選択時のみ有効)。
|
|
214
215
|
- **`kakidash.updateLayout(mode)`**: レイアウトモードを変更します ('Standard', 'Left', 'Right')。
|
|
215
216
|
- **`kakidash.setReadOnly(boolean)`**: 読み取り専用モードを切り替えます。
|
|
@@ -391,6 +392,28 @@ board.registerCommand({
|
|
|
391
392
|
|
|
392
393
|
登録されたコマンドはコマンドパレット(デフォルト:`m` キー)の一覧に表示されます。項目をクリックするか Enter キーを押すことで実行されます。
|
|
393
394
|
|
|
395
|
+
## 画像の管理 (ハイブリッド形式)
|
|
396
|
+
|
|
397
|
+
Kakidashは、大量の画像を効率的に扱うために「ハイブリッド保存方式」を採用しています。
|
|
398
|
+
- **サムネイル**: 軽量な画像データ。マインドマップのJSON内に直接保存されます。
|
|
399
|
+
- **オリジナル画像**: 高解像度の画像データ。JSONからは切り離され、メモリ上(`ImageStore`)で管理されます。これらはホストアプリケーション(VSCode拡張機能など)側でサイドカーフォルダ等に保存する必要があります。
|
|
400
|
+
|
|
401
|
+
### 実装例: VSCode拡張機能との連携
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
// 1. 保存時
|
|
405
|
+
const data = kakidash.getData(); // 巨大な画像を含まない軽量なJSON
|
|
406
|
+
const images = kakidash.getImages(); // { 参照ID: Base64データ } のマップ
|
|
407
|
+
|
|
408
|
+
// 'data' を .kaki ファイルに、'images' を 'filename_images/' フォルダ等に保存します
|
|
409
|
+
saveToDisk(data, images);
|
|
410
|
+
|
|
411
|
+
// 2. 読み込み時
|
|
412
|
+
const { data, images } = loadFromDisk();
|
|
413
|
+
kakidash.loadData(data); // 旧形式(画像埋め込み)の場合も自動でマイグレーションされます
|
|
414
|
+
// コンストラクタの getImage コールバックを通じて、読み込んだ画像をライブラリに提供します
|
|
415
|
+
```
|
|
416
|
+
|
|
394
417
|
## アーキテクチャ
|
|
395
418
|
|
|
396
419
|
ソフトウェアアーキテクチャの詳細や内部モジュールの依存関係については、以下を参照してください:
|
package/README.md
CHANGED
|
@@ -90,13 +90,12 @@ Prepare a container element (e.g., `div`) to display `kakidash`.
|
|
|
90
90
|
pnpm add kakidash
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
```typescript
|
|
94
94
|
import { Kakidash } from 'kakidash';
|
|
95
95
|
|
|
96
96
|
// Get container
|
|
97
97
|
const container = document.getElementById('mindmap-container');
|
|
98
98
|
|
|
99
|
-
// Instantiate
|
|
100
99
|
// Instantiate with optional configuration
|
|
101
100
|
const kakidash = new Kakidash(container, {
|
|
102
101
|
locale: 'en', // Optional: 'en' | 'ja' (Default: 'en')
|
|
@@ -104,11 +103,13 @@ const kakidash = new Kakidash(container, {
|
|
|
104
103
|
customStyles: { // Optional: Initial custom styles
|
|
105
104
|
rootNode: { border: '2px solid red' }
|
|
106
105
|
},
|
|
107
|
-
disabledCommandPaletteFeatures: ['import'] // Optional: Disable specific features
|
|
106
|
+
disabledCommandPaletteFeatures: ['import'], // Optional: Disable specific features
|
|
107
|
+
//getImage: (ref) => myImageMap[ref] // Optional: Callback to fetch original images for zooming
|
|
108
108
|
});
|
|
109
109
|
|
|
110
110
|
// Add initial data or nodes if needed
|
|
111
111
|
kakidash.addNode(kakidash.getRootId(), 'Hello World');
|
|
112
|
+
```
|
|
112
113
|
|
|
113
114
|
### 3. Theme Selection
|
|
114
115
|
|
|
@@ -116,9 +117,7 @@ You can switch themes dynamically:
|
|
|
116
117
|
|
|
117
118
|
```typescript
|
|
118
119
|
kakidash.setTheme('dark'); // 'default', 'simple', 'colorful', 'dark'
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
````
|
|
120
|
+
```
|
|
122
121
|
|
|
123
122
|
#### B. Browser Direct Import (Script Tag / CDN)
|
|
124
123
|
|
|
@@ -204,7 +203,9 @@ All values accept standard CSS strings.
|
|
|
204
203
|
- `options.disabledCommandPaletteFeatures`: Features to disable in the command palette ('search' | 'icon' | 'import' | 'export').
|
|
205
204
|
- **`kakidash.addNode(parentId, topic)`**: Adds a new child node to the specified parent node.
|
|
206
205
|
- **`kakidash.getData()`**: Retrieves current mindmap data as a JSON object.
|
|
207
|
-
- **`kakidash.loadData(data)`**: Loads JSON data and renders the mindmap.
|
|
206
|
+
- **`kakidash.loadData(data)`**: Loads JSON data and renders the mindmap. Supports legacy format with embedded images.
|
|
207
|
+
- **`kakidash.getImages()`**: Retrieves all original high-resolution images currently in memory.
|
|
208
|
+
- **`kakidash.gcImages()`**: Cleans up unused images from memory.
|
|
208
209
|
- **`kakidash.updateGlobalStyles(styles)`**: Updates global styles (only active when theme is 'custom').
|
|
209
210
|
- **`kakidash.updateLayout(mode)`**: Changes layout mode ('Standard', 'Left', 'Right').
|
|
210
211
|
- **`kakidash.setReadOnly(boolean)`**: Toggles read-only mode.
|
|
@@ -386,6 +387,28 @@ board.registerCommand({
|
|
|
386
387
|
|
|
387
388
|
Registered commands will appear in the Command Palette (default key: `m`). Clicking or pressing Enter on the item will execute the handler.
|
|
388
389
|
|
|
390
|
+
## Image Management (Hybrid Storage)
|
|
391
|
+
|
|
392
|
+
Kakidash uses a hybrid storage approach to handle large images efficiently.
|
|
393
|
+
- **Thumbnails**: Small, low-resolution versions are stored directly in the JSON data.
|
|
394
|
+
- **Originals**: High-resolution versions are kept in a separate memory store (`ImageStore`) and should be persisted by the host application (e.g., in a sidecar folder).
|
|
395
|
+
|
|
396
|
+
### Example: VSCode Extension Integration
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
// 1. Saving
|
|
400
|
+
const data = kakidash.getData(); // JSON without large images
|
|
401
|
+
const images = kakidash.getImages(); // Map of { imageRef: base64Data }
|
|
402
|
+
|
|
403
|
+
// Save 'data' to .kaki file and 'images' to .kaki_images/ folder
|
|
404
|
+
saveToDisk(data, images);
|
|
405
|
+
|
|
406
|
+
// 2. Loading
|
|
407
|
+
const { data, images } = loadFromDisk();
|
|
408
|
+
kakidash.loadData(data); // Library handles migration if old format
|
|
409
|
+
// Images should be provided via the getImage callback in constructor
|
|
410
|
+
```
|
|
411
|
+
|
|
389
412
|
## Architecture
|
|
390
413
|
|
|
391
414
|
For details on the software architecture and internal module dependencies, please refer to:
|
package/dist/index.d.ts
CHANGED
|
@@ -137,6 +137,8 @@ declare interface ControllerDependencies {
|
|
|
137
137
|
fileIOService: FileIOService;
|
|
138
138
|
themeService: ThemeService;
|
|
139
139
|
commandBus: CommandBus;
|
|
140
|
+
imageStore: ImageStore;
|
|
141
|
+
imageProcessingService: ImageProcessingService;
|
|
140
142
|
locale?: 'en' | 'ja';
|
|
141
143
|
commandPaletteFeatures?: ('search' | 'icon' | 'import' | 'export')[];
|
|
142
144
|
}
|
|
@@ -204,6 +206,54 @@ declare interface IdGenerator {
|
|
|
204
206
|
generate(): string;
|
|
205
207
|
}
|
|
206
208
|
|
|
209
|
+
declare class ImageProcessingService {
|
|
210
|
+
/**
|
|
211
|
+
* Generates a lightweight thumbnail from a base64 image string.
|
|
212
|
+
* Uses HTML Canvas API.
|
|
213
|
+
* @param base64Data The original base64 image data
|
|
214
|
+
* @param maxWidth The maximum width for the thumbnail (default 200)
|
|
215
|
+
* @param quality Image quality for lossy formats (0 to 1, default 0.7)
|
|
216
|
+
*/
|
|
217
|
+
generateThumbnail(base64Data: string, maxWidth?: number, quality?: number): Promise<ThumbnailResult>;
|
|
218
|
+
/**
|
|
219
|
+
* Calculates proportional dimensions preserving aspect ratio, constrained by maxWidth.
|
|
220
|
+
*/
|
|
221
|
+
calculateDimensions(originalWidth: number, originalHeight: number, maxWidth: number): {
|
|
222
|
+
width: number;
|
|
223
|
+
height: number;
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
declare class ImageStore {
|
|
228
|
+
private images;
|
|
229
|
+
/**
|
|
230
|
+
* Adds an image to the store.
|
|
231
|
+
* @param ref The unique reference or filename of the image
|
|
232
|
+
* @param base64Data The original base64 image data
|
|
233
|
+
*/
|
|
234
|
+
addImage(ref: string, base64Data: string): void;
|
|
235
|
+
/**
|
|
236
|
+
* Retrieves an image from the store.
|
|
237
|
+
* @param ref The unique reference or filename of the image
|
|
238
|
+
* @returns The base64 image data, or undefined if not found
|
|
239
|
+
*/
|
|
240
|
+
getImage(ref: string): string | undefined;
|
|
241
|
+
/**
|
|
242
|
+
* Removes an image from the store.
|
|
243
|
+
* @param ref The unique reference or filename of the image
|
|
244
|
+
*/
|
|
245
|
+
removeImage(ref: string): void;
|
|
246
|
+
/**
|
|
247
|
+
* Retrieves all image references currently in the store.
|
|
248
|
+
* @returns Array of references
|
|
249
|
+
*/
|
|
250
|
+
getAllRefs(): string[];
|
|
251
|
+
/**
|
|
252
|
+
* Clears all images from the store.
|
|
253
|
+
*/
|
|
254
|
+
clear(): void;
|
|
255
|
+
}
|
|
256
|
+
|
|
207
257
|
declare interface IMindMapEventBus {
|
|
208
258
|
emit<K extends keyof KakidashEventMap>(event: K, payload: KakidashEventMap[K]): void;
|
|
209
259
|
on<K extends keyof KakidashEventMap>(event: K, handler: (payload: KakidashEventMap[K]) => void): void;
|
|
@@ -349,6 +399,7 @@ export declare class Kakidash extends TypedEventEmitter<KakidashEventMap> {
|
|
|
349
399
|
panBoard(dx: number, dy: number): void;
|
|
350
400
|
zoomBoard(delta: number, clientX: number, clientY: number): void;
|
|
351
401
|
resetZoom(): void;
|
|
402
|
+
zoomNode(nodeId: string): void;
|
|
352
403
|
copyNode(nodeId: string): void;
|
|
353
404
|
pasteNode(parentId: string): void;
|
|
354
405
|
pasteImage(parentId: string, imageData: string, width?: number, height?: number): void;
|
|
@@ -358,6 +409,8 @@ export declare class Kakidash extends TypedEventEmitter<KakidashEventMap> {
|
|
|
358
409
|
getLayoutMode(): LayoutMode;
|
|
359
410
|
navigateNode(nodeId: string, direction: Direction): void;
|
|
360
411
|
getData(): MindMapData;
|
|
412
|
+
getImages(): Record<string, string>;
|
|
413
|
+
gcImages(): void;
|
|
361
414
|
loadData(data: MindMapData): void;
|
|
362
415
|
getRootId(): string;
|
|
363
416
|
}
|
|
@@ -526,6 +579,8 @@ declare class MindMapController {
|
|
|
526
579
|
private searchService;
|
|
527
580
|
private viewportService;
|
|
528
581
|
private navigationService;
|
|
582
|
+
private imageStore;
|
|
583
|
+
private imageProcessingService;
|
|
529
584
|
private anchorNodeId;
|
|
530
585
|
private selectedNodeId;
|
|
531
586
|
private selectedNodeIds;
|
|
@@ -541,6 +596,9 @@ declare class MindMapController {
|
|
|
541
596
|
init(containerWidth: number, containerHeight: number): void;
|
|
542
597
|
destroy(): void;
|
|
543
598
|
getData(): MindMapData;
|
|
599
|
+
getImages(): Record<string, string>;
|
|
600
|
+
getImage(ref: string): string | undefined;
|
|
601
|
+
gcImages(): void;
|
|
544
602
|
loadData(data: MindMapData): void;
|
|
545
603
|
batch(callback: () => void): void;
|
|
546
604
|
getSelectedNodeId(): string | null;
|
|
@@ -579,6 +637,7 @@ declare class MindMapController {
|
|
|
579
637
|
* Fast path: update selection styles without full DOM rebuild.
|
|
580
638
|
*/
|
|
581
639
|
private renderSelection;
|
|
640
|
+
zoomNode(nodeId: string): void;
|
|
582
641
|
setLayoutMode(mode: LayoutMode): void;
|
|
583
642
|
getLayoutMode(): LayoutMode;
|
|
584
643
|
setMaxNodeWidth(width: number): void;
|
|
@@ -637,6 +696,8 @@ export declare interface MindMapNodeData {
|
|
|
637
696
|
root?: boolean;
|
|
638
697
|
isFolded?: boolean;
|
|
639
698
|
parentId?: string;
|
|
699
|
+
thumbnail?: string;
|
|
700
|
+
imageRef?: string;
|
|
640
701
|
image?: string;
|
|
641
702
|
imageSize?: {
|
|
642
703
|
width: number;
|
|
@@ -652,7 +713,7 @@ declare class MindMapService {
|
|
|
652
713
|
private idGenerator;
|
|
653
714
|
constructor(mindMap: MindMap, idGenerator: IdGenerator);
|
|
654
715
|
addNode(parentId: string, topic?: string, layoutSide?: 'left' | 'right'): Node_2 | null;
|
|
655
|
-
addImageNode(parentId: string,
|
|
716
|
+
addImageNode(parentId: string, thumbnail: string, imageRef: string, width?: number, height?: number): Node_2 | null;
|
|
656
717
|
removeNode(id: string): boolean;
|
|
657
718
|
removeNodes(ids: string[]): boolean;
|
|
658
719
|
updateNodeTopic(id: string, topic: string): boolean;
|
|
@@ -726,6 +787,8 @@ declare class Node_2 {
|
|
|
726
787
|
style: NodeStyle;
|
|
727
788
|
parentId: string | null;
|
|
728
789
|
isRoot: boolean;
|
|
790
|
+
thumbnail?: string;
|
|
791
|
+
imageRef?: string;
|
|
729
792
|
image?: string;
|
|
730
793
|
imageSize?: {
|
|
731
794
|
width: number;
|
|
@@ -733,10 +796,11 @@ declare class Node_2 {
|
|
|
733
796
|
};
|
|
734
797
|
icon?: string;
|
|
735
798
|
presentation: NodePresentationData;
|
|
736
|
-
constructor(id: string, topic: string, parentId?: string | null, isRoot?: boolean, image?: string,
|
|
799
|
+
constructor(id: string, topic: string, parentId?: string | null, isRoot?: boolean, image?: string, // @deprecated
|
|
800
|
+
layoutSide?: 'left' | 'right', isFolded?: boolean, icon?: string, imageSize?: {
|
|
737
801
|
width: number;
|
|
738
802
|
height: number;
|
|
739
|
-
}, customWidth?: number);
|
|
803
|
+
}, customWidth?: number, thumbnail?: string, imageRef?: string);
|
|
740
804
|
addChild(node: Node_2): void;
|
|
741
805
|
insertChild(node: Node_2, index: number): void;
|
|
742
806
|
removeChild(nodeId: string): void;
|
|
@@ -780,6 +844,7 @@ declare interface Renderer {
|
|
|
780
844
|
};
|
|
781
845
|
updateSelection(selectedNodeIds: Set<string>): void;
|
|
782
846
|
getNodeElement(nodeId: string): HTMLElement | undefined;
|
|
847
|
+
zoomNode(nodeId: string): void;
|
|
783
848
|
}
|
|
784
849
|
|
|
785
850
|
declare class SearchService {
|
|
@@ -927,6 +992,12 @@ declare interface ThemeServiceDependencies {
|
|
|
927
992
|
eventBus: IMindMapEventBus;
|
|
928
993
|
}
|
|
929
994
|
|
|
995
|
+
declare interface ThumbnailResult {
|
|
996
|
+
thumbnailBase64: string;
|
|
997
|
+
width: number;
|
|
998
|
+
height: number;
|
|
999
|
+
}
|
|
1000
|
+
|
|
930
1001
|
export declare class TypedEventEmitter<EventMap extends Record<string, any>> {
|
|
931
1002
|
private listeners;
|
|
932
1003
|
on<K extends keyof EventMap>(event: K, listener: (payload: EventMap[K]) => void): void;
|