Skip to content

Commit 8455f9d

Browse files
committed
feat: add drag handle menu items example
1 parent 798c4f5 commit 8455f9d

File tree

12 files changed

+312
-3
lines changed

12 files changed

+312
-3
lines changed

docs/src/app/app.routes.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { AlertBlockPage } from '../pages/examples/custom/alert-block/alert-block
1111
import { ApiContentBlockPage } from '../pages/examples/custom/api-content-block/api-content-block.page';
1212
import { ExamplesPage } from '../pages/examples/examples.page';
1313
import { ConvertToHtmlPage } from '../pages/examples/interoperability/convert-to-html/convert-to-html.page';
14+
import { AddingSideMenuDragHandleItemsPage } from '../pages/examples/ui-components/adding-side-menu-drag-handle-items/adding-side-menu-drag-handle-items.page';
1415
import { FormattingSideMenuButtonsPage } from '../pages/examples/ui-components/formatting-side-menu-buttons/formatting-side-menu-buttons.page';
1516
import { FormattingToolbarButtonsPage } from '../pages/examples/ui-components/formatting-toolbar-buttons/formatting-toolbar-buttons.page';
1617
import { OverviewPage } from '../pages/overview.page';
@@ -63,6 +64,10 @@ export const appRoutes: Route[] = [
6364
path: 'ui-components/formatting-side-menu-buttons',
6465
component: FormattingSideMenuButtonsPage,
6566
},
67+
{
68+
path: 'ui-components/adding-side-menu-drag-handle-items',
69+
component: AddingSideMenuDragHandleItemsPage,
70+
},
6671
{ path: '**', redirectTo: 'overview' },
6772
],
6873
},

