@37signals/lexxy 0.9.4-beta → 0.9.6-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.
package/dist/lexxy.esm.js CHANGED
@@ -18,14 +18,28 @@ import { marked } from 'marked';
18
18
  import { $insertDataTransferForRichText } from '@lexical/clipboard';
19
19
  import 'prismjs';
20
20
  import 'prismjs/components/prism-clike';
21
+ import 'prismjs/components/prism-diff';
22
+ import 'prismjs/components/prism-javascript';
21
23
  import 'prismjs/components/prism-markup';
24
+ import 'prismjs/components/prism-markdown';
25
+ import 'prismjs/components/prism-c';
26
+ import 'prismjs/components/prism-css';
27
+ import 'prismjs/components/prism-objectivec';
28
+ import 'prismjs/components/prism-sql';
29
+ import 'prismjs/components/prism-powershell';
30
+ import 'prismjs/components/prism-python';
31
+ import 'prismjs/components/prism-rust';
32
+ import 'prismjs/components/prism-swift';
33
+ import 'prismjs/components/prism-typescript';
34
+ import 'prismjs/components/prism-java';
35
+ import 'prismjs/components/prism-cpp';
22
36
  import 'prismjs/components/prism-markup-templating';
23
37
  import 'prismjs/components/prism-ruby';
24
38
  import 'prismjs/components/prism-php';
25
39
  import 'prismjs/components/prism-go';
26
40
  import 'prismjs/components/prism-bash';
27
41
  import 'prismjs/components/prism-json';
28
- import 'prismjs/components/prism-diff';
42
+ import 'prismjs/components/prism-kotlin';
29
43
 
30
44
  const ALLOWED_HTML_ATTRIBUTES = [ "class", "contenteditable", "href", "src", "style", "title" ];
31
45
 
