@jvs-milkdown/components 1.1.9 → 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 (139) hide show
  1. package/lib/code-block/index.js +37 -2
  2. package/lib/code-block/index.js.map +1 -1
  3. package/lib/image-block/index.js +628 -107
  4. package/lib/image-block/index.js.map +1 -1
  5. package/lib/table-block/index.js +135 -64
  6. package/lib/table-block/index.js.map +1 -1
  7. package/lib/tsconfig.tsbuildinfo +1 -1
  8. package/package.json +10 -10
  9. package/src/code-block/config.ts +4 -0
  10. package/src/code-block/view/components/code-block.tsx +24 -0
  11. package/src/code-block/view/node-view.ts +15 -0
  12. package/src/image-block/config.ts +10 -0
  13. package/src/image-block/schema.ts +16 -0
  14. package/src/image-block/view/components/__tests__/image-viewer.onImageLoadError.spec.tsx +14 -0
  15. package/src/image-block/view/components/image-block.tsx +40 -0
  16. package/src/image-block/view/components/image-viewer.tsx +548 -65
  17. package/src/image-block/view/index.ts +42 -0
  18. package/src/table-block/view/component.tsx +116 -46
  19. package/src/table-block/view/operation.ts +55 -30
  20. package/lib/__internal__/components/icon.d.ts +0 -24
  21. package/lib/__internal__/components/icon.d.ts.map +0 -1
  22. package/lib/__internal__/components/image-input.d.ts +0 -17
  23. package/lib/__internal__/components/image-input.d.ts.map +0 -1
  24. package/lib/__internal__/keep-alive.d.ts +0 -2
  25. package/lib/__internal__/keep-alive.d.ts.map +0 -1
  26. package/lib/__internal__/meta.d.ts +0 -3
  27. package/lib/__internal__/meta.d.ts.map +0 -1
  28. package/lib/__tests__/setup.d.ts +0 -2
  29. package/lib/__tests__/setup.d.ts.map +0 -1
  30. package/lib/code-block/config.d.ts +0 -23
  31. package/lib/code-block/config.d.ts.map +0 -1
  32. package/lib/code-block/index.d.ts +0 -5
  33. package/lib/code-block/index.d.ts.map +0 -1
  34. package/lib/code-block/view/components/code-block.d.ts +0 -16
  35. package/lib/code-block/view/components/code-block.d.ts.map +0 -1
  36. package/lib/code-block/view/components/copy-button.d.ts +0 -9
  37. package/lib/code-block/view/components/copy-button.d.ts.map +0 -1
  38. package/lib/code-block/view/components/language-picker.d.ts +0 -5
  39. package/lib/code-block/view/components/language-picker.d.ts.map +0 -1
  40. package/lib/code-block/view/components/preview-panel.d.ts +0 -9
  41. package/lib/code-block/view/components/preview-panel.d.ts.map +0 -1
  42. package/lib/code-block/view/index.d.ts +0 -3
  43. package/lib/code-block/view/index.d.ts.map +0 -1
  44. package/lib/code-block/view/loader.d.ts +0 -13
  45. package/lib/code-block/view/loader.d.ts.map +0 -1
  46. package/lib/code-block/view/node-view.d.ts +0 -40
  47. package/lib/code-block/view/node-view.d.ts.map +0 -1
  48. package/lib/image-block/config.d.ts +0 -16
  49. package/lib/image-block/config.d.ts.map +0 -1
  50. package/lib/image-block/convert-plugin.d.ts +0 -2
  51. package/lib/image-block/convert-plugin.d.ts.map +0 -1
  52. package/lib/image-block/index.d.ts +0 -9
  53. package/lib/image-block/index.d.ts.map +0 -1
  54. package/lib/image-block/paste-rule.d.ts +0 -2
  55. package/lib/image-block/paste-rule.d.ts.map +0 -1
  56. package/lib/image-block/remark-plugin.d.ts +0 -2
  57. package/lib/image-block/remark-plugin.d.ts.map +0 -1
  58. package/lib/image-block/schema.d.ts +0 -3
  59. package/lib/image-block/schema.d.ts.map +0 -1
  60. package/lib/image-block/view/components/__tests__/image-viewer.onImageLoadError.spec.d.ts +0 -2
  61. package/lib/image-block/view/components/__tests__/image-viewer.onImageLoadError.spec.d.ts.map +0 -1
  62. package/lib/image-block/view/components/image-block.d.ts +0 -19
  63. package/lib/image-block/view/components/image-block.d.ts.map +0 -1
  64. package/lib/image-block/view/components/image-viewer.d.ts +0 -3
  65. package/lib/image-block/view/components/image-viewer.d.ts.map +0 -1
  66. package/lib/image-block/view/index.d.ts +0 -3
  67. package/lib/image-block/view/index.d.ts.map +0 -1
  68. package/lib/image-inline/components/image-inline.d.ts +0 -18
  69. package/lib/image-inline/components/image-inline.d.ts.map +0 -1
  70. package/lib/image-inline/config.d.ts +0 -11
  71. package/lib/image-inline/config.d.ts.map +0 -1
  72. package/lib/image-inline/index.d.ts +0 -5
  73. package/lib/image-inline/index.d.ts.map +0 -1
  74. package/lib/image-inline/view.d.ts +0 -3
  75. package/lib/image-inline/view.d.ts.map +0 -1
  76. package/lib/index.d.ts +0 -2
  77. package/lib/index.d.ts.map +0 -1
  78. package/lib/link-tooltip/command.d.ts +0 -2
  79. package/lib/link-tooltip/command.d.ts.map +0 -1
  80. package/lib/link-tooltip/configure.d.ts +0 -3
  81. package/lib/link-tooltip/configure.d.ts.map +0 -1
  82. package/lib/link-tooltip/edit/component.d.ts +0 -11
  83. package/lib/link-tooltip/edit/component.d.ts.map +0 -1
  84. package/lib/link-tooltip/edit/edit-configure.d.ts +0 -3
  85. package/lib/link-tooltip/edit/edit-configure.d.ts.map +0 -1
  86. package/lib/link-tooltip/edit/edit-view.d.ts +0 -15
  87. package/lib/link-tooltip/edit/edit-view.d.ts.map +0 -1
  88. package/lib/link-tooltip/index.d.ts +0 -7
  89. package/lib/link-tooltip/index.d.ts.map +0 -1
  90. package/lib/link-tooltip/preview/component.d.ts +0 -11
  91. package/lib/link-tooltip/preview/component.d.ts.map +0 -1
  92. package/lib/link-tooltip/preview/preview-configure.d.ts +0 -3
  93. package/lib/link-tooltip/preview/preview-configure.d.ts.map +0 -1
  94. package/lib/link-tooltip/preview/preview-view.d.ts +0 -14
  95. package/lib/link-tooltip/preview/preview-view.d.ts.map +0 -1
  96. package/lib/link-tooltip/slices.d.ts +0 -34
  97. package/lib/link-tooltip/slices.d.ts.map +0 -1
  98. package/lib/link-tooltip/tooltips.d.ts +0 -3
  99. package/lib/link-tooltip/tooltips.d.ts.map +0 -1
  100. package/lib/link-tooltip/utils.d.ts +0 -14
  101. package/lib/link-tooltip/utils.d.ts.map +0 -1
  102. package/lib/list-item-block/component.d.ts +0 -19
  103. package/lib/list-item-block/component.d.ts.map +0 -1
  104. package/lib/list-item-block/config.d.ts +0 -13
  105. package/lib/list-item-block/config.d.ts.map +0 -1
  106. package/lib/list-item-block/index.d.ts +0 -6
  107. package/lib/list-item-block/index.d.ts.map +0 -1
  108. package/lib/list-item-block/view.d.ts +0 -3
  109. package/lib/list-item-block/view.d.ts.map +0 -1
  110. package/lib/table-block/config.d.ts +0 -8
  111. package/lib/table-block/config.d.ts.map +0 -1
  112. package/lib/table-block/dnd/calc-drag-over.d.ts +0 -3
  113. package/lib/table-block/dnd/calc-drag-over.d.ts.map +0 -1
  114. package/lib/table-block/dnd/create-drag-handler.d.ts +0 -5
  115. package/lib/table-block/dnd/create-drag-handler.d.ts.map +0 -1
  116. package/lib/table-block/dnd/drag-over-handler.d.ts +0 -3
  117. package/lib/table-block/dnd/drag-over-handler.d.ts.map +0 -1
  118. package/lib/table-block/dnd/prepare-dnd-context.d.ts +0 -3
  119. package/lib/table-block/dnd/prepare-dnd-context.d.ts.map +0 -1
  120. package/lib/table-block/dnd/preview.d.ts +0 -3
  121. package/lib/table-block/dnd/preview.d.ts.map +0 -1
  122. package/lib/table-block/index.d.ts +0 -5
  123. package/lib/table-block/index.d.ts.map +0 -1
  124. package/lib/table-block/view/component.d.ts +0 -16
  125. package/lib/table-block/view/component.d.ts.map +0 -1
  126. package/lib/table-block/view/drag.d.ts +0 -10
  127. package/lib/table-block/view/drag.d.ts.map +0 -1
  128. package/lib/table-block/view/index.d.ts +0 -2
  129. package/lib/table-block/view/index.d.ts.map +0 -1
  130. package/lib/table-block/view/operation.d.ts +0 -13
  131. package/lib/table-block/view/operation.d.ts.map +0 -1
  132. package/lib/table-block/view/pointer.d.ts +0 -7
  133. package/lib/table-block/view/pointer.d.ts.map +0 -1
  134. package/lib/table-block/view/types.d.ts +0 -28
  135. package/lib/table-block/view/types.d.ts.map +0 -1
  136. package/lib/table-block/view/utils.d.ts +0 -12
  137. package/lib/table-block/view/utils.d.ts.map +0 -1
  138. package/lib/table-block/view/view.d.ts +0 -22
  139. package/lib/table-block/view/view.d.ts.map +0 -1
