@datarobot/design-system 29.5.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 +1 -0
- package/cjs/index.js +11 -0
- package/cjs/key-value-pairs/key-value-inputs.d.ts +2 -1
- package/cjs/key-value-pairs/key-value-inputs.js +5 -3
- package/cjs/key-value-pairs/key-value-pairs.d.ts +3 -1
- package/cjs/key-value-pairs/key-value-pairs.js +2 -0
- package/cjs/text-merge-view/index.d.ts +2 -0
- package/cjs/text-merge-view/index.js +12 -0
- package/cjs/text-merge-view/text-merge-view.d.ts +21 -0
- package/cjs/text-merge-view/text-merge-view.js +109 -0
- package/esm/index.d.ts +1 -0
- package/esm/index.js +1 -0
- package/esm/key-value-pairs/key-value-inputs.d.ts +2 -1
- package/esm/key-value-pairs/key-value-inputs.js +5 -3
- package/esm/key-value-pairs/key-value-pairs.d.ts +3 -1
- package/esm/key-value-pairs/key-value-pairs.js +2 -0
- package/esm/text-merge-view/index.d.ts +2 -0
- package/esm/text-merge-view/index.js +2 -0
- package/esm/text-merge-view/text-merge-view.d.ts +21 -0
- package/esm/text-merge-view/text-merge-view.js +101 -0
- package/js/bundle/bundle.js +255 -54
- package/js/bundle/bundle.min.js +1 -1
- package/js/bundle/index.d.ts +27 -1
- package/package.json +4 -1
- package/styles/index.css +36 -0
- package/styles/index.min.css +1 -1
- package/styles/themes/alpine-light.css +8 -0
- package/styles/themes/alpine-light.min.css +1 -1
- package/styles/themes/light.css +8 -0
- package/styles/themes/light.min.css +1 -1
- package/styles/themes/midnight-gray.css +8 -0
- package/styles/themes/midnight-gray.min.css +1 -1
- package/text-merge-view/package.json +7 -0
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;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { MouseEvent } from 'react';
|
|
2
|
-
import { Item } from './types';
|
|
2
|
+
import { Item, ValueObject } from './types';
|
|
3
3
|
import { FormFieldValidity } from '../form-field/validity-shape';
|
|
4
4
|
type OnChangeEvent = Item;
|
|
5
5
|
type KeyValueInputsProps = {
|
|
@@ -9,6 +9,7 @@ type KeyValueInputsProps = {
|
|
|
9
9
|
value?: string | number;
|
|
10
10
|
/** True to disable inputs, false to enable inputs */
|
|
11
11
|
isDisabled?: boolean;
|
|
12
|
+
disabledPairs?: ValueObject;
|
|
12
13
|
/** Change handler */
|
|
13
14
|
onChange?: (event: OnChangeEvent) => void;
|
|
14
15
|
/** Delete handler */
|
|
@@ -23,6 +23,7 @@ const KeyValueInputs = exports.KeyValueInputs = /*#__PURE__*/(0, _react.forwardR
|
|
|
23
23
|
name,
|
|
24
24
|
value = '',
|
|
25
25
|
isDisabled = false,
|
|
26
|
+
disabledPairs,
|
|
26
27
|
onChange = () => {},
|
|
27
28
|
onDelete = () => {},
|
|
28
29
|
validity = {},
|
|
@@ -40,6 +41,7 @@ const KeyValueInputs = exports.KeyValueInputs = /*#__PURE__*/(0, _react.forwardR
|
|
|
40
41
|
id,
|
|
41
42
|
validationValues
|
|
42
43
|
});
|
|
44
|
+
const disabled = isDisabled || disabledPairs?.[name] !== undefined && disabledPairs[name] === value;
|
|
43
45
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
|
|
44
46
|
className: "kvp-inputs",
|
|
45
47
|
"test-id": "kvp-inputs",
|
|
@@ -48,7 +50,7 @@ const KeyValueInputs = exports.KeyValueInputs = /*#__PURE__*/(0, _react.forwardR
|
|
|
48
50
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_input.Input, {
|
|
49
51
|
type: _formField.INPUT_TYPES.TEXT,
|
|
50
52
|
value: name,
|
|
51
|
-
isDisabled:
|
|
53
|
+
isDisabled: disabled,
|
|
52
54
|
onChange: ({
|
|
53
55
|
target
|
|
54
56
|
}) => onChange({
|
|
@@ -67,7 +69,7 @@ const KeyValueInputs = exports.KeyValueInputs = /*#__PURE__*/(0, _react.forwardR
|
|
|
67
69
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_input.Input, {
|
|
68
70
|
type: _formField.INPUT_TYPES.TEXT,
|
|
69
71
|
value: value,
|
|
70
|
-
isDisabled:
|
|
72
|
+
isDisabled: disabled,
|
|
71
73
|
onChange: ({
|
|
72
74
|
target
|
|
73
75
|
}) => onChange({
|
|
@@ -85,7 +87,7 @@ const KeyValueInputs = exports.KeyValueInputs = /*#__PURE__*/(0, _react.forwardR
|
|
|
85
87
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_button.Button, {
|
|
86
88
|
accentType: _button.ACCENT_TYPES.ROUND_ICON,
|
|
87
89
|
onClick: onDelete,
|
|
88
|
-
isDisabled:
|
|
90
|
+
isDisabled: disabled,
|
|
89
91
|
testId: "kvp-delete-button",
|
|
90
92
|
"aria-label": deleteKeyValueText,
|
|
91
93
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_fontAwesomeIcon.FontAwesomeIcon, {
|
|
@@ -8,7 +8,9 @@ type KeyValuePairsProps = {
|
|
|
8
8
|
/** Object that represents the key value pairs in this component */
|
|
9
9
|
value: ValueObject;
|
|
10
10
|
className?: string;
|
|
11
|
+
/** whether whole form is disabled */
|
|
11
12
|
isDisabled?: boolean;
|
|
13
|
+
disabledPairs?: ValueObject;
|
|
12
14
|
label?: string;
|
|
13
15
|
/** Label for the key column */
|
|
14
16
|
keyLabel?: string;
|
|
@@ -54,5 +56,5 @@ type KeyValuePairsProps = {
|
|
|
54
56
|
@midnight-gray-supported
|
|
55
57
|
@alpine-light-supported
|
|
56
58
|
*/
|
|
57
|
-
export declare const KeyValuePairs: ({ value, className, label, keyLabel, valueLabel, helperText, placeholder: placeholderParams, isDisabled, onChange, hasWarning, emptyCheck, warningMessage: warningMessageParams, buttonText: buttonTextParams, maxItemsTooltipText: maxItemsTooltipTextParams, emptyItemErrorText: emptyItemErrorTextParams, deleteKeyValueText: deleteKeyValueTextParams, buildDuplicateItemErrorText: buildDuplicateItemErrorTextParams, testId, infoIconProps, onError, maxSize, addButtonAccentType, keyInputAriaLabel: keyInputAriaLabelParams, valueInputAriaLabel: valueInputAriaLabelParams, id, }: KeyValuePairsProps) => import("react/jsx-runtime").JSX.Element;
|
|
59
|
+
export declare const KeyValuePairs: ({ value, className, label, keyLabel, valueLabel, helperText, placeholder: placeholderParams, isDisabled, disabledPairs, onChange, hasWarning, emptyCheck, warningMessage: warningMessageParams, buttonText: buttonTextParams, maxItemsTooltipText: maxItemsTooltipTextParams, emptyItemErrorText: emptyItemErrorTextParams, deleteKeyValueText: deleteKeyValueTextParams, buildDuplicateItemErrorText: buildDuplicateItemErrorTextParams, testId, infoIconProps, onError, maxSize, addButtonAccentType, keyInputAriaLabel: keyInputAriaLabelParams, valueInputAriaLabel: valueInputAriaLabelParams, id, }: KeyValuePairsProps) => import("react/jsx-runtime").JSX.Element;
|
|
58
60
|
export {};
|
|
@@ -65,6 +65,7 @@ const KeyValuePairs = ({
|
|
|
65
65
|
helperText = '',
|
|
66
66
|
placeholder: placeholderParams,
|
|
67
67
|
isDisabled = false,
|
|
68
|
+
disabledPairs,
|
|
68
69
|
onChange = () => {},
|
|
69
70
|
hasWarning = false,
|
|
70
71
|
emptyCheck = false,
|
|
@@ -197,6 +198,7 @@ const KeyValuePairs = ({
|
|
|
197
198
|
name: item.name,
|
|
198
199
|
value: item.value,
|
|
199
200
|
isDisabled: isDisabled,
|
|
201
|
+
disabledPairs: disabledPairs,
|
|
200
202
|
onChange: updatedOption => changeItem(index, updatedOption),
|
|
201
203
|
onDelete: () => removeItem(index),
|
|
202
204
|
deleteKeyValueText: `${deleteKeyValueText} ${paddedIndex}`,
|
|
@@ -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';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { MouseEvent } from 'react';
|
|
2
|
-
import { Item } from './types';
|
|
2
|
+
import { Item, ValueObject } from './types';
|
|
3
3
|
import { FormFieldValidity } from '../form-field/validity-shape';
|
|
4
4
|
type OnChangeEvent = Item;
|
|
5
5
|
type KeyValueInputsProps = {
|
|
@@ -9,6 +9,7 @@ type KeyValueInputsProps = {
|
|
|
9
9
|
value?: string | number;
|
|
10
10
|
/** True to disable inputs, false to enable inputs */
|
|
11
11
|
isDisabled?: boolean;
|
|
12
|
+
disabledPairs?: ValueObject;
|
|
12
13
|
/** Change handler */
|
|
13
14
|
onChange?: (event: OnChangeEvent) => void;
|
|
14
15
|
/** Delete handler */
|
|
@@ -16,6 +16,7 @@ const KeyValueInputs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
16
16
|
name,
|
|
17
17
|
value = '',
|
|
18
18
|
isDisabled = false,
|
|
19
|
+
disabledPairs,
|
|
19
20
|
onChange = () => {},
|
|
20
21
|
onDelete = () => {},
|
|
21
22
|
validity = {},
|
|
@@ -33,6 +34,7 @@ const KeyValueInputs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
33
34
|
id,
|
|
34
35
|
validationValues
|
|
35
36
|
});
|
|
37
|
+
const disabled = isDisabled || disabledPairs?.[name] !== undefined && disabledPairs[name] === value;
|
|
36
38
|
return /*#__PURE__*/_jsxs("div", {
|
|
37
39
|
className: "kvp-inputs",
|
|
38
40
|
"test-id": "kvp-inputs",
|
|
@@ -41,7 +43,7 @@ const KeyValueInputs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
41
43
|
children: /*#__PURE__*/_jsx(Input, {
|
|
42
44
|
type: INPUT_TYPES.TEXT,
|
|
43
45
|
value: name,
|
|
44
|
-
isDisabled:
|
|
46
|
+
isDisabled: disabled,
|
|
45
47
|
onChange: ({
|
|
46
48
|
target
|
|
47
49
|
}) => onChange({
|
|
@@ -60,7 +62,7 @@ const KeyValueInputs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
60
62
|
children: /*#__PURE__*/_jsx(Input, {
|
|
61
63
|
type: INPUT_TYPES.TEXT,
|
|
62
64
|
value: value,
|
|
63
|
-
isDisabled:
|
|
65
|
+
isDisabled: disabled,
|
|
64
66
|
onChange: ({
|
|
65
67
|
target
|
|
66
68
|
}) => onChange({
|
|
@@ -78,7 +80,7 @@ const KeyValueInputs = /*#__PURE__*/forwardRef((props, ref) => {
|
|
|
78
80
|
children: /*#__PURE__*/_jsx(Button, {
|
|
79
81
|
accentType: ACCENT_TYPES.ROUND_ICON,
|
|
80
82
|
onClick: onDelete,
|
|
81
|
-
isDisabled:
|
|
83
|
+
isDisabled: disabled,
|
|
82
84
|
testId: "kvp-delete-button",
|
|
83
85
|
"aria-label": deleteKeyValueText,
|
|
84
86
|
children: /*#__PURE__*/_jsx(FontAwesomeIcon, {
|
|
@@ -8,7 +8,9 @@ type KeyValuePairsProps = {
|
|
|
8
8
|
/** Object that represents the key value pairs in this component */
|
|
9
9
|
value: ValueObject;
|
|
10
10
|
className?: string;
|
|
11
|
+
/** whether whole form is disabled */
|
|
11
12
|
isDisabled?: boolean;
|
|
13
|
+
disabledPairs?: ValueObject;
|
|
12
14
|
label?: string;
|
|
13
15
|
/** Label for the key column */
|
|
14
16
|
keyLabel?: string;
|
|
@@ -54,5 +56,5 @@ type KeyValuePairsProps = {
|
|
|
54
56
|
@midnight-gray-supported
|
|
55
57
|
@alpine-light-supported
|
|
56
58
|
*/
|
|
57
|
-
export declare const KeyValuePairs: ({ value, className, label, keyLabel, valueLabel, helperText, placeholder: placeholderParams, isDisabled, onChange, hasWarning, emptyCheck, warningMessage: warningMessageParams, buttonText: buttonTextParams, maxItemsTooltipText: maxItemsTooltipTextParams, emptyItemErrorText: emptyItemErrorTextParams, deleteKeyValueText: deleteKeyValueTextParams, buildDuplicateItemErrorText: buildDuplicateItemErrorTextParams, testId, infoIconProps, onError, maxSize, addButtonAccentType, keyInputAriaLabel: keyInputAriaLabelParams, valueInputAriaLabel: valueInputAriaLabelParams, id, }: KeyValuePairsProps) => import("react/jsx-runtime").JSX.Element;
|
|
59
|
+
export declare const KeyValuePairs: ({ value, className, label, keyLabel, valueLabel, helperText, placeholder: placeholderParams, isDisabled, disabledPairs, onChange, hasWarning, emptyCheck, warningMessage: warningMessageParams, buttonText: buttonTextParams, maxItemsTooltipText: maxItemsTooltipTextParams, emptyItemErrorText: emptyItemErrorTextParams, deleteKeyValueText: deleteKeyValueTextParams, buildDuplicateItemErrorText: buildDuplicateItemErrorTextParams, testId, infoIconProps, onError, maxSize, addButtonAccentType, keyInputAriaLabel: keyInputAriaLabelParams, valueInputAriaLabel: valueInputAriaLabelParams, id, }: KeyValuePairsProps) => import("react/jsx-runtime").JSX.Element;
|
|
58
60
|
export {};
|
|
@@ -57,6 +57,7 @@ export const KeyValuePairs = ({
|
|
|
57
57
|
helperText = '',
|
|
58
58
|
placeholder: placeholderParams,
|
|
59
59
|
isDisabled = false,
|
|
60
|
+
disabledPairs,
|
|
60
61
|
onChange = () => {},
|
|
61
62
|
hasWarning = false,
|
|
62
63
|
emptyCheck = false,
|
|
@@ -189,6 +190,7 @@ export const KeyValuePairs = ({
|
|
|
189
190
|
name: item.name,
|
|
190
191
|
value: item.value,
|
|
191
192
|
isDisabled: isDisabled,
|
|
193
|
+
disabledPairs: disabledPairs,
|
|
192
194
|
onChange: updatedOption => changeItem(index, updatedOption),
|
|
193
195
|
onDelete: () => removeItem(index),
|
|
194
196
|
deleteKeyValueText: `${deleteKeyValueText} ${paddedIndex}`,
|
|
@@ -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
|
+
}
|