@cloud-ru/ds-markdown 1.0.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 (212) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/LICENSE +201 -0
  3. package/README.md +273 -0
  4. package/dist/cjs/components/Markdown/CodeBlock.d.ts +9 -0
  5. package/dist/cjs/components/Markdown/CodeBlock.js +58 -0
  6. package/dist/cjs/components/Markdown/Markdown.d.ts +2 -0
  7. package/dist/cjs/components/Markdown/Markdown.js +25 -0
  8. package/dist/cjs/components/Markdown/index.d.ts +1 -0
  9. package/dist/cjs/components/Markdown/index.js +17 -0
  10. package/dist/cjs/components/Markdown/styles.module.css +205 -0
  11. package/dist/cjs/components/MarkdownEditor/MarkdownEditor.d.ts +2 -0
  12. package/dist/cjs/components/MarkdownEditor/MarkdownEditor.js +176 -0
  13. package/dist/cjs/components/MarkdownEditor/index.d.ts +1 -0
  14. package/dist/cjs/components/MarkdownEditor/index.js +17 -0
  15. package/dist/cjs/components/MarkdownEditor/styles.module.css +273 -0
  16. package/dist/cjs/components/Toolbar/Toolbar.d.ts +9 -0
  17. package/dist/cjs/components/Toolbar/Toolbar.js +173 -0
  18. package/dist/cjs/components/Toolbar/constants.d.ts +13 -0
  19. package/dist/cjs/components/Toolbar/constants.js +40 -0
  20. package/dist/cjs/components/Toolbar/hooks/index.d.ts +2 -0
  21. package/dist/cjs/components/Toolbar/hooks/index.js +18 -0
  22. package/dist/cjs/components/Toolbar/hooks/useToolbarHotkeys.d.ts +21 -0
  23. package/dist/cjs/components/Toolbar/hooks/useToolbarHotkeys.js +59 -0
  24. package/dist/cjs/components/Toolbar/hooks/useToolbarOverflow.d.ts +14 -0
  25. package/dist/cjs/components/Toolbar/hooks/useToolbarOverflow.js +87 -0
  26. package/dist/cjs/components/Toolbar/index.d.ts +2 -0
  27. package/dist/cjs/components/Toolbar/index.js +20 -0
  28. package/dist/cjs/components/Toolbar/styles.module.css +17 -0
  29. package/dist/cjs/components/index.d.ts +2 -0
  30. package/dist/cjs/components/index.js +20 -0
  31. package/dist/cjs/constants.d.ts +65 -0
  32. package/dist/cjs/constants.js +67 -0
  33. package/dist/cjs/helperComponents/ButtonHeading/ButtonHeading.d.ts +6 -0
  34. package/dist/cjs/helperComponents/ButtonHeading/ButtonHeading.js +61 -0
  35. package/dist/cjs/helperComponents/ButtonHeading/index.d.ts +1 -0
  36. package/dist/cjs/helperComponents/ButtonHeading/index.js +17 -0
  37. package/dist/cjs/helperComponents/ButtonHeading/styles.module.css +3 -0
  38. package/dist/cjs/helperComponents/Buttons/Buttons.d.ts +10 -0
  39. package/dist/cjs/helperComponents/Buttons/Buttons.js +21 -0
  40. package/dist/cjs/helperComponents/Buttons/index.d.ts +1 -0
  41. package/dist/cjs/helperComponents/Buttons/index.js +17 -0
  42. package/dist/cjs/helperComponents/Buttons/styles.module.css +17 -0
  43. package/dist/cjs/helperComponents/Modals/CustomizeTableModal.d.ts +8 -0
  44. package/dist/cjs/helperComponents/Modals/CustomizeTableModal.js +39 -0
  45. package/dist/cjs/helperComponents/Modals/ImageModal.d.ts +7 -0
  46. package/dist/cjs/helperComponents/Modals/ImageModal.js +44 -0
  47. package/dist/cjs/helperComponents/Modals/LinkModal.d.ts +13 -0
  48. package/dist/cjs/helperComponents/Modals/LinkModal.js +42 -0
  49. package/dist/cjs/helperComponents/Modals/index.d.ts +3 -0
  50. package/dist/cjs/helperComponents/Modals/index.js +19 -0
  51. package/dist/cjs/helperComponents/Modals/styles.module.css +17 -0
  52. package/dist/cjs/helperComponents/PrivateButton/PrivateButton.d.ts +17 -0
  53. package/dist/cjs/helperComponents/PrivateButton/PrivateButton.js +27 -0
  54. package/dist/cjs/helperComponents/PrivateButton/index.d.ts +1 -0
  55. package/dist/cjs/helperComponents/PrivateButton/index.js +17 -0
  56. package/dist/cjs/helperComponents/PrivateButton/styles.module.css +140 -0
  57. package/dist/cjs/helperComponents/TableSelectItem/TableSelectItem.d.ts +11 -0
  58. package/dist/cjs/helperComponents/TableSelectItem/TableSelectItem.js +12 -0
  59. package/dist/cjs/helperComponents/TableSelectItem/index.d.ts +1 -0
  60. package/dist/cjs/helperComponents/TableSelectItem/index.js +17 -0
  61. package/dist/cjs/helperComponents/TableSelectItem/styles.module.css +101 -0
  62. package/dist/cjs/helperComponents/TableSelectSettingsGrid/TableSelectSettingsGrid.d.ts +4 -0
  63. package/dist/cjs/helperComponents/TableSelectSettingsGrid/TableSelectSettingsGrid.js +27 -0
  64. package/dist/cjs/helperComponents/TableSelectSettingsGrid/index.d.ts +1 -0
  65. package/dist/cjs/helperComponents/TableSelectSettingsGrid/index.js +17 -0
  66. package/dist/cjs/helperComponents/TableSelectSettingsGrid/styles.module.css +54 -0
  67. package/dist/cjs/helperComponents/index.d.ts +6 -0
  68. package/dist/cjs/helperComponents/index.js +22 -0
  69. package/dist/cjs/index.d.ts +4 -0
  70. package/dist/cjs/index.js +20 -0
  71. package/dist/cjs/locale/index.d.ts +199 -0
  72. package/dist/cjs/locale/index.js +104 -0
  73. package/dist/cjs/lowlight.d.ts +14 -0
  74. package/dist/cjs/lowlight.js +35 -0
  75. package/dist/cjs/mixins.css +0 -0
  76. package/dist/cjs/package.json +3 -0
  77. package/dist/cjs/rawMarkdownCommands.d.ts +16 -0
  78. package/dist/cjs/rawMarkdownCommands.js +145 -0
  79. package/dist/cjs/style.css +875 -0
  80. package/dist/cjs/styles/syntax.module.css +47 -0
  81. package/dist/cjs/toolbarApi.d.ts +33 -0
  82. package/dist/cjs/toolbarApi.js +100 -0
  83. package/dist/cjs/types.d.ts +52 -0
  84. package/dist/cjs/types.js +2 -0
  85. package/dist/esm/components/Markdown/CodeBlock.d.ts +9 -0
  86. package/dist/esm/components/Markdown/CodeBlock.js +52 -0
  87. package/dist/esm/components/Markdown/Markdown.d.ts +2 -0
  88. package/dist/esm/components/Markdown/Markdown.js +19 -0
  89. package/dist/esm/components/Markdown/index.d.ts +1 -0
  90. package/dist/esm/components/Markdown/index.js +1 -0
  91. package/dist/esm/components/Markdown/styles.module.css +205 -0
  92. package/dist/esm/components/MarkdownEditor/MarkdownEditor.d.ts +2 -0
  93. package/dist/esm/components/MarkdownEditor/MarkdownEditor.js +170 -0
  94. package/dist/esm/components/MarkdownEditor/index.d.ts +1 -0
  95. package/dist/esm/components/MarkdownEditor/index.js +1 -0
  96. package/dist/esm/components/MarkdownEditor/styles.module.css +273 -0
  97. package/dist/esm/components/Toolbar/Toolbar.d.ts +9 -0
  98. package/dist/esm/components/Toolbar/Toolbar.js +167 -0
  99. package/dist/esm/components/Toolbar/constants.d.ts +13 -0
  100. package/dist/esm/components/Toolbar/constants.js +37 -0
  101. package/dist/esm/components/Toolbar/hooks/index.d.ts +2 -0
  102. package/dist/esm/components/Toolbar/hooks/index.js +2 -0
  103. package/dist/esm/components/Toolbar/hooks/useToolbarHotkeys.d.ts +21 -0
  104. package/dist/esm/components/Toolbar/hooks/useToolbarHotkeys.js +56 -0
  105. package/dist/esm/components/Toolbar/hooks/useToolbarOverflow.d.ts +14 -0
  106. package/dist/esm/components/Toolbar/hooks/useToolbarOverflow.js +84 -0
  107. package/dist/esm/components/Toolbar/index.d.ts +2 -0
  108. package/dist/esm/components/Toolbar/index.js +2 -0
  109. package/dist/esm/components/Toolbar/styles.module.css +17 -0
  110. package/dist/esm/components/index.d.ts +2 -0
  111. package/dist/esm/components/index.js +4 -0
  112. package/dist/esm/constants.d.ts +65 -0
  113. package/dist/esm/constants.js +61 -0
  114. package/dist/esm/helperComponents/ButtonHeading/ButtonHeading.d.ts +6 -0
  115. package/dist/esm/helperComponents/ButtonHeading/ButtonHeading.js +55 -0
  116. package/dist/esm/helperComponents/ButtonHeading/index.d.ts +1 -0
  117. package/dist/esm/helperComponents/ButtonHeading/index.js +1 -0
  118. package/dist/esm/helperComponents/ButtonHeading/styles.module.css +3 -0
  119. package/dist/esm/helperComponents/Buttons/Buttons.d.ts +10 -0
  120. package/dist/esm/helperComponents/Buttons/Buttons.js +13 -0
  121. package/dist/esm/helperComponents/Buttons/index.d.ts +1 -0
  122. package/dist/esm/helperComponents/Buttons/index.js +1 -0
  123. package/dist/esm/helperComponents/Buttons/styles.module.css +17 -0
  124. package/dist/esm/helperComponents/Modals/CustomizeTableModal.d.ts +8 -0
  125. package/dist/esm/helperComponents/Modals/CustomizeTableModal.js +33 -0
  126. package/dist/esm/helperComponents/Modals/ImageModal.d.ts +7 -0
  127. package/dist/esm/helperComponents/Modals/ImageModal.js +38 -0
  128. package/dist/esm/helperComponents/Modals/LinkModal.d.ts +13 -0
  129. package/dist/esm/helperComponents/Modals/LinkModal.js +36 -0
  130. package/dist/esm/helperComponents/Modals/index.d.ts +3 -0
  131. package/dist/esm/helperComponents/Modals/index.js +3 -0
  132. package/dist/esm/helperComponents/Modals/styles.module.css +17 -0
  133. package/dist/esm/helperComponents/PrivateButton/PrivateButton.d.ts +17 -0
  134. package/dist/esm/helperComponents/PrivateButton/PrivateButton.js +21 -0
  135. package/dist/esm/helperComponents/PrivateButton/index.d.ts +1 -0
  136. package/dist/esm/helperComponents/PrivateButton/index.js +1 -0
  137. package/dist/esm/helperComponents/PrivateButton/styles.module.css +140 -0
  138. package/dist/esm/helperComponents/TableSelectItem/TableSelectItem.d.ts +11 -0
  139. package/dist/esm/helperComponents/TableSelectItem/TableSelectItem.js +6 -0
  140. package/dist/esm/helperComponents/TableSelectItem/index.d.ts +1 -0
  141. package/dist/esm/helperComponents/TableSelectItem/index.js +1 -0
  142. package/dist/esm/helperComponents/TableSelectItem/styles.module.css +101 -0
  143. package/dist/esm/helperComponents/TableSelectSettingsGrid/TableSelectSettingsGrid.d.ts +4 -0
  144. package/dist/esm/helperComponents/TableSelectSettingsGrid/TableSelectSettingsGrid.js +21 -0
  145. package/dist/esm/helperComponents/TableSelectSettingsGrid/index.d.ts +1 -0
  146. package/dist/esm/helperComponents/TableSelectSettingsGrid/index.js +1 -0
  147. package/dist/esm/helperComponents/TableSelectSettingsGrid/styles.module.css +54 -0
  148. package/dist/esm/helperComponents/index.d.ts +6 -0
  149. package/dist/esm/helperComponents/index.js +6 -0
  150. package/dist/esm/index.d.ts +4 -0
  151. package/dist/esm/index.js +4 -0
  152. package/dist/esm/locale/index.d.ts +199 -0
  153. package/dist/esm/locale/index.js +101 -0
  154. package/dist/esm/lowlight.d.ts +14 -0
  155. package/dist/esm/lowlight.js +29 -0
  156. package/dist/esm/mixins.css +0 -0
  157. package/dist/esm/rawMarkdownCommands.d.ts +16 -0
  158. package/dist/esm/rawMarkdownCommands.js +135 -0
  159. package/dist/esm/style.css +875 -0
  160. package/dist/esm/styles/syntax.module.css +47 -0
  161. package/dist/esm/toolbarApi.d.ts +33 -0
  162. package/dist/esm/toolbarApi.js +96 -0
  163. package/dist/esm/types.d.ts +52 -0
  164. package/dist/esm/types.js +1 -0
  165. package/dist/tsconfig.cjs.tsbuildinfo +1 -0
  166. package/dist/tsconfig.esm.tsbuildinfo +1 -0
  167. package/package.json +84 -0
  168. package/src/components/Markdown/CodeBlock.tsx +96 -0
  169. package/src/components/Markdown/Markdown.tsx +47 -0
  170. package/src/components/Markdown/index.ts +1 -0
  171. package/src/components/Markdown/styles.module.scss +105 -0
  172. package/src/components/MarkdownEditor/MarkdownEditor.tsx +322 -0
  173. package/src/components/MarkdownEditor/index.ts +1 -0
  174. package/src/components/MarkdownEditor/styles.module.scss +201 -0
  175. package/src/components/Toolbar/Toolbar.tsx +292 -0
  176. package/src/components/Toolbar/constants.tsx +63 -0
  177. package/src/components/Toolbar/hooks/index.ts +2 -0
  178. package/src/components/Toolbar/hooks/useToolbarHotkeys.ts +74 -0
  179. package/src/components/Toolbar/hooks/useToolbarOverflow.ts +102 -0
  180. package/src/components/Toolbar/index.ts +2 -0
  181. package/src/components/Toolbar/styles.module.scss +29 -0
  182. package/src/components/index.ts +4 -0
  183. package/src/constants.ts +67 -0
  184. package/src/helperComponents/ButtonHeading/ButtonHeading.tsx +100 -0
  185. package/src/helperComponents/ButtonHeading/index.ts +1 -0
  186. package/src/helperComponents/ButtonHeading/styles.module.scss +5 -0
  187. package/src/helperComponents/Buttons/Buttons.tsx +30 -0
  188. package/src/helperComponents/Buttons/index.ts +1 -0
  189. package/src/helperComponents/Buttons/styles.module.scss +26 -0
  190. package/src/helperComponents/Modals/CustomizeTableModal.tsx +82 -0
  191. package/src/helperComponents/Modals/ImageModal.tsx +84 -0
  192. package/src/helperComponents/Modals/LinkModal.tsx +92 -0
  193. package/src/helperComponents/Modals/index.ts +3 -0
  194. package/src/helperComponents/Modals/styles.module.scss +21 -0
  195. package/src/helperComponents/PrivateButton/PrivateButton.tsx +88 -0
  196. package/src/helperComponents/PrivateButton/index.ts +1 -0
  197. package/src/helperComponents/PrivateButton/styles.module.scss +77 -0
  198. package/src/helperComponents/TableSelectItem/TableSelectItem.tsx +43 -0
  199. package/src/helperComponents/TableSelectItem/index.ts +1 -0
  200. package/src/helperComponents/TableSelectItem/styles.module.scss +26 -0
  201. package/src/helperComponents/TableSelectSettingsGrid/TableSelectSettingsGrid.tsx +48 -0
  202. package/src/helperComponents/TableSelectSettingsGrid/index.ts +1 -0
  203. package/src/helperComponents/TableSelectSettingsGrid/styles.module.scss +65 -0
  204. package/src/helperComponents/index.ts +6 -0
  205. package/src/index.ts +4 -0
  206. package/src/locale/index.ts +105 -0
  207. package/src/lowlight.ts +30 -0
  208. package/src/mixins.scss +123 -0
  209. package/src/rawMarkdownCommands.ts +179 -0
  210. package/src/styles/syntax.module.scss +54 -0
  211. package/src/toolbarApi.ts +152 -0
  212. package/src/types.ts +56 -0
