@snack-uikit/markdown 0.4.12 → 0.5.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 (28) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +4 -0
  3. package/dist/cjs/components/Markdown/Markdown.d.ts +6 -1
  4. package/dist/cjs/components/Markdown/Markdown.js +9 -5
  5. package/dist/cjs/components/MarkdownEditor/MarkdownEditor.d.ts +6 -1
  6. package/dist/cjs/components/MarkdownEditor/MarkdownEditor.js +11 -7
  7. package/dist/cjs/helperComponents/Code/Code.d.ts +2 -1
  8. package/dist/cjs/helperComponents/Code/Code.js +7 -3
  9. package/dist/cjs/helperComponents/Code/styles.module.css +2 -2
  10. package/dist/esm/components/Markdown/Markdown.d.ts +6 -1
  11. package/dist/esm/components/Markdown/Markdown.js +2 -8
  12. package/dist/esm/components/MarkdownEditor/MarkdownEditor.d.ts +6 -1
  13. package/dist/esm/components/MarkdownEditor/MarkdownEditor.js +4 -4
  14. package/dist/esm/helperComponents/Code/Code.d.ts +2 -1
  15. package/dist/esm/helperComponents/Code/Code.js +3 -2
  16. package/dist/esm/helperComponents/Code/styles.module.css +2 -2
  17. package/dist/tsconfig.cjs.tsbuildinfo +1 -1
  18. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  19. package/package.json +4 -4
  20. package/src/components/Markdown/Markdown.tsx +8 -3
  21. package/src/components/Markdown/styles.module.scss +20 -20
  22. package/src/components/MarkdownEditor/MarkdownEditor.tsx +13 -4
  23. package/src/components/MarkdownEditor/styles.module.scss +15 -15
  24. package/src/helperComponents/Blockquote/styles.module.scss +5 -5
  25. package/src/helperComponents/Code/Code.tsx +12 -4
  26. package/src/helperComponents/Code/styles.module.scss +8 -8
  27. package/src/helperComponents/Divider/styles.module.scss +2 -2
  28. package/src/helperComponents/Table/styles.module.scss +7 -7