@@ -18,6 +18,14 @@ export const imageBlockView = $view(
18
18
  const caption = ref(initialNode.attrs.caption)
19
19
  const ratio = ref(initialNode.attrs.ratio)
20
20
  const align = ref(initialNode.attrs.align)
21
+ const cropRatio = ref(initialNode.attrs.cropRatio)
22
+ const cropTop = ref(initialNode.attrs.cropTop)
23
+ const cropLeft = ref(initialNode.attrs.cropLeft)
24
+ const cropWidth = ref(initialNode.attrs.cropWidth)
25
+ const cropHeight = ref(initialNode.attrs.cropHeight)
26
+ const borderWidth = ref(initialNode.attrs.borderWidth)
27
+ const borderColor = ref(initialNode.attrs.borderColor)
28
+ const borderStyle = ref(initialNode.attrs.borderStyle)
21
29
  const selected = ref(false)
22
30
  const readonly = ref(!view.editable)
23
31
  const setAttr = (attr: string, value: unknown) => {
@@ -38,6 +46,14 @@ export const imageBlockView = $view(
38
46
  caption,
39
47
  ratio,
40
48
  align,
49
+ cropRatio,
50
+ cropTop,
51
+ cropLeft,
52
+ cropWidth,
53
+ cropHeight,
54
+ borderWidth,
55
+ borderColor,
56
+ borderStyle,
41
57
  selected,
42
58
  readonly,
43
59
  setAttr,
@@ -57,6 +73,17 @@ export const imageBlockView = $view(
57
73
  const disposeAlignWatcher = watchEffect(() => {
58
74
  dom.dataset.align = align.value || 'center'
59
75
  })
76
+ const disposeCropWatcher = watchEffect(() => {
77
+ dom.dataset.cropRatio = cropRatio.value || 'free'
78
+ })
79
+ const disposeBorderWatcher = watchEffect(() => {
80
+ const w = borderWidth.value ?? 0
81
+ const c = borderColor.value ?? '#000000'
82
+ const s = borderStyle.value ?? 'none'
83
+ dom.dataset.borderWidth = String(w)
84
+ dom.dataset.borderColor = c
85
+ dom.dataset.borderStyle = s
86
+ })
60
87
  const proxyDomURL = config.proxyDomURL
61
88
  const bindAttrs = (node: Node) => {
62
89
  if (!proxyDomURL) {
@@ -76,6 +103,14 @@ export const imageBlockView = $view(
76
103
  ratio.value = node.attrs.ratio
77
104
  caption.value = node.attrs.caption
78
105
  align.value = node.attrs.align
106
+ cropRatio.value = node.attrs.cropRatio
107
+ cropTop.value = node.attrs.cropTop
108
+ cropLeft.value = node.attrs.cropLeft
109
+ cropWidth.value = node.attrs.cropWidth
110
+ cropHeight.value = node.attrs.cropHeight
111
+ borderWidth.value = node.attrs.borderWidth
112
+ borderColor.value = node.attrs.borderColor
113
+ borderStyle.value = node.attrs.borderStyle
79
114
 
80
115
  readonly.value = !view.editable
81
116
  }
@@ -93,6 +128,11 @@ export const imageBlockView = $view(
93
128
  },
94
129
  stopEvent: (e) => {
95
130
  if (e.target instanceof HTMLInputElement) return true
131
+ if (e.target instanceof HTMLElement && e.target.tagName === 'INPUT')
132
+ return true
133
+ const target = e.target as HTMLElement
134
+ if (target.closest?.('.setting-panel, .image-toolbar, .crop-overlay'))
135
+ return true
96
136
 
97
137
  return false
98
138
  },
@@ -105,6 +145,8 @@ export const imageBlockView = $view(
105
145
  destroy: () => {
106
146
  disposeSelectedWatcher()
107
147
  disposeAlignWatcher()
148
+ disposeCropWatcher()
149
+ disposeBorderWatcher()
108
150
  app.unmount()
109
151
  dom.remove()
110
152
  },
@@ -94,22 +94,80 @@ export const TableBlock = defineComponent<TableBlockProps>({
94
94
  const resizingCol = ref(-1)
95
95
  const colWidths = ref<number[]>([])
96
96
 
97
+ /** Count total columns in the table by expanding colspan across all rows */
98
+ const getColCount = () => {
99
+ let maxCols = 0
100
+ node.value.forEach((row) => {
101
+ let cols = 0
102
+ row.forEach((cell) => {
103
+ cols += (cell.attrs.colspan as number) || 1
104
+ })
105
+ if (cols > maxCols) maxCols = cols
106
+ })
107
+ return maxCols
108
+ }
109
+
97
110
  const syncColWidths = () => {
98
111
  if (resizingCol.value >= 0) return
99
- const firstRow = node.value.firstChild
100
- if (!firstRow) return
101
- const colCount = firstRow.content.childCount
112
+ const colCount = getColCount()
113
+ const prevColCount = colWidths.value.length
102
114
  const widths: number[] = []
103
- const hasBounds = colBounds.value.length === colCount
115
+ const hasBounds = colBounds.value.length >= colCount
116
+
117
+ // Compute average width of existing columns for new columns without data
118
+ const existingNonZero = colWidths.value.filter((w) => w > 0)
119
+ const avgWidth =
120
+ existingNonZero.length > 0
121
+ ? Math.round(
122
+ existingNonZero.reduce((a, b) => a + b, 0) /
123
+ existingNonZero.length
124
+ )
125
+ : 0
126
+
104
127
  for (let i = 0; i < colCount; i++) {
105
- const cell = firstRow.content.child(i)
106
- const w = cell.attrs.colwidth
107
- if (Array.isArray(w) && w[0]) {
108
- widths.push(w[0])
109
- } else if (hasBounds) {
110
- widths.push(Math.round(colBounds.value[i]!.width))
111
- } else {
112
- widths.push(0)
128
+ const isNewColumn = i >= prevColCount
129
+ // Find a cell that covers this column index
130
+ let found = false
131
+ node.value.forEach((row) => {
132
+ if (found) return
133
+ let colIdx = 0
134
+ row.forEach((cell) => {
135
+ if (found) return
136
+ const colspan = (cell.attrs.colspan as number) || 1
137
+ const colwidth: unknown = cell.attrs.colwidth
138
+ if (colIdx === i) {
139
+ if (colspan > 1) {
140
+ if (Array.isArray(colwidth) && colwidth.length > 0) {
141
+ const totalW = colwidth.reduce(
142
+ (sum: number, w: unknown) => sum + ((w as number) || 0),
143
+ 0
144
+ )
145
+ widths.push(Math.round(totalW / colspan))
146
+ } else if (!isNewColumn && hasBounds && colBounds.value[i]) {
147
+ widths.push(Math.round(colBounds.value[i]!.width))
148
+ } else {
149
+ widths.push(avgWidth)
150
+ }
151
+ } else {
152
+ if (Array.isArray(colwidth) && colwidth[0]) {
153
+ widths.push(colwidth[0] as number)
154
+ } else if (!isNewColumn && hasBounds && colBounds.value[i]) {
155
+ widths.push(Math.round(colBounds.value[i]!.width))
156
+ } else {
157
+ widths.push(avgWidth)
158
+ }
159
+ }
160
+ found = true
161
+ }
162
+ colIdx += colspan
163
+ })
164
+ })
165
+ if (!found) {
166
+ widths.push(
167
+ !isNewColumn && hasBounds && colBounds.value[i]
168
+ ? Math.round(colBounds.value[i]!.width)
169
+ : avgWidth
170
+ )
113
171
  }
114
172
  }
115
173
  colWidths.value = widths
@@ -238,17 +296,28 @@ export const TableBlock = defineComponent<TableBlockProps>({
238
296
  const content = contentWrapperRef.value
239
297
  if (!content) return
240
298
 
241
- const firstRow = content.querySelector('tr')
299
+ const rows = content.querySelectorAll('tr')
242
300
  const tableRect = content.getBoundingClientRect()
301
+ const expectedColCount = getColCount()
302
+
303
+ // Find the first row where all cells are unmerged (no colspan),
304
+ // so we can accurately measure individual column positions.
305
+ let bestRow: HTMLTableRowElement | null = null
306
+ rows.forEach((row) => {
307
+ if (bestRow) return
308
+ if (row.children.length === expectedColCount) {
309
+ bestRow = row as HTMLTableRowElement
310
+ }
311
+ })
243
312
 
244
- if (firstRow) {
245
- colBounds.value = Array.from(firstRow.children).map((c) => {
313
+ const measureRow = bestRow ?? content.querySelector('tr')
314
+ if (measureRow) {
315
+ colBounds.value = Array.from(measureRow.children).map((c) => {
246
316
  const rect = c.getBoundingClientRect()
247
317
  return { left: rect.left - tableRect.left, width: rect.width }
248
318
  })
249
319
  }
250
320
 
251
- const rows = content.querySelectorAll('tr')
252
321
  rowBounds.value = Array.from(rows).map((c) => {
253
322
  const rect = c.getBoundingClientRect()
254
323
  return { top: rect.top - tableRect.top, height: rect.height }
@@ -404,6 +473,7 @@ export const TableBlock = defineComponent<TableBlockProps>({
404
473
 
405
474
  watch(node, () => {
406
475
  dispatchListener()
476
+ requestAnimationFrame(updateBounds)
407
477
  })
408
478
 
409
479
  onBeforeUnmount(() => {
@@ -447,7 +517,7 @@ export const TableBlock = defineComponent<TableBlockProps>({
447
517
  contenteditable="false"
448
518
  onPointerdown={(e: PointerEvent) => e.stopPropagation()}
449
519
  >
450
- {
520
+ {canMerge.value ? (
451
521
  <button
452
522
  type="button"
453
523
  class="cell-toolbar-btn"
@@ -455,8 +525,7 @@ export const TableBlock = defineComponent<TableBlockProps>({
455
525
  >
456
526
  <Icon icon={config.renderButton('merge_cells')} />
457
527
  </button>
458
- }
459
- {
528
+ ) : canSplit.value ? (
460
529
  <button
461
530
  type="button"
462
531
  class="cell-toolbar-btn"
@@ -464,7 +533,7 @@ export const TableBlock = defineComponent<TableBlockProps>({
464
533
  >
465
534
  <Icon icon={config.renderButton('split_cell')} />
466
535
  </button>
467
- }
536
+ ) : undefined}
468
537
  </div>
469
538
 
470
539
  <div class="table-wrapper" ref={tableWrapperRef}>
@@ -496,6 +565,15 @@ export const TableBlock = defineComponent<TableBlockProps>({
496
565
  data-show={activeColIndex.value === i ? 'true' : 'false'}
497
566
  onPointermove={(e: PointerEvent) => e.stopPropagation()}
498
567
  >
568
+ {canMerge.value ? (
569
+ <button type="button" onPointerdown={onMergeCells}>
570
+ <Icon icon={config.renderButton('merge_cells')} />
571
+ </button>
572
+ ) : canSplit.value ? (
573
+ <button type="button" onPointerdown={onSplitCell}>
574
+ <Icon icon={config.renderButton('split_cell')} />
575
+ </button>
576
+ ) : undefined}
499
577
  <button
500
578
  type="button"
501
579
  onPointerdown={(e) => {
@@ -532,16 +610,6 @@ export const TableBlock = defineComponent<TableBlockProps>({
532
610
  >
533
611
  <Icon icon={config.renderButton('delete_col')} />
534
612
  </button>
535
- {canMerge.value && (
536
- <button type="button" onPointerdown={onMergeCells}>
537
- <Icon icon={config.renderButton('merge_cells')} />
538
- </button>
539
- )}
540
- {canSplit.value && (
541
- <button type="button" onPointerdown={onSplitCell}>
542
- <Icon icon={config.renderButton('split_cell')} />
543
- </button>
544
- )}
545
613
  </div>
546
614
  </div>
547
615
  ))}
@@ -612,6 +680,15 @@ export const TableBlock = defineComponent<TableBlockProps>({
612
680
  data-show={activeRowIndex.value === i ? 'true' : 'false'}
613
681
  onPointermove={(e: PointerEvent) => e.stopPropagation()}
614
682
  >
683
+ {canMerge.value ? (
684
+ <button type="button" onPointerdown={onMergeCells}>
685
+ <Icon icon={config.renderButton('merge_cells')} />
686
+ </button>
687
+ ) : canSplit.value ? (
688
+ <button type="button" onPointerdown={onSplitCell}>
689
+ <Icon icon={config.renderButton('split_cell')} />
690
+ </button>
691
+ ) : undefined}
615
692
  <button
616
693
  type="button"
617
694
  onPointerdown={(e) => {
@@ -621,16 +698,6 @@ export const TableBlock = defineComponent<TableBlockProps>({
621
698
  >
622
699
  <Icon icon={config.renderButton('delete_row')} />
623
700
  </button>
624
- {canMerge.value && (
625
- <button type="button" onPointerdown={onMergeCells}>
626
- <Icon icon={config.renderButton('merge_cells')} />
627
- </button>
628
- )}
629
- {canSplit.value && (
630
- <button type="button" onPointerdown={onSplitCell}>
631
- <Icon icon={config.renderButton('split_cell')} />
632
- </button>
633
- )}
634
701
  </div>
635
702
  </div>
636
703
  ))}
@@ -688,12 +755,15 @@ export const TableBlock = defineComponent<TableBlockProps>({
688
755
 
689
756
  <table ref={contentWrapperFunctionRef} class="children">
690
757
  <colgroup>
691
- {colWidths.value.map((w, i) => (
692
- <col
693
- key={i}
694
- style={w > 0 ? { width: `${w}px` } : undefined}
695
- />
696
- ))}
758
+ {Array.from({ length: getColCount() }, (_, i) => {
759
+ const w = colWidths.value[i]
760
+ return (
761
+ <col
762
+ key={i}
763
+ style={w && w > 0 ? { width: `${w}px` } : undefined}
764
+ />
765
+ )
766
+ })}
697
767
  </colgroup>
698
768
  </table>
699
769
  </div>
@@ -2,10 +2,7 @@ import type { Ctx } from '@jvs-milkdown/ctx'
2
2
 
3
3
  import { commandsCtx, editorViewCtx } from '@jvs-milkdown/core'
4
4
  import {
5
- addColAfterCommand,
6
- addColBeforeCommand,
7
- addRowAfterCommand,
8
- addRowBeforeCommand,
5
+ addRowWithAlignment,
9
6
  deleteSelectedCellsCommand,
10
7
  mergeCellsCommand,
11
8
  selectColCommand,
@@ -17,6 +14,9 @@ import {
17
14
  CellSelection,
18
15
  selectedRect,
19
16
  splitCellWithType,
17
+ TableMap,
18
+ type TableRect,
19
+ addColumn,
20
20
  } from '@jvs-milkdown/prose/tables'
21
21
 
22
22
  import type { Refs } from './types'
@@ -26,43 +26,62 @@ export function useOperation(
26
26
  ctx?: Ctx,
27
27
  getPos?: () => number | undefined
28
28
  ) {
29
- const { contentWrapperRef, hoverIndex } = refs
29
+ const { hoverIndex } = refs
30
30
 
31
31
  const addRowByIndex = (index: number) => {
32
32
  if (!ctx || !ctx.get(editorViewCtx).editable) return
33
33
 
34
- const rows = Array.from(
35
- contentWrapperRef.value?.querySelectorAll('tr') ?? []
36
- )
37
- const commands = ctx.get(commandsCtx)
38
- const pos = (getPos?.() ?? 0) + 1
39
- if (rows.length === index) {
40
- commands.call(selectRowCommand.key, { pos, index: index - 1 })
41
- commands.call(addRowAfterCommand.key)
42
- } else {
43
- commands.call(selectRowCommand.key, { pos, index })
44
- commands.call(addRowBeforeCommand.key)
34
+ const view = ctx.get(editorViewCtx)
35
+ const tablePos = getPos?.()
36
+ if (tablePos == null) return
37
+
38
+ const table = view.state.doc.nodeAt(tablePos)
39
+ if (!table) return
40
+
41
+ const tableStart = tablePos + 1
42
+ const map = TableMap.get(table)
43
+ const insertRow = Math.min(index, map.height)
44
+
45
+ const tr = view.state.tr
46
+ const rect: TableRect = {
47
+ map,
48
+ tableStart,
49
+ table,
50
+ left: 0,
51
+ right: map.width,
52
+ top: 0,
53
+ bottom: map.height,
45
54
  }
46
-
47
- commands.call(selectRowCommand.key, { pos, index })
55
+ addRowWithAlignment(ctx, tr, rect, insertRow)
56
+ view.dispatch(tr)
48
57
  }
49
58
 
50
59
  const addColByIndex = (index: number) => {
51
60
  if (!ctx || !ctx.get(editorViewCtx).editable) return
52
- const cols = Array.from(
53
- contentWrapperRef.value?.querySelector('tr')?.children ?? []
54
- )
55
- const commands = ctx.get(commandsCtx)
56
61
 
57
- const pos = (getPos?.() ?? 0) + 1
58
- if (cols.length === index) {
59
- commands.call(selectColCommand.key, { pos, index: index - 1 })
60
- commands.call(addColAfterCommand.key)
61
- } else {
62
- commands.call(selectColCommand.key, { pos, index })
63
- commands.call(addColBeforeCommand.key)
62
+ const view = ctx.get(editorViewCtx)
63
+ const tablePos = getPos?.()
64
+ if (tablePos == null) return
65
+
66
+ const table = view.state.doc.nodeAt(tablePos)
67
+ if (!table) return
68
+
69
+ const tableStart = tablePos + 1
70
+ const map = TableMap.get(table)
71
+ const insertCol = Math.min(index, map.width)
72
+
73
+ const tr = view.state.tr
74
+ const rect: TableRect = {
75
+ map,
76
+ tableStart,
77
+ table,
78
+ left: 0,
79
+ right: map.width,
80
+ top: 0,
81
+ bottom: map.height,
64
82
  }
65
- commands.call(selectColCommand.key, { pos, index })
83
+ addColumn(tr, rect, insertCol)
84
+ view.dispatch(tr)
66
85
  }
67
86
 
68
87
  const selectCol = () => {
@@ -86,6 +105,8 @@ export function useOperation(
86
105
 
87
106
  if (!ctx.get(editorViewCtx).editable) return
88
107
 
108
+ if (e.button !== 0) return
109
+
89
110
  e.preventDefault()
90
111
  e.stopPropagation()
91
112
  const commands = ctx.get(commandsCtx)
@@ -101,6 +122,8 @@ export function useOperation(
101
122
 
102
123
  if (!ctx.get(editorViewCtx).editable) return
103
124
 
125
+ if (e.button !== 0) return
126
+
104
127
  e.preventDefault()
105
128
  e.stopPropagation()
106
129
  const commands = ctx.get(commandsCtx)
@@ -113,6 +136,7 @@ export function useOperation(
113
136
  const onMergeCells = (e: PointerEvent) => {
114
137
  if (!ctx) return
115
138
  if (!ctx.get(editorViewCtx).editable) return
139
+ if (e.button !== 0) return
116
140
  e.preventDefault()
117
141
  e.stopPropagation()
118
142
  const commands = ctx.get(commandsCtx)
@@ -125,6 +149,7 @@ export function useOperation(
125
149
  const onSplitCell = (e: PointerEvent) => {
126
150
  if (!ctx) return
127
151
  if (!ctx.get(editorViewCtx).editable) return
152
+ if (e.button !== 0) return
128
153
  e.preventDefault()
129
154
  e.stopPropagation()
130
155
  const view = ctx.get(editorViewCtx)
@@ -1,24 +0,0 @@
1
- type IconProps = {
2
- icon?: string | null;
3
- class?: string;
4
- onClick?: (event: PointerEvent) => void;
5
- };
6
- export declare function Icon({ icon, class: className, onClick }: IconProps): import("vue/jsx-runtime").JSX.Element;
7
- export declare namespace Icon {
8
- var props: {
9
- icon: {
10
- type: StringConstructor;
11
- required: boolean;
12
- };
13
- class: {
14
- type: StringConstructor;
15
- required: boolean;
16
- };
17
- onClick: {
18
- type: FunctionConstructor;
19
- required: boolean;
20
- };
21
- };
22
- }
23
- export {};
24
- //# sourceMappingURL=icon.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../../../src/__internal__/components/icon.tsx"],"names":[],"mappings":"AAQA,KAAK,SAAS,GAAG;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAA;CACxC,CAAA;AAED,wBAAgB,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,SAAS,yCAQlE;yBARe,IAAI"}
@@ -1,17 +0,0 @@
1
- import { type Ref } from 'vue';
2
- type ImageInputProps = {
3
- src: Ref<string | undefined>;
4
- selected: Ref<boolean>;
5
- readonly: Ref<boolean>;
6
- setLink: (link: string) => void;
7
- imageIcon?: string;
8
- uploadButton?: string;
9
- confirmButton?: string;
10
- uploadPlaceholderText?: string;
11
- className?: string;
12
- onUpload: (file: File) => Promise<string>;
13
- onImageLoadError?: (event: Event) => void | Promise<void>;
14
- };
15
- export declare const ImageInput: import("vue").DefineComponent<ImageInputProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ImageInputProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
- export {};
17
- //# sourceMappingURL=image-input.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"image-input.d.ts","sourceRoot":"","sources":["../../../src/__internal__/components/image-input.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA2B,KAAK,GAAG,EAAE,MAAM,KAAK,CAAA;AASvD,KAAK,eAAe,GAAG;IACrB,GAAG,EAAE,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAC5B,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACtB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACtB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAE/B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAE9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACzC,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC1D,CAAA;AAED,eAAO,MAAM,UAAU,0SAiLrB,CAAA"}
@@ -1,2 +0,0 @@
1
- export declare function keepAlive(..._args: unknown[]): void;
2
- //# sourceMappingURL=keep-alive.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"keep-alive.d.ts","sourceRoot":"","sources":["../../src/__internal__/keep-alive.ts"],"names":[],"mappings":"AAEA,wBAAgB,SAAS,CAAC,GAAG,KAAK,EAAE,OAAO,EAAE,QAAI"}
@@ -1,3 +0,0 @@
1
- import type { Meta, MilkdownPlugin } from '@jvs-milkdown/ctx';
2
- export declare function withMeta<T extends MilkdownPlugin>(plugin: T, meta: Partial<Meta> & Pick<Meta, 'displayName'>): T;
3
- //# sourceMappingURL=meta.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../../src/__internal__/meta.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAE7D,wBAAgB,QAAQ,CAAC,CAAC,SAAS,cAAc,EAC/C,MAAM,EAAE,CAAC,EACT,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,aAAa,CAAC,GAC9C,CAAC,CASH"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=setup.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/__tests__/setup.ts"],"names":[],"mappings":""}
@@ -1,23 +0,0 @@
1
- import type { LanguageDescription } from '@codemirror/language';
2
- import type { Extension } from '@codemirror/state';
3
- export interface CodeBlockConfig {
4
- extensions: Extension[];
5
- languages: LanguageDescription[];
6
- expandIcon: string;
7
- searchIcon: string;
8
- clearSearchIcon: string;
9
- searchPlaceholder: string;
10
- noResultText: string;
11
- copyText: string;
12
- copyIcon: string;
13
- onCopy?: (text: string) => void;
14
- renderLanguage: (language: string, selected: boolean) => string;
15
- renderPreview: (language: string, content: string, applyPreview: (value: null | string | HTMLElement) => void) => void | null | string | HTMLElement;
16
- previewToggleButton: (previewOnlyMode: boolean) => string;
17
- previewLabel: string;
18
- previewOnlyByDefault?: boolean;
19
- previewLoading: string | HTMLElement;
20
- }
21
- export declare const defaultConfig: CodeBlockConfig;
22
- export declare const codeBlockConfig: import("@jvs-milkdown/utils").$Ctx<CodeBlockConfig, "codeBlockConfigCtx">;
23
- //# sourceMappingURL=config.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/code-block/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAMlD,MAAM,WAAW,eAAe;IAC9B,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,SAAS,EAAE,mBAAmB,EAAE,CAAA;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC/B,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,KAAK,MAAM,CAAA;IAC/D,aAAa,EAAE,CACb,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,WAAW,KAAK,IAAI,KACvD,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,WAAW,CAAA;IACvC,mBAAmB,EAAE,CAAC,eAAe,EAAE,OAAO,KAAK,MAAM,CAAA;IACzD,YAAY,EAAE,MAAM,CAAA;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,cAAc,EAAE,MAAM,GAAG,WAAW,CAAA;CACrC;AAED,eAAO,MAAM,aAAa,EAAE,eAgB3B,CAAA;AAED,eAAO,MAAM,eAAe,2EAA4C,CAAA"}
@@ -1,5 +0,0 @@
1
- import type { MilkdownPlugin } from '@jvs-milkdown/ctx';
2
- export * from './config';
3
- export * from './view';
4
- export declare const codeBlockComponent: MilkdownPlugin[];
5
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/code-block/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAKvD,cAAc,UAAU,CAAA;AACxB,cAAc,QAAQ,CAAA;AAEtB,eAAO,MAAM,kBAAkB,EAAE,cAAc,EAG9C,CAAA"}
@@ -1,16 +0,0 @@
1
- import type { EditorView as CodeMirror } from '@codemirror/view';
2
- import { type Ref } from 'vue';
3
- import type { CodeBlockConfig } from '../../config';
4
- import type { LanguageInfo } from '../loader';
5
- export type CodeBlockProps = {
6
- text: Ref<string>;
7
- selected: Ref<boolean>;
8
- getReadOnly: () => boolean;
9
- codemirror: CodeMirror;
10
- language: Ref<string>;
11
- getAllLanguages: () => Array<LanguageInfo>;
12
- setLanguage: (language: string) => void;
13
- config: Omit<CodeBlockConfig, 'languages' | 'extensions'>;
14
- };
15
- export declare const CodeBlock: import("vue").DefineComponent<CodeBlockProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<CodeBlockProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
- //# sourceMappingURL=code-block.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"code-block.d.ts","sourceRoot":"","sources":["../../../../src/code-block/view/components/code-block.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,IAAI,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAIhE,OAAO,EAGL,KAAK,GAAG,EAKT,MAAM,KAAK,CAAA;AAEZ,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAU7C,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACjB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACtB,WAAW,EAAE,MAAM,OAAO,CAAA;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB,eAAe,EAAE,MAAM,KAAK,CAAC,YAAY,CAAC,CAAA;IAC1C,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,MAAM,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,YAAY,CAAC,CAAA;CAC1D,CAAA;AAED,eAAO,MAAM,SAAS,wSAqIpB,CAAA"}
@@ -1,9 +0,0 @@
1
- type CopyButtonProps = {
2
- copyText: string;
3
- copyIcon: string;
4
- onCopy: (text: string) => void;
5
- text: string;
6
- };
7
- export declare const CopyButton: import("vue").DefineComponent<CopyButtonProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<CopyButtonProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
- export {};
9
- //# sourceMappingURL=copy-button.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"copy-button.d.ts","sourceRoot":"","sources":["../../../../src/code-block/view/components/copy-button.tsx"],"names":[],"mappings":"AAOA,KAAK,eAAe,GAAG;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AA8CD,eAAO,MAAM,UAAU,0SAqCrB,CAAA"}
@@ -1,5 +0,0 @@
1
- import type { CodeBlockProps } from './code-block';
2
- type LanguagePickerProps = Pick<CodeBlockProps, 'language' | 'config' | 'setLanguage' | 'getAllLanguages' | 'getReadOnly'>;
3
- export declare const LanguagePicker: import("vue").DefineComponent<LanguagePickerProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<LanguagePickerProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
4
- export {};
5
- //# sourceMappingURL=language-picker.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"language-picker.d.ts","sourceRoot":"","sources":["../../../../src/code-block/view/components/language-picker.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAOlD,KAAK,mBAAmB,GAAG,IAAI,CAC7B,cAAc,EACd,UAAU,GAAG,QAAQ,GAAG,aAAa,GAAG,iBAAiB,GAAG,aAAa,CAC1E,CAAA;AAED,eAAO,MAAM,cAAc,kTAqNzB,CAAA"}
@@ -1,9 +0,0 @@
1
- import { type Ref } from 'vue';
2
- import type { CodeBlockProps } from './code-block';
3
- type PreviewPanelProps = Pick<CodeBlockProps, 'text' | 'language' | 'config'> & {
4
- previewOnlyMode: Ref<boolean>;
5
- preview: Ref<string | HTMLElement | null>;
6
- };
7
- export declare const PreviewPanel: import("vue").DefineComponent<PreviewPanelProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<PreviewPanelProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
8
- export {};
9
- //# sourceMappingURL=preview-panel.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"preview-panel.d.ts","sourceRoot":"","sources":["../../../../src/code-block/view/components/preview-panel.tsx"],"names":[],"mappings":"AACA,OAAO,EAAqC,KAAK,GAAG,EAAe,MAAM,KAAK,CAAA;AAE9E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAMlD,KAAK,iBAAiB,GAAG,IAAI,CAC3B,cAAc,EACd,MAAM,GAAG,UAAU,GAAG,QAAQ,CAC/B,GAAG;IACF,eAAe,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IAC7B,OAAO,EAAE,GAAG,CAAC,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC,CAAA;CAC1C,CAAA;AAED,eAAO,MAAM,YAAY,8SA6DvB,CAAA"}
@@ -1,3 +0,0 @@
1
- import type { NodeViewConstructor } from '@jvs-milkdown/prose/view';
2
- export declare const codeBlockView: import("@jvs-milkdown/utils").$View<import("@jvs-milkdown/utils").$Node, NodeViewConstructor>;
3
- //# sourceMappingURL=index.d.ts.map