@mdzip/editor-ng 1.2.8 → 1.3.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.md +114 -0
- package/dist/README.md +114 -0
- package/dist/fesm2022/mdzip-editor-ng.mjs +199 -0
- package/dist/fesm2022/mdzip-editor-ng.mjs.map +1 -0
- package/dist/index.d.ts +62 -0
- package/dist/index.d.ts.map +1 -0
- package/package.json +18 -4
- package/ng-package.json +0 -8
- package/src/public-api.ts +0 -2
- package/src/workspace.component.css +0 -2
- package/src/workspace.component.html +0 -1
- package/src/workspace.component.ts +0 -177
- package/tsconfig.lib.json +0 -19
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# @mdzip/editor-ng
|
|
2
|
+
|
|
3
|
+
Angular component wrapper for the MDZip workspace editor.
|
|
4
|
+
|
|
5
|
+
`@mdzip/editor-ng` provides a standalone `MdzipWorkspaceComponent` that embeds the full MDZip workspace UI — document preview, editor, package navigator, and asset manager — as a native Angular component.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @mdzip/editor @mdzip/editor-ng
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Peer dependencies: `@angular/common` and `@angular/core` >=20.
|
|
14
|
+
|
|
15
|
+
## Basic Usage
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { MdzipWorkspaceComponent } from '@mdzip/editor-ng';
|
|
19
|
+
|
|
20
|
+
@Component({
|
|
21
|
+
imports: [MdzipWorkspaceComponent],
|
|
22
|
+
template: `
|
|
23
|
+
<mdzip-workspace
|
|
24
|
+
[bytes]="fileBytes"
|
|
25
|
+
fileName="document.mdz"
|
|
26
|
+
mode="read-only"
|
|
27
|
+
controls="viewer"
|
|
28
|
+
(failed)="onError($event)"
|
|
29
|
+
/>
|
|
30
|
+
`,
|
|
31
|
+
styles: [':host { display: block; height: 600px; }']
|
|
32
|
+
})
|
|
33
|
+
export class AppComponent {
|
|
34
|
+
fileBytes: Uint8Array | null = null;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The host element must have an explicit height. The component expands to fill it.
|
|
39
|
+
|
|
40
|
+
## Editor Mode
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
<mdzip-workspace
|
|
44
|
+
[bytes]="fileBytes"
|
|
45
|
+
fileName="document.mdz"
|
|
46
|
+
mode="editable"
|
|
47
|
+
controls="standalone-editor"
|
|
48
|
+
(saved)="onSaved($event)"
|
|
49
|
+
(changed)="onChanged($event)"
|
|
50
|
+
/>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Inputs
|
|
54
|
+
|
|
55
|
+
| Input | Type | Default | Description |
|
|
56
|
+
|-------|------|---------|-------------|
|
|
57
|
+
| `bytes` | `Uint8Array \| null` | `null` | Raw archive bytes to open |
|
|
58
|
+
| `workspace` | `MdzWorkspace \| null` | `null` | Pre-built workspace object |
|
|
59
|
+
| `fileName` | `string` | `'document.mdz'` | Filename used for format detection and Save dialogs |
|
|
60
|
+
| `mode` | `MdzipWorkspaceMode` | `'read-only'` | `'read-only'` or `'editable'` |
|
|
61
|
+
| `sourceFormat` | `MdzipSourceFormat` | — | Override format detection: `'mdz'` or `'markdown'` |
|
|
62
|
+
| `controls` | `MdzipControlPreset \| MdzipControlPolicy` | `'viewer'` | `'preview'`, `'viewer'`, `'standalone-editor'`, `'hosted-editor'`, or a policy object |
|
|
63
|
+
| `initialLayout` | `MdzipWorkspaceLayout` | — | Starting layout: `'preview'`, `'editor'`, `'split'` |
|
|
64
|
+
| `initialColorScheme` | `MdzipColorScheme` | — | `'light'` or `'dark'` |
|
|
65
|
+
| `navigationMode` | `MdzipNavigationMode` | `'editor'` | Package navigation mode |
|
|
66
|
+
| `navigationButtonActive` | `boolean` | `true` | Whether the navigation button is shown |
|
|
67
|
+
|
|
68
|
+
## Outputs
|
|
69
|
+
|
|
70
|
+
| Output | Payload | Description |
|
|
71
|
+
|--------|---------|-------------|
|
|
72
|
+
| `changed` | `MdzipWorkspaceChange` | Emitted when archive bytes change |
|
|
73
|
+
| `saved` | `MdzipWorkspaceSave` | Emitted on Save |
|
|
74
|
+
| `snapshotChanged` | `MdzipWorkspaceSnapshot` | Emitted on any state change |
|
|
75
|
+
| `selectionChanged` | `MdzipWorkspaceSnapshot` | Emitted when the editor selection changes |
|
|
76
|
+
| `dirtyChanged` | `MdzipWorkspaceSnapshot` | Emitted when the dirty flag changes |
|
|
77
|
+
| `validationChanged` | `MdzipWorkspaceSnapshot` | Emitted when validation state changes |
|
|
78
|
+
| `colorSchemeChanged` | `MdzipColorScheme` | Emitted when the color scheme changes |
|
|
79
|
+
| `failed` | `unknown` | Emitted on unrecoverable errors |
|
|
80
|
+
|
|
81
|
+
## Conversion hook
|
|
82
|
+
|
|
83
|
+
`onConversionRequested` is an **input function** (not an output, because it must return a
|
|
84
|
+
value): bind `[onConversionRequested]="handler"` where `handler` is
|
|
85
|
+
`(action: MdzipConversionAction) => boolean | Promise<boolean>`. It fires when the user
|
|
86
|
+
triggers the markdown→MDZ conversion flow (nav button, Insert Image, or image paste on a
|
|
87
|
+
plain `.md`). Return/resolve `true` to take over and suppress the built-in conversion dialog.
|
|
88
|
+
|
|
89
|
+
## File management (nav pane)
|
|
90
|
+
|
|
91
|
+
With `controls="standalone-editor"` or `"hosted-editor"` (or `fileActions: true` in a custom
|
|
92
|
+
policy), the navigation pane offers a right-click context menu: new `.md` file, new folder,
|
|
93
|
+
rename/move, duplicate, replace, download, copy markdown link, set entry point, set cover
|
|
94
|
+
image, and delete. Files can also be dragged between folders, and OS files can be dropped
|
|
95
|
+
onto the pane. Copy and Download remain available in read-only mode. The same operations are
|
|
96
|
+
exposed as component methods: `removeFile`, `renameFile`, `setEntryPoint`, and `setCoverImage`.
|
|
97
|
+
|
|
98
|
+
## Imperative API
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
@ViewChild(MdzipWorkspaceComponent) workspace!: MdzipWorkspaceComponent;
|
|
102
|
+
|
|
103
|
+
// Flush pending edits and persist
|
|
104
|
+
const snapshot = await this.workspace.flush();
|
|
105
|
+
if (snapshot) {
|
|
106
|
+
await save(snapshot.bytes);
|
|
107
|
+
this.workspace.markPersisted();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Execute editor commands
|
|
111
|
+
await this.workspace.executeCommand('bold');
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
See the [`@mdzip/editor`](https://www.npmjs.com/package/@mdzip/editor) package for the full API reference, theming guide, and framework-agnostic usage.
|
package/dist/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# @mdzip/editor-ng
|
|
2
|
+
|
|
3
|
+
Angular component wrapper for the MDZip workspace editor.
|
|
4
|
+
|
|
5
|
+
`@mdzip/editor-ng` provides a standalone `MdzipWorkspaceComponent` that embeds the full MDZip workspace UI — document preview, editor, package navigator, and asset manager — as a native Angular component.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install @mdzip/editor @mdzip/editor-ng
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Peer dependencies: `@angular/common` and `@angular/core` >=20.
|
|
14
|
+
|
|
15
|
+
## Basic Usage
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { MdzipWorkspaceComponent } from '@mdzip/editor-ng';
|
|
19
|
+
|
|
20
|
+
@Component({
|
|
21
|
+
imports: [MdzipWorkspaceComponent],
|
|
22
|
+
template: `
|
|
23
|
+
<mdzip-workspace
|
|
24
|
+
[bytes]="fileBytes"
|
|
25
|
+
fileName="document.mdz"
|
|
26
|
+
mode="read-only"
|
|
27
|
+
controls="viewer"
|
|
28
|
+
(failed)="onError($event)"
|
|
29
|
+
/>
|
|
30
|
+
`,
|
|
31
|
+
styles: [':host { display: block; height: 600px; }']
|
|
32
|
+
})
|
|
33
|
+
export class AppComponent {
|
|
34
|
+
fileBytes: Uint8Array | null = null;
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The host element must have an explicit height. The component expands to fill it.
|
|
39
|
+
|
|
40
|
+
## Editor Mode
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
<mdzip-workspace
|
|
44
|
+
[bytes]="fileBytes"
|
|
45
|
+
fileName="document.mdz"
|
|
46
|
+
mode="editable"
|
|
47
|
+
controls="standalone-editor"
|
|
48
|
+
(saved)="onSaved($event)"
|
|
49
|
+
(changed)="onChanged($event)"
|
|
50
|
+
/>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Inputs
|
|
54
|
+
|
|
55
|
+
| Input | Type | Default | Description |
|
|
56
|
+
|-------|------|---------|-------------|
|
|
57
|
+
| `bytes` | `Uint8Array \| null` | `null` | Raw archive bytes to open |
|
|
58
|
+
| `workspace` | `MdzWorkspace \| null` | `null` | Pre-built workspace object |
|
|
59
|
+
| `fileName` | `string` | `'document.mdz'` | Filename used for format detection and Save dialogs |
|
|
60
|
+
| `mode` | `MdzipWorkspaceMode` | `'read-only'` | `'read-only'` or `'editable'` |
|
|
61
|
+
| `sourceFormat` | `MdzipSourceFormat` | — | Override format detection: `'mdz'` or `'markdown'` |
|
|
62
|
+
| `controls` | `MdzipControlPreset \| MdzipControlPolicy` | `'viewer'` | `'preview'`, `'viewer'`, `'standalone-editor'`, `'hosted-editor'`, or a policy object |
|
|
63
|
+
| `initialLayout` | `MdzipWorkspaceLayout` | — | Starting layout: `'preview'`, `'editor'`, `'split'` |
|
|
64
|
+
| `initialColorScheme` | `MdzipColorScheme` | — | `'light'` or `'dark'` |
|
|
65
|
+
| `navigationMode` | `MdzipNavigationMode` | `'editor'` | Package navigation mode |
|
|
66
|
+
| `navigationButtonActive` | `boolean` | `true` | Whether the navigation button is shown |
|
|
67
|
+
|
|
68
|
+
## Outputs
|
|
69
|
+
|
|
70
|
+
| Output | Payload | Description |
|
|
71
|
+
|--------|---------|-------------|
|
|
72
|
+
| `changed` | `MdzipWorkspaceChange` | Emitted when archive bytes change |
|
|
73
|
+
| `saved` | `MdzipWorkspaceSave` | Emitted on Save |
|
|
74
|
+
| `snapshotChanged` | `MdzipWorkspaceSnapshot` | Emitted on any state change |
|
|
75
|
+
| `selectionChanged` | `MdzipWorkspaceSnapshot` | Emitted when the editor selection changes |
|
|
76
|
+
| `dirtyChanged` | `MdzipWorkspaceSnapshot` | Emitted when the dirty flag changes |
|
|
77
|
+
| `validationChanged` | `MdzipWorkspaceSnapshot` | Emitted when validation state changes |
|
|
78
|
+
| `colorSchemeChanged` | `MdzipColorScheme` | Emitted when the color scheme changes |
|
|
79
|
+
| `failed` | `unknown` | Emitted on unrecoverable errors |
|
|
80
|
+
|
|
81
|
+
## Conversion hook
|
|
82
|
+
|
|
83
|
+
`onConversionRequested` is an **input function** (not an output, because it must return a
|
|
84
|
+
value): bind `[onConversionRequested]="handler"` where `handler` is
|
|
85
|
+
`(action: MdzipConversionAction) => boolean | Promise<boolean>`. It fires when the user
|
|
86
|
+
triggers the markdown→MDZ conversion flow (nav button, Insert Image, or image paste on a
|
|
87
|
+
plain `.md`). Return/resolve `true` to take over and suppress the built-in conversion dialog.
|
|
88
|
+
|
|
89
|
+
## File management (nav pane)
|
|
90
|
+
|
|
91
|
+
With `controls="standalone-editor"` or `"hosted-editor"` (or `fileActions: true` in a custom
|
|
92
|
+
policy), the navigation pane offers a right-click context menu: new `.md` file, new folder,
|
|
93
|
+
rename/move, duplicate, replace, download, copy markdown link, set entry point, set cover
|
|
94
|
+
image, and delete. Files can also be dragged between folders, and OS files can be dropped
|
|
95
|
+
onto the pane. Copy and Download remain available in read-only mode. The same operations are
|
|
96
|
+
exposed as component methods: `removeFile`, `renameFile`, `setEntryPoint`, and `setCoverImage`.
|
|
97
|
+
|
|
98
|
+
## Imperative API
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
@ViewChild(MdzipWorkspaceComponent) workspace!: MdzipWorkspaceComponent;
|
|
102
|
+
|
|
103
|
+
// Flush pending edits and persist
|
|
104
|
+
const snapshot = await this.workspace.flush();
|
|
105
|
+
if (snapshot) {
|
|
106
|
+
await save(snapshot.bytes);
|
|
107
|
+
this.workspace.markPersisted();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Execute editor commands
|
|
111
|
+
await this.workspace.executeCommand('bold');
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
See the [`@mdzip/editor`](https://www.npmjs.com/package/@mdzip/editor) package for the full API reference, theming guide, and framework-agnostic usage.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { EventEmitter, ViewChild, Output, Input, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { MdzipWorkspaceView } from '@mdzip/editor';
|
|
4
|
+
|
|
5
|
+
class MdzipWorkspaceComponent {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.bytes = null;
|
|
8
|
+
this.workspace = null;
|
|
9
|
+
this.fileName = 'document.mdz';
|
|
10
|
+
this.mode = 'read-only';
|
|
11
|
+
this.controls = 'viewer';
|
|
12
|
+
this.navigationMode = 'editor';
|
|
13
|
+
this.navigationButtonActive = true;
|
|
14
|
+
this.changed = new EventEmitter();
|
|
15
|
+
this.saved = new EventEmitter();
|
|
16
|
+
this.workspaceChanged = new EventEmitter();
|
|
17
|
+
this.documentChanged = new EventEmitter();
|
|
18
|
+
this.assetChanged = new EventEmitter();
|
|
19
|
+
this.manifestChanged = new EventEmitter();
|
|
20
|
+
this.snapshotChanged = new EventEmitter();
|
|
21
|
+
this.selectionChanged = new EventEmitter();
|
|
22
|
+
this.dirtyChanged = new EventEmitter();
|
|
23
|
+
this.validationChanged = new EventEmitter();
|
|
24
|
+
this.colorSchemeChanged = new EventEmitter();
|
|
25
|
+
this.failed = new EventEmitter();
|
|
26
|
+
this.view = null;
|
|
27
|
+
}
|
|
28
|
+
ngAfterViewInit() {
|
|
29
|
+
this.createView();
|
|
30
|
+
this.syncView();
|
|
31
|
+
}
|
|
32
|
+
ngOnChanges(changes) {
|
|
33
|
+
if (this.view && (changes['controls'] || changes['initialLayout']
|
|
34
|
+
|| changes['initialColorScheme'] || changes['navigationMode']
|
|
35
|
+
|| changes['navigationButtonActive'])) {
|
|
36
|
+
this.createView();
|
|
37
|
+
this.syncView();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (this.view && (changes['bytes'] || changes['workspace'] || changes['mode']
|
|
41
|
+
|| changes['sourceFormat'] || changes['fileName'])) {
|
|
42
|
+
this.syncView();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
ngOnDestroy() {
|
|
46
|
+
this.view?.destroy();
|
|
47
|
+
}
|
|
48
|
+
canExecuteCommand(command) {
|
|
49
|
+
return this.view?.canExecuteCommand(command) ?? false;
|
|
50
|
+
}
|
|
51
|
+
executeCommand(command, file) {
|
|
52
|
+
return this.view?.executeCommand(command, file) ?? Promise.resolve(false);
|
|
53
|
+
}
|
|
54
|
+
convertToMdz() {
|
|
55
|
+
return this.view?.convertToMdz() ?? Promise.resolve(false);
|
|
56
|
+
}
|
|
57
|
+
focus() {
|
|
58
|
+
this.view?.focus();
|
|
59
|
+
}
|
|
60
|
+
flush() {
|
|
61
|
+
return this.view?.flush() ?? Promise.resolve(null);
|
|
62
|
+
}
|
|
63
|
+
serialize() {
|
|
64
|
+
return this.view?.serialize() ?? Promise.resolve(null);
|
|
65
|
+
}
|
|
66
|
+
getCurrentSnapshot() {
|
|
67
|
+
return this.view?.getCurrentSnapshot() ?? Promise.resolve(null);
|
|
68
|
+
}
|
|
69
|
+
markPersisted() {
|
|
70
|
+
this.view?.markPersisted();
|
|
71
|
+
}
|
|
72
|
+
addAsset(archivePath, fileBytes) {
|
|
73
|
+
return this.view?.addAsset(archivePath, fileBytes) ?? Promise.resolve();
|
|
74
|
+
}
|
|
75
|
+
replaceAsset(archivePath, fileBytes) {
|
|
76
|
+
return this.view?.replaceAsset(archivePath, fileBytes) ?? Promise.resolve(false);
|
|
77
|
+
}
|
|
78
|
+
removeAsset(archivePath, options) {
|
|
79
|
+
return this.view?.removeAsset(archivePath, options) ?? Promise.resolve(false);
|
|
80
|
+
}
|
|
81
|
+
removeFile(archivePath) {
|
|
82
|
+
return this.view?.removeFile(archivePath) ?? Promise.resolve(false);
|
|
83
|
+
}
|
|
84
|
+
renameFile(oldPath, newPath) {
|
|
85
|
+
return this.view?.renameFile(oldPath, newPath) ?? Promise.resolve(false);
|
|
86
|
+
}
|
|
87
|
+
setEntryPoint(archivePath) {
|
|
88
|
+
return this.view?.setEntryPoint(archivePath) ?? Promise.resolve(false);
|
|
89
|
+
}
|
|
90
|
+
setCoverImage(archivePath) {
|
|
91
|
+
return this.view?.setCoverImage(archivePath) ?? Promise.resolve(false);
|
|
92
|
+
}
|
|
93
|
+
listAssets() {
|
|
94
|
+
return this.view?.listAssets() ?? [];
|
|
95
|
+
}
|
|
96
|
+
syncView() {
|
|
97
|
+
if (this.view && this.workspace) {
|
|
98
|
+
void this.view.openWorkspace(this.workspace, {
|
|
99
|
+
mode: this.mode,
|
|
100
|
+
sourceFormat: this.sourceFormat,
|
|
101
|
+
fileName: this.fileName
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else if (this.view && this.bytes) {
|
|
105
|
+
void this.view.open(this.bytes, {
|
|
106
|
+
mode: this.mode,
|
|
107
|
+
sourceFormat: this.sourceFormat,
|
|
108
|
+
fileName: this.fileName
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
createView() {
|
|
113
|
+
this.view?.destroy();
|
|
114
|
+
this.view = new MdzipWorkspaceView(this.hostRef.nativeElement, {
|
|
115
|
+
controls: this.controls,
|
|
116
|
+
initialLayout: this.initialLayout,
|
|
117
|
+
initialColorScheme: this.initialColorScheme,
|
|
118
|
+
navigationMode: this.navigationMode,
|
|
119
|
+
navigationButtonActive: this.navigationButtonActive,
|
|
120
|
+
onChanged: (bytes, snapshot) => this.changed.emit({ bytes, snapshot }),
|
|
121
|
+
onSaved: (bytes, snapshot) => this.saved.emit({ bytes, snapshot }),
|
|
122
|
+
onWorkspaceChanged: (event) => this.workspaceChanged.emit(event),
|
|
123
|
+
onDocumentChanged: (event) => this.documentChanged.emit(event),
|
|
124
|
+
onAssetChanged: (event) => this.assetChanged.emit(event),
|
|
125
|
+
onManifestChanged: (event) => this.manifestChanged.emit(event),
|
|
126
|
+
onSnapshotChanged: (snapshot) => this.snapshotChanged.emit(snapshot),
|
|
127
|
+
onSelectionChanged: (snapshot) => this.selectionChanged.emit(snapshot),
|
|
128
|
+
onDirtyChanged: (snapshot) => this.dirtyChanged.emit(snapshot),
|
|
129
|
+
onValidationChanged: (snapshot) => this.validationChanged.emit(snapshot),
|
|
130
|
+
onColorSchemeChanged: (colorScheme) => this.colorSchemeChanged.emit(colorScheme),
|
|
131
|
+
onFailed: (e) => this.failed.emit(e),
|
|
132
|
+
onConversionRequested: this.onConversionRequested
|
|
133
|
+
? (action) => this.onConversionRequested(action)
|
|
134
|
+
: undefined,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MdzipWorkspaceComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
138
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.24", type: MdzipWorkspaceComponent, isStandalone: true, selector: "mdzip-workspace", inputs: { bytes: "bytes", workspace: "workspace", fileName: "fileName", mode: "mode", sourceFormat: "sourceFormat", controls: "controls", initialLayout: "initialLayout", initialColorScheme: "initialColorScheme", navigationMode: "navigationMode", navigationButtonActive: "navigationButtonActive", onConversionRequested: "onConversionRequested" }, outputs: { changed: "changed", saved: "saved", workspaceChanged: "workspaceChanged", documentChanged: "documentChanged", assetChanged: "assetChanged", manifestChanged: "manifestChanged", snapshotChanged: "snapshotChanged", selectionChanged: "selectionChanged", dirtyChanged: "dirtyChanged", validationChanged: "validationChanged", colorSchemeChanged: "colorSchemeChanged", failed: "failed" }, viewQueries: [{ propertyName: "hostRef", first: true, predicate: ["host"], descendants: true }], usesOnChanges: true, ngImport: i0, template: '<div #host></div>', isInline: true, styles: [":host{display:block;height:100%}div{height:100%}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
139
|
+
}
|
|
140
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.24", ngImport: i0, type: MdzipWorkspaceComponent, decorators: [{
|
|
141
|
+
type: Component,
|
|
142
|
+
args: [{ selector: 'mdzip-workspace', standalone: true, template: '<div #host></div>', changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:block;height:100%}div{height:100%}\n"] }]
|
|
143
|
+
}], propDecorators: { bytes: [{
|
|
144
|
+
type: Input
|
|
145
|
+
}], workspace: [{
|
|
146
|
+
type: Input
|
|
147
|
+
}], fileName: [{
|
|
148
|
+
type: Input
|
|
149
|
+
}], mode: [{
|
|
150
|
+
type: Input
|
|
151
|
+
}], sourceFormat: [{
|
|
152
|
+
type: Input
|
|
153
|
+
}], controls: [{
|
|
154
|
+
type: Input
|
|
155
|
+
}], initialLayout: [{
|
|
156
|
+
type: Input
|
|
157
|
+
}], initialColorScheme: [{
|
|
158
|
+
type: Input
|
|
159
|
+
}], navigationMode: [{
|
|
160
|
+
type: Input
|
|
161
|
+
}], navigationButtonActive: [{
|
|
162
|
+
type: Input
|
|
163
|
+
}], onConversionRequested: [{
|
|
164
|
+
type: Input
|
|
165
|
+
}], changed: [{
|
|
166
|
+
type: Output
|
|
167
|
+
}], saved: [{
|
|
168
|
+
type: Output
|
|
169
|
+
}], workspaceChanged: [{
|
|
170
|
+
type: Output
|
|
171
|
+
}], documentChanged: [{
|
|
172
|
+
type: Output
|
|
173
|
+
}], assetChanged: [{
|
|
174
|
+
type: Output
|
|
175
|
+
}], manifestChanged: [{
|
|
176
|
+
type: Output
|
|
177
|
+
}], snapshotChanged: [{
|
|
178
|
+
type: Output
|
|
179
|
+
}], selectionChanged: [{
|
|
180
|
+
type: Output
|
|
181
|
+
}], dirtyChanged: [{
|
|
182
|
+
type: Output
|
|
183
|
+
}], validationChanged: [{
|
|
184
|
+
type: Output
|
|
185
|
+
}], colorSchemeChanged: [{
|
|
186
|
+
type: Output
|
|
187
|
+
}], failed: [{
|
|
188
|
+
type: Output
|
|
189
|
+
}], hostRef: [{
|
|
190
|
+
type: ViewChild,
|
|
191
|
+
args: ['host']
|
|
192
|
+
}] } });
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Generated bundle index. Do not edit.
|
|
196
|
+
*/
|
|
197
|
+
|
|
198
|
+
export { MdzipWorkspaceComponent };
|
|
199
|
+
//# sourceMappingURL=mdzip-editor-ng.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mdzip-editor-ng.mjs","sources":["../../src/workspace.component.ts","../../src/mdzip-editor-ng.ts"],"sourcesContent":["import {\n AfterViewInit,\n ChangeDetectionStrategy,\n Component,\n ElementRef,\n EventEmitter,\n Input,\n OnChanges,\n OnDestroy,\n Output,\n SimpleChanges,\n ViewChild,\n} from '@angular/core';\nimport { MdzipWorkspaceView } from '@mdzip/editor';\nimport type {\n MdzipControlPolicy,\n MdzipControlPreset,\n MdzipColorScheme,\n MdzipConversionAction,\n MdzipEditorCommand,\n MdzipDocumentChangeEvent,\n MdzipEditorSnapshot,\n MdzipNavigationMode,\n MdzipRemoveAssetOptions,\n MdzipSourceFormat,\n MdzWorkspace,\n MdzWorkspaceAsset,\n MdzipWorkspaceChange,\n MdzipWorkspaceLayout,\n MdzipWorkspaceMode,\n MdzipWorkspaceSave,\n MdzipWorkspaceSnapshot,\n} from '@mdzip/editor';\n\n@Component({\n selector: 'mdzip-workspace',\n standalone: true,\n template: '<div #host></div>',\n styles: [':host { display: block; height: 100%; } div { height: 100%; }'],\n changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class MdzipWorkspaceComponent implements AfterViewInit, OnChanges, OnDestroy {\n @Input() bytes: Uint8Array | null = null;\n @Input() workspace: MdzWorkspace | null = null;\n @Input() fileName = 'document.mdz';\n @Input() mode: MdzipWorkspaceMode = 'read-only';\n @Input() sourceFormat?: MdzipSourceFormat;\n @Input() controls: MdzipControlPreset | MdzipControlPolicy = 'viewer';\n @Input() initialLayout?: MdzipWorkspaceLayout;\n @Input() initialColorScheme?: MdzipColorScheme;\n @Input() navigationMode: MdzipNavigationMode = 'editor';\n @Input() navigationButtonActive = true;\n /**\n * Host hook for the markdown→MDZ conversion flow. An input function (not an\n * output) because it must return/resolve `true` to suppress the built-in\n * conversion dialog.\n */\n @Input() onConversionRequested?: (action: MdzipConversionAction) => boolean | Promise<boolean>;\n @Output() readonly changed = new EventEmitter<MdzipWorkspaceChange>();\n @Output() readonly saved = new EventEmitter<MdzipWorkspaceSave>();\n @Output() readonly workspaceChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly documentChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly assetChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly manifestChanged = new EventEmitter<MdzipDocumentChangeEvent>();\n @Output() readonly snapshotChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly selectionChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly dirtyChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly validationChanged = new EventEmitter<MdzipWorkspaceSnapshot>();\n @Output() readonly colorSchemeChanged = new EventEmitter<MdzipColorScheme>();\n @Output() readonly failed = new EventEmitter<unknown>();\n\n @ViewChild('host') private readonly hostRef!: ElementRef<HTMLDivElement>;\n private view: MdzipWorkspaceView | null = null;\n\n ngAfterViewInit(): void {\n this.createView();\n this.syncView();\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (this.view && (changes['controls'] || changes['initialLayout']\n || changes['initialColorScheme'] || changes['navigationMode']\n || changes['navigationButtonActive'])) {\n this.createView();\n this.syncView();\n return;\n }\n if (this.view && (changes['bytes'] || changes['workspace'] || changes['mode']\n || changes['sourceFormat'] || changes['fileName'])) {\n this.syncView();\n }\n }\n\n ngOnDestroy(): void {\n this.view?.destroy();\n }\n\n canExecuteCommand(command: MdzipEditorCommand): boolean {\n return this.view?.canExecuteCommand(command) ?? false;\n }\n\n executeCommand(command: MdzipEditorCommand, file?: File): Promise<boolean> {\n return this.view?.executeCommand(command, file) ?? Promise.resolve(false);\n }\n\n convertToMdz(): Promise<boolean> {\n return this.view?.convertToMdz() ?? Promise.resolve(false);\n }\n\n focus(): void {\n this.view?.focus();\n }\n\n flush(): Promise<MdzipEditorSnapshot | null> {\n return this.view?.flush() ?? Promise.resolve(null);\n }\n\n serialize(): Promise<Blob | null> {\n return this.view?.serialize() ?? Promise.resolve(null);\n }\n\n getCurrentSnapshot(): Promise<MdzipEditorSnapshot | null> {\n return this.view?.getCurrentSnapshot() ?? Promise.resolve(null);\n }\n\n markPersisted(): void {\n this.view?.markPersisted();\n }\n\n addAsset(archivePath: string, fileBytes: Uint8Array): Promise<void> {\n return this.view?.addAsset(archivePath, fileBytes) ?? Promise.resolve();\n }\n\n replaceAsset(archivePath: string, fileBytes: Uint8Array): Promise<boolean> {\n return this.view?.replaceAsset(archivePath, fileBytes) ?? Promise.resolve(false);\n }\n\n removeAsset(archivePath: string, options?: MdzipRemoveAssetOptions): Promise<boolean> {\n return this.view?.removeAsset(archivePath, options) ?? Promise.resolve(false);\n }\n\n removeFile(archivePath: string): Promise<boolean> {\n return this.view?.removeFile(archivePath) ?? Promise.resolve(false);\n }\n\n renameFile(oldPath: string, newPath: string): Promise<boolean> {\n return this.view?.renameFile(oldPath, newPath) ?? Promise.resolve(false);\n }\n\n setEntryPoint(archivePath: string): Promise<boolean> {\n return this.view?.setEntryPoint(archivePath) ?? Promise.resolve(false);\n }\n\n setCoverImage(archivePath: string | null): Promise<boolean> {\n return this.view?.setCoverImage(archivePath) ?? Promise.resolve(false);\n }\n\n listAssets(): MdzWorkspaceAsset[] {\n return this.view?.listAssets() ?? [];\n }\n\n private syncView(): void {\n if (this.view && this.workspace) {\n void this.view.openWorkspace(this.workspace, {\n mode: this.mode,\n sourceFormat: this.sourceFormat,\n fileName: this.fileName\n });\n } else if (this.view && this.bytes) {\n void this.view.open(this.bytes, {\n mode: this.mode,\n sourceFormat: this.sourceFormat,\n fileName: this.fileName\n });\n }\n }\n\n private createView(): void {\n this.view?.destroy();\n this.view = new MdzipWorkspaceView(this.hostRef.nativeElement, {\n controls: this.controls,\n initialLayout: this.initialLayout,\n initialColorScheme: this.initialColorScheme,\n navigationMode: this.navigationMode,\n navigationButtonActive: this.navigationButtonActive,\n onChanged: (bytes, snapshot) => this.changed.emit({ bytes, snapshot }),\n onSaved: (bytes, snapshot) => this.saved.emit({ bytes, snapshot }),\n onWorkspaceChanged: (event) => this.workspaceChanged.emit(event),\n onDocumentChanged: (event) => this.documentChanged.emit(event),\n onAssetChanged: (event) => this.assetChanged.emit(event),\n onManifestChanged: (event) => this.manifestChanged.emit(event),\n onSnapshotChanged: (snapshot) => this.snapshotChanged.emit(snapshot),\n onSelectionChanged: (snapshot: MdzipWorkspaceSnapshot) => this.selectionChanged.emit(snapshot),\n onDirtyChanged: (snapshot: MdzipWorkspaceSnapshot) => this.dirtyChanged.emit(snapshot),\n onValidationChanged: (snapshot: MdzipWorkspaceSnapshot) => this.validationChanged.emit(snapshot),\n onColorSchemeChanged: (colorScheme: MdzipColorScheme) => this.colorSchemeChanged.emit(colorScheme),\n onFailed: (e: unknown) => this.failed.emit(e),\n onConversionRequested: this.onConversionRequested\n ? (action) => this.onConversionRequested!(action)\n : undefined,\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { AfterViewInit, OnChanges, OnDestroy, EventEmitter, SimpleChanges } from '@angular/core';
|
|
3
|
+
import { MdzWorkspace, MdzipWorkspaceMode, MdzipSourceFormat, MdzipControlPreset, MdzipControlPolicy, MdzipWorkspaceLayout, MdzipColorScheme, MdzipNavigationMode, MdzipConversionAction, MdzipWorkspaceChange, MdzipWorkspaceSave, MdzipDocumentChangeEvent, MdzipWorkspaceSnapshot, MdzipEditorCommand, MdzipEditorSnapshot, MdzipRemoveAssetOptions, MdzWorkspaceAsset } from '@mdzip/editor';
|
|
4
|
+
|
|
5
|
+
declare class MdzipWorkspaceComponent implements AfterViewInit, OnChanges, OnDestroy {
|
|
6
|
+
bytes: Uint8Array | null;
|
|
7
|
+
workspace: MdzWorkspace | null;
|
|
8
|
+
fileName: string;
|
|
9
|
+
mode: MdzipWorkspaceMode;
|
|
10
|
+
sourceFormat?: MdzipSourceFormat;
|
|
11
|
+
controls: MdzipControlPreset | MdzipControlPolicy;
|
|
12
|
+
initialLayout?: MdzipWorkspaceLayout;
|
|
13
|
+
initialColorScheme?: MdzipColorScheme;
|
|
14
|
+
navigationMode: MdzipNavigationMode;
|
|
15
|
+
navigationButtonActive: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Host hook for the markdown→MDZ conversion flow. An input function (not an
|
|
18
|
+
* output) because it must return/resolve `true` to suppress the built-in
|
|
19
|
+
* conversion dialog.
|
|
20
|
+
*/
|
|
21
|
+
onConversionRequested?: (action: MdzipConversionAction) => boolean | Promise<boolean>;
|
|
22
|
+
readonly changed: EventEmitter<MdzipWorkspaceChange>;
|
|
23
|
+
readonly saved: EventEmitter<MdzipWorkspaceSave>;
|
|
24
|
+
readonly workspaceChanged: EventEmitter<MdzipDocumentChangeEvent>;
|
|
25
|
+
readonly documentChanged: EventEmitter<MdzipDocumentChangeEvent>;
|
|
26
|
+
readonly assetChanged: EventEmitter<MdzipDocumentChangeEvent>;
|
|
27
|
+
readonly manifestChanged: EventEmitter<MdzipDocumentChangeEvent>;
|
|
28
|
+
readonly snapshotChanged: EventEmitter<MdzipWorkspaceSnapshot>;
|
|
29
|
+
readonly selectionChanged: EventEmitter<MdzipWorkspaceSnapshot>;
|
|
30
|
+
readonly dirtyChanged: EventEmitter<MdzipWorkspaceSnapshot>;
|
|
31
|
+
readonly validationChanged: EventEmitter<MdzipWorkspaceSnapshot>;
|
|
32
|
+
readonly colorSchemeChanged: EventEmitter<MdzipColorScheme>;
|
|
33
|
+
readonly failed: EventEmitter<unknown>;
|
|
34
|
+
private readonly hostRef;
|
|
35
|
+
private view;
|
|
36
|
+
ngAfterViewInit(): void;
|
|
37
|
+
ngOnChanges(changes: SimpleChanges): void;
|
|
38
|
+
ngOnDestroy(): void;
|
|
39
|
+
canExecuteCommand(command: MdzipEditorCommand): boolean;
|
|
40
|
+
executeCommand(command: MdzipEditorCommand, file?: File): Promise<boolean>;
|
|
41
|
+
convertToMdz(): Promise<boolean>;
|
|
42
|
+
focus(): void;
|
|
43
|
+
flush(): Promise<MdzipEditorSnapshot | null>;
|
|
44
|
+
serialize(): Promise<Blob | null>;
|
|
45
|
+
getCurrentSnapshot(): Promise<MdzipEditorSnapshot | null>;
|
|
46
|
+
markPersisted(): void;
|
|
47
|
+
addAsset(archivePath: string, fileBytes: Uint8Array): Promise<void>;
|
|
48
|
+
replaceAsset(archivePath: string, fileBytes: Uint8Array): Promise<boolean>;
|
|
49
|
+
removeAsset(archivePath: string, options?: MdzipRemoveAssetOptions): Promise<boolean>;
|
|
50
|
+
removeFile(archivePath: string): Promise<boolean>;
|
|
51
|
+
renameFile(oldPath: string, newPath: string): Promise<boolean>;
|
|
52
|
+
setEntryPoint(archivePath: string): Promise<boolean>;
|
|
53
|
+
setCoverImage(archivePath: string | null): Promise<boolean>;
|
|
54
|
+
listAssets(): MdzWorkspaceAsset[];
|
|
55
|
+
private syncView;
|
|
56
|
+
private createView;
|
|
57
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<MdzipWorkspaceComponent, never>;
|
|
58
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<MdzipWorkspaceComponent, "mdzip-workspace", never, { "bytes": { "alias": "bytes"; "required": false; }; "workspace": { "alias": "workspace"; "required": false; }; "fileName": { "alias": "fileName"; "required": false; }; "mode": { "alias": "mode"; "required": false; }; "sourceFormat": { "alias": "sourceFormat"; "required": false; }; "controls": { "alias": "controls"; "required": false; }; "initialLayout": { "alias": "initialLayout"; "required": false; }; "initialColorScheme": { "alias": "initialColorScheme"; "required": false; }; "navigationMode": { "alias": "navigationMode"; "required": false; }; "navigationButtonActive": { "alias": "navigationButtonActive"; "required": false; }; "onConversionRequested": { "alias": "onConversionRequested"; "required": false; }; }, { "changed": "changed"; "saved": "saved"; "workspaceChanged": "workspaceChanged"; "documentChanged": "documentChanged"; "assetChanged": "assetChanged"; "manifestChanged": "manifestChanged"; "snapshotChanged": "snapshotChanged"; "selectionChanged": "selectionChanged"; "dirtyChanged": "dirtyChanged"; "validationChanged": "validationChanged"; "colorSchemeChanged": "colorSchemeChanged"; "failed": "failed"; }, never, never, true, never>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export { MdzipWorkspaceComponent };
|
|
62
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sources":["../src/workspace.component.ts"],"mappings":";;;;AAkCA,cAAA,mCAOqC,aAAW,EAAA,SAAe,EAAA,SAAW;AAC/D,WAAO,UAAU;AACjB,eAAW,YAAY;AACvB;UACM,kBAAkB;mBACT,iBAAiB;AAChC,cAAU,kBAAkB,GAAG,kBAAkB;oBACjC,oBAAoB;yBACf,gBAAgB;oBACrB,mBAAmB;AACnC;AACT;;;;AAIG;AACM,qCAAiC,qBAAqB,eAAe,OAAO;sBAC3D,YAAA,CAAA,oBAAA;oBACF,YAAA,CAAA,kBAAA;+BACW,YAAA,CAAA,wBAAA;8BACD,YAAA,CAAA,wBAAA;2BACH,YAAA,CAAA,wBAAA;8BACG,YAAA,CAAA,wBAAA;8BACA,YAAA,CAAA,sBAAA;+BACC,YAAA,CAAA,sBAAA;2BACJ,YAAA,CAAA,sBAAA;gCACK,YAAA,CAAA,sBAAA;iCACC,YAAA,CAAA,gBAAA;qBACZ,YAAA;AAEN;;AAGnB;AAKA,yBAAqB,aAAa;AAclC;AAIA,+BAA2B,kBAAkB;AAI7C,4BAAwB,kBAAkB,SAAS,IAAI,GAAG,OAAO;AAIjE,oBAAgB,OAAO;AAIvB;AAIA,aAAS,OAAO,CAAC,mBAAmB;AAIpC,iBAAa,OAAO,CAAC,IAAI;AAIzB,0BAAsB,OAAO,CAAC,mBAAmB;AAIjD;AAIA,6CAAyC,UAAU,GAAG,OAAO;AAI7D,iDAA6C,UAAU,GAAG,OAAO;AAIjE,+CAA2C,uBAAuB,GAAG,OAAO;qCAI3C,OAAO;AAIxC,kDAA8C,OAAO;wCAIjB,OAAO;+CAIA,OAAO;kBAIpC,iBAAiB;AAI/B;AAgBA;yCAxIW,uBAAuB;2CAAvB,uBAAuB;AAiKnC;;;;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,21 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mdzip/editor-ng",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Angular UI components for the MDZip workspace engine.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"module": "dist/fesm2022/mdzip-editor-ng.mjs",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
"./package.json": {
|
|
11
|
+
"default": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/fesm2022/mdzip-editor-ng.mjs"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"sideEffects": false,
|
|
7
19
|
"peerDependencies": {
|
|
8
20
|
"@angular/common": ">=20.0.0",
|
|
9
21
|
"@angular/core": ">=20.0.0",
|
|
10
|
-
"@mdzip/editor": "^1.
|
|
22
|
+
"@mdzip/editor": "^1.3.0"
|
|
11
23
|
},
|
|
12
24
|
"dependencies": {
|
|
13
25
|
"tslib": "^2.8.1"
|
|
14
26
|
},
|
|
15
27
|
"scripts": {
|
|
16
|
-
"build": "ng build @mdzip/editor-ng"
|
|
17
|
-
"publish": "npm publish ../../dist/packages/editor-ng"
|
|
28
|
+
"build": "ng build @mdzip/editor-ng"
|
|
18
29
|
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
19
33
|
"publishConfig": {
|
|
20
34
|
"access": "public"
|
|
21
35
|
}
|
package/ng-package.json
DELETED
package/src/public-api.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<div #host></div>
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AfterViewInit,
|
|
3
|
-
ChangeDetectionStrategy,
|
|
4
|
-
Component,
|
|
5
|
-
ElementRef,
|
|
6
|
-
EventEmitter,
|
|
7
|
-
Input,
|
|
8
|
-
OnChanges,
|
|
9
|
-
OnDestroy,
|
|
10
|
-
Output,
|
|
11
|
-
SimpleChanges,
|
|
12
|
-
ViewChild,
|
|
13
|
-
} from '@angular/core';
|
|
14
|
-
import { MdzipWorkspaceView } from '@mdzip/editor';
|
|
15
|
-
import type {
|
|
16
|
-
MdzipControlPolicy,
|
|
17
|
-
MdzipControlPreset,
|
|
18
|
-
MdzipColorScheme,
|
|
19
|
-
MdzipEditorCommand,
|
|
20
|
-
MdzipDocumentChangeEvent,
|
|
21
|
-
MdzipEditorSnapshot,
|
|
22
|
-
MdzipNavigationMode,
|
|
23
|
-
MdzipRemoveAssetOptions,
|
|
24
|
-
MdzipSourceFormat,
|
|
25
|
-
MdzWorkspace,
|
|
26
|
-
MdzWorkspaceAsset,
|
|
27
|
-
MdzipWorkspaceChange,
|
|
28
|
-
MdzipWorkspaceLayout,
|
|
29
|
-
MdzipWorkspaceMode,
|
|
30
|
-
MdzipWorkspaceSave,
|
|
31
|
-
MdzipWorkspaceSnapshot,
|
|
32
|
-
} from '@mdzip/editor';
|
|
33
|
-
|
|
34
|
-
@Component({
|
|
35
|
-
selector: 'mdzip-workspace',
|
|
36
|
-
standalone: true,
|
|
37
|
-
template: '<div #host></div>',
|
|
38
|
-
styles: [':host { display: block; height: 100%; } div { height: 100%; }'],
|
|
39
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
40
|
-
})
|
|
41
|
-
export class MdzipWorkspaceComponent implements AfterViewInit, OnChanges, OnDestroy {
|
|
42
|
-
@Input() bytes: Uint8Array | null = null;
|
|
43
|
-
@Input() workspace: MdzWorkspace | null = null;
|
|
44
|
-
@Input() fileName = 'document.mdz';
|
|
45
|
-
@Input() mode: MdzipWorkspaceMode = 'read-only';
|
|
46
|
-
@Input() sourceFormat?: MdzipSourceFormat;
|
|
47
|
-
@Input() controls: MdzipControlPreset | MdzipControlPolicy = 'viewer';
|
|
48
|
-
@Input() initialLayout?: MdzipWorkspaceLayout;
|
|
49
|
-
@Input() initialColorScheme?: MdzipColorScheme;
|
|
50
|
-
@Input() navigationMode: MdzipNavigationMode = 'editor';
|
|
51
|
-
@Input() navigationButtonActive = true;
|
|
52
|
-
@Output() readonly changed = new EventEmitter<MdzipWorkspaceChange>();
|
|
53
|
-
@Output() readonly saved = new EventEmitter<MdzipWorkspaceSave>();
|
|
54
|
-
@Output() readonly workspaceChanged = new EventEmitter<MdzipDocumentChangeEvent>();
|
|
55
|
-
@Output() readonly documentChanged = new EventEmitter<MdzipDocumentChangeEvent>();
|
|
56
|
-
@Output() readonly assetChanged = new EventEmitter<MdzipDocumentChangeEvent>();
|
|
57
|
-
@Output() readonly manifestChanged = new EventEmitter<MdzipDocumentChangeEvent>();
|
|
58
|
-
@Output() readonly snapshotChanged = new EventEmitter<MdzipWorkspaceSnapshot>();
|
|
59
|
-
@Output() readonly selectionChanged = new EventEmitter<MdzipWorkspaceSnapshot>();
|
|
60
|
-
@Output() readonly dirtyChanged = new EventEmitter<MdzipWorkspaceSnapshot>();
|
|
61
|
-
@Output() readonly validationChanged = new EventEmitter<MdzipWorkspaceSnapshot>();
|
|
62
|
-
@Output() readonly colorSchemeChanged = new EventEmitter<MdzipColorScheme>();
|
|
63
|
-
@Output() readonly failed = new EventEmitter<unknown>();
|
|
64
|
-
|
|
65
|
-
@ViewChild('host') private readonly hostRef!: ElementRef<HTMLDivElement>;
|
|
66
|
-
private view: MdzipWorkspaceView | null = null;
|
|
67
|
-
|
|
68
|
-
ngAfterViewInit(): void {
|
|
69
|
-
this.createView();
|
|
70
|
-
this.syncView();
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
ngOnChanges(changes: SimpleChanges): void {
|
|
74
|
-
if (this.view && (changes['controls'] || changes['initialLayout']
|
|
75
|
-
|| changes['initialColorScheme'] || changes['navigationMode']
|
|
76
|
-
|| changes['navigationButtonActive'])) {
|
|
77
|
-
this.createView();
|
|
78
|
-
this.syncView();
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
if (this.view && (changes['bytes'] || changes['workspace'] || changes['mode']
|
|
82
|
-
|| changes['sourceFormat'] || changes['fileName'])) {
|
|
83
|
-
this.syncView();
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
ngOnDestroy(): void {
|
|
88
|
-
this.view?.destroy();
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
canExecuteCommand(command: MdzipEditorCommand): boolean {
|
|
92
|
-
return this.view?.canExecuteCommand(command) ?? false;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
executeCommand(command: MdzipEditorCommand, file?: File): Promise<boolean> {
|
|
96
|
-
return this.view?.executeCommand(command, file) ?? Promise.resolve(false);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
convertToMdz(): Promise<boolean> {
|
|
100
|
-
return this.view?.convertToMdz() ?? Promise.resolve(false);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
focus(): void {
|
|
104
|
-
this.view?.focus();
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
flush(): Promise<MdzipEditorSnapshot | null> {
|
|
108
|
-
return this.view?.flush() ?? Promise.resolve(null);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
serialize(): Promise<Blob | null> {
|
|
112
|
-
return this.view?.serialize() ?? Promise.resolve(null);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
getCurrentSnapshot(): Promise<MdzipEditorSnapshot | null> {
|
|
116
|
-
return this.view?.getCurrentSnapshot() ?? Promise.resolve(null);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
markPersisted(): void {
|
|
120
|
-
this.view?.markPersisted();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
addAsset(archivePath: string, fileBytes: Uint8Array): Promise<void> {
|
|
124
|
-
return this.view?.addAsset(archivePath, fileBytes) ?? Promise.resolve();
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
replaceAsset(archivePath: string, fileBytes: Uint8Array): Promise<boolean> {
|
|
128
|
-
return this.view?.replaceAsset(archivePath, fileBytes) ?? Promise.resolve(false);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
removeAsset(archivePath: string, options?: MdzipRemoveAssetOptions): Promise<boolean> {
|
|
132
|
-
return this.view?.removeAsset(archivePath, options) ?? Promise.resolve(false);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
listAssets(): MdzWorkspaceAsset[] {
|
|
136
|
-
return this.view?.listAssets() ?? [];
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private syncView(): void {
|
|
140
|
-
if (this.view && this.workspace) {
|
|
141
|
-
void this.view.openWorkspace(this.workspace, {
|
|
142
|
-
mode: this.mode,
|
|
143
|
-
sourceFormat: this.sourceFormat,
|
|
144
|
-
fileName: this.fileName
|
|
145
|
-
});
|
|
146
|
-
} else if (this.view && this.bytes) {
|
|
147
|
-
void this.view.open(this.bytes, {
|
|
148
|
-
mode: this.mode,
|
|
149
|
-
sourceFormat: this.sourceFormat,
|
|
150
|
-
fileName: this.fileName
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
private createView(): void {
|
|
156
|
-
this.view?.destroy();
|
|
157
|
-
this.view = new MdzipWorkspaceView(this.hostRef.nativeElement, {
|
|
158
|
-
controls: this.controls,
|
|
159
|
-
initialLayout: this.initialLayout,
|
|
160
|
-
initialColorScheme: this.initialColorScheme,
|
|
161
|
-
navigationMode: this.navigationMode,
|
|
162
|
-
navigationButtonActive: this.navigationButtonActive,
|
|
163
|
-
onChanged: (bytes, snapshot) => this.changed.emit({ bytes, snapshot }),
|
|
164
|
-
onSaved: (bytes, snapshot) => this.saved.emit({ bytes, snapshot }),
|
|
165
|
-
onWorkspaceChanged: (event) => this.workspaceChanged.emit(event),
|
|
166
|
-
onDocumentChanged: (event) => this.documentChanged.emit(event),
|
|
167
|
-
onAssetChanged: (event) => this.assetChanged.emit(event),
|
|
168
|
-
onManifestChanged: (event) => this.manifestChanged.emit(event),
|
|
169
|
-
onSnapshotChanged: (snapshot) => this.snapshotChanged.emit(snapshot),
|
|
170
|
-
onSelectionChanged: (snapshot: MdzipWorkspaceSnapshot) => this.selectionChanged.emit(snapshot),
|
|
171
|
-
onDirtyChanged: (snapshot: MdzipWorkspaceSnapshot) => this.dirtyChanged.emit(snapshot),
|
|
172
|
-
onValidationChanged: (snapshot: MdzipWorkspaceSnapshot) => this.validationChanged.emit(snapshot),
|
|
173
|
-
onColorSchemeChanged: (colorScheme: MdzipColorScheme) => this.colorSchemeChanged.emit(colorScheme),
|
|
174
|
-
onFailed: (e: unknown) => this.failed.emit(e),
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
}
|
package/tsconfig.lib.json
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "../../out-tsc/lib",
|
|
5
|
-
"declaration": true,
|
|
6
|
-
"declarationMap": true,
|
|
7
|
-
"inlineSources": true,
|
|
8
|
-
"paths": {
|
|
9
|
-
"@mdzip/editor": ["../editor/dist/index.d.ts"]
|
|
10
|
-
},
|
|
11
|
-
"types": []
|
|
12
|
-
},
|
|
13
|
-
"angularCompilerOptions": {
|
|
14
|
-
"strictTemplates": true,
|
|
15
|
-
"compilationMode": "partial"
|
|
16
|
-
},
|
|
17
|
-
"exclude": ["**/*.spec.ts"],
|
|
18
|
-
"include": ["src/**/*.ts"]
|
|
19
|
-
}
|