@textbus/xnote 0.0.1-alpha.9 → 0.0.2

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 (43) hide show
  1. package/README.md +139 -1
  2. package/bundles/components/_api.d.ts +2 -0
  3. package/bundles/components/dropdown/dropdown-menu.d.ts +4 -1
  4. package/bundles/components/dropdown/dropdown.d.ts +3 -1
  5. package/bundles/components/keymap/keymap.d.ts +5 -0
  6. package/bundles/components/menu-heading/menu-heading.d.ts +2 -0
  7. package/bundles/components/menu-item/menu-item.d.ts +2 -1
  8. package/bundles/components/popup/popup.d.ts +1 -1
  9. package/bundles/fonts/textbus.svg +3 -32
  10. package/bundles/fonts/textbus.ttf +0 -0
  11. package/bundles/fonts/textbus.woff +0 -0
  12. package/bundles/index.css +2 -2
  13. package/bundles/index.esm.css +2 -2
  14. package/bundles/index.esm.js +1589 -677
  15. package/bundles/index.js +1600 -672
  16. package/bundles/plugins/_api.d.ts +1 -0
  17. package/bundles/plugins/_common/attr.tool.d.ts +2 -2
  18. package/bundles/plugins/_common/color.tool.d.ts +2 -2
  19. package/bundles/plugins/left-toolbar/insert-tool.d.ts +1 -0
  20. package/bundles/plugins/link-jump/link-jump.d.ts +4 -0
  21. package/bundles/public-api.d.ts +1 -0
  22. package/bundles/services/editor.service.d.ts +4 -0
  23. package/bundles/textbus/components/SlotRender.d.ts +14 -0
  24. package/bundles/textbus/components/_api.d.ts +3 -0
  25. package/bundles/textbus/components/at/at-component.view.d.ts +6 -0
  26. package/bundles/textbus/components/at/at.component.d.ts +35 -0
  27. package/bundles/textbus/components/blockqoute/blockquote.component.d.ts +4 -1
  28. package/bundles/textbus/components/highlight-box/highlight-box.component.d.ts +1 -0
  29. package/bundles/textbus/components/image/image.component.d.ts +2 -1
  30. package/bundles/textbus/components/katex/katex-editor.d.ts +7 -0
  31. package/bundles/textbus/components/katex/katex.component.d.ts +16 -0
  32. package/bundles/textbus/components/list/list.component.d.ts +3 -0
  33. package/bundles/textbus/components/paragraph/paragraph.component.d.ts +1 -0
  34. package/bundles/textbus/components/root/root.component.d.ts +2 -0
  35. package/bundles/textbus/components/source-code/source-code.component.d.ts +2 -1
  36. package/bundles/textbus/components/table/components/resize-column.d.ts +2 -1
  37. package/bundles/textbus/components/table/components/scroll.d.ts +1 -2
  38. package/bundles/textbus/components/table/components/top-bar.d.ts +2 -2
  39. package/bundles/textbus/components/table/table-selection-awareness-delegate.d.ts +15 -0
  40. package/bundles/textbus/components/table/table.component.d.ts +1 -1
  41. package/bundles/textbus/components/todolist/todolist.component.d.ts +1 -0
  42. package/bundles/textbus/components/video/video.component.d.ts +1 -1
  43. package/package.json +35 -11
@@ -1,15 +1,17 @@
1
1
  import { jsxs, jsx, Fragment } from '@viewfly/core/jsx-runtime';
2
2
  import { withScopedCSS } from '@viewfly/scoped-css';
3
- import { Injectable, InjectFlags, Injector, inject, createSignal, onUnmounted, createRef, withAnnotation, onMounted, InjectionToken, viewfly, createDynamicRef, getCurrentInstance, onUpdated, watch, ReflectiveInjector } from '@viewfly/core';
4
- import { Subject, Selection, fromEvent, Subscription, Attribute, Keyboard, Commander, Controller, ContentType, Component, Registry, Slot, useContext, onBreak, createVNode, BehaviorSubject, onPaste, onFocus, onBlur, useDynamicShortcut, VTextNode, Query, QueryStateType, onContentInsert, onFocusIn, onFocusOut, onGetRanges, Formatter, onParentSlotUpdated, Textbus, RootComponentRef, filter, map, distinctUntilChanged, sampleTime, merge, debounceTime, throttleTime, delay, onCompositionStart } from '@textbus/core';
5
- import { VIEW_CONTAINER, DomAdapter, Input, SelectionBridge, VIEW_DOCUMENT, BrowserModule, Parser } from '@textbus/platform-browser';
6
- import { createPortal, DomRenderer, createApp, HTMLRenderer, OutputTranslator } from '@viewfly/platform-browser';
3
+ import { Injectable, InjectFlags, Injector, inject, createSignal, onUnmounted, createRef, withAnnotation, onUpdated, onMounted, InjectionToken, getCurrentInstance, ReflectiveInjector, createDynamicRef, jsx as jsx$1, viewfly, watch } from '@viewfly/core';
4
+ import { Subject, Selection, fromEvent, Subscription, Attribute, Keyboard, Commander, Controller, useContext, onBreak, onContentInsert, ContentType, merge, createVNode, Slot, Component, Registry, Query, QueryStateType, BehaviorSubject, onSlotApplyFormat, onSlotSetAttribute, onPaste, onFocus, onBlur, useDynamicShortcut, VTextNode, onFocusIn, onFocusOut, onDestroy, onGetRanges, Formatter, onParentSlotUpdated, Textbus, RootComponentRef, filter, map, distinctUntilChanged, sampleTime, debounceTime, throttleTime, delay, onContentInserted, onContentDeleted, switchMap, fromPromise, onCompositionStart } from '@textbus/core';
5
+ import { VIEW_CONTAINER, isMac, DomAdapter, Input, SelectionBridge, BrowserModule, VIEW_DOCUMENT, CollaborateSelectionAwarenessDelegate, isMobileBrowser, Parser } from '@textbus/platform-browser';
6
+ import { createPortal, createApp, DomRenderer, HTMLRenderer, OutputTranslator } from '@viewfly/platform-browser';
7
7
  import { useProduce } from '@viewfly/hooks';
8
8
  import highlightjs from 'highlight.js';
9
+ import Katex from 'katex';
9
10
  import { ViewflyAdapter, ViewflyVDomAdapter } from '@textbus/adapter-viewfly';
11
+ import { any2Hsl, hsl2Rgb } from '@tanbo/color';
10
12
  import { CollaborateModule } from '@textbus/collaborate';
11
13
 
12
- var scopedId$k = "vf-3d0183";
14
+ var scopedId$n = "vf-d94b56";
13
15
 
14
16
  /******************************************************************************
15
17
  Copyright (c) Microsoft Corporation.
@@ -28,6 +30,18 @@ PERFORMANCE OF THIS SOFTWARE.
28
30
  /* global Reflect, Promise, SuppressedError, Symbol */
29
31
 
30
32
 
