lexxy 0.1.3.beta → 0.1.4.beta
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +48 -20
- data/app/assets/javascript/lexxy.js +96 -17
- data/app/assets/javascript/lexxy.js.br +0 -0
- data/app/assets/javascript/lexxy.js.gz +0 -0
- data/app/assets/javascript/lexxy.min.js +3 -3
- data/app/assets/javascript/lexxy.min.js.br +0 -0
- data/app/assets/javascript/lexxy.min.js.gz +0 -0
- data/app/assets/stylesheets/lexxy-content.css +1 -1
- data/app/assets/stylesheets/lexxy-editor.css +33 -6
- data/lib/lexxy/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a63dfb829afd1242b6a38e4c9f6511ef717ee81b2a4950b11d486531fdd5b7d0
|
4
|
+
data.tar.gz: 78e54bc5f3ce08662c381d8e9dd32995828125da453ba35234b602a368dd65b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69fb8247e66a3242f475c12a66bc3529132d0e41707e173db743fba3d6bc23b98031b8543c3eee44c240113049810f91d445599c6d628a9001236cde863b857b
|
7
|
+
data.tar.gz: 07cb12a656a71c6a1e944e59789314eeb9855ccf3583f5f86c29d0c51e77cd520c345aad5712385d9a04315fe13179487bf312bf6aca98aaa837f14b7b44eb12
|
data/README.md
CHANGED
@@ -23,7 +23,7 @@ A modern rich text editor for Rails.
|
|
23
23
|
Add this line to your application's Gemfile:
|
24
24
|
|
25
25
|
```ruby
|
26
|
-
gem 'lexxy'
|
26
|
+
gem 'lexxy', '~> 0.1.3.beta' # Need to specify the version since it's a pre-release
|
27
27
|
```
|
28
28
|
|
29
29
|
And then execute:
|
@@ -32,18 +32,41 @@ And then execute:
|
|
32
32
|
bundle install
|
33
33
|
```
|
34
34
|
|
35
|
-
|
35
|
+
### Import maps
|
36
|
+
|
37
|
+
If you are using [propshaft](https://github.com/rails/propshaft) and [import maps](https://github.com/rails/importmap-rails):
|
36
38
|
|
37
39
|
```ruby
|
38
40
|
# importmap.rb
|
39
41
|
pin "lexxy", to: "lexxy.js"
|
42
|
+
pin "@rails/activestorage", to: "activestorage.esm.js" # to support attachments
|
43
|
+
```
|
44
|
+
|
45
|
+
Then import it in your JavaScript entry point:
|
46
|
+
|
47
|
+
```javascript
|
48
|
+
// app/javascript/application.js
|
49
|
+
import "@37signals/lexxy"
|
50
|
+
```
|
51
|
+
|
52
|
+
### JavaScript Bundling (jsbundling-rails, Vite, etc.)
|
53
|
+
|
54
|
+
If you're using [jsbundling-rails](https://github.com/rails/jsbundling-rails) with esbuild, webpack, or any other JavaScript bundler, you'll need to install the NPM package:
|
55
|
+
|
56
|
+
```bash
|
57
|
+
yarn add @37signals/lexxy
|
58
|
+
yarn add @rails/activestorage # to support attachments
|
40
59
|
```
|
41
60
|
|
61
|
+
Then import it in your JavaScript entry point:
|
62
|
+
|
42
63
|
```javascript
|
43
|
-
// application.js
|
44
|
-
import "lexxy"
|
64
|
+
// app/javascript/application.js
|
65
|
+
import "@37signals/lexxy"
|
45
66
|
```
|
46
67
|
|
68
|
+
### CSS Setup
|
69
|
+
|
47
70
|
For the CSS, you can include it with the standard Rails helper:
|
48
71
|
|
49
72
|
```erb
|
@@ -83,9 +106,9 @@ Under the hood, this will insert a `<lexxy-editor>` tag, that will be a first-cl
|
|
83
106
|
|
84
107
|
The `<lexxy-editor>` element supports these options:
|
85
108
|
|
86
|
-
- `placeholder
|
87
|
-
- `toolbar
|
88
|
-
- `attachments
|
109
|
+
- `placeholder`: Text displayed when the editor is empty.
|
110
|
+
- `toolbar`: Pass `"false"` to disable the toolbar entirely, or pass an element ID to render the toolbar in an external element. By default, the toolbar is bootstrapped and displayed above the editor.
|
111
|
+
- `attachments`: Pass `"false"` to disable attachments completely. By default, attachments are supported, including paste and Drag & Drop support.
|
89
112
|
|
90
113
|
Lexxy uses the `ElementInternals` API to participate in HTML forms as any standard control. This means that you can use standard HTML attributes like `name`, `value`, `required`, `disabled`, etc.
|
91
114
|
|
@@ -103,7 +126,7 @@ Lexxy also lets you configure how to load the items: inline or remotely, and how
|
|
103
126
|
The first thing to do is to add a `<lexxy-prompt>` element to the editor:
|
104
127
|
|
105
128
|
```erb
|
106
|
-
<%=
|
129
|
+
<%= form.rich_text_area :body do %>
|
107
130
|
<lexxy-prompt trigger="@">
|
108
131
|
</lexxy-prompt>
|
109
132
|
<% end %>
|
@@ -238,30 +261,31 @@ By default, the `SPACE` key will select the current item in the prompt. If you w
|
|
238
261
|
|
239
262
|
#### `<lexxy-prompt>`
|
240
263
|
|
241
|
-
- `trigger
|
242
|
-
- `src
|
243
|
-
- `name
|
244
|
-
- `empty-results
|
245
|
-
- `remote-filtering
|
246
|
-
- `insert-editable-text
|
247
|
-
- `supports-space-in-searches
|
264
|
+
- `trigger`: The character that activates the prompt (e.g., "@", "#", "/").
|
265
|
+
- `src`: Path or URL to load items remotely.
|
266
|
+
- `name`: Identifier for the prompt type (determines attachment content type, e.g., `name= "mention"` creates `application/vnd.actiontext.mention`). Mandatory unless using `insert-editable-text`.
|
267
|
+
- `empty-results`: Message shown when no matches found. By default it is "Nothing found".
|
268
|
+
- `remote-filtering`: Enable server-side filtering instead of loading all options at once.
|
269
|
+
- `insert-editable-text`: Insert prompt item HTML directly as editable text instead of Action Text attachments.
|
270
|
+
- `supports-space-in-searches`: Allow spaces in search queries (useful with remote filtering for full name searches).
|
248
271
|
|
249
272
|
#### `<lexxy-prompt-item>`
|
250
273
|
|
251
|
-
- `search
|
252
|
-
- `sgid
|
274
|
+
- `search`: The text to match against when filtering (can include multiple fields for better search).
|
275
|
+
- `sgid`: The signed GlobalID for Action Text attachments (use `attachable_sgid` helper). Mandatory unless using `insert-editable-text`.
|
253
276
|
|
254
277
|
## Roadmap
|
255
278
|
|
256
279
|
This is an early beta. Here's what's coming next:
|
257
280
|
|
258
|
-
- Configurable editors in Action Text
|
281
|
+
- Configurable editors in Action Text: Choose your editor like you choose your database.
|
259
282
|
- More editing features:
|
260
283
|
- Tables
|
261
284
|
- Text highlighting
|
262
|
-
- Image galleries
|
285
|
+
- Image galleries: The only remaining feature for full Action Text compatibility
|
263
286
|
- Install task that generates the necessary JS and adds stylesheets.
|
264
|
-
-
|
287
|
+
- Configuration hooks.
|
288
|
+
- Standalone JS package: to use in non-Rails environments.
|
265
289
|
|
266
290
|
## Development
|
267
291
|
|
@@ -279,6 +303,10 @@ bin/rails server
|
|
279
303
|
|
280
304
|
The sandbox app is available at http://localhost:3000. There is also a CRUD example at http://localhost:3000/posts.
|
281
305
|
|
306
|
+
## Events
|
307
|
+
|
308
|
+
* `lexxy:change`: Fired whenever the editor content changes.
|
309
|
+
|
282
310
|
## Contributing
|
283
311
|
|
284
312
|
- Bug reports and pull requests are welcome on [GitHub Issues](https://github.com/basecamp/lexxy/issues). Help is especially welcome with [those tagged as "Help Wanted"](https://github.com/basecamp/lexxy/issues?q=is%3Aissue%20state%3Aopen%20label%3A%22help%20wanted%22).
|
@@ -3746,6 +3746,21 @@ function getListType(node) {
|
|
3746
3746
|
}
|
3747
3747
|
|
3748
3748
|
class LexicalToolbarElement extends HTMLElement {
|
3749
|
+
constructor() {
|
3750
|
+
super();
|
3751
|
+
this.internals = this.attachInternals();
|
3752
|
+
this.internals.role = "toolbar";
|
3753
|
+
}
|
3754
|
+
|
3755
|
+
connectedCallback() {
|
3756
|
+
this.#refreshToolbarOverflow();
|
3757
|
+
window.addEventListener("resize", this.#refreshToolbarOverflow);
|
3758
|
+
}
|
3759
|
+
|
3760
|
+
disconnectedCallback() {
|
3761
|
+
window.removeEventListener("resize", this.#refreshToolbarOverflow);
|
3762
|
+
}
|
3763
|
+
|
3749
3764
|
setEditor(editorElement) {
|
3750
3765
|
this.editorElement = editorElement;
|
3751
3766
|
this.editor = editorElement.editor;
|
@@ -3810,13 +3825,12 @@ class LexicalToolbarElement extends HTMLElement {
|
|
3810
3825
|
event.shiftKey ? 'shift' : null,
|
3811
3826
|
].filter(Boolean);
|
3812
3827
|
|
3813
|
-
return [...modifiers, pressedKey].join('+')
|
3828
|
+
return [ ...modifiers, pressedKey ].join('+')
|
3814
3829
|
}
|
3815
3830
|
|
3816
3831
|
#assignButtonTabindex() {
|
3817
3832
|
const baseTabIndex = parseInt(this.editorElement.editorContentElement.getAttribute("tabindex") ?? "0");
|
3818
|
-
|
3819
|
-
buttons.forEach((button, index) => {
|
3833
|
+
this.#buttons.forEach((button, index) => {
|
3820
3834
|
button.setAttribute("tabindex", `${baseTabIndex + index + 1}`);
|
3821
3835
|
});
|
3822
3836
|
}
|
@@ -3895,16 +3909,60 @@ class LexicalToolbarElement extends HTMLElement {
|
|
3895
3909
|
}
|
3896
3910
|
}
|
3897
3911
|
|
3912
|
+
#toolbarIsOverflowing() {
|
3913
|
+
return this.scrollWidth > this.clientWidth
|
3914
|
+
}
|
3915
|
+
|
3916
|
+
#refreshToolbarOverflow = () => {
|
3917
|
+
this.#resetToolbar();
|
3918
|
+
this.#compactMenu();
|
3919
|
+
|
3920
|
+
this.#overflow.style.display = this.#overflowMenu.children.length ? "block" : "none";
|
3921
|
+
}
|
3922
|
+
|
3923
|
+
get #overflow() {
|
3924
|
+
return this.querySelector(".lexxy-editor__toolbar-overflow")
|
3925
|
+
}
|
3926
|
+
|
3927
|
+
get #overflowMenu() {
|
3928
|
+
return this.querySelector(".lexxy-editor__toolbar-overflow-menu")
|
3929
|
+
}
|
3930
|
+
|
3931
|
+
#resetToolbar() {
|
3932
|
+
while (this.#overflowMenu.children.length > 0) {
|
3933
|
+
this.insertBefore(this.#overflowMenu.children[0], this.#overflow);
|
3934
|
+
}
|
3935
|
+
}
|
3936
|
+
|
3937
|
+
#compactMenu() {
|
3938
|
+
const buttons = this.#buttons.reverse();
|
3939
|
+
let movedToOverflow = false;
|
3940
|
+
|
3941
|
+
for (const button of buttons) {
|
3942
|
+
if (this.#toolbarIsOverflowing()) {
|
3943
|
+
this.#overflowMenu.appendChild(button);
|
3944
|
+
movedToOverflow = true;
|
3945
|
+
} else {
|
3946
|
+
if (movedToOverflow) this.#overflowMenu.appendChild(button);
|
3947
|
+
break
|
3948
|
+
}
|
3949
|
+
}
|
3950
|
+
}
|
3951
|
+
|
3952
|
+
get #buttons() {
|
3953
|
+
return Array.from(this.querySelectorAll(":scope > button"))
|
3954
|
+
}
|
3955
|
+
|
3898
3956
|
static get defaultTemplate() {
|
3899
3957
|
return `
|
3900
3958
|
<button type="button" name="bold" data-command="bold" title="Bold">
|
3901
3959
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"> <path d="m4.1 23c-.5 0-.7-.4-.7-.7v-20.6c0-.4.4-.7.7-.7h8.9c2 0 3.8.6 4.9 1.5 1.2 1 1.8 2.4 1.8 4.1s-.9 3.2-2.3 4.1c-.2 0-.3.3-.3.5s0 .4.3.5c1.9.8 3.2 2.7 3.2 5s-.7 3.6-2.1 4.7-3.3 1.7-5.6 1.7h-8.8zm4.2-18.1v5.1h3c1.2 0 2-.3 2.7-.7.6-.5.9-1.1.9-1.9s-.3-1.4-.8-1.8-1.3-.6-2.3-.6-2.4 0-3.5 0zm0 8.5v5.8h3.7c1.3 0 2.2-.3 2.8-.7s.9-1.2.9-2.2-.4-1.7-1-2.1-1.7-.7-2.9-.7-2.4 0-3.5 0z" fill-rule="evenodd"/> </svg>
|
3902
3960
|
</button>
|
3903
|
-
|
3961
|
+
|
3904
3962
|
<button type="button" name="italic" data-command="italic" title="Italic">
|
3905
3963
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m18.3 1.7c-1.7.4-2.5 1.3-2.7 2.6l-2.4 15.6c-.2 1.1.5 2.1 1.6 2.4.2 0 .2.2.2.3v.7h-.1c0 .1-.2.3-.3.3h-9c-.2 0-.3-.1-.3-.3v-.7h.1c0-.1.1-.2.2-.2 1.7-.4 2.5-1.3 2.7-2.6l2.4-15.6c.2-1.1-.5-2.1-1.6-2.4-.2 0-.2-.2-.2-.3v-.7h.1c0-.1.2-.3.3-.3h9c.2 0 .3.1.3.3v.7h-.1c0 .1-.1.2-.2.2z" fill-rule="evenodd"/></svg>
|
3906
3964
|
</button>
|
3907
|
-
|
3965
|
+
|
3908
3966
|
<button type="button" name="link" title="Link" data-dialog-target="link-dialog" data-hotkey="cmd+k ctrl+k">
|
3909
3967
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m22.2 1.8c-1.1-1.2-2.5-1.8-4.3-1.8s-3.1.6-4.4 1.8l-4.4 4.4c-1.2 1.2-1.8 2.7-1.8 4.3s.6 3.1 1.8 4.3h.2c.2.3.5.4 1 .4.7 0 1.1-.3 1.2-.6.3-.3.4-.7.4-1.1s-.2-.8-.5-1.2c-.5-.5-.8-1.2-.8-1.9s.3-1.4.8-1.9l4.4-4.2c.6-.5 1.5-.8 2.1-.8s1.4.2 1.9.7.8 1.2.8 1.9-.3 1.4-.8 1.9l-2.6 2.2c-.3.3-.5.7-.5 1.2s.2.8.5 1.2c.8.6 1.7.6 2.4 0l2.6-2.2c2.4-2.4 2.4-6.1 0-8.5z"/><path d="m12.3 9.3c-.3.3-.5.8-.5 1.3 0 .4.2.8.5 1.1.5.5.8 1.2.8 1.9s-.3 1.4-.9 1.9l-4.4 4.4c-.4.4-1.2.7-1.8.7s-1.4-.2-1.9-.7-.8-1.2-.8-1.9.3-1.4.8-1.9l2.5-2.4c.7-.7.7-1.7 0-2.4-.8-.6-1.7-.6-2.4 0l-2.5 2.4c-1 1.1-1.7 2.6-1.7 4.2s.6 3.1 1.8 4.3c1.3 1.2 2.7 1.8 4.2 1.8s3.2-.7 4.3-1.8l4.4-4.4c2.4-2.4 2.4-6.1 0-8.6-.8-.6-1.7-.6-2.4 0z"/></svg>
|
3910
3968
|
</button>
|
@@ -3916,33 +3974,38 @@ class LexicalToolbarElement extends HTMLElement {
|
|
3916
3974
|
<button type="submit" class="btn" value="link">Link</button>
|
3917
3975
|
<button type="button" class="btn" value="unlink">Unlink</button>
|
3918
3976
|
</div>
|
3919
|
-
</form>
|
3920
|
-
</dialog>
|
3977
|
+
</form>
|
3978
|
+
</dialog>
|
3921
3979
|
</lexxy-link-dialog>
|
3922
|
-
|
3980
|
+
|
3923
3981
|
<button type="button" name="quote" data-command="insertQuoteBlock" title="Quote">
|
3924
3982
|
<svg viewBox="0 0 24 22" xmlns="http://www.w3.org/2000/svg"> <path d="m1.1 5.2c.6-.7 1.4-1.3 2.4-1.4 2.6-.4 4.2.4 5.3 1.9 2 2.3 1.9 5.1.6 7.6-1.3 2.4-4 4.6-7.2 5.1-.4 0-.7-.1-1-.4-.1-.3-.1-.7.3-1.1l1.1-1.1c.3-.4.6-.7.7-1.1s.3-.9 0-1.3c0-.4-.6-.7-1-1-1.2-.8-2.3-2.2-2.3-4.1.1-1.4.4-2.4 1.1-3.1z"/> <path d="m14.6 5.2c.6-.7 1.6-1.1 2.6-1.4 2.4-.4 4.2.4 5.3 1.9 2 2.3 1.9 5.1.6 7.6-1.3 2.4-4 4.6-7.2 5.1-.4 0-.7-.1-1-.4-.1-.3-.1-.7.3-1.1l1.1-1.1c.3-.4.6-.7.7-1.1s.3-.9 0-1.3c-.1-.4-.6-.7-1-1-1.3-.6-2.4-2-2.4-3.9s.4-2.6 1-3.3z"/> </svg>
|
3925
3983
|
</button>
|
3926
|
-
|
3984
|
+
|
3927
3985
|
<button type="button" name="heading" data-command="rotateHeadingFormat" title="Heading">
|
3928
3986
|
<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m5.7 6.2v16.3h3.8v-16.3h5.7v-3.8h-15.2v3.8zm10.1 16.4h3.8v-8.8h4.4v-3.8h-12.6v3.8h4.4z" fill-rule="evenodd"/></svg>
|
3929
3987
|
</button>
|
3930
|
-
|
3988
|
+
|
3931
3989
|
<button type="button" name="code" data-command="insertCodeBlock" title="Code">
|
3932
3990
|
<svg viewBox="0 0 24 22" xmlns="http://www.w3.org/2000/svg"><path d="m8 4.7c-.6-.6-1.6-.6-2.4 0l-5.1 5.2c-.3.3-.5.7-.5 1.2s.2.9.5 1.2l5.1 5.1c.3.3.7.5 1.2.5s.9-.2 1.2-.5c.6-.6.6-1.7 0-2.4l-4-4 4-4c.6-.6.6-1.7 0-2.4z"/><path d="m23.5 9.9-5.1-5.1c-.6-.6-1.8-.6-2.4 0-.3.3-.5.7-.5 1.2s.2.9.5 1.2l4 4-4 4c-.3.3-.5.7-.5 1.2s.2.9.5 1.2c.3.2.7.4 1.1.4s.9-.2 1.2-.5l5.1-5.1c.3-.3.5-.7.5-1.2s-.2-.9-.5-1.2z"/></svg>
|
3933
3991
|
</button>
|
3934
|
-
|
3992
|
+
|
3935
3993
|
<button type="button" name="unordered-list" data-command="insertUnorderedList" title="Bullet list">
|
3936
|
-
<svg viewBox="0 0 24 22" xmlns="http://www.w3.org/2000/svg"> <path d="m2.1 4.8c1.1 0 2.1-.9 2.1-2.1s-1-2-2.1-2-2.1.9-2.1 2.1.9 2 2.1 2zm4.1-2c0-.8.6-1.4 1.4-1.4h15.1c.7 0 1.3.6 1.3 1.4s-.6 1.4-1.4 1.4h-15.1c-.7 0-1.3-.7-1.3-1.4zm1.3 6.8c-.8 0-1.4.6-1.4 1.4s.6 1.4 1.4 1.4h15.1c.8 0 1.4-.6 1.4-1.4s-.6-1.4-1.4-1.4zm0 8.3c-.8 0-1.4.6-1.4 1.4s.6 1.4 1.4 1.4h15.1c.8 0 1.4-.6 1.4-1.4s-.6-1.4-1.4-1.4zm-3.4-6.9c0 1.1-.9 2.1-2.1 2.1s-2-1-2-2.1.9-2.1 2.1-2.1 2 1 2 2.1zm-2 10.3c1.1 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1-2.1 1-2.1 2.1.9 2.1 2.1 2.1z" fill-rule="evenodd"/> </svg>
|
3994
|
+
<svg viewBox="0 0 24 22" xmlns="http://www.w3.org/2000/svg"> <path d="m2.1 4.8c1.1 0 2.1-.9 2.1-2.1s-1-2-2.1-2-2.1.9-2.1 2.1.9 2 2.1 2zm4.1-2c0-.8.6-1.4 1.4-1.4h15.1c.7 0 1.3.6 1.3 1.4s-.6 1.4-1.4 1.4h-15.1c-.7 0-1.3-.7-1.3-1.4zm1.3 6.8c-.8 0-1.4.6-1.4 1.4s.6 1.4 1.4 1.4h15.1c.8 0 1.4-.6 1.4-1.4s-.6-1.4-1.4-1.4zm0 8.3c-.8 0-1.4.6-1.4 1.4s.6 1.4 1.4 1.4h15.1c.8 0 1.4-.6 1.4-1.4s-.6-1.4-1.4-1.4zm-3.4-6.9c0 1.1-.9 2.1-2.1 2.1s-2-1-2-2.1.9-2.1 2.1-2.1 2 1 2 2.1zm-2 10.3c1.1 0 2.1-.9 2.1-2.1s-.9-2.1-2.1-2.1-2.1 1-2.1 2.1.9 2.1 2.1 2.1z" fill-rule="evenodd"/> </svg>
|
3937
3995
|
</button>
|
3938
|
-
|
3996
|
+
|
3939
3997
|
<button type="button" name="ordered-list" data-command="insertOrderedList" title="Numbered list">
|
3940
3998
|
<svg viewBox="0 0 24 22" xmlns="http://www.w3.org/2000/svg"><path d="m6.7 3c0-.7.6-1.3 1.3-1.3h14.7c.7 0 1.3.6 1.3 1.3s-.6 1.3-1.3 1.3h-14.7c-.7 0-1.3-.6-1.3-1.3zm1.3 6.7c-.7 0-1.3.6-1.3 1.3s.6 1.3 1.3 1.3h14.7c.7 0 1.3-.6 1.3-1.3s-.6-1.3-1.3-1.3zm0 8c-.7 0-1.3.6-1.3 1.3s.6 1.3 1.3 1.3h14.7c.7 0 1.3-.6 1.3-1.3s-.6-1.3-1.3-1.3z" fill-rule="evenodd"/><path d="m1.5 19.6v-.9h.5c.4 0 .8-.3.8-.7s-.3-.7-.8-.7-.8.3-.8.7h-1.2c0-.9.8-1.6 2-1.6s2 .5 2 1.5-.4 1.1-1.1 1.2c.7 0 1.2.7 1.2 1.3 0 1.1-1.1 1.6-2.1 1.6s-2-.8-2-1.6h1.2c0 .4.4.7.8.7s.8-.3.8-.7-.3-.7-.8-.7h-.7.1zm0-9.7h-1.2c0-.9.7-1.7 2-1.7s2 .7 2 1.6-.5 1.2-.9 1.7l-1.1 1.2h2.1v1.1h-3.9v-.8l2-2c.3-.3.5-.7.5-1.1s-.3-.7-.7-.7-.7.3-.7.7h-.3zm1.7-4.4h-1.3v-4.3l-1.2.8v-1.2l1.3-.8h1.3v5.5z"/></svg>
|
3941
3999
|
</button>
|
3942
|
-
|
4000
|
+
|
3943
4001
|
<button type="button" name="upload" data-command="uploadAttachments" title="Upload file">
|
3944
4002
|
<svg viewBox="0 0 24 20" xmlns="http://www.w3.org/2000/svg"> <path d="m22 20h-20c-1.1 0-2-.9-2-2.1v-15.8c0-1.2.9-2.1 2-2.1h20c1.1 0 2 .9 2 2.1v15.8c0 1.1-.9 2.1-2 2.1zm0-2.9v-14.5c0-.3-.2-.5-.5-.5h-19c-.3 0-.5.2-.5.5v14.5c0 .1.1.2.2.2s.2 0 .2-.1l2.2-3.3c.1-.2.3-.3.5-.3h.7l2.6-4c.1-.2.3-.3.5-.3h.7c.2 0 .4.1.5.3l5.3 8c0 .1.2.2.3.2h.3c.2 0 .4-.2.4-.4s0-.2 0-.2l-1.3-1.9c-.2-.2-.2-.6 0-.8l1.2-1.6c.1-.2.3-.3.5-.3h1.1c.2 0 .4 0 .5.3l3.2 4.4c0 .1.3.2.4 0 .2 0 .2 0 .2-.2zm-5.5-7.6c-1.4 0-2.5-1.2-2.5-2.6s1.1-2.6 2.5-2.6 2.5 1.2 2.5 2.6-1.1 2.6-2.5 2.6z" fill-rule="evenodd"/> </svg>
|
3945
4003
|
</button>
|
4004
|
+
|
4005
|
+
<details class="lexxy-editor__toolbar-overflow">
|
4006
|
+
<summary aria-label="Show more toolbar buttons">•••</summary>
|
4007
|
+
<div class="lexxy-editor__toolbar-overflow-menu" aria-label="More toolbar buttons"></div>
|
4008
|
+
</details>
|
3946
4009
|
`
|
3947
4010
|
}
|
3948
4011
|
}
|
@@ -7264,7 +7327,7 @@ class LexicalEditorElement extends HTMLElement {
|
|
7264
7327
|
constructor() {
|
7265
7328
|
super();
|
7266
7329
|
this.internals = this.attachInternals();
|
7267
|
-
this.internals.role = "
|
7330
|
+
this.internals.role = "presentation";
|
7268
7331
|
}
|
7269
7332
|
|
7270
7333
|
connectedCallback() {
|
@@ -7416,12 +7479,20 @@ class LexicalEditorElement extends HTMLElement {
|
|
7416
7479
|
}
|
7417
7480
|
|
7418
7481
|
#createEditorContentElement() {
|
7419
|
-
const editorContentElement = createElement("div", {
|
7482
|
+
const editorContentElement = createElement("div", {
|
7483
|
+
classList: "lexxy-editor__content",
|
7484
|
+
contenteditable: true,
|
7485
|
+
role: "textbox",
|
7486
|
+
"aria-multiline": true,
|
7487
|
+
"aria-label": this.#labelText,
|
7488
|
+
placeholder: this.getAttribute("placeholder")
|
7489
|
+
});
|
7420
7490
|
editorContentElement.id = `${this.id}-content`;
|
7491
|
+
this.#ariaAttributes.forEach(attribute => editorContentElement.setAttribute(attribute.name, attribute.value));
|
7421
7492
|
this.appendChild(editorContentElement);
|
7422
7493
|
|
7423
7494
|
if (this.getAttribute("tabindex")) {
|
7424
|
-
|
7495
|
+
editorContentElement.setAttribute("tabindex", this.getAttribute("tabindex"));
|
7425
7496
|
this.removeAttribute("tabindex");
|
7426
7497
|
} else {
|
7427
7498
|
editorContentElement.setAttribute("tabindex", 0);
|
@@ -7430,6 +7501,14 @@ class LexicalEditorElement extends HTMLElement {
|
|
7430
7501
|
return editorContentElement
|
7431
7502
|
}
|
7432
7503
|
|
7504
|
+
get #labelText() {
|
7505
|
+
return Array.from(this.internals.labels).map(label => label.textContent).join(" ")
|
7506
|
+
}
|
7507
|
+
|
7508
|
+
get #ariaAttributes() {
|
7509
|
+
return Array.from(this.attributes).filter(attribute => attribute.name.startsWith("aria-"))
|
7510
|
+
}
|
7511
|
+
|
7433
7512
|
set #internalFormValue(html) {
|
7434
7513
|
const changed = this.#internalFormValue !== undefined && this.#internalFormValue !== this.value;
|
7435
7514
|
|
Binary file
|
Binary file
|