@dxos/react-ui-editor 0.4.7-main.e015b9e → 0.4.7-main.ea67fec

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.
@@ -596,7 +596,7 @@ var RemoteSelectionsDecorator = class {
596
596
  to: startLine.from + startLine.length,
597
597
  value: Decoration2.mark({
598
598
  attributes: {
599
- style: `background-color: ${color}`
599
+ style: `background-color: ${lightColor}`
600
600
  },
601
601
  class: "cm-collab-selection"
602
602
  })
@@ -606,7 +606,7 @@ var RemoteSelectionsDecorator = class {
606
606
  to: end,
607
607
  value: Decoration2.mark({
608
608
  attributes: {
609
- style: `background-color: ${color}`
609
+ style: `background-color: ${lightColor}`
610
610
  },
611
611
  class: "cm-collab-selection"
612
612
  })
@@ -618,7 +618,7 @@ var RemoteSelectionsDecorator = class {
618
618
  to: linePos,
619
619
  value: Decoration2.line({
620
620
  attributes: {
621
- style: `background-color: ${color}`,
621
+ style: `background-color: ${lightColor}`,
622
622
  class: "cm-collab-selectionLine"
623
623
  }
624
624
  })
@@ -1072,44 +1072,6 @@ import { useEffect } from "react";
1072
1072
  import { debounce } from "@dxos/async";
1073
1073
  import { nonNullable } from "@dxos/util";
1074
1074
 
1075
- // packages/ui/react-ui-editor/src/styles/cursors.ts
1076
- import * as random2 from "lib0/random";
1077
- var cursorColors = [
1078
- {
1079
- color: "#30bced",
1080
- light: "#30bced33"
1081
- },
1082
- {
1083
- color: "#6eeb83",
1084
- light: "#6eeb8333"
1085
- },
1086
- {
1087
- color: "#ffbc42",
1088
- light: "#ffbc4233"
1089
- },
1090
- {
1091
- color: "#ecd444",
1092
- light: "#ecd44433"
1093
- },
1094
- {
1095
- color: "#ee6352",
1096
- light: "#ee635233"
1097
- },
1098
- {
1099
- color: "#9ac2c9",
1100
- light: "#9ac2c933"
1101
- },
1102
- {
1103
- color: "#8acb88",
1104
- light: "#8acb8833"
1105
- },
1106
- {
1107
- color: "#1be7ff",
1108
- light: "#1be7ff33"
1109
- }
1110
- ];
1111
- var cursorColor = cursorColors[random2.uint32() % cursorColors.length];
1112
-
1113
1075
  // packages/ui/react-ui-editor/src/styles/markdown.ts
1114
1076
  import { mx } from "@dxos/react-ui-theme";
1115
1077
  var headings = {
@@ -1897,7 +1859,7 @@ var createMarkdownExtensions = ({ themeMode, placeholder: _placeholder, lineWrap
1897
1859
 
1898
1860
  // packages/ui/react-ui-editor/src/extensions/markdown/decorate.ts
1899
1861
  import { syntaxTree } from "@codemirror/language";
1900
- import { RangeSetBuilder } from "@codemirror/state";
1862
+ import { RangeSetBuilder, StateEffect as StateEffect3 } from "@codemirror/state";
1901
1863
  import { EditorView as EditorView10, Decoration as Decoration4, WidgetType as WidgetType2, ViewPlugin as ViewPlugin3 } from "@codemirror/view";
1902
1864
  import { mx as mx2 } from "@dxos/react-ui-theme";
1903
1865
  var HorizontalRuleWidget = class extends WidgetType2 {
@@ -1978,9 +1940,9 @@ var checkedTask = Decoration4.replace({
1978
1940
  var uncheckedTask = Decoration4.replace({
1979
1941
  widget: new CheckboxWidget(false)
1980
1942
  });
1981
- var editingRange = (state, range) => {
1943
+ var editingRange = (state, range, focus) => {
1982
1944
  const { readOnly, selection: { main: { head } } } = state;
1983
- return !readOnly && head >= range.from && head <= range.to;
1945
+ return focus && !readOnly && head >= range.from && head < range.to;
1984
1946
  };
1985
1947
  var MarksByParent = /* @__PURE__ */ new Set([
1986
1948
  "CodeMark",
@@ -1989,8 +1951,9 @@ var MarksByParent = /* @__PURE__ */ new Set([
1989
1951
  "SubscriptMark",
1990
1952
  "SuperscriptMark"
1991
1953
  ]);
1992
- var buildDecorations = (view, options) => {
1993
- const builder = new RangeSetBuilder();
1954
+ var buildDecorations = (view, options, focus) => {
1955
+ const deco = new RangeSetBuilder();
1956
+ const atomicDeco = new RangeSetBuilder();
1994
1957
  const { state } = view;
1995
1958
  for (const { from, to } of view.visibleRanges) {
1996
1959
  syntaxTree(state).iterate({
@@ -1998,7 +1961,7 @@ var buildDecorations = (view, options) => {
1998
1961
  to,
1999
1962
  enter: (node) => {
2000
1963
  if (node.name === "FencedCode") {
2001
- const editing = editingRange(state, node);
1964
+ const editing = editingRange(state, node, focus);
2002
1965
  for (const block of view.viewportLineBlocks) {
2003
1966
  if (block.to < node.from) {
2004
1967
  continue;
@@ -2008,22 +1971,22 @@ var buildDecorations = (view, options) => {
2008
1971
  }
2009
1972
  const first = block.from <= node.from;
2010
1973
  const last = block.to >= node.to;
2011
- builder.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
1974
+ deco.add(block.from, block.from, first ? fencedCodeLineFirst : last ? fencedCodeLineLast : fencedCodeLine);
2012
1975
  if (!editing && (first || last)) {
2013
- builder.add(block.from, block.to, hide);
1976
+ atomicDeco.add(block.from, block.to, hide);
2014
1977
  }
2015
1978
  }
2016
1979
  return false;
2017
1980
  } else if (node.name === "Link") {
2018
1981
  const marks = node.node.getChildren("LinkMark");
2019
1982
  const urlNode = node.node.getChild("URL");
2020
- const editing = editingRange(state, node);
1983
+ const editing = editingRange(state, node, focus);
2021
1984
  if (urlNode && marks.length >= 2) {
2022
1985
  const url = state.sliceDoc(urlNode.from, urlNode.to);
2023
1986
  if (!editing) {
2024
- builder.add(node.from, marks[0].to, hide);
1987
+ atomicDeco.add(node.from, marks[0].to, hide);
2025
1988
  }
2026
- builder.add(marks[0].to, marks[1].from, Decoration4.mark({
1989
+ deco.add(marks[0].to, marks[1].from, Decoration4.mark({
2027
1990
  tagName: "a",
2028
1991
  attributes: {
2029
1992
  class: "cm-link",
@@ -2033,52 +1996,81 @@ var buildDecorations = (view, options) => {
2033
1996
  }
2034
1997
  }));
2035
1998
  if (!editing) {
2036
- builder.add(marks[1].from, node.to, options.renderLinkButton ? Decoration4.replace({
1999
+ atomicDeco.add(marks[1].from, node.to, options.renderLinkButton ? Decoration4.replace({
2037
2000
  widget: new LinkButton(url, options.renderLinkButton)
2038
2001
  }) : hide);
2039
2002
  }
2040
2003
  }
2041
2004
  } else if (node.name === "HeaderMark") {
2042
2005
  const parent = node.node.parent;
2043
- if (/^ATX/.test(parent.name) && !editingRange(state, state.doc.lineAt(node.from))) {
2006
+ if (/^ATX/.test(parent.name) && !editingRange(state, state.doc.lineAt(node.from), focus)) {
2044
2007
  const next = state.doc.sliceString(node.to, node.to + 1);
2045
- builder.add(node.from, node.to + (next === " " ? 1 : 0), hide);
2008
+ atomicDeco.add(node.from, node.to + (next === " " ? 1 : 0), hide);
2046
2009
  }
2047
2010
  } else if (node.name === "HorizontalRule") {
2048
- if (!editingRange(state, node)) {
2049
- builder.add(node.from, node.to, horizontalRule);
2011
+ if (!editingRange(state, node, focus)) {
2012
+ deco.add(node.from, node.to, horizontalRule);
2050
2013
  }
2051
2014
  } else if (node.name === "TaskMarker") {
2052
- if (!editingRange(state, node)) {
2015
+ if (!editingRange(state, node, focus)) {
2053
2016
  const checked = state.doc.sliceString(node.from + 1, node.to - 1) === "x";
2054
- builder.add(node.from - 2, node.from - 1, Decoration4.mark({
2017
+ atomicDeco.add(node.from - 2, node.from - 1, Decoration4.mark({
2055
2018
  class: "cm-task"
2056
2019
  }));
2057
- builder.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
2020
+ atomicDeco.add(node.from, node.to, checked ? checkedTask : uncheckedTask);
2058
2021
  }
2059
2022
  } else if (MarksByParent.has(node.name)) {
2060
- if (!editingRange(state, node.node.parent)) {
2061
- builder.add(node.from, node.to, hide);
2023
+ if (!editingRange(state, node.node.parent, focus)) {
2024
+ atomicDeco.add(node.from, node.to, hide);
2062
2025
  }
2063
2026
  }
2064
2027
  }
2065
2028
  });
2066
2029
  }
2067
- return builder.finish();
2030
+ return {
2031
+ deco: deco.finish(),
2032
+ atomicDeco: atomicDeco.finish()
2033
+ };
2068
2034
  };
2035
+ var forceUpdate = StateEffect3.define();
2069
2036
  var decorateMarkdown = (options = {}) => {
2070
2037
  return [
2071
2038
  ViewPlugin3.fromClass(class {
2072
2039
  constructor(view) {
2073
- this.decorations = buildDecorations(view, options);
2040
+ this.pendingUpdate = -1;
2041
+ ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(view, options, view.hasFocus));
2074
2042
  }
2075
2043
  update(update2) {
2076
- if (update2.docChanged || update2.selectionSet || update2.viewportChanged) {
2077
- this.decorations = buildDecorations(update2.view, options);
2044
+ if (update2.docChanged || update2.viewportChanged || update2.focusChanged || update2.transactions.some((tr) => tr.effects.some((e) => e.is(forceUpdate)))) {
2045
+ ({ deco: this.deco, atomicDeco: this.atomicDeco } = buildDecorations(update2.view, options, update2.view.hasFocus));
2046
+ this.clearUpdate();
2047
+ } else if (update2.selectionSet) {
2048
+ this.scheduleUpdate(update2.view);
2049
+ }
2050
+ }
2051
+ clearUpdate() {
2052
+ if (this.pendingUpdate > -1) {
2053
+ window.clearTimeout(this.pendingUpdate);
2054
+ this.pendingUpdate = -1;
2078
2055
  }
2079
2056
  }
2057
+ scheduleUpdate(view) {
2058
+ this.clearUpdate();
2059
+ this.pendingUpdate = window.setTimeout(() => {
2060
+ view.dispatch({
2061
+ effects: forceUpdate.of(null)
2062
+ });
2063
+ }, options.selectionChangeDelay ?? 400);
2064
+ }
2065
+ destroy() {
2066
+ this.clearUpdate();
2067
+ }
2080
2068
  }, {
2081
- decorations: (value) => value.decorations
2069
+ provide: (plugin) => [
2070
+ EditorView10.atomicRanges.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration4.none),
2071
+ EditorView10.decorations.of((view) => view.plugin(plugin)?.deco ?? Decoration4.none),
2072
+ EditorView10.decorations.of((view) => view.plugin(plugin)?.atomicDeco ?? Decoration4.none)
2073
+ ]
2082
2074
  }),
2083
2075
  formattingStyles
2084
2076
  ];
@@ -4550,11 +4542,15 @@ import { generateName } from "@dxos/display-name";
4550
4542
  import { getRawDoc } from "@dxos/echo-schema";
4551
4543
  import { invariant as invariant3 } from "@dxos/invariant";
4552
4544
  import { isAutomergeObject } from "@dxos/react-client/echo";
4545
+ import { hueTokens } from "@dxos/react-ui-theme";
4546
+ import { hexToHue } from "@dxos/util";
4553
4547
  var __dxlog_file7 = "/home/runner/work/dxos/dxos/packages/ui/react-ui-editor/src/hooks/useTextModel.ts";
4554
4548
  var useTextExtensions = ({ id, text, space, identity }) => {
4555
4549
  const extensions = [
4556
4550
  automerge(text)
4557
4551
  ];
4552
+ const peerId = identity?.identityKey.toHex();
4553
+ const { cursorLightValue, cursorDarkValue } = hueTokens[hexToHue(peerId ?? "0")];
4558
4554
  if (space && identity) {
4559
4555
  const awarenessProvider2 = new SpaceAwarenessProvider({
4560
4556
  space,
@@ -4562,8 +4558,8 @@ var useTextExtensions = ({ id, text, space, identity }) => {
4562
4558
  peerId: identity.identityKey.toHex(),
4563
4559
  info: {
4564
4560
  displayName: identity.profile?.displayName ?? generateName(identity.identityKey.toHex()),
4565
- color: cursorColor.color,
4566
- lightColor: cursorColor.light
4561
+ color: cursorDarkValue,
4562
+ lightColor: cursorLightValue
4567
4563
  }
4568
4564
  });
4569
4565
  extensions.push(awareness(awarenessProvider2));
@@ -4586,7 +4582,7 @@ var createModel = ({ space, identity, text }) => {
4586
4582
  }
4587
4583
  invariant3(isAutomergeObject(text), void 0, {
4588
4584
  F: __dxlog_file7,
4589
- L: 83,
4585
+ L: 87,
4590
4586
  S: void 0,
4591
4587
  A: [
4592
4588
  "isAutomergeObject(text)",
@@ -4597,13 +4593,15 @@ var createModel = ({ space, identity, text }) => {
4597
4593
  const doc = getRawDoc(obj, [
4598
4594
  obj.field
4599
4595
  ]);
4596
+ const peerId = identity?.identityKey.toHex();
4597
+ const { cursorLightValue, cursorDarkValue } = hueTokens[hexToHue(peerId ?? "0")];
4600
4598
  const awarenessProvider2 = space && new SpaceAwarenessProvider({
4601
4599
  space,
4602
4600
  channel: `automerge.awareness.${obj.id}`,
4603
4601
  info: {
4604
4602
  displayName: identity ? identity.profile?.displayName ?? generateName(identity.identityKey.toHex()) : void 0,
4605
- color: cursorColor.color,
4606
- lightColor: cursorColor.light
4603
+ color: cursorLightValue,
4604
+ lightColor: cursorDarkValue
4607
4605
  },
4608
4606
  peerId: identity?.identityKey.toHex() ?? "Anonymous"
4609
4607
  });