Skip to content

Commit 4c6f086

Browse files
fix: adjust slash menu
1 parent c2d7933 commit 4c6f086

2 files changed

Lines changed: 71 additions & 19 deletions

File tree

src/app/app.html

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -124,23 +124,6 @@
124124
class="block inspector-block"
125125
></qti-attributes-panel>
126126

127-
@if (savedFiles.length) {
128-
<section class="panel-card">
129-
<h2>Saved files</h2>
130-
<div class="saved-files">
131-
@for (file of savedFiles; track trackFile($index, file)) {
132-
<div class="saved-file-row">
133-
<button type="button" class="saved-file-link" (click)="loadFile(file.id)">
134-
{{ file.name }}
135-
</button>
136-
<button type="button" class="saved-file-delete" (click)="deleteFile(file.id)">
137-
Delete
138-
</button>
139-
</div>
140-
}
141-
</div>
142-
</section>
143-
}
144127
</aside>
145128
</section>
146129
</main>

src/components/editor/ui/slash-menu/slash-menu.js

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ if (!customElements.get('prosekit-autocomplete-item')) customElements.define('pr
99
if (!customElements.get('prosekit-autocomplete-empty')) customElements.define('prosekit-autocomplete-empty', AutocompleteEmpty)
1010

1111
import { html, LitElement } from 'lit';
12-
import { canUseRegexLookbehind } from 'prosekit/core'
12+
import { canUseRegexLookbehind, defineUpdateHandler } from 'prosekit/core'
13+
import { Selection } from 'prosekit/pm/state'
1314
import { insertChoiceInteraction } from '@qti-editor/interaction-choice';
1415
import { insertExtendedTextInteraction } from '@qti-editor/interaction-extended-text';
1516
import { insertInlineChoiceInteraction } from '@qti-editor/interaction-inline-choice';
@@ -35,24 +36,90 @@ function canInsert(view, nodeType) {
3536
return false;
3637
}
3738

39+
function isSelectionInsideNodeType(view, nodeType) {
40+
const { $from } = view.state.selection;
41+
42+
for (let depth = $from.depth; depth >= 0; depth -= 1) {
43+
if ($from.node(depth).type === nodeType) {
44+
return true;
45+
}
46+
}
47+
48+
return false;
49+
}
50+
3851
class SlashMenuElement extends LitElement {
3952
static properties = {
4053
editor: {
4154
attribute: false
4255
},
4356
};
4457

58+
removeUpdateExtension;
59+
lastSelectionJson = null;
60+
4561
createRenderRoot() {
4662
return this
4763
}
4864

65+
connectedCallback() {
66+
super.connectedCallback()
67+
this.attachEditorListener()
68+
}
69+
70+
disconnectedCallback() {
71+
this.detachEditorListener()
72+
super.disconnectedCallback()
73+
}
74+
75+
updated(changedProperties) {
76+
super.updated(changedProperties)
77+
if (changedProperties.has('editor')) {
78+
this.attachEditorListener()
79+
}
80+
}
81+
4982
getView() {
5083
return this.editor?.view ?? null
5184
}
5285

86+
attachEditorListener() {
87+
this.detachEditorListener()
88+
if (!this.editor) return
89+
this.removeUpdateExtension = this.editor.use(defineUpdateHandler(() => {
90+
this.snapshotSelection()
91+
this.requestUpdate()
92+
}))
93+
this.snapshotSelection()
94+
}
95+
96+
detachEditorListener() {
97+
this.removeUpdateExtension?.()
98+
this.removeUpdateExtension = undefined
99+
}
100+
101+
snapshotSelection() {
102+
const view = this.getView()
103+
if (!view) return
104+
this.lastSelectionJson = view.state.selection.toJSON()
105+
}
106+
107+
restoreSelection() {
108+
const view = this.getView()
109+
if (!view || !this.lastSelectionJson) return
110+
111+
try {
112+
const restored = Selection.fromJSON(view.state.doc, this.lastSelectionJson)
113+
view.dispatch(view.state.tr.setSelection(restored))
114+
} catch {
115+
return
116+
}
117+
}
118+
53119
runCommand = (command) => {
54120
const view = this.getView()
55121
if (!view) return
122+
this.restoreSelection()
56123
command(view)
57124
view.focus()
58125
};
@@ -61,6 +128,8 @@ class SlashMenuElement extends LitElement {
61128
const view = this.getView()
62129
if (!view) return
63130

131+
this.restoreSelection()
132+
64133
const nodeType = view.state.schema.nodes.qtiTextEntryInteraction
65134
if (!nodeType) return
66135

@@ -107,7 +176,7 @@ class SlashMenuElement extends LitElement {
107176
<lit-editor-slash-menu-item
108177
class="contents"
109178
label="Inline choice"
110-
?disabled=${!canInsert(view, schema.nodes.qtiInlineChoiceInteraction)}
179+
?disabled=${isSelectionInsideNodeType(view, schema.nodes.qtiInlineChoiceInteraction) || !canInsert(view, schema.nodes.qtiInlineChoiceInteraction)}
111180
@select=${() => this.runCommand((currentView) => insertInlineChoiceInteraction(currentView.state, currentView.dispatch, currentView))}
112181
></lit-editor-slash-menu-item>
113182
`

0 commit comments

Comments
 (0)