@datarobot/design-system 29.6.0 → 29.7.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.
package/cjs/index.d.ts CHANGED
@@ -90,6 +90,7 @@ export * from './table-react';
90
90
  export * from './tabs';
91
91
  export * from './tabular-data-tooltip';
92
92
  export * from './text-editor';
93
+ export * from './text-merge-view';
93
94
  export * from './text-with-hyperlinks';
94
95
  export * from './textarea';
95
96
  export * from './time-from-now';
package/cjs/index.js CHANGED
@@ -1015,6 +1015,17 @@ Object.keys(_textEditor).forEach(function (key) {
1015
1015
  }
1016
1016
  });
1017
1017
  });
1018
+ var _textMergeView = require("./text-merge-view");
1019
+ Object.keys(_textMergeView).forEach(function (key) {
1020
+ if (key === "default" || key === "__esModule") return;
1021
+ if (key in exports && exports[key] === _textMergeView[key]) return;
1022
+ Object.defineProperty(exports, key, {
1023
+ enumerable: true,
1024
+ get: function () {
1025
+ return _textMergeView[key];
1026
+ }
1027
+ });
1028
+ });
1018
1029
  var _textWithHyperlinks = require("./text-with-hyperlinks");
1019
1030
  Object.keys(_textWithHyperlinks).forEach(function (key) {
1020
1031
  if (key === "default" || key === "__esModule") return;
@@ -0,0 +1,2 @@
1
+ import { TextMergeView, type TextMergeProps } from './text-merge-view';
2
+ export { TextMergeView, type TextMergeProps };
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "TextMergeView", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _textMergeView.TextMergeView;
10
+ }
11
+ });
12
+ var _textMergeView = require("./text-merge-view");
@@ -0,0 +1,21 @@
1
+ import './text-merge-view.less';
2
+ export type TextMergeProps = {
3
+ className?: string;
4
+ testId?: string;
5
+ isDarkTheme?: boolean;
6
+ values: {
7
+ left: string;
8
+ right: string;
9
+ };
10
+ viewSettings?: {
11
+ showLineNumbers: boolean;
12
+ highlightActiveLine: boolean;
13
+ };
14
+ };
15
+ /**
16
+ * Merge view for 2 text versions
17
+ * Limited to read-only view.
18
+ * @midnight-gray-supported
19
+ * @alpine-light-supported
20
+ */
21
+ export declare function TextMergeView({ className, testId, isDarkTheme, values, viewSettings, }: TextMergeProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.TextMergeView = TextMergeView;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _classnames = _interopRequireDefault(require("classnames"));
9
+ var _merge = require("@codemirror/merge");
10
+ var _state = require("@codemirror/state");
11
+ var _view = require("@codemirror/view");
12
+ var _useTranslation = require("../hooks/use-translation");
13
+ var _jsxRuntime = require("react/jsx-runtime");
14
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
15
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
16
+ const readOnlyExtensions = [
17
+ // only read-only is supported
18
+ _view.EditorView.editable.of(false), _state.EditorState.readOnly.of(true)];
19
+ const viewSettingsDefault = {
20
+ showLineNumbers: true,
21
+ highlightActiveLine: false
22
+ };
23
+
24
+ /**
25
+ * Merge view for 2 text versions
26
+ * Limited to read-only view.
27
+ * @midnight-gray-supported
28
+ * @alpine-light-supported
29
+ */
30
+ function TextMergeView({
31
+ className,
32
+ testId = 'text-merge-view-container',
33
+ isDarkTheme = true,
34
+ values,
35
+ viewSettings = viewSettingsDefault
36
+ }) {
37
+ const {
38
+ t
39
+ } = (0, _useTranslation.useTranslation)();
40
+ const mergeViewParentRef = (0, _react.useRef)(null);
41
+ const mergeViewRef = (0, _react.useRef)(null);
42
+ const ariaLabelForSection = t('Text merge view - read only');
43
+ const allExtensionsMemo = (0, _react.useMemo)(() => {
44
+ const extentions = [...readOnlyExtensions, _view.EditorView.contentAttributes.of({
45
+ 'aria-label': ariaLabelForSection
46
+ })];
47
+ if (viewSettings.showLineNumbers) {
48
+ extentions.push((0, _view.lineNumbers)());
49
+ }
50
+ if (viewSettings.highlightActiveLine) {
51
+ extentions.push((0, _view.highlightActiveLine)());
52
+ }
53
+ extentions.push(_view.EditorView.theme({}, {
54
+ dark: isDarkTheme
55
+ }));
56
+ return extentions;
57
+ }, [viewSettings, isDarkTheme, ariaLabelForSection]);
58
+ (0, _react.useEffect)(() => {
59
+ return () => {
60
+ mergeViewRef.current?.destroy();
61
+ mergeViewRef.current = null;
62
+ };
63
+ }, []);
64
+ (0, _react.useEffect)(() => {
65
+ mergeViewRef.current = new _merge.MergeView({
66
+ a: {
67
+ doc: values.left,
68
+ extensions: [...allExtensionsMemo]
69
+ },
70
+ b: {
71
+ doc: values.right,
72
+ extensions: [...allExtensionsMemo]
73
+ },
74
+ // @ts-expect-error because parent: Element | DocumentFragment | undefined allows undefined and ref does not allow
75
+ parent: mergeViewParentRef.current
76
+ });
77
+ }, [allExtensionsMemo]);
78
+ (0, _react.useEffect)(() => {
79
+ const mv = mergeViewRef.current;
80
+ if (!mv || !values) {
81
+ return;
82
+ }
83
+ const replaceDoc = (view, text) => {
84
+ const current = view.state.doc.toString();
85
+ if (current === text) {
86
+ return;
87
+ }
88
+ view.dispatch({
89
+ changes: {
90
+ from: 0,
91
+ to: view.state.doc.length,
92
+ insert: text
93
+ }
94
+ });
95
+ };
96
+ // Update only if content changed
97
+ replaceDoc(mv.a, values.left);
98
+ replaceDoc(mv.b, values.right);
99
+ }, [values]);
100
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
101
+ className: (0, _classnames.default)('text-merge-view', className),
102
+ "test-id": testId,
103
+ ref: mergeViewParentRef,
104
+ "aria-label": t('Comparison of two text view'),
105
+ "aria-readonly": true,
106
+ tabIndex: 0,
107
+ role: "textbox"
108
+ });
109
+ }
package/esm/index.d.ts CHANGED
@@ -90,6 +90,7 @@ export * from './table-react';
90
90
  export * from './tabs';
