@datarobot/design-system 30.7.0 → 30.9.0

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.
Files changed (36) hide show
  1. package/cjs/chat/chat-message-body.js +9 -7
  2. package/cjs/chat/utils.js +5 -1
  3. package/cjs/index.d.ts +1 -0
  4. package/cjs/index.js +11 -0
  5. package/cjs/scoped-theme/index.d.ts +1 -0
  6. package/cjs/scoped-theme/index.js +24 -0
  7. package/cjs/scoped-theme/scoped-theme.d.ts +14 -0
  8. package/cjs/scoped-theme/scoped-theme.js +46 -0
  9. package/cjs/text-editor/edited-text.js +12 -4
  10. package/cjs/text-editor/text-editor.js +8 -1
  11. package/esm/chat/chat-message-body.js +9 -7
  12. package/esm/chat/utils.js +4 -1
  13. package/esm/index.d.ts +1 -0
  14. package/esm/index.js +1 -0
  15. package/esm/scoped-theme/index.d.ts +1 -0
  16. package/esm/scoped-theme/index.js +1 -0
  17. package/esm/scoped-theme/scoped-theme.d.ts +14 -0
  18. package/esm/scoped-theme/scoped-theme.js +37 -0
  19. package/esm/text-editor/edited-text.js +12 -4
  20. package/esm/text-editor/text-editor.js +8 -1
  21. package/js/bundle/bundle.js +451 -1390
  22. package/js/bundle/bundle.min.js +1 -1
  23. package/js/bundle/bundle.min.js.LICENSE.txt +0 -21
  24. package/js/bundle/index.d.ts +15 -0
  25. package/package.json +5 -5
  26. package/scoped-theme/package.json +7 -0
  27. package/styles/index.css +10069 -10065
  28. package/styles/index.min.css +1 -1
  29. package/styles/scoped/index.css +14132 -0
  30. package/styles/scoped/index.min.css +1 -0
  31. package/styles/scoped/themes/alpine-light.css +1100 -0
  32. package/styles/scoped/themes/alpine-light.min.css +1 -0
  33. package/styles/scoped/themes/light.css +484 -0
  34. package/styles/scoped/themes/light.min.css +1 -0
  35. package/styles/scoped/themes/midnight-gray.css +1082 -0
  36. package/styles/scoped/themes/midnight-gray.min.css +1 -0
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.ChatMessageBody = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _isEqual = _interopRequireDefault(require("lodash-es/isEqual"));
9
+ var _cloneDeep = _interopRequireDefault(require("lodash-es/cloneDeep"));
9
10
  var _classnames = _interopRequireDefault(require("classnames"));
10
11
  var _slate = require("slate");
11
12
  var _slateReact = require("slate-react");
@@ -36,8 +37,9 @@ function ChatMessageBodyBase({
36
37
  editableContentClassName,
37
38
  mentionsPropmptText,
38
39
  autoFocus,
39
- value = _constants.DEFAULT_VALUE
40
+ value
40
41
  }) {
42
+ const slateValue = (0, _react.useMemo)(() => (0, _cloneDeep.default)(value ?? _constants.DEFAULT_VALUE), [value]);
41
43
  const anchorRef = (0, _react.useRef)(null);
42
44
  const [target, setTarget] = (0, _react.useState)();
43
45
  const [search, setSearch] = (0, _react.useState)('');
@@ -54,10 +56,10 @@ function ChatMessageBodyBase({
54
56
  event.preventDefault();
55
57
  onSubmit({
56
58
  key: itemKey,
57
- value
59
+ value: slateValue
58
60
  });
59
61
  }
60
- }, [mentions, target, value, itemKey, onSubmit]);
62
+ }, [mentions, target, slateValue, itemKey, onSubmit]);
61
63
  const handleChange = (0, _react.useCallback)(val => {
62
64
  onChange({
63
65
  key: itemKey,
@@ -124,14 +126,14 @@ function ChatMessageBodyBase({
124
126
  });
125
127
  }, [search]);
126
128
  (0, _react.useEffect)(() => {
127
- if (!(0, _isEqual.default)(editor.children, value)) {
128
- (0, _utils.resetNodes)(editor, value);
129
+ if (!(0, _isEqual.default)(editor.children, slateValue)) {
130
+ (0, _utils.resetNodes)(editor, slateValue);
129
131
  }
130
- }, [value, editor]);
132
+ }, [slateValue, editor]);
131
133
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
132
134
  children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_slateReact.Slate, {
133
135
  editor: editor,
134
- initialValue: value,
136
+ initialValue: slateValue,
135
137
  onChange: handleChange,
136
138
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
137
139
  "test-id": `chat-item-body-editable-content-${itemKey}`,
package/cjs/chat/utils.js CHANGED
@@ -7,7 +7,9 @@ exports.getMentionsCount = getMentionsCount;
7
7
  exports.isMentionElement = isMentionElement;
8
8
  exports.resetNodes = resetNodes;
9
9
  var _slate = require("slate");
10
+ var _cloneDeep = _interopRequireDefault(require("lodash-es/cloneDeep"));
10
11
  var _constants = require("./constants");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
13
  function isMentionElement(type) {
12
14
  return type === _constants.CUSTOM_ELEMENT_TYPES.mention;
13
15
  }
@@ -34,10 +36,12 @@ function resetNodes(editor, nodes) {
34
36
  path: [0],
35
37
  node
36
38
  }));
