@jvs-milkdown/crepe 1.2.0 → 1.2.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.
Files changed (75) hide show
  1. package/lib/cjs/builder.js +55 -2
  2. package/lib/cjs/builder.js.map +1 -1
  3. package/lib/cjs/feature/block-edit/index.js +73 -5
  4. package/lib/cjs/feature/block-edit/index.js.map +1 -1
  5. package/lib/cjs/feature/code-mirror/index.js +65 -3
  6. package/lib/cjs/feature/code-mirror/index.js.map +1 -1
  7. package/lib/cjs/feature/cursor/index.js +55 -2
  8. package/lib/cjs/feature/cursor/index.js.map +1 -1
  9. package/lib/cjs/feature/image-block/index.js +76 -8
  10. package/lib/cjs/feature/image-block/index.js.map +1 -1
  11. package/lib/cjs/feature/latex/index.js +55 -2
  12. package/lib/cjs/feature/latex/index.js.map +1 -1
  13. package/lib/cjs/feature/link-tooltip/index.js +55 -2
  14. package/lib/cjs/feature/link-tooltip/index.js.map +1 -1
  15. package/lib/cjs/feature/list-item/index.js +55 -2
  16. package/lib/cjs/feature/list-item/index.js.map +1 -1
  17. package/lib/cjs/feature/placeholder/index.js +55 -2
  18. package/lib/cjs/feature/placeholder/index.js.map +1 -1
  19. package/lib/cjs/feature/table/index.js +55 -2
  20. package/lib/cjs/feature/table/index.js.map +1 -1
  21. package/lib/cjs/feature/toolbar/index.js +73 -5
  22. package/lib/cjs/feature/toolbar/index.js.map +1 -1
  23. package/lib/cjs/index.js +451 -30
  24. package/lib/cjs/index.js.map +1 -1
  25. package/lib/esm/builder.js +55 -2
  26. package/lib/esm/builder.js.map +1 -1
  27. package/lib/esm/feature/block-edit/index.js +73 -5
  28. package/lib/esm/feature/block-edit/index.js.map +1 -1
  29. package/lib/esm/feature/code-mirror/index.js +65 -3
  30. package/lib/esm/feature/code-mirror/index.js.map +1 -1
  31. package/lib/esm/feature/cursor/index.js +55 -2
  32. package/lib/esm/feature/cursor/index.js.map +1 -1
  33. package/lib/esm/feature/image-block/index.js +76 -8
  34. package/lib/esm/feature/image-block/index.js.map +1 -1
  35. package/lib/esm/feature/latex/index.js +55 -2
  36. package/lib/esm/feature/latex/index.js.map +1 -1
  37. package/lib/esm/feature/link-tooltip/index.js +55 -2
  38. package/lib/esm/feature/link-tooltip/index.js.map +1 -1
  39. package/lib/esm/feature/list-item/index.js +55 -2
  40. package/lib/esm/feature/list-item/index.js.map +1 -1
  41. package/lib/esm/feature/placeholder/index.js +55 -2
  42. package/lib/esm/feature/placeholder/index.js.map +1 -1
  43. package/lib/esm/feature/table/index.js +55 -2
  44. package/lib/esm/feature/table/index.js.map +1 -1
  45. package/lib/esm/feature/toolbar/index.js +73 -5
  46. package/lib/esm/feature/toolbar/index.js.map +1 -1
  47. package/lib/esm/index.js +452 -31
  48. package/lib/esm/index.js.map +1 -1
  49. package/lib/theme/common/code-mirror.css +13 -0
  50. package/lib/theme/common/image-block.css +321 -22
  51. package/lib/theme/common/reset.css +3 -0
  52. package/lib/theme/common/toolbar.css +27 -2
  53. package/lib/tsconfig.tsbuildinfo +1 -1
  54. package/package.json +4 -4
  55. package/src/core/locale.ts +55 -0
  56. package/src/feature/block-edit/menu/config.ts +19 -3
  57. package/src/feature/code-mirror/index.ts +3 -0
  58. package/src/feature/fixed-toolbar/component.tsx +31 -2
  59. package/src/feature/fixed-toolbar/config.ts +18 -3
  60. package/src/feature/fixed-toolbar/document-header.tsx +8 -4
  61. package/src/feature/fixed-toolbar/index.ts +18 -1
  62. package/src/feature/fixed-toolbar/menu-bar.tsx +83 -2
  63. package/src/feature/fixed-toolbar/shortcut-help-modal.tsx +244 -0
  64. package/src/feature/fixed-toolbar/view-menu-state.ts +9 -0
  65. package/src/feature/image-block/index.ts +11 -1
  66. package/src/icons/border.ts +5 -0
  67. package/src/icons/close.ts +3 -0
  68. package/src/icons/crop.ts +6 -0
  69. package/src/icons/index.ts +5 -0
  70. package/src/icons/keyboard.ts +3 -0
  71. package/src/icons/word-wrap.ts +6 -0
  72. package/src/theme/common/code-mirror.css +13 -0
  73. package/src/theme/common/image-block.css +364 -23
  74. package/src/theme/common/reset.css +3 -0
  75. package/src/theme/common/toolbar.css +30 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jvs-milkdown/crepe",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "keywords": [
