Skip to content

Commit

Permalink
feat: support shared toolbar
Browse files Browse the repository at this point in the history
  • Loading branch information
splincode committed Aug 7, 2024
1 parent 92ffc97 commit 1b06192
Show file tree
Hide file tree
Showing 34 changed files with 723 additions and 228 deletions.
1 change: 1 addition & 0 deletions .github/workflows/announce.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jobs:
echo "name=$(node -p "require('./projects/editor/package.json').name")" >> $GITHUB_OUTPUT
- name: Announce to Telegram
if: ${{ !contains(steps.info.outputs.version, 'rc') }}
uses: taiga-family/ci/actions/messenger/telegram/announce@v1.66.3
with:
chatId: ${{ secrets.TAIGA_TELEGRAM_CHAT_ID }}
Expand Down
8 changes: 6 additions & 2 deletions projects/demo-playwright/utils/goto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,15 @@ export async function tuiGoto(
await expect(page.locator('app')).toHaveClass(/_loaded/, {timeout: 15_000});

if (hideHeader) {
await page.locator('[tuidocheader]').evaluate((el) => el.remove());
(await page.locator('[tuidocheader]').all()).forEach((e) =>
e.evaluate((el) => el.remove()),
);
}

if (hideNavigation) {
await page.locator('tui-doc-navigation').evaluate((el) => el.remove());
(await page.locator('tui-doc-navigation').all()).forEach((e) =>
e.evaluate((el) => el.remove()),
);
}

await page.waitForTimeout(1000);
Expand Down
7 changes: 7 additions & 0 deletions projects/demo/src/app/app.pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,13 @@ export const DEMO_PAGES: TuiDocRoutePages = [
'editor, toolbar, floating, wysiwyg, редактор, текст, подсветка, html, rich, text',
route: `/${TuiDemoPath.ToolbarFloating}`,
},
{
section: 'Documentation',
title: 'Shared',
keywords:
'editor, toolbar, shared, multiple, один на всех, html, rich, text',
route: `/${TuiDemoPath.ToolbarShared}`,
},
],
},
];
5 changes: 5 additions & 0 deletions projects/demo/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ export const routes: Routes = [
loadComponent: async () => import('./pages/toolbar/floating'),
title: 'Editor — Toolbar',
}),
route({
path: TuiDemoPath.ToolbarShared,
loadComponent: async () => import('./pages/toolbar/shared'),
title: 'Editor — Toolbar',
}),
{
path: '**',
redirectTo: TuiDemoPath.StarterKit,
Expand Down
47 changes: 47 additions & 0 deletions projects/demo/src/app/pages/toolbar/shared/examples/1/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<form [formGroup]="group">
<tui-toolbar
class="toolbar"
[editor]="editorRef"
[tools]="builtInTools"
/>

<tui-editor
#header
formControlName="header"
class="editor"
[tools]="[]"
(focusIn)="editorRef = header.editor"
>
Header
</tui-editor>

<tui-editor
#main
formControlName="main"
class="editor"
[tools]="[]"
(focusIn)="editorRef = main.editor"
>
Main
</tui-editor>

<tui-editor
#footer
formControlName="footer"
class="editor"
[tools]="[]"
(focusIn)="editorRef = footer.editor"
>
Footer
</tui-editor>
</form>

<tui-accordion [rounded]="false">
<tui-accordion-item [open]="true">
Output

<ng-template tuiAccordionItemContent>
<pre><code>{{group.value|json}}</code></pre>
</ng-template>
</tui-accordion-item>
</tui-accordion>
17 changes: 17 additions & 0 deletions projects/demo/src/app/pages/toolbar/shared/examples/1/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
:host {
display: flex;
flex-direction: column;
gap: 0;
}

tui-toolbar.toolbar {
position: sticky;
top: 0;
z-index: 1;
background: var(--tui-base-01);
}

tui-editor.editor {
min-height: auto;
border-radius: 0;
}
49 changes: 49 additions & 0 deletions projects/demo/src/app/pages/toolbar/shared/examples/1/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {JsonPipe} from '@angular/common';
import {
ChangeDetectionStrategy,
Component,
Injector,
ViewEncapsulation,
} from '@angular/core';
import {FormControl, FormGroup, ReactiveFormsModule} from '@angular/forms';
import type {AbstractTuiEditor} from '@taiga-ui/editor';
import {
TUI_EDITOR_DEFAULT_EXTENSIONS,
TUI_EDITOR_DEFAULT_TOOLS,
TUI_EDITOR_EXTENSIONS,
TuiEditor,
TuiToolbar,
} from '@taiga-ui/editor';
import {TuiAccordion} from '@taiga-ui/kit';

@Component({
standalone: true,
imports: [JsonPipe, ReactiveFormsModule, TuiAccordion, TuiEditor, TuiToolbar],
templateUrl: './index.html',
styleUrls: ['./index.less'],
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: TUI_EDITOR_EXTENSIONS,
deps: [Injector],
useFactory: (injector: Injector) => [
...TUI_EDITOR_DEFAULT_EXTENSIONS,
import('@taiga-ui/editor').then(({tuiCreateImageEditorExtension}) =>
tuiCreateImageEditorExtension({injector}),
),
],
},
],
})
export default class Example {
public editorRef: AbstractTuiEditor | null = null;

public readonly builtInTools = TUI_EDITOR_DEFAULT_TOOLS;

public readonly group = new FormGroup({
header: new FormControl(''),
main: new FormControl(''),
footer: new FormControl(''),
});
}
12 changes: 12 additions & 0 deletions projects/demo/src/app/pages/toolbar/shared/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<tui-doc-page
header="Editor"
type="components"
>
<tui-doc-example
id="shared-toolbar"
heading="One toolbar for many editors"
[component]="component1"
[content]="example1"
[fullsize]="true"
/>
</tui-doc-page>
24 changes: 24 additions & 0 deletions projects/demo/src/app/pages/toolbar/shared/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {ChangeDetectionStrategy, Component} from '@angular/core';
import {TuiAddonDoc} from '@taiga-ui/addon-doc';
import {TUI_EDITOR_DEFAULT_EXTENSIONS, TUI_EDITOR_EXTENSIONS} from '@taiga-ui/editor';

