diff --git a/.changeset/late-zebras-march.md b/.changeset/late-zebras-march.md
new file mode 100644
index 00000000..09f722f0
--- /dev/null
+++ b/.changeset/late-zebras-march.md
@@ -0,0 +1,5 @@
+---
+"rhino-editor": patch
+---
+
+fix: link-dialog buttons now have proper hover / focus state.
diff --git a/.changeset/serious-avocados-act.md b/.changeset/serious-avocados-act.md
new file mode 100644
index 00000000..357681c4
--- /dev/null
+++ b/.changeset/serious-avocados-act.md
@@ -0,0 +1,5 @@
+---
+"rhino-editor": minor
+---
+
+BREAKING_CHANGE: Allow the light-dom editor to be slotted. Do note, this change may result in a small breaking change for the users relying on the original light-dom structure being `div > div.trix-content`. Most users should not see a difference.
diff --git a/docs/frontend/styles/_normalize.css b/docs/frontend/styles/_normalize.css
index 8dceecf1..49387381 100644
--- a/docs/frontend/styles/_normalize.css
+++ b/docs/frontend/styles/_normalize.css
@@ -1,7 +1,7 @@
html {
box-sizing: border-box;
height: 100%;
- font-size: 18px;
+ font-size: 16px;
/* letter-spacing: 0.025em; */
}
diff --git a/docs/frontend/styles/components/_top_nav.css b/docs/frontend/styles/components/_top_nav.css
index 10cf8494..240a41f8 100644
--- a/docs/frontend/styles/components/_top_nav.css
+++ b/docs/frontend/styles/components/_top_nav.css
@@ -20,6 +20,8 @@
.top-nav__hamburger__button {
font-size: 1.75em;
+ display: flex;
+ align-items: center;
}
.top-nav__hamburger__button::part(base),
diff --git a/docs/src/_documentation/how_tos/13-add-additional-attributes-onto-the-editor.md b/docs/src/_documentation/how_tos/13-add-additional-attributes-onto-the-editor.md
new file mode 100644
index 00000000..3dce87dd
--- /dev/null
+++ b/docs/src/_documentation/how_tos/13-add-additional-attributes-onto-the-editor.md
@@ -0,0 +1,37 @@
+---
+title: Add Additional Attributes onto the Editor
+permalink: /add-additional-attributes-onto-the-editor/
+---
+
+Sometimes you may want to add additional attributes directly onto the `contenteditable` of RhinoEditor.
+
+The easiest way to do this is by slotting in an editor with the attributes you would like. Here's an example of how we
+could add `aria-*` attributes onto the editor in cases where perhaps the form failed validation.
+
+```erb
+
+
+
+
+
+
+
+ <%% if object.errors.any? %>
+ <%%= object.errors.to_s %>
+ <%% end %>
+
+```
+
+This will produce something like the following:
+
+```html
+
+
+
+
+
+
+
+ Wow dude. You really messed up. What did you even submit?
+
+```
diff --git a/src/exports/elements/tip-tap-editor-base.ts b/src/exports/elements/tip-tap-editor-base.ts
index 6d57ac16..e7eef19c 100644
--- a/src/exports/elements/tip-tap-editor-base.ts
+++ b/src/exports/elements/tip-tap-editor-base.ts
@@ -121,33 +121,68 @@ export class TipTapEditorBase extends BaseElement {
*/
extensions: EditorOptions["extensions"] = [];
+ /**
+ * @internal
+ */
+ __initialAttributes: Record = {};
+
+ /**
+ * @internal
+ */
+ __hasRendered: boolean = false;
+
+ __getInitialAttributes() {
+ if (this.__hasRendered) return;
+
+ const slottedEditor = this.slottedEditor;
+ if (slottedEditor) {
+ this.__initialAttributes = {};
+ [...slottedEditor.attributes].forEach((attr) => {
+ const { nodeName, nodeValue } = attr;
+ if (nodeName && nodeValue != null) {
+ this.__initialAttributes[nodeName] = nodeValue;
+ }
+ });
+ }
+
+ this.__hasRendered = true;
+ }
+
/**
* Reset mechanism. This is called on first connect, and called anytime extensions,
* or editor options get modified to make sure we have a fresh instance.
*/
rebuildEditor() {
+ const editors = this.querySelectorAll("[slot='editor']");
+
+ this.__getInitialAttributes();
+
// Make sure we dont render the editor more than once.
if (this.editor) this.editor.destroy();
- const editors = this.querySelectorAll("[slot='editor']");
+
editors.forEach((el) => {
// @ts-expect-error
- el.querySelector(".tiptap")?.editor?.destroy();
+ el.editor?.destroy();
el.remove();
});
- // light-dom version.
- const div = document.createElement("div");
- div.setAttribute("slot", "editor");
+ this.editor = this.__setupEditor(this);
- // This may seem strange, but for some reason its the only wayto get the DropCursor working correctly.
- div.style.position = "relative";
- this.insertAdjacentElement("beforeend", div);
+ this.__bindEditorListeners();
- this.editor = this.__setupEditor(div);
+ this.editorElement = this.querySelector(".ProseMirror");
- this.__bindEditorListeners();
- this.editorElement = div.querySelector(".ProseMirror");
- //
+ Object.entries(this.__initialAttributes)?.forEach(
+ ([attrName, attrValue]) => {
+ if (attrName === "class") {
+ this.editorElement?.classList.add(...attrValue.split(" "));
+ return;
+ }
+ this.editorElement?.setAttribute(attrName, attrValue);
+ },
+ );
+
+ this.editorElement?.setAttribute("slot", "editor");
this.editorElement?.classList.add("trix-content");
this.editorElement?.setAttribute("tabindex", "0");
this.editorElement?.setAttribute("role", "textbox");
@@ -157,9 +192,7 @@ export class TipTapEditorBase extends BaseElement {
}
protected willUpdate(
- changedProperties:
- | PropertyValueMap
- | Map,
+ changedProperties: PropertyValueMap | Map,
): void {
if (changedProperties.has("class")) {
this.classList.add("rhino-editor");
@@ -175,6 +208,10 @@ export class TipTapEditorBase extends BaseElement {
protected updated(
changedProperties: PropertyValueMap | Map,
): void {
+ if (changedProperties.has("readonly")) {
+ this.editor?.setEditable(!this.readonly);
+ }
+
if (
changedProperties.has("extensions") ||
changedProperties.has("starterKitOptions") ||
@@ -183,10 +220,6 @@ export class TipTapEditorBase extends BaseElement {
this.rebuildEditor();
}
- if (changedProperties.has("readonly")) {
- this.editor?.setEditable(!this.readonly);
- }
-
super.updated(changedProperties);
}
@@ -614,7 +647,7 @@ export class TipTapEditorBase extends BaseElement {
this.editor.off("blur", this.__handleBlur);
}
- private __setupEditor(element: Element): Editor {
+ private __setupEditor(element: Element = this): Editor {
if (!this.serializer || this.serializer === "html") {
// This is a super hacky way to get __to_trix_html to support figcaptions without patching it.
this.normalizeDOM(this.inputElement);
diff --git a/src/exports/elements/tip-tap-editor.ts b/src/exports/elements/tip-tap-editor.ts
index ea81322b..ff9452e9 100644
--- a/src/exports/elements/tip-tap-editor.ts
+++ b/src/exports/elements/tip-tap-editor.ts
@@ -1109,14 +1109,14 @@ export class TipTapEditor extends TipTapEditorBase {
/>
`)
+ await aTimeout(0)
+
const rhinoEditor = div.querySelector("rhino-editor")
const input = div.querySelector("input")
assert.equal(rhinoEditor.serializer, "html")
- assert.equal(input.value, "")
+ assert.equal(input.value, "")
rhinoEditor.serializer = "json"