@jvs-milkdown/crepe 1.2.12 → 1.2.14

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 (114) hide show
  1. package/lib/cjs/builder.js +41 -2
  2. package/lib/cjs/builder.js.map +1 -1
  3. package/lib/cjs/feature/block-edit/index.js +10 -2
  4. package/lib/cjs/feature/block-edit/index.js.map +1 -1
  5. package/lib/cjs/feature/code-mirror/index.js +9 -2
  6. package/lib/cjs/feature/code-mirror/index.js.map +1 -1
  7. package/lib/cjs/feature/cursor/index.js +9 -2
  8. package/lib/cjs/feature/cursor/index.js.map +1 -1
  9. package/lib/cjs/feature/image-block/index.js +10 -3
  10. package/lib/cjs/feature/image-block/index.js.map +1 -1
  11. package/lib/cjs/feature/inline-diff/index.js +1298 -0
  12. package/lib/cjs/feature/inline-diff/index.js.map +1 -0
  13. package/lib/cjs/feature/latex/index.js +9 -2
  14. package/lib/cjs/feature/latex/index.js.map +1 -1
  15. package/lib/cjs/feature/link-tooltip/index.js +10 -2
  16. package/lib/cjs/feature/link-tooltip/index.js.map +1 -1
  17. package/lib/cjs/feature/list-item/index.js +9 -2
  18. package/lib/cjs/feature/list-item/index.js.map +1 -1
  19. package/lib/cjs/feature/placeholder/index.js +9 -2
  20. package/lib/cjs/feature/placeholder/index.js.map +1 -1
  21. package/lib/cjs/feature/table/index.js +10 -2
  22. package/lib/cjs/feature/table/index.js.map +1 -1
  23. package/lib/cjs/feature/toolbar/index.js +134 -12
  24. package/lib/cjs/feature/toolbar/index.js.map +1 -1
  25. package/lib/cjs/index.js +1410 -241
  26. package/lib/cjs/index.js.map +1 -1
  27. package/lib/esm/builder.js +41 -2
  28. package/lib/esm/builder.js.map +1 -1
  29. package/lib/esm/feature/block-edit/index.js +10 -2
  30. package/lib/esm/feature/block-edit/index.js.map +1 -1
  31. package/lib/esm/feature/code-mirror/index.js +9 -2
  32. package/lib/esm/feature/code-mirror/index.js.map +1 -1
  33. package/lib/esm/feature/cursor/index.js +9 -2
  34. package/lib/esm/feature/cursor/index.js.map +1 -1
  35. package/lib/esm/feature/image-block/index.js +10 -3
  36. package/lib/esm/feature/image-block/index.js.map +1 -1
  37. package/lib/esm/feature/inline-diff/index.js +1274 -0
  38. package/lib/esm/feature/inline-diff/index.js.map +1 -0
  39. package/lib/esm/feature/latex/index.js +9 -2
  40. package/lib/esm/feature/latex/index.js.map +1 -1
  41. package/lib/esm/feature/link-tooltip/index.js +10 -2
  42. package/lib/esm/feature/link-tooltip/index.js.map +1 -1
  43. package/lib/esm/feature/list-item/index.js +9 -2
  44. package/lib/esm/feature/list-item/index.js.map +1 -1
  45. package/lib/esm/feature/placeholder/index.js +9 -2
  46. package/lib/esm/feature/placeholder/index.js.map +1 -1
  47. package/lib/esm/feature/table/index.js +10 -2
  48. package/lib/esm/feature/table/index.js.map +1 -1
  49. package/lib/esm/feature/toolbar/index.js +134 -12
  50. package/lib/esm/feature/toolbar/index.js.map +1 -1
  51. package/lib/esm/index.js +1392 -242
  52. package/lib/esm/index.js.map +1 -1
  53. package/lib/theme/common/diff-block.css +41 -0
  54. package/lib/theme/common/inline-diff.css +142 -0
  55. package/lib/theme/common/style.css +2 -0
  56. package/lib/theme/common/table.css +4 -4
  57. package/lib/tsconfig.tsbuildinfo +1 -1
  58. package/lib/types/core/builder.d.ts +2 -0
  59. package/lib/types/core/builder.d.ts.map +1 -1
  60. package/lib/types/core/locale.d.ts +4 -0
  61. package/lib/types/core/locale.d.ts.map +1 -1
  62. package/lib/types/feature/diff-block/index.d.ts +10 -0
  63. package/lib/types/feature/diff-block/index.d.ts.map +1 -0
  64. package/lib/types/feature/fixed-toolbar/document-header.d.ts.map +1 -1
  65. package/lib/types/feature/fixed-toolbar/index.d.ts.map +1 -1
  66. package/lib/types/feature/fixed-toolbar/menu-bar.d.ts.map +1 -1
  67. package/lib/types/feature/fixed-toolbar/outline-panel.d.ts.map +1 -1
  68. package/lib/types/feature/index.d.ts +7 -1
  69. package/lib/types/feature/index.d.ts.map +1 -1
  70. package/lib/types/feature/inline-diff/change-panel.d.ts +4 -0
  71. package/lib/types/feature/inline-diff/change-panel.d.ts.map +1 -0
  72. package/lib/types/feature/inline-diff/config.d.ts +12 -0
  73. package/lib/types/feature/inline-diff/config.d.ts.map +1 -0
  74. package/lib/types/feature/inline-diff/diff-engine.d.ts +20 -0
  75. package/lib/types/feature/inline-diff/diff-engine.d.ts.map +1 -0
  76. package/lib/types/feature/inline-diff/diff-view.d.ts +2 -0
  77. package/lib/types/feature/inline-diff/diff-view.d.ts.map +1 -0
  78. package/lib/types/feature/inline-diff/doc-builder.d.ts +21 -0
  79. package/lib/types/feature/inline-diff/doc-builder.d.ts.map +1 -0
  80. package/lib/types/feature/inline-diff/index.d.ts +9 -0
  81. package/lib/types/feature/inline-diff/index.d.ts.map +1 -0
  82. package/lib/types/feature/loader.d.ts.map +1 -1
  83. package/lib/types/feature/toolbar/component.d.ts.map +1 -1
  84. package/lib/types/feature/toolbar/index.d.ts.map +1 -1
  85. package/lib/types/icons/remove.d.ts +1 -1
  86. package/lib/types/icons/remove.d.ts.map +1 -1
  87. package/lib/types/utils/fixed-toolbar-popup-state.d.ts +7 -0
  88. package/lib/types/utils/fixed-toolbar-popup-state.d.ts.map +1 -0
  89. package/package.json +15 -4
  90. package/src/core/builder.ts +19 -0
  91. package/src/core/locale.ts +7 -0
  92. package/src/feature/diff-block/index.ts +48 -0
  93. package/src/feature/fixed-toolbar/index.ts +97 -25
  94. package/src/feature/fixed-toolbar/menu-bar.tsx +13 -2
  95. package/src/feature/fixed-toolbar/outline-panel.tsx +3 -2
  96. package/src/feature/fixed-toolbar/shortcut-help-modal.tsx +1 -1
  97. package/src/feature/fixed-toolbar/view-menu-state.ts +1 -1
  98. package/src/feature/image-block/index.ts +1 -1
  99. package/src/feature/index.ts +12 -0
  100. package/src/feature/inline-diff/change-panel.ts +280 -0
  101. package/src/feature/inline-diff/config.ts +28 -0
  102. package/src/feature/inline-diff/diff-engine.ts +181 -0
  103. package/src/feature/inline-diff/diff-view.ts +2 -0
  104. package/src/feature/inline-diff/doc-builder.ts +139 -0
  105. package/src/feature/inline-diff/index.ts +514 -0
  106. package/src/feature/loader.ts +8 -0
  107. package/src/feature/toolbar/component.tsx +97 -9
  108. package/src/feature/toolbar/index.ts +33 -0
  109. package/src/icons/remove.ts +1 -0
  110. package/src/theme/common/diff-block.css +43 -0
  111. package/src/theme/common/inline-diff.css +148 -0
  112. package/src/theme/common/style.css +2 -0
  113. package/src/theme/common/table.css +4 -4
  114. package/src/utils/fixed-toolbar-popup-state.ts +27 -0