39
+
40
+ // Clone nodes before inserting so multiple editors never share Slate node refs.
37
41
  nodes.forEach((node, i) => editor.apply({
38
42
  type: 'insert_node',
39
43
  path: [i],
40
- node
44
+ node: (0, _cloneDeep.default)(node)
41
45
  }));
42
46
  const point = _slate.Editor.end(editor, []);
43
47
  _slate.Transforms.select(editor, point);
package/cjs/index.d.ts CHANGED
@@ -73,6 +73,7 @@ export * from './range-slider';
73
73
  export * from './react-popper';
74
74
  export * from './refresh-button';
75
75
  export * from './scheduler';
76
+ export * from './scoped-theme';
76
77
  export * from './search';
77
78
  export * from './searchable-list';
78
79
  export * from './selectable-tiles';
package/cjs/index.js CHANGED
@@ -828,6 +828,17 @@ Object.keys(_scheduler).forEach(function (key) {
828
828
  }
829
829
  });
830
830
  });
831
+ var _scopedTheme = require("./scoped-theme");
832
+ Object.keys(_scopedTheme).forEach(function (key) {
833
+ if (key === "default" || key === "__esModule") return;
834
+ if (key in exports && exports[key] === _scopedTheme[key]) return;
835
+ Object.defineProperty(exports, key, {
836
+ enumerable: true,
837
+ get: function () {
838
+ return _scopedTheme[key];
839
+ }
840
+ });
841
+ });
831
842
  var _search = require("./search");