@@ -2175,7 +2189,7 @@ class CommandDispatcher {
2175
2189
 
2176
2190
  dispatchInsertUnorderedList() {
2177
2191
  const selection = $getSelection();
2178
- if (!selection) return
2192
+ if (!$isRangeSelection(selection)) return
2179
2193
 
2180
2194
  const anchorNode = selection.anchor.getNode();
2181
2195
 
@@ -2188,7 +2202,7 @@ class CommandDispatcher {
2188
2202
 
2189
2203
  dispatchInsertOrderedList() {
2190
2204
  const selection = $getSelection();
2191
- if (!selection) return
2205
+ if (!$isRangeSelection(selection)) return
2192
2206
 
2193
2207
  const anchorNode = selection.anchor.getNode();
2194
2208
 
@@ -2480,6 +2494,15 @@ function capitalize(str) {
2480
2494
  return str.charAt(0).toUpperCase() + str.slice(1)
2481
2495
  }
2482
2496
 
2497
+ function debounce(fn, wait) {
2498
+ let timeout;
2499
+
2500
+ return (...args) => {
2501
+ clearTimeout(timeout);
2502
+ timeout = setTimeout(() => fn(...args), wait);
2503
+ }
2504
+ }
2505
+
2483
2506
  function debounceAsync(fn, wait) {
2484
2507
  let timeout;
2485
2508
 
@@ -5903,9 +5926,9 @@ class AttachmentDragAndDrop {
5903
5926
  // -- Event handlers --------------------------------------------------------
5904
5927
 
5905
5928
  #handleDragStart(event) {
5906
- if (event.target.closest("textarea")) return false
5929
+ if (event.target.closest?.("textarea")) return false
5907
5930
 
5908
- const figure = event.target.closest("figure.attachment[data-lexical-node-key]");
5931
+ const figure = event.target.closest?.("figure.attachment[data-lexical-node-key]");
5909
5932
  if (!figure) return false
5910
5933
 
5911
5934
  this.#draggedNodeKey = figure.dataset.lexicalNodeKey;
@@ -6350,6 +6373,11 @@ class EarlyEscapeCodeNode extends CodeNode {
6350
6373
  insertNewAfter(selection, restoreSelection) {
6351
6374
  if (!selection.isCollapsed()) return super.insertNewAfter(selection, restoreSelection)
6352
6375
 
6376
+ if (this.#isCursorAtStart(selection)) {
6377
+ this.insertBefore($createParagraphNode());
6378
+ return null
6379
+ }
6380
+
6353
6381
  if (this.#isCursorOnEmptyLastLine(selection)) {
6354
6382
  $trimTrailingBlankNodes(this);
6355
6383
 
@@ -6361,6 +6389,14 @@ class EarlyEscapeCodeNode extends CodeNode {
6361
6389
  return super.insertNewAfter(selection, restoreSelection)
6362
6390
  }
6363
6391
 
6392
+ #isCursorAtStart(selection) {
6393
+ const { anchor } = selection;
6394
+ if (!$isAtNodeStart(anchor)) return false
6395
+
6396
+ const anchorNode = anchor.getNode();
6397
+ return this.is(anchorNode) || this.getFirstChild()?.is(anchorNode)
6398
+ }
6399
+
6364
6400
  #isCursorOnEmptyLastLine(selection) {
6365
6401
  if (!$isCursorOnLastLine(selection)) return false
6366
6402
 
@@ -7478,6 +7514,8 @@ class BaseSource {
7478
7514
  }
7479
7515
  }
7480
7516
 
7517
+ const MAX_RENDERED_SUGGESTIONS$1 = 100;
7518
+
7481
7519
  class LocalFilterSource extends BaseSource {
7482
7520
  async buildListItems(filter = "") {
7483
7521
  const promptItems = await this.fetchPromptItems();
@@ -7496,7 +7534,10 @@ class LocalFilterSource extends BaseSource {
7496
7534
  #buildListItemsFromPromptItems(promptItems, filter) {
7497
7535
  const listItems = [];
7498
7536
  this.promptItemByListItem = new WeakMap();
7499
- promptItems.forEach((promptItem) => {
7537
+
7538
+ for (const promptItem of promptItems) {
7539
+ if (listItems.length >= MAX_RENDERED_SUGGESTIONS$1) break
7540
+
7500
7541
  const searchableText = promptItem.getAttribute("search");
7501
7542
 
7502
7543
  if (!filter || filterMatches(searchableText, filter)) {
@@ -7504,7 +7545,7 @@ class LocalFilterSource extends BaseSource {
7504
7545
  this.promptItemByListItem.set(listItem, promptItem);
7505
7546
  listItems.push(listItem);
7506
7547
  }
7507
- });
7548
+ }
7508
7549
 
7509
7550
  return listItems
7510
7551
  }
@@ -7537,6 +7578,7 @@ class DeferredPromptSource extends LocalFilterSource {
7537
7578
  }
7538
7579
 
7539
7580
  const DEBOUNCE_INTERVAL = 200;
7581
+ const MAX_RENDERED_SUGGESTIONS = 100;
7540
7582
 
7541
7583
  class RemoteFilterSource extends BaseSource {
7542
7584
  constructor(url) {
@@ -7570,6 +7612,8 @@ class RemoteFilterSource extends BaseSource {
7570
7612
  this.promptItemByListItem = new WeakMap();
7571
7613
 
7572
7614
  for (const promptItem of promptItems) {
7615
+ if (listItems.length >= MAX_RENDERED_SUGGESTIONS) break
7616
+
7573
7617
  const listItem = this.buildListItemElementFor(promptItem);
7574
7618
  this.promptItemByListItem.set(listItem, promptItem);
7575
7619
  listItems.push(listItem);
@@ -7580,10 +7624,12 @@ class RemoteFilterSource extends BaseSource {
7580
7624
  }
7581
7625
 
7582
7626
  const NOTHING_FOUND_DEFAULT_MESSAGE = "Nothing found";
7627
+ const FILTER_DEBOUNCE_INTERVAL = 50;
7583
7628
 
7584
7629
  class LexicalPromptElement extends HTMLElement {
7585
7630
  #globalListeners = new ListenerBin()
7586
7631
  #popoverListeners = new ListenerBin()
7632
+ #debouncedFilterOptions = debounce(() => this.#filterOptions(), FILTER_DEBOUNCE_INTERVAL)
7587
7633
 
7588
7634
  constructor() {
7589
7635
  super();
@@ -7741,7 +7787,7 @@ class LexicalPromptElement extends HTMLElement {
7741
7787
 
7742
7788
  this.#popoverListeners.track(
7743
7789
  registerEventListener(this.#editorElement, "keydown", this.#handleKeydownOnPopover),
7744
- registerEventListener(this.#editorElement, "lexxy:change", this.#filterOptions)
7790
+ registerEventListener(this.#editorElement, "lexxy:change", this.#debouncedFilterOptions)
7745
7791
  );
7746
7792
 
7747
7793
  this.#registerKeyListeners();
@@ -8123,6 +8169,8 @@ class CodeLanguagePicker extends HTMLElement {
8123
8169
  languages.bash ||= "Bash";
8124
8170
  languages.json ||= "JSON";
8125
8171
  languages.diff ||= "Diff";
8172
+ languages.kotlin ||= "Kotlin";
8173
+
8126
8174
 
8127
8175
  // Place the "plain" entry first, then the rest of language sorted alphabetically
8128
8176
  delete languages.plain;
@@ -1,13 +1,27 @@
1
1
  import Prism from 'prismjs';
2
2
  import 'prismjs/components/prism-clike';
3
+ import 'prismjs/components/prism-diff';
4
+ import 'prismjs/components/prism-javascript';
3
5
  import 'prismjs/components/prism-markup';
6
+ import 'prismjs/components/prism-markdown';
7
+ import 'prismjs/components/prism-c';
8
+ import 'prismjs/components/prism-css';
9
+ import 'prismjs/components/prism-objectivec';
10
+ import 'prismjs/components/prism-sql';
11
+ import 'prismjs/components/prism-powershell';
12
+ import 'prismjs/components/prism-python';
13
+ import 'prismjs/components/prism-rust';
14
+ import 'prismjs/components/prism-swift';
15
+ import 'prismjs/components/prism-typescript';
16
+ import 'prismjs/components/prism-java';
17
+ import 'prismjs/components/prism-cpp';
4
18
  import 'prismjs/components/prism-markup-templating';
5
19
  import 'prismjs/components/prism-ruby';
6
20
  import 'prismjs/components/prism-php';
7
21
  import 'prismjs/components/prism-go';
8
22
  import 'prismjs/components/prism-bash';
9
23
  import 'prismjs/components/prism-json';
10
- import 'prismjs/components/prism-diff';
24
+ import 'prismjs/components/prism-kotlin';
11
25
 
12
26
  // Configure Prism for manual highlighting mode
13
27
  // This must be set before importing prismjs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@37signals/lexxy",
3
- "version": "0.9.4-beta",
3
+ "version": "0.9.6-beta",
4
4
  "description": "Lexxy - A modern rich text editor for Rails.",
5
5
  "module": "dist/lexxy.esm.js",
6
6
  "type": "module",