@tnotesjs/core 0.1.19 → 0.1.20

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/README.md +87 -87
  2. package/package.json +1 -1
  3. package/types/config.ts +61 -61
  4. package/types/index.ts +11 -11
  5. package/types/note.ts +33 -33
  6. package/vitepress/assets/icons/icon__check.svg +3 -3
  7. package/vitepress/assets/icons/icon__clipboard.svg +7 -7
  8. package/vitepress/assets/icons/icon__close.svg +1 -1
  9. package/vitepress/assets/icons/icon__collapse.svg +1 -1
  10. package/vitepress/assets/icons/icon__confirm.svg +1 -1
  11. package/vitepress/assets/icons/icon__copy.svg +4 -4
  12. package/vitepress/assets/icons/icon__focus.svg +1 -1
  13. package/vitepress/assets/icons/icon__fold.svg +3 -3
  14. package/vitepress/assets/icons/icon__folder.svg +1 -1
  15. package/vitepress/assets/icons/icon__fullscreen.svg +1 -1
  16. package/vitepress/assets/icons/icon__fullscreen_exit.svg +1 -1
  17. package/vitepress/assets/icons/icon__github.svg +3 -3
  18. package/vitepress/assets/icons/icon__mindmap.svg +1 -1
  19. package/vitepress/assets/icons/icon__next.svg +1 -1
  20. package/vitepress/assets/icons/icon__number_gray.svg +1 -1
  21. package/vitepress/assets/icons/icon__number_purple.svg +1 -1
  22. package/vitepress/assets/icons/icon__prev.svg +1 -1
  23. package/vitepress/assets/icons/icon__restore.svg +1 -1
  24. package/vitepress/assets/icons/icon__rotate.svg +4 -4
  25. package/vitepress/assets/icons/icon__search.svg +1 -1
  26. package/vitepress/assets/icons/icon__sidebar_collapsed.svg +1 -1
  27. package/vitepress/assets/icons/icon__sidebar_opened.svg +1 -1
  28. package/vitepress/assets/icons/icon__totop.svg +5 -5
  29. package/vitepress/assets/icons/icon__vscode.svg +5 -5
  30. package/vitepress/assets/icons/icon__zoom_fit.svg +1 -1
  31. package/vitepress/assets/icons/icon__zoom_in.svg +1 -1
  32. package/vitepress/assets/icons/icon__zoom_out.svg +1 -1
  33. package/vitepress/assets/icons/icon__zoom_reset.svg +1 -1
  34. package/vitepress/assets/icons/index.ts +39 -39
  35. package/vitepress/components/BilibiliOutsidePlayer/BilibiliOutsidePlayer.vue +20 -20
  36. package/vitepress/components/CodeBlockFullscreen/CodeBlockFullscreen.vue +369 -369
  37. package/vitepress/components/CodeBlockFullscreen/index.ts +213 -213
  38. package/vitepress/components/CodeBlockFullscreen/styles.css +126 -126
  39. package/vitepress/components/Discussions/Discussions.module.scss +32 -32
  40. package/vitepress/components/Discussions/Discussions.vue +211 -211
  41. package/vitepress/components/EnWordList/EnWordList.module.scss +124 -124
  42. package/vitepress/components/EnWordList/EnWordList.vue +543 -543
  43. package/vitepress/components/EnWordList/RightClickMenu.module.scss +22 -22
  44. package/vitepress/components/EnWordList/RightClickMenu.vue +66 -66
  45. package/vitepress/components/Footprints/Footprints.module.scss +93 -93
  46. package/vitepress/components/Footprints/Footprints.vue +377 -377
  47. package/vitepress/components/Layout/AboutModal.module.scss +233 -233
  48. package/vitepress/components/Layout/AboutModal.vue +105 -105
  49. package/vitepress/components/Layout/AboutPanel.vue +270 -270
  50. package/vitepress/components/Layout/ContentCollapse.vue +603 -603
  51. package/vitepress/components/Layout/CustomSidebar.vue +817 -817
  52. package/vitepress/components/Layout/DocBeforeControls.vue +149 -149
  53. package/vitepress/components/Layout/DocFooter.vue +233 -233
  54. package/vitepress/components/Layout/ImagePreview.module.scss +201 -201
  55. package/vitepress/components/Layout/ImagePreview.vue +281 -281
  56. package/vitepress/components/Layout/Layout.module.scss +661 -661
  57. package/vitepress/components/Layout/Layout.vue +621 -621
  58. package/vitepress/components/Layout/NoteStatus.vue +140 -140
  59. package/vitepress/components/Layout/SidebarItems.vue +1083 -1083
  60. package/vitepress/components/Layout/SidebarNavBefore.vue +171 -171
  61. package/vitepress/components/Layout/SidebarResizeHandle.vue +319 -319
  62. package/vitepress/components/Layout/Swiper.vue +167 -167
  63. package/vitepress/components/Layout/ToggleFullContent.module.scss +11 -11
  64. package/vitepress/components/Layout/ToggleFullContent.vue +35 -35
  65. package/vitepress/components/Layout/ToggleSidebar.module.scss +11 -11
  66. package/vitepress/components/Layout/ToggleSidebar.vue +26 -26
  67. package/vitepress/components/Layout/composables/useCollapseControl.ts +88 -88
  68. package/vitepress/components/Layout/composables/useNoteConfig.ts +119 -119
  69. package/vitepress/components/Layout/composables/useNoteSave.ts +178 -178
  70. package/vitepress/components/Layout/composables/useNoteValidation.ts +85 -85
  71. package/vitepress/components/Layout/composables/useRedirect.ts +113 -113
  72. package/vitepress/components/Layout/composables/useSidebarLayout.ts +122 -122
  73. package/vitepress/components/Layout/composables/useVSCodeIntegration.ts +85 -85
  74. package/vitepress/components/Layout/homeReadme.data.ts +124 -124
  75. package/vitepress/components/MarkMap/MarkMap.module.scss +159 -159
  76. package/vitepress/components/MarkMap/MarkMap.vue +405 -405
  77. package/vitepress/components/Mermaid/Mermaid.module.scss +275 -275
  78. package/vitepress/components/Mermaid/Mermaid.vue +365 -365
  79. package/vitepress/components/NotesTable/NotesTable.module.scss +77 -77
  80. package/vitepress/components/NotesTable/NotesTable.vue +98 -98
  81. package/vitepress/components/NotesTable/README.md +67 -67
  82. package/vitepress/components/Settings/Settings.module.scss +375 -375
  83. package/vitepress/components/Settings/Settings.vue +334 -334
  84. package/vitepress/components/SidebarCard/MindMapView.vue +484 -484
  85. package/vitepress/components/SidebarCard/NotesTrendChart.vue +108 -108
  86. package/vitepress/components/SidebarCard/SidebarCard.vue +946 -946
  87. package/vitepress/components/Tooltip/Tooltip.vue +70 -70
  88. package/vitepress/components/constants.ts +109 -109
  89. package/vitepress/components/notesConfig.data.ts +73 -73
  90. package/vitepress/components/sidebar.data.ts +59 -59
  91. package/vitepress/components/tnotes-config.data.ts +21 -21
  92. package/vitepress/components/utils.ts +26 -26
  93. package/vitepress/config/index.ts +169 -169
  94. package/vitepress/configs/constants.ts +26 -26
  95. package/vitepress/configs/head.config.ts +25 -25
  96. package/vitepress/configs/index.ts +9 -9
  97. package/vitepress/configs/markdown-it.d.ts +23 -23
  98. package/vitepress/configs/markdown.config.ts +366 -366
  99. package/vitepress/configs/theme.config.ts +108 -108
  100. package/vitepress/plugins/buildProgressPlugin.ts +434 -434
  101. package/vitepress/plugins/getNoteByConfigIdPlugin.ts +107 -107
  102. package/vitepress/plugins/renameNotePlugin.ts +68 -68
  103. package/vitepress/plugins/sidebarStructurePlugin.ts +260 -260
  104. package/vitepress/plugins/updateConfigPlugin.ts +63 -63
  105. package/vitepress/theme/index.ts +137 -137
  106. package/vitepress/theme/styles/base.scss +64 -59
  107. package/vitepress/theme/styles/components/404.scss +31 -31
  108. package/vitepress/theme/styles/components/collapse.scss +172 -172
  109. package/vitepress/theme/styles/components/markmap.scss +101 -101
  110. package/vitepress/theme/styles/components/swiper.scss +255 -255
  111. package/vitepress/theme/styles/index.scss +25 -25
  112. package/vitepress/theme/styles/layout.scss +78 -78
  113. package/vitepress/theme/styles/utilities.scss +39 -39
  114. package/vitepress/theme/styles/vitepress-override.scss +25 -25