@@ -93,6 +93,10 @@ import {
93
93
  splitCellIcon,
94
94
  formatPainterIcon,
95
95
  } from '../../icons'
96
+ import {
97
+ incrementPopupCount,
98
+ decrementPopupCount,
99
+ } from '../../utils/fixed-toolbar-popup-state'
96
100
  import { keepAlive } from '../../utils/keep-alive'
97
101
  import { menuAPI } from '../block-edit/menu'
98
102
  import { getGroups as getBlockGroups } from '../block-edit/menu/config'
@@ -147,6 +151,8 @@ type ToolbarProps = {
147
151
  interface FormatPainterState {
148
152
  marks: Mark[]
149
153
  align?: string | null
154
+ blockType?: string | null
155
+ blockAttrs?: Record<string, any> | null
150
156
  isPersistent: boolean
151
157
  }
152
158
 
@@ -238,6 +244,8 @@ export const Toolbar = defineComponent<ToolbarProps>({
238
244
  const {
239
245
  marks: savedMarks,
240
246
  align: savedAlign,
247
+ blockType: savedBlockType,
248
+ blockAttrs: savedBlockAttrs,
241
249
  isPersistent,
242
250
  } = formatPainterState!.value
243
251
 
@@ -263,6 +271,30 @@ export const Toolbar = defineComponent<ToolbarProps>({
263
271
  }
264
272
  )
265
273
  }
274
+ if (savedBlockType) {
275
+ curState.doc.nodesBetween(
276
+ curSelection.from,
277
+ curSelection.to,
278
+ (node: any, pos: number) => {
279
+ if (node.type.name === 'paragraph') {
280
+ tr.setNodeMarkup(
281
+ pos,
282
+ curState.schema.nodes[savedBlockType],
283
+ {
284
+ ...savedBlockAttrs,
285
+ ...(savedAlign ? { align: savedAlign } : {}),
286
+ }
287
+ )
288
+ } else if (node.type.name === 'heading' && savedBlockAttrs) {
289
+ tr.setNodeMarkup(pos, null, {
290
+ ...node.attrs,
291
+ ...savedBlockAttrs,
292
+ ...(savedAlign ? { align: savedAlign } : {}),
293
+ })
294
+ }
295
+ }
296
+ )
297
+ }
266
298
  dispatch(tr)
267
299
  applied = true
268
300
  } else {
@@ -301,6 +333,28 @@ export const Toolbar = defineComponent<ToolbarProps>({
301
333
  })
302
334
  }
303
335
  }