5
5
  "crepe",
6
6
  "editor",
@@ -97,9 +97,9 @@
97
97
  "@codemirror/theme-one-dark": "^6.1.2",
98
98
  "@codemirror/view": "^6.26.0",
99
99
  "@floating-ui/dom": "^1.7.6",
100
- "@jvs-milkdown/kit": "^1.2.0",
101
- "@jvs-milkdown/prose": "^1.2.0",
102
- "@jvs-milkdown/utils": "^1.2.0",
100
+ "@jvs-milkdown/kit": "^1.2.1",
101
+ "@jvs-milkdown/prose": "^1.2.1",
102
+ "@jvs-milkdown/utils": "^1.2.1",
103
103
  "@types/lodash-es": "^4.17.12",
104
104
  "clsx": "^2.0.0",
105
105
  "codemirror": "^6.0.1",
@@ -29,6 +29,10 @@ export const zhCN = {
29
29
  'view.docBackground': '文档背景色',
30
30
  'view.title': '显示标题',
31
31
  'view.cover': '显示封面',
32
+ 'view.editorWidth': '内容宽度',
33
+ 'view.widthDefault': '默认',
34
+ 'view.widthWide': '较宽',
35
+ 'view.widthFull': '全宽',
32
36
 
33
37
  // code-mirror
34
38
  'codeMirror.searchPlaceholder': '搜索语言',
@@ -36,6 +40,7 @@ export const zhCN = {
36
40
  'codeMirror.previewToggleOptionEdit': '编辑',
37
41
  'codeMirror.previewToggleOptionHide': '隐藏',
38
42
  'codeMirror.previewLabel': '预览',
43
+ 'codeMirror.wrapText': '自动换行',
39
44
 
40
45
  // link-tooltip
41
46
  'linkTooltip.pasteLink': '粘贴链接...',
@@ -144,6 +149,29 @@ export const zhCN = {
144
149
  'latex.helpDoc': '查看帮助文档',
145
150
  'latex.emptyPlaceholder': '添加 LaTeX 公式',
146
151
  'latex.inputPlaceholder': '请输入公式',
152
+
153
+ // shortcuts
154
+ 'shortcuts.title': '键盘快捷键',
155
+ 'shortcuts.formatting': '文本格式',
156
+ 'shortcuts.bold': '加粗',
157
+ 'shortcuts.italic': '斜体',
158
+ 'shortcuts.underline': '下划线',
159
+ 'shortcuts.strikethrough': '删除线',
160
+ 'shortcuts.inlineCode': '行内代码',
161
+ 'shortcuts.highlight': '高亮',
162
+ 'shortcuts.paragraph': '段落',
163
+ 'shortcuts.heading': '标题',
164
+ 'shortcuts.block': '块级元素',
165
+ 'shortcuts.codeBlock': '代码块',
166
+ 'shortcuts.blockquote': '引用',
167
+ 'shortcuts.orderedList': '有序列表',
168
+ 'shortcuts.bulletList': '无序列表',
169
+ 'shortcuts.indent': '增加缩进',
170
+ 'shortcuts.outdent': '减少缩进',
171
+ 'shortcuts.hardBreak': '换行',
172
+ 'shortcuts.history': '历史记录',
173
+ 'shortcuts.undo': '撤销',
174
+ 'shortcuts.redo': '重做',
147
175
  }
148
176
 
149
177
  export const enUS: typeof zhCN = {
@@ -168,12 +196,17 @@ export const enUS: typeof zhCN = {
168
196
  'view.docBackground': 'Document Background',
169
197
  'view.title': 'Show Title',
170
198
  'view.cover': 'Show Cover',
199
+ 'view.editorWidth': 'Content Width',
200
+ 'view.widthDefault': 'Default',
201
+ 'view.widthWide': 'Wide',
202
+ 'view.widthFull': 'Full Width',
171
203
 
172
204
  'codeMirror.searchPlaceholder': 'Search language',
173
205
  'codeMirror.noResultText': 'No result',
174
206
  'codeMirror.previewToggleOptionEdit': 'Edit',
175
207
  'codeMirror.previewToggleOptionHide': 'Hide',
176
208
  'codeMirror.previewLabel': 'Preview',
209
+ 'codeMirror.wrapText': 'Wrap',
177
210
 
178
211
  'linkTooltip.pasteLink': 'Paste link...',
179
212
 
@@ -274,6 +307,28 @@ export const enUS: typeof zhCN = {
274
307
  'latex.helpDoc': 'Help Doc',
275
308
  'latex.emptyPlaceholder': 'Add LaTeX',
276
309
  'latex.inputPlaceholder': 'Please enter formula',
310
+
311
+ 'shortcuts.title': 'Keyboard Shortcuts',
312
+ 'shortcuts.formatting': 'Text Formatting',
313
+ 'shortcuts.bold': 'Bold',
314
+ 'shortcuts.italic': 'Italic',
315
+ 'shortcuts.underline': 'Underline',
316
+ 'shortcuts.strikethrough': 'Strikethrough',
317
+ 'shortcuts.inlineCode': 'Inline Code',
318
+ 'shortcuts.highlight': 'Highlight',
319
+ 'shortcuts.paragraph': 'Paragraph',
320
+ 'shortcuts.heading': 'Heading',
321
+ 'shortcuts.block': 'Block Elements',
322
+ 'shortcuts.codeBlock': 'Code Block',
323
+ 'shortcuts.blockquote': 'Blockquote',
324
+ 'shortcuts.orderedList': 'Ordered List',
325
+ 'shortcuts.bulletList': 'Bullet List',
326
+ 'shortcuts.indent': 'Indent',
327
+ 'shortcuts.outdent': 'Outdent',
328
+ 'shortcuts.hardBreak': 'Hard Break',
329
+ 'shortcuts.history': 'History',
330
+ 'shortcuts.undo': 'Undo',
331
+ 'shortcuts.redo': 'Redo',
277
332
  }
278
333
 
279
334
  export type CrepeTranslations = typeof zhCN
@@ -25,6 +25,7 @@ import {
25
25
  import { createTable } from '@jvs-milkdown/kit/preset/gfm'
26
26
  import { findNodeInSelection } from '@jvs-milkdown/kit/prose'
27
27
  import { lift } from '@jvs-milkdown/kit/prose/commands'
28
+ import { wrapInList } from '@jvs-milkdown/kit/prose/schema-list'
28
29
  import { TextSelection } from '@jvs-milkdown/kit/prose/state'
29
30
 
30
31
  import type { BlockEditFeatureConfig } from '../index'
@@ -711,10 +712,25 @@ export function getGroups(
711
712
 
712
713
  // Convert heading to paragraph first, then wrap
713
714
  convertHeadingToParagraphIfNeeded(ctx)
714
- commands.call(wrapInBlockTypeCommand.key, {
715
- nodeType: listItem,
716
- attrs: { checked: false },
715
+ const result = wrapInList(bulletList)(view.state, (tr) => {
716
+ // Set checked attribute on each list item
717
+ tr.doc.nodesBetween(
718
+ tr.mapping.map(from),
719
+ tr.mapping.map(to),
720
+ (node, pos) => {
721
+ if (node.type === listItem) {
722
+ tr.setNodeMarkup(pos, undefined, {
723
+ ...node.attrs,
724
+ checked: false,
725
+ listType: 'bullet',
726
+ label: '•',
727
+ })
728
+ }
729
+ }
730
+ )
731
+ view.dispatch(tr)
717
732
  })
733
+ if (result) return
718
734
  },
719
735
  })
720
736
  }
@@ -20,6 +20,7 @@ import {
20
20
  editIcon,
21
21
  searchIcon,
22
22
  visibilityOffIcon,
23
+ wordWrapIcon,
23
24
  } from '../../icons'
24
25
  import { CrepeFeature } from '../index'
25
26
 
@@ -82,6 +83,8 @@ export const codeMirror: DefineFeature<CodeMirrorFeatureConfig> = (
82
83
  previewLoading: config.previewLoading || defaultConfig.previewLoading,
83
84
  previewOnlyByDefault:
84
85
  config.previewOnlyByDefault ?? defaultConfig.previewOnlyByDefault,
86
+ wrapText: config.wrapText || i18n(ctx, 'codeMirror.wrapText'),
87
+ wrapIcon: config.wrapIcon || wordWrapIcon,
85
88
  }))
86
89
  })