docs/src/pages/examples/examples.page.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,15 +120,22 @@ import { HlmButtonDirective } from '@spartan-ng/ui-button-helm';
120120
class="justify-start"
121121
routerLinkActive="active-link"
122122
routerLink="ui-components/formatting-toolbar-buttons"
123-
>Formatting Toolbar Buttons</a
123+
>Adding Formatting Toolbar Buttons</a
124124
>
125125
<a
126126
hlmBtn
127127
variant="ghost"
128128
class="justify-start"
129129
routerLinkActive="active-link"
130130
routerLink="ui-components/formatting-side-menu-buttons"
131-
>Formatting Side Menu Buttons</a
131+
>Adding Block Side Menu Buttons</a
132+
>
133+
<a
134+
hlmBtn
135+
variant="ghost"
136+
class="justify-start"
137+
routerLink="ui-components/adding-side-menu-drag-handle-items"
138+
>Adding Drag Handle Menu Items</a
132139
>
133140
</aside>
134141
<main class="overflow-hidden py-6">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { CommonModule } from '@angular/common';
2+
import { Component } from '@angular/core';
3+
import { PartialBlock } from '@blocknote/core';
4+
import {
5+
BasicTextStyleButtonComponent,
6+
BnaAddBlockButtonComponent,
7+
BnaDragHandleMenuComponent,
8+
BnaEditorComponent,
9+
BnaSideMenuComponent,
10+
BnaSideMenuControllerDirective,
11+
} from '@dytab/block-note-angular';
12+
import { HlmButtonDirective } from '@spartan-ng/ui-button-helm';
13+
import { BnaDeleteBlockItemComponent } from '../../../../../../libs/block-note-angular/src/lib/components/bna-side-menu/default-buttons/bna-delete-block-item/bna-delete-block-item.component';
14+
import { ResetBlockButtonComponent } from './reset-block-button.component';
15+
16+
@Component({
17+
selector: 'bna-basic-setup-example',
18+
standalone: true,
19+
imports: [
20+
CommonModule,
21+
BnaEditorComponent,
22+
BasicTextStyleButtonComponent,
23+
HlmButtonDirective,
24+
BnaSideMenuControllerDirective,
25+
BnaSideMenuComponent,
26+
BnaAddBlockButtonComponent,
27+
ResetBlockButtonComponent,
28+
BnaDragHandleMenuComponent,
29+
BnaDeleteBlockItemComponent,
30+
],
31+
template: `<bna-editor [initialContent]="initialContent">
32+
<bna-side-menu-controller>
33+
<bna-side-menu>
34+
<bna-add-block-btn />
35+
<bna-drag-handle-menu-btn>
36+
<bna-delete-block-item />
37+
<bna-reset-block-button />
38+
<button
39+
hlmBtn
40+
variant="ghost"
41+
size="sm"
42+
class="justify-start w-full"
43+
(click)="doSomething()"
44+
>
45+
Test
46+
</button>
47+
</bna-drag-handle-menu-btn></bna-side-menu
48+
>
49+
</bna-side-menu-controller>
50+
</bna-editor> `,
51+
})
52+
export class AddingSideMenuDragHandleItemsExample {
53+
initialContent: PartialBlock[] = [
54+
{
55+
type: 'paragraph',
56+
content: 'Welcome to this demo!',
57+
},
58+
{
59+
type: 'paragraph',
60+
content: '<- Click the Drag Handle to see the new item',
61+
},
62+
{
63+
type: 'bulletListItem',
64+
content:
65+
"Try resetting this block's type using the new Drag Handle Menu item",
66+
},
67+
{
68+
type: 'paragraph',
69+
},
70+
];
71+
72+
doSomething() {
73+
console.log('Do something');
74+
}
75+
}
76+
77+
export const addingSideMenuDragHandleItemsExampleCode = `import { CommonModule } from '@angular/common';
78+
import { Component } from '@angular/core';
79+
import { BnaEditorComponent } from '@dytab/block-note-angular';
80+
81+
@Component({
82+
standalone: true,
83+
imports: [CommonModule, BnaEditorComponent],
84+
template: \` <bna-editor [initialContent]="initialContent" /> \`,
85+
})
86+
export class BasicSetupExample {
87+
initialContent = undefined;
88+
}`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { CommonModule } from '@angular/common';
2+
import { Component } from '@angular/core';
3+
import {
4+
HlmTabsComponent,
5+
HlmTabsContentDirective,
6+
HlmTabsListComponent,
7+
HlmTabsTriggerDirective,
8+
} from '@spartan-ng/ui-tabs-helm';
9+
import { hlmP } from '@spartan-ng/ui-typography-helm';
10+
import { Highlight } from 'ngx-highlightjs';
11+
import { CodeComponent } from '../../../../shared/code/code.component';
12+
import { DemoBoxComponent } from '../../../../shared/layout/demo-box.component';
13+
import { TabsComponent } from '../../../../shared/layout/example-tabs.component';
14+
import { SectionIntroComponent } from '../../../../shared/layout/section-intro.component';
15+
import {
16+
AddingSideMenuDragHandleItemsExample,
17+
addingSideMenuDragHandleItemsExampleCode,
18+
} from './adding-side-menu-drag-handle-items.example';
19+
20+
@Component({
21+
standalone: true,
22+
imports: [
23+
CommonModule,
24+
SectionIntroComponent,
25+
DemoBoxComponent,
26+
HlmTabsComponent,
27+
HlmTabsListComponent,
28+
HlmTabsContentDirective,
29+
HlmTabsTriggerDirective,
30+
TabsComponent,
31+
CodeComponent,
32+
AddingSideMenuDragHandleItemsExample,
33+
Highlight,
34+
],
35+
template: `
36+
<bna-section-intro name="Adding Drag Handle Menu Items">
37+
<p class="${hlmP} mb-8">
38+
In this example, we add an item to the Drag Handle Menu, which resets
39+
the hovered block to a paragraph.
40+
</p>
41+
<p>
42+
<strong>Try it out</strong>:Hover a block to open the Block Side Menu,
43+
and click "Reset Type" in the Drag Handle Menu to reset the selected
44+
block!
45+
</p>
46+
</bna-section-intro>
47+
<hlm-tabs tab="preview">
48+
<bna-example-tabs firstTab="Preview" secondTab="Code">
49+
<bna-demo-box firstTab>
50+
<bna-basic-setup-example />
51+
</bna-demo-box>
52+
<bna-code [code]="exampleCode" secondTab />
53+
</bna-example-tabs>
54+
</hlm-tabs>
55+
`,
56+
})
57+
export class AddingSideMenuDragHandleItemsPage {
58+
exampleCode = addingSideMenuDragHandleItemsExampleCode;
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { ResetBlockButtonComponent } from './reset-block-button.component';
3+
4+
describe('RemoveBlockButtonComponent', () => {
5+
let component: ResetBlockButtonComponent;
6+
let fixture: ComponentFixture<ResetBlockButtonComponent>;
7+
8+
beforeEach(async () => {
9+
await TestBed.configureTestingModule({
10+
imports: [ResetBlockButtonComponent],
11+
}).compileComponents();
12+
13+
fixture = TestBed.createComponent(ResetBlockButtonComponent);
14+
component = fixture.componentInstance;
15+
fixture.detectChanges();
16+
});
17+
18+
it('should create', () => {
19+
expect(component).toBeTruthy();
20+
});
21+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { CommonModule } from '@angular/common';
2+
import { Component, effect } from '@angular/core';
3+
import { Block } from '@blocknote/core';
4+
import { BlockNoteAngularService } from '@dytab/block-note-angular';
5+
import { provideIcons } from '@ng-icons/core';
6+
import { lucideTrash } from '@ng-icons/lucide';
7+
import { HlmButtonDirective } from '@spartan-ng/ui-button-helm';
8+
import { HlmIconComponent } from '@spartan-ng/ui-icon-helm';
9+
10+
@Component({
11+
selector: 'bna-reset-block-button',
12+
standalone: true,
13+
imports: [CommonModule, HlmButtonDirective, HlmIconComponent],
14+
providers: [provideIcons({ lucideTrash })],
15+
template: ` <button
16+
hlmBtn
17+
size="sm"
18+
class="w-full justify-start"
19+
variant="ghost"
20+
(click)="resetBlock()"
21+
>
22+
Reset Block
23+
</button>`,
24+
styles: ``,
25+
})
26+
export class ResetBlockButtonComponent {
27+
block?: Block;
28+
constructor(public blockNoteAngularService: BlockNoteAngularService) {
29+
effect(() => {
30+
const editor = blockNoteAngularService.editor();
31+
if (!editor) {
32+
return;
33+
}
34+
editor.sideMenu.onUpdate((state) => {
35+
this.block = state.block;
36+
});
37+
});
38+
}
39+
40+
resetBlock() {
41+
const editor = this.blockNoteAngularService.editor();
42+
if (!editor || !this.block) {
43+
return;
44+
}
45+
this.blockNoteAngularService
46+
.editor()!
47+
.updateBlock(this.block, { type: 'paragraph' });
48+
}
49+
}

libs/block-note-angular/src/lib/components/bna-side-menu/default-buttons/bna-delete-block-item/bna-delete-block-item.component.css

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<button hlmBtn variant="ghost" size="sm" class="w-full justify-start" type="button" (click)="deleteBlock()">Delete</button>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { BnaDeleteBlockItemComponent } from './bna-delete-block-item.component';
3+
4+
describe('DeleteBlockItemComponent', () => {
5+
let component: BnaDeleteBlockItemComponent;
6+
let fixture: ComponentFixture<BnaDeleteBlockItemComponent>;
7+
8+
beforeEach(async () => {
9+
await TestBed.configureTestingModule({
10+
imports: [BnaDeleteBlockItemComponent],
11+
}).compileComponents();
12+
13+
fixture = TestBed.createComponent(BnaDeleteBlockItemComponent);
14+
component = fixture.componentInstance;
15+
fixture.detectChanges();
16+
});
17+
18+
it('should create', () => {
19+
expect(component).toBeTruthy();
20+
});
21+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { CommonModule } from '@angular/common';
2+
import { Component, effect } from '@angular/core';
3+
import { Block } from '@blocknote/core';
4+
import { BlockNoteAngularService } from '@dytab/block-note-angular';
5+
import { HlmButtonDirective } from '@spartan-ng/ui-button-helm';
6+
import { HlmMenuItemDirective } from '@spartan-ng/ui-menu-helm';
7+
8+
@Component({
9+
selector: 'bna-delete-block-item',
10+
standalone: true,
11+
imports: [CommonModule, HlmMenuItemDirective, HlmButtonDirective],
12+
templateUrl: './bna-delete-block-item.component.html',
13+
styleUrl: './bna-delete-block-item.component.css',
14+
host: {
15+
class: 'block',
16+
},
17+
})
18+
export class BnaDeleteBlockItemComponent {
19+
dragBlock?: Block<any, any, any>;
20+
21+
constructor(public blockNoteAngularService: BlockNoteAngularService) {
22+
effect(() => {
23+
const editor = blockNoteAngularService.editor();
24+
if (!editor) {
25+
return;
26+
}
27+
editor.sideMenu.onUpdate((state) => {
28+
this.dragBlock = state.block;
29+
});
30+
});
31+
}
32+
33+
deleteBlock() {
34+
const editor = this.blockNoteAngularService.editor();
35+
if (!editor) {
36+
return;
37+
}
38+
console.log('delete block');
39+
// console.log('delete block', this.selectedBlocks);
40+
// editor.removeBlocks(this.selectedBlocks);
41+
// editor.sideMenu.unfreezeMenu();
42+
}
43+
}

libs/block-note-angular/src/lib/components/bna-side-menu/default-buttons/drag-handle-menu/bna-drag-handle-menu.component.html

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,12 @@
1414
<ng-template #menu>
1515
<hlm-menu class="shadow-3xl">
1616
<hlm-menu-group>
17-
<button hlmMenuItem type="button" (click)="deleteBlock()">Delete</button>
17+
<div #dragHandleMenuItems>
18+
<ng-content></ng-content>
19+
</div>
20+
<ng-container *ngIf="!dragHandleMenuItems.hasChildNodes()">
21+
<bna-delete-block-item />
22+
</ng-container>
1823
</hlm-menu-group>
1924
</hlm-menu>
2025
</ng-template>

libs/block-note-angular/src/lib/components/bna-side-menu/default-buttons/drag-handle-menu/bna-drag-handle-menu.component.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ import {
1717
HlmSubMenuComponent,
1818
} from '@spartan-ng/ui-menu-helm';
1919
import { BlockNoteAngularService } from '../../../../services/block-note-angular.service';
20+
import { BnaFormattingToolbarControllerDirective } from '../../../bna-formatting-toolbar/bna-formatting-toolbar-controller.directive';
21+
import { BnaFormattingToolbarComponent } from '../../../bna-formatting-toolbar/bna-formatting-toolbar.component';
22+
import { BasicTextStyleButtonComponent } from '../../../buttons/basic-text-style-button/basic-text-style-button.component';
23+
import { TextAlignButtonComponent } from '../../../buttons/text-align-button/text-align-button.component';
24+
import { BnaDeleteBlockItemComponent } from '../bna-delete-block-item/bna-delete-block-item.component';
2025

2126
@Component({
2227
selector: 'bna-drag-handle-menu-btn',
@@ -34,6 +39,11 @@ import { BlockNoteAngularService } from '../../../../services/block-note-angular
3439
HlmMenuShortcutComponent,
3540
HlmMenuSeparatorComponent,
3641
HlmMenuGroupComponent,
42+
BasicTextStyleButtonComponent,
43+
BnaFormattingToolbarComponent,
44+
BnaFormattingToolbarControllerDirective,
45+
TextAlignButtonComponent,
46+
BnaDeleteBlockItemComponent,
3747
],
3848
templateUrl: './bna-drag-handle-menu.component.html',
3949
styleUrl: './bna-drag-handle-menu.component.css',

0 commit comments

Comments
 (0)