@Component({
standalone: true,
imports: [TuiAddonDoc],
templateUrl: './index.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: TUI_EDITOR_EXTENSIONS,
useValue: TUI_EDITOR_DEFAULT_EXTENSIONS,
},
],
})
export default class Example {
protected readonly component1 = import('./examples/1');
protected readonly example1 = {
TypeScript: import('./examples/1/index.ts?raw'),
HTML: import('./examples/1/index.html?raw'),
LESS: import('./examples/1/index.less?raw'),
};
}
1 change: 1 addition & 0 deletions projects/demo/src/app/shared/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ export const TuiDemoPath = {
UploadFiles: 'upload-files',
ToolbarBottom: 'toolbar/bottom',
ToolbarFloating: 'toolbar/floating',
ToolbarShared: 'toolbar/shared',
} as const;
12 changes: 10 additions & 2 deletions projects/editor/src/components/edit-link/edit-link.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {TuiAutoFocus, tuiIsElement} from '@taiga-ui/cdk';
import {TuiButton, TuiLink, TuiScrollbar} from '@taiga-ui/core';
import {TuiInputInline} from '@taiga-ui/kit';

import type {AbstractTuiEditor} from '../../abstract/editor-adapter.abstract';
import type {
TuiEditorLinkPrefix,
TuiEditorLinkProtocol,
Expand Down Expand Up @@ -52,7 +53,7 @@ import {tuiEditLinkParseUrl} from './utils/edit-link-parse-url';
export class TuiEditLink {
private readonly doc: Document | null = inject(WA_WINDOW)?.document ?? null;
private isOnlyAnchorMode: boolean = this.detectAnchorMode();
private readonly editor = inject(TuiTiptapEditorService);
private readonly injectionEditor = inject(TuiTiptapEditorService, {optional: true});

protected readonly options = inject(TUI_EDITOR_OPTIONS);
protected url: string = this.getHrefOrAnchorId();
Expand All @@ -61,6 +62,9 @@ export class TuiEditLink {
protected anchorIds = this.getAllAnchorsIds();
protected readonly texts$ = inject(TUI_EDITOR_LINK_TEXTS);

@Input('editor')
public inputEditor: AbstractTuiEditor | null = null;

@Output()
public readonly addLink = new EventEmitter<string>();

Expand All @@ -77,6 +81,10 @@ export class TuiEditLink {
return this.isOnlyAnchorMode;
}

protected get editor(): AbstractTuiEditor | null {
return this.injectionEditor ?? this.inputEditor;
}

protected get defaultProtocol(): TuiEditorLinkProtocol {
return this.options.linkOptions?.protocol ?? TUI_EDITOR_LINK_HTTPS_PREFIX;
}
Expand Down Expand Up @@ -232,7 +240,7 @@ export class TuiEditLink {
private getAllAnchorsIds(): string[] {
const nodes: Element[] = Array.from(
this.editor
.getOriginTiptapEditor()
?.getOriginTiptapEditor()
?.view.dom.querySelectorAll('[data-type="jump-anchor"]') ?? [],
);

Expand Down
5 changes: 1 addition & 4 deletions projects/editor/src/components/editor/editor.component.less
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
isolation: isolate;
font: var(--tui-font-text-m);
border-radius: var(--tui-radius-m);
border: 0.0625rem solid var(--tui-border-normal);
max-height: inherit;
min-height: 10rem;
box-sizing: border-box;
Expand All @@ -20,10 +21,6 @@
overflow: clip;
flex-direction: column;
border-radius: inherit;

&:not([data-focus='true']) {
outline: 0.0625rem solid var(--tui-border-normal);
}
}

.t-editor-placeholder {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import {AsyncPipe, NgIf} from '@angular/common';
import {ChangeDetectionStrategy, Component, inject} from '@angular/core';
import type {OnInit} from '@angular/core';
import {ChangeDetectionStrategy, Component, inject, Input} from '@angular/core';
import {TuiLet} from '@taiga-ui/cdk';
import {TuiButton, TuiDropdown, TuiHint} from '@taiga-ui/core';
import {combineLatest, map} from 'rxjs';
import type {Observable} from 'rxjs';
import {combineLatest, map, of} from 'rxjs';

import type {AbstractTuiEditor} from '../../../abstract/editor-adapter.abstract';
import {TuiTiptapEditorService} from '../../../directives/tiptap-editor/tiptap-editor.service';
import {TUI_EDITOR_OPTIONS} from '../../../tokens/editor-options';
import {TUI_EDITOR_TOOLBAR_TEXTS} from '../../../tokens/i18n';
Expand All @@ -16,22 +19,45 @@ import {TUI_EDITOR_TOOLBAR_TEXTS} from '../../../tokens/i18n';
styleUrls: ['../../../../styles/tools-common.less'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class TuiAlignContent {
export class TuiAlignContent implements OnInit {
private localEditor: AbstractTuiEditor | null = null;
protected readonly options = inject(TUI_EDITOR_OPTIONS);
protected readonly editor = inject(TuiTiptapEditorService);
protected readonly injectionEditor = inject(TuiTiptapEditorService, {optional: true});
protected readonly texts$ = inject(TUI_EDITOR_TOOLBAR_TEXTS);
protected alignState$: Observable<{
left: boolean;
right: boolean;
center: boolean;
justify: boolean;
}> | null = null;

protected readonly alignState$ = combineLatest([
this.editor.isActive$({textAlign: 'left'}),
this.editor.isActive$({textAlign: 'right'}),
this.editor.isActive$({textAlign: 'center'}),
this.editor.isActive$({textAlign: 'justify'}),
]).pipe(
map(([left, right, center, justify]) => ({
left,
right,
center,
justify,
})),
);
@Input('editor')
public set inputEditor(value: AbstractTuiEditor | null) {
this.localEditor = value;
this.initStream();
}

public ngOnInit(): void {
this.initStream();
}

protected get editor(): AbstractTuiEditor | null {
return this.injectionEditor ?? this.localEditor;
}

private initStream(): void {
this.alignState$ = combineLatest([
this.editor?.isActive$({textAlign: 'left'}) ?? of(false),
this.editor?.isActive$({textAlign: 'right'}) ?? of(false),
this.editor?.isActive$({textAlign: 'center'}) ?? of(false),
this.editor?.isActive$({textAlign: 'justify'}) ?? of(false),
]).pipe(
map(([left, right, center, justify]) => ({
left,
right,
center,
justify,
})),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
class="t-option t-option_margin"
[iconStart]="options.icons.textAlignLeft"
[tuiHint]="texts.justifyLeft"
(click)="editor.onAlign('left')"
(click)="editor?.onAlign('left')"
></button>
<button
appearance="icon"
Expand All @@ -36,7 +36,7 @@
class="t-option t-option_margin"
[iconStart]="options.icons.textAlignCenter"
[tuiHint]="texts.justifyCenter"
(click)="editor.onAlign('center')"
(click)="editor?.onAlign('center')"
></button>
<button
appearance="icon"
Expand All @@ -46,7 +46,7 @@
class="t-option t-option_margin"
[iconStart]="options.icons.textAlignRight"
[tuiHint]="texts.justifyRight"
(click)="editor.onAlign('right')"
(click)="editor?.onAlign('right')"
></button>
<button
appearance="icon"
Expand All @@ -56,7 +56,7 @@
class="t-option t-option_margin"
[iconStart]="options.icons.textAlignJustify"
[tuiHint]="texts.justifyFull"
(click)="editor.onAlign('justify')"
(click)="editor?.onAlign('justify')"
></button>
</div>
</ng-template>
Expand Down
Loading

0 comments on commit 1b06192

Please sign in to comment.