@@ -0,0 +1,88 @@
1
+ import { WithTooltip } from '@cloud-ru/ds-tooltip';
2
+ import { Typography } from '@cloud-ru/ds-typography';
3
+ import { WithSupportProps } from '@cloud-ru/ds-utils';
4
+ import cn from 'classnames';
5
+ import { ButtonHTMLAttributes, ReactNode, Ref } from 'react';
6
+
7
+ import styles from './styles.module.scss';
8
+
9
+ const PrivateChevronIcon = (
10
+ <svg xmlns='http://www.w3.org/2000/svg' width='8' height='8' viewBox='0 0 8 8' fill='none' className={styles.chevron}>
11
+ <path d='M1 3L4 6L7 3' stroke='currentColor' strokeWidth='1.5' strokeLinecap='round' strokeLinejoin='round' />
12
+ </svg>
13
+ );
14
+
15
+ type TipContentProps = { title: string; caption?: string };
16
+
17
+ function TipContent({ title, caption }: TipContentProps) {
18
+ return (
19
+ <>
20
+ <Typography variant='body' size='s' weight='regular' className={styles.tipTitle}>
21
+ {title}
22
+ </Typography>
23
+ {caption && (
24
+ <Typography variant='body' size='s' weight='regular' className={styles.tipCaption}>
25
+ {caption}
26
+ </Typography>
27
+ )}
28
+ </>
29
+ );
30
+ }
31
+
32
+ // Иконка занимает весь container, hover — stateLayer, checked=true → accent-цвет.
33
+ export type PrivateButtonProps = WithSupportProps<
34
+ Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'> & {
35
+ icon: ReactNode;
36
+ withChevron?: boolean;
37
+ /** active/selected состояние */
38
+ checked?: boolean;
39
+ /** Внешний ref, без forwardRef (см. component-api-surface.md). */
40
+ innerRef?: Ref<HTMLButtonElement>;
41
+ tip?: TipContentProps;
42
+ }
43
+ >;
44
+
45
+ // eslint-disable-next-line ds/require-inner-ref-support -- innerRef проставляется условно (только без tip), поэтому статический маркер поддержки был бы неверен.
46
+ export function PrivateButton({
47
+ id,
48
+ tip,
49
+ icon,
50
+ checked = false,
51
+ disabled = false,
52
+ className,
53
+ innerRef,
54
+ type = 'button',
55
+ withChevron = false,
56
+ ...rest
57
+ }: PrivateButtonProps) {
58
+ return WithTooltip({
59
+ tooltip: tip
60
+ ? {
61
+ tip: <TipContent {...tip} />,
62
+ triggerClassName: styles.tooltipTrigger,
63
+ }
64
+ : undefined,
65
+ children: (
66
+ <button
67
+ data-toolbar-item={id}
68
+ {...rest}
69
+ data-toolbar-slot
70
+ ref={tip ? undefined : innerRef}
71
+ type={type}
72
+ disabled={disabled}
73
+ className={cn(styles.root, className)}
74
+ data-checked={checked || undefined}
75
+ data-disabled={disabled || undefined}
76
+ aria-pressed={checked}
77
+ >
78
+ <span
79
+ className={styles.stateLayer}
80
+ data-state={checked ? 'activatedOnBackground' : 'emptyNeutralOnBackground'}
81
+ aria-hidden
82
+ />
83
+ {icon}
84
+ {withChevron && PrivateChevronIcon}
85
+ </button>
86
+ ),
87
+ });
88
+ }
@@ -0,0 +1 @@
1
+ export * from './PrivateButton';
@@ -0,0 +1,77 @@
1
+ @use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
2
+ @use '@cloud-ru/ds-figma-variables/build/scss/components/markdown.module' as md;
3
+ @use '@cloud-ru/ds-figma-variables/build/scss/components/button.module' as button;
4
+ @use '@cloud-ru/ds-materials' as m;
5
+
6
+ // `stateLayer` нужен оставленным определённым над .root — миксин ниже его потребляет.
7
+ .stateLayer {
8
+ visibility: initial;
9
+ }
10
+
11
+ .root {
12
+ cursor: pointer;
13
+
14
+ position: relative;
15
+
16
+ display: inline-flex;
17
+ flex: 0 0 auto;
18
+ align-items: center;
19
+ justify-content: center;
20
+
21
+ box-sizing: border-box;
22
+ min-width: button.$sn-button-anatomy-size-s-container-iconOnly-minWidth;
23
+ height: button.$sn-button-anatomy-size-s-container-minHeight;
24
+ padding: 0;
25
+ border: 0;
26
+ border-radius: md.$sn-density-radius-2xs;
27
+
28
+ color: md.$sn-theme-color-neutral-text;
29
+
30
+ background: transparent;
31
+
32
+ &:has(.chevron) {
33
+ gap: md.$sn-markdown-anatomy-size-buttons-button-gap;
34
+ padding-right: md.$sn-markdown-anatomy-size-buttons-button-paddingRight;
35
+ }
36
+
37
+ svg {
38
+ flex: 0 0 auto;
39
+ stroke-width: md.$sn-density-size-icon-strokeWeight-s;
40
+
41
+ &:not(.chevron) {
42
+ width: md.$sn-density-size-icon-s;
43
+ height: md.$sn-density-size-icon-s;
44
+ }
45
+ }
46
+
47
+ &:focus-visible {
48
+ outline: md.$sn-primitive-strokeWeight-strokeSemiBold solid md.$sn-theme-color-available-complementary;
49
+ outline-offset: 0;
50
+ }
51
+
52
+ &[data-checked] {
53
+ color: md.$sn-theme-color-primary-accent;
54
+ }
55
+
56
+ &[data-disabled] {
57
+ cursor: not-allowed;
58
+ color: md.$sn-theme-color-available-version-textDisabled;
59
+ }
60
+
61
+ @include m.has-state-layer-as-child(#{stateLayer});
62
+ }
63
+
64
+ .tooltipTrigger {
65
+ display: inline-flex;
66
+ }
67
+
68
+ // Цвет наследуется от контейнера Tooltip (available/inversion/textMain) — свой не задаём.
69
+ .tipTitle {
70
+ text-align: center;
71
+ }
72
+
73
+ // Подпись-подсказка приглушена: inversion/textTertiary (тот же текст @ 60%).
74
+ .tipCaption {
75
+ color: base.$sn-theme-color-available-inversion-textTertiary;
76
+ text-align: center;
77
+ }
@@ -0,0 +1,43 @@
1
+ import styles from './styles.module.scss';
2
+
3
+ // Одна ячейка из grid-picker'а.
4
+ export type TableSelectItemProps = {
5
+ /** Hover-состояние (управляется родителем по mouseEnter). */
6
+ hovered?: boolean;
7
+ /** Будет ли ячейка попадать в выбранный диапазон. */
8
+ checked?: boolean;
9
+ onMouseEnter?(): void;
10
+ onClick?(): void;
11
+ 'aria-label'?: string;
12
+ 'data-test-id'?: string;
13
+ };
14
+
15
+ export function TableSelectItem({
16
+ hovered = false,
17
+ checked = false,
18
+ onMouseEnter,
19
+ onClick,
20
+ 'aria-label': ariaLabel,
21
+ 'data-test-id': dataTestId,
22
+ }: TableSelectItemProps) {
23
+ const state = hovered ? 'hovered' : 'default';
24
+
25
+ return (
26
+ <button
27
+ type='button'
28
+ className={styles.root}
29
+ data-state={state}
30
+ data-checked={checked || undefined}
31
+ onMouseEnter={onMouseEnter}
32
+ onClick={onClick}
33
+ aria-label={ariaLabel}
34
+ data-test-id={dataTestId}
35
+ >
36
+ <span
37
+ className={styles.stateLayer}
38
+ data-state={checked ? 'activatedOnBackground' : 'emptyNeutralOnBackground'}
39
+ aria-hidden
40
+ />
41
+ </button>
42
+ );
43
+ }
@@ -0,0 +1 @@
1
+ export * from './TableSelectItem';
@@ -0,0 +1,26 @@
1
+ @use '@cloud-ru/ds-figma-variables/build/scss/components/markdown.module' as md;
2
+ @use '@cloud-ru/ds-materials' as m;
3
+
4
+ .stateLayer {
5
+ pointer-events: none;
6
+ }
7
+
8
+ .root {
9
+ cursor: pointer;
10
+
11
+ position: relative;
12
+
13
+ box-sizing: border-box;
14
+ width: md.$sn-markdown-anatomy-size-tableSelect-container-item-size;
15
+ height: md.$sn-markdown-anatomy-size-tableSelect-container-item-size;
16
+ padding: 0;
17
+ border: md.$sn-markdown-anatomy-size-tableSelect-container-item-borderWidth solid
18
+ md.$sn-theme-color-available-borderColor;
19
+ border-radius: md.$sn-markdown-anatomy-size-tableSelect-container-item-borderRadius;
20
+
21
+ &[data-checked] {
22
+ border-color: md.$sn-theme-color-primary-accent;
23
+ }
24
+
25
+ @include m.has-state-layer-as-child(#{stateLayer});
26
+ }
@@ -0,0 +1,48 @@
1
+ import { useState } from 'react';
2
+
3
+ import { tableCellTestId, TEST_IDS } from '../../constants';
4
+ import { markdownLocale } from '../../locale';
5
+ import { TableSelectItem } from '../TableSelectItem';
6
+ import styles from './styles.module.scss';
7
+
8
+ export type TableSelectSettingsGridProps = {
9
+ onPick(rows: number, cols: number): void;
10
+ };
11
+
12
+ const MAX = 8;
13
+
14
+ export function TableSelectSettingsGrid({ onPick }: TableSelectSettingsGridProps) {
15
+ const { t } = markdownLocale.useTranslations();
16
+ const [hover, setHover] = useState<{ r: number; c: number } | null>(null);
17
+
18
+ const cells: { r: number; c: number }[] = [];
19
+ for (let r = 1; r <= MAX; r += 1) {
20
+ for (let c = 1; c <= MAX; c += 1) {
21
+ cells.push({ r, c });
22
+ }
23
+ }
24
+
25
+ return (
26
+ <div className={styles.root} data-test-id={TEST_IDS.tableGridPicker}>
27
+ <div className={styles.container}>
28
+ <div className={styles.grid} onMouseLeave={() => setHover(null)}>
29
+ {cells.map(({ r, c }) => {
30
+ const checked = hover !== null && r <= hover.r && c <= hover.c;
31
+ return (
32
+ <TableSelectItem
33
+ key={`${r}-${c}`}
34
+ hovered={hover?.r === r && hover?.c === c}
35
+ checked={checked}
36
+ onMouseEnter={() => setHover({ r, c })}
37
+ onClick={() => onPick(r, c)}
38
+ aria-label={t('table.insert', { rows: r, cols: c })}
39
+ data-test-id={tableCellTestId(r, c)}
40
+ />
41
+ );
42
+ })}
43
+ </div>
44
+ <div className={styles.label}>{hover ? `${hover.r} × ${hover.c}` : t('table.pickSize')}</div>
45
+ </div>
46
+ </div>
47
+ );
48
+ }
@@ -0,0 +1 @@
1
+ export * from './TableSelectSettingsGrid';
@@ -0,0 +1,65 @@
1
+ @use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
2
+ @use '@cloud-ru/ds-figma-variables/build/scss/components/markdown.module' as md;
3
+
4
+ .root {
5
+ display: flex;
6
+ flex-direction: column;
7
+ }
8
+
9
+ .container {
10
+ display: flex;
11
+ flex-direction: column;
12
+ gap: md.$sn-markdown-anatomy-size-tableSelect-container-gap;
13
+
14
+ box-sizing: border-box;
15
+ padding: md.$sn-markdown-anatomy-size-tableSelect-container-paddingHorizontal
16
+ md.$sn-markdown-anatomy-size-tableSelect-container-paddingHorizontal
17
+ md.$sn-markdown-anatomy-size-tableSelect-container-paddingBottom;
18
+ }
19
+
20
+ .grid {
21
+ display: grid;
22
+ grid-template-columns: repeat(8, md.$sn-markdown-anatomy-size-tableSelect-container-item-size);
23
+ gap: md.$sn-markdown-anatomy-size-tableSelect-container-gap;
24
+ }
25
+
26
+ .label {
27
+ font-size: md.$sn-density-typography-roleBody-fontSizeS;
28
+ line-height: md.$sn-density-typography-roleBody-lineHeightS;
29
+ color: md.$sn-theme-color-available-version-textSecondary;
30
+ text-align: center;
31
+ }
32
+
33
+ .customize {
34
+ cursor: pointer;
35
+
36
+ display: flex;
37
+ gap: base.$sn-primitive-dimension-8;
38
+ align-items: center;
39
+ justify-content: space-between;
40
+
41
+ box-sizing: border-box;
42
+ padding: base.$sn-primitive-dimension-4 base.$sn-primitive-dimension-12;
43
+ border: none;
44
+
45
+ font-family: md.$sn-brand-font-fontFamily-regular-body;
46
+ font-size: md.$sn-density-typography-roleBody-fontSizeM;
47
+ line-height: md.$sn-density-typography-roleBody-lineHeightM;
48
+ color: md.$sn-theme-color-available-version-textMain;
49
+ text-align: left;
50
+
51
+ background: transparent;
52
+
53
+ &:hover {
54
+ background: md.$sn-theme-color-neutral-background2Level;
55
+ }
56
+ }
57
+
58
+ .customizeLabel {
59
+ flex: 1 1 auto;
60
+ }
61
+
62
+ .customizeChevron {
63
+ flex: 0 0 auto;
64
+ color: md.$sn-theme-color-available-version-textSecondary;
65
+ }
@@ -0,0 +1,6 @@
1
+ export * from './ButtonHeading';
2
+ export * from './Buttons';
3
+ export * from './Modals';
4
+ export * from './PrivateButton';
5
+ export * from './TableSelectItem';
6
+ export * from './TableSelectSettingsGrid';
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './components';
2
+ export * from './constants';
3
+ export * from './types';
4
+ export * from './locale';
@@ -0,0 +1,105 @@
1
+ import { defineLocale, defineMessages } from '@cloud-ru/ds-locale';
2
+
3
+ const MARKDOWN_MESSAGES = defineMessages({
4
+ 'en-GB': {
5
+ toolbar: {
6
+ heading: 'Heading',
7
+ bold: 'Bold',
8
+ italic: 'Italic',
9
+ strikethrough: 'Strikethrough',
10
+ link: 'Link',
11
+ inlineCode: 'Inline code',
12
+ bulletList: 'Bullet list',
13
+ orderedList: 'Ordered list',
14
+ blockQuote: 'Block quote',
15
+ blockCode: 'Block code',
16
+ table: 'Table',
17
+ image: 'Image',
18
+ more: 'More',
19
+ },
20
+ clear: 'Clear',
21
+ copy: 'Copy',
22
+ copied: 'Copied',
23
+ add: 'Add',
24
+ cancel: 'Cancel',
25
+ link: {
26
+ title: 'Add link',
27
+ titleField: {
28
+ label: 'Text',
29
+ placeholder: 'Link text',
30
+ },
31
+ urlField: {
32
+ label: 'URL',
33
+ placeholder: 'https://',
34
+ },
35
+ },
36
+ image: {
37
+ title: 'Add image',
38
+ url: 'URL',
39
+ alt: 'Alt text',
40
+ placeholder: 'https://',
41
+ },
42
+ table: {
43
+ pickSize: 'Pick size',
44
+ insert: 'Insert {{rows}} × {{cols}} table',
45
+ column: 'Column {{index}}',
46
+ customize: 'Customize table',
47
+ columns: 'Columns',
48
+ rows: 'Rows',
49
+ },
50
+ linkText: 'link text',
51
+ },
52
+ 'ru-RU': {
53
+ toolbar: {
54
+ heading: 'Заголовок',
55
+ bold: 'Жирный',
56
+ italic: 'Курсив',
57
+ strikethrough: 'Зачёркнутый',
58
+ link: 'Ссылка',
59
+ inlineCode: 'Строчный код',
60
+ bulletList: 'Маркированный список',
61
+ orderedList: 'Нумерованный список',
62
+ blockQuote: 'Цитата',
63
+ blockCode: 'Блок кода',
64
+ table: 'Таблица',
65
+ image: 'Картинка',
66
+ more: 'Ещё',
67
+ },
68
+ clear: 'Очистить',
69
+ copy: 'Скопировать',
70
+ copied: 'Скопировано',
71
+ add: 'Добавить',
72
+ cancel: 'Отмена',
73
+ link: {
74
+ title: 'Добавить ссылку',
75
+ titleField: {
76
+ label: 'Текст',
77
+ placeholder: 'Текст ссылки',
78
+ },
79
+ urlField: {
80
+ label: 'URL',
81
+ placeholder: 'https://',
82
+ },
83
+ },
84
+ image: {
85
+ title: 'Добавить изображение',
86
+ url: 'URL',
87
+ alt: 'Альтернативный текст',
88
+ placeholder: 'https://',
89
+ },
90
+ table: {
91
+ pickSize: 'Выберите размер',
92
+ insert: 'Вставить таблицу {{rows}} × {{cols}}',
93
+ column: 'Колонка {{index}}',
94
+ customize: 'Настроить таблицу',
95
+ columns: 'Столбцы',
96
+ rows: 'Строки',
97
+ },
98
+ linkText: 'текст ссылки',
99
+ },
100
+ });
101
+
102
+ export type MarkdownMessages = (typeof MARKDOWN_MESSAGES)['en-GB'];
103
+
104
+ /** locale компонента Markdown: `markdownLocale.useTranslations()` в коде, `markdownLocale.extend(...)` в сервисе. */
105
+ export const markdownLocale = defineLocale('@cloud-ru/ds-markdown', MARKDOWN_MESSAGES);
@@ -0,0 +1,30 @@
1
+ import bash from 'highlight.js/lib/languages/bash';
2
+ import css from 'highlight.js/lib/languages/css';
3
+ import diff from 'highlight.js/lib/languages/diff';
4
+ import go from 'highlight.js/lib/languages/go';
5
+ import javascript from 'highlight.js/lib/languages/javascript';
6
+ import json from 'highlight.js/lib/languages/json';
7
+ import markdown from 'highlight.js/lib/languages/markdown';
8
+ import python from 'highlight.js/lib/languages/python';
9
+ import scss from 'highlight.js/lib/languages/scss';
10
+ import shell from 'highlight.js/lib/languages/shell';
11
+ import typescript from 'highlight.js/lib/languages/typescript';
12
+ import xml from 'highlight.js/lib/languages/xml';
13
+ import yaml from 'highlight.js/lib/languages/yaml';
14
+ import { createLowlight } from 'lowlight';
15
+
16
+ export const lowlight = createLowlight({
17
+ bash,
18
+ css,
19
+ diff,
20
+ go,
21
+ javascript,
22
+ json,
23
+ markdown,
24
+ python,
25
+ scss,
26
+ shell,
27
+ typescript,
28
+ xml,
29
+ yaml,
30
+ });
@@ -0,0 +1,123 @@
1
+ @use '@cloud-ru/ds-figma-variables/build/scss/styles/styles.module' as base;
2
+ @use '@cloud-ru/ds-figma-variables/build/scss/components/markdown.module' as md;
3
+
4
+ // Общие стили markdown-контента: типографика блоков и top-spacing'и.
5
+ // Подключаются и во viewer (`Markdown`), и в editor (`MarkdownEditor` → .ProseMirror),
6
+ // чтобы блоки выглядели одинаково в обоих режимах и правились в одном месте.
7
+
8
+ // Композитные typography-роли заголовков: один токен разворачивается в font-* через composite-var.
9
+ $headings: (
10
+ 'h1': base.$sn-regular-headline-l,
11
+ 'h2': base.$sn-regular-headline-m,
12
+ 'h3': base.$sn-regular-headline-s,
13
+ 'h4': base.$sn-regular-title-l,
14
+ 'h5': base.$sn-regular-title-m,
15
+ );
16
+
17
+ // Top-spacing на каждый блок (paddingTop при наличии предыдущего соседа).
18
+ $block-top-spacings: (
19
+ 'h1': md.$sn-markdown-anatomy-size-syntax-headings-h1-paddingTop,
20
+ 'h2': md.$sn-markdown-anatomy-size-syntax-headings-h2-paddingTop,
21
+ 'h3': md.$sn-markdown-anatomy-size-syntax-headings-h3-paddingTop,
22
+ 'h4': md.$sn-markdown-anatomy-size-syntax-headings-h4-paddingTop,
23
+ 'h5': md.$sn-markdown-anatomy-size-syntax-headings-h5-paddingTop,
24
+ 'blockquote': md.$sn-markdown-anatomy-size-syntax-quote-paddingTop,
25
+ 'pre': md.$sn-markdown-anatomy-size-syntax-codeEditor-paddingTop,
26
+ 'table': md.$sn-markdown-anatomy-size-syntax-table-paddingTop,
27
+ 'img': md.$sn-markdown-anatomy-size-syntax-image-paddingTop,
28
+ 'hr': md.$sn-markdown-anatomy-size-syntax-divider-paddingTop,
29
+ );
30
+
31
+ @mixin markdown-content {
32
+ p,
33
+ h1,
34
+ h2,
35
+ h3,
36
+ h4,
37
+ h5,
38
+ ul,
39
+ ol,
40
+ blockquote,
41
+ pre,
42
+ table,
43
+ hr,
44
+ img {
45
+ margin: 0;
46
+ }
47
+
48
+ @each $tag, $token in $headings {
49
+ #{$tag} {
50
+ @include base.composite-var($headings, $tag);
51
+ }
52
+ }
53
+
54
+ ul,
55
+ ol {
56
+ padding-left: base.$sn-primitive-dimension-24;
57
+ }
58
+
59
+ blockquote {
60
+ padding: md.$sn-markdown-anatomy-size-syntax-quote-wrapper-paddingVertical
61
+ md.$sn-markdown-anatomy-size-syntax-quote-wrapper-paddingHorizontal;
62
+ border-left: md.$sn-markdown-anatomy-size-syntax-quote-wrapper-borderWidth solid
63
+ md.$sn-theme-color-available-borderColor;
64
+ color: md.$sn-theme-color-available-version-textMain;
65
+ background: base.$sn-theme-color-neutral-decorTransparent;
66
+ }
67
+
68
+ code {
69
+ min-height: md.$sn-markdown-anatomy-size-syntax-inlineCode-minHeight;
70
+ padding: 0 md.$sn-markdown-anatomy-size-syntax-inlineCode-paddingHorizontal;
71
+ border-radius: md.$sn-markdown-anatomy-size-syntax-inlineCode-borderRadius;
72
+
73
+ font-family: md.$sn-brand-font-fontFamily-mono-body;
74
+
75
+ background: md.$sn-theme-color-neutral-decorTransparent;
76
+ }
77
+
78
+ a {
79
+ color: md.$sn-theme-color-neutral-accent;
80
+ text-decoration: underline;
81
+ }
82
+
83
+ table {
84
+ border-collapse: collapse;
85
+ width: 100%;
86
+ }
87
+
88
+ th,
89
+ td {
90
+ min-height: md.$sn-markdown-anatomy-size-syntax-table-tableCell-minHeight;
91
+ padding: md.$sn-markdown-anatomy-size-syntax-table-tableCell-paddingVertical
92
+ md.$sn-markdown-anatomy-size-syntax-table-tableCell-paddingHorizontal;
93
+ // Ячейка несёт только нижнюю линейку: в мастере вертикальных границ нет, соседние
94
+ // ячейки стыкуются вплотную.
95
+ border-bottom: md.$sn-primitive-strokeWeight-strokeRegular solid md.$sn-theme-color-available-borderColor;
96
+ text-align: left;
97
+ }
98
+
99
+ th {
100
+ font-weight: 600;
101
+ background: base.$sn-theme-color-neutral-decorTransparent;
102
+ }
103
+ }
104
+
105
+ // Top-spacings: каждый блок имеет свой paddingTop.
106
+ // Default — paragraph; конкретные блоки переопределяют.
107
+ @mixin markdown-block-spacings {
108
+ > *:not(:first-child) {
109
+ margin-top: md.$sn-markdown-anatomy-size-syntax-paragraphs-paddingTop;
110
+ }
111
+
112
+ // Списки делят один токен — задаём отдельно от карты блоков.
113
+ > ul:not(:first-child),
114
+ > ol:not(:first-child) {
115
+ margin-top: md.$sn-markdown-anatomy-size-syntax-list-paddingTop;
116
+ }
117
+
118
+ @each $tag, $padding-top in $block-top-spacings {
119
+ > #{$tag}:not(:first-child) {
120
+ margin-top: $padding-top;
121
+ }
122
+ }
123
+ }