@synerise/ds-code-area 0.0.1

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/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Synerise
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ ---
2
+ id: code-area
3
+ title: CodeArea
4
+ ---
5
+
6
+ CodeArea UI Component
7
+
8
+ ## Installation
9
+
10
+ ```
11
+ npm i @synerise/ds-code-area
12
+ or
13
+ yarn add @synerise/ds-code-area
14
+ ```
15
+
16
+ To have syntax validation you need to follow the integration instructions here:
17
+ https://github.com/microsoft/monaco-editor/blob/main/docs/integrate-esm.md
18
+
19
+ ## Usage
20
+
21
+ ```js
22
+ import CodeArea from '@synerise/ds-code-area'
23
+
24
+ type SupportedSyntaxes = 'json' | 'javascript';
25
+ const syntaxOptions = [
26
+ {
27
+ language: 'json',
28
+ label: 'JSON'
29
+ },
30
+ {
31
+ language: 'javascript',
32
+ label: 'Javascript'
33
+ }
34
+ ];
35
+
36
+ <CodeArea<SupportedSyntaxes>
37
+ syntaxOptions={syntaxOptions}
38
+ onSyntaxChange={ /* current syntax handler */ }
39
+ onChange={ /* current value handler */ }
40
+ />
41
+
42
+ ```
43
+
44
+
45
+ ## API
46
+
47
+ | Property | Description | Type | Default |
48
+ | --------------------------- | -------------------------------------------------------------- | ------------------------------------- | -------------- |
49
+ | label | label above editor | `ReactNode` | - |
50
+ | description | description below editor | `ReactNode` | - |
51
+ | counter | limit character count | `{ limit: number; placement?: 'bottom' &#124; 'top'; }` | - |
52
+ | errorText | error message to show below editor (also adds "error styles") | `ReactNode` | - |
53
+ | syntaxOptions | array of available syntaxes | `CodeAreaSyntaxOption[]` | - |
54
+ | currentSyntax | current syntax of editor value | `CodeAreaSyntax` | - |
55
+ | allowFullscreen | renders fullscreen mode button | `boolean` | - |
56
+ | tooltip | tooltip text displayed next to label | `ReactNode` | - |
57
+ | tooltipProps | tooltip properties (see @synerise/ds-tooltip) | `TooltipExtendedProps & TooltipProps` | - |
58
+ | style | custom style added to outermost div | `CSSProperties` | - |
59
+ | className | class name to add to outermost div | `string` | - |
60
+ | renderFooterContent | renders custom content in footer bar | `(CodeAreaStateProps) => ReactNode` | - |
61
+ | renderAdditionalDescription | renders custom content above description | `(CodeAreaStateProps) => ReactNode` | - |
62
+ | onFullscreenChange | triggered when fullscreen is toggled on/off | `(isFullscreen: boolean) => void` | - |
63
+ | onSyntaxChange | triggered when user switches syntax | `(newSyntax: SyntaxName) => void` | - |
64
+ | texts | customise displayed texts | `CodeAreaTexts` | - |
65
+
66
+ ### CodeAreaTexts
67
+
68
+ Customisable user-facing labels
69
+
70
+ | Property | Description | Type | Default |
71
+ | ------------------ | --------------------------------------------------- | ------------- | -------------- |
72
+ | fullscreen | fullscreen button label | `ReactNode` | - |
73
+ | closeFullscreen | close fullscreen button label | `ReactNode` | - |
74
+ | fullscreenTitle | used in fullscreen mode if no `label` prop provided | `ReactNode` | - |
75
+
76
+
77
+
78
+ ### CodeAreaSyntaxOption
79
+
80
+ At least one syntax option must be provided.
81
+
82
+ | Property | Description | Type | Default |
83
+ | ------------------ | ---------------------------------------------- | ---------------- | -------------- |
84
+ | language | language of editor `value` | `CodeAreaSyntax` | - |
85
+ | label | optional user-friendly display name | `string` | - |
86
+
87
+ ### CodeAreaSyntax
88
+
89
+ See list of languages supported by monaco here: https://github.com/microsoft/monaco-editor/tree/main/src/basic-languages.
90
+
91
+ ```js
92
+ CodeAreaSyntax = 'json' | 'html' | 'css' | 'typescript' | 'javascript' | string;
93
+ ```
94
+
95
+ ### CodeAreaStateProps
96
+
97
+ Props passed to `renderAdditionalDescription()` and `renderFooterContent()`.
98
+
99
+ | Property | Description | Type | Default |
100
+ | ------------------ | -------------------------------------------- | ------------- | -------------- |
101
+ | isFullscreen | is fullscreen mode on or off | `boolean` | - |
102
+ | count | current character count | `number` | - |
103
+ | isValid | is editor value valid | `boolean` | - |
@@ -0,0 +1,3 @@
1
+ import { CodeAreaProps } from './CodeArea.types';
2
+ declare const CodeArea: ({ label, description, counter, errorText, syntaxOptions, currentSyntax, allowFullscreen, renderFooterContent, renderAdditionalDescription, tooltip, tooltipProps, style, className, texts, onChange, onFullscreenChange, onSyntaxChange, value, ...monacoProps }: CodeAreaProps) => JSX.Element;
3
+ export default CodeArea;
@@ -0,0 +1,226 @@
1
+ var _excluded = ["label", "description", "counter", "errorText", "syntaxOptions", "currentSyntax", "allowFullscreen", "renderFooterContent", "renderAdditionalDescription", "tooltip", "tooltipProps", "style", "className", "texts", "onChange", "onFullscreenChange", "onSyntaxChange", "value"];
2
+
3
+ function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
4
+
5
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
6
+
7
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
8
+
9
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
10
+
11
+ function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
12
+
13
+ import React, { useState, useMemo, useRef, useEffect } from 'react';
14
+ import MonacoEditor from 'react-monaco-editor';
15
+ import { InlineSelect } from '@synerise/ds-inline-edit';
16
+ import { Label } from '@synerise/ds-input';
17
+ import { useResizeObserver } from '@synerise/ds-utils';
18
+ import * as S from './CodeArea.styles';
19
+ import { FullscreenHeader, ContentBelow, ContentAbove, BottomBar } from './components';
20
+ import { getDefaultTexts, getCharCount, calculateRequiredSpace } from './utils';
21
+ import { MONACO_DEFAULT_OPTIONS, TRIGGER_SOURCE, DS_MONACO_THEME, DS_MONACO_THEME_NAME } from './constants';
22
+
23
+ var CodeArea = function CodeArea(_ref) {
24
+ var label = _ref.label,
25
+ description = _ref.description,
26
+ counter = _ref.counter,
27
+ errorText = _ref.errorText,
28
+ syntaxOptions = _ref.syntaxOptions,
29
+ currentSyntax = _ref.currentSyntax,
30
+ allowFullscreen = _ref.allowFullscreen,
31
+ renderFooterContent = _ref.renderFooterContent,
32
+ renderAdditionalDescription = _ref.renderAdditionalDescription,
33
+ tooltip = _ref.tooltip,
34
+ tooltipProps = _ref.tooltipProps,
35
+ style = _ref.style,
36
+ className = _ref.className,
37
+ texts = _ref.texts,
38
+ onChange = _ref.onChange,
39
+ onFullscreenChange = _ref.onFullscreenChange,
40
+ onSyntaxChange = _ref.onSyntaxChange,
41
+ value = _ref.value,
42
+ monacoProps = _objectWithoutPropertiesLoose(_ref, _excluded);
43
+
44
+ var _useState = useState(true),
45
+ isValid = _useState[0],
46
+ setIsValid = _useState[1];
47
+
48
+ var _useState2 = useState(false),
49
+ isFullscreen = _useState2[0],
50
+ setIsFullscreen = _useState2[1];
51
+
52
+ var editorRef = useRef(null);
53
+ var monacoRef = useRef(null);
54
+ var wrapperRef = useRef(null);
55
+ var contentBelowRef = useRef(null);
56
+
57
+ var _useResizeObserver = useResizeObserver(wrapperRef),
58
+ height = _useResizeObserver.height,
59
+ width = _useResizeObserver.width;
60
+
61
+ var _useResizeObserver2 = useResizeObserver(contentBelowRef),
62
+ contentBelowHeight = _useResizeObserver2.height;
63
+
64
+ var count = getCharCount(value, counter == null ? void 0 : counter.limit);
65
+ var allTexts = getDefaultTexts(texts);
66
+
67
+ var toggleFullscreen = function toggleFullscreen() {
68
+ setIsFullscreen(!isFullscreen);
69
+ onFullscreenChange && onFullscreenChange(isFullscreen);
70
+ };
71
+
72
+ var editorWillMount = monacoProps.editorWillMount,
73
+ editorDidMount = monacoProps.editorDidMount,
74
+ options = monacoProps.options;
75
+
76
+ var combinedOptions = _objectSpread({}, MONACO_DEFAULT_OPTIONS, {}, options);
77
+
78
+ var handleEditorWillMount = function handleEditorWillMount(monacoInstance) {
79
+ monacoRef.current = monacoInstance;
80
+ monacoInstance.editor.defineTheme(DS_MONACO_THEME_NAME, DS_MONACO_THEME);
81
+ monacoInstance.editor.setTheme(DS_MONACO_THEME_NAME);
82
+ monacoInstance.editor.onDidChangeMarkers(function () {
83
+ var markers = monacoInstance.editor.getModelMarkers({});
84
+ setIsValid(!markers.length);
85
+ });
86
+ editorWillMount && editorWillMount(monacoInstance);
87
+ };
88
+
89
+ var handleEditorDidMount = function handleEditorDidMount(editor, monacoInstance) {
90
+ editorRef.current = editor;
91
+ editorDidMount && editorDidMount(editor, monacoInstance);
92
+ };
93
+
94
+ var handleChange = function handleChange(newValue, event) {
95
+ if (counter != null && counter.limit && newValue.length > (counter == null ? void 0 : counter.limit)) {
96
+ editorRef.current && editorRef.current.trigger(TRIGGER_SOURCE, 'undo', null);
97
+ return;
98
+ }
99
+
100
+ if (editorRef.current) {
101
+ editorRef.current.pushUndoStop();
102
+ }
103
+
104
+ onChange && onChange(newValue, event);
105
+ };
106
+
107
+ var labelWithTooltip = label && /*#__PURE__*/React.createElement(Label, {
108
+ label: label,
109
+ tooltip: tooltip,
110
+ tooltipConfig: (tooltip || tooltipProps) && _objectSpread({}, tooltipProps, {
111
+ placement: isFullscreen ? 'right' : undefined,
112
+ title: tooltip
113
+ })
114
+ });
115
+
116
+ var renderCounter = function renderCounter(placement) {
117
+ return (counter == null ? void 0 : counter.limit) && (!placement || (counter == null ? void 0 : counter.placement) === placement) && /*#__PURE__*/React.createElement(S.Counter, null, count, " / ", counter.limit);
118
+ };
119
+
120
+ useEffect(function () {
121
+ setIsValid(!errorText);
122
+ }, [errorText]);
123
+ useEffect(function () {
124
+ if (editorRef.current) {
125
+ var _editorRef$current, _monacoRef$current;
126
+
127
+ var currentModel = (_editorRef$current = editorRef.current) == null ? void 0 : _editorRef$current.getModel(); // eslint-disable-next-line no-unused-expressions
128
+
129
+ currentModel && ((_monacoRef$current = monacoRef.current) == null ? void 0 : _monacoRef$current.editor.setModelLanguage(currentModel, currentSyntax));
130
+ }
131
+ }, [currentSyntax]);
132
+
133
+ var _useMemo = useMemo(function () {
134
+ var source = syntaxOptions == null ? void 0 : syntaxOptions.map(function (item) {
135
+ var itemLabel = item.label,
136
+ language = item.language;
137
+ return {
138
+ key: language,
139
+ text: itemLabel || language,
140
+ onSelect: function onSelect() {
141
+ onSyntaxChange && onSyntaxChange(language);
142
+ }
143
+ };
144
+ });
145
+ var currentItem = syntaxOptions == null ? void 0 : syntaxOptions.find(function (item) {
146
+ return item.language === currentSyntax;
147
+ });
148
+ return {
149
+ syntaxDataSource: source,
150
+ currentSyntaxItem: currentItem || {
151
+ language: currentSyntax
152
+ }
153
+ };
154
+ }, [currentSyntax, onSyntaxChange, syntaxOptions]),
155
+ syntaxDataSource = _useMemo.syntaxDataSource,
156
+ currentSyntaxItem = _useMemo.currentSyntaxItem;
157
+
158
+ var syntaxSelect = useMemo(function () {
159
+ return syntaxDataSource && syntaxDataSource.length > 1 ? /*#__PURE__*/React.createElement(InlineSelect, {
160
+ size: "small",
161
+ expanded: false,
162
+ input: {
163
+ name: 'syntax-select',
164
+ value: currentSyntaxItem.label || currentSyntaxItem.language
165
+ },
166
+ initialValue: currentSyntaxItem.label || currentSyntaxItem.language,
167
+ dataSource: syntaxDataSource
168
+ }) : /*#__PURE__*/React.createElement(S.SyntaxTitle, {
169
+ size: "small"
170
+ }, currentSyntaxItem.label || currentSyntaxItem.language);
171
+ }, [currentSyntaxItem, syntaxDataSource]);
172
+ var customFooterContent = renderFooterContent && /*#__PURE__*/React.createElement(S.BottomBarElement, null, renderFooterContent({
173
+ isFullscreen: isFullscreen,
174
+ count: count,
175
+ isValid: isValid
176
+ }));
177
+ var additionalDescription = renderAdditionalDescription && /*#__PURE__*/React.createElement(S.AdditionalDescription, null, renderAdditionalDescription({
178
+ isFullscreen: isFullscreen,
179
+ count: count,
180
+ isValid: isValid
181
+ }));
182
+ var isBottomBarShowing = Boolean(syntaxSelect || allowFullscreen && !isFullscreen || customFooterContent);
183
+ var requiredSpace = isFullscreen ? calculateRequiredSpace(isBottomBarShowing, contentBelowHeight) : 0;
184
+ return /*#__PURE__*/React.createElement(S.CodeAreaWrapper, {
185
+ requiredSpace: requiredSpace,
186
+ className: className,
187
+ style: style,
188
+ isFullscreen: isFullscreen
189
+ }, isFullscreen && /*#__PURE__*/React.createElement(FullscreenHeader, {
190
+ label: labelWithTooltip,
191
+ texts: allTexts,
192
+ onClick: toggleFullscreen
193
+ }), !isFullscreen && /*#__PURE__*/React.createElement(ContentAbove, {
194
+ label: labelWithTooltip,
195
+ counter: renderCounter('top')
196
+ }), /*#__PURE__*/React.createElement(S.CodeAreaContent, null, /*#__PURE__*/React.createElement(S.EditorWrapper, {
197
+ hasError: Boolean(errorText)
198
+ }, /*#__PURE__*/React.createElement(S.EditorInnerWrapper, {
199
+ ref: wrapperRef
200
+ }, /*#__PURE__*/React.createElement(MonacoEditor, _extends({
201
+ theme: DS_MONACO_THEME_NAME,
202
+ width: width,
203
+ height: height
204
+ }, monacoProps, {
205
+ options: combinedOptions,
206
+ value: value,
207
+ onChange: handleChange,
208
+ editorDidMount: handleEditorDidMount,
209
+ editorWillMount: handleEditorWillMount,
210
+ language: currentSyntax
211
+ }))), isBottomBarShowing && /*#__PURE__*/React.createElement(BottomBar, {
212
+ texts: allTexts,
213
+ syntaxSelect: syntaxSelect,
214
+ allowFullscreen: allowFullscreen && !isFullscreen,
215
+ toggleFullscreen: toggleFullscreen,
216
+ customFooterContent: customFooterContent
217
+ })), /*#__PURE__*/React.createElement(ContentBelow, {
218
+ ref: contentBelowRef,
219
+ errorText: errorText,
220
+ description: description,
221
+ additionalDescription: additionalDescription,
222
+ counter: renderCounter(!isFullscreen ? 'bottom' : undefined)
223
+ })));
224
+ };
225
+
226
+ export default CodeArea;
@@ -0,0 +1,29 @@
1
+ /// <reference types="react" />
2
+ export declare const EditorInnerWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
3
+ export declare const CodeAreaContent: import("styled-components").StyledComponent<"div", any, {}, never>;
4
+ export declare const EditorWrapper: import("styled-components").StyledComponent<"div", any, {
5
+ hasError: boolean;
6
+ }, never>;
7
+ export declare const FullscreenHeaderTitle: import("styled-components").StyledComponent<({ level, withoutMargin, children, className, ellipsis, ...antdProps }: import("@synerise/ds-typography/dist/Title.types").Props) => JSX.Element, any, {}, never>;
8
+ export declare const FullscreenHeader: import("styled-components").StyledComponent<"div", any, {}, never>;
9
+ export declare const CodeAreaWrapper: import("styled-components").StyledComponent<"div", any, {
10
+ isFullscreen: boolean;
11
+ requiredSpace: number;
12
+ }, never>;
13
+ export declare const AdditionalDescription: import("styled-components").StyledComponent<"div", any, {}, never>;
14
+ export declare const ContentBelow: import("styled-components").StyledComponent<"div", any, {}, never>;
15
+ export declare const ContentAbove: import("styled-components").StyledComponent<"div", any, {}, never>;
16
+ export declare const SyntaxTitle: import("styled-components").StyledComponent<({ size, className, children, ellipsis }: {
17
+ size?: import("@synerise/ds-typography").TextSize | undefined;
18
+ ellipsis?: import("@synerise/ds-typography/dist/Ellipsis").EllipsisProps | undefined;
19
+ children?: import("react").ReactNode;
20
+ className?: string | undefined;
21
+ }) => JSX.Element, any, {}, never>;
22
+ export declare const BottomBar: import("styled-components").StyledComponent<"div", any, {}, never>;
23
+ export declare const LeftSide: import("styled-components").StyledComponent<"div", any, {}, never>;
24
+ export declare const RightSide: import("styled-components").StyledComponent<"div", any, {}, never>;
25
+ export declare const SyntaxSelect: import("styled-components").StyledComponent<"div", any, {}, never>;
26
+ export declare const BottomBarElement: import("styled-components").StyledComponent<"div", any, {}, never>;
27
+ export declare const Description: import("styled-components").StyledComponent<"div", any, {}, never>;
28
+ export declare const Counter: import("styled-components").StyledComponent<"div", any, {}, never>;
29
+ export declare const ErrorText: import("styled-components").StyledComponent<"div", any, {}, never>;
@@ -0,0 +1,92 @@
1
+ import styled, { css } from 'styled-components';
2
+ import { Title, Text } from '@synerise/ds-typography';
3
+ var FlexRow = styled.div.withConfig({
4
+ displayName: "CodeAreastyles__FlexRow",
5
+ componentId: "svoej2-0"
6
+ })(["display:flex;justify-content:space-between;align-items:center;"]);
7
+ export var EditorInnerWrapper = styled.div.withConfig({
8
+ displayName: "CodeAreastyles__EditorInnerWrapper",
9
+ componentId: "svoej2-1"
10
+ })(["height:295px;"]);
11
+ export var CodeAreaContent = styled.div.withConfig({
12
+ displayName: "CodeAreastyles__CodeAreaContent",
13
+ componentId: "svoej2-2"
14
+ })([""]);
15
+ export var EditorWrapper = styled.div.withConfig({
16
+ displayName: "CodeAreastyles__EditorWrapper",
17
+ componentId: "svoej2-3"
18
+ })(["border:solid 1px ", ";border-radius:3px;padding-top:12px;", ";canvas{opacity:0;}"], function (props) {
19
+ return props.hasError ? props.theme.palette['red-600'] : props.theme.palette['grey-200'];
20
+ }, function (props) {
21
+ return props.hasError && css(["background:", ";box-shadow:inset 0 0 0 1px ", ";"], props.theme.palette['red-050'], props.theme.palette['red-600']);
22
+ });
23
+ export var FullscreenHeaderTitle = styled(Title).withConfig({
24
+ displayName: "CodeAreastyles__FullscreenHeaderTitle",
25
+ componentId: "svoej2-4"
26
+ })(["display:flex;gap:16px;align-items:center;margin-bottom:0;"]);
27
+ export var FullscreenHeader = styled(FlexRow).withConfig({
28
+ displayName: "CodeAreastyles__FullscreenHeader",
29
+ componentId: "svoej2-5"
30
+ })(["padding:16px 24px;"]);
31
+ export var CodeAreaWrapper = styled.div.withConfig({
32
+ displayName: "CodeAreastyles__CodeAreaWrapper",
33
+ componentId: "svoej2-6"
34
+ })(["", ""], function (props) {
35
+ if (props.isFullscreen) {
36
+ return css(["position:fixed;width:100vw;height:100vh;z-index:999;left:0;top:0;background:", ";", "{height:calc(100vh - ", "px);}", "{margin:0 24px;}"], props.theme.palette.white, EditorInnerWrapper, props.requiredSpace, CodeAreaContent);
37
+ }
38
+
39
+ return css(["margin-bottom:12px;"]);
40
+ });
41
+ export var AdditionalDescription = styled.div.withConfig({
42
+ displayName: "CodeAreastyles__AdditionalDescription",
43
+ componentId: "svoej2-7"
44
+ })(["margin-bottom:8px;"]);
45
+ export var ContentBelow = styled(FlexRow).withConfig({
46
+ displayName: "CodeAreastyles__ContentBelow",
47
+ componentId: "svoej2-8"
48
+ })(["margin-top:8px;align-items:flex-start;"]);
49
+ export var ContentAbove = styled(FlexRow).withConfig({
50
+ displayName: "CodeAreastyles__ContentAbove",
51
+ componentId: "svoej2-9"
52
+ })(["margin-bottom:8px;"]);
53
+ export var SyntaxTitle = styled(Text).withConfig({
54
+ displayName: "CodeAreastyles__SyntaxTitle",
55
+ componentId: "svoej2-10"
56
+ })([""]);
57
+ export var BottomBar = styled(FlexRow).withConfig({
58
+ displayName: "CodeAreastyles__BottomBar",
59
+ componentId: "svoej2-11"
60
+ })(["border-top:solid 1px ", ";padding:8px;"], function (props) {
61
+ return props.theme.palette['grey-200'];
62
+ });
63
+ export var LeftSide = styled.div.withConfig({
64
+ displayName: "CodeAreastyles__LeftSide",
65
+ componentId: "svoej2-12"
66
+ })([""]);
67
+ export var RightSide = styled.div.withConfig({
68
+ displayName: "CodeAreastyles__RightSide",
69
+ componentId: "svoej2-13"
70
+ })(["margin-left:auto;display:flex;gap:8px;"]);
71
+ export var SyntaxSelect = styled(LeftSide).withConfig({
72
+ displayName: "CodeAreastyles__SyntaxSelect",
73
+ componentId: "svoej2-14"
74
+ })(["padding-left:8px;"]);
75
+ export var BottomBarElement = styled.div.withConfig({
76
+ displayName: "CodeAreastyles__BottomBarElement",
77
+ componentId: "svoej2-15"
78
+ })([""]);
79
+ export var Description = styled.div.withConfig({
80
+ displayName: "CodeAreastyles__Description",
81
+ componentId: "svoej2-16"
82
+ })([""]);
83
+ export var Counter = styled.div.withConfig({
84
+ displayName: "CodeAreastyles__Counter",
85
+ componentId: "svoej2-17"
86
+ })(["font-weight:500;"]);
87
+ export var ErrorText = styled.div.withConfig({
88
+ displayName: "CodeAreastyles__ErrorText",
89
+ componentId: "svoej2-18"
90
+ })(["color:", ";margin-bottom:4px;"], function (props) {
91
+ return props.theme.palette['red-600'];
92
+ });
@@ -0,0 +1,43 @@
1
+ import type { CSSProperties, ReactNode } from 'react';
2
+ import { MonacoEditorProps } from 'react-monaco-editor';
3
+ import { TooltipProps } from 'antd/lib/tooltip';
4
+ import TooltipExtendedProps from '@synerise/ds-tooltip/dist/Tooltip.types';
5
+ export type CodeAreaSyntax = 'json' | 'html' | 'css' | 'typescript' | 'javascript' | string;
6
+ export type CodeAreaSyntaxOption<SyntaxName extends CodeAreaSyntax = CodeAreaSyntax> = {
7
+ language: SyntaxName;
8
+ label?: string;
9
+ };
10
+ export type CodeAreaTexts = {
11
+ fullscreen: ReactNode;
12
+ closeFullscreen: ReactNode;
13
+ fullscreenTitle: ReactNode;
14
+ };
15
+ export type CodeAreaProps<SyntaxName extends CodeAreaSyntax = CodeAreaSyntax> = MonacoEditorProps & {
16
+ label?: ReactNode;
17
+ description?: ReactNode;
18
+ texts?: Partial<CodeAreaTexts>;
19
+ counter?: {
20
+ limit: number;
21
+ placement?: 'bottom' | 'top';
22
+ };
23
+ errorText?: ReactNode;
24
+ syntaxOptions?: CodeAreaSyntaxOption<SyntaxName>[];
25
+ currentSyntax: SyntaxName;
26
+ allowFullscreen?: boolean;
27
+ tooltip?: ReactNode;
28
+ tooltipProps?: TooltipExtendedProps & TooltipProps;
29
+ style?: CSSProperties;
30
+ className?: string;
31
+ renderFooterContent?: (props: {
32
+ isFullscreen?: boolean;
33
+ count?: number;
34
+ isValid?: boolean;
35
+ }) => ReactNode;
36
+ renderAdditionalDescription?: (props: {
37
+ isFullscreen?: boolean;
38
+ count?: number;
39
+ isValid?: boolean;
40
+ }) => ReactNode;
41
+ onFullscreenChange?: (isFullscreen: boolean) => void;
42
+ onSyntaxChange?: (newSyntax: SyntaxName) => void;
43
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { ReactNode } from 'react';
2
+ import { CodeAreaTexts } from '../CodeArea.types';
3
+ type BottomBarProps = {
4
+ texts: CodeAreaTexts;
5
+ allowFullscreen?: boolean;
6
+ syntaxSelect?: ReactNode;
7
+ customFooterContent?: ReactNode;
8
+ toggleFullscreen?: () => void;
9
+ };
10
+ export declare const BottomBar: ({ texts, syntaxSelect, customFooterContent, allowFullscreen, toggleFullscreen, }: BottomBarProps) => JSX.Element;
11
+ export {};
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import Button from '@synerise/ds-button';
3
+ import Icon, { FullScreenM } from '@synerise/ds-icon';
4
+ import * as S from '../CodeArea.styles';
5
+ export var BottomBar = function BottomBar(_ref) {
6
+ var texts = _ref.texts,
7
+ syntaxSelect = _ref.syntaxSelect,
8
+ customFooterContent = _ref.customFooterContent,
9
+ allowFullscreen = _ref.allowFullscreen,
10
+ toggleFullscreen = _ref.toggleFullscreen;
11
+ var fullscreenButton = allowFullscreen && /*#__PURE__*/React.createElement(Button, {
12
+ type: "ghost",
13
+ mode: "icon-label",
14
+ icon: /*#__PURE__*/React.createElement(Icon, {
15
+ component: /*#__PURE__*/React.createElement(FullScreenM, null)
16
+ }),
17
+ onClick: toggleFullscreen
18
+ }, texts.fullscreen);
19
+ return /*#__PURE__*/React.createElement(S.BottomBar, {
20
+ "data-testid": "code-area-bottombar"
21
+ }, syntaxSelect && /*#__PURE__*/React.createElement(S.SyntaxSelect, {
22
+ "data-testid": "code-area-syntaxoptions"
23
+ }, syntaxSelect), (customFooterContent || fullscreenButton) && /*#__PURE__*/React.createElement(S.RightSide, null, customFooterContent, fullscreenButton));
24
+ };
@@ -0,0 +1,7 @@
1
+ import { ReactNode } from 'react';
2
+ type ContentAboveProps = {
3
+ label?: ReactNode;
4
+ counter?: ReactNode;
5
+ };
6
+ export declare const ContentAbove: ({ label, counter }: ContentAboveProps) => JSX.Element;
7
+ export {};
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import * as S from '../CodeArea.styles';
3
+ export var ContentAbove = function ContentAbove(_ref) {
4
+ var label = _ref.label,
5
+ counter = _ref.counter;
6
+ return /*#__PURE__*/React.createElement(S.ContentAbove, null, label && /*#__PURE__*/React.createElement(S.LeftSide, {
7
+ "data-testid": "code-area-label"
8
+ }, label), counter && /*#__PURE__*/React.createElement(S.RightSide, {
9
+ "data-testid": "code-area-counter-top"
10
+ }, counter));
11
+ };
@@ -0,0 +1,6 @@
1
+ import React, { ReactNode } from 'react';
2
+ import { CodeAreaProps } from '../CodeArea.types';
3
+ export declare const ContentBelow: React.ForwardRefExoticComponent<Pick<CodeAreaProps<string>, "description" | "errorText"> & {
4
+ additionalDescription?: ReactNode;
5
+ counter?: ReactNode;
6
+ } & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,18 @@
1
+ import React, { forwardRef } from 'react';
2
+ import * as S from '../CodeArea.styles';
3
+ export var ContentBelow = forwardRef(function (_ref, ref) {
4
+ var description = _ref.description,
5
+ additionalDescription = _ref.additionalDescription,
6
+ errorText = _ref.errorText,
7
+ counter = _ref.counter;
8
+ return /*#__PURE__*/React.createElement(S.ContentBelow, {
9
+ "data-testid": "code-area-below",
10
+ ref: ref
11
+ }, (description || additionalDescription || errorText) && /*#__PURE__*/React.createElement(S.LeftSide, null, additionalDescription, errorText && /*#__PURE__*/React.createElement(S.ErrorText, {
12
+ "data-testid": "code-area-error"
13
+ }, errorText), description && /*#__PURE__*/React.createElement(S.Description, {
14
+ "data-testid": "code-area-description"
15
+ }, description)), counter && /*#__PURE__*/React.createElement(S.RightSide, {
16
+ "data-testid": "code-area-counter-bottom"
17
+ }, counter));
18
+ });
@@ -0,0 +1,9 @@
1
+ import { ReactNode } from 'react';
2
+ import { CodeAreaTexts } from '../CodeArea.types';
3
+ type FullscreenHeaderProps = {
4
+ label?: ReactNode;
5
+ texts: CodeAreaTexts;
6
+ onClick: () => void;
7
+ };
8
+ export declare const FullscreenHeader: ({ label, texts, onClick }: FullscreenHeaderProps) => JSX.Element;
9
+ export {};
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import Button from '@synerise/ds-button';
3
+ import Icon, { CloseM, CodeTerminalM } from '@synerise/ds-icon';
4
+ import * as S from '../CodeArea.styles';
5
+ export var FullscreenHeader = function FullscreenHeader(_ref) {
6
+ var label = _ref.label,
7
+ texts = _ref.texts,
8
+ onClick = _ref.onClick;
9
+ return /*#__PURE__*/React.createElement(S.FullscreenHeader, null, /*#__PURE__*/React.createElement(S.LeftSide, null, /*#__PURE__*/React.createElement(S.FullscreenHeaderTitle, {
10
+ level: 3
11
+ }, /*#__PURE__*/React.createElement(Icon, {
12
+ component: /*#__PURE__*/React.createElement(CodeTerminalM, null)
13
+ }), label || texts.fullscreenTitle)), /*#__PURE__*/React.createElement(S.RightSide, null, /*#__PURE__*/React.createElement(Button, {
14
+ type: "primary",
15
+ mode: "icon-label",
16
+ onClick: onClick,
17
+ icon: /*#__PURE__*/React.createElement(Icon, {
18
+ component: /*#__PURE__*/React.createElement(CloseM, null)
19
+ })
20
+ }, texts.closeFullscreen)));
21
+ };
@@ -0,0 +1,4 @@
1
+ export * from './ContentAbove';
2
+ export * from './ContentBelow';
3
+ export * from './FullscreenHeader';
4
+ export * from './BottomBar';
@@ -0,0 +1,4 @@
1
+ export * from './ContentAbove';
2
+ export * from './ContentBelow';
3
+ export * from './FullscreenHeader';
4
+ export * from './BottomBar';
@@ -0,0 +1,5 @@
1
+ import type { monaco } from 'react-monaco-editor';
2
+ export declare const MONACO_DEFAULT_OPTIONS: monaco.editor.IStandaloneEditorConstructionOptions;
3
+ export declare const TRIGGER_SOURCE = "ds-code-area";
4
+ export declare const DS_MONACO_THEME_NAME = "DSTheme";
5
+ export declare const DS_MONACO_THEME: monaco.editor.IStandaloneThemeData;
@@ -0,0 +1,31 @@
1
+ import { theme } from '@synerise/ds-core';
2
+ export var MONACO_DEFAULT_OPTIONS = {
3
+ minimap: {
4
+ enabled: false
5
+ },
6
+ automaticLayout: true,
7
+ renderLineHighlight: 'none',
8
+ scrollbar: {
9
+ verticalScrollbarSize: 11,
10
+ verticalSliderSize: 3,
11
+ vertical: 'visible',
12
+ useShadows: false
13
+ }
14
+ };
15
+ export var TRIGGER_SOURCE = 'ds-code-area';
16
+ var TRANSPARENT = '#00000000';
17
+ export var DS_MONACO_THEME_NAME = 'DSTheme';
18
+ export var DS_MONACO_THEME = {
19
+ base: 'vs',
20
+ inherit: true,
21
+ rules: [],
22
+ colors: {
23
+ 'editor.foreground': theme.palette['grey-800'],
24
+ 'editor.background': TRANSPARENT,
25
+ 'editorOverviewRuler.border': TRANSPARENT,
26
+ 'scrollbarSlider.background': theme.palette['grey-300'],
27
+ 'scrollbarSlider.hoverBackground': theme.palette['grey-500'],
28
+ 'scrollbarSlider.activeBackground': theme.palette['grey-500'],
29
+ 'editorLineNumber.foreground': theme.palette['grey-500']
30
+ }
31
+ };
@@ -0,0 +1,2 @@
1
+ export { default } from './CodeArea';
2
+ export type { CodeAreaProps, CodeAreaTexts, CodeAreaSyntaxOption, CodeAreaSyntax } from './CodeArea.types';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { default } from './CodeArea';
@@ -0,0 +1 @@
1
+ import '@testing-library/jest-dom/extend-expect';
@@ -0,0 +1 @@
1
+ export declare const calculateRequiredSpace: (isBottomBarShowing: boolean, contentBelowHeight: number) => number;
@@ -0,0 +1,6 @@
1
+ var HEADER_HEIGHT = 64;
2
+ var BAR_HEIGHT = 49;
3
+ var MARGINS = 40;
4
+ export var calculateRequiredSpace = function calculateRequiredSpace(isBottomBarShowing, contentBelowHeight) {
5
+ return HEADER_HEIGHT + (isBottomBarShowing ? BAR_HEIGHT : 0) + contentBelowHeight + MARGINS;
6
+ };
@@ -0,0 +1 @@
1
+ export declare const getCharCount: (value?: string | null, limit?: number) => number | undefined;
@@ -0,0 +1,4 @@
1
+ export var getCharCount = function getCharCount(value, limit) {
2
+ if (limit && value && value.toString().length > limit) return undefined;
3
+ return value ? value.toString().length : 0;
4
+ };
@@ -0,0 +1,2 @@
1
+ import { CodeAreaTexts } from '../CodeArea.types';
2
+ export declare const getDefaultTexts: (texts?: Partial<CodeAreaTexts>) => CodeAreaTexts;
@@ -0,0 +1,25 @@
1
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
2
+
3
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
4
+
5
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
6
+
7
+ import React from 'react';
8
+ import { FormattedMessage } from 'react-intl';
9
+ export var getDefaultTexts = function getDefaultTexts(texts) {
10
+ var defaultTexts = {
11
+ fullscreen: /*#__PURE__*/React.createElement(FormattedMessage, {
12
+ id: "DS.CODE-AREA.FULLSCREEN",
13
+ defaultMessage: "Fullscreen"
14
+ }),
15
+ closeFullscreen: /*#__PURE__*/React.createElement(FormattedMessage, {
16
+ id: "DS.CODE-AREA.CLOSE-FULLSCREEN",
17
+ defaultMessage: "Close fullscreen"
18
+ }),
19
+ fullscreenTitle: /*#__PURE__*/React.createElement(FormattedMessage, {
20
+ id: "DS.CODE-AREA.FULLSCREEN-TITLE",
21
+ defaultMessage: "Fullscreen editor"
22
+ })
23
+ };
24
+ return _objectSpread({}, defaultTexts, {}, texts);
25
+ };
@@ -0,0 +1,3 @@
1
+ export * from './getDefaultTexts';
2
+ export * from './getCharCount';
3
+ export * from './calculateRequiredSpace';
@@ -0,0 +1,3 @@
1
+ export * from './getDefaultTexts';
2
+ export * from './getCharCount';
3
+ export * from './calculateRequiredSpace';
package/package.json ADDED
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@synerise/ds-code-area",
3
+ "version": "0.0.1",
4
+ "description": "CodeArea UI Component for the Synerise Design System",
5
+ "license": "ISC",
6
+ "repository": "Synerise/synerise-design",
7
+ "main": "dist/index.js",
8
+ "files": [
9
+ "/dist",
10
+ "CHANGELOG.md",
11
+ "README.md",
12
+ "package.json",
13
+ "LICENSE.md"
14
+ ],
15
+ "publishConfig": {
16
+ "access": "public"
17
+ },
18
+ "scripts": {
19
+ "build": "npm run build:js && npm run build:css && npm run defs",
20
+ "build:css": "node ../../../scripts/style/less.js",
21
+ "build:js": "babel --delete-dir-on-start --root-mode upward src --out-dir dist --extensions '.js,.ts,.tsx'",
22
+ "build:watch": "npm run build:js -- --watch",
23
+ "defs": "tsc --declaration --outDir dist/ --emitDeclarationOnly",
24
+ "pack:ci": "npm pack --pack-destination ../../portal/storybook-static/static",
25
+ "prepublish": "npm run build",
26
+ "test": "jest",
27
+ "test:watch": "npm run test -- --watchAll",
28
+ "types": "tsc --noEmit"
29
+ },
30
+ "sideEffects": [
31
+ "dist/style/*",
32
+ "*.less"
33
+ ],
34
+ "types": "dist/index.d.ts",
35
+ "dependencies": {
36
+ "@synerise/ds-button": "^0.19.4",
37
+ "@synerise/ds-core": "^0.40.12",
38
+ "@synerise/ds-icon": "^0.60.4",
39
+ "@synerise/ds-inline-edit": "^0.6.101",
40
+ "@synerise/ds-input": "^0.20.2",
41
+ "@synerise/ds-tooltip": "^0.14.21",
42
+ "@synerise/ds-typography": "^0.14.3",
43
+ "@synerise/ds-utils": "^0.26.0",
44
+ "monaco-editor": "0.47.0",
45
+ "react-monaco-editor": "^0.55.0"
46
+ },
47
+ "peerDependencies": {
48
+ "@synerise/ds-core": "*",
49
+ "react": ">=16.9.0 < 17.0.0",
50
+ "styled-components": "5.0.1"
51
+ },
52
+ "devDependencies": {
53
+ "@testing-library/jest-dom": "5.1.1"
54
+ },
55
+ "gitHead": "2f935cb84d9f0c1171540094be36ab73bc024871"
56
+ }