87
90
  .use(codeBlockComponent)
@@ -1,12 +1,16 @@
1
1
  import type { Ctx } from '@jvs-milkdown/kit/ctx'
2
2
  import type { Selection } from '@jvs-milkdown/kit/prose/state'
3
3
 
4
- import { defineComponent, type ShallowRef, type Ref, h } from 'vue'
4
+ import { Icon } from '@jvs-milkdown/kit/component'
5
+ import { defineComponent, type ShallowRef, type Ref, h, ref } from 'vue'
5
6
 
6
7
  import type { FixedToolbarFeatureConfig } from '.'
7
8
 
9
+ import { i18n } from '../../core/locale'
10
+ import { keyboardIcon } from '../../icons'
8
11
  import { Toolbar } from '../toolbar/component'
9
12
  import { MenuBar } from './menu-bar'
13
+ import { ShortcutHelpModal } from './shortcut-help-modal'
10
14
 
11
15
  type FixedToolbarProps = {
12
16
  ctx: Ctx
@@ -25,6 +29,8 @@ export const FixedToolbarComponent = defineComponent<FixedToolbarProps>({
25
29
  config: { type: Object, required: false },
26
30
  },
27
31
  setup(props) {
32
+ const showShortcuts = ref(false)
33
+
28
34
  return () => (
29
35
  <div
30
36
  style={{
@@ -32,7 +38,7 @@ export const FixedToolbarComponent = defineComponent<FixedToolbarProps>({
32
38
  alignItems: 'center',
33
39
  justifyContent: 'center',
34
40
  width: '100%',
35
- gap: '12px',
41
+ gap: '0px',
36
42
  }}
37
43
  >
38
44
  <MenuBar ctx={props.ctx} config={props.config} />
@@ -53,6 +59,29 @@ export const FixedToolbarComponent = defineComponent<FixedToolbarProps>({
53
59
  config={props.config as any}
54
60
  isFixed={true}
55
61
  />
62
+ <div
63
+ style={{
64
+ width: '1px',
65
+ minWidth: '1px',
66
+ height: '20px',
67
+ flexShrink: 0,
68
+ backgroundColor:
69
+ 'var(--crepe-color-outline-variant, color-mix(in srgb, var(--crepe-color-outline), transparent 80%))',
70
+ }}
71
+ />
72
+ <button
73
+ type="button"
74
+ class="toolbar-shortcut-btn"
75
+ title={i18n(props.ctx, 'shortcuts.title')}
76
+ onClick={() => {
77
+ showShortcuts.value = true
78
+ }}
79
+ >
80
+ <Icon icon={keyboardIcon} />
81
+ </button>
82
+ {showShortcuts.value && (
83
+ <ShortcutHelpModal ctx={props.ctx} visible={showShortcuts} />
84
+ )}
56
85
  </div>
57
86
  )
58
87
  },
@@ -23,6 +23,7 @@ import {
23
23
  import { createTable } from '@jvs-milkdown/kit/preset/gfm'
24
24
  import { findNodeInSelection } from '@jvs-milkdown/kit/prose'
25
25
  import { lift } from '@jvs-milkdown/kit/prose/commands'
26
+ import { wrapInList } from '@jvs-milkdown/kit/prose/schema-list'
26
27
 
27
28
  import type { GroupBuilder } from '../../utils'
28
29
  import type { ToolbarItem } from '../toolbar/config'
@@ -477,10 +478,24 @@ export function buildDefaultFixedToolbar(
477
478
  }
478
479
 
479
480
  convertHeadingToParagraphIfNeeded(ctx)
480
- commands.call(wrapInBlockTypeCommand.key, {
481
- nodeType: listItem,
482
- attrs: { checked: false },
481
+ const result = wrapInList(bulletList)(view.state, (tr) => {
482
+ tr.doc.nodesBetween(
483
+ tr.mapping.map(from),
484
+ tr.mapping.map(to),
485
+ (node, pos) => {
486
+ if (node.type === listItem) {
487
+ tr.setNodeMarkup(pos, undefined, {
488
+ ...node.attrs,
489
+ checked: false,
490
+ listType: 'bullet',
491
+ label: '•',
492
+ })
493
+ }
494
+ }
495
+ )
496
+ view.dispatch(tr)
483
497
  })
498
+ if (result) return
484
499
  },
485
500
  })
486
501
  }
@@ -5,7 +5,7 @@ import { defineComponent, computed, ref, watch, h } from 'vue'
5
5
  import type { FixedToolbarConfig } from './index'
6
6
 
7
7
  import { builtInCoverImages, randomCover } from './cover-defaults'
8
- import { viewMenuStateCtx } from './view-menu-state'
8
+ import { viewMenuStateCtx, editorWidthMap } from './view-menu-state'
9
9
 
10
10
  export const DocumentHeader = defineComponent({
11
11
  props: {
@@ -237,9 +237,13 @@ export const DocumentHeader = defineComponent({
237
237
  class="milkdown-document-title-wrapper"
238
238
  style={{
239
239
  width: '100%',
240
- // maxWidth: '900px',
241
- // margin: '0 auto',
242
- padding: '40px 120px 0', // Match ProseMirror padding
240
+ maxWidth:
241
+ editorWidthMap[state.editorWidth] === 'none'
242
+ ? undefined
243
+ : editorWidthMap[state.editorWidth],
244
+ margin:
245
+ editorWidthMap[state.editorWidth] === 'none' ? '0' : '0 auto',
246
+ padding: `40px ${editorWidthMap[state.editorWidth] === 'none' ? '80px' : '0'} 0`,
243
247
  }}
244
248
  >
245
249
  <style>{`.milkdown-document-title::placeholder { color: #BFBFBF; }`}</style>
@@ -25,7 +25,7 @@ import { FixedToolbarComponent } from './component'
25
25
  import { buildDefaultFixedToolbar } from './config'
26
26
  import { DocumentHeader } from './document-header'
27
27
  import { OutlinePanel } from './outline-panel'
28
- import { viewMenuStateCtx } from './view-menu-state'
28
+ import { viewMenuStateCtx, editorWidthMap } from './view-menu-state'
29
29
 
30
30
  export interface FixedToolbarConfig {
31
31
  boldIcon?: string
@@ -65,8 +65,10 @@ class FixedToolbarView implements PluginView {
65
65
  #resizeObserver?: ResizeObserver
66
66
  #updateOutlineGeometry?: () => void
67
67
  #scrollContainers: Element[] = []
68
+ #view: EditorView
68
69
 
69
70
  constructor(ctx: Ctx, view: EditorView) {
71
+ this.#view = view
70
72
  const config = ctx.get(fixedToolbarConfig.key)
71
73
  const content = document.createElement('div')
72
74
  content.className = 'milkdown-fixed-toolbar'
@@ -185,6 +187,7 @@ class FixedToolbarView implements PluginView {
185
187
  viewState.outlineWidth,
186
188
  viewState.documentBackground,
187
189
  viewState.showCover,
190
+ viewState.editorWidth,
188
191
  ],
189
192
  () => {
190
193
  if (viewState.documentBackground) {
@@ -215,6 +218,20 @@ class FixedToolbarView implements PluginView {
215
218
  this.#content.style.marginRight = '0'
216
219
  }
217
220
 
221
+ const maxWidth = editorWidthMap[viewState.editorWidth]
222
+ const isFull = maxWidth === 'none'
223
+ const px = isFull ? '80px' : '0'
224
+ this.#view.dom.style.maxWidth = maxWidth
225
+ this.#view.dom.style.width = isFull ? '100%' : maxWidth
226
+ this.#view.dom.style.margin = isFull ? '0' : '0 auto'
227
+ this.#view.dom.style.padding = `20px ${px} 0`
228
+ if (this.#headerContent) {
229
+ // this.#headerContent.style.maxWidth = maxWidth
230
+ // this.#headerContent.style.width = isFull ? '100%' : maxWidth
231
+ this.#headerContent.style.margin = isFull ? '0' : '0 auto'
232
+ this.#headerContent.style.padding = `0px`
233
+ }
234
+
218
235
  // Compute geometry after styles and DOM (cover) are updated
219
236
  nextTick(() => {
220
237
  this.#updateOutlineGeometry?.()
@@ -8,7 +8,7 @@ import type { FixedToolbarConfig } from './index'
8
8
  import { i18n } from '../../core/locale'
9
9
  import { menuIcon } from '../../icons'
10
10
  import { randomCover } from './cover-defaults'
11
- import { viewMenuStateCtx } from './view-menu-state'
11
+ import { viewMenuStateCtx, type EditorWidth } from './view-menu-state'
12
12
 
13
13
  // Simple iOS-style Toggle Switch
14
14
  const ToggleSwitch = defineComponent({
@@ -142,7 +142,7 @@ export const MenuBar = defineComponent({
142
142
  style={{
143
143
  display: 'flex',
144
144
  alignItems: 'center',
145
- padding: '0 0px',
145
+ padding: '0 6px 0 0',
146
146
  position: 'relative',
147
147
  }}
148
148
  >
@@ -453,6 +453,87 @@ export const MenuBar = defineComponent({
453
453
  </div>
454
454
  ))}
455
455
  </div>
456
+
457
+ <div
458
+ style={{
459
+ height: '1px',
460
+ background:
461
+ 'var(--crepe-color-outline-variant, #eee)',
462
+ margin: '4px 0',
463
+ }}
464
+ />
465
+
466
+ <div
467
+ style={{
468
+ padding: '8px 16px',
469
+ display: 'flex',
470
+ justifyContent: 'space-between',
471
+ alignItems: 'center',
472
+ }}
473
+ >
474
+ <span
475
+ style={{
476
+ fontSize: '14px',
477
+ color: 'var(--crepe-color-on-surface, #333)',
478
+ }}
479
+ >
480
+ {i18n(props.ctx, 'view.editorWidth' as any) ||
481
+ '内容宽度'}
482
+ </span>
483
+ </div>
484
+
485
+ <div
486
+ style={{
487
+ padding: '4px 16px 8px',
488
+ display: 'flex',
489
+ gap: '6px',
490
+ }}
491
+ >
492
+ {[
493
+ {
494
+ key: 'default' as EditorWidth,
495
+ labelKey: 'view.widthDefault',
496
+ },
497
+ {
498
+ key: 'wide' as EditorWidth,
499
+ labelKey: 'view.widthWide',
500
+ },
501
+ {
502
+ key: 'full' as EditorWidth,
503
+ labelKey: 'view.widthFull',
504
+ },
505
+ ].map(({ key, labelKey }) => (
506
+ <button
507
+ key={key}
508
+ type="button"
509
+ onClick={(e) => {
510
+ e.stopPropagation()
511
+ state.editorWidth = key
512
+ }}
513
+ style={{
514
+ flex: 1,
515
+ padding: '4px 0',
516
+ fontSize: '12px',
517
+ cursor: 'pointer',
518
+ borderRadius: '4px',
519
+ border:
520
+ state.editorWidth === key
521
+ ? '1px solid var(--crepe-color-primary, #1890ff)'
522
+ : '1px solid var(--crepe-color-outline-variant, #e8e8e8)',
523
+ background:
524
+ state.editorWidth === key
525
+ ? 'var(--crepe-color-primary, #1890ff)'
526
+ : 'transparent',
527
+ color:
528
+ state.editorWidth === key
529
+ ? '#fff'
530
+ : 'var(--crepe-color-on-surface, #333)',
531
+ }}
532
+ >
533
+ {i18n(props.ctx, labelKey as any) || key}
534
+ </button>
535
+ ))}
536
+ </div>
456
537
  </div>
457
538
  ) : null}
458
539
  </div>