832
843
  Object.keys(_search).forEach(function (key) {
833
844
  if (key === "default" || key === "__esModule") return;
@@ -0,0 +1 @@
1
+ export { ScopedTheme, useSyncDesignSystemTheme, syncDesignSystemTheme, } from './scoped-theme';
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "ScopedTheme", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _scopedTheme.ScopedTheme;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "syncDesignSystemTheme", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _scopedTheme.syncDesignSystemTheme;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "useSyncDesignSystemTheme", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _scopedTheme.useSyncDesignSystemTheme;
22
+ }
23
+ });
24
+ var _scopedTheme = require("./scoped-theme");
@@ -0,0 +1,14 @@
1
+ export declare const defaultThemeMapping: {
2
+ 'midnight-gray': string;
3
+ 'alpine-light': string;
4
+ dark: string;
5
+ light: string;
6
+ };
7
+ export declare const syncDesignSystemTheme: (theme: string, themeMapping?: Record<string, string>) => void;
8
+ export declare const useSyncDesignSystemTheme: (theme: string, themeMapping?: Record<string, string>) => void;
9
+ export declare function ScopedTheme(props: {
10
+ children: React.ReactNode;
11
+ theme: keyof typeof defaultThemeMapping;
12
+ className?: string;
13
+ themeMapping?: Record<string, string>;
14
+ } & React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.ScopedTheme = ScopedTheme;
7
+ exports.useSyncDesignSystemTheme = exports.syncDesignSystemTheme = exports.defaultThemeMapping = void 0;
8
+ var _react = require("react");
9
+ var _jsxRuntime = require("react/jsx-runtime");
10
+ const defaultThemeMapping = exports.defaultThemeMapping = {
11
+ 'midnight-gray': 'midnight-gray',
12
+ 'alpine-light': 'alpine-light',
13
+ dark: 'midnight-gray',
14
+ light: 'alpine-light'
15
+ };
16
+ const syncDesignSystemTheme = (theme, themeMapping = defaultThemeMapping) => {
17
+ if (theme && theme in themeMapping) {
18
+ for (const container of document.querySelectorAll('[data-ds]')) {
19
+ container.setAttribute('data-theme', themeMapping[theme]);
20
+ }
21
+ }
22
+ };
23
+ exports.syncDesignSystemTheme = syncDesignSystemTheme;
24
+ const useSyncDesignSystemTheme = (theme, themeMapping = defaultThemeMapping) => {
25
+ (0, _react.useLayoutEffect)(() => {
26
+ syncDesignSystemTheme(theme, themeMapping);
27
+ }, [theme, themeMapping]);
28
+ };
29
+ exports.useSyncDesignSystemTheme = useSyncDesignSystemTheme;
30
+ function ScopedTheme(props) {
31
+ const {
32
+ children,
33
+ theme,
34
+ className = '',
35
+ themeMapping = defaultThemeMapping,
36
+ ...rest
37
+ } = props;
38
+ const scopedTheme = themeMapping[theme] || theme;
39
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
40
+ "data-ds": true,
41
+ "data-theme": scopedTheme,
42
+ className: className,
43
+ ...rest,
44
+ children: children
45
+ });
46
+ }
@@ -7,6 +7,7 @@ exports.default = EditedText;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _classnames = _interopRequireDefault(require("classnames"));
9
9
  var _isEqual = _interopRequireDefault(require("lodash-es/isEqual"));
10
+ var _cloneDeep = _interopRequireDefault(require("lodash-es/cloneDeep"));
10
11
  var _slateHistory = require("slate-history");
11
12
  var _chat = require("../chat");
12
13
  var _textEditorContext = _interopRequireDefault(require("./text-editor-context"));