336
+
337
+ if (savedBlockType) {
338
+ const pos = curSelection.$from.before(curSelection.$from.depth)
339
+ const node = curState.doc.nodeAt(pos)
340
+ if (node && node.type.name === 'paragraph') {
341
+ tr.setNodeMarkup(pos, curState.schema.nodes[savedBlockType], {
342
+ ...savedBlockAttrs,
343
+ ...(savedAlign ? { align: savedAlign } : {}),
344
+ })
345
+ } else if (
346
+ node &&
347
+ node.type.name === 'heading' &&
348
+ savedBlockAttrs
349
+ ) {
350
+ tr.setNodeMarkup(pos, null, {
351
+ ...node.attrs,
352
+ ...savedBlockAttrs,
353
+ ...(savedAlign ? { align: savedAlign } : {}),
354
+ })
355
+ }
356
+ }
357
+
304
358
  tr.setStoredMarks(savedMarks)
305
359
  dispatch(tr)
306
360
  applied = true
@@ -363,7 +417,24 @@ export const Toolbar = defineComponent<ToolbarProps>({
363
417
  }
364
418
  align = foundAlign
365
419
 
366
- formatPainterState!.value = { marks, align, isPersistent }
420
+ // Capture block type (heading level) if selection is within a heading
421
+ let blockType: string | null = null
422
+ let blockAttrs: Record<string, any> | null = null
423
+ {
424
+ const parent = selection.$from.parent
425
+ if (parent.type.name === 'heading') {
426
+ blockType = 'heading'
427
+ blockAttrs = { level: parent.attrs.level }
428
+ }
429
+ }
430
+
431
+ formatPainterState!.value = {
432
+ marks,
433
+ align,
434
+ blockType,
435
+ blockAttrs,
436
+ isPersistent,
437
+ }
367
438
  document.removeEventListener('pointerup', formatPainterHandler!)
368
439
 
369
440
  setTimeout(() => {
@@ -432,6 +503,23 @@ export const Toolbar = defineComponent<ToolbarProps>({
432
503
  }>({ top: 0 })
433
504
  const cachedWidths = new Map<number, number>()
434
505
 
506
+ // Track popup state for fixed toolbar → notify floating toolbar
507
+ const anyFixedPopup = computed(
508
+ () =>
509
+ !!isFixed &&
510
+ (showBlockMenu.value ||
511
+ showAlignMenu.value ||
512
+ showColorMenu.value ||
513
+ showFontFamilyMenu.value ||
514
+ showFontSizeMenu.value ||
515
+ showTableMenu.value ||
516
+ showOverflowMenu.value)
517
+ )
518
+ watch(anyFixedPopup, (val) => {
519
+ if (val) incrementPopupCount()
520
+ else decrementPopupCount()
521
+ })
522
+
435
523
  const getMenuLeftPos = (rect: DOMRect, menuWidth: number) => {
436
524
  let left = rect.left
437
525
  if (left + menuWidth > window.innerWidth) {
@@ -483,7 +571,8 @@ export const Toolbar = defineComponent<ToolbarProps>({
483
571
  containerWidth = container.clientWidth
484
572
  }
485
573
  } else {
486
- containerWidth = container.clientWidth
574
+ const view = ctx.get(editorViewCtx)
575
+ containerWidth = view.dom.clientWidth - 32
487
576
  }
488
577
 
489
578
  if (containerWidth === lastContainerWidth) {
@@ -697,6 +786,7 @@ export const Toolbar = defineComponent<ToolbarProps>({
697
786
  if (hideFontFamilyTimer) clearTimeout(hideFontFamilyTimer)
698
787
  if (hideFontSizeTimer) clearTimeout(hideFontSizeTimer)
699
788
  if (hideTableTimer) clearTimeout(hideTableTimer)
789
+ if (anyFixedPopup.value) decrementPopupCount()
700
790
  })
701
791
 
702
792
  // --- Overflow lifecycle (fixed toolbar only) ---
@@ -1240,13 +1330,11 @@ export const Toolbar = defineComponent<ToolbarProps>({
1240
1330
  })
1241
1331
 
1242
1332
  // Ensure proper formatting tools are visible
1243
- const nonHeadingGroups = toolbarGroupInfo.value.filter(
1244
- (group: any) => {
1245
- if ((group as any).key === 'heading') return false
1246
- if (props.isFixed && (group as any).key === 'function') return false
1247
- return true
1248
- }
1249
- )
1333
+ const nonHeadingGroups = toolbarGroupInfo.value.filter((group: any) => {
1334
+ if ((group as any).key === 'heading') return false
1335
+ if (props.isFixed && (group as any).key === 'function') return false
1336
+ return true
1337
+ })
1250
1338
 
1251
1339
  const isSectionOverflowed = (idx: number) =>
1252
1340
  idx >= overflowVisibleCount.value
@@ -25,6 +25,10 @@ import { colorPlugins } from './color'
25
25
  import { Toolbar } from './component'
26
26
  import { highlightMark } from './highlight-mark'
27
27
  import { underline } from './underline'
28
+ import {
29
+ getIsAnyPopupOpen,
30
+ addPopupChangeListener,
31
+ } from '../../utils/fixed-toolbar-popup-state'
28
32
 
29
33
  interface ToolbarConfig {
30
34
  boldIcon: string
@@ -55,6 +59,8 @@ class ToolbarView implements PluginView {
55
59
  #selection: ShallowRef<Selection>
56
60
  #show = ref(false)
57
61
  #mousePressed = false
62
+ #removePopupListener: (() => void) | undefined
63
+ #onDocumentMouseUp: ((ev: MouseEvent) => void) | undefined
58
64
 
59
65
  constructor(ctx: Ctx, view: EditorView, config?: ToolbarFeatureConfig) {
60
66
  const content = document.createElement('div')
@@ -83,12 +89,25 @@ class ToolbarView implements PluginView {
83
89
  }, 0)
84
90
  })
85
91
 
92
+ // Handle mouseup outside the editor view (finish selection outside)
93
+ const onDocumentMouseUp = () => {
94
+ if (this.#mousePressed) {
95
+ this.#mousePressed = false
96
+ setTimeout(() => {
97
+ this.update(view)
98
+ }, 0)
99
+ }
100
+ }
101
+ document.addEventListener('mouseup', onDocumentMouseUp)
102
+ this.#onDocumentMouseUp = onDocumentMouseUp
103
+
86
104
  this.#tooltipProvider = new TooltipProvider({
87
105
  content: this.#content,
88
106
  debounce: 20,
89
107
  offset: 10,
90
108
  shouldShow: (view: EditorView) => {
91
109
  if (this.#mousePressed) return false
110
+ if (getIsAnyPopupOpen()) return false
92
111
 
93
112
  const { doc, selection } = view.state
94
113
  const { empty, from, to } = selection
@@ -127,6 +146,16 @@ class ToolbarView implements PluginView {
127
146
  this.#tooltipProvider.onHide = () => {
128
147
  this.#show.value = false
129
148
  }
149
+
150
+ // React to fixed toolbar popup state changes
151
+ this.#removePopupListener = addPopupChangeListener(() => {
152
+ if (getIsAnyPopupOpen()) {
153
+ this.#tooltipProvider.hide()
154
+ } else {
155
+ this.#tooltipProvider.update(view)
156
+ }
157
+ })
158
+
130
159
  this.update(view)
131
160
  }
132
161
 
@@ -136,6 +165,10 @@ class ToolbarView implements PluginView {
136
165
  }
137
166
 
138
167
  destroy = () => {
168
+ this.#removePopupListener?.()
169
+ if (this.#onDocumentMouseUp) {
170
+ document.removeEventListener('mouseup', this.#onDocumentMouseUp)
171
+ }
139
172
  this.#tooltipProvider.destroy()
140
173
  this.#app.unmount()
141
174
  this.#content.remove()
@@ -7,6 +7,7 @@ export const removeIcon = `
7
7
  >
8
8
  <path
9
9
  d="M7.30775 20.4997C6.81058 20.4997 6.385 20.3227 6.031 19.9687C5.677 19.6147 5.5 19.1892 5.5 18.692V5.99973H5.25C5.0375 5.99973 4.85942 5.92782 4.71575 5.78398C4.57192 5.64015 4.5 5.46198 4.5 5.24948C4.5 5.03682 4.57192 4.85873 4.71575 4.71523C4.85942 4.57157 5.0375 4.49973 5.25 4.49973H9C9 4.2549 9.08625 4.04624 9.25875 3.87374C9.43108 3.7014 9.63967 3.61523 9.8845 3.61523H14.1155C14.3603 3.61523 14.5689 3.7014 14.7413 3.87374C14.9138 4.04624 15 4.2549 15 4.49973H18.75C18.9625 4.49973 19.1406 4.57165 19.2843 4.71548C19.4281 4.85932 19.5 5.03748 19.5 5.24998C19.5 5.46265 19.4281 5.64073 19.2843 5.78423C19.1406 5.9279 18.9625 5.99973 18.75 5.99973H18.5V18.692C18.5 19.1892 18.323 19.6147 17.969 19.9687C17.615 20.3227 17.1894 20.4997 16.6923 20.4997H7.30775ZM17 5.99973H7V18.692C7 18.7818 7.02883 18.8556 7.0865 18.9132C7.14417 18.9709 7.21792 18.9997 7.30775 18.9997H16.6923C16.7821 18.9997 16.8558 18.9709 16.9135 18.9132C16.9712 18.8556 17 18.7818 17 18.692V5.99973ZM10.1543 16.9997C10.3668 16.9997 10.5448 16.9279 10.6885 16.7842C10.832 16.6404 10.9037 16.4622 10.9037 16.2497V8.74973C10.9037 8.53723 10.8318 8.35907 10.688 8.21523C10.5443 8.07157 10.3662 7.99973 10.1535 7.99973C9.941 7.99973 9.76292 8.07157 9.61925 8.21523C9.47575 8.35907 9.404 8.53723 9.404 8.74973V16.2497C9.404 16.4622 9.47583 16.6404 9.6195 16.7842C9.76333 16.9279 9.94158 16.9997 10.1543 16.9997ZM13.8465 16.9997C14.059 16.9997 14.2371 16.9279 14.3807 16.7842C14.5243 16.6404 14.596 16.4622 14.596 16.2497V8.74973C14.596 8.53723 14.5242 8.35907 14.3805 8.21523C14.2367 8.07157 14.0584 7.99973 13.8458 7.99973C13.6333 7.99973 13.4552 8.07157 13.3115 8.21523C13.168 8.35907 13.0962 8.53723 13.0962 8.74973V16.2497C13.0962 16.4622 13.1682 16.6404 13.312 16.7842C13.4557 16.9279 13.6338 16.9997 13.8465 16.9997Z"
10
+ fill="#363B4C"
10
11
  />
11
12
  </svg>
12
13
  `
@@ -0,0 +1,43 @@
1
+ .milkdown {
2
+ .milkdown-diff-block {
3
+ display: block;
4
+ position: relative;
5
+ padding: 16px 0;
6
+ margin: 20px 0;
7
+ border-radius: 8px;
8
+ background: var(--crepe-color-surface-low);
9
+ overflow: hidden;
10
+
11
+ .cm-editor {
12
+ outline: none !important;
13
+ background: transparent;
14
+ }
15
+
16
+ .cm-merge-a .cm-merge-chunk {
17
+ background-color: rgba(244, 63, 94, 0.15) !important;
18
+ }
19
+
20
+ .cm-merge-b .cm-merge-chunk {
21
+ background-color: rgba(16, 185, 129, 0.15) !important;
22
+ }
23
+
24
+ .cm-merge-chunk-a {
25
+ background-color: rgba(244, 63, 94, 0.3) !important;
26
+ }
27
+
28
+ .cm-merge-chunk-b {
29
+ background-color: rgba(16, 185, 129, 0.3) !important;
30
+ }
31
+
32
+ .cm-merge-spacer {
33
+ background-color: transparent !important;
34
+ background-image: repeating-linear-gradient(
35
+ 45deg,
36
+ rgba(150, 150, 150, 0.05),
37
+ rgba(150, 150, 150, 0.05) 10px,
38
+ transparent 10px,
39
+ transparent 20px
40
+ );
41
+ }
42
+ }
43
+ }
@@ -0,0 +1,148 @@
1
+ .milkdown {
2
+ .crepe-diff-added,
3
+ .crepe-diff-deleted {
4
+ position: relative;
5
+ display: block;
6
+ border-radius: 0;
7
+ padding: 2px 4px 2px 12px !important;
8
+ margin: 0 !important;
9
+ }
10
+
11
+ .crepe-diff-added {
12
+ background-color: rgba(46, 160, 67, 0.08);
13
+ border-left: 3px solid #2ea043;
14
+ }
15
+
16
+ .crepe-diff-deleted {
17
+ background-color: rgba(248, 81, 73, 0.08);
18
+ border-left: 3px solid #f85149;
19
+ }
20
+
21
+ .crepe-diff-inline-added {
22
+ background-color: rgba(46, 160, 67, 0.25);
23
+ border-radius: 2px;
24
+ }
25
+
26
+ .crepe-diff-inline-deleted {
27
+ background-color: rgba(248, 81, 73, 0.25);
28
+ border-radius: 2px;
29
+ }
30
+ }
31
+
32
+ .crepe-diff-panel {
33
+ display: flex;
34
+ flex-direction: column;
35
+ height: 100%;
36
+ background: #fff;
37
+ border-left: 1px solid #e8e8e8;
38
+ font-family:
39
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
40
+ font-size: 14px;
41
+ color: #333;
42
+ }
43
+
44
+ .crepe-diff-panel-header {
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: space-between;
48
+ padding: 12px 16px;
49
+ font-size: 14px;
50
+ font-weight: 600;
51
+ border-bottom: 1px solid #eee;
52
+ flex-shrink: 0;
53
+ }
54
+
55
+ .crepe-diff-panel-close {
56
+ width: 24px;
57
+ height: 24px;
58
+ border: none;
59
+ background: none;
60
+ font-size: 16px;
61
+ color: #999;
62
+ cursor: pointer;
63
+ border-radius: 4px;
64
+ display: flex;
65
+ align-items: center;
66
+ justify-content: center;
67
+ }
68
+
69
+ .crepe-diff-panel-close:hover {
70
+ background: #f0f0f0;
71
+ color: #333;
72
+ }
73
+
74
+ .crepe-diff-panel-tabs {
75
+ display: flex;
76
+ border-bottom: 1px solid #eee;
77
+ padding: 0 8px;
78
+ flex-shrink: 0;
79
+ }
80
+
81
+ .crepe-diff-panel-tab {
82
+ padding: 6px 10px;
83
+ border: none;
84
+ background: none;
85
+ cursor: pointer;
86
+ font-size: 12px;
87
+ color: #666;
88
+ border-bottom: 2px solid transparent;
89
+ transition: color 0.2s;
90
+ }
91
+
92
+ .crepe-diff-panel-tab:hover {
93
+ color: #333;
94
+ }
95
+
96
+ .crepe-diff-panel-tab.active {
97
+ color: #1890ff;
98
+ border-bottom-color: #1890ff;
99
+ }
100
+
101
+ .crepe-diff-panel-list {
102
+ flex: 1;
103
+ overflow-y: auto;
104
+ padding: 8px;
105
+ }
106
+
107
+ .crepe-diff-panel-item {
108
+ padding: 8px 10px;
109
+ border-radius: 4px;
110
+ margin-bottom: 6px;
111
+ background: #fafafa;
112
+ border: 1px solid #eee;
113
+ cursor: pointer;
114
+ transition:
115
+ border-color 0.2s,
116
+ background 0.2s;
117
+ }
118
+
119
+ .crepe-diff-panel-item:hover {
120
+ border-color: #1890ff;
121
+ background: #f0f7ff;
122
+ }
123
+
124
+ .crepe-diff-panel-item-header {
125
+ margin-bottom: 4px;
126
+ }
127
+
128
+ .crepe-diff-panel-item-badge {
129
+ display: inline-block;
130
+ padding: 1px 6px;
131
+ border-radius: 3px;
132
+ color: #fff;
133
+ font-size: 11px;
134
+ font-weight: 500;
135
+ }
136
+
137
+ .crepe-diff-panel-item-row {
138
+ margin-top: 3px;
139
+ font-size: 12px;
140
+ line-height: 1.5;
141
+ color: #555;
142
+ word-break: break-all;
143
+ }
144
+
145
+ .crepe-diff-panel-item-label {
146
+ color: #999;
147
+ font-size: 11px;
148
+ }
@@ -11,3 +11,5 @@
11
11
  @import './table.css';
12
12
  @import './latex.css';
13
13
  @import './attachment-block.css';
14
+ @import './inline-diff.css';
15
+ @import './diff-block.css';
@@ -91,7 +91,7 @@
91
91
  left: 0;
92
92
  right: 0;
93
93
  height: 8px;
94
- z-index: 50;
94
+ z-index: 102;
95
95
  overflow: visible;
96
96
  }
97
97
 
@@ -101,7 +101,7 @@
101
101
  left: -8px;
102
102
  bottom: 0;
103
103
  width: 8px;
104
- z-index: 50;
104
+ z-index: 102;
105
105
  overflow: visible;
106
106
  }
107
107
 
@@ -290,7 +290,7 @@
290
290
  background-color: var(--crepe-color-surface);
291
291
  border-radius: 8px;
292
292
  box-shadow: var(--crepe-shadow-1);
293
- z-index: 60;
293
+ z-index: 102;
294
294
 
295
295
  &::after {
296
296
  content: '';
@@ -455,7 +455,7 @@
455
455
 
456
456
  .cell-toolbar {
457
457
  position: absolute;
458
- z-index: 60;
458
+ z-index: 102;
459
459
  display: flex;
460
460
  gap: 2px;
461
461
  background-color: var(--crepe-color-surface);
@@ -0,0 +1,27 @@
1
+ type Listener = () => void
2
+ const listeners = new Set<Listener>()
3
+ let _popupCount = 0
4
+
5
+ export function getIsAnyPopupOpen(): boolean {
6
+ return _popupCount > 0
7
+ }
8
+
9
+ export function addPopupChangeListener(fn: Listener): () => void {
10
+ listeners.add(fn)
11
+ return () => listeners.delete(fn)
12
+ }
13
+
14
+ export function incrementPopupCount(): void {
15
+ const wasZero = _popupCount === 0
16
+ _popupCount++
17
+ if (wasZero) {
18
+ listeners.forEach((fn) => fn())
19
+ }
20
+ }
21
+
22
+ export function decrementPopupCount(): void {
23
+ _popupCount = Math.max(0, _popupCount - 1)
24
+ if (_popupCount === 0) {
25
+ listeners.forEach((fn) => fn())
26
+ }
27
+ }