Skip to content

Commit d7b8b51

Browse files
committed
fix bubble menu, add extensions, fix default styles
1 parent 07efbb8 commit d7b8b51

File tree

9 files changed

+97
-20
lines changed

9 files changed

+97
-20
lines changed

.changeset/long-snails-hunt.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"rhino-editor": patch
3+
---
4+
5+
Bug fix: bubble menu will now anchor the `<figcaption>` or an attachment.

.changeset/nine-deers-accept.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"rhino-editor": patch
3+
---
4+
5+
Style fix: attachments without previews no longer have weird empty border lines

.changeset/nine-turtles-teach.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"rhino-editor": minor
3+
---
4+
5+
Feature: Added the `determineNodeViewAnchor` to the bubble menu extension

docs/src/rhino-editor/exports/styles/trix.css

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/exports/elements/tip-tap-editor.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,6 @@ export class TipTapEditor extends TipTapEditorBase {
256256
setTimeout(() => {
257257
if (inputElement != null) inputElement.focus();
258258
});
259-
260-
console.log("showing");
261259
}
262260

263261
get linkDialog(): Maybe<HTMLDivElement> {

src/exports/extensions/attachment.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -756,12 +756,16 @@ export const Attachment = Node.create<AttachmentOptions>({
756756
</rhino-attachment-editor>
757757
758758
${when(
759-
content && !isPreviewable,
759+
content,
760760
/* This is really not great. This is how Trix does it, but it feels very unsafe.
761761
https://github.com/basecamp/trix/blob/fda14c5ae88a0821cf8999a53dcb3572b4172cf0/src/trix/views/attachment_view.js#L36
762762
*/
763763
() => html`${unsafeHTML(content)}`,
764-
() => html`
764+
() => html``
765+
)}
766+
767+
${when(isPreviewable && !content,
768+
() => html`
765769
<img
766770
class=${loadingState === LOADING_STATES.error
767771
? "rhino-upload-error"
@@ -770,8 +774,8 @@ export const Attachment = Node.create<AttachmentOptions>({
770774
height=${String(height)}
771775
src=${ifDefined(imgSrc)}
772776
contenteditable="false"
773-
/>
774-
`,
777+
/>`,
778+
() => html``
775779
)}
776780
777781
<figcaption

src/exports/extensions/bubble-menu.ts

Lines changed: 53 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,20 @@ export interface BubbleMenuPluginProps {
5656
to: number;
5757
}) => boolean)
5858
| null;
59+
60+
/**
61+
* A function that determines what DOM Element to use as an anchor for a NodeView. Useful for things like attachments.
62+
*/
63+
determineNodeViewAnchor?:
64+
| ((props: {
65+
editor: Editor;
66+
view: EditorView;
67+
state: EditorState;
68+
oldState?: EditorState;
69+
from: number;
70+
to: number;
71+
}) => HTMLElement | null)
72+
| null;
5973
}
6074

6175
export type BubbleMenuViewProps = BubbleMenuPluginProps & {
@@ -103,13 +117,39 @@ export class BubbleMenuView {
103117
return true;
104118
};
105119

120+
public determineNodeViewAnchor: Exclude<BubbleMenuPluginProps["determineNodeViewAnchor"], null> = ({
121+
view,
122+
from,
123+
}) => {
124+
let node = view.nodeDOM(from) as HTMLElement;
125+
126+
// Attachment node views are special, we dont want to show text editing operations.
127+
// Perhaps in the future we may have a default bubble menu for attachment transforms??
128+
if (this.editor.isActive("attachment-figure") || this.editor.isActive("previewable-attachment-figure")) {
129+
const figcaption = node.querySelector("figcaption")
130+
node = figcaption || node
131+
}
132+
133+
let nodeViewWrapper = node.dataset.nodeViewWrapper
134+
? node
135+
: node.querySelector("[data-node-view-wrapper]");
136+
137+
if (nodeViewWrapper) {
138+
node = nodeViewWrapper.firstChild as HTMLElement;
139+
}
140+
141+
return node
142+
}
143+
144+
106145
constructor({
107146
editor,
108147
element,
109148
view,
110149
// tippyOptions = {},
111150
updateDelay = 250,
112151
shouldShow,
152+
determineNodeViewAnchor,
113153
}: BubbleMenuViewProps) {
114154
this.editor = editor;
115155
this.element = element;
@@ -120,6 +160,10 @@ export class BubbleMenuView {
120160
this.shouldShow = shouldShow;
121161
}
122162

163+
if (determineNodeViewAnchor) {
164+
this.determineNodeViewAnchor = determineNodeViewAnchor
165+
}
166+
123167
this.view.dom.addEventListener("dragstart", this.dragstartHandler);
124168
this.editor.on("focus", this.focusHandler);
125169
this.editor.on("blur", this.blurHandler);
@@ -223,15 +267,14 @@ export class BubbleMenuView {
223267
let clientRect: null | (() => DOMRect) = null;
224268

225269
if (isNodeSelection(state.selection)) {
226-
let node = view.nodeDOM(from) as HTMLElement;
227-
228-
const nodeViewWrapper = node.dataset.nodeViewWrapper
229-
? node
230-
: node.querySelector("[data-node-view-wrapper]");
231-
232-
if (nodeViewWrapper) {
233-
node = nodeViewWrapper.firstChild as HTMLElement;
234-
}
270+
const node = this.determineNodeViewAnchor?.({
271+
editor: this.editor,
272+
view,
273+
state,
274+
oldState,
275+
from,
276+
to,
277+
}) || view.nodeDOM(from) as HTMLElement;
235278

236279
if (node) {
237280
clientRect = () => node.getBoundingClientRect();
@@ -315,6 +358,7 @@ export const BubbleMenuExtension = Extension.create<BubbleMenuOptions>({
315358
element: this.options.element,
316359
updateDelay: this.options.updateDelay,
317360
shouldShow: this.options.shouldShow,
361+
determineNodeViewAnchor: this.options.determineNodeViewAnchor
318362
}),
319363
];
320364
},

src/exports/styles/trix-core.css

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,14 @@
6969

7070
/* Attachments */
7171
.trix-content:not([readonly])
72-
figure:is(:focus-within, :focus, .has-focus)
73-
:nth-child(2) {
72+
.attachment--preview:is(:focus-within, :focus, .has-focus)
73+
:is(img) {
74+
outline: transparent;
75+
box-shadow: var(--rhino-focus-ring);
76+
}
77+
78+
.trix-content:not([readonly])
79+
.attachment:not(.attachment--preview):is(:focus-within, :focus, .has-focus) {
7480
outline: transparent;
7581
box-shadow: var(--rhino-focus-ring);
7682
}

src/exports/styles/trix.css

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,14 @@
7070

7171
/* Attachments */
7272
.trix-content:not([readonly])
73-
figure:is(:focus-within, :focus, .has-focus)
74-
:nth-child(2) {
73+
.attachment--preview:is(:focus-within, :focus, .has-focus)
74+
:is(img) {
75+
outline: transparent;
76+
box-shadow: var(--rhino-focus-ring);
77+
}
78+
79+
.trix-content:not([readonly])
80+
.attachment:not(.attachment--preview):is(:focus-within, :focus, .has-focus) {
7581
outline: transparent;
7682
box-shadow: var(--rhino-focus-ring);
7783
}

0 commit comments

Comments
 (0)