@@ -37,12 +38,19 @@ function EditedTextComponent({
37
38
  Slate
38
39
  } = slateReact;
39
40
  const editor = (0, _react.useMemo)(() => (0, _withLinks.default)((0, _slateHistory.withHistory)(withReact(createEditor()))), []);
41
+
42
+ // Clone the incoming value so this editor instance owns its own Slate node
43
+ // references. slate-dom 0.123+ keys internal WeakMaps by node identity, and
44
+ // sharing node references across editors (e.g. the same value bound to a
45
+ // form's TextEditor and a preview's EditedText at the same time) makes
46
+ // findPath throw "Unable to find the path for Slate node".
47
+ const slateValue = (0, _react.useMemo)(() => value ? (0, _cloneDeep.default)(value) : value, [value]);
40
48
  (0, _react.useEffect)(() => {
41
- if (value && !(0, _isEqual.default)(editor.children, value)) {
49
+ if (slateValue && !(0, _isEqual.default)(editor.children, slateValue)) {
42
50
  // Update the cached value inside the editor
43
- (0, _chat.resetNodes)(editor, value);
51
+ (0, _chat.resetNodes)(editor, slateValue);
44
52
  }
45
- }, [value, editor]);
53
+ }, [slateValue, editor]);
46
54
  const ariaAttrs = (0, _react.useMemo)(() => {
47
55
  return {
48
56
  'aria-label': ariaLabel
@@ -53,7 +61,7 @@ function EditedTextComponent({
53
61
  // Slate throws an error when no onChange is given, providing a noop func to avoid issues
54
62
  (0, _jsxRuntime.jsx)(Slate, {
55
63
  editor: editor,
56
- initialValue: value,
64
+ initialValue: slateValue,
57
65
  onChange: () => undefined,
58
66
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_textEditorContent.default, {
59
67
  placeholder: placeholder,
@@ -7,6 +7,7 @@ exports.default = TextEditor;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _classnames = _interopRequireDefault(require("classnames"));
9
9
  var _isEqual = _interopRequireDefault(require("lodash-es/isEqual"));
10
+ var _cloneDeep = _interopRequireDefault(require("lodash-es/cloneDeep"));
10
11
  var _slateHistory = require("slate-history");
11
12
  var _formField = require("../form-field");
12
13
  var _chat = require("../chat");
@@ -79,7 +80,13 @@ function TextEditorComponent({
79
80
  }, [getCharactersCounterString]);
80
81
  const editor = (0, _react.useMemo)(() => (0, _chat.withMaxLength)(maxLength)((0, _withLinks.default)((0, _slateHistory.withHistory)(withReact(createEditor())))), [maxLength]);
81
82
  const selection = (0, _react.useRef)(null);
82
- const slateValue = value || initialValue || _textEditorConstants.TEXT_EDITOR_DEFAULT_VALUE;
83
+ // Clone the incoming value so this editor instance owns its own Slate node
84
+ // references. slate-dom 0.123+ keys internal WeakMaps by node identity, and
85
+ // sharing the same node references across editors (e.g. several editors
86
+ // falling back to TEXT_EDITOR_DEFAULT_VALUE, or the same parent state being
87
+ // bound to multiple editors at once) makes findPath throw
88
+ // "Unable to find the path for Slate node".
89
+ const slateValue = (0, _react.useMemo)(() => (0, _cloneDeep.default)(value || initialValue || _textEditorConstants.TEXT_EDITOR_DEFAULT_VALUE), [value, initialValue]);
83
90
  (0, _react.useEffect)(() => {
84
91
  if (!(0, _isEqual.default)(editor.children, slateValue)) {
85
92
  // Update the cached value inside the editor
@@ -1,5 +1,6 @@
1
1
  import React, { useMemo, useState, useCallback, useRef, useEffect, memo } from 'react';
2
2
  import isEqual from 'lodash-es/isEqual';
3
+ import cloneDeep from 'lodash-es/cloneDeep';
3
4
  import classNames from 'classnames';
4
5
  import { Editor, createEditor, Transforms, Range } from 'slate';
5
6
  import { Slate, Editable, ReactEditor, withReact } from 'slate-react';
@@ -28,8 +29,9 @@ function ChatMessageBodyBase({
28
29
  editableContentClassName,
29
30
  mentionsPropmptText,
30
31
  autoFocus,
31
- value = DEFAULT_VALUE
32
+ value
32
33
  }) {
34
+ const slateValue = useMemo(() => cloneDeep(value ?? DEFAULT_VALUE), [value]);
33
35
  const anchorRef = useRef(null);
34
36
  const [target, setTarget] = useState();
35
37
  const [search, setSearch] = useState('');
@@ -46,10 +48,10 @@ function ChatMessageBodyBase({
46
48
  event.preventDefault();
47
49
  onSubmit({
48
50
  key: itemKey,
49
- value
51
+ value: slateValue
50
52
  });
51
53
  }
52
- }, [mentions, target, value, itemKey, onSubmit]);
54
+ }, [mentions, target, slateValue, itemKey, onSubmit]);
53
55
  const handleChange = useCallback(val => {
54
56
  onChange({
55
57
  key: itemKey,
@@ -116,14 +118,14 @@ function ChatMessageBodyBase({
116
118
  });
117
119
  }, [search]);
118
120
  useEffect(() => {
119
- if (!isEqual(editor.children, value)) {
120
- resetNodes(editor, value);
121
+ if (!isEqual(editor.children, slateValue)) {
122
+ resetNodes(editor, slateValue);
121
123
  }
122
- }, [value, editor]);
124
+ }, [slateValue, editor]);
123
125
  return /*#__PURE__*/_jsxs(_Fragment, {
124
126
  children: [/*#__PURE__*/_jsxs(Slate, {
125
127
  editor: editor,
126
- initialValue: value,
128
+ initialValue: slateValue,
127
129
  onChange: handleChange,
128
130
  children: [/*#__PURE__*/_jsx("div", {
129
131
  "test-id": `chat-item-body-editable-content-${itemKey}`,
package/esm/chat/utils.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Editor, Transforms } from 'slate';
2
+ import cloneDeep from 'lodash-es/cloneDeep';
2
3
  import { CUSTOM_ELEMENT_TYPES } from './constants';
3
4
  export function isMentionElement(type) {
4
5
  return type === CUSTOM_ELEMENT_TYPES.mention;
@@ -26,10 +27,12 @@ export function resetNodes(editor, nodes) {
26
27
  path: [0],
27
28
  node
28
29
  }));
30
+
31
+ // Clone nodes before inserting so multiple editors never share Slate node refs.
29
32
  nodes.forEach((node, i) => editor.apply({
30
33
  type: 'insert_node',
31
34
  path: [i],
32
- node
35
+ node: cloneDeep(node)
33
36
  }));
34
37
  const point = Editor.end(editor, []);
35
38
  Transforms.select(editor, point);
package/esm/index.d.ts CHANGED
@@ -73,6 +73,7 @@ export * from './range-slider';
73
73
  export * from './react-popper';
74
74
  export * from './refresh-button';
75
75
  export * from './scheduler';
76
+ export * from './scoped-theme';
76
77
  export * from './search';
77
78
  export * from './searchable-list';
78
79
  export * from './selectable-tiles';
package/esm/index.js CHANGED
@@ -73,6 +73,7 @@ export * from './range-slider';
73
73
  export * from './react-popper';
74
74
  export * from './refresh-button';
75
75
  export * from './scheduler';
76
+ export * from './scoped-theme';
76
77
  export * from './search';
77
78
  export * from './searchable-list';
78
79
  export * from './selectable-tiles';
@@ -0,0 +1 @@
1
+ export { ScopedTheme, useSyncDesignSystemTheme, syncDesignSystemTheme, } from './scoped-theme';
@@ -0,0 +1 @@
1
+ export { ScopedTheme, useSyncDesignSystemTheme, syncDesignSystemTheme } from './scoped-theme';
@@ -0,0 +1,14 @@
1
+ export declare const defaultThemeMapping: {
2
+ 'midnight-gray': string;
3
+ 'alpine-light': string;
4
+ dark: string;
5
+ light: string;
6
+ };
7
+ export declare const syncDesignSystemTheme: (theme: string, themeMapping?: Record<string, string>) => void;
8
+ export declare const useSyncDesignSystemTheme: (theme: string, themeMapping?: Record<string, string>) => void;
9
+ export declare function ScopedTheme(props: {
10
+ children: React.ReactNode;
11
+ theme: keyof typeof defaultThemeMapping;
12
+ className?: string;
13
+ themeMapping?: Record<string, string>;
14
+ } & React.HTMLAttributes<HTMLDivElement>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,37 @@
1
+ import { useLayoutEffect } from 'react';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ export const defaultThemeMapping = {
4
+ 'midnight-gray': 'midnight-gray',
5
+ 'alpine-light': 'alpine-light',
6
+ dark: 'midnight-gray',
7
+ light: 'alpine-light'
8
+ };
9
+ export const syncDesignSystemTheme = (theme, themeMapping = defaultThemeMapping) => {
10
+ if (theme && theme in themeMapping) {
11
+ for (const container of document.querySelectorAll('[data-ds]')) {
12
+ container.setAttribute('data-theme', themeMapping[theme]);
13
+ }
14
+ }
15
+ };
16
+ export const useSyncDesignSystemTheme = (theme, themeMapping = defaultThemeMapping) => {
17
+ useLayoutEffect(() => {
18
+ syncDesignSystemTheme(theme, themeMapping);
19
+ }, [theme, themeMapping]);
20
+ };
21
+ export function ScopedTheme(props) {
22
+ const {
23
+ children,
24
+ theme,
25
+ className = '',
26
+ themeMapping = defaultThemeMapping,
27
+ ...rest
28
+ } = props;
29
+ const scopedTheme = themeMapping[theme] || theme;
30
+ return /*#__PURE__*/_jsx("div", {
31
+ "data-ds": true,
32
+ "data-theme": scopedTheme,
33
+ className: className,
34
+ ...rest,
35
+ children: children
36
+ });
37
+ }
@@ -1,6 +1,7 @@
1
1
  import React, { useMemo, useContext, useEffect } from 'react';
2
2
  import classnames from 'classnames';
3
3
  import isEqual from 'lodash-es/isEqual';
4
+ import cloneDeep from 'lodash-es/cloneDeep';
4
5
  import { withHistory } from 'slate-history';
5
6
  import { resetNodes } from '../chat';
6
7
  import TextEditorContext from './text-editor-context';
@@ -29,12 +30,19 @@ function EditedTextComponent({
29
30
  Slate
30
31
  } = slateReact;
31
32
  const editor = useMemo(() => withLinks(withHistory(withReact(createEditor()))), []);
33
+
34
+ // Clone the incoming value so this editor instance owns its own Slate node
35
+ // references. slate-dom 0.123+ keys internal WeakMaps by node identity, and
36
+ // sharing node references across editors (e.g. the same value bound to a
37
+ // form's TextEditor and a preview's EditedText at the same time) makes
38
+ // findPath throw "Unable to find the path for Slate node".
39
+ const slateValue = useMemo(() => value ? cloneDeep(value) : value, [value]);
32
40
  useEffect(() => {
33
- if (value && !isEqual(editor.children, value)) {
41
+ if (slateValue && !isEqual(editor.children, slateValue)) {
34
42
  // Update the cached value inside the editor
35
- resetNodes(editor, value);
43
+ resetNodes(editor, slateValue);
36
44
  }
37
- }, [value, editor]);
45
+ }, [slateValue, editor]);
38
46
  const ariaAttrs = useMemo(() => {
39
47
  return {
40
48
  'aria-label': ariaLabel
@@ -45,7 +53,7 @@ function EditedTextComponent({
45
53
  // Slate throws an error when no onChange is given, providing a noop func to avoid issues
46
54
  _jsx(Slate, {
47
55
  editor: editor,
48
- initialValue: value,
56
+ initialValue: slateValue,
49
57
  onChange: () => undefined,
50
58
  children: /*#__PURE__*/_jsx(TextEditorContent, {
51
59
  placeholder: placeholder,
@@ -1,6 +1,7 @@
1
1
  import React, { useMemo, useRef, useContext, useState, useEffect, useCallback } from 'react';
2
2
  import classnames from 'classnames';
3
3
  import isEqual from 'lodash-es/isEqual';
4
+ import cloneDeep from 'lodash-es/cloneDeep';
4
5
  import { withHistory } from 'slate-history';
5
6
  import { ValidityMessages, getErrorAriaAttributes, useDefaultValidationValues } from '../form-field';
6
7
  import { resetNodes, CharactersCounter, withMaxLength } from '../chat';
@@ -71,7 +72,13 @@ function TextEditorComponent({
71
72
  }, [getCharactersCounterString]);
72
73
  const editor = useMemo(() => withMaxLength(maxLength)(withLinks(withHistory(withReact(createEditor())))), [maxLength]);
73
74
  const selection = useRef(null);
74
- const slateValue = value || initialValue || TEXT_EDITOR_DEFAULT_VALUE;
75
+ // Clone the incoming value so this editor instance owns its own Slate node
76
+ // references. slate-dom 0.123+ keys internal WeakMaps by node identity, and
77
+ // sharing the same node references across editors (e.g. several editors
78
+ // falling back to TEXT_EDITOR_DEFAULT_VALUE, or the same parent state being
79
+ // bound to multiple editors at once) makes findPath throw
80
+ // "Unable to find the path for Slate node".
81
+ const slateValue = useMemo(() => cloneDeep(value || initialValue || TEXT_EDITOR_DEFAULT_VALUE), [value, initialValue]);
75
82
  useEffect(() => {
76
83
  if (!isEqual(editor.children, slateValue)) {
77
84
  // Update the cached value inside the editor