91
91
  export * from './tabular-data-tooltip';
92
92
  export * from './text-editor';
93
+ export * from './text-merge-view';
93
94
  export * from './text-with-hyperlinks';
94
95
  export * from './textarea';
95
96
  export * from './time-from-now';
package/esm/index.js CHANGED
@@ -90,6 +90,7 @@ export * from './table-react';
90
90
  export * from './tabs';
91
91
  export * from './tabular-data-tooltip';
92
92
  export * from './text-editor';
93
+ export * from './text-merge-view';
93
94
  export * from './text-with-hyperlinks';
94
95
  export * from './textarea';
95
96
  export * from './time-from-now';
@@ -0,0 +1,2 @@
1
+ import { TextMergeView, type TextMergeProps } from './text-merge-view';
2
+ export { TextMergeView, type TextMergeProps };
@@ -0,0 +1,2 @@
1
+ import { TextMergeView } from './text-merge-view';
2
+ export { TextMergeView };
@@ -0,0 +1,21 @@
1
+ import './text-merge-view.less';
2
+ export type TextMergeProps = {
3
+ className?: string;
4
+ testId?: string;
5
+ isDarkTheme?: boolean;
6
+ values: {
7
+ left: string;
8
+ right: string;
9
+ };
10
+ viewSettings?: {
11
+ showLineNumbers: boolean;
12
+ highlightActiveLine: boolean;
13
+ };
14
+ };
15
+ /**
16
+ * Merge view for 2 text versions
17
+ * Limited to read-only view.
18
+ * @midnight-gray-supported
19
+ * @alpine-light-supported
20
+ */
21
+ export declare function TextMergeView({ className, testId, isDarkTheme, values, viewSettings, }: TextMergeProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,101 @@
1
+ import React, { useRef, useEffect, useMemo } from 'react';
2
+ import classNames from 'classnames';
3
+ import { MergeView } from '@codemirror/merge';
4
+ import { EditorState } from '@codemirror/state';
5
+ import { lineNumbers, highlightActiveLine, EditorView } from '@codemirror/view';
6
+ import { useTranslation } from '../hooks/use-translation';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ const readOnlyExtensions = [
9
+ // only read-only is supported
10
+ EditorView.editable.of(false), EditorState.readOnly.of(true)];
11
+ const viewSettingsDefault = {
12
+ showLineNumbers: true,
13
+ highlightActiveLine: false
14
+ };
15
+
16
+ /**
17
+ * Merge view for 2 text versions
18
+ * Limited to read-only view.
19
+ * @midnight-gray-supported
20
+ * @alpine-light-supported
21
+ */
22
+ export function TextMergeView({
23
+ className,
24
+ testId = 'text-merge-view-container',
25
+ isDarkTheme = true,
26
+ values,
27
+ viewSettings = viewSettingsDefault
28
+ }) {
29
+ const {
30
+ t
31
+ } = useTranslation();
32
+ const mergeViewParentRef = useRef(null);
33
+ const mergeViewRef = useRef(null);
34
+ const ariaLabelForSection = t('Text merge view - read only');
35
+ const allExtensionsMemo = useMemo(() => {
36
+ const extentions = [...readOnlyExtensions, EditorView.contentAttributes.of({
37
+ 'aria-label': ariaLabelForSection
38
+ })];
39
+ if (viewSettings.showLineNumbers) {
40
+ extentions.push(lineNumbers());
41
+ }
42
+ if (viewSettings.highlightActiveLine) {
43
+ extentions.push(highlightActiveLine());
44
+ }
45
+ extentions.push(EditorView.theme({}, {
46
+ dark: isDarkTheme
47
+ }));
48
+ return extentions;
49
+ }, [viewSettings, isDarkTheme, ariaLabelForSection]);
50
+ useEffect(() => {
51
+ return () => {
52
+ mergeViewRef.current?.destroy();
53
+ mergeViewRef.current = null;
54
+ };
55
+ }, []);
56
+ useEffect(() => {
57
+ mergeViewRef.current = new MergeView({
58
+ a: {
59
+ doc: values.left,
60
+ extensions: [...allExtensionsMemo]
61
+ },
62
+ b: {
63
+ doc: values.right,
64
+ extensions: [...allExtensionsMemo]
65
+ },
66
+ // @ts-expect-error because parent: Element | DocumentFragment | undefined allows undefined and ref does not allow
67
+ parent: mergeViewParentRef.current
68
+ });
69
+ }, [allExtensionsMemo]);
70
+ useEffect(() => {
71
+ const mv = mergeViewRef.current;
72
+ if (!mv || !values) {
73
+ return;
74
+ }
75
+ const replaceDoc = (view, text) => {
76
+ const current = view.state.doc.toString();
77
+ if (current === text) {
78
+ return;
79
+ }
80
+ view.dispatch({
81
+ changes: {
82
+ from: 0,
83
+ to: view.state.doc.length,
84
+ insert: text
85
+ }
86
+ });
87
+ };
88
+ // Update only if content changed
89
+ replaceDoc(mv.a, values.left);
90
+ replaceDoc(mv.b, values.right);
91
+ }, [values]);
92
+ return /*#__PURE__*/_jsx("div", {
93
+ className: classNames('text-merge-view', className),
94
+ "test-id": testId,
95
+ ref: mergeViewParentRef,
96
+ "aria-label": t('Comparison of two text view'),
97
+ "aria-readonly": true,
98
+ tabIndex: 0,
99
+ role: "textbox"
100
+ });
101
+ }