Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/calm-jokes-shout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'slate-angular': patch
---

support custom elements to set the position of children elements
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { ChangeDetectionStrategy, Component, HostListener } from '@angular/core';
import { ButtonElement } from '../../../../custom-types';
import { BaseElementComponent } from 'slate-angular';
import { SlateChildren } from '../../../../packages/src/components/children/children.component';
import { SlateChildrenOutlet } from '../../../../packages/src/components/children/children-outlet.component';

@Component({
selector: 'span[demo-element-button]',
template: `
<span contenteditable="false" style="font-size: 0;">{{ inlineChromiumBugfix }}</span>
<slate-children [children]="children" [context]="childrenContext" [viewContext]="viewContext"></slate-children>
<slate-children-outlet></slate-children-outlet>
<span contenteditable="false" style="font-size: 0;">{{ inlineChromiumBugfix }}</span>
`,
host: {
class: 'demo-element-button'
},
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [SlateChildren]
imports: [SlateChildrenOutlet]
})
export class DemoElementEditableButtonComponent extends BaseElementComponent<ButtonElement> {
// Put this at the start and end of an inline component to work around this Chromium bug:
Expand Down
6 changes: 3 additions & 3 deletions demo/app/components/link/link.component.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { ChangeDetectionStrategy, Component, HostBinding, HostListener } from '@angular/core';
import { LinkElement } from 'custom-types';
import { BaseElementComponent } from 'slate-angular';
import { SlateChildren } from '../../../../packages/src/components/children/children.component';
import { SlateChildrenOutlet } from '../../../../packages/src/components/children/children-outlet.component';

@Component({
selector: 'a[demo-element-link]',
template: `
<span contenteditable="false" style="font-size: 0;">{{ inlineChromiumBugfix }}</span>
<slate-children [children]="children" [context]="childrenContext" [viewContext]="viewContext"></slate-children>
<slate-children-outlet></slate-children-outlet>
<span contenteditable="false" style="font-size: 0;">{{ inlineChromiumBugfix }}</span>
`,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [SlateChildren]
imports:[SlateChildrenOutlet]
})
export class DemoElementLinkComponent extends BaseElementComponent<LinkElement> {
// Put this at the start and end of an inline component to work around this Chromium bug:
Expand Down
14 changes: 14 additions & 0 deletions packages/src/components/children/children-outlet.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ChangeDetectionStrategy, Component, ElementRef } from '@angular/core';

@Component({
selector: 'slate-children-outlet',
template: ``,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true
})
export class SlateChildrenOutlet {
constructor(private elementRef: ElementRef<HTMLElement>) {}
getNativeElement() {
return this.elementRef.nativeElement;
}
}
3 changes: 1 addition & 2 deletions packages/src/components/children/children.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ import { NgFor } from '@angular/common';
selector: 'slate-children',
template: ``,
changeDetection: ChangeDetectionStrategy.OnPush,
standalone: true,
imports: [NgFor]
standalone: true
})
export class SlateChildren extends ViewContainer<any> {
@Input() children: Descendant[];
Expand Down
2 changes: 1 addition & 1 deletion packages/src/components/editable/editable.component.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<slate-string-template #templateComponent></slate-string-template>
<slate-string-template #templateComponent></slate-string-template>
7 changes: 3 additions & 4 deletions packages/src/components/editable/editable.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export class SlateEditable implements OnInit, OnChanges, OnDestroy, AfterViewChe

viewContainerRef = inject(ViewContainerRef);

getOutletElement = () => {
getOutletParent = () => {
return this.elementRef.nativeElement;
};

Expand All @@ -211,8 +211,7 @@ export class SlateEditable implements OnInit, OnChanges, OnDestroy, AfterViewChe
public defaultVoidText: ComponentType<BaseTextComponent>,
@Inject(SLATE_DEFAULT_LEAF_COMPONENT_TOKEN)
public defaultLeaf: ComponentType<BaseLeafComponent>
) {
}
) {}

ngOnInit() {
this.editor.injector = this.injector;
Expand Down Expand Up @@ -240,7 +239,7 @@ export class SlateEditable implements OnInit, OnChanges, OnDestroy, AfterViewChe
// add browser class
let browserClass = IS_FIREFOX ? 'firefox' : IS_SAFARI ? 'safari' : '';
browserClass && this.elementRef.nativeElement.classList.add(browserClass);
this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletElement);
this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletParent, () => null);
}

ngOnChanges(simpleChanges: SimpleChanges) {
Expand Down
5 changes: 4 additions & 1 deletion packages/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { SlateDefaultElement } from './components/element/default-element.compon
import { SlateString } from './components/string/string.component';
import { SlateStringTemplate } from './components/string/template.component';
import { SlateChildren } from './components/children/children.component';
import { SlateChildrenOutlet } from './components/children/children-outlet.component';
import { SlateBlockCard } from './components/block-card/block-card.component';
import { SlateDefaultLeaf } from './components/leaf/default-leaf.component';
import { SlateLeaves } from './components/leaves/leaves.component';
Expand All @@ -28,11 +29,13 @@ import { SlateDefaultString } from './components/string/default-string.component
SlateBlockCard,
SlateLeaves,
SlateDefaultLeaf,
SlateDefaultString
SlateDefaultString,
SlateChildrenOutlet
],
exports: [
SlateEditable,
SlateChildren,
SlateChildrenOutlet,
SlateElement,
SlateLeaves,
SlateString,
Expand Down
2 changes: 1 addition & 1 deletion packages/src/testing/create-document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export function createDefaultDocument() {
];
}