package/CHANGELOG.md CHANGED
@@ -3,6 +3,26 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 0.5.0 (2025-05-28)
7
+
8
+
9
+ ### Features
10
+
11
+ * **PDS-2227:** add copy button for code editor ([6891964](https://github.com/cloud-ru-tech/snack-uikit/commit/6891964be3dffecab54a3a226f250f6d303da7e9))
12
+
13
+
14
+
15
+
16
+
17
+ ## 0.4.13 (2025-05-27)
18
+
19
+ ### Only dependencies have been changed
20
+ * [@snack-uikit/fields@0.47.0](https://github.com/cloud-ru-tech/snack-uikit/blob/master/packages/fields/CHANGELOG.md)
21
+
22
+
23
+
24
+
25
+
6
26
  ## 0.4.12 (2025-05-26)
7
27
 
8
28
  ### Only dependencies have been changed
package/README.md CHANGED
@@ -35,6 +35,8 @@ const handleChange = (newValue: string) => {
35
35
  |------|------|---------------|-------------|
36
36
  | value | `string` | - | Текст c разметкой |
37
37
  | className | `string` | - | CSS-класс |
38
+ | components | `Partial<Omit<NormalComponents, keyof SpecialComponents> & SpecialComponents>` | {} | Переопределение компонентов по умолчанию и добавление новых в CodeEditor |
39
+ | onCopyClick | `() => void` | - | Действие при клике на кнопку копирования кода |
38
40
  ## MarkdownEditor
39
41
  ### Props
40
42
  | name | type | default value | description |
@@ -48,6 +50,8 @@ const handleChange = (newValue: string) => {
48
50
  | placeholder | `string` | - | Плейсхолдер для textarea |
49
51
  | required | `boolean` | - | Является ли поле обязательным |
50
52
  | resizable | `boolean` | - | Может ли ли пользователь изменять размеры поля (если св-во не включено, поле автоматически меняет свой размер) |
53
+ | onCodeCopyClick | `() => void` | - | Действие при клике на кнопку копирования кода |
54
+ | components | `Partial<Omit<NormalComponents, keyof SpecialComponents> & SpecialComponents>` | - | Переопределение компонентов по умолчанию и добавление новых в CodeEditor |
51
55
 
52
56
 
53
57
  [//]: DOCUMENTATION_SECTION_END
@@ -1,8 +1,13 @@
1
+ import { Components } from 'react-markdown';
1
2
  import { WithSupportProps } from '@snack-uikit/utils';
2
3
  export type MarkdownProps = WithSupportProps<{
3
4
  /** Текст c разметкой */
4
5
  value?: string;
5
6
  /** CSS-класс */
6
7
  className?: string;
8
+ /** Переопределение компонентов по умолчанию и добавление новых в CodeEditor */
9
+ components?: Components;
10
+ /** Действие при клике на кнопку копирования кода */
11
+ onCopyClick?(): void;
7
12
  }>;
8
- export declare function Markdown({ value, className, ...rest }: MarkdownProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function Markdown({ value, className, onCopyClick, components, ...rest }: MarkdownProps): import("react/jsx-runtime").JSX.Element;
@@ -26,9 +26,11 @@ const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
26
26
  function Markdown(_a) {
27
27
  var {
28
28
  value,
29
- className
29
+ className,
30
+ onCopyClick,
31
+ components = {}
30
32
  } = _a,
31
- rest = __rest(_a, ["value", "className"]);
33
+ rest = __rest(_a, ["value", "className", "onCopyClick", "components"]);
32
34
  return (0, jsx_runtime_1.jsx)("div", Object.assign({
33
35
  className: className
34
36
  }, (0, utils_1.extractSupportProps)(rest), {
@@ -36,13 +38,15 @@ function Markdown(_a) {
36
38
  className: styles_module_scss_1.default.markdown,
37
39
  remarkPlugins: [remark_gfm_1.default],
38
40
  skipHtml: true,
39
- components: {
40
- code: helperComponents_1.Code,
41
+ components: Object.assign({
42
+ code: props => (0, jsx_runtime_1.jsx)(helperComponents_1.Code, Object.assign({}, props, {
43
+ onClick: onCopyClick
44
+ })),
41
45
  table: helperComponents_1.Table,
42
46
  hr: helperComponents_1.Divider,
43
47
  blockquote: helperComponents_1.Blockquote,
44
48
  a: helperComponents_1.Link
45
- },
49
+ }, components),
46
50
  children: value
47
51
  })
48
52
  }));
@@ -1,3 +1,4 @@
1
+ import { Components } from 'react-markdown';
1
2
  import { WithSupportProps } from '@snack-uikit/utils';
2
3
  import { Mode } from '../../types';
3
4
  export type MarkdownEditorProps = WithSupportProps<{
@@ -19,5 +20,9 @@ export type MarkdownEditorProps = WithSupportProps<{
19
20
  required?: boolean;
20
21
  /** Может ли ли пользователь изменять размеры поля (если св-во не включено, поле автоматически меняет свой размер) */
21
22
  resizable?: boolean;
23
+ /** Действие при клике на кнопку копирования кода*/
24
+ onCodeCopyClick?(): void;
25
+ /** Переопределение компонентов по умолчанию и добавление новых в CodeEditor*/
26
+ components?: Components;
22
27
  }>;
23
- export declare function MarkdownEditor({ value, onChange, defaultMode, className, error, label, placeholder, required, resizable, ...rest }: MarkdownEditorProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function MarkdownEditor({ value, onChange, defaultMode, className, error, label, placeholder, required, resizable, onCodeCopyClick, components, ...rest }: MarkdownEditorProps): import("react/jsx-runtime").JSX.Element;
@@ -37,12 +37,14 @@ function MarkdownEditor(_a) {
37
37
  label,
38
38
  placeholder,
39
39
  required,
40
- resizable
40
+ resizable,
41
+ onCodeCopyClick,
42
+ components
41
43
  } = _a,
42
- rest = __rest(_a, ["value", "onChange", "defaultMode", "className", "error", "label", "placeholder", "required", "resizable"]);
43
- const [viewMode, setViewMode] = (0, react_1.useState)(false);
44
+ rest = __rest(_a, ["value", "onChange", "defaultMode", "className", "error", "label", "placeholder", "required", "resizable", "onCodeCopyClick", "components"]);
45
+ const [isViewMode, setIsViewMode] = (0, react_1.useState)(false);
44
46
  (0, react_1.useEffect)(() => {
45
- setViewMode(defaultMode === constants_1.MODE.View);
47
+ setIsViewMode(defaultMode === constants_1.MODE.View);
46
48
  }, [defaultMode]);
47
49
  return (0, jsx_runtime_1.jsxs)("div", Object.assign({
48
50
  className: (0, classnames_1.default)(styles_module_scss_1.default.editor, className)
@@ -52,8 +54,8 @@ function MarkdownEditor(_a) {
52
54
  children: [(0, jsx_runtime_1.jsxs)("div", {
53
55
  className: styles_module_scss_1.default.switchWrapper,
54
56
  children: [(0, jsx_runtime_1.jsx)(toggles_1.Switch, {
55
- checked: viewMode,
56
- onChange: setViewMode
57
+ checked: isViewMode,
58
+ onChange: setIsViewMode
57
59
  }), (0, jsx_runtime_1.jsx)(typography_1.Typography.SansBodyM, {
58
60
  children: "\u041F\u0440\u0435\u0434\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440"
59
61
  })]
@@ -61,14 +63,16 @@ function MarkdownEditor(_a) {
61
63
  className: styles_module_scss_1.default.tip,
62
64
  children: "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F Markdown"
63
65
  })]
64
- }), viewMode ? (0, jsx_runtime_1.jsx)(fields_1.FieldDecorator, {
66
+ }), isViewMode ? (0, jsx_runtime_1.jsx)(fields_1.FieldDecorator, {
65
67
  label: label,
66
68
  required: required,
67
69
  error: error,
68
70
  size: 'm',
69
71
  children: (0, jsx_runtime_1.jsx)(Markdown_1.Markdown, {
70
72
  value: value,
73
+ onCopyClick: onCodeCopyClick,
71
74
  className: styles_module_scss_1.default.viewWrapper,
75
+ components: components,
72
76
  "data-validation": error ? fields_1.VALIDATION_STATE.Error : fields_1.VALIDATION_STATE.Default
73
77
  })
74
78
  }) : (0, jsx_runtime_1.jsx)(fields_1.FieldTextArea, {
@@ -3,6 +3,7 @@ type CodeProps = {
3
3
  inline?: boolean;
4
4
  className?: string;
5
5
  children: ReactNode & ReactNode[];
6
+ onClick?(): void;
6
7
  };
7
- export declare function Code({ inline, className, children }: CodeProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function Code({ inline, className, children, onClick }: CodeProps): import("react/jsx-runtime").JSX.Element;
8
9
  export {};
@@ -16,16 +16,20 @@ function Code(_ref) {
16
16
  let {
17
17
  inline,
18
18
  className,
19
- children
19
+ children,
20
+ onClick
20
21
  } = _ref;
21
22
  var _a;
22
23
  const language = (_a = /language-(\w+)/.exec(className || '')) === null || _a === void 0 ? void 0 : _a[1];
24
+ const value = String(children).replace(/\n$/, '');
23
25
  if (!inline) {
24
26
  return (0, jsx_runtime_1.jsx)(code_editor_1.CodeEditor, {
25
- className: styles_module_scss_1.default.wrapper,
27
+ onCopyClick: onClick,
26
28
  height: 200,
29
+ className: styles_module_scss_1.default.wrapper,
27
30
  language: language,
28
- value: String(children).replace(/\n$/, ''),
31
+ hasHeader: true,
32
+ value: value,
29
33
  options: {
30
34
  readOnly: true,
31
35
  minimap: {
@@ -1,7 +1,7 @@
1
1
  .wrapper{
2
2
  padding-top:var(--space-markdown-syntax-code-editor, 5px);
3
- display:flex;
4
- max-height:200px;
3
+ box-sizing:border-box;
4
+ max-height:241px;
5
5
  }
6
6
 
7
7
  .code{
@@ -1,8 +1,13 @@
1
+ import { Components } from 'react-markdown';
1
2
  import { WithSupportProps } from '@snack-uikit/utils';
2
3
  export type MarkdownProps = WithSupportProps<{
3
4
  /** Текст c разметкой */
4
5
  value?: string;
5
6
  /** CSS-класс */
6
7
  className?: string;
8
+ /** Переопределение компонентов по умолчанию и добавление новых в CodeEditor */
9
+ components?: Components;
10
+ /** Действие при клике на кнопку копирования кода */
11
+ onCopyClick?(): void;
7
12
  }>;
8
- export declare function Markdown({ value, className, ...rest }: MarkdownProps): import("react/jsx-runtime").JSX.Element;
13
+ export declare function Markdown({ value, className, onCopyClick, components, ...rest }: MarkdownProps): import("react/jsx-runtime").JSX.Element;
@@ -16,12 +16,6 @@ import { extractSupportProps } from '@snack-uikit/utils';
16
16
  import { Blockquote, Code, Divider, Link, Table } from '../../helperComponents';
17
17
  import styles from './styles.module.css';
18
18
  export function Markdown(_a) {
19
- var { value, className } = _a, rest = __rest(_a, ["value", "className"]);
20
- return (_jsx("div", Object.assign({ className: className }, extractSupportProps(rest), { children: value && (_jsx(ReactMarkdown, { className: styles.markdown, remarkPlugins: [remarkGfm], skipHtml: true, components: {
21
- code: Code,
22
- table: Table,
23
- hr: Divider,
24
- blockquote: Blockquote,
25
- a: Link,
26
- }, children: value })) })));
19
+ var { value, className, onCopyClick, components = {} } = _a, rest = __rest(_a, ["value", "className", "onCopyClick", "components"]);
20
+ return (_jsx("div", Object.assign({ className: className }, extractSupportProps(rest), { children: value && (_jsx(ReactMarkdown, { className: styles.markdown, remarkPlugins: [remarkGfm], skipHtml: true, components: Object.assign({ code: props => _jsx(Code, Object.assign({}, props, { onClick: onCopyClick })), table: Table, hr: Divider, blockquote: Blockquote, a: Link }, components), children: value })) })));
27
21
  }
@@ -1,3 +1,4 @@
1
+ import { Components } from 'react-markdown';
1
2
  import { WithSupportProps } from '@snack-uikit/utils';
2
3
  import { Mode } from '../../types';
3
4
  export type MarkdownEditorProps = WithSupportProps<{
@@ -19,5 +20,9 @@ export type MarkdownEditorProps = WithSupportProps<{
19
20
  required?: boolean;
20
21
  /** Может ли ли пользователь изменять размеры поля (если св-во не включено, поле автоматически меняет свой размер) */
21
22
  resizable?: boolean;
23
+ /** Действие при клике на кнопку копирования кода*/
24
+ onCodeCopyClick?(): void;
25
+ /** Переопределение компонентов по умолчанию и добавление новых в CodeEditor*/
26
+ components?: Components;
22
27
  }>;
23
- export declare function MarkdownEditor({ value, onChange, defaultMode, className, error, label, placeholder, required, resizable, ...rest }: MarkdownEditorProps): import("react/jsx-runtime").JSX.Element;
28
+ export declare function MarkdownEditor({ value, onChange, defaultMode, className, error, label, placeholder, required, resizable, onCodeCopyClick, components, ...rest }: MarkdownEditorProps): import("react/jsx-runtime").JSX.Element;
@@ -20,10 +20,10 @@ import { MODE } from '../../constants';
20
20
  import { Markdown } from '../Markdown';
21
21
  import styles from './styles.module.css';
22
22
  export function MarkdownEditor(_a) {
23
- var { value, onChange, defaultMode, className, error, label, placeholder, required, resizable } = _a, rest = __rest(_a, ["value", "onChange", "defaultMode", "className", "error", "label", "placeholder", "required", "resizable"]);
24
- const [viewMode, setViewMode] = useState(false);
23
+ var { value, onChange, defaultMode, className, error, label, placeholder, required, resizable, onCodeCopyClick, components } = _a, rest = __rest(_a, ["value", "onChange", "defaultMode", "className", "error", "label", "placeholder", "required", "resizable", "onCodeCopyClick", "components"]);
24
+ const [isViewMode, setIsViewMode] = useState(false);
25
25
  useEffect(() => {
26
- setViewMode(defaultMode === MODE.View);
26
+ setIsViewMode(defaultMode === MODE.View);
27
27
  }, [defaultMode]);
28
- return (_jsxs("div", Object.assign({ className: cn(styles.editor, className) }, extractSupportProps(rest), { children: [_jsxs("div", { className: styles.control, children: [_jsxs("div", { className: styles.switchWrapper, children: [_jsx(Switch, { checked: viewMode, onChange: setViewMode }), _jsx(Typography.SansBodyM, { children: "\u041F\u0440\u0435\u0434\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440" })] }), _jsx(Typography.SansBodyS, { className: styles.tip, children: "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F Markdown" })] }), viewMode ? (_jsx(FieldDecorator, { label: label, required: required, error: error, size: 'm', children: _jsx(Markdown, { value: value, className: styles.viewWrapper, "data-validation": error ? VALIDATION_STATE.Error : VALIDATION_STATE.Default }) })) : (_jsx(FieldTextArea, { value: value, onChange: onChange, label: label, placeholder: placeholder, required: required, resizable: resizable, error: error, size: 'm' }))] })));
28
+ return (_jsxs("div", Object.assign({ className: cn(styles.editor, className) }, extractSupportProps(rest), { children: [_jsxs("div", { className: styles.control, children: [_jsxs("div", { className: styles.switchWrapper, children: [_jsx(Switch, { checked: isViewMode, onChange: setIsViewMode }), _jsx(Typography.SansBodyM, { children: "\u041F\u0440\u0435\u0434\u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440" })] }), _jsx(Typography.SansBodyS, { className: styles.tip, children: "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044F Markdown" })] }), isViewMode ? (_jsx(FieldDecorator, { label: label, required: required, error: error, size: 'm', children: _jsx(Markdown, { value: value, onCopyClick: onCodeCopyClick, className: styles.viewWrapper, components: components, "data-validation": error ? VALIDATION_STATE.Error : VALIDATION_STATE.Default }) })) : (_jsx(FieldTextArea, { value: value, onChange: onChange, label: label, placeholder: placeholder, required: required, resizable: resizable, error: error, size: 'm' }))] })));
29
29
  }
@@ -3,6 +3,7 @@ type CodeProps = {
3
3
  inline?: boolean;
4
4
  className?: string;
5
5
  children: ReactNode & ReactNode[];
6
+ onClick?(): void;
6
7
  };
7
- export declare function Code({ inline, className, children }: CodeProps): import("react/jsx-runtime").JSX.Element;
8
+ export declare function Code({ inline, className, children, onClick }: CodeProps): import("react/jsx-runtime").JSX.Element;
8
9
  export {};
@@ -1,11 +1,12 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { CodeEditor } from '@snack-uikit/code-editor';
3
3
  import styles from './styles.module.css';
4
- export function Code({ inline, className, children }) {
4
+ export function Code({ inline, className, children, onClick }) {
5
5
  var _a;
6
6
  const language = (_a = /language-(\w+)/.exec(className || '')) === null || _a === void 0 ? void 0 : _a[1];
7
+ const value = String(children).replace(/\n$/, '');
7
8
  if (!inline) {
8
- return (_jsx(CodeEditor, { className: styles.wrapper, height: 200, language: language, value: String(children).replace(/\n$/, ''), options: {
9
+ return (_jsx(CodeEditor, { onCopyClick: onClick, height: 200, className: styles.wrapper, language: language, hasHeader: true, value: value, options: {
9
10
  readOnly: true,
10
11
  minimap: {
11
12
  enabled: false,
@@ -1,7 +1,7 @@
1
1
  .wrapper{
2
2
  padding-top:var(--space-markdown-syntax-code-editor, 5px);
3
- display:flex;
4
- max-height:200px;
3
+ box-sizing:border-box;
4
+ max-height:241px;
5
5
  }
6
6
 
7
7
  .code{