@@ -1,319 +1,319 @@
1
- <template>
2
- <div
3
- class="sidebar-resize-handle"
4
- :class="{
5
- 'is-hidden': hidden,
6
- 'is-dragging': isDragging,
7
- 'is-fullscreen': isContentFullscreen,
8
- }"
9
- >
10
- <div
11
- v-if="!hidden"
12
- class="resize-hotspot"
13
- :aria-label="`拖动调整侧边栏宽度,当前 ${width}px`"
14
- role="separator"
15
- aria-orientation="vertical"
16
- :aria-valuemin="minWidth"
17
- :aria-valuemax="maxWidth"
18
- :aria-valuenow="width"
19
- @mousedown.prevent="startResize"
20
- ></div>
21
-
22
- <div v-if="!hidden" class="resize-indicator" aria-hidden="true"></div>
23
-
24
- <button
25
- class="sidebar-edge-toggle"
26
- type="button"
27
- :aria-label="toggleTitle"
28
- :aria-pressed="hidden"
29
- @click.stop="toggleSidebar"
30
- >
31
- <img :src="toggleIcon" alt="" />
32
- <span class="sidebar-edge-tooltip" role="tooltip">
33
- <span>{{ toggleActionText }}</span>
34
- <kbd>{{ shortcutText }}</kbd>
35
- </span>
36
- </button>
37
- </div>
38
- </template>
39
-
40
- <script setup lang="ts">
41
- import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
42
-
43
- import { useSidebarLayout } from './composables/useSidebarLayout'
44
- import { icon__next, icon__prev } from '../../assets/icons'
45
-
46
- const {
47
- hidden,
48
- width,
49
- minWidth,
50
- maxWidth,
51
- initSidebarLayout,
52
- toggleSidebar,
53
- setSidebarWidth,
54
- saveSidebarWidth,
55
- } = useSidebarLayout()
56
-
57
- const isDragging = ref(false)
58
- const isContentFullscreen = ref(false)
59
- const shortcutText = ref('Ctrl + Alt + ,')
60
- let fullscreenObserver: MutationObserver | null = null
61
-
62
- const toggleIcon = computed(() => (hidden.value ? icon__next : icon__prev))
63
- const toggleActionText = computed(() =>
64
- hidden.value ? '展开侧边栏' : '收起侧边栏',
65
- )
66
- const toggleTitle = computed(
67
- () => `${toggleActionText.value}\n${shortcutText.value}`,
68
- )
69
-
70
- onMounted(() => {
71
- initSidebarLayout()
72
- shortcutText.value = getShortcutText()
73
- updateContentFullscreen()
74
- fullscreenObserver = new MutationObserver(updateContentFullscreen)
75
- fullscreenObserver.observe(document.documentElement, {
76
- attributes: true,
77
- attributeFilter: ['class'],
78
- })
79
- window.addEventListener('keydown', handleShortcut)
80
- })
81
-
82
- onBeforeUnmount(() => {
83
- window.removeEventListener('keydown', handleShortcut)
84
- fullscreenObserver?.disconnect()
85
- fullscreenObserver = null
86
- stopResize()
87
- })
88
-
89
- function startResize(event: MouseEvent) {
90
- if (hidden.value || event.button !== 0) return
91
-
92
- isDragging.value = true
93
- document.body.classList.add('is-sidebar-resizing')
94
- window.addEventListener('mousemove', resize)
95
- window.addEventListener('mouseup', stopResize)
96
- setSidebarWidth(event.clientX)
97
- }
98
-
99
- function resize(event: MouseEvent) {
100
- if (!isDragging.value) return
101
-
102
- setSidebarWidth(event.clientX)
103
- }
104
-
105
- function stopResize() {
106
- if (!isDragging.value) return
107
-
108
- isDragging.value = false
109
- document.body.classList.remove('is-sidebar-resizing')
110
- window.removeEventListener('mousemove', resize)
111
- window.removeEventListener('mouseup', stopResize)
112
- saveSidebarWidth()
113
- }
114
-
115
- function handleShortcut(event: KeyboardEvent) {
116
- if (!isToggleShortcut(event) || isEditableTarget(event.target)) return
117
-
118
- event.preventDefault()
119
- toggleSidebar()
120
- }
121
-
122
- function updateContentFullscreen() {
123
- isContentFullscreen.value =
124
- document.documentElement.classList.contains('content-fullscreen')
125
- }
126
-
127
- function isToggleShortcut(event: KeyboardEvent): boolean {
128
- return (
129
- (event.ctrlKey || event.metaKey) && event.altKey && event.code === 'Comma'
130
- )
131
- }
132
-
133
- function getShortcutText(): string {
134
- return isMacPlatform() ? 'Cmd + Option + ,' : 'Ctrl + Alt + ,'
135
- }
136
-
137
- function isMacPlatform(): boolean {
138
- if (typeof navigator === 'undefined') return false
139
-
140
- return /Mac|iPhone|iPad|iPod/i.test(navigator.platform)
141
- }
142
-
143
- function isEditableTarget(target: EventTarget | null): boolean {
144
- if (!(target instanceof HTMLElement)) return false
145
-
146
- const tagName = target.tagName.toLowerCase()
147
- if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {
148
- return true
149
- }
150
-
151
- return target.isContentEditable || !!target.closest('[contenteditable="true"]')
152
- }
153
- </script>
154
-
155
- <style scoped>
156
- .sidebar-resize-handle {
157
- position: fixed;
158
- top: 0;
159
- bottom: 0;
160
- left: calc(var(--tn-sidebar-width, 260px) - 5px);
161
- z-index: 30;
162
- width: 10px;
163
- cursor: col-resize;
164
- }
165
-
166
- .sidebar-resize-handle::before {
167
- position: absolute;
168
- top: var(--vp-nav-height);
169
- bottom: 0;
170
- left: 4px;
171
- width: 2px;
172
- background: var(--vp-c-brand-1);
173
- border-radius: 999px;
174
- box-shadow: 0 0 0 1px var(--vp-c-brand-soft);
175
- content: '';
176
- opacity: 0;
177
- pointer-events: none;
178
- transition: opacity 0.18s ease;
179
- }
180
-
181
- .resize-hotspot {
182
- position: absolute;
183
- top: var(--vp-nav-height);
184
- right: 0;
185
- bottom: 0;
186
- left: 0;
187
- }
188
-
189
- .resize-indicator {
190
- position: absolute;
191
- top: 50%;
192
- left: 50%;
193
- width: 4px;
194
- height: 28px;
195
- border-right: 1px solid var(--vp-c-brand-1);
196
- border-left: 1px solid var(--vp-c-brand-1);
197
- opacity: 0;
198
- pointer-events: none;
199
- transform: translate(-50%, -50%);
200
- transition: opacity 0.18s ease;
201
- }
202
-
203
- .sidebar-edge-toggle {
204
- position: absolute;
205
- top: 220px;
206
- left: -2px;
207
- display: inline-flex;
208
- align-items: center;
209
- justify-content: center;
210
- width: 14px;
211
- height: 44px;
212
- padding: 0;
213
- color: var(--vp-c-text-2);
214
- background: var(--vp-c-bg);
215
- border: 1px solid var(--vp-c-divider);
216
- border-radius: 7px;
217
- box-shadow: var(--vp-shadow-2);
218
- cursor: pointer;
219
- opacity: 0;
220
- pointer-events: none;
221
- transition:
222
- opacity 0.18s ease,
223
- border-color 0.18s ease,
224
- background-color 0.18s ease;
225
- }
226
-
227
- .sidebar-edge-toggle img {
228
- width: 10px;
229
- height: 10px;
230
- }
231
-
232
- .sidebar-edge-tooltip {
233
- position: absolute;
234
- top: 50%;
235
- left: calc(100% + 8px);
236
- display: flex;
237
- flex-direction: column;
238
- gap: 2px;
239
- min-width: 128px;
240
- padding: 7px 9px;
241
- color: var(--vp-c-text-1);
242
- background: var(--vp-c-bg-elv);
243
- border: 1px solid var(--vp-c-divider);
244
- border-radius: 6px;
245
- box-shadow: var(--vp-shadow-2);
246
- font-size: 12px;
247
- line-height: 18px;
248
- opacity: 0;
249
- pointer-events: none;
250
- text-align: left;
251
- transform: translate(2px, -50%);
252
- transition:
253
- opacity 0.16s ease,
254
- transform 0.16s ease;
255
- white-space: nowrap;
256
- }
257
-
258
- .sidebar-edge-tooltip kbd {
259
- color: var(--vp-c-text-2);
260
- font-family: var(--vp-font-family-mono);
261
- font-size: 11px;
262
- }
263
-
264
- .sidebar-edge-toggle:hover .sidebar-edge-tooltip,
265
- .sidebar-edge-toggle:focus-visible .sidebar-edge-tooltip {
266
- opacity: 1;
267
- transform: translate(0, -50%);
268
- }
269
-
270
- .sidebar-resize-handle:hover::before,
271
- .sidebar-resize-handle.is-dragging::before,
272
- .sidebar-resize-handle:hover .resize-indicator,
273
- .sidebar-resize-handle.is-dragging .resize-indicator,
274
- .sidebar-resize-handle:hover .sidebar-edge-toggle,
275
- .sidebar-resize-handle.is-dragging .sidebar-edge-toggle,
276
- .sidebar-resize-handle.is-hidden .sidebar-edge-toggle {
277
- opacity: 1;
278
- pointer-events: auto;
279
- }
280
-
281
- .sidebar-edge-toggle:hover {
282
- color: var(--vp-c-brand-1);
283
- background: var(--vp-c-bg-soft);
284
- border-color: var(--vp-c-brand-1);
285
- }
286
-
287
- .sidebar-resize-handle.is-hidden {
288
- left: 0;
289
- width: 14px;
290
- cursor: default;
291
- }
292
-
293
- .sidebar-resize-handle.is-hidden::before,
294
- .sidebar-resize-handle.is-hidden .resize-indicator {
295
- display: none;
296
- }
297
-
298
- .sidebar-resize-handle.is-hidden .sidebar-edge-toggle {
299
- left: 0;
300
- border-left-color: var(--vp-c-divider);
301
- border-radius: 0 7px 7px 0;
302
- }
303
-
304
- :global(body.is-sidebar-resizing),
305
- :global(body.is-sidebar-resizing *) {
306
- cursor: col-resize !important;
307
- user-select: none !important;
308
- }
309
-
310
- .sidebar-resize-handle.is-fullscreen {
311
- display: none;
312
- }
313
-
314
- @media (max-width: 959px) {
315
- .sidebar-resize-handle {
316
- display: none;
317
- }
318
- }
319
- </style>
1
+ <template>
2
+ <div
3
+ class="sidebar-resize-handle"
4
+ :class="{
5
+ 'is-hidden': hidden,
6
+ 'is-dragging': isDragging,
7
+ 'is-fullscreen': isContentFullscreen,
8
+ }"
9
+ >
10
+ <div
11
+ v-if="!hidden"
12
+ class="resize-hotspot"
13
+ :aria-label="`拖动调整侧边栏宽度,当前 ${width}px`"
14
+ role="separator"
15
+ aria-orientation="vertical"
16
+ :aria-valuemin="minWidth"
17
+ :aria-valuemax="maxWidth"
18
+ :aria-valuenow="width"
19
+ @mousedown.prevent="startResize"
20
+ ></div>
21
+
22
+ <div v-if="!hidden" class="resize-indicator" aria-hidden="true"></div>
23
+
24
+ <button
25
+ class="sidebar-edge-toggle"
26
+ type="button"
27
+ :aria-label="toggleTitle"
28
+ :aria-pressed="hidden"
29
+ @click.stop="toggleSidebar"
30
+ >
31
+ <img :src="toggleIcon" alt="" />
32
+ <span class="sidebar-edge-tooltip" role="tooltip">
33
+ <span>{{ toggleActionText }}</span>
34
+ <kbd>{{ shortcutText }}</kbd>
35
+ </span>
36
+ </button>
37
+ </div>
38
+ </template>
39
+
40
+ <script setup lang="ts">
41
+ import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
42
+
43
+ import { useSidebarLayout } from './composables/useSidebarLayout'
44
+ import { icon__next, icon__prev } from '../../assets/icons'
45
+
46
+ const {
47
+ hidden,
48
+ width,
49
+ minWidth,
50
+ maxWidth,
51
+ initSidebarLayout,
52
+ toggleSidebar,
53
+ setSidebarWidth,
54
+ saveSidebarWidth,
55
+ } = useSidebarLayout()
56
+
57
+ const isDragging = ref(false)
58
+ const isContentFullscreen = ref(false)
59
+ const shortcutText = ref('Ctrl + Alt + ,')
60
+ let fullscreenObserver: MutationObserver | null = null
61
+
62
+ const toggleIcon = computed(() => (hidden.value ? icon__next : icon__prev))
63
+ const toggleActionText = computed(() =>
64
+ hidden.value ? '展开侧边栏' : '收起侧边栏',
65
+ )
66
+ const toggleTitle = computed(
67
+ () => `${toggleActionText.value}\n${shortcutText.value}`,
68
+ )
69
+
70
+ onMounted(() => {
71
+ initSidebarLayout()
72
+ shortcutText.value = getShortcutText()
73
+ updateContentFullscreen()
74
+ fullscreenObserver = new MutationObserver(updateContentFullscreen)
75
+ fullscreenObserver.observe(document.documentElement, {
76
+ attributes: true,
77
+ attributeFilter: ['class'],
78
+ })
79
+ window.addEventListener('keydown', handleShortcut)
80
+ })
81
+
82
+ onBeforeUnmount(() => {
83
+ window.removeEventListener('keydown', handleShortcut)
84
+ fullscreenObserver?.disconnect()
85
+ fullscreenObserver = null
86
+ stopResize()
87
+ })
88
+
89
+ function startResize(event: MouseEvent) {
90
+ if (hidden.value || event.button !== 0) return
91
+
92
+ isDragging.value = true
93
+ document.body.classList.add('is-sidebar-resizing')
94
+ window.addEventListener('mousemove', resize)
95
+ window.addEventListener('mouseup', stopResize)
96
+ setSidebarWidth(event.clientX)
97
+ }
98
+
99
+ function resize(event: MouseEvent) {
100
+ if (!isDragging.value) return
101
+
102
+ setSidebarWidth(event.clientX)
103
+ }
104
+
105
+ function stopResize() {
106
+ if (!isDragging.value) return
107
+
108
+ isDragging.value = false
109
+ document.body.classList.remove('is-sidebar-resizing')
110
+ window.removeEventListener('mousemove', resize)
111
+ window.removeEventListener('mouseup', stopResize)
112
+ saveSidebarWidth()
113
+ }
114
+
115
+ function handleShortcut(event: KeyboardEvent) {
116
+ if (!isToggleShortcut(event) || isEditableTarget(event.target)) return
117
+
118
+ event.preventDefault()
119
+ toggleSidebar()
120
+ }
121
+
122
+ function updateContentFullscreen() {
123
+ isContentFullscreen.value =
124
+ document.documentElement.classList.contains('content-fullscreen')
125
+ }
126
+
127
+ function isToggleShortcut(event: KeyboardEvent): boolean {
128
+ return (
129
+ (event.ctrlKey || event.metaKey) && event.altKey && event.code === 'Comma'
130
+ )
131
+ }
132
+
133
+ function getShortcutText(): string {
134
+ return isMacPlatform() ? 'Cmd + Option + ,' : 'Ctrl + Alt + ,'
135
+ }
136
+
137
+ function isMacPlatform(): boolean {
138
+ if (typeof navigator === 'undefined') return false
139
+
140
+ return /Mac|iPhone|iPad|iPod/i.test(navigator.platform)
141
+ }
142
+
143
+ function isEditableTarget(target: EventTarget | null): boolean {
144
+ if (!(target instanceof HTMLElement)) return false
145
+
146
+ const tagName = target.tagName.toLowerCase()
147
+ if (tagName === 'input' || tagName === 'textarea' || tagName === 'select') {
148
+ return true
149
+ }
150
+
151
+ return target.isContentEditable || !!target.closest('[contenteditable="true"]')
152
+ }
153
+ </script>
154
+
155
+ <style scoped>
156
+ .sidebar-resize-handle {
157
+ position: fixed;
158
+ top: 0;
159
+ bottom: 0;
160
+ left: calc(var(--tn-sidebar-width, 260px) - 5px);
161
+ z-index: 30;
162
+ width: 10px;
163
+ cursor: col-resize;
164
+ }
165
+
166
+ .sidebar-resize-handle::before {
167
+ position: absolute;
168
+ top: var(--vp-nav-height);
169
+ bottom: 0;
170
+ left: 4px;
171
+ width: 2px;
172
+ background: var(--vp-c-brand-1);
173
+ border-radius: 999px;
174
+ box-shadow: 0 0 0 1px var(--vp-c-brand-soft);
175
+ content: '';
176
+ opacity: 0;
177
+ pointer-events: none;
178
+ transition: opacity 0.18s ease;
179
+ }
180
+
181
+ .resize-hotspot {
182
+ position: absolute;
183
+ top: var(--vp-nav-height);
184
+ right: 0;
185
+ bottom: 0;
186
+ left: 0;
187
+ }
188
+
189
+ .resize-indicator {
190
+ position: absolute;
191
+ top: 50%;
192
+ left: 50%;
193
+ width: 4px;
194
+ height: 28px;
195
+ border-right: 1px solid var(--vp-c-brand-1);
196
+ border-left: 1px solid var(--vp-c-brand-1);
197
+ opacity: 0;
198
+ pointer-events: none;
199
+ transform: translate(-50%, -50%);
200
+ transition: opacity 0.18s ease;
201
+ }
202
+
203
+ .sidebar-edge-toggle {
204
+ position: absolute;
205
+ top: 220px;
206
+ left: -2px;
207
+ display: inline-flex;
208
+ align-items: center;
209
+ justify-content: center;
210
+ width: 14px;
211
+ height: 44px;
212
+ padding: 0;
213
+ color: var(--vp-c-text-2);
214
+ background: var(--vp-c-bg);
215
+ border: 1px solid var(--vp-c-divider);
216
+ border-radius: 7px;
217
+ box-shadow: var(--vp-shadow-2);
218
+ cursor: pointer;
219
+ opacity: 0;
220
+ pointer-events: none;
221
+ transition:
222
+ opacity 0.18s ease,
223
+ border-color 0.18s ease,
224
+ background-color 0.18s ease;
225
+ }
226
+
227
+ .sidebar-edge-toggle img {
228
+ width: 10px;
229
+ height: 10px;
230
+ }
231
+
232
+ .sidebar-edge-tooltip {
233
+ position: absolute;
234
+ top: 50%;
235
+ left: calc(100% + 8px);
236
+ display: flex;
237
+ flex-direction: column;
238
+ gap: 2px;
239
+ min-width: 128px;
240
+ padding: 7px 9px;
241
+ color: var(--vp-c-text-1);
242
+ background: var(--vp-c-bg-elv);
243
+ border: 1px solid var(--vp-c-divider);
244
+ border-radius: 6px;
245
+ box-shadow: var(--vp-shadow-2);
246
+ font-size: 12px;
247
+ line-height: 18px;
248
+ opacity: 0;
249
+ pointer-events: none;
250
+ text-align: left;
251
+ transform: translate(2px, -50%);
252
+ transition:
253
+ opacity 0.16s ease,
254
+ transform 0.16s ease;
255
+ white-space: nowrap;
256
+ }
257
+
258
+ .sidebar-edge-tooltip kbd {
259
+ color: var(--vp-c-text-2);
260
+ font-family: var(--vp-font-family-mono);
261
+ font-size: 11px;
262
+ }
263
+
264
+ .sidebar-edge-toggle:hover .sidebar-edge-tooltip,
265
+ .sidebar-edge-toggle:focus-visible .sidebar-edge-tooltip {
266
+ opacity: 1;
267
+ transform: translate(0, -50%);
268
+ }
269
+
270
+ .sidebar-resize-handle:hover::before,
271
+ .sidebar-resize-handle.is-dragging::before,
272
+ .sidebar-resize-handle:hover .resize-indicator,
273
+ .sidebar-resize-handle.is-dragging .resize-indicator,
274
+ .sidebar-resize-handle:hover .sidebar-edge-toggle,
275
+ .sidebar-resize-handle.is-dragging .sidebar-edge-toggle,
276
+ .sidebar-resize-handle.is-hidden .sidebar-edge-toggle {
277
+ opacity: 1;
278
+ pointer-events: auto;
279
+ }
280
+
281
+ .sidebar-edge-toggle:hover {
282
+ color: var(--vp-c-brand-1);
283
+ background: var(--vp-c-bg-soft);
284
+ border-color: var(--vp-c-brand-1);
285
+ }
286
+
287
+ .sidebar-resize-handle.is-hidden {
288
+ left: 0;
289
+ width: 14px;
290
+ cursor: default;
291
+ }
292
+
293
+ .sidebar-resize-handle.is-hidden::before,
294
+ .sidebar-resize-handle.is-hidden .resize-indicator {
295
+ display: none;
296
+ }
297
+
298
+ .sidebar-resize-handle.is-hidden .sidebar-edge-toggle {
299
+ left: 0;
300
+ border-left-color: var(--vp-c-divider);
301
+ border-radius: 0 7px 7px 0;
302
+ }
303
+
304
+ :global(body.is-sidebar-resizing),
305
+ :global(body.is-sidebar-resizing *) {
306
+ cursor: col-resize !important;
307
+ user-select: none !important;
308
+ }
309
+
310
+ .sidebar-resize-handle.is-fullscreen {
311
+ display: none;
312
+ }
313
+
314
+ @media (max-width: 959px) {
315
+ .sidebar-resize-handle {
316
+ display: none;
317
+ }
318
+ }
319
+ </style>