export function createMutipleParagraph() {
export function createMultipleParagraph() {
return [
{
type: 'paragraph',
Expand Down
68 changes: 68 additions & 0 deletions packages/src/testing/editable-with-outlet.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Component, ViewChild } from '@angular/core';
import { createEditor, Element } from 'slate';
import { SlateEditable } from '../components/editable/editable.component';
import { withAngular } from '../plugins/with-angular';
import { SlateChildrenOutlet } from '../components/children/children-outlet.component';
import { BaseElementComponent } from '../view/base';

const customType = 'custom-with-outlet';

@Component({
selector: 'editable-with-outlet',
template: `<slate-editable
[editor]="editor"
[(ngModel)]="value"
(ngModelChange)="ngModelChange()"
[renderElement]="renderElement()"
></slate-editable> `
})
export class EditableWithOutletComponent {
editor = withAngular(createEditor());

value: Element[] = createDefaultDocument() as Element[];

@ViewChild(SlateEditable, { static: true })
editableComponent: SlateEditable;

renderElement() {
return (element: Element) => {
if ((element.type as any) === customType) {
return TestElementWithOutletComponent;
}
return null;
};
}

ngModelChange() {}

constructor() {}
}

export function createDefaultDocument() {
return [
{
type: customType,
children: [
{
type: 'paragraph',
children: [{ text: 'This is editable text!' }]
}
]
}
];
}

@Component({
selector: 'div[test-element-with-outlet]',
template: `
<div>before</div>
<slate-children-outlet></slate-children-outlet>
<div>after</div>
`,
host: {
class: 'test-element-with-outlet'
},
standalone: true,
imports: [SlateChildrenOutlet]
})
export class TestElementWithOutletComponent extends BaseElementComponent<any> {}
1 change: 1 addition & 0 deletions packages/src/testing/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ export * from './module';
export * from './basic-editable.component';
export * from './advanced-editable.component';
export * from './image-editable.component';
export * from './editable-with-outlet.component';
export * from './leaf.component';
42 changes: 37 additions & 5 deletions packages/src/view/base.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
import { ChangeDetectorRef, Directive, ElementRef, HostBinding, Input, OnDestroy, OnInit, ViewContainerRef, inject } from '@angular/core';
import {
ChangeDetectorRef,
Directive,
ElementRef,
HostBinding,
Input,
OnDestroy,
OnInit,
ViewChild,
ViewContainerRef,
inject
} from '@angular/core';
import { AngularEditor } from '../plugins/angular-editor';
import { ELEMENT_TO_COMPONENT, ELEMENT_TO_NODE, NODE_TO_ELEMENT } from '../utils/weak-maps';
import { SlateViewContext, SlateElementContext, SlateTextContext, SlateLeafContext } from './context';
Expand All @@ -7,6 +18,7 @@ import { SlateChildrenContext } from './context';
import { hasAfterContextChange, hasBeforeContextChange } from './context-change';
import { ListRender } from './render/list-render';
import { LeavesRender } from './render/leaves-render';
import { SlateChildrenOutlet } from 'slate-angular/components/children/children-outlet.component';

/**
* base class for template
Expand Down Expand Up @@ -140,6 +152,9 @@ export class BaseElementComponent<T extends Element = Element, K extends Angular

childrenContext: SlateChildrenContext;

@ViewChild(SlateChildrenOutlet, { static: true })
childrenOutletInstance?: SlateChildrenOutlet;

get element(): T {
return this._context && this._context.element;
}
Expand Down Expand Up @@ -168,18 +183,25 @@ export class BaseElementComponent<T extends Element = Element, K extends Angular
return this._context && this._context.readonly;
}

getOutletElement = () => {
getOutletParent = () => {
return this.elementRef.nativeElement;
};

getOutletElement = () => {
if (this.childrenOutletInstance) {
return this.childrenOutletInstance.getNativeElement();
}
return null;
};

listRender: ListRender;

ngOnInit() {
for (const key in this._context.attributes) {
this.nativeElement.setAttribute(key, this._context.attributes[key]);
}
this.initialized = true;
this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletElement);
this.listRender = new ListRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
this.listRender.initialize(this.children, this.element, this.childrenContext);
}

Expand Down Expand Up @@ -231,13 +253,23 @@ export class BaseTextComponent<T extends Text = Text> extends BaseComponent<Slat

leavesRender: LeavesRender;

getOutletElement = () => {
@ViewChild(SlateChildrenOutlet, { static: true })
childrenOutletInstance?: SlateChildrenOutlet;

getOutletParent = () => {
return this.elementRef.nativeElement;
};

getOutletElement = () => {
if (this.childrenOutletInstance) {
return this.childrenOutletInstance.getNativeElement();
}
return null;
};

ngOnInit() {
this.initialized = true;
this.leavesRender = new LeavesRender(this.viewContext, this.viewContainerRef, this.getOutletElement);
this.leavesRender = new LeavesRender(this.viewContext, this.viewContainerRef, this.getOutletParent, this.getOutletElement);
this.leavesRender.initialize(this.context);
}

Expand Down
65 changes: 0 additions & 65 deletions packages/src/view/container.spec.ts

This file was deleted.

Loading