33
+ function __rest(s, e) {
34
+ var t = {};
35
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
36
+ t[p] = s[p];
37
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
38
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
39
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
40
+ t[p[i]] = s[p[i]];
41
+ }
42
+ return t;
43
+ }
44
+
31
45
  function __decorate(decorators, target, key, desc) {
32
46
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
33
47
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -71,7 +85,7 @@ let DropdownContextService = DropdownContextService_1 = class DropdownContextSer
71
85
  this.canHide = true;
72
86
  this.openStateChangeEvent = new Subject();
73
87
  this.timer = null;
74
- this.parentDropdownContextService = this.injector.get(DropdownContextService_1, InjectFlags.SkipSelf, null);
88
+ this.parentDropdownContextService = this.injector.get(DropdownContextService_1, null, InjectFlags.SkipSelf);
75
89
  this.onOpenStateChange = this.openStateChangeEvent.asObservable();
76
90
  dropdownService.onSiblingOpen.subscribe(id => {
77
91
  if (id === this.id) {
@@ -120,7 +134,7 @@ DropdownContextService = DropdownContextService_1 = __decorate([
120
134
  ], DropdownContextService);
121
135
 
122
136
  function Button(props) {
123
- const dropdownContextService = inject(DropdownContextService, InjectFlags.Optional, null);
137
+ const dropdownContextService = inject(DropdownContextService, null);
124
138
  const isActive = createSignal((dropdownContextService === null || dropdownContextService === void 0 ? void 0 : dropdownContextService.isOpen) || false);
125
139
  if (dropdownContextService) {
126
140
  const subscription = dropdownContextService.onOpenStateChange.subscribe(b => {
@@ -130,7 +144,7 @@ function Button(props) {
130
144
  subscription.unsubscribe();
131
145
  });
132
146
  }
133
- return withScopedCSS(scopedId$k, () => {
147
+ return withScopedCSS(scopedId$n, () => {
134
148
  return (jsxs("button", Object.assign({ type: "button" }, props, { class: [
135
149
  'btn',
136
150
  {
@@ -142,10 +156,10 @@ function Button(props) {
142
156
  });
143
157
  }
144
158
 
145
- var scopedId$j = "vf-ac7e8d";
159
+ var scopedId$m = "vf-ac7e8d";
146
160
 
147
161
  function ComponentToolbar(props) {
148
- return withScopedCSS(scopedId$j, () => {
162
+ return withScopedCSS(scopedId$m, () => {
149
163
  return (jsx("div", { class: "component-toolbar", style: props.style, children: jsx("div", { class: [
150
164
  'toolbar',
151
165
  {
@@ -155,15 +169,15 @@ function ComponentToolbar(props) {
155
169
  });
156
170
  }
157
171
 
158
- var scopedId$i = "vf-ede279";
172
+ var scopedId$l = "vf-ede279";
159
173
 
160
174
  function Divider() {
161
- return withScopedCSS(scopedId$i, () => {
175
+ return withScopedCSS(scopedId$l, () => {
162
176
  return jsx("div", { class: "divider" });
163
177
  });
164
178
  }
165
179
 
166
- var scopedId$h = "vf-4c1803";
180
+ var scopedId$k = "vf-8abf2c";
167
181
 
168
182
  function DragResize(props) {
169
183
  const isShow = createSignal(false);
@@ -184,7 +198,7 @@ function DragResize(props) {
184
198
  isShow.set(true);
185
199
  const width = ref.current.offsetWidth;
186
200
  const height = ref.current.offsetHeight;
187
- mask.current.innerText = `${Math.round(width)}px * ${Math.round(height)}px`;
201
+ sizeText.set(`${Math.round(width)}px * ${Math.round(height)}px`);
188
202
  });
189
203
  function selectComponent() {
190
204
  selection.selectComponent(component, true);
@@ -261,7 +275,7 @@ function DragResize(props) {
261
275
  }
262
276
  ele.style.width = endWidth + 'px';
263
277
  ele.style.height = endHeight + 'px';
264
- mask.current.innerText = `${Math.round(endWidth)}px * ${Math.round(endHeight)}px`;
278
+ sizeText.set(`${Math.round(endWidth)}px * ${Math.round(endHeight)}px`);
265
279
  });
266
280
  const unUp = fromEvent(document, 'mouseup').subscribe(() => {
267
281
  component.state.width = endWidth + 'px';
@@ -271,16 +285,17 @@ function DragResize(props) {
271
285
  unUp.unsubscribe();
272
286
  });
273
287
  }
274
- return withScopedCSS(scopedId$h, () => {
288
+ const sizeText = createSignal(`${component.state.width}*${component.state.height}`);
289
+ return withScopedCSS(scopedId$k, () => {
275
290
  return (jsxs("div", { class: "drag-resize", onClick: selectComponent, children: [jsx("div", { class: "container", ref: ref, children: props.children }), jsxs("div", { class: ['resize-tool', {
276
291
  active: isShow()
277
- }], children: [jsxs("div", { class: "mask", ref: mask, children: [component.state.width, "*", component.state.height] }), jsxs("div", { class: "btn-group", ref: btnGroup, onMousedown: drag, children: [jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" })] })] })] }));
292
+ }], children: [jsx("div", { class: "mask", ref: mask, children: sizeText() }), jsxs("div", { class: "btn-group", ref: btnGroup, onMousedown: drag, children: [jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" }), jsx("button", { type: "button" })] })] })] }));
278
293
  });
279
294
  }
280
295
 
281
- var scopedId$g = "vf-a99c5e";
296
+ var scopedId$j = "vf-a99c5e";
282
297
 
283
- var scopedId$f = "vf-41a617";
298
+ var scopedId$i = "vf-8a05e9";
284
299
 
285
300
  const DropdownMenuPortal = withAnnotation({
286
301
  providers: [
@@ -288,11 +303,14 @@ const DropdownMenuPortal = withAnnotation({
288
303
  ]
289
304
  }, function DropdownMenuPortal(props) {
290
305
  const dropdownContextService = inject(DropdownContextService);
306
+ const container = inject(VIEW_CONTAINER);
291
307
  const menuRef = createRef();
292
308
  let timer = null;
293
309
  const delay = 10;
294
- onMounted(() => {
310
+ function update() {
295
311
  const menuElement = menuRef.current;
312
+ menuElement.style.height = 'auto';
313
+ const containerRect = container.getBoundingClientRect();
296
314
  if (props.abreast) {
297
315
  const btnEle = props.triggerRef.current;
298
316
  const screenHeight = document.documentElement.clientHeight;
@@ -307,19 +325,19 @@ const DropdownMenuPortal = withAnnotation({
307
325
  else if (offsetTop + maxHeight > screenHeight - 10) {
308
326
  offsetTop = screenHeight - 10 - maxHeight;
309
327
  }
310
- menuElement.style.top = offsetTop + 'px';
328
+ menuElement.style.top = offsetTop - containerRect.top + 'px';
311
329
  const triggerRect = props.triggerRef.current.getBoundingClientRect();
312
330
  const leftDistance = triggerRect.left;
313
331
  const isToLeft = leftDistance >= menuElement.offsetWidth + 20;
314
- if (isToLeft) {
315
- menuElement.style.left = leftDistance - menuElement.offsetWidth - 20 + 'px';
332
+ if (isToLeft && props.toLeft) {
333
+ menuElement.style.left = leftDistance - menuElement.offsetWidth - 20 - containerRect.left + 'px';
316
334
  timer = setTimeout(() => {
317
335
  menuElement.style.transform = 'translateX(10px)';
318
336
  menuElement.style.opacity = '1';
319
337
  }, delay);
320
338
  }
321
339
  else {
322
- menuElement.style.left = triggerRect.right + 20 + 'px';
340
+ menuElement.style.left = triggerRect.right + 20 - containerRect.left + 'px';
323
341
  timer = setTimeout(() => {
324
342
  menuElement.style.transform = 'translateX(-10px)';
325
343
  menuElement.style.opacity = '1';
@@ -331,12 +349,12 @@ const DropdownMenuPortal = withAnnotation({
331
349
  const documentClientHeight = document.documentElement.clientHeight;
332
350
  const bottomDistance = documentClientHeight - triggerRect.bottom;
333
351
  const isToTop = bottomDistance < 200 && triggerRect.top > bottomDistance;
334
- menuElement.style.left = triggerRect.left + 'px';
352
+ menuElement.style.left = triggerRect.left - containerRect.left + 'px';
335
353
  if (isToTop) {
336
354
  const maxHeight = Math.max(menuElement.scrollHeight, menuElement.offsetHeight);
337
355
  const height = Math.min(triggerRect.top - 20, maxHeight, 400);
338
356
  menuElement.style.height = height + 'px';
339
- menuElement.style.top = triggerRect.top - 20 - height + 'px';
357
+ menuElement.style.top = triggerRect.top - 20 - height - containerRect.top + 'px';
340
358
  timer = setTimeout(() => {
341
359
  menuElement.style.transform = 'translateY(10px)';
342
360
  menuElement.style.opacity = '1';
@@ -344,30 +362,41 @@ const DropdownMenuPortal = withAnnotation({
344
362
  }
345
363
  else {
346
364
  menuElement.style.height = Math.min(bottomDistance - 20, menuElement.scrollHeight) + 'px';
347
- menuElement.style.top = triggerRect.bottom + 20 + 'px';
365
+ menuElement.style.top = triggerRect.bottom + 20 - containerRect.top + 'px';
348
366
  timer = setTimeout(() => {
349
367
  menuElement.style.transform = 'translateY(-10px)';
350
368
  menuElement.style.opacity = '1';
351
369
  }, delay);
352
370
  }
353
371
  }
372
+ }
373
+ onUpdated(() => {
374
+ update();
354
375
  });
355
376
  onUnmounted(() => {
356
377
  clearTimeout(timer);
357
378
  });
358
379
  function onEnter() {
380
+ if (props.noTrigger) {
381
+ return;
382
+ }
359
383
  dropdownContextService.canHide = false;
360
384
  dropdownContextService.open();
361
385
  }
362
386
  function onLeave() {
387
+ if (props.noTrigger) {
388
+ return;
389
+ }
363
390
  dropdownContextService.canHide = true;
364
391
  dropdownContextService.hide();
365
392
  }
366
- return createPortal(withScopedCSS(scopedId$f, () => {
393
+ return createPortal(withScopedCSS(scopedId$i, () => {
367
394
  return (jsx("div", { onMouseenter: onEnter, onMouseleave: onLeave, ref: menuRef, style: {
368
395
  width: props.width
369
- }, class: "dropdown-menu", children: jsx("div", { class: "dropdown-menu-content", children: props.children }) }));
370
- }), document.body);
396
+ }, class: "dropdown-menu", children: jsx("div", { class: "dropdown-menu-content", style: {
397
+ padding: props.padding
398
+ }, children: props.children }) }));
399
+ }), container);
371
400
  });
372
401
 
373
402
  const Dropdown = withAnnotation({
@@ -395,6 +424,9 @@ const Dropdown = withAnnotation({
395
424
  });
396
425
  const subscription = new Subscription();
397
426
  onMounted(() => {
427
+ if (props.trigger === 'none') {
428
+ return;
429
+ }
398
430
  if (props.trigger === 'click') {
399
431
  subscription.add(fromEvent(triggerRef.current, 'click').subscribe(toggle));
400
432
  return;
@@ -420,14 +452,14 @@ const Dropdown = withAnnotation({
420
452
  return {
421
453
  isShow(b) {
422
454
  if (b) {
423
- dropdownContextService.hide(false);
455
+ dropdownContextService.open();
424
456
  }
425
457
  else {
426
- dropdownContextService.open();
458
+ dropdownContextService.hide(false);
427
459
  }
428
460
  },
429
- $render: withScopedCSS(scopedId$g, () => {
430
- return (jsxs("div", { class: ['dropdown', props.class], style: props.style, ref: dropdownRef, children: [jsxs("div", { class: "dropdown-btn", ref: triggerRef, children: [jsx("div", { class: "dropdown-btn-inner", children: props.children }), jsx("div", { class: "dropdown-btn-arrow" })] }), isShow() && jsx(DropdownMenuPortal, { width: props.width, abreast: props.abreast, triggerRef: triggerRef, children: Array.isArray(props.menu) ?
461
+ $render: withScopedCSS(scopedId$j, () => {
462
+ return (jsxs("div", { class: ['dropdown', props.class], style: props.style, ref: dropdownRef, children: [jsxs("div", { class: "dropdown-btn", ref: triggerRef, children: [jsx("div", { class: "dropdown-btn-inner", children: props.children }), jsx("div", { class: "dropdown-btn-arrow" })] }), isShow() && jsx(DropdownMenuPortal, { toLeft: props.toLeft, padding: props.padding, noTrigger: props.trigger === 'none', width: props.width, abreast: props.abreast, triggerRef: triggerRef, children: Array.isArray(props.menu) ?
431
463
  props.menu.map(menu => {
432
464
  return (jsx("div", { class: "dropdown-menu-item", onClick: () => {
433
465
  var _a;
@@ -442,10 +474,54 @@ const Dropdown = withAnnotation({
442
474
  };
443
475
  });
444
476
 
445
- var scopedId$e = "vf-678daa";
477
+ var scopedId$h = "vf-c32a7b";
478
+
479
+ function Keymap(props) {
480
+ const arr = [];
481
+ const keymap = props.keymap;
482
+ if (keymap.ctrlKey) {
483
+ arr.push(isMac() ? jsx("span", { class: "xnote-icon-command" }) : jsx("span", { children: "Ctrl" }));
484
+ }
485
+ if (keymap.shiftKey) {
486
+ if (arr.length) {
487
+ arr.push('+');
488
+ }
489
+ arr.push(isMac() ? jsx("span", { class: "xnote-icon-shift" }) : jsx("span", { children: "Shift" }));
490
+ }
491
+ if (keymap.altKey) {
492
+ if (arr.length) {
493
+ arr.push('+');
494
+ }
495
+ arr.push(isMac() ? jsx("span", { class: "xnote-icon-opt" }) : jsx("span", { children: "Alt" }));
496
+ }
497
+ if (keymap.key) {
498
+ if (arr.length) {
499
+ arr.push('+');
500
+ }
501
+ if (Array.isArray(keymap.key)) {
502
+ arr.push(jsx("span", { children: keymap.key.join('/') }));
503
+ }
504
+ else {
505
+ arr.push(jsx("span", { children: keymap.key }));
506
+ }
507
+ }
508
+ return withScopedCSS(scopedId$h, () => {
509
+ return (jsx("span", { class: "keymap", children: arr }));
510
+ });
511
+ }
512
+
513
+ var scopedId$g = "vf-acaa5f";
514
+
515
+ function MenuHeading(props) {
516
+ return withScopedCSS(scopedId$g, () => {
517
+ return (jsx("div", { class: "menu-heading", children: props.children }));
518
+ });
519
+ }
520
+
521
+ var scopedId$f = "vf-c3b9dc";
446
522
 
447
523
  function MenuItem(props) {
448
- const dropdownContextService = inject(DropdownContextService, InjectFlags.Optional, null);
524
+ const dropdownContextService = inject(DropdownContextService, null);
449
525
  const isActive = createSignal((dropdownContextService === null || dropdownContextService === void 0 ? void 0 : dropdownContextService.isOpen) || false);
450
526
  if (dropdownContextService) {
451
527
  const subscription = dropdownContextService.onOpenStateChange.subscribe(b => {
@@ -462,8 +538,8 @@ function MenuItem(props) {
462
538
  }
463
539
  (_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props, props.value);
464
540
  }
465
- return withScopedCSS(scopedId$e, () => {
466
- return (jsxs("div", { class: ['menu-item', { disabled: props.disabled, active: props.arrow && isActive() }], onClick: click, children: [jsxs("div", { children: [props.icon && jsx("span", { class: "menu-icon", children: props.icon }), props.children] }), props.arrow ?
541
+ return withScopedCSS(scopedId$f, () => {
542
+ return (jsxs("div", { class: ['menu-item', { disabled: props.disabled, active: props.arrow && isActive() }], onClick: click, children: [jsxs("div", { class: "menu-item-content", children: [jsxs("div", { children: [props.icon && jsx("span", { class: "menu-icon", children: props.icon }), props.children] }), jsx("div", { children: props.desc })] }), props.arrow ?
467
543
  jsx("div", { class: "arrow", children: jsx("span", { class: "xnote-icon-arrow-right" }) }) :
468
544
  jsx("div", { class: [
469
545
  'menu-check',
@@ -472,11 +548,11 @@ function MenuItem(props) {
472
548
  });
473
549
  }
474
550
 
475
- var scopedId$d = "vf-a23c47";
551
+ var scopedId$e = "vf-a23c47";
476
552
 
477
553
  function Popup(props) {
478
554
  const host = inject(VIEW_CONTAINER);
479
- return createPortal(withScopedCSS(scopedId$d, () => {
555
+ return createPortal(withScopedCSS(scopedId$e, () => {
480
556
  return (jsx("div", { class: "popup", style: {
481
557
  left: props.left + 'px',
482
558
  top: props.top + 'px'
@@ -484,15 +560,15 @@ function Popup(props) {
484
560
  }), host);
485
561
  }
486
562
 
487
- var scopedId$c = "vf-216815";
563
+ var scopedId$d = "vf-216815";
488
564
 
489
565
  function ToolbarItem(props) {
490
- return withScopedCSS(scopedId$c, () => {
566
+ return withScopedCSS(scopedId$d, () => {
491
567
  return (jsx("div", { class: "toolbar-item", children: props.children }));
492
568
  });
493
569
  }
494
570
 
495
- var scopedId$b = "vf-2a8a65";
571
+ var scopedId$c = "vf-2a8a65";
496
572
 
497
573
  let RefreshService = class RefreshService {
498
574
  constructor() {
@@ -554,6 +630,308 @@ function useOutput() {
554
630
  return createSignal(inject(OutputInjectionToken));
555
631
  }
556
632
 
633
+ const headingAttr = new Attribute('Heading', {
634
+ render(node, formatValue) {
635
+ node.classes.add('xnote-' + formatValue);
636
+ }
637
+ });
638
+ const headingAttrLoader = {
639
+ match(element) {
640
+ return /H[1-6]/.test(element.tagName) || /(^|\s)xnote-h[1-6](\s|$)/.test(element.className);
641
+ },
642
+ read(element) {
643
+ if (/H[1-6]/.test(element.tagName)) {
644
+ return {
645
+ attribute: headingAttr,
646
+ value: element.tagName.toLowerCase()
647
+ };
648
+ }
649
+ return {
650
+ attribute: headingAttr,
651
+ value: element.className.substring(6)
652
+ };
653
+ }
654
+ };
655
+ function registerHeadingShortcut(textbus) {
656
+ const keyboard = textbus.get(Keyboard);
657
+ const commander = textbus.get(Commander);
658
+ const selection = textbus.get(Selection);
659
+ keyboard.addShortcut({
660
+ keymap: {
661
+ key: '0123456'.split(''),
662
+ ctrlKey: true
663
+ },
664
+ action(key) {
665
+ if (key === '0') {
666
+ commander.unApplyAttribute(headingAttr);
667
+ return;
668
+ }
669
+ commander.applyAttribute(headingAttr, 'h' + key);
670
+ }
671
+ });
672
+ keyboard.addZenCodingInterceptor({
673
+ match(content) {
674
+ return /^#{1,6}$/.test(content);
675
+ },
676
+ try(key) {
677
+ return key === ' ';
678
+ },
679
+ action(content) {
680
+ if (selection.commonAncestorComponent instanceof SourceCodeComponent) {
681
+ return false;
682
+ }
683
+ const commonAncestorSlot = selection.commonAncestorSlot;
684
+ commonAncestorSlot.cut();
685
+ commander.applyAttribute(headingAttr, 'h' + content.length);
686
+ selection.setPosition(commonAncestorSlot, 0);
687
+ return true;
688
+ }
689
+ });
690
+ }
691
+
692
+ function useBlockContent(slot) {
693
+ const textbus = useContext();
694
+ const selection = textbus.get(Selection);
695
+ onBreak(ev => {
696
+ if (typeof slot === 'function' ? slot(ev.target) : ev.target === slot) {
697
+ const p = new ParagraphComponent(textbus);
698
+ ev.target.insert(p);
699
+ selection.setPosition(p.state.slot, 0);
700
+ ev.preventDefault();
701
+ }
702
+ });
703
+ onContentInsert(ev => {
704
+ if ((typeof slot === 'function' ? slot(ev.target) : ev.target === slot) &&
705
+ (typeof ev.data.content === 'string' || ev.data.content.type !== ContentType.BlockComponent)) {
706
+ const p = new ParagraphComponent(textbus);
707
+ const childSlot = p.state.slot;
708
+ childSlot.insert(ev.data.content);
709
+ ev.target.insert(p);
710
+ selection.setPosition(childSlot, childSlot.index);
711
+ ev.preventDefault();
712
+ }
713
+ });
714
+ }
715
+
716
+ function SlotRender(props) {
717
+ const adapter = inject(DomAdapter);
718
+ const instance = getCurrentInstance();
719
+ const slot = props.slot;
720
+ const sub = merge(slot.__changeMarker__.onChange, slot.__changeMarker__.onForceChange).subscribe(() => {
721
+ if (props.slot.__changeMarker__.dirty) {
722
+ instance.markAsDirtied();
723
+ }
724
+ });
725
+ onUnmounted(() => {
726
+ sub.unsubscribe();
727
+ });
728
+ return () => {
729
+ const { slot, tag = 'div', renderEnv = false, elRef, elKey } = props, rest = __rest(props, ["slot", "tag", "renderEnv", "elRef", "elKey"]);
730
+ return adapter.slotRender(slot, children => {
731
+ return createVNode(tag, Object.assign({ ref: elRef, key: elKey }, rest), children);
732
+ }, renderEnv);
733
+ };
734
+ }
735
+
736
+ class BlockquoteComponent extends Component {
737
+ static fromJSON(textbus, json) {
738
+ const slot = textbus.get(Registry).createSlot(json.slot);
739
+ return new BlockquoteComponent(textbus, {
740
+ slot
741
+ });
742
+ }
743
+ constructor(textbus, state = {
744
+ slot: new Slot([
745
+ ContentType.BlockComponent
746
+ ])
747
+ }) {
748
+ super(textbus, state);
749
+ }
750
+ getSlots() {
751
+ return [this.state.slot];
752
+ }
753
+ setup() {
754
+ useBlockContent(this.state.slot);
755
+ }
756
+ }
757
+ BlockquoteComponent.type = ContentType.BlockComponent;
758
+ BlockquoteComponent.componentName = 'BlockquoteComponent';
759
+ BlockquoteComponent.zenCoding = {
760
+ key: ' ',
761
+ match(content, textbus) {
762
+ const selection = textbus.get(Selection);
763
+ if (selection.commonAncestorComponent instanceof ParagraphComponent) {
764
+ return /^>$/.test(content);
765
+ }
766
+ return false;
767
+ },
768
+ createState(_, textbus) {
769
+ const selection = textbus.get(Selection);
770
+ const commonAncestorSlot = selection.commonAncestorSlot;
771
+ const slot = new Slot([
772
+ ContentType.BlockComponent
773
+ ]);
774
+ if (commonAncestorSlot === null || commonAncestorSlot === void 0 ? void 0 : commonAncestorSlot.hasAttribute(textIndentAttr)) {
775
+ slot.setAttribute(textIndentAttr, commonAncestorSlot.getAttribute(textIndentAttr));
776
+ }
777
+ return {
778
+ slot
779
+ };
780
+ }
781
+ };
782
+ function toBlockquote(textbus) {
783
+ const query = textbus.get(Query);
784
+ const commander = textbus.get(Commander);
785
+ const selection = textbus.get(Selection);
786
+ const state = query.queryComponent(BlockquoteComponent);
787
+ if (state.state === QueryStateType.Enabled) {
788
+ const current = state.value;
789
+ const parent = current.parent;
790
+ const index = parent.indexOf(current);
791
+ parent.retain(index);
792
+ commander.removeComponent(current);
793
+ current.slots.at(0).sliceContent().forEach(i => {
794
+ parent.insert(i);
795
+ });
796
+ }
797
+ else {
798
+ const block = new BlockquoteComponent(textbus);
799
+ const slot = block.state.slot;
800
+ if (selection.startSlot === selection.endSlot) {
801
+ const parentComponent = selection.startSlot.parent;
802
+ const parentSlot = parentComponent.parent;
803
+ const position = parentSlot.indexOf(parentComponent);
804
+ slot.insert(parentComponent);
805
+ parentSlot.retain(position);
806
+ parentSlot.insert(block);
807
+ }
808
+ else {
809
+ const commonAncestorSlot = selection.commonAncestorSlot;
810
+ const scope = selection.getCommonAncestorSlotScope();
811
+ commonAncestorSlot.cut(scope.startOffset, scope.endOffset).sliceContent().forEach(i => {
812
+ slot.insert(i);
813
+ });
814
+ commonAncestorSlot.retain(scope.startOffset);
815
+ commonAncestorSlot.insert(block);
816
+ }
817
+ }
818
+ }
819
+ function registerBlockquoteShortcut(textbus) {
820
+ const keyboard = textbus.get(Keyboard);
821
+ keyboard.addShortcut({
822
+ keymap: {
823
+ ctrlKey: true,
824
+ key: '\''
825
+ },
826
+ action() {
827
+ toBlockquote(textbus);
828
+ }
829
+ });
830
+ }
831
+ function BlockquoteView(props) {
832
+ const readonly = useReadonly();
833
+ const output = useOutput();
834
+ return () => {
835
+ const slot = props.component.state.slot;
836
+ return (jsx("blockquote", { class: "xnote-blockquote", ref: props.rootRef, "data-component": props.component.name, children: jsx(SlotRender, { slot: slot, renderEnv: readonly() || output() }) }));
837
+ };
838
+ }
839
+ const blockquoteComponentLoader = {
840
+ match(element, returnableContentTypes) {
841
+ return returnableContentTypes.includes(ContentType.BlockComponent) && element.tagName === 'BLOCKQUOTE';
842
+ },
843
+ read(element, textbus, slotParser) {
844
+ const delta = slotParser(new Slot([
845
+ ContentType.BlockComponent,
846
+ ContentType.InlineComponent,
847
+ ContentType.Text
848
+ ]), element).toDelta();
849
+ const slot = new Slot([
850
+ ContentType.BlockComponent,
851
+ ]);
852
+ deltaToBlock(delta, textbus).forEach(i => {
853
+ slot.insert(i);
854
+ });
855
+ return new BlockquoteComponent(textbus, {
856
+ slot
857
+ });
858
+ },
859
+ };
860
+
861
+ class HighlightBoxComponent extends Component {
862
+ static fromJSON(textbus, json) {
863
+ return new HighlightBoxComponent(textbus, {
864
+ type: json.type,
865
+ slot: textbus.get(Registry).createSlot(json.slot)
866
+ });
867
+ }
868
+ constructor(textbus, state = {
869
+ type: '',
870
+ slot: new Slot([
871
+ ContentType.BlockComponent,
872
+ ])
873
+ }) {
874
+ super(textbus, state);
875
+ }
876
+ getSlots() {
877
+ return [this.state.slot];
878
+ }
879
+ setup() {
880
+ useBlockContent(this.state.slot);
881
+ }
882
+ }
883
+ HighlightBoxComponent.defaultTypes = ['❤️', '💡', '📌', '✅', '❎', '👍', '🎉', '🚫', '❗'];
884
+ HighlightBoxComponent.componentName = 'HighlightBoxComponent';
885
+ HighlightBoxComponent.type = ContentType.BlockComponent;
886
+ function HighlightBoxView(props) {
887
+ const readonly = useReadonly();
888
+ const output = useOutput();
889
+ const emoji = [];
890
+ for (let i = 0x1F600; i <= 0x1F64F; i++) {
891
+ emoji.push(i);
892
+ }
893
+ const dropdownRef = createRef();
894
+ function setType(type) {
895
+ var _a;
896
+ (_a = dropdownRef.current) === null || _a === void 0 ? void 0 : _a.isShow(false);
897
+ props.component.state.type = type;
898
+ }
899
+ return () => {
900
+ const { state, name } = props.component;
901
+ if (readonly() || output()) {
902
+ return (jsxs("div", { "data-component": name, ref: props.rootRef, "data-icon": state.type, class: "xnote-highlight-box", children: [jsx("div", { class: "xnote-highlight-box-left", children: jsx("div", { class: "xnote-highlight-box-icon", children: jsx("button", { type: "button", children: state.type || '❤️' }) }) }), jsx(SlotRender, { slot: state.slot, class: 'xnote-highlight-box-content', renderEnv: readonly() || output() })] }));
903
+ }
904
+ return (jsxs("div", { "data-component": name, ref: props.rootRef, "data-icon": state.type, class: "xnote-highlight-box", children: [jsx("div", { class: "xnote-highlight-box-left", children: jsx(Dropdown, { trigger: "click", ref: dropdownRef, width: "282px", menu: jsxs("div", { class: "xnote-highlight-box-icons", children: [jsx("div", { class: "xnote-highlight-box-heading", children: "\u5E38\u7528" }), HighlightBoxComponent.defaultTypes.map(icon => {
905
+ return (jsx("button", { onClick: () => setType(icon), type: "button", children: icon }));
906
+ }), jsx("div", { class: "xnote-highlight-box-heading", children: "\u66F4\u591A" }), emoji.map(i => {
907
+ const icon = String.fromCodePoint(i);
908
+ return (jsx("button", { onClick: () => setType(icon), type: "button", children: icon }));
909
+ })] }), children: jsx("div", { class: "xnote-highlight-box-icon", children: jsx("button", { type: "button", children: state.type || '❤️' }) }) }) }), jsx(SlotRender, { slot: state.slot, class: 'xnote-highlight-box-content', renderEnv: readonly() || output() })] }));
910
+ };
911
+ }
912
+ const highlightBoxComponentLoader = {
913
+ match(element) {
914
+ return element.tagName === 'DIV' && element.dataset.component === HighlightBoxComponent.componentName;
915
+ },
916
+ read(element, textbus, slotParser) {
917
+ const delta = slotParser(new Slot([
918
+ ContentType.BlockComponent,
919
+ ContentType.InlineComponent,
920
+ ContentType.Text
921
+ ]), element.querySelector('.xnote-highlight-box-content')).toDelta();
922
+ const slot = new Slot([
923
+ ContentType.BlockComponent,
924
+ ]);
925
+ deltaToBlock(delta, textbus).forEach(i => {
926
+ slot.insert(i);
927
+ });
928
+ return new HighlightBoxComponent(textbus, {
929
+ type: element.dataset.icon || '',
930
+ slot
931
+ });
932
+ }
933
+ };
934
+
557
935
  class ParagraphComponent extends Component {
558
936
  static fromJSON(textbus, json) {
559
937
  const slot = textbus.get(Registry).createSlot(json.slot);
@@ -569,16 +947,28 @@ class ParagraphComponent extends Component {
569
947
  }) {
570
948
  super(textbus, state);
571
949
  }
950
+ getSlots() {
951
+ return [this.state.slot];
952
+ }
572
953
  setup() {
573
954
  const injector = useContext();
574
955
  const commander = injector.get(Commander);
575
956
  const selection = injector.get(Selection);
576
957
  onBreak(ev => {
958
+ const isEmpty = this.state.slot.isEmpty;
577
959
  const afterSlot = ev.target.cut(ev.data.index);
960
+ afterSlot.removeAttribute(headingAttr);
578
961
  const nextParagraph = new ParagraphComponent(injector, {
579
962
  slot: afterSlot
580
963
  });
581
- commander.insertAfter(nextParagraph, this);
964
+ if (isEmpty && (this.parentComponent instanceof BlockquoteComponent ||
965
+ this.parentComponent instanceof HighlightBoxComponent)) {
966
+ commander.insertAfter(nextParagraph, this.parentComponent);
967
+ commander.removeComponent(this);
968
+ }
969
+ else {
970
+ commander.insertAfter(nextParagraph, this);
971
+ }
582
972
  selection.setPosition(afterSlot, 0);
583
973
  ev.preventDefault();
584
974
  });
@@ -587,22 +977,30 @@ class ParagraphComponent extends Component {
587
977
  ParagraphComponent.componentName = 'ParagraphComponent';
588
978
  ParagraphComponent.type = ContentType.BlockComponent;
589
979
  function ParagraphView(props) {
590
- const adapter = inject(DomAdapter);
591
980
  const readonly = useReadonly();
592
981
  const output = useOutput();
593
982
  return () => {
594
983
  const slot = props.component.state.slot;
595
- return (jsx("div", { class: "xnote-paragraph", ref: props.rootRef, "data-component": ParagraphComponent.name, children: adapter.slotRender(slot, children => {
596
- return (createVNode('p', null, children));
597
- }, readonly() || output()) }));
984
+ return (jsx("div", { class: "xnote-paragraph", ref: props.rootRef, "data-component": ParagraphComponent.componentName, children: jsx(SlotRender, { tag: "div", slot: slot, renderEnv: readonly() || output() }) }));
598
985
  };
599
986
  }
600
987
  const paragraphComponentLoader = {
601
- match(element) {
602
- return element.dataset.compoment === ParagraphComponent.name || /P|H[1-6]/.test(element.tagName);
988
+ match(element, returnableContentTypes) {
989
+ return returnableContentTypes.includes(ContentType.BlockComponent) && (element.dataset.component === ParagraphComponent.componentName || /^P|H[1-6]$/.test(element.tagName));
603
990
  },
604
991
  read(element, textbus, slotParser) {
605
- const content = /P|H[1-6]/.test(element.tagName) ? element : element.children[0];
992
+ let content;
993
+ if (/^P|H[1-6]$/.test(element.tagName)) {
994
+ content = element;
995
+ }
996
+ else {
997
+ content = element.children[0];
998
+ if (!content) {
999
+ const p = document.createElement('p');
1000
+ p.append(element.innerText);
1001
+ content = p;
1002
+ }
1003
+ }
606
1004
  const delta = slotParser(new Slot([
607
1005
  ContentType.Text,
608
1006
  ContentType.InlineComponent,
@@ -678,6 +1076,15 @@ const languageList = [{
678
1076
  }, {
679
1077
  label: 'Go',
680
1078
  value: 'Go'
1079
+ }, {
1080
+ label: 'Kotlin',
1081
+ value: 'kotlin'
1082
+ }, {
1083
+ label: 'Python',
1084
+ value: 'python'
1085
+ }, {
1086
+ label: 'PHP',
1087
+ value: 'php'
681
1088
  }, {
682
1089
  label: 'JSON',
683
1090
  value: 'JSON',
@@ -702,6 +1109,9 @@ const languageList = [{
702
1109
  }, {
703
1110
  label: 'Shell',
704
1111
  value: 'shell',
1112
+ }, {
1113
+ label: 'Katex',
1114
+ value: 'latex',
705
1115
  }, {
706
1116
  label: 'Yaml',
707
1117
  value: 'yaml',
@@ -720,11 +1130,16 @@ const languageList = [{
720
1130
  }, {
721
1131
  label: 'Dart',
722
1132
  value: 'dart',
1133
+ }, {
1134
+ label: 'Rust',
1135
+ value: 'rust',
723
1136
  }, {
724
1137
  label: '',
725
1138
  value: '',
726
1139
  }];
727
1140
  const sourceCodeThemes = [
1141
+ 'xnote-dark',
1142
+ 'xnote-dark-blue',
728
1143
  'github',
729
1144
  'atom-one-dark',
730
1145
  'foundation',
@@ -780,12 +1195,17 @@ class SourceCodeComponent extends Component {
780
1195
  theme: json.theme
781
1196
  });
782
1197
  }
1198
+ getSlots() {
1199
+ return this.state.slots.map(i => i.slot);
1200
+ }
783
1201
  setup() {
784
1202
  const textbus = useContext();
785
1203
  const selection = useContext(Selection);
786
1204
  onBreak(ev => {
787
1205
  const slots = this.state.slots;
788
- if (ev.target.isEmpty && ev.target === slots[slots.length - 1].slot) {
1206
+ const parentComponent = selection.commonAncestorComponent;
1207
+ const parentSlot = parentComponent.parent;
1208
+ if (parentSlot && ev.target.isEmpty && ev.target === slots[slots.length - 1].slot) {
789
1209
  const prevSlot = slots[slots.length - 2];
790
1210
  if (prevSlot === null || prevSlot === void 0 ? void 0 : prevSlot.slot.isEmpty) {
791
1211
  const slot = new Slot([
@@ -795,8 +1215,6 @@ class SourceCodeComponent extends Component {
795
1215
  const paragraph = new ParagraphComponent(textbus, {
796
1216
  slot
797
1217
  });
798
- const parentComponent = selection.commonAncestorComponent;
799
- const parentSlot = parentComponent.parent;
800
1218
  const index = parentSlot.indexOf(parentComponent);
801
1219
  parentSlot.retain(index + 1);
802
1220
  slots.pop();
@@ -824,6 +1242,12 @@ class SourceCodeComponent extends Component {
824
1242
  });
825
1243
  ev.preventDefault();
826
1244
  });
1245
+ onSlotApplyFormat(ev => {
1246
+ ev.preventDefault();
1247
+ });
1248
+ onSlotSetAttribute(ev => {
1249
+ ev.preventDefault();
1250
+ });
827
1251
  onPaste(ev => {
828
1252
  const codeList = [];
829
1253
  const sourceCode = ev.data.text;
@@ -947,11 +1371,15 @@ class SourceCodeComponent extends Component {
947
1371
  SourceCodeComponent.type = ContentType.BlockComponent;
948
1372
  SourceCodeComponent.componentName = 'SourceCodeComponent';
949
1373
  SourceCodeComponent.zenCoding = {
950
- key: 'Enter',
951
- match(c) {
952
- const matchString = languageList.map(i => i.label || i.value).concat('js', 'ts').join('|').replace(/\+/, '\\+');
953
- const reg = new RegExp(`^\`\`\`(${matchString})$`, 'i');
954
- return reg.test(c);
1374
+ key: ['Enter', ' '],
1375
+ match(c, textbus) {
1376
+ const selection = textbus.get(Selection);
1377
+ if (selection.commonAncestorComponent instanceof ParagraphComponent) {
1378
+ const matchString = languageList.map(i => i.label || i.value).concat('js', 'ts').join('|').replace(/\+/, '\\+');
1379
+ const reg = new RegExp(`^\`\`\`(${matchString})$`, 'i');
1380
+ return reg.test(c);
1381
+ }
1382
+ return false;
955
1383
  },
956
1384
  createState(content) {
957
1385
  const matchString = content.replace(/`/g, '').replace(/\+/, '\\+');
@@ -1018,7 +1446,7 @@ function SourceCodeView(props) {
1018
1446
  }
1019
1447
  const input = inject(Input);
1020
1448
  function updateCaret() {
1021
- input.caret.refresh(false);
1449
+ input.caret.refresh();
1022
1450
  }
1023
1451
  const readonly = useReadonly();
1024
1452
  const output = useOutput();
@@ -1055,28 +1483,6 @@ function SourceCodeView(props) {
1055
1483
  }
1056
1484
  }
1057
1485
  }
1058
- function nodesToVNodes(slot, nodes, index) {
1059
- return nodes.map(i => {
1060
- const location = {
1061
- slot,
1062
- startIndex: index,
1063
- endIndex: index + i.textContent.length
1064
- };
1065
- if (i.nodeType === Node.ELEMENT_NODE) {
1066
- const childNodes = Array.from(i.childNodes);
1067
- const vEle = createVNode('span', {
1068
- class: i.className
1069
- }, nodesToVNodes(slot, childNodes, index));
1070
- index = location.endIndex;
1071
- vEle.location = Object.assign({}, location);
1072
- return vEle;
1073
- }
1074
- index = location.endIndex;
1075
- const textNode = new VTextNode(i.textContent);
1076
- textNode.location = location;
1077
- return textNode;
1078
- });
1079
- }
1080
1486
  return (jsxs("div", { ref: props.rootRef, class: {
1081
1487
  'xnote-source-code': true,
1082
1488
  'xnote-source-code-line-number': state.lineNumber,
@@ -1107,7 +1513,7 @@ function SourceCodeView(props) {
1107
1513
  }
1108
1514
  ], children: [jsx("div", { class: "xnote-source-code-line-number-bg", style: {
1109
1515
  width: Math.max(String(slots.length).length, 2.5) + 'em'
1110
- } }), jsx("div", { onScroll: updateCaret, class: {
1516
+ } }), jsx("pre", { onScroll: updateCaret, class: {
1111
1517
  'xnote-source-code-content': true,
1112
1518
  'xnote-source-code-content-highlight': blockHighlight
1113
1519
  }, style: {
@@ -1128,7 +1534,7 @@ function SourceCodeView(props) {
1128
1534
  children.push(br);
1129
1535
  }
1130
1536
  }
1131
- return createVNode('pre', {
1537
+ return createVNode('div', {
1132
1538
  class: 'xnote-source-code-line' + (item.emphasize ? ' xnote-source-code-line-emphasize' : '')
1133
1539
  }, [
1134
1540
  createVNode('span', { class: 'xnote-source-code-line-content' }, children)
@@ -1137,10 +1543,33 @@ function SourceCodeView(props) {
1137
1543
  }) }), jsx("span", { class: "xnote-source-code-lang", children: lang })] })] }));
1138
1544
  };
1139
1545
  }
1546
+ function nodesToVNodes(slot, nodes, index) {
1547
+ return nodes.map(i => {
1548
+ const location = {
1549
+ slot,
1550
+ startIndex: index,
1551
+ endIndex: index + i.textContent.length
1552
+ };
1553
+ if (i.nodeType === Node.ELEMENT_NODE) {
1554
+ const childNodes = Array.from(i.childNodes);
1555
+ const vEle = createVNode('span', {
1556
+ class: i.className
1557
+ }, nodesToVNodes(slot, childNodes, index));
1558
+ index = location.endIndex;
1559
+ vEle.location = Object.assign({}, location);
1560
+ return vEle;
1561
+ }
1562
+ index = location.endIndex;
1563
+ const textNode = new VTextNode(i.textContent);
1564
+ textNode.location = location;
1565
+ return textNode;
1566
+ });
1567
+ }
1140
1568
  const sourceCodeComponentLoader = {
1141
- match(element) {
1142
- return (element.tagName === 'DIV' && element.dataset.component === SourceCodeComponent.componentName) ||
1143
- element.tagName === 'PRE';
1569
+ match(element, returnableContentTypes) {
1570
+ return returnableContentTypes.includes(ContentType.BlockComponent) &&
1571
+ ((element.tagName === 'DIV' && element.dataset.component === SourceCodeComponent.componentName) ||
1572
+ element.tagName === 'PRE');
1144
1573
  },
1145
1574
  read(el, textbus) {
1146
1575
  let slots = [];
@@ -1268,15 +1697,26 @@ function AttrTool(props) {
1268
1697
  textIndent: 0
1269
1698
  });
1270
1699
  function updateCheckStates() {
1271
- var _a, _b;
1272
- (_a = props.queryBefore) === null || _a === void 0 ? void 0 : _a.call(props);
1700
+ if (!props.slot && !selection.isSelected) {
1701
+ return;
1702
+ }
1273
1703
  setCheckStates(draft => {
1274
- const textAlignState = query.queryAttribute(textAlignAttr);
1275
- const textIndentState = query.queryAttribute(textIndentAttr);
1704
+ const range = props.slot ? {
1705
+ startSlot: props.slot,
1706
+ endSlot: props.slot,
1707
+ startOffset: 0,
1708
+ endOffset: props.slot.length
1709
+ } : {
1710
+ startSlot: selection.startSlot,
1711
+ startOffset: selection.startOffset,
1712
+ endSlot: selection.endSlot,
1713
+ endOffset: selection.endOffset
1714
+ };
1715
+ const textAlignState = query.queryAttributeByRange(textAlignAttr, range);
1716
+ const textIndentState = query.queryAttributeByRange(textIndentAttr, range);
1276
1717
  draft.textAlign = textAlignState.state === QueryStateType.Enabled ? textAlignState.value : 'left';
1277
1718
  draft.textIndent = textIndentState.state === QueryStateType.Enabled ? textIndentState.value : 0;
1278
1719
  });
1279
- (_b = props.queryAfter) === null || _b === void 0 ? void 0 : _b.call(props);
1280
1720
  }
1281
1721
  updateCheckStates();
1282
1722
  const subscription = refreshService.onRefresh.subscribe(() => {
@@ -1323,110 +1763,35 @@ function AttrTool(props) {
1323
1763
  break;
1324
1764
  }
1325
1765
  }
1326
- return withScopedCSS(scopedId$b, () => {
1766
+ return withScopedCSS(scopedId$c, () => {
1327
1767
  const states = checkStates();
1328
- return (jsx(Dropdown, { style: props.style, abreast: props.abreast, onCheck: updateAttr, trigger: 'hover', menu: [
1768
+ return (jsx(Dropdown, { width: 'auto', style: props.style, abreast: props.abreast, onCheck: updateAttr, trigger: 'hover', menu: [
1329
1769
  {
1330
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paragraph-left" }), checked: states.textAlign === 'left', children: "\u5DE6\u5BF9\u9F50" }),
1770
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paragraph-left" }), desc: jsx(Keymap, { keymap: { key: 'L', ctrlKey: true } }), checked: states.textAlign === 'left', children: "\u5DE6\u5BF9\u9F50" }),
1331
1771
  value: 't-l'
1332
1772
  }, {
1333
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paragraph-right" }), checked: states.textAlign === 'right', children: "\u53F3\u5BF9\u9F50" }),
1773
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paragraph-right" }), desc: jsx(Keymap, { keymap: { key: 'R', ctrlKey: true } }), checked: states.textAlign === 'right', children: "\u53F3\u5BF9\u9F50" }),
1334
1774
  value: 't-r'
1335
1775
  }, {
1336
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paragraph-center" }), checked: states.textAlign === 'center', children: "\u5C45\u4E2D\u5BF9\u9F50" }),
1776
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paragraph-center" }), desc: jsx(Keymap, { keymap: { key: 'E', ctrlKey: true } }), checked: states.textAlign === 'center', children: "\u5C45\u4E2D\u5BF9\u9F50" }),
1337
1777
  value: 't-c'
1338
1778
  }, {
1339
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paragraph-justify" }), checked: states.textAlign === 'justify', children: "\u5206\u6563\u5BF9\u9F50" }),
1779
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paragraph-justify" }), desc: jsx(Keymap, { keymap: { key: 'J', ctrlKey: true } }), checked: states.textAlign === 'justify', children: "\u5206\u6563\u5BF9\u9F50" }),
1340
1780
  value: 't-j'
1341
1781
  }, {
1342
1782
  label: jsx(Divider, {}),
1343
1783
  value: ''
1344
1784
  }, {
1345
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-indent-increase" }), children: "\u589E\u52A0\u7F29\u8FDB" }),
1785
+ label: jsx(MenuItem, { desc: jsx(Keymap, { keymap: { key: 'Tab' } }), icon: jsx("span", { class: "xnote-icon-indent-increase" }), children: "\u589E\u52A0\u7F29\u8FDB" }),
1346
1786
  value: 'i+'
1347
1787
  }, {
1348
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-indent-decrease" }), children: "\u51CF\u5C11\u7F29\u8FDB" }),
1788
+ label: jsx(MenuItem, { desc: jsx(Keymap, { keymap: { key: 'Tab', shiftKey: true } }), icon: jsx("span", { class: "xnote-icon-indent-decrease" }), children: "\u51CF\u5C11\u7F29\u8FDB" }),
1349
1789
  value: 'i-'
1350
1790
  }
1351
1791
  ], children: props.children || jsx(Button, { arrow: true, highlight: false, children: jsx("span", { class: `xnote-icon-paragraph-${states.textAlign || 'left'} icon` }) }) }));
1352
1792
  });
1353
1793
  }
1354
1794
 
1355
- const headingAttr = new Attribute('Heading', {
1356
- render(node, formatValue) {
1357
- node.classes.add('xnote-' + formatValue);
1358
- }
1359
- });
1360
- const headingAttrLoader = {
1361
- match(element) {
1362
- return /H[1-6]/.test(element.tagName) || /(^|\s)xnote-h[1-6](\s|$)/.test(element.className);
1363
- },
1364
- read(element) {
1365
- if (/H[1-6]/.test(element.tagName)) {
1366
- return {
1367
- attribute: headingAttr,
1368
- value: element.tagName.toLowerCase()
1369
- };
1370
- }
1371
- return {
1372
- attribute: headingAttr,
1373
- value: element.className.substring(6)
1374
- };
1375
- }
1376
- };
1377
- function registerHeadingShortcut(textbus) {
1378
- const keyboard = textbus.get(Keyboard);
1379
- const commander = textbus.get(Commander);
1380
- const selection = textbus.get(Selection);
1381
- keyboard.addShortcut({
1382
- keymap: {
1383
- key: '123456'.split(''),
1384
- ctrlKey: true
1385
- },
1386
- action(key) {
1387
- commander.applyAttribute(headingAttr, 'h' + key);
1388
- }
1389
- });
1390
- keyboard.addZenCodingInterceptor({
1391
- match(content) {
1392
- return /^#{1,6}$/.test(content);
1393
- },
1394
- try(key) {
1395
- return key === ' ';
1396
- },
1397
- action(content) {
1398
- const commonAncestorSlot = selection.commonAncestorSlot;
1399
- commonAncestorSlot.cut();
1400
- commander.applyAttribute(headingAttr, 'h' + content.length);
1401
- return true;
1402
- }
1403
- });
1404
- }
1405
-
1406
- function useBlockContent(slot) {
1407
- const textbus = useContext();
1408
- const selection = textbus.get(Selection);
1409
- onBreak(ev => {
1410
- if (typeof slot === 'function' ? slot(ev.target) : ev.target === slot) {
1411
- const p = new ParagraphComponent(textbus);
1412
- ev.target.insert(p);
1413
- selection.setPosition(p.state.slot, 0);
1414
- ev.preventDefault();
1415
- }
1416
- });
1417
- onContentInsert(ev => {
1418
- if ((typeof slot === 'function' ? slot(ev.target) : ev.target === slot) &&
1419
- (typeof ev.data.content === 'string' || ev.data.content.type !== ContentType.BlockComponent)) {
1420
- const p = new ParagraphComponent(textbus);
1421
- const childSlot = p.state.slot;
1422
- childSlot.insert(ev.data.content);
1423
- ev.target.insert(p);
1424
- selection.setPosition(childSlot, childSlot.index);
1425
- ev.preventDefault();
1426
- }
1427
- });
1428
- }
1429
-
1430
1795
  const defaultRowHeight = 30;
1431
1796
  const defaultColumnWidth = 100;
1432
1797
  class TableComponent extends Component {
@@ -1449,17 +1814,18 @@ class TableComponent extends Component {
1449
1814
  });
1450
1815
  }
1451
1816
  constructor(textbus, state = {
1452
- layoutWidth: Array.from({ length: 3 }).fill(100),
1817
+ layoutWidth: Array.from({ length: 5 }).fill(100),
1453
1818
  rows: Array.from({ length: 3 }).map(() => {
1454
1819
  return {
1455
1820
  height: defaultRowHeight,
1456
- cells: Array.from({ length: 3 }).map(() => {
1821
+ cells: Array.from({ length: 5 }).map(() => {
1822
+ const p = new ParagraphComponent(textbus);
1823
+ const slot = new Slot([ContentType.BlockComponent]);
1824
+ slot.insert(p);
1457
1825
  return {
1458
1826
  rowspan: 1,
1459
1827
  colspan: 1,
1460
- slot: new Slot([
1461
- ContentType.BlockComponent
1462
- ])
1828
+ slot
1463
1829
  };
1464
1830
  })
1465
1831
  };
@@ -1470,7 +1836,11 @@ class TableComponent extends Component {
1470
1836
  this.focus = new Subject();
1471
1837
  this.tableSelection = createSignal(null);
1472
1838
  }
1839
+ getSlots() {
1840
+ return this.state.rows.map(i => i.cells.map(j => j.slot)).flat();
1841
+ }
1473
1842
  setup() {
1843
+ const selection = useContext(Selection);
1474
1844
  onFocusIn(() => {
1475
1845
  this.focus.next(true);
1476
1846
  });
@@ -1480,12 +1850,42 @@ class TableComponent extends Component {
1480
1850
  useBlockContent((slot) => {
1481
1851
  return slot.parent === this;
1482
1852
  });
1483
- onGetRanges(ev => {
1484
- const selectPosition = this.tableSelection();
1853
+ const sub = selection.onChange.subscribe(() => {
1854
+ if (selection.commonAncestorComponent !== this || selection.isCollapsed) {
1855
+ this.tableSelection.set(null);
1856
+ }
1857
+ });
1858
+ onDestroy(() => {
1859
+ sub.unsubscribe();
1860
+ });
1861
+ const findPosition = (slot) => {
1862
+ let cell = slot;
1863
+ while ((cell === null || cell === void 0 ? void 0 : cell.parent) && cell.parent !== this) {
1864
+ cell = cell.parentSlot;
1865
+ }
1866
+ if (cell) {
1867
+ const rows = this.state.rows;
1868
+ for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
1869
+ const row = rows[rowIndex].cells;
1870
+ for (let colIndex = 0; colIndex < row.length; colIndex++) {
1871
+ const item = row[colIndex].slot;
1872
+ if (item === cell) {
1873
+ return {
1874
+ rowIndex,
1875
+ colIndex
1876
+ };
1877
+ }
1878
+ }
1879
+ }
1880
+ }
1881
+ return null;
1882
+ };
1883
+ const select = (ev, selectPosition) => {
1884
+ this.tableSelection.set(selectPosition);
1485
1885
  if (selectPosition) {
1486
1886
  const cells = [];
1487
- this.state.rows.slice(selectPosition.startRow, selectPosition.endRow + 1).forEach(row => {
1488
- cells.push(...row.cells.slice(selectPosition.startColumn, selectPosition.endColumn + 1).map(i => i.slot));
1887
+ this.state.rows.slice(selectPosition.startRow, selectPosition.endRow).forEach(row => {
1888
+ cells.push(...row.cells.slice(selectPosition.startColumn, selectPosition.endColumn).map(i => i.slot));
1489
1889
  });
1490
1890
  ev.useRanges(cells.map(i => {
1491
1891
  return {
@@ -1496,33 +1896,64 @@ class TableComponent extends Component {
1496
1896
  }));
1497
1897
  ev.preventDefault();
1498
1898
  }
1499
- });
1500
- }
1501
- afterContentCheck() {
1502
- const selection = this.selection;
1503
- const rows = this.state.rows;
1504
- rows.forEach(row => {
1505
- row.cells.forEach(cell => {
1506
- const slot = cell.slot;
1507
- if (slot.isEmpty) {
1508
- const childSlot = new Slot([
1509
- ContentType.Text,
1510
- ContentType.InlineComponent
1511
- ]);
1512
- const p = new ParagraphComponent(this.textbus, {
1513
- slot: childSlot
1514
- });
1515
- slot.insert(p);
1516
- if (slot === selection.anchorSlot) {
1517
- selection.setAnchor(childSlot, 0);
1518
- }
1519
- if (slot === selection.focusSlot) {
1520
- selection.setFocus(childSlot, 0);
1899
+ };
1900
+ onGetRanges(ev => {
1901
+ var _a;
1902
+ const startPosition = findPosition(selection.startSlot);
1903
+ const endPosition = findPosition(selection.endSlot);
1904
+ if (startPosition && endPosition) {
1905
+ if (startPosition.rowIndex === endPosition.rowIndex && startPosition.colIndex === endPosition.colIndex) {
1906
+ if (selection.startSlot === selection.endSlot && selection.startOffset === 0 && selection.endOffset === ((_a = selection.startSlot) === null || _a === void 0 ? void 0 : _a.length)) {
1907
+ select(ev, {
1908
+ startColumn: startPosition.colIndex,
1909
+ startRow: startPosition.rowIndex,
1910
+ endColumn: endPosition.colIndex + 1,
1911
+ endRow: endPosition.rowIndex + 1
1912
+ });
1913
+ return;
1521
1914
  }
1915
+ select(ev, null);
1916
+ return;
1522
1917
  }
1523
- });
1918
+ const [startColumn, endColumn] = [startPosition.colIndex, endPosition.colIndex].sort((a, b) => a - b);
1919
+ const [startRow, endRow] = [startPosition.rowIndex, endPosition.rowIndex].sort((a, b) => a - b);
1920
+ select(ev, {
1921
+ startColumn,
1922
+ startRow,
1923
+ endColumn: endColumn + 1,
1924
+ endRow: endRow + 1
1925
+ });
1926
+ }
1927
+ else {
1928
+ select(ev, null);
1929
+ }
1524
1930
  });
1525
1931
  }
1932
+ // afterContentCheck() {
1933
+ // const selection = this.selection
1934
+ // const rows = this.state.rows
1935
+ // rows.forEach(row => {
1936
+ // row.cells.forEach(cell => {
1937
+ // const slot = cell.slot
1938
+ // if (slot.isEmpty) {
1939
+ // const childSlot = new Slot([
1940
+ // ContentType.Text,
1941
+ // ContentType.InlineComponent
1942
+ // ])
1943
+ // const p = new ParagraphComponent(this.textbus, {
1944
+ // slot: childSlot
1945
+ // })
1946
+ // slot.insert(p)
1947
+ // if (slot === selection.anchorSlot) {
1948
+ // selection.setAnchor(childSlot, 0)
1949
+ // }
1950
+ // if (slot === selection.focusSlot) {
1951
+ // selection.setFocus(childSlot, 0)
1952
+ // }
1953
+ // }
1954
+ // })
1955
+ // })
1956
+ // }
1526
1957
  deleteColumn(index) {
1527
1958
  this.state.layoutWidth.splice(index, 1);
1528
1959
  this.state.rows.forEach(row => {
@@ -1645,12 +2076,16 @@ class TodolistComponent extends Component {
1645
2076
  checked: json.checked
1646
2077
  });
1647
2078
  }
2079
+ getSlots() {
2080
+ return [this.state.slot];
2081
+ }
1648
2082
  setup() {
1649
2083
  const textbus = useContext();
1650
2084
  const commander = useContext(Commander);
1651
2085
  const selection = useContext(Selection);
1652
2086
  onBreak(ev => {
1653
2087
  const slot = ev.target.cut(ev.data.index);
2088
+ slot.removeAttribute(headingAttr);
1654
2089
  if (ev.target.isEmpty && slot.isEmpty) {
1655
2090
  const beforeIndex = this.parent.indexOf(this);
1656
2091
  const beforeComponent = this.parent.getContentAtIndex(beforeIndex - 1);
@@ -1698,21 +2133,32 @@ class TodolistComponent extends Component {
1698
2133
  TodolistComponent.type = ContentType.BlockComponent;
1699
2134
  TodolistComponent.componentName = 'TodoListComponent';
1700
2135
  TodolistComponent.zenCoding = {
1701
- match: /^\[(x|\s)?\]$/,
2136
+ match(content, textbus) {
2137
+ const selection = textbus.get(Selection);
2138
+ if (selection.commonAncestorComponent instanceof ParagraphComponent) {
2139
+ return /^\[(x|\s)?\]$/.test(content);
2140
+ }
2141
+ return false;
2142
+ },
1702
2143
  key: ' ',
1703
- createState(content) {
2144
+ createState(content, textbus) {
2145
+ const selection = textbus.get(Selection);
2146
+ const commonAncestorSlot = selection.commonAncestorSlot;
2147
+ const slot = new Slot([
2148
+ ContentType.InlineComponent,
2149
+ ContentType.Text
2150
+ ]);
2151
+ if (commonAncestorSlot === null || commonAncestorSlot === void 0 ? void 0 : commonAncestorSlot.hasAttribute(textIndentAttr)) {
2152
+ slot.setAttribute(textIndentAttr, commonAncestorSlot.getAttribute(textIndentAttr));
2153
+ }
1704
2154
  const isChecked = content.charAt(1) === 'x';
1705
2155
  return {
1706
2156
  checked: isChecked,
1707
- slot: new Slot([
1708
- ContentType.InlineComponent,
1709
- ContentType.Text
1710
- ])
2157
+ slot
1711
2158
  };
1712
2159
  }
1713
2160
  };
1714
2161
  function TodolistView(props) {
1715
- const adapter = inject(DomAdapter);
1716
2162
  const component = props.component;
1717
2163
  const state = component.state;
1718
2164
  function toggle() {
@@ -1741,11 +2187,7 @@ function TodolistView(props) {
1741
2187
  marginLeft: indent * 24 + 'px',
1742
2188
  justifyContent: align[component.state.slot.getAttribute(textAlignAttr)],
1743
2189
  textAlign: component.state.slot.getAttribute(textAlignAttr) === 'justify' ? 'justify' : void 0
1744
- }, children: [jsx("div", { class: "xnote-todolist-icon", onClick: toggle, children: jsx("span", { "data-checked": checked, class: [checked ? 'xnote-icon-checkbox-checked' : 'xnote-icon-checkbox-unchecked'] }) }), adapter.slotRender(slot, children => {
1745
- return createVNode('div', {
1746
- class: 'xnote-todolist-content'
1747
- }, children);
1748
- }, readonly() || output())] }));
2190
+ }, children: [jsx("div", { class: "xnote-todolist-icon", onClick: toggle, children: jsx("span", { "data-checked": checked, class: [checked ? 'xnote-icon-checkbox-checked' : 'xnote-icon-checkbox-unchecked'] }) }), jsx(SlotRender, { slot: slot, tag: 'div', class: 'xnote-todolist-content', renderEnv: readonly() || output() })] }));
1749
2191
  };
1750
2192
  }
1751
2193
  const todolistComponentLoader = {
@@ -1764,68 +2206,40 @@ const todolistComponentLoader = {
1764
2206
  }
1765
2207
  };
1766
2208
 
1767
- class BlockquoteComponent extends Component {
1768
- static fromJSON(textbus, json) {
1769
- const slot = textbus.get(Registry).createSlot(json.slot);
1770
- return new BlockquoteComponent(textbus, {
1771
- slot
1772
- });
1773
- }
1774
- constructor(textbus, state = {
1775
- slot: new Slot([
1776
- ContentType.BlockComponent
1777
- ])
1778
- }) {
1779
- super(textbus, state);
1780
- }
1781
- setup() {
1782
- useBlockContent(this.state.slot);
1783
- }
1784
- }
1785
- BlockquoteComponent.type = ContentType.BlockComponent;
1786
- BlockquoteComponent.componentName = 'BlockquoteComponent';
1787
- BlockquoteComponent.zenCoding = {
1788
- key: ' ',
1789
- match: /^>$/,
1790
- createState() {
1791
- return {
1792
- slot: new Slot([
1793
- ContentType.BlockComponent
1794
- ])
1795
- };
1796
- }
1797
- };
1798
- function BlockquoteView(props) {
1799
- const adapter = inject(DomAdapter);
1800
- const readonly = useReadonly();
1801
- const output = useOutput();
1802
- return () => {
1803
- const slot = props.component.state.slot;
1804
- return (jsx("blockquote", { class: "xnote-blockquote", ref: props.rootRef, "data-component": props.component.name, children: adapter.slotRender(slot, children => {
1805
- return createVNode('div', null, children);
1806
- }, readonly() || output()) }));
1807
- };
2209
+ function toList(textbus, type) {
2210
+ const commander = textbus.get(Commander);
2211
+ commander.transform({
2212
+ targetType: ListComponent.type,
2213
+ slotFactory() {
2214
+ return new Slot([
2215
+ ContentType.InlineComponent,
2216
+ ContentType.Text
2217
+ ]);
2218
+ },
2219
+ stateFactory(slots) {
2220
+ return slots.map((slot, index) => {
2221
+ return new ListComponent(textbus, {
2222
+ type,
2223
+ reorder: index === 0,
2224
+ slot
2225
+ });
2226
+ });
2227
+ }
2228
+ });
2229
+ }
2230
+ function registerListShortcut(textbus) {
2231
+ const keyboard = textbus.get(Keyboard);
2232
+ keyboard.addShortcut({
2233
+ keymap: {
2234
+ key: ['o', 'u'],
2235
+ ctrlKey: true,
2236
+ shiftKey: true
2237
+ },
2238
+ action(key) {
2239
+ toList(textbus, key === 'o' ? 'OrderedList' : 'UnorderedList');
2240
+ }
2241
+ });
1808
2242
  }
1809
- const blockquoteComponentLoader = {
1810
- match(element) {
1811
- return element.tagName === 'BLOCKQUOTE';
1812
- },
1813
- read(element, textbus, slotParser) {
1814
- const delta = slotParser(new Slot([
1815
- ContentType.BlockComponent,
1816
- ]), element).toDelta();
1817
- const slot = new Slot([
1818
- ContentType.BlockComponent,
1819
- ]);
1820
- deltaToBlock(delta, textbus).forEach(i => {
1821
- slot.insert(i);
1822
- });
1823
- return new BlockquoteComponent(textbus, {
1824
- slot
1825
- });
1826
- },
1827
- };
1828
-
1829
2243
  class ListComponent extends Component {
1830
2244
  static fromJSON(textbus, json) {
1831
2245
  return new ListComponent(textbus, {
@@ -1834,6 +2248,9 @@ class ListComponent extends Component {
1834
2248
  slot: textbus.get(Registry).createSlot(json.slot)
1835
2249
  });
1836
2250
  }
2251
+ getSlots() {
2252
+ return [this.state.slot];
2253
+ }
1837
2254
  setup() {
1838
2255
  const textbus = useContext();
1839
2256
  const commander = useContext(Commander);
@@ -1847,8 +2264,7 @@ class ListComponent extends Component {
1847
2264
  const afterContent = parentSlot.sliceContent(index + 1);
1848
2265
  for (const item of afterContent) {
1849
2266
  if (item instanceof ListComponent &&
1850
- item.state.type === 'OrderedList' &&
1851
- item.state.slot.getAttribute(textIndentAttr) === this.state.slot.getAttribute(textIndentAttr)) {
2267
+ item.state.type === 'OrderedList') {
1852
2268
  if (item.state.reorder) {
1853
2269
  break;
1854
2270
  }
@@ -1861,6 +2277,7 @@ class ListComponent extends Component {
1861
2277
  });
1862
2278
  onBreak(ev => {
1863
2279
  const slot = ev.target.cut(ev.data.index);
2280
+ slot.removeAttribute(headingAttr);
1864
2281
  if (ev.target.isEmpty && slot.isEmpty) {
1865
2282
  const beforeIndex = this.parent.indexOf(this);
1866
2283
  const beforeComponent = this.parent.getContentAtIndex(beforeIndex - 1);
@@ -1911,7 +2328,7 @@ class ListComponent extends Component {
1911
2328
  key: 'Tab'
1912
2329
  },
1913
2330
  action: () => {
1914
- updateAfterList(this);
2331
+ Promise.resolve().then(() => updateAfterList(this));
1915
2332
  return false;
1916
2333
  }
1917
2334
  });
@@ -1931,15 +2348,27 @@ ListComponent.componentName = 'ListComponent';
1931
2348
  ListComponent.type = ContentType.BlockComponent;
1932
2349
  ListComponent.zenCoding = {
1933
2350
  key: ' ',
1934
- match: /^([1-9]\.|[+*])$/,
1935
- createState(content) {
2351
+ match(content, textbus) {
2352
+ const selection = textbus.get(Selection);
2353
+ if (selection.commonAncestorComponent instanceof ParagraphComponent) {
2354
+ return /^([1-9]\.|[+*-])$/.test(content);
2355
+ }
2356
+ return false;
2357
+ },
2358
+ createState(content, textbus) {
2359
+ const selection = textbus.get(Selection);
2360
+ const commonAncestorSlot = selection.commonAncestorSlot;
2361
+ const slot = new Slot([
2362
+ ContentType.InlineComponent,
2363
+ ContentType.Text
2364
+ ]);
2365
+ if (commonAncestorSlot === null || commonAncestorSlot === void 0 ? void 0 : commonAncestorSlot.hasAttribute(textIndentAttr)) {
2366
+ slot.setAttribute(textIndentAttr, commonAncestorSlot.getAttribute(textIndentAttr));
2367
+ }
1936
2368
  return {
1937
2369
  type: /[-+*]/.test(content) ? 'UnorderedList' : 'OrderedList',
1938
2370
  reorder: true,
1939
- slot: new Slot([
1940
- ContentType.InlineComponent,
1941
- ContentType.Text
1942
- ])
2371
+ slot
1943
2372
  };
1944
2373
  }
1945
2374
  };
@@ -1961,7 +2390,6 @@ function numberToLetter(num) {
1961
2390
  }).join('');
1962
2391
  }
1963
2392
  function ListComponentView(props) {
1964
- const adapter = inject(DomAdapter);
1965
2393
  const component = props.component;
1966
2394
  function reorder(is) {
1967
2395
  component.state.reorder = is;
@@ -1988,7 +2416,8 @@ function ListComponentView(props) {
1988
2416
  return () => {
1989
2417
  const ListType = component.state.type === 'UnorderedList' ? 'ul' : 'ol';
1990
2418
  const ulIcons = ['•', '◦', '▪'];
1991
- let icon = '';
2419
+ let icon;
2420
+ let listStep = 0;
1992
2421
  const indent = component.state.slot.getAttribute(textIndentAttr) || 0;
1993
2422
  if (ListType === 'ul') {
1994
2423
  icon = ulIcons[indent % 3];
@@ -1996,7 +2425,6 @@ function ListComponentView(props) {
1996
2425
  else {
1997
2426
  const parentSlot = component.parent;
1998
2427
  const index = parentSlot.indexOf(component);
1999
- let listStep = 0;
2000
2428
  if (!component.state.reorder) {
2001
2429
  const beforeContent = parentSlot.sliceContent(0, index);
2002
2430
  while (beforeContent.length) {
@@ -2027,7 +2455,7 @@ function ListComponentView(props) {
2027
2455
  icon = numberToLetter(listStep) + '.';
2028
2456
  }
2029
2457
  }
2030
- return (jsx(ListType, { ref: props.rootRef, "data-component": component.name, class: "xnote-list", style: {
2458
+ return (jsx(ListType, { ref: props.rootRef, "data-component": component.name, "data-reorder": (listStep === 0) + '', class: "xnote-list", style: {
2031
2459
  marginLeft: indent * 24 + 'px'
2032
2460
  }, children: jsxs("li", { style: {
2033
2461
  justifyContent: align[component.state.slot.getAttribute(textAlignAttr)],
@@ -2035,16 +2463,12 @@ function ListComponentView(props) {
2035
2463
  }, children: [jsx("div", { class: "xnote-list-type", children: (component.state.type === 'UnorderedList' || readonly() || output()) ?
2036
2464
  jsx("span", { class: "xnote-order-btn", children: icon })
2037
2465
  :
2038
- jsx(Dropdown, { menu: jsxs(Fragment, { children: [jsx(MenuItem, { onClick: () => reorder(false), children: "\u7EE7\u7EED\u7F16\u53F7" }), jsx(MenuItem, { onClick: () => reorder(true), children: "\u91CD\u65B0\u7F16\u53F7" })] }), children: jsx(Button, { style: { color: 'inherit' }, children: icon }) }) }), adapter.slotRender(component.state.slot, children => {
2039
- return createVNode('div', {
2040
- class: 'xnote-list-content'
2041
- }, children);
2042
- }, readonly() || output())] }) }));
2466
+ jsx(Dropdown, { menu: jsxs(Fragment, { children: [jsx(MenuItem, { onClick: () => reorder(false), children: "\u7EE7\u7EED\u7F16\u53F7" }), jsx(MenuItem, { onClick: () => reorder(true), children: "\u91CD\u65B0\u7F16\u53F7" })] }), children: jsx(Button, { style: { color: 'inherit' }, children: icon }) }) }), jsx(SlotRender, { slot: component.state.slot, class: 'xnote-list-content', renderEnv: readonly() || output() })] }) }));
2043
2467
  };
2044
2468
  }
2045
2469
  const listComponentLoader = {
2046
- match(element) {
2047
- return element.tagName === 'UL' || element.tagName === 'OL';
2470
+ match(element, returnableContentTypes) {
2471
+ return returnableContentTypes.includes(ContentType.BlockComponent) && (element.tagName === 'UL' || element.tagName === 'OL');
2048
2472
  },
2049
2473
  read(element, textbus, slotParser) {
2050
2474
  const type = element.tagName === 'OL' ? 'OrderedList' : 'UnorderedList';
@@ -2055,7 +2479,7 @@ const listComponentLoader = {
2055
2479
  ]), element.querySelector('.xnote-list-content') || document.createElement('div'));
2056
2480
  return new ListComponent(textbus, {
2057
2481
  slot,
2058
- reorder: true,
2482
+ reorder: element.dataset.reorder !== 'false',
2059
2483
  type
2060
2484
  });
2061
2485
  }
@@ -2098,119 +2522,58 @@ function useActiveBlock() {
2098
2522
  sourceCode: false,
2099
2523
  highlightBox: false
2100
2524
  });
2101
- function updateCheckStates() {
2525
+ function updateCheckStates(range) {
2102
2526
  setCheckStates(draft => {
2103
- const heading = query.queryAttribute(headingAttr);
2104
- draft.paragraph = query.queryComponent(ParagraphComponent).state === QueryStateType.Enabled;
2527
+ const heading = query.queryAttributeByRange(headingAttr, range);
2528
+ draft.paragraph = query.queryComponentByRange(ParagraphComponent, range).state === QueryStateType.Enabled;
2105
2529
  draft.h1 = draft.h2 = draft.h3 = draft.h4 = draft.h5 = draft.h6 = false;
2106
2530
  if (heading.state === QueryStateType.Enabled) {
2107
2531
  draft[heading.value] = true;
2108
2532
  draft.paragraph = false;
2109
2533
  }
2110
- const queryList = query.queryComponent(ListComponent);
2534
+ const queryList = query.queryComponentByRange(ListComponent, range);
2111
2535
  draft.unorderedList = queryList.state === QueryStateType.Enabled && queryList.value.state.type === 'UnorderedList';
2112
2536
  draft.orderedList = queryList.state === QueryStateType.Enabled && queryList.value.state.type === 'OrderedList';
2113
- draft.table = query.queryComponent(TableComponent).state === QueryStateType.Enabled;
2114
- draft.todolist = query.queryComponent(TodolistComponent).state === QueryStateType.Enabled;
2115
- draft.blockquote = query.queryComponent(BlockquoteComponent).state === QueryStateType.Enabled;
2116
- draft.sourceCode = query.queryComponent(SourceCodeComponent).state === QueryStateType.Enabled;
2537
+ draft.table = query.queryComponentByRange(TableComponent, range).state === QueryStateType.Enabled;
2538
+ draft.todolist = query.queryComponentByRange(TodolistComponent, range).state === QueryStateType.Enabled;
2539
+ draft.blockquote = query.queryComponentByRange(BlockquoteComponent, range).state === QueryStateType.Enabled;
2540
+ draft.sourceCode = query.queryComponentByRange(SourceCodeComponent, range).state === QueryStateType.Enabled;
2117
2541
  });
2118
2542
  }
2119
- updateCheckStates();
2120
2543
  const subscription = refreshService.onRefresh.subscribe(() => {
2121
- updateCheckStates();
2544
+ if (!selection.isSelected) {
2545
+ return;
2546
+ }
2547
+ updateCheckStates({
2548
+ startOffset: selection.startOffset,
2549
+ startSlot: selection.startSlot,
2550
+ endSlot: selection.endSlot,
2551
+ endOffset: selection.endOffset
2552
+ });
2122
2553
  });
2123
2554
  onUnmounted(() => {
2124
2555
  subscription.unsubscribe();
2125
2556
  });
2126
2557
  return function (slot = null) {
2127
2558
  if (slot) {
2128
- const snapshot = selection.createSnapshot();
2129
- selection.setBaseAndExtent(slot, 0, slot, slot.length);
2130
- updateCheckStates();
2131
- snapshot.restore();
2559
+ updateCheckStates({
2560
+ startOffset: 0,
2561
+ endOffset: slot.length,
2562
+ startSlot: slot,
2563
+ endSlot: slot
2564
+ });
2132
2565
  }
2133
- return checkStates();
2134
- };
2135
- }
2136
-
2137
- class HighlightBoxComponent extends Component {
2138
- static fromJSON(textbus, json) {
2139
- return new HighlightBoxComponent(textbus, {
2140
- type: json.type,
2141
- slot: textbus.get(Registry).createSlot(json.slot)
2142
- });
2143
- }
2144
- constructor(textbus, state = {
2145
- type: '',
2146
- slot: new Slot([
2147
- ContentType.BlockComponent,
2148
- ])
2149
- }) {
2150
- super(textbus, state);
2151
- }
2152
- setup() {
2153
- useBlockContent(this.state.slot);
2154
- }
2155
- }
2156
- HighlightBoxComponent.defaultTypes = ['❤️', '💡', '📌', '✅', '❎', '👍', '🎉', '🚫', '❗'];
2157
- HighlightBoxComponent.componentName = 'HighlightBoxComponent';
2158
- HighlightBoxComponent.type = ContentType.BlockComponent;
2159
- function HighlightBoxView(props) {
2160
- const adapter = inject(DomAdapter);
2161
- const readonly = useReadonly();
2162
- const output = useOutput();
2163
- const emoji = [];
2164
- for (let i = 0x1F600; i <= 0x1F64F; i++) {
2165
- emoji.push(i);
2166
- }
2167
- const dropdownRef = createRef();
2168
- function setType(type) {
2169
- var _a;
2170
- (_a = dropdownRef.current) === null || _a === void 0 ? void 0 : _a.isShow(false);
2171
- props.component.state.type = type;
2172
- }
2173
- return () => {
2174
- const { state, name } = props.component;
2175
- if (readonly() || output()) {
2176
- return (jsxs("div", { "data-component": name, ref: props.rootRef, "data-icon": state.type, class: "xnote-highlight-box", children: [jsx("div", { class: "xnote-highlight-box-left", children: jsx("div", { class: "xnote-highlight-box-icon", children: jsx("button", { type: "button", children: state.type || '❤️' }) }) }), adapter.slotRender(state.slot, children => {
2177
- return createVNode('div', {
2178
- class: 'xnote-highlight-box-content'
2179
- }, children);
2180
- }, readonly() || output())] }));
2566
+ else if (selection.isSelected) {
2567
+ updateCheckStates({
2568
+ startOffset: selection.startOffset,
2569
+ startSlot: selection.startSlot,
2570
+ endSlot: selection.endSlot,
2571
+ endOffset: selection.endOffset
2572
+ });
2181
2573
  }
2182
- return (jsxs("div", { "data-component": name, ref: props.rootRef, "data-icon": state.type, class: "xnote-highlight-box", children: [jsx("div", { class: "xnote-highlight-box-left", children: jsx(Dropdown, { trigger: "click", ref: dropdownRef, width: "260px", menu: jsxs("div", { class: "xnote-highlight-box-icons", children: [HighlightBoxComponent.defaultTypes.map(icon => {
2183
- return (jsx("button", { onClick: () => setType(icon), type: "button", children: icon }));
2184
- }), jsx(Divider, {}), emoji.map(i => {
2185
- const icon = String.fromCodePoint(i);
2186
- return (jsx("button", { onClick: () => setType(icon), type: "button", children: icon }));
2187
- })] }), children: jsx("div", { class: "xnote-highlight-box-icon", children: jsx("button", { type: "button", children: state.type || '❤️' }) }) }) }), adapter.slotRender(state.slot, children => {
2188
- return createVNode('div', {
2189
- class: 'xnote-highlight-box-content'
2190
- }, children);
2191
- }, readonly() || output())] }));
2574
+ return checkStates();
2192
2575
  };
2193
2576
  }
2194
- const highlightBoxComponentLoader = {
2195
- match(element) {
2196
- return element.tagName === 'DIV' && element.dataset.component === HighlightBoxComponent.componentName;
2197
- },
2198
- read(element, textbus, slotParser) {
2199
- const delta = slotParser(new Slot([
2200
- ContentType.BlockComponent,
2201
- ]), element.querySelector('.xnote-highlight-box-content')).toDelta();
2202
- const slot = new Slot([
2203
- ContentType.BlockComponent,
2204
- ]);
2205
- deltaToBlock(delta, textbus).forEach(i => {
2206
- slot.insert(i);
2207
- });
2208
- return new HighlightBoxComponent(textbus, {
2209
- type: element.dataset.icon || '',
2210
- slot
2211
- });
2212
- }
2213
- };
2214
2577
 
2215
2578
  function useBlockTransform() {
2216
2579
  const commander = inject(Commander);
@@ -2278,62 +2641,10 @@ function useBlockTransform() {
2278
2641
  break;
2279
2642
  case 'ol':
2280
2643
  case 'ul':
2281
- {
2282
- commander.transform({
2283
- targetType: ListComponent.type,
2284
- slotFactory() {
2285
- return new Slot([
2286
- ContentType.InlineComponent,
2287
- ContentType.Text
2288
- ]);
2289
- },
2290
- stateFactory(slots) {
2291
- return slots.map((slot, index) => {
2292
- return new ListComponent(textbus, {
2293
- type: value === 'ol' ? 'OrderedList' : 'UnorderedList',
2294
- reorder: index === 0,
2295
- slot
2296
- });
2297
- });
2298
- }
2299
- });
2300
- }
2644
+ toList(textbus, value === 'ol' ? 'OrderedList' : 'UnorderedList');
2301
2645
  break;
2302
2646
  case 'blockquote':
2303
- {
2304
- const state = query.queryComponent(BlockquoteComponent);
2305
- if (state.state === QueryStateType.Enabled) {
2306
- const current = state.value;
2307
- const parent = current.parent;
2308
- const index = parent.indexOf(current);
2309
- parent.retain(index);
2310
- commander.removeComponent(current);
2311
- current.__slots__.get(0).sliceContent().forEach(i => {
2312
- parent.insert(i);
2313
- });
2314
- }
2315
- else {
2316
- const block = new BlockquoteComponent(textbus);
2317
- const slot = block.state.slot;
2318
- if (selection.startSlot === selection.endSlot) {
2319
- const parentComponent = selection.startSlot.parent;
2320
- const parentSlot = parentComponent.parent;
2321
- const position = parentSlot.indexOf(parentComponent);
2322
- slot.insert(parentComponent);
2323
- parentSlot.retain(position);
2324
- parentSlot.insert(block);
2325
- }
2326
- else {
2327
- const commonAncestorSlot = selection.commonAncestorSlot;
2328
- const scope = selection.getCommonAncestorSlotScope();
2329
- commonAncestorSlot.cut(scope.startOffset, scope.endOffset).sliceContent().forEach(i => {
2330
- slot.insert(i);
2331
- });
2332
- commonAncestorSlot.retain(scope.startOffset);
2333
- commonAncestorSlot.insert(block);
2334
- }
2335
- }
2336
- }
2647
+ toBlockquote(textbus);
2337
2648
  break;
2338
2649
  case 'sourceCode':
2339
2650
  {
@@ -2370,6 +2681,8 @@ function useBlockTransform() {
2370
2681
  lineNumber: true,
2371
2682
  autoBreak: true,
2372
2683
  slots: slots.map(slot => {
2684
+ slot.cleanFormats();
2685
+ slot.cleanAttributes();
2373
2686
  return {
2374
2687
  slot,
2375
2688
  emphasize: false
@@ -2390,7 +2703,7 @@ function useBlockTransform() {
2390
2703
  const index = parent.indexOf(current);
2391
2704
  parent.retain(index);
2392
2705
  commander.removeComponent(current);
2393
- current.__slots__.get(0).sliceContent().forEach(i => {
2706
+ current.slots.at(0).sliceContent().forEach(i => {
2394
2707
  parent.insert(i);
2395
2708
  });
2396
2709
  }
@@ -2424,7 +2737,7 @@ function useBlockTransform() {
2424
2737
  function BlockTool() {
2425
2738
  const checkStates = useActiveBlock();
2426
2739
  const transform = useBlockTransform();
2427
- return withScopedCSS(scopedId$b, () => {
2740
+ return withScopedCSS(scopedId$c, () => {
2428
2741
  const states = checkStates();
2429
2742
  const types = [
2430
2743
  [states.paragraph, 'xnote-icon-pilcrow'],
@@ -2439,7 +2752,7 @@ function BlockTool() {
2439
2752
  [states.todolist, 'xnote-icon-checkbox-checked'],
2440
2753
  [states.blockquote, 'xnote-icon-quotes-right'],
2441
2754
  [states.sourceCode, 'xnote-icon-source-code'],
2442
- [states.highlightBox, 'xnote-icon-paint-bucket'],
2755
+ [states.highlightBox, 'xnote-icon-highlight-box'],
2443
2756
  ];
2444
2757
  let currentType = 'xnote-icon-pilcrow';
2445
2758
  for (const t of types) {
@@ -2448,27 +2761,48 @@ function BlockTool() {
2448
2761
  break;
2449
2762
  }
2450
2763
  }
2451
- return (jsx(Dropdown, { onCheck: transform, trigger: 'hover', menu: [
2764
+ return (jsx(Dropdown, { width: 'auto', onCheck: transform, trigger: 'hover', menu: [
2452
2765
  {
2453
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-pilcrow" }), checked: states.paragraph, children: "\u6B63\u6587" }),
2766
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-pilcrow" }), desc: jsx(Keymap, { keymap: {
2767
+ ctrlKey: true,
2768
+ key: '0'
2769
+ } }), checked: states.paragraph, children: "\u6B63\u6587" }),
2454
2770
  value: 'paragraph'
2455
2771
  }, {
2456
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h1" }), checked: states.h1, children: "\u4E00\u7EA7\u6807\u9898" }),
2772
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h1" }), desc: jsx(Keymap, { keymap: {
2773
+ ctrlKey: true,
2774
+ key: '1'
2775
+ } }), checked: states.h1, children: "\u4E00\u7EA7\u6807\u9898" }),
2457
2776
  value: 'h1'
2458
2777
  }, {
2459
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h2" }), checked: states.h2, children: "\u4E8C\u7EA7\u6807\u9898" }),
2778
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h2" }), desc: jsx(Keymap, { keymap: {
2779
+ ctrlKey: true,
2780
+ key: '2'
2781
+ } }), checked: states.h2, children: "\u4E8C\u7EA7\u6807\u9898" }),
2460
2782
  value: 'h2'
2461
2783
  }, {
2462
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h3" }), checked: states.h3, children: "\u4E09\u7EA7\u6807\u9898" }),
2784
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h3" }), desc: jsx(Keymap, { keymap: {
2785
+ ctrlKey: true,
2786
+ key: '3'
2787
+ } }), checked: states.h3, children: "\u4E09\u7EA7\u6807\u9898" }),
2463
2788
  value: 'h3'
2464
2789
  }, {
2465
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h4" }), checked: states.h4, children: "\u56DB\u7EA7\u6807\u9898" }),
2790
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h4" }), desc: jsx(Keymap, { keymap: {
2791
+ ctrlKey: true,
2792
+ key: '4'
2793
+ } }), checked: states.h4, children: "\u56DB\u7EA7\u6807\u9898" }),
2466
2794
  value: 'h4'
2467
2795
  }, {
2468
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h5" }), checked: states.h5, children: "\u4E94\u7EA7\u6807\u9898" }),
2796
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h5" }), desc: jsx(Keymap, { keymap: {
2797
+ ctrlKey: true,
2798
+ key: '5'
2799
+ } }), checked: states.h5, children: "\u4E94\u7EA7\u6807\u9898" }),
2469
2800
  value: 'h5'
2470
2801
  }, {
2471
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h6" }), checked: states.h6, children: "\u516D\u7EA7\u6807\u9898" }),
2802
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-heading-h6" }), desc: jsx(Keymap, { keymap: {
2803
+ ctrlKey: true,
2804
+ key: '6'
2805
+ } }), checked: states.h6, children: "\u516D\u7EA7\u6807\u9898" }),
2472
2806
  value: 'h6'
2473
2807
  }, {
2474
2808
  label: jsx(Divider, {}),
@@ -2477,19 +2811,19 @@ function BlockTool() {
2477
2811
  label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-checkbox-checked" }), checked: states.todolist, children: "\u5F85\u529E\u4E8B\u9879" }),
2478
2812
  value: 'todolist'
2479
2813
  }, {
2480
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-list-numbered" }), checked: states.orderedList, children: "\u6709\u5E8F\u5217\u8868" }),
2814
+ label: jsx(MenuItem, { desc: jsx(Keymap, { keymap: { key: 'O', shiftKey: true, ctrlKey: true } }), icon: jsx("span", { class: "xnote-icon-list-numbered" }), checked: states.orderedList, children: "\u6709\u5E8F\u5217\u8868" }),
2481
2815
  value: 'ol'
2482
2816
  }, {
2483
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-list" }), checked: states.unorderedList, children: "\u65E0\u5E8F\u5217\u8868" }),
2817
+ label: jsx(MenuItem, { desc: jsx(Keymap, { keymap: { key: 'U', shiftKey: true, ctrlKey: true } }), icon: jsx("span", { class: "xnote-icon-list" }), checked: states.unorderedList, children: "\u65E0\u5E8F\u5217\u8868" }),
2484
2818
  value: 'ul'
2485
2819
  }, {
2486
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-quotes-right" }), checked: states.blockquote, children: "\u5F15\u7528" }),
2820
+ label: jsx(MenuItem, { desc: jsx(Keymap, { keymap: { key: '\'', ctrlKey: true } }), icon: jsx("span", { class: "xnote-icon-quotes-right" }), checked: states.blockquote, children: "\u5F15\u7528" }),
2487
2821
  value: 'blockquote'
2488
2822
  }, {
2489
2823
  label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-source-code" }), checked: states.sourceCode, children: "\u4EE3\u7801\u5757" }),
2490
2824
  value: 'sourceCode'
2491
2825
  }, {
2492
- label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paint-bucket" }), checked: states.highlightBox, children: "\u9AD8\u4EAE\u5757" }),
2826
+ label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-hightlight-box" }), checked: states.highlightBox, children: "\u9AD8\u4EAE\u5757" }),
2493
2827
  value: 'highlightBox'
2494
2828
  }
2495
2829
  ], children: jsx(Button, { arrow: true, highlight: false, children: jsx("span", { class: currentType }) }) }));
@@ -2855,12 +3189,13 @@ function CodeTool() {
2855
3189
  };
2856
3190
  }
2857
3191
 
2858
- var scopedId$a = "vf-1fbbdf";
3192
+ var scopedId$b = "vf-accb31";
2859
3193
 
2860
3194
  function ColorTool(props) {
2861
3195
  const query = inject(Query);
2862
3196
  const refreshService = inject(RefreshService);
2863
3197
  const commander = inject(Commander);
3198
+ const selection = inject(Selection);
2864
3199
  const textColor = createSignal('');
2865
3200
  const backgroundColor = createSignal('');
2866
3201
  const [viewModel] = useProduce({
@@ -2868,13 +3203,24 @@ function ColorTool(props) {
2868
3203
  disabled: false,
2869
3204
  });
2870
3205
  function updateCheckState() {
2871
- var _a, _b;
2872
- (_a = props.queryBefore) === null || _a === void 0 ? void 0 : _a.call(props);
2873
- const textState = query.queryFormat(colorFormatter);
2874
- const backgroundState = query.queryFormat(backgroundColorFormatter);
3206
+ if (!props.slot && !selection.isSelected) {
3207
+ return;
3208
+ }
3209
+ const range = props.slot ? {
3210
+ startSlot: props.slot,
3211
+ endSlot: props.slot,
3212
+ startOffset: 0,
3213
+ endOffset: props.slot.length
3214
+ } : {
3215
+ startSlot: selection.startSlot,
3216
+ startOffset: selection.startOffset,
3217
+ endSlot: selection.endSlot,
3218
+ endOffset: selection.endOffset
3219
+ };
3220
+ const textState = query.queryFormatByRange(colorFormatter, range);
3221
+ const backgroundState = query.queryFormatByRange(backgroundColorFormatter, range);
2875
3222
  textColor.set(textState.state === QueryStateType.Enabled ? textState.value : '');
2876
3223
  backgroundColor.set(backgroundState.state === QueryStateType.Enabled ? backgroundState.value : '');
2877
- (_b = props.queryAfter) === null || _b === void 0 ? void 0 : _b.call(props);
2878
3224
  }
2879
3225
  const sub = refreshService.onRefresh.subscribe(() => {
2880
3226
  updateCheckState();
@@ -2884,6 +3230,7 @@ function ColorTool(props) {
2884
3230
  sub.unsubscribe();
2885
3231
  });
2886
3232
  const textColors = [
3233
+ '#000',
2887
3234
  '#aaa',
2888
3235
  '#ff2e2e',
2889
3236
  '#ff8d45',
@@ -2893,6 +3240,7 @@ function ColorTool(props) {
2893
3240
  '#1296db',
2894
3241
  '#617fff',
2895
3242
  '#c459ff',
3243
+ '#fff',
2896
3244
  ];
2897
3245
  const backgroundColors = [
2898
3246
  '#aaa',
@@ -2904,15 +3252,16 @@ function ColorTool(props) {
2904
3252
  '#90a0e5',
2905
3253
  '#c596e0',
2906
3254
  ];
2907
- return withScopedCSS(scopedId$a, () => {
3255
+ return withScopedCSS(scopedId$b, () => {
2908
3256
  const vm = viewModel();
2909
- return (jsx(Dropdown, { style: props.style, abreast: props.abreast, trigger: 'hover', menu: jsxs("div", { children: [jsx("div", { class: "color-type", children: "\u6587\u5B57\u989C\u8272" }), jsxs("div", { class: "text-colors", children: [jsx("div", { class: {
3257
+ return (jsx(Dropdown, { style: props.style, width: '180px', abreast: props.abreast, trigger: 'hover', menu: jsxs("div", { children: [jsx("div", { class: "color-type", children: "\u6587\u5B57\u989C\u8272" }), jsxs("div", { class: "text-colors", children: [jsx("div", { class: {
3258
+ 'no-background': true,
2910
3259
  active: textColor() === ''
2911
3260
  }, onClick: () => {
2912
3261
  var _a;
2913
3262
  (_a = props.applyBefore) === null || _a === void 0 ? void 0 : _a.call(props);
2914
3263
  commander.unApplyFormat(colorFormatter);
2915
- }, children: "A" }), textColors.map(c => {
3264
+ } }), textColors.map(c => {
2916
3265
  return jsx("div", { class: {
2917
3266
  active: textColor() === c
2918
3267
  }, onClick: () => {
@@ -2972,6 +3321,9 @@ const isSupportFont = (function () {
2972
3321
  function FontFamilyTool() {
2973
3322
  const currentFontFamily = createSignal('');
2974
3323
  const fontFamilyOptions = [{
3324
+ label: '默认',
3325
+ value: ''
3326
+ }, {
2975
3327
  label: '宋体',
2976
3328
  value: 'SimSun, STSong'
2977
3329
  }, {
@@ -3013,7 +3365,12 @@ function FontFamilyTool() {
3013
3365
  }];
3014
3366
  const commander = inject(Commander);
3015
3367
  function check(v) {
3016
- commander.applyFormat(fontFamilyFormatter, v);
3368
+ if (v) {
3369
+ commander.applyFormat(fontFamilyFormatter, v);
3370
+ }
3371
+ else {
3372
+ commander.unApplyFormat(fontFamilyFormatter);
3373
+ }
3017
3374
  }
3018
3375
  const refreshService = inject(RefreshService);
3019
3376
  const query = inject(Query);
@@ -3022,7 +3379,7 @@ function FontFamilyTool() {
3022
3379
  const result = query.queryFormat(fontFamilyFormatter);
3023
3380
  const isHighlight = result.state === QueryStateType.Enabled;
3024
3381
  highlight.set(isHighlight);
3025
- currentFontFamily.set(isHighlight ? result.value : '默认');
3382
+ currentFontFamily.set(isHighlight ? result.value : '');
3026
3383
  });
3027
3384
  onUnmounted(() => {
3028
3385
  subscription.unsubscribe();
@@ -3030,7 +3387,7 @@ function FontFamilyTool() {
3030
3387
  return () => {
3031
3388
  var _a;
3032
3389
  return (jsx(Dropdown, { onCheck: check, menu: fontFamilyOptions.map(i => {
3033
- const disabled = !i.value.split(',').map(i => isSupportFont(i.trim())).some(v => v);
3390
+ const disabled = i.value ? !i.value.split(',').map(i => isSupportFont(i.trim())).some(v => v) : false;
3034
3391
  return {
3035
3392
  label: jsx(MenuItem, { disabled: disabled, checked: currentFontFamily() === i.value, children: i.label }),
3036
3393
  disabled,
@@ -3062,7 +3419,12 @@ function FontSizeTool() {
3062
3419
  ];
3063
3420
  const commander = inject(Commander);
3064
3421
  function check(v) {
3065
- commander.applyFormat(fontSizeFormatter, v);
3422
+ if (v) {
3423
+ commander.applyFormat(fontSizeFormatter, v);
3424
+ }
3425
+ else {
3426
+ commander.unApplyFormat(fontSizeFormatter);
3427
+ }
3066
3428
  }
3067
3429
  const refreshService = inject(RefreshService);
3068
3430
  const query = inject(Query);
@@ -3112,12 +3474,30 @@ function ItalicTool() {
3112
3474
  };
3113
3475
  }
3114
3476
 
3115
- var scopedId$9 = "vf-269a0b";
3477
+ var scopedId$a = "vf-e74208";
3478
+
3479
+ let EditorService = class EditorService {
3480
+ constructor() {
3481
+ this.hideInlineToolbar = false;
3482
+ this.canShowLeftToolbar = true;
3483
+ this.onLeftToolbarCanVisibleChange = new Subject();
3484
+ }
3485
+ changeLeftToolbarVisible(b) {
3486
+ this.canShowLeftToolbar = b;
3487
+ this.onLeftToolbarCanVisibleChange.next();
3488
+ }
3489
+ };
3490
+ EditorService = __decorate([
3491
+ Injectable({
3492
+ provideIn: 'root'
3493
+ })
3494
+ ], EditorService);
3116
3495
 
3117
3496
  function LinkTool(props) {
3118
3497
  const selectionBridge = inject(SelectionBridge);
3119
3498
  const selection = inject(Selection);
3120
3499
  const commander = inject(Commander);
3500
+ const editorService = inject(EditorService);
3121
3501
  const container = inject(VIEW_CONTAINER);
3122
3502
  const isShow = createSignal(false);
3123
3503
  const inputRef = createRef();
@@ -3138,22 +3518,24 @@ function LinkTool(props) {
3138
3518
  isClickFromSelf = false;
3139
3519
  return;
3140
3520
  }
3521
+ editorService.hideInlineToolbar = false;
3141
3522
  isShow.set(false);
3142
3523
  });
3143
3524
  onUnmounted(() => {
3144
3525
  sub.unsubscribe();
3145
3526
  });
3146
- return withScopedCSS(scopedId$9, () => {
3527
+ return withScopedCSS(scopedId$a, () => {
3147
3528
  const containerRect = container.getBoundingClientRect();
3148
3529
  const rect = isShow() ? selectionBridge.getRect({
3149
3530
  slot: selection.focusSlot,
3150
3531
  offset: selection.focusOffset
3151
3532
  }) : {};
3152
3533
  return (jsxs("span", { children: [jsx(Button, { onClick: () => {
3534
+ var _a;
3153
3535
  isShow.set(true);
3154
3536
  isClickFromSelf = true;
3155
- setTimeout(() => { var _a; return (_a = props.hideToolbar) === null || _a === void 0 ? void 0 : _a.call(props); }, 10);
3156
- }, arrow: true, children: jsx("span", { class: "xnote-icon-link" }) }), isShow() &&
3537
+ (_a = props.hideToolbar) === null || _a === void 0 ? void 0 : _a.call(props);
3538
+ }, children: jsx("span", { class: "xnote-icon-link" }) }), isShow() &&
3157
3539
  jsx(Popup, { left: rect.left - containerRect.left, top: rect.top + rect.height - containerRect.top, children: jsxs("form", { onSubmit: setLink, onClick: () => {
3158
3540
  isClickFromSelf = true;
3159
3541
  }, class: "input-group", children: [jsx("input", { ref: inputRef, placeholder: "\u8BF7\u8F93\u5165\u94FE\u63A5\u5730\u5740", type: "text" }), jsx(Button, { type: "submit", children: "\u786E\u5B9A" })] }) })] }));
@@ -3212,7 +3594,7 @@ function UnderlineTool() {
3212
3594
  };
3213
3595
  }
3214
3596
 
3215
- var scopedId$8 = "vf-cf8e1c";
3597
+ var scopedId$9 = "vf-cf8e1c";
3216
3598
 
3217
3599
  class FileUploader {
3218
3600
  }
@@ -3221,6 +3603,9 @@ class ImageComponent extends Component {
3221
3603
  static fromJSON(textbus, json) {
3222
3604
  return new ImageComponent(textbus, Object.assign({}, json));
3223
3605
  }
3606
+ getSlots() {
3607
+ return [];
3608
+ }
3224
3609
  }
3225
3610
  ImageComponent.type = ContentType.InlineComponent;
3226
3611
  ImageComponent.componentName = 'ImageComponent';
@@ -3247,9 +3632,11 @@ const imageComponentLoader = {
3247
3632
  return element.tagName === 'IMG' || element.dataset.component === ImageComponent.componentName;
3248
3633
  },
3249
3634
  read(element, textbus) {
3250
- var _a;
3635
+ const img = element instanceof HTMLImageElement ? element : (element.querySelector('img') || document.createElement('img'));
3251
3636
  return new ImageComponent(textbus, {
3252
- src: element instanceof HTMLImageElement ? element.src : ((_a = element.querySelector('img')) === null || _a === void 0 ? void 0 : _a.src) || ''
3637
+ src: img.src,
3638
+ width: img.style.width || 'auto',
3639
+ height: img.style.height || 'auto'
3253
3640
  });
3254
3641
  }
3255
3642
  };
@@ -3258,8 +3645,8 @@ class VideoComponent extends Component {
3258
3645
  static fromJSON(textbus, json) {
3259
3646
  return new VideoComponent(textbus, Object.assign({}, json));
3260
3647
  }
3261
- setup() {
3262
- //
3648
+ getSlots() {
3649
+ return [];
3263
3650
  }
3264
3651
  }
3265
3652
  VideoComponent.type = ContentType.InlineComponent;
@@ -3271,7 +3658,7 @@ function VideoView(props) {
3271
3658
  const output = useOutput();
3272
3659
  return () => {
3273
3660
  if (readonly() || output()) {
3274
- return (jsx("div", { class: "xnote-video", "data-component": name, children: jsx("video", { ref: videoRef, src: state.src, style: {
3661
+ return (jsx("div", { class: "xnote-video", ref: props.rootRef, "data-component": name, children: jsx("video", { ref: videoRef, src: state.src, style: {
3275
3662
  width: state.width,
3276
3663
  height: state.height
3277
3664
  } }) }));
@@ -3284,12 +3671,169 @@ function VideoView(props) {
3284
3671
  }
3285
3672
  const videoComponentLoader = {
3286
3673
  match(element) {
3287
- return element.tagName === 'IMG' || element.dataset.component === VideoComponent.componentName;
3674
+ return element.tagName === 'VIDEO' || element.dataset.component === VideoComponent.componentName;
3288
3675
  },
3289
3676
  read(element, textbus) {
3290
- var _a;
3677
+ const video = element instanceof HTMLVideoElement ? element : (element.querySelector('video') || document.createElement('video'));
3291
3678
  return new VideoComponent(textbus, {
3292
- src: element instanceof HTMLImageElement ? element.src : ((_a = element.querySelector('video')) === null || _a === void 0 ? void 0 : _a.src) || ''
3679
+ src: video.src,
3680
+ width: video.style.width || 'auto',
3681
+ height: video.style.height || 'auto'
3682
+ });
3683
+ }
3684
+ };
3685
+
3686
+ class KatexEditor extends Textbus {
3687
+ constructor() {
3688
+ const adapter = new ViewflyAdapter({
3689
+ [SourceCodeComponent.componentName]: SourceCodeView
3690
+ }, (host, root, injector) => {
3691
+ const appInjector = new ReflectiveInjector(injector, [{
3692
+ provide: OutputInjectionToken,
3693
+ useValue: true
3694
+ }]);
3695
+ const app = createApp(root, {
3696
+ context: appInjector
3697
+ }).mount(host);
3698
+ return () => {
3699
+ app.destroy();
3700
+ };
3701
+ });
3702
+ const browserModule = new BrowserModule({
3703
+ adapter,
3704
+ renderTo: () => {
3705
+ return this.host;
3706
+ }
3707
+ });
3708
+ super({
3709
+ components: [
3710
+ SourceCodeComponent
3711
+ ],
3712
+ imports: [browserModule]
3713
+ });
3714
+ this.onValueChange = new Subject();
3715
+ }
3716
+ mount(host, code) {
3717
+ this.host = host;
3718
+ const model = new SourceCodeComponent(this, {
3719
+ lineNumber: true,
3720
+ autoBreak: true,
3721
+ lang: 'latex',
3722
+ theme: 'github',
3723
+ slots: code.split('\n').map(i => {
3724
+ const slot = new Slot([ContentType.Text]);
3725
+ slot.insert(i);
3726
+ return {
3727
+ slot,
3728
+ emphasize: false
3729
+ };
3730
+ })
3731
+ });
3732
+ this.onChange.subscribe(() => {
3733
+ const str = model.state.slots.map(i => {
3734
+ if (i.slot.isEmpty) {
3735
+ return '';
3736
+ }
3737
+ return i.slot.toString();
3738
+ }).join('\n');
3739
+ this.onValueChange.next(str);
3740
+ });
3741
+ return this.render(model);
3742
+ }
3743
+ }
3744
+
3745
+ class KatexComponent extends Component {
3746
+ static fromJSON(textbus, state) {
3747
+ return new KatexComponent(textbus, state);
3748
+ }
3749
+ constructor(textbus, state = {
3750
+ text: '% \\f is defined as #1f(#2) using the macro\n' +
3751
+ '\\f\\relax{x} = \\int_{-\\infty}^\\infty\n' +
3752
+ '\\f\\hat\\xi\\,e^{2 \\pi i \\xi x}\n' +
3753
+ '\\,d\\xi'
3754
+ }) {
3755
+ super(textbus, state);
3756
+ }
3757
+ getSlots() {
3758
+ return [];
3759
+ }
3760
+ }
3761
+ KatexComponent.componentName = 'KatexComponent';
3762
+ KatexComponent.type = ContentType.InlineComponent;
3763
+ function domToVDom(el) {
3764
+ const attrs = {};
3765
+ el.getAttributeNames().forEach(key => {
3766
+ attrs[key] = el.getAttribute(key);
3767
+ });
3768
+ attrs.children = Array.from(el.childNodes).map(child => {
3769
+ if (child.nodeType === Node.ELEMENT_NODE) {
3770
+ return domToVDom(child);
3771
+ }
3772
+ return child.textContent || '';
3773
+ });
3774
+ return jsx$1(el.tagName.toLowerCase(), attrs);
3775
+ }
3776
+ function KatexComponentView(props) {
3777
+ function toDOM(value) {
3778
+ let htmlString;
3779
+ try {
3780
+ htmlString = Katex.renderToString(value, {
3781
+ displayMode: true,
3782
+ leqno: false,
3783
+ fleqn: false,
3784
+ throwOnError: true,
3785
+ errorColor: '#cc0000',
3786
+ strict: 'warn',
3787
+ output: 'html',
3788
+ trust: false,
3789
+ macros: { '\\f': '#1f(#2)' }
3790
+ });
3791
+ }
3792
+ catch (e) {
3793
+ htmlString = '<span style="color: red">公式错误</span>';
3794
+ }
3795
+ return new DOMParser().parseFromString(htmlString, 'text/html').body.children[0];
3796
+ }
3797
+ const selection = inject(Textbus);
3798
+ const editorRef = createDynamicRef(node => {
3799
+ const editor = new KatexEditor();
3800
+ editor.mount(node, props.component.state.text).then(() => {
3801
+ editor.focus();
3802
+ });
3803
+ selection.blur();
3804
+ const subscription = editor.onValueChange.subscribe((value) => {
3805
+ props.component.state.text = value;
3806
+ }).add(fromEvent(node, 'mousedown').subscribe(ev => ev.stopPropagation()), fromEvent(document, 'mousedown').subscribe(() => {
3807
+ var _a;
3808
+ (_a = dropdownRef.current) === null || _a === void 0 ? void 0 : _a.isShow(false);
3809
+ }));
3810
+ return () => {
3811
+ subscription.unsubscribe();
3812
+ editor.destroy();
3813
+ };
3814
+ });
3815
+ const dropdownRef = createRef();
3816
+ const output = useOutput();
3817
+ const readonly = useReadonly();
3818
+ return () => {
3819
+ const text = props.component.state.text;
3820
+ return (jsx("span", { onClick: () => {
3821
+ var _a;
3822
+ (_a = dropdownRef.current) === null || _a === void 0 ? void 0 : _a.isShow(true);
3823
+ }, ref: props.rootRef, "data-component": KatexComponent.componentName, "data-katex": encodeURIComponent(text), class: "xnote-katex", children: (output() || readonly()) ?
3824
+ domToVDom(toDOM(text))
3825
+ :
3826
+ jsx(Dropdown, { padding: '0', ref: dropdownRef, trigger: 'none', width: '600px', menu: jsx("div", { class: "xnote-katex-input", ref: editorRef }), children: domToVDom(toDOM(text)) }) }));
3827
+ };
3828
+ }
3829
+ const katexComponentLoader = {
3830
+ match(element) {
3831
+ return element.dataset.component === KatexComponent.componentName;
3832
+ },
3833
+ read(element, textbus) {
3834
+ const value = element.dataset.katex || '';
3835
+ return new KatexComponent(textbus, {
3836
+ text: decodeURIComponent(value)
3293
3837
  });
3294
3838
  }
3295
3839
  };
@@ -3298,7 +3842,8 @@ function InsertTool(props) {
3298
3842
  const commander = inject(Commander);
3299
3843
  const selection = inject(Selection);
3300
3844
  const textbus = inject(Textbus);
3301
- const fileUploader = inject(FileUploader, InjectFlags.Optional, null);
3845
+ const fileUploader = inject(FileUploader, null);
3846
+ const dropdownContextService = inject(DropdownContextService);
3302
3847
  function insert(type) {
3303
3848
  var _a;
3304
3849
  const component = (_a = props.slot) === null || _a === void 0 ? void 0 : _a.parent;
@@ -3312,6 +3857,8 @@ function InsertTool(props) {
3312
3857
  else {
3313
3858
  commander.insertAfter(comp, component);
3314
3859
  }
3860
+ dropdownContextService.canHide = true;
3861
+ dropdownContextService.hide(false);
3315
3862
  }
3316
3863
  switch (type) {
3317
3864
  case 'h1':
@@ -3373,7 +3920,9 @@ function InsertTool(props) {
3373
3920
  {
3374
3921
  const table = new TableComponent(textbus);
3375
3922
  insertComponent(table);
3376
- selection.setPosition(table.state.rows[0].cells[0].slot, 0);
3923
+ textbus.nextTick(() => {
3924
+ selection.selectFirstPosition(table, true, true);
3925
+ });
3377
3926
  }
3378
3927
  break;
3379
3928
  case 'todolist':
@@ -3392,7 +3941,7 @@ function InsertTool(props) {
3392
3941
  break;
3393
3942
  case 'image':
3394
3943
  if (fileUploader) {
3395
- Promise.resolve(fileUploader.uploadFile('image')).then(url => {
3944
+ Promise.resolve().then(() => fileUploader.uploadFile('image')).then(url => {
3396
3945
  const img = new ImageComponent(textbus, {
3397
3946
  src: url
3398
3947
  });
@@ -3402,7 +3951,7 @@ function InsertTool(props) {
3402
3951
  break;
3403
3952
  case 'video':
3404
3953
  if (fileUploader) {
3405
- Promise.resolve(fileUploader.uploadFile('video')).then(url => {
3954
+ Promise.resolve().then(() => fileUploader.uploadFile('video')).then(url => {
3406
3955
  const img = new VideoComponent(textbus, {
3407
3956
  src: url
3408
3957
  });
@@ -3419,14 +3968,23 @@ function InsertTool(props) {
3419
3968
  selection.setPosition(p.state.slot, 0);
3420
3969
  }
3421
3970
  break;
3971
+ case 'katex':
3972
+ {
3973
+ const p = new ParagraphComponent(textbus);
3974
+ const comp = new KatexComponent(textbus);
3975
+ p.state.slot.insert(comp);
3976
+ insertComponent(p);
3977
+ selection.selectComponent(comp);
3978
+ }
3979
+ break;
3422
3980
  }
3423
3981
  }
3424
- return withScopedCSS(scopedId$8, () => {
3425
- return jsxs(Fragment, { children: [jsxs("div", { class: "btn-group", children: [jsx(Button, { ordinary: true, onClick: () => insert('paragraph'), children: jsx("span", { class: "xnote-icon-pilcrow" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h1'), children: jsx("span", { class: "xnote-icon-heading-h1" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h2'), children: jsx("span", { class: "xnote-icon-heading-h2" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h3'), children: jsx("span", { class: "xnote-icon-heading-h3" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h4'), children: jsx("span", { class: "xnote-icon-heading-h4" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h5'), children: jsx("span", { class: "xnote-icon-heading-h5" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h6'), children: jsx("span", { class: "xnote-icon-heading-h6" }) }), jsx(Button, { ordinary: true, onClick: () => insert('ol'), children: jsx("span", { class: "xnote-icon-list-numbered" }) }), jsx(Button, { ordinary: true, onClick: () => insert('ul'), children: jsx("span", { class: "xnote-icon-list" }) }), jsx(Button, { ordinary: true, onClick: () => insert('sourceCode'), children: jsx("span", { class: "xnote-icon-source-code" }) })] }), jsx(Divider, {}), jsx(MenuItem, { onClick: () => insert('table'), icon: jsx("span", { class: "xnote-icon-table" }), children: "\u8868\u683C" }), jsx(MenuItem, { onClick: () => insert('todolist'), icon: jsx("span", { class: "xnote-icon-checkbox-checked" }), children: "\u5F85\u529E\u5217\u8868" }), jsx(MenuItem, { onClick: () => insert('image'), icon: jsx("span", { class: "xnote-icon-image" }), children: "\u56FE\u7247" }), jsx(MenuItem, { onClick: () => insert('video'), icon: jsx("span", { class: "xnote-icon-video" }), children: "\u89C6\u9891" }), jsx(MenuItem, { onClick: () => insert('highlightBox'), icon: jsx("span", { class: "xnote-icon-warning" }), children: "\u9AD8\u4EAE\u5757" })] });
3982
+ return withScopedCSS(scopedId$9, () => {
3983
+ return jsxs(Fragment, { children: [props.hideTitle ? null : jsx(MenuHeading, { children: props.replace ? '替换为' : '在下面添加' }), jsxs("div", { class: "btn-group", children: [jsx(Button, { ordinary: true, onClick: () => insert('paragraph'), children: jsx("span", { class: "xnote-icon-pilcrow" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h1'), children: jsx("span", { class: "xnote-icon-heading-h1" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h2'), children: jsx("span", { class: "xnote-icon-heading-h2" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h3'), children: jsx("span", { class: "xnote-icon-heading-h3" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h4'), children: jsx("span", { class: "xnote-icon-heading-h4" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h5'), children: jsx("span", { class: "xnote-icon-heading-h5" }) }), jsx(Button, { ordinary: true, onClick: () => insert('h6'), children: jsx("span", { class: "xnote-icon-heading-h6" }) }), jsx(Button, { ordinary: true, onClick: () => insert('ol'), children: jsx("span", { class: "xnote-icon-list-numbered" }) }), jsx(Button, { ordinary: true, onClick: () => insert('ul'), children: jsx("span", { class: "xnote-icon-list" }) }), jsx(Button, { ordinary: true, onClick: () => insert('sourceCode'), children: jsx("span", { class: "xnote-icon-source-code" }) })] }), jsx(Divider, {}), jsx(MenuItem, { onClick: () => insert('table'), icon: jsx("span", { class: "xnote-icon-table" }), children: "\u8868\u683C" }), jsx(MenuItem, { onClick: () => insert('todolist'), icon: jsx("span", { class: "xnote-icon-checkbox-checked" }), children: "\u5F85\u529E\u5217\u8868" }), jsx(MenuItem, { onClick: () => insert('image'), icon: jsx("span", { class: "xnote-icon-image" }), children: "\u56FE\u7247" }), jsx(MenuItem, { onClick: () => insert('video'), icon: jsx("span", { class: "xnote-icon-video" }), children: "\u89C6\u9891" }), jsx(MenuItem, { onClick: () => insert('highlightBox'), icon: jsx("span", { class: "xnote-icon-hightlight-box" }), children: "\u9AD8\u4EAE\u5757" }), jsx(MenuItem, { onClick: () => insert('katex'), icon: jsx("span", { class: "xnote-icon-function" }), children: "\u6570\u5B66\u516C\u5F0F" })] });
3426
3984
  });
3427
3985
  }
3428
3986
 
3429
- var scopedId$7 = "vf-b05292";
3987
+ var scopedId$8 = "vf-b05292";
3430
3988
 
3431
3989
  const LeftToolbar = withAnnotation({
3432
3990
  providers: [RefreshService]
@@ -3436,6 +3994,7 @@ const LeftToolbar = withAnnotation({
3436
3994
  const selection = inject(Selection);
3437
3995
  const rootComponentRef = inject(RootComponentRef);
3438
3996
  const refreshService = inject(RefreshService);
3997
+ const editorService = inject(EditorService);
3439
3998
  const checkStates = useActiveBlock();
3440
3999
  const toBlock = useBlockTransform();
3441
4000
  const activeSlot = createSignal(null);
@@ -3454,6 +4013,14 @@ const LeftToolbar = withAnnotation({
3454
4013
  top: 0,
3455
4014
  display: false
3456
4015
  });
4016
+ const sub = editorService.onLeftToolbarCanVisibleChange.subscribe(() => {
4017
+ updatePosition(d => {
4018
+ d.display = editorService.canShowLeftToolbar;
4019
+ });
4020
+ });
4021
+ onUnmounted(() => {
4022
+ sub.unsubscribe();
4023
+ });
3457
4024
  let isIgnoreMove = false;
3458
4025
  onMounted(() => {
3459
4026
  const rootComponent = rootComponentRef.component;
@@ -3461,12 +4028,14 @@ const LeftToolbar = withAnnotation({
3461
4028
  const sub = fromEvent(docContentContainer, 'mousemove').pipe(filter(() => {
3462
4029
  return !isIgnoreMove;
3463
4030
  }), map(ev => {
4031
+ var _a;
3464
4032
  let currentNode = ev.target;
3465
4033
  while (currentNode) {
3466
4034
  const slot = adapter.getSlotByNativeNode(currentNode);
3467
4035
  if (slot) {
3468
- if ((slot === null || slot === void 0 ? void 0 : slot.parent) instanceof SourceCodeComponent || (slot === null || slot === void 0 ? void 0 : slot.parent) instanceof TableComponent) {
3469
- return null;
4036
+ if (((_a = slot === null || slot === void 0 ? void 0 : slot.parent) === null || _a === void 0 ? void 0 : _a.type) === ContentType.InlineComponent) {
4037
+ currentNode = currentNode.parentNode;
4038
+ continue;
3470
4039
  }
3471
4040
  return slot;
3472
4041
  }
@@ -3481,7 +4050,9 @@ const LeftToolbar = withAnnotation({
3481
4050
  activeSlot.set(slot);
3482
4051
  if (slot) {
3483
4052
  checkStates(slot);
3484
- isEmptyBlock.set(slot.parent instanceof ParagraphComponent && slot.isEmpty);
4053
+ isEmptyBlock.set((slot.parent instanceof ParagraphComponent && slot.isEmpty) ||
4054
+ slot.parent instanceof SourceCodeComponent ||
4055
+ slot.parent instanceof TableComponent);
3485
4056
  const nativeNode = adapter.getNativeNodeByComponent(slot.parent);
3486
4057
  updatePosition(draft => {
3487
4058
  const containerRect = docContentContainer.getBoundingClientRect();
@@ -3534,18 +4105,6 @@ const LeftToolbar = withAnnotation({
3534
4105
  isShow.set(true);
3535
4106
  }));
3536
4107
  });
3537
- let snapshot = null;
3538
- function queryBefore() {
3539
- const slot = activeSlot();
3540
- if (slot) {
3541
- snapshot = selection.createSnapshot();
3542
- selection.selectSlot(slot);
3543
- }
3544
- }
3545
- function queryAfter() {
3546
- snapshot === null || snapshot === void 0 ? void 0 : snapshot.restore();
3547
- snapshot = null;
3548
- }
3549
4108
  function applyBefore() {
3550
4109
  const slot = activeSlot();
3551
4110
  if (slot) {
@@ -3577,7 +4136,7 @@ const LeftToolbar = withAnnotation({
3577
4136
  if (!slot) {
3578
4137
  return;
3579
4138
  }
3580
- if (slot.parent.__slots__.length <= 1) {
4139
+ if (slot.parent.slots.length <= 1) {
3581
4140
  commander.removeComponent(slot.parent);
3582
4141
  }
3583
4142
  else {
@@ -3589,20 +4148,21 @@ const LeftToolbar = withAnnotation({
3589
4148
  function changeIgnoreMove(b) {
3590
4149
  isIgnoreMove = b;
3591
4150
  }
3592
- return withScopedCSS(scopedId$7, () => {
4151
+ return withScopedCSS(scopedId$8, () => {
4152
+ var _a;
3593
4153
  const position = positionSignal();
3594
4154
  const slot = activeSlot();
3595
4155
  let activeNode = jsx("span", { class: "xnote-icon-pilcrow" });
3596
- const states = checkStates();
4156
+ const states = checkStates(slot);
3597
4157
  if (slot) {
3598
4158
  const types = [
3599
4159
  [states.paragraph, jsx("span", { class: "xnote-icon-pilcrow" })],
3600
4160
  [states.sourceCode, jsx("span", { class: "xnote-icon-source-code" })],
3601
4161
  [states.blockquote, jsx("span", { class: "xnote-icon-quotes-right" })],
3602
4162
  [states.todolist, jsx("span", { class: "xnote-icon-checkbox-checked" })],
3603
- [states.table, jsx("span", { class: "xnote-icon-table" })],
3604
4163
  [states.unorderedList, jsx("span", { class: "xnote-icon-list" })],
3605
4164
  [states.orderedList, jsx("span", { class: "xnote-icon-list-numbered" })],
4165
+ [states.table, jsx("span", { class: "xnote-icon-table" })],
3606
4166
  [states.h1, jsx("span", { class: "xnote-icon-heading-h1" })],
3607
4167
  [states.h2, jsx("span", { class: "xnote-icon-heading-h2" })],
3608
4168
  [states.h3, jsx("span", { class: "xnote-icon-heading-h3" })],
@@ -3617,18 +4177,20 @@ const LeftToolbar = withAnnotation({
3617
4177
  }
3618
4178
  }
3619
4179
  }
4180
+ const activeParentComponent = (_a = activeSlot()) === null || _a === void 0 ? void 0 : _a.parent;
4181
+ const needInsert = activeParentComponent instanceof TableComponent || activeParentComponent instanceof SourceCodeComponent;
3620
4182
  return (jsx("div", { class: "left-toolbar", ref: toolbarRef, children: jsx("div", { class: "left-toolbar-btn-wrap", ref: btnRef, style: {
3621
4183
  left: position.left + 'px',
3622
4184
  top: position.top + 'px',
3623
- display: position.display && selection.isCollapsed ? 'block' : 'none'
3624
- }, children: jsx(Dropdown, { onExpendStateChange: changeIgnoreMove, abreast: true, style: {
4185
+ display: position.display && selection.isCollapsed && editorService.canShowLeftToolbar ? 'block' : 'none'
4186
+ }, children: jsx(Dropdown, { toLeft: true, onExpendStateChange: changeIgnoreMove, abreast: true, style: {
3625
4187
  position: 'absolute',
3626
4188
  right: 0,
3627
4189
  top: 0
3628
4190
  }, menu: isEmptyBlock() ?
3629
- jsx(InsertTool, { replace: true, slot: activeSlot() })
4191
+ jsx(InsertTool, { replace: !needInsert, slot: activeSlot() })
3630
4192
  :
3631
- jsxs(Fragment, { children: [jsxs("div", { class: "btn-group", children: [jsx(Button, { ordinary: true, highlight: states.paragraph, onClick: () => transform('paragraph'), children: jsx("span", { class: "xnote-icon-pilcrow" }) }), jsx(Button, { ordinary: true, highlight: states.h1, onClick: () => transform('h1'), children: jsx("span", { class: "xnote-icon-heading-h1" }) }), jsx(Button, { ordinary: true, highlight: states.h2, onClick: () => transform('h2'), children: jsx("span", { class: "xnote-icon-heading-h2" }) }), jsx(Button, { ordinary: true, highlight: states.h3, onClick: () => transform('h3'), children: jsx("span", { class: "xnote-icon-heading-h3" }) }), jsx(Button, { ordinary: true, highlight: states.h4, onClick: () => transform('h4'), children: jsx("span", { class: "xnote-icon-heading-h4" }) }), jsx(Button, { ordinary: true, highlight: states.todolist, onClick: () => transform('todolist'), children: jsx("span", { class: "xnote-icon-checkbox-checked" }) }), jsx(Button, { ordinary: true, highlight: states.orderedList, onClick: () => transform('ol'), children: jsx("span", { class: "xnote-icon-list-numbered" }) }), jsx(Button, { ordinary: true, highlight: states.unorderedList, onClick: () => transform('ul'), children: jsx("span", { class: "xnote-icon-list" }) }), jsx(Button, { ordinary: true, highlight: states.blockquote, onClick: () => transform('blockquote'), children: jsx("span", { class: "xnote-icon-quotes-right" }) }), jsx(Button, { ordinary: true, highlight: states.sourceCode, onClick: () => transform('sourceCode'), children: jsx("span", { class: "xnote-icon-source-code" }) })] }), jsx(Divider, {}), jsx(AttrTool, { style: { display: 'block' }, abreast: true, applyBefore: applyBefore, queryBefore: queryBefore, queryAfter: queryAfter, children: jsx(MenuItem, { arrow: true, icon: jsx("span", { class: "xnote-icon-indent-decrease" }), children: "\u7F29\u8FDB\u548C\u5BF9\u9F50" }) }), jsx(ColorTool, { style: { display: 'block' }, abreast: true, applyBefore: applyBefore, queryBefore: queryBefore, queryAfter: queryAfter, children: jsx(MenuItem, { arrow: true, icon: jsx("span", { class: "xnote-icon-color" }), children: "\u989C\u8272" }) }), jsx(Divider, {}), jsx(MenuItem, { onClick: copy, icon: jsx("span", { class: "xnote-icon-copy" }), children: "\u590D\u5236" }), jsx(MenuItem, { onClick: remove, icon: jsx("span", { class: "xnote-icon-bin" }), children: "\u5220\u9664" }), jsx(MenuItem, { onClick: cut, icon: jsx("span", { class: "xnote-icon-cut" }), children: "\u526A\u5207" }), jsx(Divider, {}), jsx(Dropdown, { style: { display: 'block' }, abreast: true, menu: jsx(InsertTool, { slot: activeSlot() }), children: jsx(MenuItem, { arrow: true, icon: jsx("span", { class: "xnote-icon-plus" }), children: "\u5728\u4E0B\u9762\u6DFB\u52A0" }) })] }), children: jsx("button", { type: "button", class: "left-toolbar-btn", children: isEmptyBlock() ?
4193
+ jsxs(Fragment, { children: [jsxs("div", { class: "btn-group", children: [jsx(Button, { ordinary: true, highlight: states.paragraph, onClick: () => transform('paragraph'), children: jsx("span", { class: "xnote-icon-pilcrow" }) }), jsx(Button, { ordinary: true, highlight: states.h1, onClick: () => transform('h1'), children: jsx("span", { class: "xnote-icon-heading-h1" }) }), jsx(Button, { ordinary: true, highlight: states.h2, onClick: () => transform('h2'), children: jsx("span", { class: "xnote-icon-heading-h2" }) }), jsx(Button, { ordinary: true, highlight: states.h3, onClick: () => transform('h3'), children: jsx("span", { class: "xnote-icon-heading-h3" }) }), jsx(Button, { ordinary: true, highlight: states.h4, onClick: () => transform('h4'), children: jsx("span", { class: "xnote-icon-heading-h4" }) }), jsx(Button, { ordinary: true, highlight: states.todolist, onClick: () => transform('todolist'), children: jsx("span", { class: "xnote-icon-checkbox-checked" }) }), jsx(Button, { ordinary: true, highlight: states.orderedList, onClick: () => transform('ol'), children: jsx("span", { class: "xnote-icon-list-numbered" }) }), jsx(Button, { ordinary: true, highlight: states.unorderedList, onClick: () => transform('ul'), children: jsx("span", { class: "xnote-icon-list" }) }), jsx(Button, { ordinary: true, highlight: states.blockquote, onClick: () => transform('blockquote'), children: jsx("span", { class: "xnote-icon-quotes-right" }) }), jsx(Button, { ordinary: true, highlight: states.sourceCode, onClick: () => transform('sourceCode'), children: jsx("span", { class: "xnote-icon-source-code" }) })] }), jsx(Divider, {}), jsx(AttrTool, { style: { display: 'block' }, abreast: true, slot: slot, applyBefore: applyBefore, children: jsx(MenuItem, { arrow: true, icon: jsx("span", { class: "xnote-icon-indent-decrease" }), children: "\u7F29\u8FDB\u548C\u5BF9\u9F50" }) }), jsx(ColorTool, { style: { display: 'block' }, abreast: true, applyBefore: applyBefore, children: jsx(MenuItem, { arrow: true, icon: jsx("span", { class: "xnote-icon-color" }), children: "\u989C\u8272" }) }), jsx(Divider, {}), jsx(MenuItem, { onClick: copy, icon: jsx("span", { class: "xnote-icon-copy" }), children: "\u590D\u5236" }), jsx(MenuItem, { onClick: remove, icon: jsx("span", { class: "xnote-icon-bin" }), children: "\u5220\u9664" }), jsx(MenuItem, { onClick: cut, icon: jsx("span", { class: "xnote-icon-cut" }), children: "\u526A\u5207" }), jsx(Divider, {}), jsx(Dropdown, { style: { display: 'block' }, abreast: true, menu: jsx(InsertTool, { hideTitle: true, slot: activeSlot() }), children: jsx(MenuItem, { arrow: true, icon: jsx("span", { class: "xnote-icon-plus" }), children: "\u5728\u4E0B\u9762\u6DFB\u52A0" }) })] }), children: jsx("button", { type: "button", class: "left-toolbar-btn", children: isEmptyBlock() ?
3632
4194
  jsx("span", { children: jsx("i", { class: "xnote-icon-plus" }) })
3633
4195
  :
3634
4196
  jsxs("span", { children: [activeNode, jsx("i", { style: "font-size: 12px", class: "xnote-icon-more" })] }) }) }) }) }));
@@ -3663,24 +4225,74 @@ class LeftToolbarPlugin {
3663
4225
  }
3664
4226
  }
3665
4227
 
3666
- var scopedId$6 = "vf-fee98b";
4228
+ var scopedId$7 = "vf-3073ba";
3667
4229
 
3668
- let EditorService = class EditorService {
3669
- constructor() {
3670
- this.hideInlineToolbar = false;
4230
+ function LinkJump() {
4231
+ const selection = inject(Selection);
4232
+ const query = inject(Query);
4233
+ const bridge = inject(SelectionBridge);
4234
+ const container = inject(VIEW_CONTAINER);
4235
+ const href = createSignal('');
4236
+ const ref = createRef();
4237
+ const isShow = createSignal(false);
4238
+ function onSelectionChange() {
4239
+ if (selection.isCollapsed) {
4240
+ const queryState = query.queryFormat(linkFormatter);
4241
+ if (queryState.state === QueryStateType.Enabled) {
4242
+ const rect = bridge.getRect({
4243
+ slot: selection.startSlot,
4244
+ offset: selection.startOffset
4245
+ });
4246
+ if (rect) {
4247
+ const offsetRect = container.getBoundingClientRect();
4248
+ Object.assign(ref.current.style, {
4249
+ left: rect.left - offsetRect.left + 'px',
4250
+ top: rect.top - offsetRect.top + 'px'
4251
+ });
4252
+ isShow.set(true);
4253
+ let url = queryState.value.href;
4254
+ if (url.indexOf('://') < 0) {
4255
+ url = 'http://' + url;
4256
+ }
4257
+ href.set(url);
4258
+ return;
4259
+ }
4260
+ }
4261
+ }
4262
+ isShow.set(false);
3671
4263
  }
3672
- };
3673
- EditorService = __decorate([
3674
- Injectable({
3675
- provideIn: 'root'
3676
- })
3677
- ], EditorService);
4264
+ selection.onChange.pipe(delay()).subscribe(() => {
4265
+ onSelectionChange();
4266
+ });
4267
+ function cleanLink() {
4268
+ isShow.set(false);
4269
+ const commonAncestorSlot = selection.commonAncestorSlot;
4270
+ const index = selection.focusOffset;
4271
+ const ranges = commonAncestorSlot.getFormatRangesByFormatter(linkFormatter, 0, commonAncestorSlot.length);
4272
+ ranges.forEach(range => {
4273
+ if (range.startIndex < index && range.endIndex >= index) {
4274
+ commonAncestorSlot.applyFormat(linkFormatter, {
4275
+ startIndex: range.startIndex,
4276
+ endIndex: range.endIndex,
4277
+ value: null
4278
+ });
4279
+ }
4280
+ });
4281
+ }
4282
+ return createPortal(withScopedCSS(scopedId$7, () => {
4283
+ return (jsxs("div", { ref: ref, class: "link-jump-plugin", style: { display: isShow() ? '' : 'none' }, children: [jsx("span", { onClick: cleanLink, children: "\u6E05\u9664" }), jsx("a", { target: "_blank", href: href(), children: "\u8DF3\u8F6C" })] }));
4284
+ }), container);
4285
+ }
4286
+
4287
+ var scopedId$6 = "vf-fee98b";
3678
4288
 
3679
4289
  const Toolbar = withAnnotation({
3680
4290
  providers: [RefreshService]
3681
4291
  }, function Toolbar() {
3682
4292
  const selection = inject(Selection);
3683
4293
  const viewDocument = inject(VIEW_CONTAINER);
4294
+ const rootComponentRef = inject(RootComponentRef);
4295
+ const adapter = inject(DomAdapter);
3684
4296
  const bridge = inject(SelectionBridge);
3685
4297
  const textbus = inject(Textbus);
3686
4298
  const editorService = inject(EditorService);
@@ -3702,7 +4314,7 @@ const Toolbar = withAnnotation({
3702
4314
  const toolbarRef = createRef();
3703
4315
  function getTop() {
3704
4316
  const docRect = viewDocument.getBoundingClientRect();
3705
- const toolbarRect = toolbarRef.current.getBoundingClientRect();
4317
+ const toolbarHeight = 36;
3706
4318
  // const documentHeight = document.documentElement.clientHeight
3707
4319
  const selectionFocusRect = bridge.getRect({
3708
4320
  slot: selection.focusSlot,
@@ -3711,14 +4323,12 @@ const Toolbar = withAnnotation({
3711
4323
  if (!selectionFocusRect) {
3712
4324
  return null;
3713
4325
  }
3714
- // console.log(selectionFocusRect.top, toolbarRect.height)
3715
4326
  const centerLeft = selectionFocusRect.left;
3716
- const toBottom = selectionFocusRect.top < toolbarRect.height + 10;
4327
+ const toBottom = selectionFocusRect.top < toolbarHeight + 10;
3717
4328
  const top = toBottom ?
3718
4329
  selectionFocusRect.top + selectionFocusRect.height - docRect.top + 10 :
3719
- selectionFocusRect.top - docRect.top - toolbarRect.height - 10;
4330
+ selectionFocusRect.top - docRect.top - toolbarHeight - 10;
3720
4331
  updateViewPosition(draft => {
3721
- draft.isHide = false;
3722
4332
  draft.transitionDuration = .15;
3723
4333
  draft.left = centerLeft - docRect.left;
3724
4334
  draft.top = top + 10;
@@ -3739,13 +4349,15 @@ const Toolbar = withAnnotation({
3739
4349
  sub.unsubscribe();
3740
4350
  });
3741
4351
  function bindMouseup() {
3742
- mouseupSubscription = fromEvent(viewDocument, 'mouseup').pipe(filter(ev => {
4352
+ const docElement = adapter.getNativeNodeByComponent(rootComponentRef.component);
4353
+ mouseupSubscription = fromEvent(docElement, 'mouseup').pipe(filter(ev => {
3743
4354
  return !ev.composedPath().includes(toolbarRef.current);
3744
4355
  }), delay(100), filter(() => {
3745
4356
  return !selection.isCollapsed && !(selection.commonAncestorComponent instanceof SourceCodeComponent);
3746
4357
  }), map(getTop), delay(200)).subscribe((top) => {
3747
4358
  if (top !== null) {
3748
4359
  updateViewPosition(draft => {
4360
+ draft.isHide = false;
3749
4361
  draft.opacity = 1;
3750
4362
  draft.top = top;
3751
4363
  });
@@ -3764,10 +4376,10 @@ const Toolbar = withAnnotation({
3764
4376
  });
3765
4377
  bindMouseup();
3766
4378
  });
4379
+ const instance = getCurrentInstance();
3767
4380
  function hideToolbar() {
3768
- updateViewPosition(draft => {
3769
- draft.isHide = true;
3770
- });
4381
+ editorService.hideInlineToolbar = true;
4382
+ instance.markAsDirtied();
3771
4383
  }
3772
4384
  onUnmounted(() => {
3773
4385
  mousedownSubscription.unsubscribe();
@@ -3908,6 +4520,225 @@ class Matcher {
3908
4520
  }
3909
4521
  }
3910
4522
 
4523
+ class Organization {
4524
+ }
4525
+ function registerAtShortcut(textbus) {
4526
+ const keyboard = textbus.get(Keyboard);
4527
+ const selection = textbus.get(Selection);
4528
+ const commander = textbus.get(Commander);
4529
+ keyboard.addShortcut({
4530
+ keymap: {
4531
+ key: '@',
4532
+ shiftKey: true
4533
+ },
4534
+ action() {
4535
+ const { commonAncestorComponent } = selection;
4536
+ if (commonAncestorComponent instanceof SourceCodeComponent) {
4537
+ return false;
4538
+ }
4539
+ const at = new AtComponent(textbus);
4540
+ commander.insert(at);
4541
+ selection.setPosition(at.state.slot, 0);
4542
+ }
4543
+ });
4544
+ }
4545
+ class AtComponent extends Component {
4546
+ static fromJSON(textbus, { slot: slotState, userInfo }) {
4547
+ const registry = textbus.get(Registry);
4548
+ if (slotState) {
4549
+ const slot = registry.createSlot(slotState);
4550
+ return new AtComponent(textbus, {
4551
+ slot
4552
+ });
4553
+ }
4554
+ return new AtComponent(textbus, {
4555
+ userInfo,
4556
+ });
4557
+ }
4558
+ constructor(textbus, state = {
4559
+ slot: new Slot([ContentType.Text])
4560
+ }) {
4561
+ if (!state.userInfo && !state.slot) {
4562
+ state.slot = new Slot([ContentType.Text]);
4563
+ }
4564
+ super(textbus, state);
4565
+ this.focus = new Subject();
4566
+ this.members = createSignal([]);
4567
+ this.selectedIndex = createSignal(0);
4568
+ }
4569
+ getSlots() {
4570
+ if (this.state.userInfo) {
4571
+ return [];
4572
+ }
4573
+ if (this.state.slot) {
4574
+ return [this.state.slot];
4575
+ }
4576
+ return [];
4577
+ }
4578
+ setup() {
4579
+ let isFocus = false;
4580
+ onFocus(() => {
4581
+ isFocus = true;
4582
+ this.focus.next(true);
4583
+ onChange.next();
4584
+ });
4585
+ onBlur(() => {
4586
+ isFocus = false;
4587
+ this.focus.next(false);
4588
+ setTimeout(() => {
4589
+ if (this.parent && !this.state.userInfo) {
4590
+ const slot = this.state.slot;
4591
+ let text = '@';
4592
+ if (slot) {
4593
+ text += slot.isEmpty ? '' : slot.toString();
4594
+ }
4595
+ const snapshot = selection.createSnapshot();
4596
+ selection.selectComponent(this);
4597
+ commander.insert(text);
4598
+ snapshot.restore(true);
4599
+ }
4600
+ });
4601
+ });
4602
+ const organization = useContext(Organization);
4603
+ const selection = useContext(Selection);
4604
+ const commander = useContext(Commander);
4605
+ const onChange = new Subject();
4606
+ onContentInserted((ev) => {
4607
+ const key = this.state.slot.toString();
4608
+ if (key.length > 10) {
4609
+ selection.selectComponent(this);
4610
+ commander.insert(key);
4611
+ ev.preventDefault();
4612
+ return;
4613
+ }
4614
+ onChange.next();
4615
+ });
4616
+ onContentDeleted(() => {
4617
+ onChange.next();
4618
+ });
4619
+ onBreak((ev) => {
4620
+ const member = this.members()[this.selectedIndex()];
4621
+ if (member) {
4622
+ this.state.userInfo = Object.assign({}, member);
4623
+ }
4624
+ selection.selectComponentEnd(this);
4625
+ ev.preventDefault();
4626
+ });
4627
+ useDynamicShortcut({
4628
+ keymap: {
4629
+ key: ['ArrowDown', 'ArrowUp']
4630
+ },
4631
+ action: (key) => {
4632
+ let index = this.selectedIndex();
4633
+ if (key === 'ArrowUp') {
4634
+ if (index > 0) {
4635
+ index--;
4636
+ this.selectedIndex.set(index);
4637
+ }
4638
+ return;
4639
+ }
4640
+ if (index < this.members().length - 1) {
4641
+ index++;
4642
+ this.selectedIndex.set(index);
4643
+ }
4644
+ }
4645
+ });
4646
+ const subs = onChange.pipe(switchMap(() => {
4647
+ const key = this.state.slot.toString();
4648
+ return fromPromise(organization.getMembers(key));
4649
+ })).subscribe((members) => {
4650
+ this.members.set(members);
4651
+ this.selectedIndex.set(0);
4652
+ if (isFocus) {
4653
+ this.focus.next(true);
4654
+ }
4655
+ });
4656
+ onDestroy(() => {
4657
+ subs.unsubscribe();
4658
+ });
4659
+ }
4660
+ }
4661
+ AtComponent.componentName = 'AtComponent';
4662
+ AtComponent.type = ContentType.InlineComponent;
4663
+
4664
+ function AtComponentView(props) {
4665
+ const selection = inject(Selection);
4666
+ const dropdownRef = createRef();
4667
+ const subscription = props.component.focus.subscribe((b) => {
4668
+ if (dropdownRef.current && props.component.members().length) {
4669
+ dropdownRef.current.isShow(b);
4670
+ }
4671
+ });
4672
+ onUnmounted(() => {
4673
+ subscription.unsubscribe();
4674
+ });
4675
+ const readonly = useReadonly();
4676
+ const output = useOutput();
4677
+ const membersRef = createRef();
4678
+ onUpdated(() => {
4679
+ if (output() || readonly()) {
4680
+ return;
4681
+ }
4682
+ const container = membersRef.current;
4683
+ if (container) {
4684
+ const focusItem = container.children[props.component.selectedIndex()];
4685
+ if (focusItem) {
4686
+ const itemRect = focusItem.getBoundingClientRect();
4687
+ const dropdownMenu = container.parentNode.parentNode;
4688
+ const containerRect = dropdownMenu.getBoundingClientRect();
4689
+ if (itemRect.top - 5 < containerRect.top) {
4690
+ dropdownMenu.scrollTop += itemRect.top - 5 - containerRect.top;
4691
+ }
4692
+ else if (itemRect.bottom + 5 > containerRect.bottom) {
4693
+ dropdownMenu.scrollTop += itemRect.bottom + 5 - containerRect.bottom;
4694
+ }
4695
+ }
4696
+ }
4697
+ });
4698
+ return () => {
4699
+ const { slot, userInfo } = props.component.state;
4700
+ const selectedIndex = props.component.selectedIndex();
4701
+ if (userInfo) {
4702
+ return (jsxs("div", { class: "xnote-at xnote-at-complete", "data-info": encodeURIComponent(JSON.stringify(userInfo)), ref: props.rootRef, "data-component": props.component.name, children: [jsx("span", { children: "@" }), userInfo.name] }));
4703
+ }
4704
+ if (readonly() || output()) {
4705
+ return (jsxs("div", { class: "xnote-at", ref: props.rootRef, "data-component": props.component.name, children: [jsx("span", { children: "@" }), slot && jsx(SlotRender, { slot: slot, class: 'xnote-at-input', tag: "span" })] }));
4706
+ }
4707
+ const members = props.component.members();
4708
+ return (jsx("div", { class: "xnote-at", ref: props.rootRef, "data-component": props.component.name, children: jsxs(Dropdown, { trigger: 'none', ref: dropdownRef, menu: jsx("div", { class: "xnote-at-menu", ref: membersRef, children: members.map((member, index) => {
4709
+ let hsl = any2Hsl(member.color);
4710
+ if (hsl === 'unknown') {
4711
+ hsl = any2Hsl('#000');
4712
+ }
4713
+ const rgb = hsl2Rgb(hsl);
4714
+ const yiq = (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
4715
+ const color = yiq >= 128 ? '#000' : '#fff';
4716
+ return (jsxs("div", { onClick: () => {
4717
+ props.component.state.userInfo = member;
4718
+ selection.selectComponentEnd(props.component);
4719
+ }, class: ['xnote-at-member', { selected: index === selectedIndex }], children: [jsx("div", { class: "xnote-at-member-avatar", children: member.avatar ? jsx("img", { src: member.avatar, alt: member.name }) :
4720
+ jsx("span", { class: "xnote-at-member-avatar-bg", style: { background: member.color, color }, children: member.name }) }), jsxs("div", { class: "xnote-at-member-info", children: [jsx("div", { class: "xnote-at-member-name", children: member.name }), jsx("div", { class: "xnote-at-member-desc", children: member.groupName })] })] }, member.id));
4721
+ }) }), children: [jsx("span", { children: "@" }), slot && jsx(SlotRender, { slot: slot, tag: 'span', class: 'xnote-at-input' })] }) }));
4722
+ };
4723
+ }
4724
+ const atComponentLoader = {
4725
+ match(element) {
4726
+ return element.dataset.component === AtComponent.componentName;
4727
+ },
4728
+ read(element, textbus, slotParser) {
4729
+ const data = element.dataset.info;
4730
+ if (data) {
4731
+ return new AtComponent(textbus, {
4732
+ userInfo: JSON.parse(decodeURIComponent(data))
4733
+ });
4734
+ }
4735
+ const slot = slotParser(new Slot([ContentType.Text]), element.querySelector('.xnote-at-input') || document.createElement('div'));
4736
+ return new AtComponent(textbus, {
4737
+ slot
4738
+ });
4739
+ }
4740
+ };
4741
+
3911
4742
  class RootComponent extends Component {
3912
4743
  constructor() {
3913
4744
  super(...arguments);
@@ -3919,17 +4750,36 @@ class RootComponent extends Component {
3919
4750
  content
3920
4751
  });
3921
4752
  }
4753
+ getSlots() {
4754
+ return [this.state.content];
4755
+ }
3922
4756
  setup() {
3923
- useBlockContent(this.state.content);
4757
+ useBlockContent((slot) => slot === this.state.content);
3924
4758
  onCompositionStart(ev => {
3925
4759
  this.onCompositionStart.next(ev);
3926
4760
  });
4761
+ onSlotSetAttribute(ev => {
4762
+ ev.preventDefault();
4763
+ });
4764
+ onSlotApplyFormat(ev => {
4765
+ ev.preventDefault();
4766
+ });
4767
+ }
4768
+ afterCheck() {
4769
+ const content = this.state.content;
4770
+ const lastContent = content.getContentAtIndex(content.length - 1);
4771
+ if (lastContent instanceof ParagraphComponent ||
4772
+ lastContent instanceof ListComponent ||
4773
+ lastContent instanceof TodolistComponent) {
4774
+ return;
4775
+ }
4776
+ content.retain(content.length);
4777
+ content.insert(new ParagraphComponent(this.textbus));
3927
4778
  }
3928
4779
  }
3929
4780
  RootComponent.componentName = 'RootComponent';
3930
4781
  RootComponent.type = ContentType.BlockComponent;
3931
4782
  function RootView(props) {
3932
- const adapter = inject(DomAdapter);
3933
4783
  const { content } = props.component.state;
3934
4784
  const ref = createDynamicRef(node => {
3935
4785
  const sub = props.component.onCompositionStart.subscribe(() => {
@@ -3939,16 +4789,14 @@ function RootView(props) {
3939
4789
  sub.unsubscribe();
3940
4790
  };
3941
4791
  });
4792
+ onUpdated(() => {
4793
+ props.component.afterCheck();
4794
+ });
3942
4795
  const readonly = useReadonly();
3943
4796
  const output = useOutput();
3944
4797
  return () => {
3945
4798
  const { rootRef } = props;
3946
- return (jsx("div", { class: "xnote-root", ref: [rootRef, ref], children: adapter.slotRender(content, children => {
3947
- return (createVNode('div', {
3948
- class: 'xnote-content',
3949
- 'data-placeholder': content.isEmpty ? '请输入内容' : ''
3950
- }, children));
3951
- }, readonly() || output()) }));
4799
+ return (jsx("div", { class: "xnote-root", dir: "auto", ref: [rootRef, ref], "data-component": props.component.name, children: jsx(SlotRender, { slot: content, tag: "div", class: "xnote-content", "data-placeholder": content.isEmpty ? '请输入内容' : '', renderEnv: readonly() || output() }) }));
3952
4800
  };
3953
4801
  }
3954
4802
  const rootComponentLoader = {
@@ -3962,9 +4810,7 @@ const rootComponentLoader = {
3962
4810
  ContentType.Text
3963
4811
  ]), element).toDelta();
3964
4812
  const slot = new Slot([
3965
- ContentType.BlockComponent,
3966
- ContentType.InlineComponent,
3967
- ContentType.Text
4813
+ ContentType.BlockComponent
3968
4814
  ]);
3969
4815
  deltaToBlock(delta, textbus).forEach(i => {
3970
4816
  slot.insert(i);
@@ -3991,6 +4837,7 @@ TableService = __decorate([
3991
4837
  function ResizeColumn(props) {
3992
4838
  const dragLineRef = createRef();
3993
4839
  let activeCol = null;
4840
+ const editorService = inject(EditorService);
3994
4841
  onMounted(() => {
3995
4842
  const { tableRef } = props;
3996
4843
  let isDrag = false;
@@ -4023,6 +4870,7 @@ function ResizeColumn(props) {
4023
4870
  }
4024
4871
  })).add(fromEvent(dragLineRef.current, 'mousedown').subscribe(downEvent => {
4025
4872
  isDrag = true;
4873
+ editorService.changeLeftToolbarVisible(false);
4026
4874
  props.onActiveStateChange(true);
4027
4875
  const x = downEvent.clientX;
4028
4876
  const layoutWidth = props.component.state.layoutWidth;
@@ -4030,16 +4878,20 @@ function ResizeColumn(props) {
4030
4878
  const initLeft = layoutWidth.slice(0, activeCol).reduce((a, b) => a + b, 0);
4031
4879
  const minWidth = 30;
4032
4880
  const minLeft = initLeft - initWidth + minWidth;
4881
+ const layoutWidthArr = layoutWidth.slice();
4033
4882
  const moveEvent = fromEvent(document, 'mousemove').subscribe(moveEvent => {
4034
4883
  const distanceX = moveEvent.clientX - x;
4035
4884
  dragLineRef.current.style.left = Math.max(initLeft + distanceX, minLeft) + 'px';
4036
- props.component.state.layoutWidth[activeCol - 1] = Math.max(initWidth + distanceX, minWidth);
4885
+ layoutWidthArr[activeCol - 1] = Math.max(initWidth + distanceX, minWidth);
4886
+ props.layoutWidth.set(layoutWidthArr.slice());
4037
4887
  }).add(fromEvent(document, 'mouseup').subscribe(upEvent => {
4038
4888
  isDrag = false;
4889
+ editorService.changeLeftToolbarVisible(true);
4039
4890
  props.onActiveStateChange(false);
4040
4891
  moveEvent.unsubscribe();
4041
4892
  const distanceX = upEvent.clientX - x;
4042
4893
  props.component.state.layoutWidth[activeCol - 1] = Math.max(initWidth + distanceX, minWidth);
4894
+ props.layoutWidth.set(props.component.state.layoutWidth);
4043
4895
  }));
4044
4896
  }));
4045
4897
  return () => {
@@ -4065,7 +4917,7 @@ function ResizeColumn(props) {
4065
4917
  });
4066
4918
  }
4067
4919
 
4068
- var scopedId$4 = "vf-d64cf9";
4920
+ var scopedId$4 = "vf-39cb2c";
4069
4921
 
4070
4922
  function TopBar(props) {
4071
4923
  const editorService = inject(EditorService);
@@ -4140,7 +4992,7 @@ function TopBar(props) {
4140
4992
  active: props.isFocus()
4141
4993
  }], children: jsxs("div", { class: "toolbar-wrapper", children: [jsx("div", { class: "insert-bar", children: jsx("table", { style: {
4142
4994
  transform: `translateX(${-leftDistance()}px)`
4143
- }, children: jsx("tbody", { children: jsx("tr", { children: state.layoutWidth.map((i, index) => {
4995
+ }, children: jsx("tbody", { children: jsx("tr", { children: props.layoutWidth().map((i, index) => {
4144
4996
  return (jsx("td", { style: { width: i + 'px', minWidth: i + 'px' }, children: jsxs("div", { class: "tool-container", children: [index === 0 && (jsx("span", { onMouseenter: () => {
4145
4997
  tableService.onInsertColumnBefore.next(0);
4146
4998
  }, onMouseleave: () => {
@@ -4166,7 +5018,7 @@ function TopBar(props) {
4166
5018
  }, children: jsx("span", { class: "xnote-icon-bin" }) }) }) })] }) }));
4167
5019
  }) }) }) }) }), jsx("div", { class: ['action-bar', { active: props.isFocus() }], children: jsx("table", { style: {
4168
5020
  transform: `translateX(${-leftDistance()}px)`
4169
- }, children: jsx("tbody", { children: jsx("tr", { children: state.layoutWidth.map((i, index) => {
5021
+ }, children: jsx("tbody", { children: jsx("tr", { children: props.layoutWidth().map((i, index) => {
4170
5022
  return jsx("td", { onClick: ev => {
4171
5023
  mouseDownFromToolbar = true;
4172
5024
  if (!ev.shiftKey) {
@@ -4186,7 +5038,7 @@ function TopBar(props) {
4186
5038
  });
4187
5039
  }
4188
5040
 
4189
- var scopedId$3 = "vf-b1149b";
5041
+ var scopedId$3 = "vf-7bef30";
4190
5042
 
4191
5043
  function Scroll(props) {
4192
5044
  const scrollRef = createRef();
@@ -4200,37 +5052,41 @@ function Scroll(props) {
4200
5052
  const el = scrollRef.current;
4201
5053
  function update() {
4202
5054
  if (props.isFocus()) {
4203
- input.caret.refresh(false);
5055
+ input.caret.refresh();
4204
5056
  }
4205
5057
  updateShowShadow(draft => {
4206
5058
  draft.leftEnd = el.scrollLeft === 0;
4207
5059
  draft.rightEnd = el.scrollLeft === el.scrollWidth - el.offsetWidth;
4208
5060
  });
4209
5061
  }
4210
- update();
5062
+ setTimeout(update);
4211
5063
  const s = fromEvent(el, 'scroll').subscribe(update);
4212
5064
  return () => s.unsubscribe();
4213
5065
  });
4214
5066
  onUpdated(() => {
4215
5067
  const el = scrollRef.current;
4216
- updateShowShadow(draft => {
4217
- draft.leftEnd = el.scrollLeft === 0;
4218
- draft.rightEnd = el.scrollLeft === el.scrollWidth - el.offsetWidth;
5068
+ setTimeout(() => {
5069
+ updateShowShadow(draft => {
5070
+ draft.leftEnd = el.scrollLeft === 0;
5071
+ draft.rightEnd = el.scrollLeft === el.scrollWidth - el.offsetWidth;
5072
+ });
4219
5073
  });
4220
5074
  });
4221
5075
  return withScopedCSS(scopedId$3, () => {
4222
- return jsx("div", { ref: [scrollRef, props.scrollRef], class: ['scroll-container', {
5076
+ return jsx("div", { ref: [scrollRef], class: ['scroll-container', {
4223
5077
  'left-end': showShadow().leftEnd,
4224
5078
  'right-end': showShadow().rightEnd,
4225
5079
  'active': props.isFocus(),
4226
5080
  // 'hide-selection': isSelectColumn()
4227
5081
  }], onScroll: ev => {
4228
- tableService.onScroll.next(ev.target.scrollLeft);
5082
+ setTimeout(() => {
5083
+ tableService.onScroll.next(ev.target.scrollLeft);
5084
+ }, 30);
4229
5085
  }, children: props.children });
4230
5086
  });
4231
5087
  }
4232
5088
 
4233
- var scopedId$2 = "vf-ef93c0";
5089
+ var scopedId$2 = "vf-aaece0";
4234
5090
 
4235
5091
  function LeftBar(props) {
4236
5092
  const editorService = inject(EditorService);
@@ -4430,9 +5286,9 @@ function SelectionMask(props) {
4430
5286
  updateStyles(draft => {
4431
5287
  draft.visible = true;
4432
5288
  draft.left = sum(state.layoutWidth.slice(0, selection.startColumn));
4433
- draft.top = sum(trs.slice(0, selection.startRow).map(i => i.offsetHeight)) + topCompensation;
5289
+ draft.top = trs[selection.startRow].offsetTop + topCompensation;
4434
5290
  draft.width = sum(state.layoutWidth.slice(selection.startColumn, selection.endColumn)) - 1 + 'px';
4435
- draft.height = sum(trs.slice(selection.startRow, selection.endRow).map(i => i.offsetHeight)) + heightCompensation + 'px';
5291
+ draft.height = trs[selection.endRow - 1].offsetTop + trs[selection.endRow - 1].offsetHeight + heightCompensation - draft.top + 'px';
4436
5292
  });
4437
5293
  }
4438
5294
  else {
@@ -4461,81 +5317,25 @@ function SelectionMask(props) {
4461
5317
  });
4462
5318
  }
4463
5319
 
5320
+ // import { SlotRender } from '../SlotRender'
4464
5321
  const TableComponentView = withAnnotation({
4465
5322
  providers: [TableService]
4466
5323
  }, function TableComponentView(props) {
4467
5324
  const adapter = inject(DomAdapter);
5325
+ const editorService = inject(EditorService);
4468
5326
  const isFocus = createSignal(false);
5327
+ const layoutWidth = createSignal(props.component.state.layoutWidth);
4469
5328
  const subscription = props.component.focus.subscribe(b => {
4470
5329
  isFocus.set(b);
5330
+ if (!b) {
5331
+ editorService.hideInlineToolbar = false;
5332
+ }
4471
5333
  });
4472
5334
  onUnmounted(() => {
4473
5335
  subscription.unsubscribe();
4474
5336
  });
4475
5337
  const tableRef = createRef();
4476
- const scrollRef = createRef();
4477
5338
  const isResizeColumn = createSignal(false);
4478
- const selection = inject(Selection);
4479
- const findPosition = (slot) => {
4480
- let cell = slot;
4481
- while ((cell === null || cell === void 0 ? void 0 : cell.parent) && cell.parent !== props.component) {
4482
- cell = cell.parentSlot;
4483
- }
4484
- if (cell) {
4485
- const rows = props.component.state.rows;
4486
- for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
4487
- const row = rows[rowIndex].cells;
4488
- for (let colIndex = 0; colIndex < row.length; colIndex++) {
4489
- const item = row[colIndex].slot;
4490
- if (item === cell) {
4491
- return {
4492
- rowIndex,
4493
- colIndex
4494
- };
4495
- }
4496
- }
4497
- }
4498
- }
4499
- return null;
4500
- };
4501
- onMounted(() => {
4502
- const sub = selection.onChange.subscribe(() => {
4503
- var _a;
4504
- if (selection.commonAncestorComponent !== props.component || selection.isCollapsed) {
4505
- props.component.tableSelection.set(null);
4506
- return;
4507
- }
4508
- const startPosition = findPosition(selection.startSlot);
4509
- const endPosition = findPosition(selection.endSlot);
4510
- if (startPosition && endPosition) {
4511
- if (startPosition.rowIndex === endPosition.rowIndex && startPosition.colIndex === endPosition.colIndex) {
4512
- if (selection.startSlot === selection.endSlot && selection.startOffset === 0 && selection.endOffset === ((_a = selection.startSlot) === null || _a === void 0 ? void 0 : _a.length)) {
4513
- props.component.tableSelection.set({
4514
- startColumn: startPosition.colIndex,
4515
- startRow: startPosition.rowIndex,
4516
- endColumn: endPosition.colIndex + 1,
4517
- endRow: endPosition.rowIndex + 1
4518
- });
4519
- return;
4520
- }
4521
- props.component.tableSelection.set(null);
4522
- return;
4523
- }
4524
- const [startColumn, endColumn] = [startPosition.colIndex, endPosition.colIndex].sort((a, b) => a - b);
4525
- const [startRow, endRow] = [startPosition.rowIndex, endPosition.rowIndex].sort((a, b) => a - b);
4526
- props.component.tableSelection.set({
4527
- startColumn,
4528
- startRow,
4529
- endColumn: endColumn + 1,
4530
- endRow: endRow + 1
4531
- });
4532
- }
4533
- else {
4534
- props.component.tableSelection.set(null);
4535
- }
4536
- });
4537
- return () => sub.unsubscribe();
4538
- });
4539
5339
  const rowMapping = new WeakMap();
4540
5340
  const readonly = useReadonly();
4541
5341
  const output = useOutput();
@@ -4548,45 +5348,42 @@ const TableComponentView = withAnnotation({
4548
5348
  }
4549
5349
  rowMapping.set(row, Math.random());
4550
5350
  });
4551
- Promise.resolve().then(() => {
4552
- props.component.afterContentCheck();
4553
- });
4554
5351
  if (readonly() || output()) {
4555
- return (jsx("div", { class: "xnote-table", "data-component": props.component.name, "data-layout-width": state.layoutWidth, ref: props.rootRef, children: jsx("div", { class: "xnote-table-container", children: jsxs("table", { class: [
4556
- 'xnote-table-content',
4557
- {
4558
- 'hide-selection': props.component.tableSelection()
4559
- }
4560
- ], children: [jsx("colgroup", { children: state.layoutWidth.map(w => {
4561
- return jsx("col", { style: { width: w + 'px', minWidth: w + 'px' } });
4562
- }) }), jsx("tbody", { children: rows.map((row) => {
4563
- return (jsx("tr", { children: row.cells.map(cell => {
4564
- return adapter.slotRender(cell.slot, children => {
4565
- return createVNode('td', {
4566
- key: cell.slot.id
4567
- }, children);
4568
- }, readonly() || output());
4569
- }) }, rowMapping.get(row)));
4570
- }) })] }) }) }));
4571
- }
4572
- return (jsxs("div", { class: "xnote-table", "data-component": props.component.name, "data-layout-width": state.layoutWidth, ref: props.rootRef, children: [jsx(TopBar, { isFocus: isFocus, component: props.component, scrollRef: scrollRef }), jsx(LeftBar, { tableRef: tableRef, isFocus: isFocus, component: props.component }), jsx(Scroll, { scrollRef: scrollRef, isFocus: isFocus, children: jsxs("div", { class: "xnote-table-container", children: [jsxs("table", { ref: tableRef, class: [
4573
- 'xnote-table-content',
4574
- {
4575
- 'hide-selection': props.component.tableSelection()
4576
- }
4577
- ], children: [jsx("colgroup", { children: state.layoutWidth.map(w => {
4578
- return jsx("col", { style: { width: w + 'px', minWidth: w + 'px' } });
4579
- }) }), jsx("tbody", { children: rows.map((row) => {
4580
- return (jsx("tr", { children: row.cells.map(cell => {
4581
- return adapter.slotRender(cell.slot, children => {
4582
- return createVNode('td', {
4583
- key: cell.slot.id
4584
- }, children);
4585
- }, readonly() || output());
4586
- }) }, rowMapping.get(row)));
4587
- }) })] }), jsx(ResizeColumn, { tableRef: tableRef, component: props.component, onActiveStateChange: isActive => {
4588
- isResizeColumn.set(isActive);
4589
- } }), jsx(SelectionMask, { tableRef: tableRef, component: props.component })] }) }), jsx(ResizeRow, { component: props.component, tableRef: tableRef })] }));
5352
+ return (jsx("div", { class: "xnote-table", "data-component": props.component.name, "data-layout-width": state.layoutWidth, children: jsx("div", { class: "xnote-table-inner", ref: props.rootRef, children: jsx("div", { class: "xnote-table-container", children: jsxs("table", { class: [
5353
+ 'xnote-table-content',
5354
+ {
5355
+ 'hide-selection': props.component.tableSelection()
5356
+ }
5357
+ ], children: [jsx("colgroup", { children: layoutWidth().map(w => {
5358
+ return jsx("col", { style: { width: w + 'px', minWidth: w + 'px' } });
5359
+ }) }), jsx("tbody", { children: rows.map((row) => {
5360
+ return (jsx("tr", { children: row.cells.map(cell => {
5361
+ return adapter.slotRender(cell.slot, children => {
5362
+ return createVNode('td', {
5363
+ key: cell.slot.id
5364
+ }, children);
5365
+ }, readonly() || output());
5366
+ }) }, rowMapping.get(row)));
5367
+ }) })] }) }) }) }));
5368
+ }
5369
+ return (jsx("div", { class: "xnote-table", "data-component": props.component.name, "data-layout-width": `[${state.layoutWidth.join(',')}]`, children: jsxs("div", { class: "xnote-table-inner", ref: props.rootRef, children: [jsx(TopBar, { isFocus: isFocus, layoutWidth: layoutWidth, component: props.component }), jsx(LeftBar, { tableRef: tableRef, isFocus: isFocus, component: props.component }), jsx(Scroll, { isFocus: isFocus, children: jsxs("div", { class: "xnote-table-container", children: [jsxs("table", { ref: tableRef, class: [
5370
+ 'xnote-table-content',
5371
+ {
5372
+ 'hide-selection': props.component.tableSelection()
5373
+ }
5374
+ ], children: [jsx("colgroup", { children: layoutWidth().map(w => {
5375
+ return jsx("col", { style: { width: w + 'px', minWidth: w + 'px' } });
5376
+ }) }), jsx("tbody", { children: rows.map((row) => {
5377
+ return (jsx("tr", { children: row.cells.map(cell => {
5378
+ return adapter.slotRender(cell.slot, children => {
5379
+ return createVNode('td', {
5380
+ key: cell.slot.id
5381
+ }, children);
5382
+ }, readonly() || output());
5383
+ }) }, rowMapping.get(row)));
5384
+ }) })] }), jsx(ResizeColumn, { tableRef: tableRef, component: props.component, layoutWidth: layoutWidth, onActiveStateChange: isActive => {
5385
+ isResizeColumn.set(isActive);
5386
+ } }), jsx(SelectionMask, { tableRef: tableRef, component: props.component })] }) }), jsx(ResizeRow, { component: props.component, tableRef: tableRef })] }) }));
4590
5387
  };
4591
5388
  });
4592
5389
  const tableComponentLoader = {
@@ -4594,10 +5391,11 @@ const tableComponentLoader = {
4594
5391
  return element.dataset.component === TableComponent.componentName || element.tagName === 'TABLE';
4595
5392
  },
4596
5393
  read(element, textbus, slotParser) {
5394
+ let content = element;
4597
5395
  if (element.tagName === 'DIV') {
4598
- element = element.querySelector('.xnote-table-content');
5396
+ content = element.querySelector('.xnote-table-content');
4599
5397
  }
4600
- const { tHead, tBodies, tFoot } = element;
5398
+ const { tHead, tBodies, tFoot } = content;
4601
5399
  const headers = [];
4602
5400
  const bodies = [];
4603
5401
  if (tHead) {
@@ -4615,6 +5413,8 @@ const tableComponentLoader = {
4615
5413
  });
4616
5414
  const delta = slotParser(new Slot([
4617
5415
  ContentType.BlockComponent,
5416
+ ContentType.InlineComponent,
5417
+ ContentType.Text
4618
5418
  ]), cell).toDelta();
4619
5419
  const results = deltaToBlock(delta, textbus);
4620
5420
  results.forEach(i => {
@@ -4640,6 +5440,8 @@ const tableComponentLoader = {
4640
5440
  });
4641
5441
  const delta = slotParser(new Slot([
4642
5442
  ContentType.BlockComponent,
5443
+ ContentType.InlineComponent,
5444
+ ContentType.Text
4643
5445
  ]), cell).toDelta();
4644
5446
  const results = deltaToBlock(delta, textbus);
4645
5447
  results.forEach(i => {
@@ -4735,6 +5537,88 @@ function autoComplete(table) {
4735
5537
  });
4736
5538
  }
4737
5539
 
5540
+ function findFocusCell(table, slot) {
5541
+ var _a;
5542
+ while (slot) {
5543
+ if (table.slots.includes(slot)) {
5544
+ return slot;
5545
+ }
5546
+ slot = (_a = slot.parent) === null || _a === void 0 ? void 0 : _a.parent;
5547
+ }
5548
+ return null;
5549
+ }
5550
+ let TableSelectionAwarenessDelegate = class TableSelectionAwarenessDelegate extends CollaborateSelectionAwarenessDelegate {
5551
+ constructor(domAdapter, selection) {
5552
+ super();
5553
+ this.domAdapter = domAdapter;
5554
+ this.selection = selection;
5555
+ }
5556
+ getRects(abstractSelection) {
5557
+ const { focusSlot, anchorSlot } = abstractSelection;
5558
+ const focusPaths = this.selection.getPathsBySlot(focusSlot);
5559
+ const anchorPaths = this.selection.getPathsBySlot(anchorSlot);
5560
+ const focusIsStart = Selection.compareSelectionPaths(focusPaths, anchorPaths);
5561
+ let startSlot;
5562
+ let endSlot;
5563
+ if (focusIsStart) {
5564
+ startSlot = focusSlot;
5565
+ endSlot = anchorSlot;
5566
+ }
5567
+ else {
5568
+ startSlot = anchorSlot;
5569
+ endSlot = focusSlot;
5570
+ }
5571
+ const commonAncestorComponent = Selection.getCommonAncestorComponent(startSlot, endSlot);
5572
+ if (!(commonAncestorComponent instanceof TableComponent)) {
5573
+ return false;
5574
+ }
5575
+ const range = getSelectedRanges(commonAncestorComponent, findFocusCell(commonAncestorComponent, startSlot), findFocusCell(commonAncestorComponent, endSlot));
5576
+ const rows = commonAncestorComponent.state.rows;
5577
+ const startFocusSlot = rows[range.startRow].cells[range.startColumn].slot;
5578
+ const endFocusSlot = rows[range.endRow].cells[range.endColumn].slot;
5579
+ const renderer = this.domAdapter;
5580
+ const startRect = renderer.getNativeNodeBySlot(startFocusSlot).getBoundingClientRect();
5581
+ const endRect = renderer.getNativeNodeBySlot(endFocusSlot).getBoundingClientRect();
5582
+ return [{
5583
+ left: startRect.left,
5584
+ top: startRect.top,
5585
+ width: endRect.left + endRect.width - startRect.left,
5586
+ height: endRect.top + endRect.height - startRect.top
5587
+ }];
5588
+ }
5589
+ };
5590
+ TableSelectionAwarenessDelegate = __decorate([
5591
+ Injectable(),
5592
+ __metadata("design:paramtypes", [DomAdapter,
5593
+ Selection])
5594
+ ], TableSelectionAwarenessDelegate);
5595
+ function getSelectedRanges(component, startSlot, endSlot) {
5596
+ const p1 = finedPosition(component, startSlot);
5597
+ const p2 = finedPosition(component, endSlot);
5598
+ return {
5599
+ startRow: Math.min(p1.rowIndex, p2.rowIndex),
5600
+ endRow: Math.max(p1.rowIndex, p2.rowIndex),
5601
+ startColumn: Math.min(p1.columnIndex, p2.columnIndex),
5602
+ endColumn: Math.max(p1.columnIndex, p2.columnIndex)
5603
+ };
5604
+ }
5605
+ function finedPosition(component, slot) {
5606
+ const rows = component.state.rows;
5607
+ for (let i = 0; i < rows.length; i++) {
5608
+ const row = rows[i];
5609
+ for (let j = 0; j < row.cells.length; j++) {
5610
+ const cell = row.cells[j].slot;
5611
+ if (cell === slot) {
5612
+ return {
5613
+ rowIndex: i,
5614
+ columnIndex: j
5615
+ };
5616
+ }
5617
+ }
5618
+ }
5619
+ return null;
5620
+ }
5621
+
4738
5622
  class Editor extends Textbus {
4739
5623
  constructor(editorConfig = {}) {
4740
5624
  const adapter = new ViewflyAdapter({
@@ -4747,13 +5631,15 @@ class Editor extends Textbus {
4747
5631
  [HighlightBoxComponent.componentName]: HighlightBoxView,
4748
5632
  [ListComponent.componentName]: ListComponentView,
4749
5633
  [ImageComponent.componentName]: ImageView,
4750
- [VideoComponent.componentName]: VideoView
5634
+ [VideoComponent.componentName]: VideoView,
5635
+ [AtComponent.componentName]: AtComponentView,
5636
+ [KatexComponent.componentName]: KatexComponentView,
4751
5637
  }, (host, root, injector) => {
4752
5638
  const appInjector = new ReflectiveInjector(injector, [{
4753
5639
  provide: OutputInjectionToken,
4754
5640
  useValue: false
4755
5641
  }]);
4756
- const app = createApp(root, {
5642
+ const app = createApp(jsxs(Fragment, { children: [root, jsx(LinkJump, {})] }), {
4757
5643
  context: appInjector
4758
5644
  }).mount(host);
4759
5645
  return () => {
@@ -4762,16 +5648,18 @@ class Editor extends Textbus {
4762
5648
  });
4763
5649
  const browserModule = new BrowserModule(Object.assign({ renderTo: () => {
4764
5650
  return this.host;
4765
- }, adapter, componentLoaders: [
5651
+ }, useContentEditable: isMobileBrowser(), adapter, componentLoaders: [
5652
+ atComponentLoader,
4766
5653
  sourceCodeComponentLoader,
5654
+ listComponentLoader,
4767
5655
  tableComponentLoader,
4768
5656
  imageComponentLoader,
4769
- videoComponentLoader,
4770
5657
  highlightBoxComponentLoader,
4771
5658
  blockquoteComponentLoader,
4772
- paragraphComponentLoader,
5659
+ videoComponentLoader,
4773
5660
  todolistComponentLoader,
4774
- listComponentLoader,
5661
+ katexComponentLoader,
5662
+ paragraphComponentLoader,
4775
5663
  ], formatLoaders: [
4776
5664
  backgroundColorFormatLoader,
4777
5665
  boldFormatLoader,
@@ -4791,6 +5679,10 @@ class Editor extends Textbus {
4791
5679
  const modules = [browserModule];
4792
5680
  if (editorConfig.collaborateConfig) {
4793
5681
  modules.push(new CollaborateModule(editorConfig.collaborateConfig));
5682
+ browserModule.providers.push({
5683
+ provide: CollaborateSelectionAwarenessDelegate,
5684
+ useClass: TableSelectionAwarenessDelegate
5685
+ });
4794
5686
  }
4795
5687
  const vDomAdapter = new ViewflyVDomAdapter({
4796
5688
  [ParagraphComponent.componentName]: ParagraphView,
@@ -4802,7 +5694,9 @@ class Editor extends Textbus {
4802
5694
  [HighlightBoxComponent.componentName]: HighlightBoxView,
4803
5695
  [ListComponent.componentName]: ListComponentView,
4804
5696
  [ImageComponent.componentName]: ImageView,
4805
- [VideoComponent.componentName]: VideoView
5697
+ [VideoComponent.componentName]: VideoView,
5698
+ [AtComponent.componentName]: AtComponentView,
5699
+ [KatexComponent.componentName]: KatexComponentView
4806
5700
  }, (host, root, injector) => {
4807
5701
  const appInjector = new ReflectiveInjector(injector, [{
4808
5702
  provide: OutputInjectionToken,
@@ -4831,7 +5725,9 @@ class Editor extends Textbus {
4831
5725
  TableComponent,
4832
5726
  HighlightBoxComponent,
4833
5727
  ListComponent,
4834
- VideoComponent
5728
+ VideoComponent,
5729
+ AtComponent,
5730
+ KatexComponent
4835
5731
  ], formatters: [
4836
5732
  backgroundColorFormatter,
4837
5733
  boldFormatter,
@@ -4859,6 +5755,9 @@ class Editor extends Textbus {
4859
5755
  registerHeadingShortcut(textbus);
4860
5756
  registerTextAlignShortcut(textbus);
4861
5757
  registerTextIndentShortcut(textbus);
5758
+ registerAtShortcut(textbus);
5759
+ registerListShortcut(textbus);
5760
+ registerBlockquoteShortcut(textbus);
4862
5761
  } }, editorConfig));
4863
5762
  this.editorConfig = editorConfig;
4864
5763
  this.translator = new OutputTranslator();
@@ -4871,9 +5770,22 @@ class Editor extends Textbus {
4871
5770
  if (config.content) {
4872
5771
  const parser = this.get(Parser);
4873
5772
  const doc = parser.parseDoc(config.content, rootComponentLoader);
4874
- rootComp = doc instanceof Component ? doc : new RootComponent(this, {
4875
- content: doc
4876
- });
5773
+ if (doc instanceof Component) {
5774
+ rootComp = doc;
5775
+ }
5776
+ else {
5777
+ const content = new Slot([
5778
+ ContentType.BlockComponent
5779
+ ]);
5780
+ if (doc instanceof Slot) {
5781
+ deltaToBlock(doc.toDelta(), this).forEach(i => {
5782
+ content.insert(i);
5783
+ });
5784
+ }
5785
+ rootComp = new RootComponent(this, {
5786
+ content
5787
+ });
5788
+ }
4877
5789
  }
4878
5790
  else {
4879
5791
  rootComp = new RootComponent(this, {
@@ -4887,4 +5799,4 @@ class Editor extends Textbus {
4887
5799
  }
4888
5800
  }
4889
5801
 
4890
- export { AttrTool, BlockTool, BlockquoteComponent, BlockquoteView, BoldTool, Button, CodeTool, ColorTool, ComponentToolbar, Divider, DragResize, Dropdown, DropdownContextService, DropdownMenuPortal, DropdownService, Editor, EditorService, FontFamilyTool, FontSizeTool, HighlightBoxComponent, HighlightBoxView, ImageComponent, ImageView, InsertTool, ItalicTool, LeftToolbar, LeftToolbarPlugin, LinkTool, ListComponent, ListComponentView, Matcher, MenuItem, OutputInjectionToken, ParagraphComponent, ParagraphView, Popup, RefreshService, RootComponent, RootView, SourceCodeComponent, SourceCodeView, StrikeThroughTool, TableComponent, TableComponentView, TodolistComponent, TodolistView, Toolbar, ToolbarItem, ToolbarPlugin, UnderlineTool, VideoComponent, VideoView, autoComplete, backgroundColorFormatLoader, backgroundColorFormatter, blockquoteComponentLoader, boldFormatLoader, boldFormatter, codeFormatLoader, codeFormatter, colorFormatLoader, colorFormatter, deltaToBlock, fontFamilyFormatLoader, fontFamilyFormatter, fontSizeFormatLoader, fontSizeFormatter, headingAttr, headingAttrLoader, highlightBoxComponentLoader, imageComponentLoader, isSupportFont, italicFormatLoader, italicFormatter, languageList, linkFormatLoader, linkFormatter, listComponentLoader, paragraphComponentLoader, registerBoldShortcut, registerCodeShortcut, registerHeadingShortcut, registerItalicShortcut, registerStrikeThroughShortcut, registerTextAlignShortcut, registerTextIndentShortcut, registerUnderlineShortcut, rootComponentLoader, sourceCodeComponentLoader, sourceCodeThemes, strikeThroughFormatLoader, strikeThroughFormatter, tableComponentLoader, textAlignAttr, textAlignAttrLoader, textIndentAttr, textIndentAttrLoader, todolistComponentLoader, toggleBold, toggleCode, toggleItalic, toggleStrikeThrough, toggleUnderline, underlineFormatLoader, underlineFormatter, useActiveBlock, useBlockContent, useBlockTransform, useOutput, useReadonly, videoComponentLoader };
5802
+ export { AtComponent, AtComponentView, AttrTool, BlockTool, BlockquoteComponent, BlockquoteView, BoldTool, Button, CodeTool, ColorTool, ComponentToolbar, Divider, DragResize, Dropdown, DropdownContextService, DropdownMenuPortal, DropdownService, Editor, EditorService, FileUploader, FontFamilyTool, FontSizeTool, HighlightBoxComponent, HighlightBoxView, ImageComponent, ImageView, InsertTool, ItalicTool, KatexComponent, KatexComponentView, Keymap, LeftToolbar, LeftToolbarPlugin, LinkJump, LinkTool, ListComponent, ListComponentView, Matcher, MenuHeading, MenuItem, Organization, OutputInjectionToken, ParagraphComponent, ParagraphView, Popup, RefreshService, RootComponent, RootView, SourceCodeComponent, SourceCodeView, StrikeThroughTool, TableComponent, TableComponentView, TodolistComponent, TodolistView, Toolbar, ToolbarItem, ToolbarPlugin, UnderlineTool, VideoComponent, VideoView, atComponentLoader, autoComplete, backgroundColorFormatLoader, backgroundColorFormatter, blockquoteComponentLoader, boldFormatLoader, boldFormatter, codeFormatLoader, codeFormatter, colorFormatLoader, colorFormatter, deltaToBlock, fontFamilyFormatLoader, fontFamilyFormatter, fontSizeFormatLoader, fontSizeFormatter, headingAttr, headingAttrLoader, highlightBoxComponentLoader, imageComponentLoader, isSupportFont, italicFormatLoader, italicFormatter, katexComponentLoader, languageList, linkFormatLoader, linkFormatter, listComponentLoader, paragraphComponentLoader, registerAtShortcut, registerBlockquoteShortcut, registerBoldShortcut, registerCodeShortcut, registerHeadingShortcut, registerItalicShortcut, registerListShortcut, registerStrikeThroughShortcut, registerTextAlignShortcut, registerTextIndentShortcut, registerUnderlineShortcut, rootComponentLoader, sourceCodeComponentLoader, sourceCodeThemes, strikeThroughFormatLoader, strikeThroughFormatter, tableComponentLoader, textAlignAttr, textAlignAttrLoader, textIndentAttr, textIndentAttrLoader, toBlockquote, toList, todolistComponentLoader, toggleBold, toggleCode, toggleItalic, toggleStrikeThrough, toggleUnderline, underlineFormatLoader, underlineFormatter, useActiveBlock, useBlockContent, useBlockTransform, useOutput, useReadonly, videoComponentLoader };