@textbus/xnote 0.1.1 → 0.2.0

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 (53) hide show
  1. package/bundles/components/dropdown/dropdown-menu.d.ts +2 -1
  2. package/bundles/components/dropdown/dropdown.d.ts +1 -0
  3. package/bundles/fonts/textbus.svg +4 -3
  4. package/bundles/fonts/textbus.ttf +0 -0
  5. package/bundles/fonts/textbus.woff +0 -0
  6. package/bundles/index.css +2 -2
  7. package/bundles/index.esm.css +2 -2
  8. package/bundles/index.esm.js +1243 -717
  9. package/bundles/index.js +1257 -715
  10. package/bundles/plugins/_api.d.ts +8 -4
  11. package/bundles/plugins/inline-toolbar/inline-toolbar.d.ts +4 -0
  12. package/bundles/plugins/inline-toolbar/inline-toolbar.plugin.d.ts +12 -0
  13. package/bundles/plugins/static-toolbar/static-toolbar.d.ts +4 -0
  14. package/bundles/plugins/static-toolbar/static-toolbar.plugin.d.ts +14 -0
  15. package/bundles/plugins/suspension-toolbar/suspension-toolbar.d.ts +4 -0
  16. package/bundles/plugins/suspension-toolbar/suspension-toolbar.plugin.d.ts +13 -0
  17. package/bundles/plugins/{_common → tools}/_api.d.ts +8 -0
  18. package/bundles/plugins/tools/_common/common-state.d.ts +1 -0
  19. package/bundles/plugins/tools/_common/split-line.d.ts +1 -0
  20. package/bundles/plugins/tools/_common/tool.service.d.ts +14 -0
  21. package/bundles/plugins/tools/clean-formats.tool.d.ts +1 -0
  22. package/bundles/plugins/{left-toolbar/insert-tool.d.ts → tools/insert-menu.d.ts} +1 -1
  23. package/bundles/plugins/tools/insert.tool.d.ts +1 -0
  24. package/bundles/plugins/tools/redo.tool.d.ts +1 -0
  25. package/bundles/plugins/tools/subscript.tool.d.ts +1 -0
  26. package/bundles/plugins/tools/superscript.tool.d.ts +1 -0
  27. package/bundles/plugins/tools/table/help.d.ts +5 -0
  28. package/bundles/plugins/tools/undo.tool.d.ts +1 -0
  29. package/bundles/textbus/components/step/step.component.d.ts +1 -0
  30. package/bundles/textbus/components/table/table.component.d.ts +1 -0
  31. package/bundles/textbus/components/timeline/timeline.component.d.ts +1 -0
  32. package/bundles/textbus/formatters/_api.d.ts +2 -0
  33. package/bundles/textbus/formatters/subscript.d.ts +4 -0
  34. package/bundles/textbus/formatters/superscript.d.ts +4 -0
  35. package/package.json +10 -10
  36. package/bundles/plugins/toolbar/toolbar.d.ts +0 -1
  37. package/bundles/plugins/toolbar/toolbar.plugin.d.ts +0 -7
  38. /package/bundles/plugins/{_common → tools}/attr.tool.d.ts +0 -0
  39. /package/bundles/plugins/{_common → tools}/block.tool.d.ts +0 -0
  40. /package/bundles/plugins/{_common → tools}/bold.tool.d.ts +0 -0
  41. /package/bundles/plugins/{_common → tools}/code.tool.d.ts +0 -0
  42. /package/bundles/plugins/{_common → tools}/color.tool.d.ts +0 -0
  43. /package/bundles/plugins/{_common → tools}/font-family.tool.d.ts +0 -0
  44. /package/bundles/plugins/{_common → tools}/font-size.tool.d.ts +0 -0
  45. /package/bundles/plugins/{_common → tools}/italic.tool.d.ts +0 -0
  46. /package/bundles/plugins/{_common → tools}/link.tool.d.ts +0 -0
  47. /package/bundles/plugins/{_common → tools}/strike-through.tool.d.ts +0 -0
  48. /package/bundles/plugins/{_common → tools}/table/_api.d.ts +0 -0
  49. /package/bundles/plugins/{_common → tools}/table/cell-align.tool.d.ts +0 -0
  50. /package/bundles/plugins/{_common → tools}/table/cell-background.tool.d.ts +0 -0
  51. /package/bundles/plugins/{_common → tools}/table/merge-cells.tool.d.ts +0 -0
  52. /package/bundles/plugins/{_common → tools}/table/split-cells.tool.d.ts +0 -0
  53. /package/bundles/plugins/{_common → tools}/underline.tool.d.ts +0 -0
@@ -1,9 +1,9 @@
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, getCurrentInstance, createRef, withAnnotation, onUpdated, onMounted, InjectionToken, ReflectiveInjector, createDynamicRef, jsx as jsx$1, viewfly, Fragment as Fragment$1, watch } from '@viewfly/core';
4
- import { Subject, fromEvent, Selection, Subscription, Attribute, Keyboard, Commander, Controller, useContext, onBreak, onContentInsert, ContentType, merge, createVNode, Slot, Component, Registry, Query, QueryStateType, Formatter, BehaviorSubject, onSlotApplyFormat, onSlotSetAttribute, onPaste, onFocus, onBlur, useDynamicShortcut, VTextNode, onFocusIn, onFocusOut, onDestroy, onGetRanges, onParentSlotUpdated, Textbus, RootComponentRef, filter, map, distinctUntilChanged, sampleTime, debounceTime, throttleTime, delay, onContentInserted, onContentDeleted, switchMap, fromPromise, onCompositionStart } from '@textbus/core';
3
+ import { Injectable, InjectFlags, Injector, inject, createSignal, onUnmounted, getCurrentInstance, createRef, InjectionToken, withAnnotation, onUpdated, onMounted, ReflectiveInjector, createDynamicRef, jsx as jsx$1, viewfly, Fragment as Fragment$1, Context, watch } from '@viewfly/core';
4
+ import { Subject, fromEvent, Selection, Subscription, Attribute, Keyboard, Commander, Controller, useContext, onBreak, onContentInsert, ContentType, merge, createVNode, Slot, Component, Registry, Query, QueryStateType, Formatter, BehaviorSubject, onSlotApplyFormat, onSlotSetAttribute, onPaste, onFocus, onBlur, useDynamicShortcut, VTextNode, onFocusIn, onFocusOut, onDestroy, onGetRanges, onParentSlotUpdated, Textbus, History, RootComponentRef, filter, map, distinctUntilChanged, sampleTime, debounceTime, throttleTime, delay, tap, onContentInserted, onContentDeleted, switchMap, fromPromise, onCompositionStart } from '@textbus/core';
5
5
  import { normalizeHex, hex2Hsl, hex2Rgb, hex2Hsv, hsl2Hex, hsl2Hsv, hsl2Rgb, rgb2Hsl, rgb2Hex, rgb2Hsv, hsv2Hex, hsv2Hsl, hsv2Rgb, any2Hsl, parseCss } from '@tanbo/color';
6
- import { VIEW_CONTAINER, isMac, DomAdapter, Input, SelectionBridge, BrowserModule, VIEW_DOCUMENT, CollaborateSelectionAwarenessDelegate, isMobileBrowser, CollaborateCursor, Parser } from '@textbus/platform-browser';
6
+ import { VIEW_CONTAINER, isMac, DomAdapter, Input, BrowserModule, SelectionBridge, VIEW_DOCUMENT, CollaborateSelectionAwarenessDelegate, isMobileBrowser, CollaborateCursor, Parser } from '@textbus/platform-browser';
7
7
  import { createPortal, createApp, DomRenderer, HTMLRenderer, OutputTranslator } from '@viewfly/platform-browser';
8
8
  import { useProduce } from '@viewfly/hooks';
9
9
  import highlightjs from 'highlight.js';
@@ -12,7 +12,7 @@ import Katex from 'katex';
12
12
  import { ViewflyAdapter, ViewflyVDomAdapter } from '@textbus/adapter-viewfly';
13
13
  import { MessageBus, CollaborateModule } from '@textbus/collaborate';
14
14
 
15
- var scopedId$o = "vf-d94b56";
15
+ var scopedId$r = "vf-7d288d";
16
16
 
17
17
  /******************************************************************************
18
18
  Copyright (c) Microsoft Corporation.
@@ -145,7 +145,7 @@ function Button(props) {
145
145
  subscription.unsubscribe();
146
146
  });
147
147
  }
148
- return withScopedCSS(scopedId$o, () => {
148
+ return withScopedCSS(scopedId$r, () => {
149
149
  return (jsxs("button", Object.assign({ type: "button" }, props, { class: [
150
150
  'btn',
151
151
  {
@@ -157,7 +157,7 @@ function Button(props) {
157
157
  });
158
158
  }
159
159
 
160
- var scopedId$n = "vf-d552b9";
160
+ var scopedId$q = "vf-d552b9";
161
161
 
162
162
  class Picker {
163
163
  set hex(color) {
@@ -446,7 +446,7 @@ function ColorPicker(props) {
446
446
  props.onSelected(picker);
447
447
  addRecentColor();
448
448
  }
449
- return withScopedCSS(scopedId$n, () => {
449
+ return withScopedCSS(scopedId$q, () => {
450
450
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
451
451
  return (jsxs("div", { onMousedown: ev => {
452
452
  ev.stopPropagation();
@@ -497,10 +497,10 @@ function ColorPicker(props) {
497
497
  });
498
498
  }
499
499
 
500
- var scopedId$m = "vf-ac7e8d";
500
+ var scopedId$p = "vf-ac7e8d";
501
501
 
502
502
  function ComponentToolbar(props) {
503
- return withScopedCSS(scopedId$m, () => {
503
+ return withScopedCSS(scopedId$p, () => {
504
504
  return (jsx("div", { class: "component-toolbar", style: props.style, children: jsx("div", { class: [
505
505
  'toolbar',
506
506
  {
@@ -510,15 +510,15 @@ function ComponentToolbar(props) {
510
510
  });
511
511
  }
512
512
 
513
- var scopedId$l = "vf-ede279";
513
+ var scopedId$o = "vf-ede279";
514
514
 
515
515
  function Divider() {
516
- return withScopedCSS(scopedId$l, () => {
516
+ return withScopedCSS(scopedId$o, () => {
517
517
  return jsx("div", { class: "divider" });
518
518
  });
519
519
  }
520
520
 
521
- var scopedId$k = "vf-d91ad6";
521
+ var scopedId$n = "vf-d91ad6";
522
522
 
523
523
  function DragResize(props) {
524
524
  const isShow = createSignal(false);
@@ -627,24 +627,25 @@ function DragResize(props) {
627
627
  });
628
628
  }
629
629
  const sizeText = createSignal(`${component.state.width}*${component.state.height}`);
630
- return withScopedCSS(scopedId$k, () => {
630
+ return withScopedCSS(scopedId$n, () => {
631
631
  return (jsxs("div", { class: "drag-resize", onClick: selectComponent, children: [jsx("div", { class: "container", ref: ref, children: props.children }), jsxs("div", { class: ['resize-tool', {
632
632
  active: isShow()
633
633
  }], 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" })] })] })] }));
634
634
  });
635
635
  }
636
636
 
637
- var scopedId$j = "vf-a99c5e";
637
+ var scopedId$m = "vf-a99c5e";
638
638
 
639
- var scopedId$i = "vf-8a05e9";
639
+ var scopedId$l = "vf-8a05e9";
640
640
 
641
+ const DropdownMenuContainer = new InjectionToken('DropdownMenuContainer');
641
642
  const DropdownMenuPortal = withAnnotation({
642
643
  providers: [
643
644
  DropdownService
644
645
  ]
645
646
  }, function DropdownMenuPortal(props) {
646
647
  const dropdownContextService = inject(DropdownContextService);
647
- const container = inject(VIEW_CONTAINER);
648
+ const container = inject(DropdownMenuContainer, inject(VIEW_CONTAINER));
648
649
  const menuRef = createRef();
649
650
  let timer = null;
650
651
  const delay = 10;
@@ -731,8 +732,11 @@ const DropdownMenuPortal = withAnnotation({
731
732
  dropdownContextService.canHide = true;
732
733
  dropdownContextService.hide();
733
734
  }
734
- return createPortal(withScopedCSS(scopedId$i, () => {
735
- return (jsx("div", { onMouseenter: onEnter, onMouseleave: onLeave, ref: menuRef, style: {
735
+ function stopPropagation(ev) {
736
+ ev.stopPropagation();
737
+ }
738
+ return createPortal(withScopedCSS(scopedId$l, () => {
739
+ return (jsx("div", { onMouseenter: onEnter, onMousedown: stopPropagation, onMouseleave: onLeave, ref: menuRef, style: {
736
740
  width: props.width
737
741
  }, class: "dropdown-menu", children: jsx("div", { class: "dropdown-menu-content", style: {
738
742
  padding: props.padding
@@ -746,6 +750,9 @@ const Dropdown = withAnnotation({
746
750
  const isShow = createSignal(false);
747
751
  const dropdownContextService = inject(DropdownContextService);
748
752
  const toggle = () => {
753
+ if (props.disabled) {
754
+ return;
755
+ }
749
756
  if (dropdownContextService.isOpen) {
750
757
  dropdownContextService.hide(false);
751
758
  }
@@ -775,11 +782,17 @@ const Dropdown = withAnnotation({
775
782
  let leaveSub;
776
783
  const bindLeave = function () {
777
784
  leaveSub = fromEvent(dropdownRef.current, 'mouseleave').subscribe(() => {
785
+ if (props.disabled) {
786
+ return;
787
+ }
778
788
  dropdownContextService.hide();
779
789
  });
780
790
  };
781
791
  bindLeave();
782
792
  subscription.add(fromEvent(dropdownRef.current, 'mouseenter').subscribe(() => {
793
+ if (props.disabled) {
794
+ return;
795
+ }
783
796
  if (leaveSub) {
784
797
  leaveSub.unsubscribe();
785
798
  }
@@ -799,7 +812,7 @@ const Dropdown = withAnnotation({
799
812
  dropdownContextService.hide(false);
800
813
  }
801
814
  },
802
- $render: withScopedCSS(scopedId$j, () => {
815
+ $render: withScopedCSS(scopedId$m, () => {
803
816
  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() &&
804
817
  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) ?
805
818
  props.menu.map(menu => {
@@ -816,7 +829,7 @@ const Dropdown = withAnnotation({
816
829
  };
817
830
  });
818
831
 
819
- var scopedId$h = "vf-c32a7b";
832
+ var scopedId$k = "vf-c32a7b";
820
833
 
821
834
  function Keymap(props) {
822
835
  const arr = [];
@@ -850,20 +863,20 @@ function Keymap(props) {
850
863
  arr.push(jsx("span", { children: keymap.key }));
851
864
  }
852
865
  }
853
- return withScopedCSS(scopedId$h, () => {
866
+ return withScopedCSS(scopedId$k, () => {
854
867
  return (jsx("span", { class: "keymap", children: arr }));
855
868
  });
856
869
  }
857
870
 
858
- var scopedId$g = "vf-acaa5f";
871
+ var scopedId$j = "vf-acaa5f";
859
872
 
860
873
  function MenuHeading(props) {
861
- return withScopedCSS(scopedId$g, () => {
874
+ return withScopedCSS(scopedId$j, () => {
862
875
  return (jsx("div", { class: "menu-heading", children: props.children }));
863
876
  });
864
877
  }
865
878
 
866
- var scopedId$f = "vf-c3b9dc";
879
+ var scopedId$i = "vf-c3b9dc";
867
880
 
868
881
  function MenuItem(props) {
869
882
  const dropdownContextService = inject(DropdownContextService, null);
@@ -883,7 +896,7 @@ function MenuItem(props) {
883
896
  }
884
897
  (_a = props.onClick) === null || _a === void 0 ? void 0 : _a.call(props, props.value);
885
898
  }
886
- return withScopedCSS(scopedId$f, () => {
899
+ return withScopedCSS(scopedId$i, () => {
887
900
  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 ?
888
901
  jsx("div", { class: "arrow", children: jsx("span", { class: "xnote-icon-arrow-right" }) }) :
889
902
  jsx("div", { class: [
@@ -893,11 +906,11 @@ function MenuItem(props) {
893
906
  });
894
907
  }
895
908
 
896
- var scopedId$e = "vf-a23c47";
909
+ var scopedId$h = "vf-a23c47";
897
910
 
898
911
  function Popup(props) {
899
912
  const host = inject(VIEW_CONTAINER);
900
- return createPortal(withScopedCSS(scopedId$e, () => {
913
+ return createPortal(withScopedCSS(scopedId$h, () => {
901
914
  return (jsx("div", { class: "popup", style: {
902
915
  left: props.left + 'px',
903
916
  top: props.top + 'px'
@@ -905,15 +918,15 @@ function Popup(props) {
905
918
  }), host);
906
919
  }
907
920
 
908
- var scopedId$d = "vf-216815";
921
+ var scopedId$g = "vf-cd4d99";
909
922
 
910
923
  function ToolbarItem(props) {
911
- return withScopedCSS(scopedId$d, () => {
924
+ return withScopedCSS(scopedId$g, () => {
912
925
  return (jsx("div", { class: "toolbar-item", children: props.children }));
913
926
  });
914
927
  }
915
928
 
916
- var scopedId$c = "vf-2a8a65";
929
+ var scopedId$f = "vf-2a8a65";
917
930
 
918
931
  let RefreshService = class RefreshService {
919
932
  constructor() {
@@ -1399,6 +1412,14 @@ class TimelineComponent extends Component {
1399
1412
  getSlots() {
1400
1413
  return this.state.items.map(i => i.slot);
1401
1414
  }
1415
+ removeSlot(slot) {
1416
+ const index = this.state.items.findIndex(i => i.slot === slot);
1417
+ if (index >= 0) {
1418
+ this.state.items.splice(index, 1);
1419
+ return true;
1420
+ }
1421
+ return false;
1422
+ }
1402
1423
  }
1403
1424
  TimelineComponent.componentName = 'TimelineComponent';
1404
1425
  TimelineComponent.type = ContentType.BlockComponent;
@@ -1433,6 +1454,17 @@ class StepComponent extends Component {
1433
1454
  getSlots() {
1434
1455
  return this.state.items.map(i => i.slot);
1435
1456
  }
1457
+ removeSlot(slot) {
1458
+ const index = this.state.items.findIndex(i => i.slot === slot);
1459
+ if (index >= 0) {
1460
+ if (index === this.state.step) {
1461
+ this.state.step--;
1462
+ }
1463
+ this.state.items.splice(index, 1);
1464
+ return true;
1465
+ }
1466
+ return false;
1467
+ }
1436
1468
  }
1437
1469
  StepComponent.componentName = 'StepComponent';
1438
1470
  StepComponent.type = ContentType.BlockComponent;
@@ -2195,6 +2227,37 @@ function registerTextIndentShortcut(textbus) {
2195
2227
  });
2196
2228
  }
2197
2229
 
2230
+ let ToolService = class ToolService {
2231
+ constructor(selection, controller) {
2232
+ this.selection = selection;
2233
+ this.controller = controller;
2234
+ const [state, updateState] = useProduce({
2235
+ inSourceCode: false,
2236
+ readonly: controller.readonly
2237
+ });
2238
+ this.state = state;
2239
+ this.sub = merge(selection.onChange, controller.onReadonlyStateChange).subscribe(() => {
2240
+ updateState(draft => {
2241
+ draft.readonly = controller.readonly;
2242
+ draft.inSourceCode = selection.commonAncestorComponent instanceof SourceCodeComponent;
2243
+ });
2244
+ });
2245
+ }
2246
+ destroy() {
2247
+ this.sub.unsubscribe();
2248
+ }
2249
+ };
2250
+ ToolService = __decorate([
2251
+ Injectable(),
2252
+ __metadata("design:paramtypes", [Selection,
2253
+ Controller])
2254
+ ], ToolService);
2255
+
2256
+ function useCommonState() {
2257
+ const toolService = inject(ToolService);
2258
+ return toolService.state;
2259
+ }
2260
+
2198
2261
  function AttrTool(props) {
2199
2262
  const commander = inject(Commander);
2200
2263
  const selection = inject(Selection);
@@ -2271,9 +2334,11 @@ function AttrTool(props) {
2271
2334
  break;
2272
2335
  }
2273
2336
  }
2274
- return withScopedCSS(scopedId$c, () => {
2337
+ const commonState = useCommonState();
2338
+ return withScopedCSS(scopedId$f, () => {
2275
2339
  const states = checkStates();
2276
- return (jsx(Dropdown, { width: 'auto', style: props.style, abreast: props.abreast, onCheck: updateAttr, trigger: 'hover', menu: [
2340
+ const b = commonState().inSourceCode || commonState().readonly;
2341
+ return (jsx(Dropdown, { disabled: b, width: 'auto', style: props.style, abreast: props.abreast, onCheck: updateAttr, trigger: 'hover', menu: [
2277
2342
  {
2278
2343
  label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-paragraph-left" }), desc: jsx(Keymap, { keymap: { key: 'L', modKey: true } }), checked: states.textAlign === 'left', children: "\u5DE6\u5BF9\u9F50" }),
2279
2344
  value: 't-l'
@@ -2296,7 +2361,7 @@ function AttrTool(props) {
2296
2361
  label: jsx(MenuItem, { desc: jsx(Keymap, { keymap: { key: 'Tab', shiftKey: true } }), icon: jsx("span", { class: "xnote-icon-indent-decrease" }), children: "\u51CF\u5C11\u7F29\u8FDB" }),
2297
2362
  value: 'i-'
2298
2363
  }
2299
- ], children: props.children || jsx(Button, { arrow: true, highlight: false, children: jsx("span", { class: `xnote-icon-paragraph-${states.textAlign || 'left'} icon` }) }) }));
2364
+ ], children: props.children || jsx(Button, { disabled: b, arrow: true, highlight: false, children: jsx("span", { class: `xnote-icon-paragraph-${states.textAlign || 'left'} icon` }) }) }));
2300
2365
  });
2301
2366
  }
2302
2367
 
@@ -2478,6 +2543,17 @@ class TableComponent extends Component {
2478
2543
  }
2479
2544
  }
2480
2545
  }
2546
+ splitCellBySlot(slot) {
2547
+ const slots = this.getNormalizedData();
2548
+ for (const item of slots) {
2549
+ for (const cell of item.cells) {
2550
+ if (cell.raw.slot === slot) {
2551
+ Reflect.deleteProperty(this.state.mergeConfig, cell.raw.id);
2552
+ return;
2553
+ }
2554
+ }
2555
+ }
2556
+ }
2481
2557
  getMaxRectangle(startSlot, endSlot) {
2482
2558
  let index1 = -1;
2483
2559
  let index2 = -1;
@@ -3549,7 +3625,8 @@ function useBlockTransform() {
3549
3625
  function BlockTool() {
3550
3626
  const checkStates = useActiveBlock();
3551
3627
  const transform = useBlockTransform();
3552
- return withScopedCSS(scopedId$c, () => {
3628
+ const commonState = useCommonState();
3629
+ return withScopedCSS(scopedId$f, () => {
3553
3630
  const states = checkStates();
3554
3631
  const types = [
3555
3632
  [states.paragraph, 'xnote-icon-pilcrow'],
@@ -3573,7 +3650,8 @@ function BlockTool() {
3573
3650
  break;
3574
3651
  }
3575
3652
  }
3576
- return (jsx(Dropdown, { width: 'auto', onCheck: transform, trigger: 'hover', menu: [
3653
+ const b = commonState().inSourceCode || commonState().readonly;
3654
+ return (jsx(Dropdown, { disabled: b, width: 'auto', onCheck: transform, trigger: 'hover', menu: [
3577
3655
  {
3578
3656
  label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-pilcrow" }), desc: jsx(Keymap, { keymap: {
3579
3657
  modKey: true,
@@ -3638,7 +3716,7 @@ function BlockTool() {
3638
3716
  label: jsx(MenuItem, { icon: jsx("span", { class: "xnote-icon-hightlight-box" }), checked: states.highlightBox, children: "\u9AD8\u4EAE\u5757" }),
3639
3717
  value: 'highlightBox'
3640
3718
  }
3641
- ], children: jsx(Button, { arrow: true, highlight: false, children: jsx("span", { class: currentType }) }) }));
3719
+ ], children: jsx(Button, { disabled: b, arrow: true, highlight: false, children: jsx("span", { class: currentType }) }) }));
3642
3720
  });
3643
3721
  }
3644
3722
 
@@ -3816,6 +3894,40 @@ const linkFormatLoader = {
3816
3894
  }
3817
3895
  };
3818
3896
 
3897
+ const subscriptFormatter = new Formatter('sub', {
3898
+ render(children) {
3899
+ return createVNode('sub', null, children);
3900
+ }
3901
+ });
3902
+ const subscriptFormatLoader = {
3903
+ match(element) {
3904
+ return element.tagName === 'SUB';
3905
+ },
3906
+ read() {
3907
+ return {
3908
+ formatter: subscriptFormatter,
3909
+ value: true
3910
+ };
3911
+ }
3912
+ };
3913
+
3914
+ const superscriptFormatter = new Formatter('super', {
3915
+ render(children) {
3916
+ return createVNode('sup', null, children);
3917
+ }
3918
+ });
3919
+ const superscriptFormatLoader = {
3920
+ match(element) {
3921
+ return element.tagName === 'SUP';
3922
+ },
3923
+ read() {
3924
+ return {
3925
+ formatter: superscriptFormatter,
3926
+ value: true
3927
+ };
3928
+ }
3929
+ };
3930
+
3819
3931
  const underlineFormatter = new Formatter('underline', {
3820
3932
  columned: true,
3821
3933
  render(children) {
@@ -3865,9 +3977,9 @@ function BoldTool() {
3865
3977
  const query = inject(Query);
3866
3978
  const textbus = inject(Textbus);
3867
3979
  const refreshService = inject(RefreshService);
3980
+ const commonState = useCommonState();
3868
3981
  const [viewModel, update] = useProduce({
3869
3982
  highlight: false,
3870
- disabled: false,
3871
3983
  });
3872
3984
  function toggle() {
3873
3985
  toggleBold(textbus);
@@ -3883,7 +3995,20 @@ function BoldTool() {
3883
3995
  });
3884
3996
  return () => {
3885
3997
  const vm = viewModel();
3886
- return jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, onClick: toggle, children: jsx("span", { class: "xnote-icon-bold" }) });
3998
+ return jsx(Button, { highlight: vm.highlight, disabled: commonState().inSourceCode || commonState().readonly, onClick: toggle, children: jsx("span", { class: "xnote-icon-bold" }) });
3999
+ };
4000
+ }
4001
+
4002
+ function CleanFormatsTool() {
4003
+ const commonState = useCommonState();
4004
+ const commander = inject(Commander);
4005
+ function clean() {
4006
+ commander.cleanFormats([
4007
+ linkFormatter
4008
+ ]);
4009
+ }
4010
+ return () => {
4011
+ return (jsx(Button, { disabled: commonState().inSourceCode || commonState().readonly, onClick: clean, children: jsx("span", { class: "xnote-icon-clear-formatting" }) }));
3887
4012
  };
3888
4013
  }
3889
4014
 
@@ -3891,9 +4016,9 @@ function CodeTool() {
3891
4016
  const query = inject(Query);
3892
4017
  const refreshService = inject(RefreshService);
3893
4018
  const textbus = inject(Textbus);
4019
+ const commonState = useCommonState();
3894
4020
  const [viewModel, update] = useProduce({
3895
4021
  highlight: false,
3896
- disabled: false,
3897
4022
  });
3898
4023
  function toggle() {
3899
4024
  toggleCode(textbus);
@@ -3909,11 +4034,11 @@ function CodeTool() {
3909
4034
  });
3910
4035
  return () => {
3911
4036
  const vm = viewModel();
3912
- return jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, onClick: toggle, children: jsx("span", { class: "xnote-icon-code" }) });
4037
+ return jsx(Button, { highlight: vm.highlight, disabled: commonState().inSourceCode || commonState().readonly, onClick: toggle, children: jsx("span", { class: "xnote-icon-code" }) });
3913
4038
  };
3914
4039
  }
3915
4040
 
3916
- var scopedId$b = "vf-accb31";
4041
+ var scopedId$e = "vf-accb31";
3917
4042
 
3918
4043
  function ColorTool(props) {
3919
4044
  const query = inject(Query);
@@ -3924,7 +4049,6 @@ function ColorTool(props) {
3924
4049
  const backgroundColor = createSignal('');
3925
4050
  const [viewModel] = useProduce({
3926
4051
  highlight: false,
3927
- disabled: false,
3928
4052
  });
3929
4053
  function updateCheckState() {
3930
4054
  if (!props.slot && !selection.isSelected) {
@@ -3976,9 +4100,10 @@ function ColorTool(props) {
3976
4100
  '#90a0e5',
3977
4101
  '#c596e0',
3978
4102
  ];
3979
- return withScopedCSS(scopedId$b, () => {
4103
+ const commonState = useCommonState();
4104
+ return withScopedCSS(scopedId$e, () => {
3980
4105
  const vm = viewModel();
3981
- 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: {
4106
+ return (jsx(Dropdown, { disabled: commonState().readonly || commonState().inSourceCode, 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: {
3982
4107
  'no-background': true,
3983
4108
  active: textColor() === ''
3984
4109
  }, onClick: () => {
@@ -4008,7 +4133,7 @@ function ColorTool(props) {
4008
4133
  (_a = props.applyBefore) === null || _a === void 0 ? void 0 : _a.call(props);
4009
4134
  commander.applyFormat(backgroundColorFormatter, c);
4010
4135
  }, style: { backgroundColor: c }, children: "A" });
4011
- })] })] }), children: props.children || jsx(Button, { highlight: vm.highlight, arrow: true, disabled: vm.disabled, children: jsx("span", { class: "background", children: jsx("span", { style: {
4136
+ })] })] }), children: props.children || jsx(Button, { highlight: vm.highlight, arrow: true, disabled: commonState().readonly || commonState().inSourceCode, children: jsx("span", { class: "background", children: jsx("span", { style: {
4012
4137
  backgroundColor: backgroundColor(),
4013
4138
  color: textColor()
4014
4139
  }, children: jsx("span", { class: "xnote-icon-color" }) }) }) }) }));
@@ -4108,16 +4233,18 @@ function FontFamilyTool() {
4108
4233
  onUnmounted(() => {
4109
4234
  subscription.unsubscribe();
4110
4235
  });
4236
+ const commonState = useCommonState();
4111
4237
  return () => {
4112
4238
  var _a;
4113
- return (jsx(Dropdown, { onCheck: check, menu: fontFamilyOptions.map(i => {
4239
+ const b = commonState().inSourceCode || commonState().readonly;
4240
+ return (jsx(Dropdown, { disabled: b, onCheck: check, menu: fontFamilyOptions.map(i => {
4114
4241
  const disabled = i.value ? !i.value.split(',').map(i => isSupportFont(i.trim())).some(v => v) : false;
4115
4242
  return {
4116
4243
  label: jsx(MenuItem, { disabled: disabled, checked: currentFontFamily() === i.value, children: i.label }),
4117
4244
  disabled,
4118
4245
  value: i.value,
4119
4246
  };
4120
- }), children: jsx(Button, { arrow: true, highlight: highlight(), children: ((_a = fontFamilyOptions.find(v => {
4247
+ }), children: jsx(Button, { disabled: b, arrow: true, highlight: highlight(), children: ((_a = fontFamilyOptions.find(v => {
4121
4248
  return v.value === currentFontFamily();
4122
4249
  })) === null || _a === void 0 ? void 0 : _a.label) || '默认' }) }));
4123
4250
  };
@@ -4162,776 +4289,1027 @@ function FontSizeTool() {
4162
4289
  onUnmounted(() => {
4163
4290
  subscription.unsubscribe();
4164
4291
  });
4292
+ const commonState = useCommonState();
4165
4293
  return () => {
4166
- return (jsx(Dropdown, { onCheck: check, menu: fontSizeOptions.map(i => {
4294
+ const b = commonState().inSourceCode || commonState().readonly;
4295
+ return (jsx(Dropdown, { disabled: b, onCheck: check, menu: fontSizeOptions.map(i => {
4167
4296
  return {
4168
4297
  label: jsx(MenuItem, { checked: currentFontSize() === i, children: i || '默认' }),
4169
4298
  value: i
4170
4299
  };
4171
- }), children: jsxs(Button, { arrow: true, highlight: highlight(), children: [jsx("span", { class: "xnote-icon-font-size" }), jsx("span", { children: currentFontSize() || '默认' })] }) }));
4300
+ }), children: jsxs(Button, { disabled: b, arrow: true, highlight: highlight(), children: [jsx("span", { class: "xnote-icon-font-size" }), jsx("span", { children: currentFontSize() || '默认' })] }) }));
4172
4301
  };
4173
4302
  }
4174
4303
 
4175
- function ItalicTool() {
4176
- const query = inject(Query);
4177
- const refreshService = inject(RefreshService);
4178
- const textbus = inject(Textbus);
4179
- const [viewModel, update] = useProduce({
4180
- highlight: false,
4181
- disabled: false,
4182
- });
4183
- function toggle() {
4184
- toggleItalic(textbus);
4304
+ var scopedId$d = "vf-cf8e1c";
4305
+
4306
+ class FileUploader {
4307
+ }
4308
+
4309
+ class ImageComponent extends Component {
4310
+ static fromJSON(textbus, json) {
4311
+ return new ImageComponent(textbus, Object.assign({}, json));
4185
4312
  }
4186
- const sub = refreshService.onRefresh.subscribe(() => {
4187
- const state = query.queryFormat(italicFormatter);
4188
- update(draft => {
4189
- draft.highlight = state.state === QueryStateType.Enabled;
4190
- });
4191
- });
4192
- onUnmounted(() => {
4193
- sub.unsubscribe();
4194
- });
4313
+ getSlots() {
4314
+ return [];
4315
+ }
4316
+ }
4317
+ ImageComponent.type = ContentType.InlineComponent;
4318
+ ImageComponent.componentName = 'ImageComponent';
4319
+ function ImageView(props) {
4320
+ const { name, state } = props.component;
4321
+ const imageRef = createRef();
4322
+ const readonly = useReadonly();
4323
+ const output = useOutput();
4195
4324
  return () => {
4196
- const vm = viewModel();
4197
- return jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, onClick: toggle, children: jsx("span", { class: "xnote-icon-italic" }) });
4325
+ if (readonly() || output()) {
4326
+ return (jsx("div", { class: "xnote-image", ref: props.rootRef, "data-component": name, children: jsx("img", { alt: "", src: state.src, style: {
4327
+ width: state.width,
4328
+ height: state.height
4329
+ } }) }));
4330
+ }
4331
+ return (jsx("div", { class: "xnote-image", ref: props.rootRef, "data-component": name, children: jsx(DragResize, { source: imageRef, component: props.component, children: jsx("img", { alt: "", ref: imageRef, src: state.src, style: {
4332
+ width: state.width,
4333
+ height: state.height
4334
+ } }) }) }));
4198
4335
  };
4199
4336
  }
4200
-
4201
- var scopedId$a = "vf-e74208";
4202
-
4203
- let EditorService = class EditorService {
4204
- constructor() {
4205
- this.hideInlineToolbar = false;
4206
- this.canShowLeftToolbar = true;
4207
- this.onLeftToolbarCanVisibleChange = new Subject();
4208
- }
4209
- changeLeftToolbarVisible(b) {
4210
- this.canShowLeftToolbar = b;
4211
- this.onLeftToolbarCanVisibleChange.next();
4337
+ const imageComponentLoader = {
4338
+ match(element) {
4339
+ return element.tagName === 'IMG' || element.dataset.component === ImageComponent.componentName;
4340
+ },
4341
+ read(element, textbus) {
4342
+ const img = element instanceof HTMLImageElement ? element : (element.querySelector('img') || document.createElement('img'));
4343
+ return new ImageComponent(textbus, {
4344
+ src: img.src,
4345
+ width: img.style.width || 'auto',
4346
+ height: img.style.height || 'auto'
4347
+ });
4212
4348
  }
4213
4349
  };
4214
- EditorService = __decorate([
4215
- Injectable({
4216
- provideIn: 'root'
4217
- })
4218
- ], EditorService);
4219
4350
 
4220
- function LinkTool(props) {
4221
- const selectionBridge = inject(SelectionBridge);
4222
- const selection = inject(Selection);
4223
- const commander = inject(Commander);
4224
- const editorService = inject(EditorService);
4225
- const container = inject(VIEW_CONTAINER);
4226
- const isShow = createSignal(false);
4227
- const value = createSignal('');
4228
- function setLink(ev) {
4229
- ev.preventDefault();
4230
- commander.applyFormat(linkFormatter, {
4231
- href: value(),
4232
- target: '_blanK'
4233
- });
4234
- isShow.set(false);
4351
+ class VideoComponent extends Component {
4352
+ static fromJSON(textbus, json) {
4353
+ return new VideoComponent(textbus, Object.assign({}, json));
4235
4354
  }
4236
- let isClickFromSelf = false;
4237
- const sub = fromEvent(document, 'click').subscribe(() => {
4238
- if (isClickFromSelf) {
4239
- isClickFromSelf = false;
4240
- return;
4241
- }
4242
- editorService.hideInlineToolbar = false;
4243
- isShow.set(false);
4244
- });
4245
- onUnmounted(() => {
4246
- sub.unsubscribe();
4247
- });
4248
- return withScopedCSS(scopedId$a, () => {
4249
- const containerRect = container.getBoundingClientRect();
4250
- const rect = isShow() ? selectionBridge.getRect({
4251
- slot: selection.focusSlot,
4252
- offset: selection.focusOffset
4253
- }) : {};
4254
- return (jsxs("span", { children: [jsx(Button, { onClick: () => {
4255
- var _a;
4256
- isShow.set(true);
4257
- isClickFromSelf = true;
4258
- (_a = props.hideToolbar) === null || _a === void 0 ? void 0 : _a.call(props);
4259
- }, children: jsx("span", { class: "xnote-icon-link" }) }), isShow() &&
4260
- jsx(Popup, { left: rect.left - containerRect.left, top: rect.top + rect.height - containerRect.top, children: jsxs("form", { onSubmit: setLink, onClick: () => {
4261
- isClickFromSelf = true;
4262
- }, class: "input-group", children: [jsx("input", { onChange: ev => {
4263
- value.set(ev.target.value);
4264
- }, placeholder: "\u8BF7\u8F93\u5165\u94FE\u63A5\u5730\u5740", type: "text" }), jsx(Button, { type: "submit", children: "\u786E\u5B9A" })] }) })] }));
4265
- });
4266
- }
4267
-
4268
- function StrikeThroughTool() {
4269
- const query = inject(Query);
4270
- const refreshService = inject(RefreshService);
4271
- const textbus = inject(Textbus);
4272
- const [viewModel, update] = useProduce({
4273
- highlight: false,
4274
- disabled: false,
4275
- });
4276
- function toggle() {
4277
- toggleStrikeThrough(textbus);
4355
+ getSlots() {
4356
+ return [];
4278
4357
  }
4279
- const sub = refreshService.onRefresh.subscribe(() => {
4280
- const state = query.queryFormat(strikeThroughFormatter);
4281
- update(draft => {
4282
- draft.highlight = state.state === QueryStateType.Enabled;
4283
- });
4284
- });
4285
- onUnmounted(() => {
4286
- sub.unsubscribe();
4287
- });
4358
+ }
4359
+ VideoComponent.type = ContentType.InlineComponent;
4360
+ VideoComponent.componentName = 'VideoComponent';
4361
+ function VideoView(props) {
4362
+ const { name, state } = props.component;
4363
+ const videoRef = createRef();
4364
+ const readonly = useReadonly();
4365
+ const output = useOutput();
4288
4366
  return () => {
4289
- const vm = viewModel();
4290
- return jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, onClick: toggle, children: jsx("span", { class: "xnote-icon-strikethrough" }) });
4367
+ if (readonly() || output()) {
4368
+ return (jsx("div", { class: "xnote-video", ref: props.rootRef, "data-component": name, children: jsx("video", { ref: videoRef, src: state.src, style: {
4369
+ width: state.width,
4370
+ height: state.height
4371
+ } }) }));
4372
+ }
4373
+ return (jsx("div", { ref: props.rootRef, class: "xnote-video", "data-component": name, children: jsx(DragResize, { source: videoRef, component: props.component, children: jsx("video", { ref: videoRef, src: state.src, style: {
4374
+ width: state.width,
4375
+ height: state.height
4376
+ } }) }) }));
4291
4377
  };
4292
4378
  }
4293
-
4294
- function UnderlineTool() {
4295
- const query = inject(Query);
4296
- const refreshService = inject(RefreshService);
4297
- const textbus = inject(Textbus);
4298
- const [viewModel, update] = useProduce({
4299
- highlight: false,
4300
- disabled: false,
4301
- });
4302
- function toggle() {
4303
- toggleUnderline(textbus);
4379
+ const videoComponentLoader = {
4380
+ match(element) {
4381
+ return element.tagName === 'VIDEO' || element.dataset.component === VideoComponent.componentName;
4382
+ },
4383
+ read(element, textbus) {
4384
+ const video = element instanceof HTMLVideoElement ? element : (element.querySelector('video') || document.createElement('video'));
4385
+ return new VideoComponent(textbus, {
4386
+ src: video.src,
4387
+ width: video.style.width || 'auto',
4388
+ height: video.style.height || 'auto'
4389
+ });
4304
4390
  }
4305
- const sub = refreshService.onRefresh.subscribe(() => {
4306
- const state = query.queryFormat(underlineFormatter);
4307
- update(draft => {
4308
- draft.highlight = state.state === QueryStateType.Enabled;
4391
+ };
4392
+
4393
+ class KatexEditor extends Textbus {
4394
+ constructor() {
4395
+ const adapter = new ViewflyAdapter({
4396
+ [SourceCodeComponent.componentName]: SourceCodeView
4397
+ }, (host, root, injector) => {
4398
+ const appInjector = new ReflectiveInjector(injector, [{
4399
+ provide: OutputInjectionToken,
4400
+ useValue: true
4401
+ }]);
4402
+ const app = createApp(root, {
4403
+ context: appInjector
4404
+ }).mount(host);
4405
+ return () => {
4406
+ app.destroy();
4407
+ };
4309
4408
  });
4310
- });
4311
- onUnmounted(() => {
4312
- sub.unsubscribe();
4313
- });
4314
- return () => {
4315
- const vm = viewModel();
4316
- return jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, onClick: toggle, children: jsx("span", { class: "xnote-icon-underline" }) });
4317
- };
4409
+ const browserModule = new BrowserModule({
4410
+ adapter,
4411
+ renderTo: () => {
4412
+ return this.host;
4413
+ }
4414
+ });
4415
+ super({
4416
+ components: [
4417
+ SourceCodeComponent
4418
+ ],
4419
+ imports: [browserModule]
4420
+ });
4421
+ this.onValueChange = new Subject();
4422
+ }
4423
+ mount(host, code) {
4424
+ this.host = host;
4425
+ const model = new SourceCodeComponent(this, {
4426
+ lineNumber: true,
4427
+ autoBreak: true,
4428
+ lang: 'latex',
4429
+ theme: 'github',
4430
+ slots: code.split('\n').map(i => {
4431
+ const slot = new Slot([ContentType.Text]);
4432
+ slot.insert(i);
4433
+ return {
4434
+ slot,
4435
+ emphasize: false
4436
+ };
4437
+ })
4438
+ });
4439
+ this.onChange.subscribe(() => {
4440
+ const str = model.state.slots.map(i => {
4441
+ if (i.slot.isEmpty) {
4442
+ return '';
4443
+ }
4444
+ return i.slot.toString();
4445
+ }).join('\n');
4446
+ this.onValueChange.next(str);
4447
+ });
4448
+ return this.render(model);
4449
+ }
4318
4450
  }
4319
4451
 
4320
- const cellAlignAttr = new Attribute('cellAlign', {
4321
- render(node, formatValue) {
4322
- node.styles.set('verticalAlign', formatValue);
4452
+ class KatexComponent extends Component {
4453
+ static fromJSON(textbus, state) {
4454
+ return new KatexComponent(textbus, state);
4323
4455
  }
4324
- });
4325
- const cellAlignAttrLoader = {
4326
- match(element) {
4327
- return element instanceof HTMLTableCellElement && !!element.style.verticalAlign;
4328
- },
4329
- read(element) {
4330
- return {
4331
- attribute: cellAlignAttr,
4332
- value: element.style.verticalAlign
4333
- };
4456
+ constructor(textbus, state = {
4457
+ text: '% \\f is defined as #1f(#2) using the macro\n' +
4458
+ '\\f\\relax{x} = \\int_{-\\infty}^\\infty\n' +
4459
+ '\\f\\hat\\xi\\,e^{2 \\pi i \\xi x}\n' +
4460
+ '\\,d\\xi'
4461
+ }) {
4462
+ super(textbus, state);
4334
4463
  }
4335
- };
4336
-
4337
- function CellAlignTool() {
4338
- const currentValue = createSignal('');
4339
- const selection = inject(Selection);
4340
- function check(v) {
4341
- const commonAncestorComponent = selection.commonAncestorComponent;
4342
- if (commonAncestorComponent instanceof TableComponent) {
4343
- const slots = commonAncestorComponent.getSelectedNormalizedSlots();
4344
- slots.forEach(item => {
4345
- item.cells.forEach(cell => {
4346
- if (cell.visible) {
4347
- cell.raw.slot.setAttribute(cellAlignAttr, v);
4348
- }
4349
- });
4464
+ getSlots() {
4465
+ return [];
4466
+ }
4467
+ }
4468
+ KatexComponent.componentName = 'KatexComponent';
4469
+ KatexComponent.type = ContentType.InlineComponent;
4470
+ function domToVDom(el) {
4471
+ const attrs = {};
4472
+ el.getAttributeNames().forEach(key => {
4473
+ attrs[key] = el.getAttribute(key);
4474
+ });
4475
+ attrs.children = Array.from(el.childNodes).map(child => {
4476
+ if (child.nodeType === Node.ELEMENT_NODE) {
4477
+ return domToVDom(child);
4478
+ }
4479
+ return child.textContent || '';
4480
+ });
4481
+ return jsx$1(el.tagName.toLowerCase(), attrs);
4482
+ }
4483
+ function KatexComponentView(props) {
4484
+ function toDOM(value) {
4485
+ let htmlString;
4486
+ try {
4487
+ htmlString = Katex.renderToString(value, {
4488
+ displayMode: true,
4489
+ leqno: false,
4490
+ fleqn: false,
4491
+ throwOnError: true,
4492
+ errorColor: '#cc0000',
4493
+ strict: 'warn',
4494
+ output: 'html',
4495
+ trust: false,
4496
+ macros: { '\\f': '#1f(#2)' }
4350
4497
  });
4351
4498
  }
4499
+ catch (e) {
4500
+ htmlString = '<span style="color: red">公式错误</span>';
4501
+ }
4502
+ return new DOMParser().parseFromString(htmlString, 'text/html').body.children[0];
4352
4503
  }
4353
- const refreshService = inject(RefreshService);
4354
- const query = inject(Query);
4355
- const highlight = createSignal(false);
4356
- const subscription = refreshService.onRefresh.subscribe(() => {
4357
- const result = query.queryAttribute(cellAlignAttr);
4358
- const isHighlight = result.state === QueryStateType.Enabled;
4359
- highlight.set(isHighlight);
4360
- currentValue.set(isHighlight ? result.value : 'middle');
4361
- });
4362
- onUnmounted(() => {
4363
- subscription.unsubscribe();
4504
+ const selection = inject(Textbus);
4505
+ const editorRef = createDynamicRef(node => {
4506
+ const editor = new KatexEditor();
4507
+ editor.mount(node, props.component.state.text).then(() => {
4508
+ editor.focus();
4509
+ });
4510
+ selection.blur();
4511
+ const subscription = editor.onValueChange.subscribe((value) => {
4512
+ props.component.state.text = value;
4513
+ }).add(fromEvent(node, 'mousedown').subscribe(ev => ev.stopPropagation()), fromEvent(document, 'mousedown').subscribe(() => {
4514
+ var _a;
4515
+ (_a = dropdownRef.current) === null || _a === void 0 ? void 0 : _a.isShow(false);
4516
+ }));
4517
+ return () => {
4518
+ subscription.unsubscribe();
4519
+ editor.destroy();
4520
+ };
4364
4521
  });
4522
+ const dropdownRef = createRef();
4523
+ const output = useOutput();
4524
+ const readonly = useReadonly();
4365
4525
  return () => {
4366
- return (jsx(Dropdown, { onCheck: check, menu: [
4367
- {
4368
- label: jsx(MenuItem, { checked: currentValue() === 'top', icon: jsx("span", { class: "xnote-icon-align-top" }), children: "\u9876\u90E8\u5BF9\u9F50" }),
4369
- value: 'top'
4370
- },
4371
- {
4372
- label: jsx(MenuItem, { checked: currentValue() === 'middle', icon: jsx("span", { class: "xnote-icon-align-middle" }), children: "\u5782\u76F4\u5C45\u4E2D" }),
4373
- value: 'middle'
4374
- },
4375
- {
4376
- label: jsx(MenuItem, { checked: currentValue() === 'bottom', icon: jsx("span", { class: "xnote-icon-align-bottom" }), children: "\u5E95\u90E8\u5BF9\u9F50" }),
4377
- value: 'bottom'
4378
- }
4379
- ], children: jsx(Button, { arrow: true, highlight: highlight(), children: jsx("span", { class: 'xnote-icon-align-' + (currentValue() || 'middle') }) }) }));
4526
+ const text = props.component.state.text;
4527
+ return (jsx("span", { onClick: () => {
4528
+ var _a;
4529
+ (_a = dropdownRef.current) === null || _a === void 0 ? void 0 : _a.isShow(true);
4530
+ }, ref: props.rootRef, "data-component": KatexComponent.componentName, "data-katex": encodeURIComponent(text), class: "xnote-katex", children: (output() || readonly()) ?
4531
+ domToVDom(toDOM(text))
4532
+ :
4533
+ jsx(Dropdown, { padding: '0', ref: dropdownRef, trigger: 'none', width: '600px', menu: jsx("div", { class: "xnote-katex-input", ref: editorRef }), children: domToVDom(toDOM(text)) }) }));
4380
4534
  };
4381
4535
  }
4382
-
4383
- const cellBackgroundAttr = new Attribute('cellBackground', {
4384
- render(node, formatValue) {
4385
- const rgba = parseCss(formatValue);
4386
- if (rgba) {
4387
- const hsl = rgb2Hsl(rgba);
4388
- if (hsl.l > 50) {
4389
- hsl.l -= 10;
4390
- }
4391
- else {
4392
- hsl.l += Math.max((50 - hsl.l) * 0.55, 10);
4393
- }
4394
- hsl.s *= 0.7;
4395
- const newRgba = hsl2Rgb(hsl);
4396
- node.styles.set('borderColor', `rgba(${newRgba.r}, ${newRgba.g}, ${newRgba.b}, ${rgba.a || 1})`);
4397
- }
4398
- node.styles.set('backgroundColor', formatValue);
4399
- }
4400
- });
4401
- const cellBackgroundAttrLoader = {
4536
+ const katexComponentLoader = {
4402
4537
  match(element) {
4403
- return (element.tagName === 'TD' || element.tagName === 'TH') && !!element.style.backgroundColor;
4538
+ return element.dataset.component === KatexComponent.componentName;
4404
4539
  },
4405
- read(element) {
4406
- return {
4407
- attribute: cellBackgroundAttr,
4408
- value: element.style.backgroundColor
4409
- };
4540
+ read(element, textbus) {
4541
+ const value = element.dataset.katex || '';
4542
+ return new KatexComponent(textbus, {
4543
+ text: decodeURIComponent(value)
4544
+ });
4410
4545
  }
4411
4546
  };
4412
4547
 
4413
- function CellBackgroundTool() {
4414
- const refreshService = inject(RefreshService);
4548
+ function InsertMenu(props) {
4549
+ const commander = inject(Commander);
4415
4550
  const selection = inject(Selection);
4416
- const [viewModel, update] = useProduce({
4417
- highlight: false,
4418
- disabled: false,
4419
- });
4420
- function setColor(picker) {
4421
- const commonAncestorComponent = selection.commonAncestorComponent;
4422
- if (commonAncestorComponent instanceof TableComponent) {
4423
- const slots = commonAncestorComponent.getSelectedNormalizedSlots();
4424
- if (slots) {
4425
- slots.map(i => {
4426
- return i.cells.filter(t => t.visible).map(i => i.raw.slot);
4427
- }).flat().forEach(slot => {
4428
- const rgba = picker.rgba;
4429
- if (rgba) {
4430
- slot.setAttribute(cellBackgroundAttr, `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`);
4431
- }
4432
- else {
4433
- slot.removeAttribute(cellBackgroundAttr);
4551
+ const textbus = inject(Textbus);
4552
+ const fileUploader = inject(FileUploader, null);
4553
+ const dropdownContextService = inject(DropdownContextService);
4554
+ function insert(type) {
4555
+ var _a;
4556
+ const component = (_a = props.slot) === null || _a === void 0 ? void 0 : _a.parent;
4557
+ if (!component) {
4558
+ return;
4559
+ }
4560
+ function insertComponent(comp) {
4561
+ if (props.replace) {
4562
+ commander.replaceComponent(component, comp);
4563
+ }
4564
+ else {
4565
+ commander.insertAfter(comp, component);
4566
+ }
4567
+ dropdownContextService.canHide = true;
4568
+ dropdownContextService.hide(false);
4569
+ }
4570
+ switch (type) {
4571
+ case 'h1':
4572
+ case 'h2':
4573
+ case 'h3':
4574
+ case 'h4':
4575
+ case 'h5':
4576
+ case 'h6':
4577
+ case 'paragraph':
4578
+ {
4579
+ const slot = new Slot([
4580
+ ContentType.InlineComponent,
4581
+ ContentType.Text
4582
+ ]);
4583
+ if (/h[1-6]/.test(type)) {
4584
+ slot.setAttribute(headingAttr, type);
4434
4585
  }
4586
+ const p = new ParagraphComponent(textbus, {
4587
+ slot
4588
+ });
4589
+ insertComponent(p);
4590
+ selection.setPosition(slot, 0);
4591
+ }
4592
+ break;
4593
+ case 'ol':
4594
+ case 'ul':
4595
+ {
4596
+ const slot = new Slot([
4597
+ ContentType.InlineComponent,
4598
+ ContentType.Text
4599
+ ]);
4600
+ const list = new ListComponent(textbus, {
4601
+ slot,
4602
+ reorder: true,
4603
+ type: type === 'ol' ? 'OrderedList' : 'UnorderedList'
4604
+ });
4605
+ insertComponent(list);
4606
+ selection.setPosition(slot, 0);
4607
+ }
4608
+ break;
4609
+ case 'sourceCode':
4610
+ {
4611
+ const slot = new Slot([
4612
+ ContentType.Text
4613
+ ]);
4614
+ const comp = new SourceCodeComponent(textbus, {
4615
+ lang: '',
4616
+ lineNumber: true,
4617
+ slots: [{
4618
+ slot,
4619
+ emphasize: false
4620
+ }]
4621
+ });
4622
+ insertComponent(comp);
4623
+ selection.setPosition(slot, 0);
4624
+ }
4625
+ break;
4626
+ case 'table':
4627
+ {
4628
+ const table = new TableComponent(textbus);
4629
+ insertComponent(table);
4630
+ textbus.nextTick(() => {
4631
+ selection.selectFirstPosition(table, true, true);
4632
+ });
4633
+ }
4634
+ break;
4635
+ case 'todolist':
4636
+ {
4637
+ const slot = new Slot([
4638
+ ContentType.Text,
4639
+ ContentType.InlineComponent
4640
+ ]);
4641
+ const comp = new TodolistComponent(textbus, {
4642
+ slot,
4643
+ checked: false
4644
+ });
4645
+ insertComponent(comp);
4646
+ selection.setPosition(slot, 0);
4647
+ }
4648
+ break;
4649
+ case 'image':
4650
+ if (fileUploader) {
4651
+ Promise.resolve().then(() => fileUploader.uploadFile('image')).then(url => {
4652
+ const img = new ImageComponent(textbus, {
4653
+ src: url
4654
+ });
4655
+ commander.insert(img);
4656
+ });
4657
+ }
4658
+ break;
4659
+ case 'video':
4660
+ if (fileUploader) {
4661
+ Promise.resolve().then(() => fileUploader.uploadFile('video')).then(url => {
4662
+ const img = new VideoComponent(textbus, {
4663
+ src: url
4664
+ });
4665
+ commander.insert(img);
4666
+ });
4667
+ }
4668
+ break;
4669
+ case 'highlightBox':
4670
+ {
4671
+ const p = new ParagraphComponent(textbus);
4672
+ const comp = new HighlightBoxComponent(textbus);
4673
+ comp.state.slot.insert(p);
4674
+ insertComponent(comp);
4675
+ selection.setPosition(p.state.slot, 0);
4676
+ }
4677
+ break;
4678
+ case 'katex':
4679
+ {
4680
+ const p = new ParagraphComponent(textbus);
4681
+ const comp = new KatexComponent(textbus);
4682
+ p.state.slot.insert(comp);
4683
+ insertComponent(p);
4684
+ selection.selectComponent(comp);
4685
+ }
4686
+ break;
4687
+ case 'step':
4688
+ {
4689
+ const step = new StepComponent(textbus, {
4690
+ step: 0,
4691
+ items: [createStepItem(textbus)]
4692
+ });
4693
+ insertComponent(step);
4694
+ selection.selectFirstPosition(step, false, true);
4695
+ }
4696
+ break;
4697
+ case 'timeline': {
4698
+ const timeline = new TimelineComponent(textbus, {
4699
+ items: [createTimelineItem(textbus, '#296eff')]
4435
4700
  });
4701
+ insertComponent(timeline);
4702
+ selection.selectFirstPosition(timeline, false, true);
4703
+ break;
4436
4704
  }
4437
4705
  }
4438
4706
  }
4439
- const sub = refreshService.onRefresh.subscribe(() => {
4440
- const commonAncestorComponent = selection.commonAncestorComponent;
4441
- update(draft => {
4442
- draft.disabled = !(commonAncestorComponent instanceof TableComponent);
4443
- });
4444
- });
4445
- onUnmounted(() => {
4446
- sub.unsubscribe();
4707
+ return withScopedCSS(scopedId$d, () => {
4708
+ 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" }), jsx(MenuItem, { onClick: () => insert('step'), icon: jsx("span", { class: "xnote-icon-step" }), children: "\u6B65\u9AA4\u6761" }), jsx(MenuItem, { onClick: () => insert('timeline'), icon: jsx("span", { class: "xnote-icon-timeline" }), children: "\u65F6\u95F4\u8F74" })] });
4447
4709
  });
4448
- return () => {
4449
- const vm = viewModel();
4450
- return (jsx(Dropdown, { width: '177px', menu: jsx(ColorPicker, { onSelected: setColor }), trigger: 'hover', children: jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, children: jsx("span", { class: "xnote-icon-palette" }) }) }));
4451
- };
4452
4710
  }
4453
4711
 
4454
- function MergeCellsTool() {
4455
- const refreshService = inject(RefreshService);
4712
+ function InsertTool() {
4456
4713
  const selection = inject(Selection);
4457
- const [viewModel, update] = useProduce({
4458
- highlight: false,
4459
- disabled: false,
4460
- });
4461
- function merge() {
4462
- const commonAncestorComponent = selection.commonAncestorComponent;
4463
- if (commonAncestorComponent instanceof TableComponent) {
4464
- commonAncestorComponent.mergeCellBySelection();
4465
- }
4466
- }
4467
- const sub = refreshService.onRefresh.subscribe(() => {
4468
- const commonAncestorComponent = selection.commonAncestorComponent;
4469
- update(draft => {
4470
- draft.disabled = !(commonAncestorComponent instanceof TableComponent);
4471
- });
4714
+ const instance = getCurrentInstance();
4715
+ const sub = selection.onChange.subscribe(() => {
4716
+ instance.markAsDirtied();
4472
4717
  });
4473
4718
  onUnmounted(() => {
4474
4719
  sub.unsubscribe();
4475
4720
  });
4721
+ const commonState = useCommonState();
4476
4722
  return () => {
4477
- const vm = viewModel();
4478
- return jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, onClick: merge, children: jsx("span", { class: "xnote-icon-merge-cells" }) });
4723
+ const b = commonState().readonly;
4724
+ return (jsx(Dropdown, { disabled: b, menu: jsx(InsertMenu, { replace: false, hideTitle: true, slot: selection.focusSlot }), children: jsx(Button, { disabled: b, arrow: true, children: "\u63D2\u5165" }) }));
4479
4725
  };
4480
4726
  }
4481
4727
 
4482
- function SplitCellsTool() {
4728
+ function ItalicTool() {
4729
+ const query = inject(Query);
4483
4730
  const refreshService = inject(RefreshService);
4484
- const selection = inject(Selection);
4731
+ const textbus = inject(Textbus);
4485
4732
  const [viewModel, update] = useProduce({
4486
4733
  highlight: false,
4487
- disabled: false,
4488
4734
  });
4489
- function split() {
4490
- const commonAncestorComponent = selection.commonAncestorComponent;
4491
- if (commonAncestorComponent instanceof TableComponent) {
4492
- commonAncestorComponent.splitCellsBySelection();
4493
- }
4735
+ function toggle() {
4736
+ toggleItalic(textbus);
4494
4737
  }
4495
4738
  const sub = refreshService.onRefresh.subscribe(() => {
4496
- const commonAncestorComponent = selection.commonAncestorComponent;
4739
+ const state = query.queryFormat(italicFormatter);
4497
4740
  update(draft => {
4498
- if (commonAncestorComponent instanceof TableComponent) {
4499
- const slots = commonAncestorComponent.getSelectedNormalizedSlots();
4500
- if (slots) {
4501
- for (const item of slots) {
4502
- for (const cell of item.cells) {
4503
- if (cell.visible && cell.colspan > 1 || cell.colspan > 1) {
4504
- draft.disabled = false;
4505
- return;
4506
- }
4507
- }
4508
- }
4509
- }
4510
- }
4511
- draft.disabled = true;
4741
+ draft.highlight = state.state === QueryStateType.Enabled;
4512
4742
  });
4513
4743
  });
4514
4744
  onUnmounted(() => {
4515
4745
  sub.unsubscribe();
4516
4746
  });
4747
+ const commonState = useCommonState();
4517
4748
  return () => {
4518
4749
  const vm = viewModel();
4519
- return jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, onClick: split, children: jsx("span", { class: "xnote-icon-split-cells" }) });
4750
+ return jsx(Button, { highlight: vm.highlight, disabled: commonState().inSourceCode || commonState().readonly, onClick: toggle, children: jsx("span", { class: "xnote-icon-italic" }) });
4520
4751
  };
4521
4752
  }
4522
4753
 
4523
- var scopedId$9 = "vf-cf8e1c";
4524
-
4525
- class FileUploader {
4526
- }
4754
+ var scopedId$c = "vf-e74208";
4527
4755
 
4528
- class ImageComponent extends Component {
4529
- static fromJSON(textbus, json) {
4530
- return new ImageComponent(textbus, Object.assign({}, json));
4756
+ let EditorService = class EditorService {
4757
+ constructor() {
4758
+ this.hideInlineToolbar = false;
4759
+ this.canShowLeftToolbar = true;
4760
+ this.onLeftToolbarCanVisibleChange = new Subject();
4531
4761
  }
4532
- getSlots() {
4533
- return [];
4534
- }
4535
- }
4536
- ImageComponent.type = ContentType.InlineComponent;
4537
- ImageComponent.componentName = 'ImageComponent';
4538
- function ImageView(props) {
4539
- const { name, state } = props.component;
4540
- const imageRef = createRef();
4541
- const readonly = useReadonly();
4542
- const output = useOutput();
4543
- return () => {
4544
- if (readonly() || output()) {
4545
- return (jsx("div", { class: "xnote-image", ref: props.rootRef, "data-component": name, children: jsx("img", { alt: "", src: state.src, style: {
4546
- width: state.width,
4547
- height: state.height
4548
- } }) }));
4549
- }
4550
- return (jsx("div", { class: "xnote-image", ref: props.rootRef, "data-component": name, children: jsx(DragResize, { source: imageRef, component: props.component, children: jsx("img", { alt: "", ref: imageRef, src: state.src, style: {
4551
- width: state.width,
4552
- height: state.height
4553
- } }) }) }));
4554
- };
4555
- }
4556
- const imageComponentLoader = {
4557
- match(element) {
4558
- return element.tagName === 'IMG' || element.dataset.component === ImageComponent.componentName;
4559
- },
4560
- read(element, textbus) {
4561
- const img = element instanceof HTMLImageElement ? element : (element.querySelector('img') || document.createElement('img'));
4562
- return new ImageComponent(textbus, {
4563
- src: img.src,
4564
- width: img.style.width || 'auto',
4565
- height: img.style.height || 'auto'
4566
- });
4762
+ changeLeftToolbarVisible(b) {
4763
+ this.canShowLeftToolbar = b;
4764
+ this.onLeftToolbarCanVisibleChange.next();
4567
4765
  }
4568
4766
  };
4767
+ EditorService = __decorate([
4768
+ Injectable({
4769
+ provideIn: 'root'
4770
+ })
4771
+ ], EditorService);
4569
4772
 
4570
- class VideoComponent extends Component {
4571
- static fromJSON(textbus, json) {
4572
- return new VideoComponent(textbus, Object.assign({}, json));
4573
- }
4574
- getSlots() {
4575
- return [];
4773
+ function LinkTool(props) {
4774
+ const selectionBridge = inject(SelectionBridge);
4775
+ const selection = inject(Selection);
4776
+ const commander = inject(Commander);
4777
+ const editorService = inject(EditorService);
4778
+ const container = inject(VIEW_CONTAINER);
4779
+ const isShow = createSignal(false);
4780
+ const value = createSignal('');
4781
+ function setLink(ev) {
4782
+ ev.preventDefault();
4783
+ commander.applyFormat(linkFormatter, {
4784
+ href: value(),
4785
+ target: '_blanK'
4786
+ });
4787
+ isShow.set(false);
4576
4788
  }
4789
+ let isClickFromSelf = false;
4790
+ const sub = fromEvent(document, 'click').subscribe(() => {
4791
+ if (isClickFromSelf) {
4792
+ isClickFromSelf = false;
4793
+ return;
4794
+ }
4795
+ editorService.hideInlineToolbar = false;
4796
+ isShow.set(false);
4797
+ });
4798
+ onUnmounted(() => {
4799
+ sub.unsubscribe();
4800
+ });
4801
+ const commonState = useCommonState();
4802
+ return withScopedCSS(scopedId$c, () => {
4803
+ const containerRect = container.getBoundingClientRect();
4804
+ const rect = isShow() ? selectionBridge.getRect({
4805
+ slot: selection.focusSlot,
4806
+ offset: selection.focusOffset
4807
+ }) : {};
4808
+ return (jsxs("span", { children: [jsx(Button, { disabled: commonState().inSourceCode || commonState().readonly, onClick: () => {
4809
+ var _a;
4810
+ isShow.set(true);
4811
+ isClickFromSelf = true;
4812
+ (_a = props.hideToolbar) === null || _a === void 0 ? void 0 : _a.call(props);
4813
+ }, children: jsx("span", { class: "xnote-icon-link" }) }), isShow() &&
4814
+ jsx(Popup, { left: rect.left - containerRect.left, top: rect.top + rect.height - containerRect.top, children: jsxs("form", { onSubmit: setLink, onClick: () => {
4815
+ isClickFromSelf = true;
4816
+ }, class: "input-group", children: [jsx("input", { onChange: ev => {
4817
+ value.set(ev.target.value);
4818
+ }, placeholder: "\u8BF7\u8F93\u5165\u94FE\u63A5\u5730\u5740", type: "text" }), jsx(Button, { type: "submit", children: "\u786E\u5B9A" })] }) })] }));
4819
+ });
4577
4820
  }
4578
- VideoComponent.type = ContentType.InlineComponent;
4579
- VideoComponent.componentName = 'VideoComponent';
4580
- function VideoView(props) {
4581
- const { name, state } = props.component;
4582
- const videoRef = createRef();
4583
- const readonly = useReadonly();
4584
- const output = useOutput();
4821
+
4822
+ function RedoTool() {
4823
+ const history = inject(History);
4824
+ const instance = getCurrentInstance();
4825
+ function redo() {
4826
+ history.forward();
4827
+ }
4828
+ const sub = history.onChange.subscribe(() => {
4829
+ instance.markAsDirtied();
4830
+ });
4831
+ onUnmounted(() => {
4832
+ sub.unsubscribe();
4833
+ });
4834
+ const commonState = useCommonState();
4585
4835
  return () => {
4586
- if (readonly() || output()) {
4587
- return (jsx("div", { class: "xnote-video", ref: props.rootRef, "data-component": name, children: jsx("video", { ref: videoRef, src: state.src, style: {
4588
- width: state.width,
4589
- height: state.height
4590
- } }) }));
4591
- }
4592
- return (jsx("div", { ref: props.rootRef, class: "xnote-video", "data-component": name, children: jsx(DragResize, { source: videoRef, component: props.component, children: jsx("video", { ref: videoRef, src: state.src, style: {
4593
- width: state.width,
4594
- height: state.height
4595
- } }) }) }));
4836
+ return jsx(Button, { disabled: !history.canForward || commonState().readonly, onClick: redo, children: jsx("span", { class: "xnote-icon-history-forward" }) });
4596
4837
  };
4597
4838
  }
4598
- const videoComponentLoader = {
4599
- match(element) {
4600
- return element.tagName === 'VIDEO' || element.dataset.component === VideoComponent.componentName;
4601
- },
4602
- read(element, textbus) {
4603
- const video = element instanceof HTMLVideoElement ? element : (element.querySelector('video') || document.createElement('video'));
4604
- return new VideoComponent(textbus, {
4605
- src: video.src,
4606
- width: video.style.width || 'auto',
4607
- height: video.style.height || 'auto'
4608
- });
4609
- }
4610
- };
4611
4839
 
4612
- class KatexEditor extends Textbus {
4613
- constructor() {
4614
- const adapter = new ViewflyAdapter({
4615
- [SourceCodeComponent.componentName]: SourceCodeView
4616
- }, (host, root, injector) => {
4617
- const appInjector = new ReflectiveInjector(injector, [{
4618
- provide: OutputInjectionToken,
4619
- useValue: true
4620
- }]);
4621
- const app = createApp(root, {
4622
- context: appInjector
4623
- }).mount(host);
4624
- return () => {
4625
- app.destroy();
4626
- };
4627
- });
4628
- const browserModule = new BrowserModule({
4629
- adapter,
4630
- renderTo: () => {
4631
- return this.host;
4632
- }
4633
- });
4634
- super({
4635
- components: [
4636
- SourceCodeComponent
4637
- ],
4638
- imports: [browserModule]
4639
- });
4640
- this.onValueChange = new Subject();
4840
+ function StrikeThroughTool() {
4841
+ const query = inject(Query);
4842
+ const refreshService = inject(RefreshService);
4843
+ const textbus = inject(Textbus);
4844
+ const [viewModel, update] = useProduce({
4845
+ highlight: false,
4846
+ });
4847
+ function toggle() {
4848
+ toggleStrikeThrough(textbus);
4641
4849
  }
4642
- mount(host, code) {
4643
- this.host = host;
4644
- const model = new SourceCodeComponent(this, {
4645
- lineNumber: true,
4646
- autoBreak: true,
4647
- lang: 'latex',
4648
- theme: 'github',
4649
- slots: code.split('\n').map(i => {
4650
- const slot = new Slot([ContentType.Text]);
4651
- slot.insert(i);
4652
- return {
4653
- slot,
4654
- emphasize: false
4655
- };
4656
- })
4657
- });
4658
- this.onChange.subscribe(() => {
4659
- const str = model.state.slots.map(i => {
4660
- if (i.slot.isEmpty) {
4661
- return '';
4662
- }
4663
- return i.slot.toString();
4664
- }).join('\n');
4665
- this.onValueChange.next(str);
4850
+ const sub = refreshService.onRefresh.subscribe(() => {
4851
+ const state = query.queryFormat(strikeThroughFormatter);
4852
+ update(draft => {
4853
+ draft.highlight = state.state === QueryStateType.Enabled;
4666
4854
  });
4667
- return this.render(model);
4668
- }
4855
+ });
4856
+ onUnmounted(() => {
4857
+ sub.unsubscribe();
4858
+ });
4859
+ const commonState = useCommonState();
4860
+ return () => {
4861
+ const vm = viewModel();
4862
+ return jsx(Button, { highlight: vm.highlight, disabled: commonState().inSourceCode || commonState().readonly, onClick: toggle, children: jsx("span", { class: "xnote-icon-strikethrough" }) });
4863
+ };
4669
4864
  }
4670
4865
 
4671
- class KatexComponent extends Component {
4672
- static fromJSON(textbus, state) {
4673
- return new KatexComponent(textbus, state);
4674
- }
4675
- constructor(textbus, state = {
4676
- text: '% \\f is defined as #1f(#2) using the macro\n' +
4677
- '\\f\\relax{x} = \\int_{-\\infty}^\\infty\n' +
4678
- '\\f\\hat\\xi\\,e^{2 \\pi i \\xi x}\n' +
4679
- '\\,d\\xi'
4680
- }) {
4681
- super(textbus, state);
4866
+ function SubscriptTool() {
4867
+ const query = inject(Query);
4868
+ const selection = inject(Selection);
4869
+ const commander = inject(Commander);
4870
+ const [state, updateState] = useProduce({
4871
+ highlight: false
4872
+ });
4873
+ const sub = selection.onChange.subscribe(() => {
4874
+ updateState(draft => {
4875
+ draft.highlight = getState();
4876
+ });
4877
+ });
4878
+ function getState() {
4879
+ const s = query.queryFormat(subscriptFormatter);
4880
+ return s.state === QueryStateType.Enabled;
4682
4881
  }
4683
- getSlots() {
4684
- return [];
4882
+ onUnmounted(() => {
4883
+ sub.unsubscribe();
4884
+ });
4885
+ function apply() {
4886
+ const is = getState();
4887
+ if (is) {
4888
+ commander.unApplyFormat(subscriptFormatter);
4889
+ }
4890
+ else {
4891
+ commander.unApplyFormat(superscriptFormatter);
4892
+ commander.applyFormat(subscriptFormatter, true);
4893
+ }
4685
4894
  }
4895
+ const commonState = useCommonState();
4896
+ return () => {
4897
+ return (jsx(Button, { disabled: commonState().inSourceCode || commonState().readonly, highlight: state().highlight, onClick: apply, children: jsx("span", { class: "xnote-icon-subscript" }) }));
4898
+ };
4686
4899
  }
4687
- KatexComponent.componentName = 'KatexComponent';
4688
- KatexComponent.type = ContentType.InlineComponent;
4689
- function domToVDom(el) {
4690
- const attrs = {};
4691
- el.getAttributeNames().forEach(key => {
4692
- attrs[key] = el.getAttribute(key);
4900
+
4901
+ function SuperscriptTool() {
4902
+ const query = inject(Query);
4903
+ const selection = inject(Selection);
4904
+ const commander = inject(Commander);
4905
+ const [state, updateState] = useProduce({
4906
+ highlight: false
4693
4907
  });
4694
- attrs.children = Array.from(el.childNodes).map(child => {
4695
- if (child.nodeType === Node.ELEMENT_NODE) {
4696
- return domToVDom(child);
4697
- }
4698
- return child.textContent || '';
4908
+ const sub = selection.onChange.subscribe(() => {
4909
+ updateState(draft => {
4910
+ draft.highlight = getState();
4911
+ });
4699
4912
  });
4700
- return jsx$1(el.tagName.toLowerCase(), attrs);
4701
- }
4702
- function KatexComponentView(props) {
4703
- function toDOM(value) {
4704
- let htmlString;
4705
- try {
4706
- htmlString = Katex.renderToString(value, {
4707
- displayMode: true,
4708
- leqno: false,
4709
- fleqn: false,
4710
- throwOnError: true,
4711
- errorColor: '#cc0000',
4712
- strict: 'warn',
4713
- output: 'html',
4714
- trust: false,
4715
- macros: { '\\f': '#1f(#2)' }
4716
- });
4913
+ function getState() {
4914
+ const s = query.queryFormat(superscriptFormatter);
4915
+ return s.state === QueryStateType.Enabled;
4916
+ }
4917
+ onUnmounted(() => {
4918
+ sub.unsubscribe();
4919
+ });
4920
+ function apply() {
4921
+ const is = getState();
4922
+ if (is) {
4923
+ commander.unApplyFormat(superscriptFormatter);
4717
4924
  }
4718
- catch (e) {
4719
- htmlString = '<span style="color: red">公式错误</span>';
4925
+ else {
4926
+ commander.unApplyFormat(subscriptFormatter);
4927
+ commander.applyFormat(superscriptFormatter, true);
4720
4928
  }
4721
- return new DOMParser().parseFromString(htmlString, 'text/html').body.children[0];
4722
4929
  }
4723
- const selection = inject(Textbus);
4724
- const editorRef = createDynamicRef(node => {
4725
- const editor = new KatexEditor();
4726
- editor.mount(node, props.component.state.text).then(() => {
4727
- editor.focus();
4930
+ const commonState = useCommonState();
4931
+ return () => {
4932
+ return (jsx(Button, { disabled: commonState().inSourceCode || commonState().readonly, highlight: state().highlight, onClick: apply, children: jsx("span", { class: "xnote-icon-superscript" }) }));
4933
+ };
4934
+ }
4935
+
4936
+ function UnderlineTool() {
4937
+ const query = inject(Query);
4938
+ const refreshService = inject(RefreshService);
4939
+ const textbus = inject(Textbus);
4940
+ const [viewModel, update] = useProduce({
4941
+ highlight: false,
4942
+ });
4943
+ function toggle() {
4944
+ toggleUnderline(textbus);
4945
+ }
4946
+ const sub = refreshService.onRefresh.subscribe(() => {
4947
+ const state = query.queryFormat(underlineFormatter);
4948
+ update(draft => {
4949
+ draft.highlight = state.state === QueryStateType.Enabled;
4728
4950
  });
4729
- selection.blur();
4730
- const subscription = editor.onValueChange.subscribe((value) => {
4731
- props.component.state.text = value;
4732
- }).add(fromEvent(node, 'mousedown').subscribe(ev => ev.stopPropagation()), fromEvent(document, 'mousedown').subscribe(() => {
4733
- var _a;
4734
- (_a = dropdownRef.current) === null || _a === void 0 ? void 0 : _a.isShow(false);
4735
- }));
4736
- return () => {
4737
- subscription.unsubscribe();
4738
- editor.destroy();
4739
- };
4740
4951
  });
4741
- const dropdownRef = createRef();
4742
- const output = useOutput();
4743
- const readonly = useReadonly();
4952
+ onUnmounted(() => {
4953
+ sub.unsubscribe();
4954
+ });
4955
+ const commonState = useCommonState();
4744
4956
  return () => {
4745
- const text = props.component.state.text;
4746
- return (jsx("span", { onClick: () => {
4747
- var _a;
4748
- (_a = dropdownRef.current) === null || _a === void 0 ? void 0 : _a.isShow(true);
4749
- }, ref: props.rootRef, "data-component": KatexComponent.componentName, "data-katex": encodeURIComponent(text), class: "xnote-katex", children: (output() || readonly()) ?
4750
- domToVDom(toDOM(text))
4751
- :
4752
- jsx(Dropdown, { padding: '0', ref: dropdownRef, trigger: 'none', width: '600px', menu: jsx("div", { class: "xnote-katex-input", ref: editorRef }), children: domToVDom(toDOM(text)) }) }));
4957
+ const vm = viewModel();
4958
+ return jsx(Button, { highlight: vm.highlight, disabled: commonState().inSourceCode || commonState().readonly, onClick: toggle, children: jsx("span", { class: "xnote-icon-underline" }) });
4753
4959
  };
4754
4960
  }
4755
- const katexComponentLoader = {
4961
+
4962
+ function UndoTool() {
4963
+ const history = inject(History);
4964
+ const instance = getCurrentInstance();
4965
+ function undo() {
4966
+ history.back();
4967
+ }
4968
+ const sub = history.onChange.subscribe(() => {
4969
+ instance.markAsDirtied();
4970
+ });
4971
+ onUnmounted(() => {
4972
+ sub.unsubscribe();
4973
+ });
4974
+ const commonState = useCommonState();
4975
+ return () => {
4976
+ return jsx(Button, { disabled: !history.canBack || commonState().readonly, onClick: undo, children: jsx("span", { class: "xnote-icon-history-back" }) });
4977
+ };
4978
+ }
4979
+
4980
+ const cellAlignAttr = new Attribute('cellAlign', {
4981
+ render(node, formatValue) {
4982
+ node.styles.set('verticalAlign', formatValue);
4983
+ }
4984
+ });
4985
+ const cellAlignAttrLoader = {
4756
4986
  match(element) {
4757
- return element.dataset.component === KatexComponent.componentName;
4987
+ return element instanceof HTMLTableCellElement && !!element.style.verticalAlign;
4758
4988
  },
4759
- read(element, textbus) {
4760
- const value = element.dataset.katex || '';
4761
- return new KatexComponent(textbus, {
4762
- text: decodeURIComponent(value)
4763
- });
4989
+ read(element) {
4990
+ return {
4991
+ attribute: cellAlignAttr,
4992
+ value: element.style.verticalAlign
4993
+ };
4764
4994
  }
4765
4995
  };
4766
4996
 
4767
- function InsertTool(props) {
4768
- const commander = inject(Commander);
4769
- const selection = inject(Selection);
4770
- const textbus = inject(Textbus);
4771
- const fileUploader = inject(FileUploader, null);
4772
- const dropdownContextService = inject(DropdownContextService);
4773
- function insert(type) {
4774
- var _a;
4775
- const component = (_a = props.slot) === null || _a === void 0 ? void 0 : _a.parent;
4776
- if (!component) {
4777
- return;
4778
- }
4779
- function insertComponent(comp) {
4780
- if (props.replace) {
4781
- commander.replaceComponent(component, comp);
4782
- }
4783
- else {
4784
- commander.insertAfter(comp, component);
4997
+ function isInTable(selection) {
4998
+ if (selection.commonAncestorComponent instanceof TableComponent) {
4999
+ return true;
5000
+ }
5001
+ if (selection.isCollapsed) {
5002
+ let slot = selection.commonAncestorSlot;
5003
+ while (slot) {
5004
+ if (slot.parent instanceof TableComponent) {
5005
+ return true;
4785
5006
  }
4786
- dropdownContextService.canHide = true;
4787
- dropdownContextService.hide(false);
5007
+ slot = slot.parentSlot;
4788
5008
  }
4789
- switch (type) {
4790
- case 'h1':
4791
- case 'h2':
4792
- case 'h3':
4793
- case 'h4':
4794
- case 'h5':
4795
- case 'h6':
4796
- case 'paragraph':
4797
- {
4798
- const slot = new Slot([
4799
- ContentType.InlineComponent,
4800
- ContentType.Text
4801
- ]);
4802
- if (/h[1-6]/.test(type)) {
4803
- slot.setAttribute(headingAttr, type);
5009
+ return false;
5010
+ }
5011
+ const startTable = getParentTable(selection.startSlot);
5012
+ const endTable = getParentTable(selection.endSlot);
5013
+ if (startTable && endTable) {
5014
+ return startTable === endTable;
5015
+ }
5016
+ return false;
5017
+ }
5018
+ function getParentTable(slot) {
5019
+ while (slot) {
5020
+ if (slot.parent instanceof TableComponent) {
5021
+ return slot.parent;
5022
+ }
5023
+ slot = slot.parentSlot;
5024
+ }
5025
+ return null;
5026
+ }
5027
+ function getTableSlotBySlot(slot) {
5028
+ while (slot) {
5029
+ if (slot.parent instanceof TableComponent) {
5030
+ return slot;
5031
+ }
5032
+ slot = slot.parentSlot;
5033
+ }
5034
+ return null;
5035
+ }
5036
+
5037
+ function CellAlignTool() {
5038
+ const currentValue = createSignal('');
5039
+ const selection = inject(Selection);
5040
+ function check(v) {
5041
+ const commonAncestorComponent = selection.commonAncestorComponent;
5042
+ if (commonAncestorComponent instanceof TableComponent) {
5043
+ const slots = commonAncestorComponent.getSelectedNormalizedSlots();
5044
+ slots.forEach(item => {
5045
+ item.cells.forEach(cell => {
5046
+ if (cell.visible) {
5047
+ cell.raw.slot.setAttribute(cellAlignAttr, v);
4804
5048
  }
4805
- const p = new ParagraphComponent(textbus, {
4806
- slot
4807
- });
4808
- insertComponent(p);
4809
- selection.setPosition(slot, 0);
4810
- }
4811
- break;
4812
- case 'ol':
4813
- case 'ul':
4814
- {
4815
- const slot = new Slot([
4816
- ContentType.InlineComponent,
4817
- ContentType.Text
4818
- ]);
4819
- const list = new ListComponent(textbus, {
4820
- slot,
4821
- reorder: true,
4822
- type: type === 'ol' ? 'OrderedList' : 'UnorderedList'
4823
- });
4824
- insertComponent(list);
4825
- selection.setPosition(slot, 0);
5049
+ });
5050
+ });
5051
+ }
5052
+ else {
5053
+ const is = isInTable(selection);
5054
+ if (is) {
5055
+ let parentSlot = selection.commonAncestorSlot;
5056
+ while (parentSlot) {
5057
+ if (parentSlot.parent instanceof TableComponent) {
5058
+ const slots = parentSlot.parent.getNormalizedData();
5059
+ for (const item of slots) {
5060
+ for (const cell of item.cells) {
5061
+ if (cell.visible && cell.raw.slot === parentSlot) {
5062
+ cell.raw.slot.setAttribute(cellAlignAttr, v);
5063
+ return;
5064
+ }
5065
+ }
5066
+ }
5067
+ }
5068
+ parentSlot = parentSlot.parentSlot;
4826
5069
  }
4827
- break;
4828
- case 'sourceCode':
5070
+ }
5071
+ }
5072
+ }
5073
+ const refreshService = inject(RefreshService);
5074
+ const query = inject(Query);
5075
+ const highlight = createSignal(false);
5076
+ const subscription = refreshService.onRefresh.subscribe(() => {
5077
+ if (!isInTable(selection)) {
5078
+ highlight.set(false);
5079
+ currentValue.set('middle');
5080
+ return;
5081
+ }
5082
+ const result = query.queryAttribute(cellAlignAttr);
5083
+ const isHighlight = result.state === QueryStateType.Enabled;
5084
+ highlight.set(isHighlight);
5085
+ currentValue.set(isHighlight ? result.value : 'middle');
5086
+ });
5087
+ onUnmounted(() => {
5088
+ subscription.unsubscribe();
5089
+ });
5090
+ return () => {
5091
+ return (jsx(Dropdown, { onCheck: check, menu: [
4829
5092
  {
4830
- const slot = new Slot([
4831
- ContentType.Text
4832
- ]);
4833
- const comp = new SourceCodeComponent(textbus, {
4834
- lang: '',
4835
- lineNumber: true,
4836
- slots: [{
4837
- slot,
4838
- emphasize: false
4839
- }]
4840
- });
4841
- insertComponent(comp);
4842
- selection.setPosition(slot, 0);
4843
- }
4844
- break;
4845
- case 'table':
5093
+ label: jsx(MenuItem, { checked: currentValue() === 'top', icon: jsx("span", { class: "xnote-icon-align-top" }), children: "\u9876\u90E8\u5BF9\u9F50" }),
5094
+ value: 'top'
5095
+ },
4846
5096
  {
4847
- const table = new TableComponent(textbus);
4848
- insertComponent(table);
4849
- textbus.nextTick(() => {
4850
- selection.selectFirstPosition(table, true, true);
4851
- });
4852
- }
4853
- break;
4854
- case 'todolist':
5097
+ label: jsx(MenuItem, { checked: currentValue() === 'middle', icon: jsx("span", { class: "xnote-icon-align-middle" }), children: "\u5782\u76F4\u5C45\u4E2D" }),
5098
+ value: 'middle'
5099
+ },
4855
5100
  {
4856
- const slot = new Slot([
4857
- ContentType.Text,
4858
- ContentType.InlineComponent
4859
- ]);
4860
- const comp = new TodolistComponent(textbus, {
4861
- slot,
4862
- checked: false
4863
- });
4864
- insertComponent(comp);
4865
- selection.setPosition(slot, 0);
4866
- }
4867
- break;
4868
- case 'image':
4869
- if (fileUploader) {
4870
- Promise.resolve().then(() => fileUploader.uploadFile('image')).then(url => {
4871
- const img = new ImageComponent(textbus, {
4872
- src: url
4873
- });
4874
- commander.insert(img);
4875
- });
4876
- }
4877
- break;
4878
- case 'video':
4879
- if (fileUploader) {
4880
- Promise.resolve().then(() => fileUploader.uploadFile('video')).then(url => {
4881
- const img = new VideoComponent(textbus, {
4882
- src: url
4883
- });
4884
- commander.insert(img);
4885
- });
5101
+ label: jsx(MenuItem, { checked: currentValue() === 'bottom', icon: jsx("span", { class: "xnote-icon-align-bottom" }), children: "\u5E95\u90E8\u5BF9\u9F50" }),
5102
+ value: 'bottom'
4886
5103
  }
4887
- break;
4888
- case 'highlightBox':
4889
- {
4890
- const p = new ParagraphComponent(textbus);
4891
- const comp = new HighlightBoxComponent(textbus);
4892
- comp.state.slot.insert(p);
4893
- insertComponent(comp);
4894
- selection.setPosition(p.state.slot, 0);
5104
+ ], children: jsx(Button, { arrow: true, highlight: highlight(), children: jsx("span", { class: 'xnote-icon-align-' + (currentValue() || 'middle') }) }) }));
5105
+ };
5106
+ }
5107
+
5108
+ const cellBackgroundAttr = new Attribute('cellBackground', {
5109
+ render(node, formatValue) {
5110
+ const rgba = parseCss(formatValue);
5111
+ if (rgba) {
5112
+ const hsl = rgb2Hsl(rgba);
5113
+ if (hsl.l > 50) {
5114
+ hsl.l -= 10;
5115
+ }
5116
+ else {
5117
+ hsl.l += Math.max((50 - hsl.l) * 0.55, 10);
5118
+ }
5119
+ hsl.s *= 0.7;
5120
+ const newRgba = hsl2Rgb(hsl);
5121
+ node.styles.set('borderColor', `rgba(${newRgba.r}, ${newRgba.g}, ${newRgba.b}, ${rgba.a || 1})`);
5122
+ }
5123
+ node.styles.set('backgroundColor', formatValue);
5124
+ }
5125
+ });
5126
+ const cellBackgroundAttrLoader = {
5127
+ match(element) {
5128
+ return (element.tagName === 'TD' || element.tagName === 'TH') && !!element.style.backgroundColor;
5129
+ },
5130
+ read(element) {
5131
+ return {
5132
+ attribute: cellBackgroundAttr,
5133
+ value: element.style.backgroundColor
5134
+ };
5135
+ }
5136
+ };
5137
+
5138
+ function CellBackgroundTool() {
5139
+ const refreshService = inject(RefreshService);
5140
+ const selection = inject(Selection);
5141
+ const [viewModel, update] = useProduce({
5142
+ highlight: false,
5143
+ disabled: false,
5144
+ });
5145
+ function setColor(picker) {
5146
+ const commonAncestorComponent = selection.commonAncestorComponent;
5147
+ if (commonAncestorComponent instanceof TableComponent) {
5148
+ const slots = commonAncestorComponent.getSelectedNormalizedSlots();
5149
+ if (slots) {
5150
+ slots.map(i => {
5151
+ return i.cells.filter(t => t.visible).map(i => i.raw.slot);
5152
+ }).flat().forEach(slot => {
5153
+ const rgba = picker.rgba;
5154
+ if (rgba) {
5155
+ slot.setAttribute(cellBackgroundAttr, `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`);
5156
+ }
5157
+ else {
5158
+ slot.removeAttribute(cellBackgroundAttr);
5159
+ }
5160
+ });
5161
+ }
5162
+ }
5163
+ else {
5164
+ let parentSlot = selection.commonAncestorSlot;
5165
+ while (parentSlot) {
5166
+ if (parentSlot.parent instanceof TableComponent) {
5167
+ const rgba = picker.rgba;
5168
+ if (rgba) {
5169
+ parentSlot.setAttribute(cellBackgroundAttr, `rgba(${rgba.r}, ${rgba.g}, ${rgba.b}, ${rgba.a})`);
5170
+ }
5171
+ else {
5172
+ parentSlot.removeAttribute(cellBackgroundAttr);
5173
+ }
5174
+ return;
4895
5175
  }
4896
- break;
4897
- case 'katex':
4898
- {
4899
- const p = new ParagraphComponent(textbus);
4900
- const comp = new KatexComponent(textbus);
4901
- p.state.slot.insert(comp);
4902
- insertComponent(p);
4903
- selection.selectComponent(comp);
5176
+ parentSlot = parentSlot.parentSlot;
5177
+ }
5178
+ }
5179
+ }
5180
+ const sub = refreshService.onRefresh.subscribe(() => {
5181
+ update(draft => {
5182
+ draft.disabled = !isInTable(selection);
5183
+ });
5184
+ });
5185
+ onUnmounted(() => {
5186
+ sub.unsubscribe();
5187
+ });
5188
+ return () => {
5189
+ const vm = viewModel();
5190
+ return (jsx(Dropdown, { width: '177px', menu: jsx(ColorPicker, { onSelected: setColor }), trigger: 'hover', children: jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, children: jsx("span", { class: "xnote-icon-palette" }) }) }));
5191
+ };
5192
+ }
5193
+
5194
+ function MergeCellsTool() {
5195
+ const refreshService = inject(RefreshService);
5196
+ const selection = inject(Selection);
5197
+ const [viewModel, update] = useProduce({
5198
+ highlight: false,
5199
+ disabled: false,
5200
+ });
5201
+ function merge() {
5202
+ const commonAncestorComponent = selection.commonAncestorComponent;
5203
+ if (commonAncestorComponent instanceof TableComponent) {
5204
+ commonAncestorComponent.mergeCellBySelection();
5205
+ }
5206
+ }
5207
+ const sub = refreshService.onRefresh.subscribe(() => {
5208
+ update(draft => {
5209
+ const is = isInTable(selection);
5210
+ if (is) {
5211
+ const p1 = getTableSlotBySlot(selection.startSlot);
5212
+ const p2 = getTableSlotBySlot(selection.endSlot);
5213
+ if (p1 && p2) {
5214
+ draft.disabled = p1 === p2;
5215
+ return;
4904
5216
  }
4905
- break;
4906
- case 'step':
4907
- {
4908
- const step = new StepComponent(textbus, {
4909
- step: 0,
4910
- items: [createStepItem(textbus)]
4911
- });
4912
- insertComponent(step);
4913
- selection.selectFirstPosition(step, false, true);
5217
+ }
5218
+ draft.disabled = true;
5219
+ });
5220
+ });
5221
+ onUnmounted(() => {
5222
+ sub.unsubscribe();
5223
+ });
5224
+ return () => {
5225
+ const vm = viewModel();
5226
+ return jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, onClick: merge, children: jsx("span", { class: "xnote-icon-merge-cells" }) });
5227
+ };
5228
+ }
5229
+
5230
+ function SplitCellsTool() {
5231
+ const refreshService = inject(RefreshService);
5232
+ const selection = inject(Selection);
5233
+ const [viewModel, update] = useProduce({
5234
+ highlight: false,
5235
+ disabled: false,
5236
+ });
5237
+ function split() {
5238
+ const commonAncestorComponent = selection.commonAncestorComponent;
5239
+ if (commonAncestorComponent instanceof TableComponent) {
5240
+ commonAncestorComponent.splitCellsBySelection();
5241
+ return;
5242
+ }
5243
+ let parentSlot = selection.commonAncestorSlot;
5244
+ while (parentSlot) {
5245
+ if (parentSlot.parent instanceof TableComponent) {
5246
+ if (parentSlot.parent === commonAncestorComponent) {
5247
+ parentSlot.parent.splitCellsBySelection();
5248
+ return;
4914
5249
  }
4915
- break;
4916
- case 'timeline': {
4917
- const timeline = new TimelineComponent(textbus, {
4918
- items: [createTimelineItem(textbus, '#296eff')]
4919
- });
4920
- insertComponent(timeline);
4921
- selection.selectFirstPosition(timeline, false, true);
4922
- break;
5250
+ parentSlot.parent.splitCellBySlot(parentSlot);
5251
+ return;
4923
5252
  }
5253
+ parentSlot = parentSlot.parentSlot;
4924
5254
  }
4925
5255
  }
4926
- return withScopedCSS(scopedId$9, () => {
4927
- 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" }), jsx(MenuItem, { onClick: () => insert('step'), icon: jsx("span", { class: "xnote-icon-step" }), children: "\u6B65\u9AA4\u6761" }), jsx(MenuItem, { onClick: () => insert('timeline'), icon: jsx("span", { class: "xnote-icon-timeline" }), children: "\u65F6\u95F4\u8F74" })] });
5256
+ const sub = refreshService.onRefresh.subscribe(() => {
5257
+ const commonAncestorComponent = selection.commonAncestorComponent;
5258
+ update(draft => {
5259
+ if (commonAncestorComponent instanceof TableComponent) {
5260
+ const slots = commonAncestorComponent.getSelectedNormalizedSlots();
5261
+ if (slots) {
5262
+ for (const item of slots) {
5263
+ for (const cell of item.cells) {
5264
+ if (cell.visible && cell.colspan > 1 || cell.colspan > 1) {
5265
+ draft.disabled = false;
5266
+ return;
5267
+ }
5268
+ }
5269
+ }
5270
+ }
5271
+ }
5272
+ else {
5273
+ let parentSlot = selection.commonAncestorSlot;
5274
+ while (parentSlot) {
5275
+ if (parentSlot.parent instanceof TableComponent) {
5276
+ const slots = parentSlot.parent.getNormalizedData();
5277
+ for (const item of slots) {
5278
+ for (const cell of item.cells) {
5279
+ if (cell.raw.slot === parentSlot) {
5280
+ draft.disabled = !(cell.colspan > 1 || cell.colspan > 1);
5281
+ return;
5282
+ }
5283
+ }
5284
+ }
5285
+ }
5286
+ parentSlot = parentSlot.parentSlot;
5287
+ }
5288
+ }
5289
+ draft.disabled = true;
5290
+ });
5291
+ });
5292
+ onUnmounted(() => {
5293
+ sub.unsubscribe();
5294
+ });
5295
+ return () => {
5296
+ const vm = viewModel();
5297
+ return jsx(Button, { highlight: vm.highlight, disabled: vm.disabled, onClick: split, children: jsx("span", { class: "xnote-icon-split-cells" }) });
5298
+ };
5299
+ }
5300
+
5301
+ var scopedId$b = "vf-669084";
5302
+
5303
+ function SplitLine() {
5304
+ return withScopedCSS(scopedId$b, () => {
5305
+ return jsx("div", { class: "split-line" });
4928
5306
  });
4929
5307
  }
4930
5308
 
4931
- var scopedId$8 = "vf-b05292";
5309
+ var scopedId$a = "vf-b05292";
4932
5310
 
4933
5311
  const LeftToolbar = withAnnotation({
4934
- providers: [RefreshService]
5312
+ providers: [RefreshService, ToolService]
4935
5313
  }, function LeftToolbar() {
4936
5314
  const adapter = inject(DomAdapter);
4937
5315
  const textbus = inject(Textbus);
@@ -5092,7 +5470,7 @@ const LeftToolbar = withAnnotation({
5092
5470
  function changeIgnoreMove(b) {
5093
5471
  isIgnoreMove = b;
5094
5472
  }
5095
- return withScopedCSS(scopedId$8, () => {
5473
+ return withScopedCSS(scopedId$a, () => {
5096
5474
  var _a;
5097
5475
  const position = positionSignal();
5098
5476
  const slot = activeSlot();
@@ -5132,9 +5510,9 @@ const LeftToolbar = withAnnotation({
5132
5510
  right: 0,
5133
5511
  top: 0
5134
5512
  }, menu: isEmptyBlock() ?
5135
- jsx(InsertTool, { replace: !needInsert, slot: activeSlot() })
5513
+ jsx(InsertMenu, { replace: !needInsert, slot: activeSlot() })
5136
5514
  :
5137
- 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() ?
5515
+ 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(InsertMenu, { 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() ?
5138
5516
  jsx("span", { children: jsx("i", { class: "xnote-icon-plus" }) })
5139
5517
  :
5140
5518
  jsxs("span", { children: [activeNode, jsx("i", { style: "font-size: 12px", class: "xnote-icon-more" })] }) }) }) }) }));
@@ -5169,7 +5547,7 @@ class LeftToolbarPlugin {
5169
5547
  }
5170
5548
  }
5171
5549
 
5172
- var scopedId$7 = "vf-3073ba";
5550
+ var scopedId$9 = "vf-3073ba";
5173
5551
 
5174
5552
  function LinkJump() {
5175
5553
  const selection = inject(Selection);
@@ -5223,25 +5601,26 @@ function LinkJump() {
5223
5601
  }
5224
5602
  });
5225
5603
  }
5226
- return createPortal(withScopedCSS(scopedId$7, () => {
5604
+ return createPortal(withScopedCSS(scopedId$9, () => {
5227
5605
  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" })] }));
5228
5606
  }), container);
5229
5607
  }
5230
5608
 
5231
- var scopedId$6 = "vf-fee98b";
5609
+ var scopedId$8 = "vf-33b3ca";
5232
5610
 
5233
5611
  function sum(numbers) {
5234
5612
  return numbers.reduce((a, b) => a + b, 0);
5235
5613
  }
5236
5614
 
5237
- const Toolbar = withAnnotation({
5238
- providers: [RefreshService]
5239
- }, function Toolbar() {
5615
+ const InlineToolbar = withAnnotation({
5616
+ providers: [RefreshService, ToolService]
5617
+ }, function Toolbar(props) {
5240
5618
  const selection = inject(Selection);
5241
5619
  const viewDocument = inject(VIEW_CONTAINER);
5242
5620
  const rootComponentRef = inject(RootComponentRef);
5243
5621
  const adapter = inject(DomAdapter);
5244
5622
  const bridge = inject(SelectionBridge);
5623
+ const query = inject(Query);
5245
5624
  const textbus = inject(Textbus);
5246
5625
  const editorService = inject(EditorService);
5247
5626
  const refreshService = inject(RefreshService);
@@ -5364,28 +5743,29 @@ const Toolbar = withAnnotation({
5364
5743
  mousedownSubscription.unsubscribe();
5365
5744
  mouseupSubscription.unsubscribe();
5366
5745
  });
5367
- return withScopedCSS(scopedId$6, () => {
5746
+ return withScopedCSS(scopedId$8, () => {
5368
5747
  const p = viewPosition();
5369
- return (jsxs("div", { class: "toolbar", ref: toolbarRef, style: {
5748
+ return (jsxs("div", { class: ['toolbar', props.theme], ref: toolbarRef, style: {
5370
5749
  left: p.left + 'px',
5371
5750
  top: p.top + 'px',
5372
5751
  pointerEvents: p.isHide ? 'none' : 'initial',
5373
5752
  opacity: p.opacity,
5374
5753
  display: editorService.hideInlineToolbar ? 'none' : '',
5375
5754
  transitionDuration: p.transitionDuration + 's'
5376
- }, children: [selection.commonAncestorComponent instanceof TableComponent && jsxs(Fragment$1, { children: [jsx(ToolbarItem, { children: jsx(MergeCellsTool, {}) }), jsx(ToolbarItem, { children: jsx(SplitCellsTool, {}) }), jsx(ToolbarItem, { children: jsx(CellBackgroundTool, {}) }), jsx(ToolbarItem, { children: jsx(CellAlignTool, {}) })] }, "table"), jsx(ToolbarItem, { children: jsx(BlockTool, {}) }), jsx(ToolbarItem, { children: jsx(AttrTool, {}) }), jsx(ToolbarItem, { children: jsx(BoldTool, {}) }), jsx(ToolbarItem, { children: jsx(ItalicTool, {}) }), jsx(ToolbarItem, { children: jsx(StrikeThroughTool, {}) }), jsx(ToolbarItem, { children: jsx(UnderlineTool, {}) }), jsx(ToolbarItem, { children: jsx(FontSizeTool, {}) }), jsx(ToolbarItem, { children: jsx(FontFamilyTool, {}) }), jsx(ToolbarItem, { children: jsx(LinkTool, { hideToolbar: hideToolbar }) }), jsx(ToolbarItem, { children: jsx(CodeTool, {}) }), jsx(ToolbarItem, { children: jsx(ColorTool, {}) })] }));
5755
+ }, children: [jsx(ToolbarItem, { children: jsx(BlockTool, {}) }), jsx(ToolbarItem, { children: jsx(AttrTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(BoldTool, {}) }), jsx(ToolbarItem, { children: jsx(ItalicTool, {}) }), jsx(ToolbarItem, { children: jsx(StrikeThroughTool, {}) }), jsx(ToolbarItem, { children: jsx(UnderlineTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(FontSizeTool, {}) }), jsx(ToolbarItem, { children: jsx(FontFamilyTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(LinkTool, { hideToolbar: hideToolbar }) }), jsx(ToolbarItem, { children: jsx(CodeTool, {}) }), jsx(ToolbarItem, { children: jsx(ColorTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(SubscriptTool, {}) }), jsx(ToolbarItem, { children: jsx(SuperscriptTool, {}) }), jsx(ToolbarItem, { children: jsx(CleanFormatsTool, {}) }), query.queryComponent(TableComponent).state === QueryStateType.Enabled && jsxs(Fragment$1, { children: [jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(MergeCellsTool, {}) }), jsx(ToolbarItem, { children: jsx(SplitCellsTool, {}) }), jsx(ToolbarItem, { children: jsx(CellBackgroundTool, {}) }), jsx(ToolbarItem, { children: jsx(CellAlignTool, {}) })] }, "table")] }));
5377
5756
  });
5378
5757
  });
5379
5758
 
5380
- class ToolbarPlugin {
5381
- constructor() {
5759
+ class InlineToolbarPlugin {
5760
+ constructor(config = {}) {
5761
+ this.config = config;
5382
5762
  this.app = null;
5383
5763
  }
5384
5764
  setup(injector) {
5385
- const App = function () {
5765
+ const App = () => {
5386
5766
  const readonly = useReadonly();
5387
5767
  return () => {
5388
- return readonly() ? null : jsx(Toolbar, {});
5768
+ return readonly() ? null : jsx(InlineToolbar, { theme: this.config.theme });
5389
5769
  };
5390
5770
  };
5391
5771
  this.app = createApp(jsx(App, {}), {
@@ -5402,6 +5782,133 @@ class ToolbarPlugin {
5402
5782
  }
5403
5783
  }
5404
5784
 
5785
+ var scopedId$7 = "vf-42c12d";
5786
+
5787
+ const StaticToolbar = withAnnotation({
5788
+ providers: [RefreshService, ToolService]
5789
+ }, function Toolbar(props) {
5790
+ const selection = inject(Selection);
5791
+ const textbus = inject(Textbus);
5792
+ const query = inject(Query);
5793
+ const refreshService = inject(RefreshService);
5794
+ const instance = getCurrentInstance();
5795
+ const subscription = merge(textbus.onChange, selection.onChange).pipe(debounceTime(20)).subscribe(() => {
5796
+ refreshService.onRefresh.next();
5797
+ instance.markAsDirtied();
5798
+ });
5799
+ onUnmounted(() => {
5800
+ subscription.unsubscribe();
5801
+ });
5802
+ return withScopedCSS(scopedId$7, () => {
5803
+ return (jsxs("div", { class: ['toolbar', props.theme], children: [jsx(ToolbarItem, { children: jsx(UndoTool, {}) }), jsx(ToolbarItem, { children: jsx(RedoTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(InsertTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(BlockTool, {}) }), jsx(ToolbarItem, { children: jsx(AttrTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(BoldTool, {}) }), jsx(ToolbarItem, { children: jsx(ItalicTool, {}) }), jsx(ToolbarItem, { children: jsx(StrikeThroughTool, {}) }), jsx(ToolbarItem, { children: jsx(UnderlineTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(FontSizeTool, {}) }), jsx(ToolbarItem, { children: jsx(FontFamilyTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(LinkTool, {}) }), jsx(ToolbarItem, { children: jsx(CodeTool, {}) }), jsx(ToolbarItem, { children: jsx(ColorTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(SubscriptTool, {}) }), jsx(ToolbarItem, { children: jsx(SuperscriptTool, {}) }), jsx(ToolbarItem, { children: jsx(CleanFormatsTool, {}) }), query.queryComponent(TableComponent).state === QueryStateType.Enabled && jsxs(Fragment$1, { children: [jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(MergeCellsTool, {}) }), jsx(ToolbarItem, { children: jsx(SplitCellsTool, {}) }), jsx(ToolbarItem, { children: jsx(CellBackgroundTool, {}) }), jsx(ToolbarItem, { children: jsx(CellAlignTool, {}) })] }, "table")] }));
5804
+ });
5805
+ });
5806
+
5807
+ class StaticToolbarPlugin {
5808
+ constructor(options) {
5809
+ this.options = options;
5810
+ this.app = null;
5811
+ this.container = null;
5812
+ }
5813
+ setup(injector) {
5814
+ const container = document.createElement('div');
5815
+ container.style.position = 'relative';
5816
+ container.style.borderRadius = 'inherit';
5817
+ this.app = createApp(jsx(Context, { providers: [{
5818
+ provide: DropdownMenuContainer,
5819
+ useValue: container
5820
+ }], children: jsx(StaticToolbar, { theme: this.options.theme }) }), {
5821
+ context: injector
5822
+ });
5823
+ this.options.host.appendChild(container);
5824
+ this.container = container;
5825
+ this.app.mount(container);
5826
+ }
5827
+ onDestroy() {
5828
+ var _a, _b;
5829
+ (_a = this.container) === null || _a === void 0 ? void 0 : _a.remove();
5830
+ (_b = this.app) === null || _b === void 0 ? void 0 : _b.destroy();
5831
+ }
5832
+ }
5833
+
5834
+ var scopedId$6 = "vf-25fd9c";
5835
+
5836
+ const SuspensionToolbar = withAnnotation({
5837
+ providers: [RefreshService, ToolService]
5838
+ }, function Toolbar(props) {
5839
+ const selection = inject(Selection);
5840
+ const textbus = inject(Textbus);
5841
+ const query = inject(Query);
5842
+ const refreshService = inject(RefreshService);
5843
+ const viewDocument = inject(VIEW_CONTAINER);
5844
+ const instance = getCurrentInstance();
5845
+ const subscription = merge(textbus.onChange, selection.onChange).pipe(debounceTime(20)).subscribe(() => {
5846
+ refreshService.onRefresh.next();
5847
+ instance.markAsDirtied();
5848
+ });
5849
+ onUnmounted(() => {
5850
+ subscription.unsubscribe();
5851
+ });
5852
+ const [styles, updateStyles] = useProduce({
5853
+ top: 0,
5854
+ opacity: 1,
5855
+ });
5856
+ subscription.add(fromEvent(document, 'scroll').pipe(tap(() => {
5857
+ updateStyles(draft => {
5858
+ draft.opacity = 0;
5859
+ });
5860
+ }), debounceTime(100), tap(() => {
5861
+ const rect = viewDocument.getBoundingClientRect();
5862
+ if (rect.top < 10) {
5863
+ updateStyles(draft => {
5864
+ draft.top = Math.min(-rect.top + 10, rect.height - 100);
5865
+ });
5866
+ }
5867
+ else {
5868
+ updateStyles(draft => {
5869
+ draft.top = 0;
5870
+ });
5871
+ }
5872
+ }), delay(100)).subscribe(() => {
5873
+ updateStyles(draft => {
5874
+ draft.opacity = 1;
5875
+ });
5876
+ }));
5877
+ return withScopedCSS(scopedId$6, () => {
5878
+ const s = styles();
5879
+ return (jsxs("div", { class: ['toolbar', props.theme, {
5880
+ suspension: s.top === 0 ? '' : 'suspension'
5881
+ }], style: {
5882
+ top: s.top + 'px',
5883
+ opacity: s.opacity,
5884
+ pointerEvents: s.opacity === 0 ? 'none' : 'initial',
5885
+ }, children: [jsx(ToolbarItem, { children: jsx(UndoTool, {}) }), jsx(ToolbarItem, { children: jsx(RedoTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(InsertTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(BlockTool, {}) }), jsx(ToolbarItem, { children: jsx(AttrTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(BoldTool, {}) }), jsx(ToolbarItem, { children: jsx(ItalicTool, {}) }), jsx(ToolbarItem, { children: jsx(StrikeThroughTool, {}) }), jsx(ToolbarItem, { children: jsx(UnderlineTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(FontSizeTool, {}) }), jsx(ToolbarItem, { children: jsx(FontFamilyTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(LinkTool, {}) }), jsx(ToolbarItem, { children: jsx(CodeTool, {}) }), jsx(ToolbarItem, { children: jsx(ColorTool, {}) }), jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(SubscriptTool, {}) }), jsx(ToolbarItem, { children: jsx(SuperscriptTool, {}) }), jsx(ToolbarItem, { children: jsx(CleanFormatsTool, {}) }), query.queryComponent(TableComponent).state === QueryStateType.Enabled && jsxs(Fragment$1, { children: [jsx(SplitLine, {}), jsx(ToolbarItem, { children: jsx(MergeCellsTool, {}) }), jsx(ToolbarItem, { children: jsx(SplitCellsTool, {}) }), jsx(ToolbarItem, { children: jsx(CellBackgroundTool, {}) }), jsx(ToolbarItem, { children: jsx(CellAlignTool, {}) })] }, "table")] }));
5886
+ });
5887
+ });
5888
+
5889
+ class SuspensionToolbarPlugin {
5890
+ constructor(options = {}) {
5891
+ this.options = options;
5892
+ this.app = null;
5893
+ this.container = null;
5894
+ }
5895
+ setup(injector) {
5896
+ const host = injector.get(VIEW_CONTAINER);
5897
+ const container = document.createElement('div');
5898
+ this.app = createApp(jsx(SuspensionToolbar, { theme: this.options.theme }), {
5899
+ context: injector
5900
+ });
5901
+ host.prepend(container);
5902
+ this.container = container;
5903
+ this.app.mount(container);
5904
+ }
5905
+ onDestroy() {
5906
+ var _a, _b;
5907
+ (_a = this.container) === null || _a === void 0 ? void 0 : _a.remove();
5908
+ (_b = this.app) === null || _b === void 0 ? void 0 : _b.destroy();
5909
+ }
5910
+ }
5911
+
5405
5912
  class Matcher {
5406
5913
  constructor(target, rule) {
5407
5914
  this.target = target;
@@ -5502,6 +6009,10 @@ class Matcher {
5502
6009
  class Organization {
5503
6010
  }
5504
6011
  function registerAtShortcut(textbus) {
6012
+ const organization = textbus.get(Organization, null);
6013
+ if (!organization) {
6014
+ return;
6015
+ }
5505
6016
  const keyboard = textbus.get(Keyboard);
5506
6017
  const selection = textbus.get(Selection);
5507
6018
  const commander = textbus.get(Commander);
@@ -5752,8 +6263,11 @@ class RootComponent extends Component {
5752
6263
  lastContent instanceof TodolistComponent) {
5753
6264
  return;
5754
6265
  }
6266
+ const selection = this.textbus.get(Selection);
5755
6267
  content.retain(content.length);
5756
- content.insert(new ParagraphComponent(this.textbus));
6268
+ const newParagraph = new ParagraphComponent(this.textbus);
6269
+ content.insert(newParagraph);
6270
+ selection.setPosition(newParagraph.state.slot, 0);
5757
6271
  }
5758
6272
  }
5759
6273
  RootComponent.componentName = 'RootComponent';
@@ -5768,14 +6282,22 @@ function RootView(props) {
5768
6282
  sub.unsubscribe();
5769
6283
  };
5770
6284
  });
5771
- onUpdated(() => {
5772
- props.component.afterCheck();
5773
- });
6285
+ const containerRef = createRef();
5774
6286
  const readonly = useReadonly();
5775
6287
  const output = useOutput();
6288
+ function checkContent(ev) {
6289
+ if (ev.target === containerRef.current) {
6290
+ const rect = containerRef.current.getBoundingClientRect();
6291
+ if (rect.bottom - ev.clientY < 40) {
6292
+ props.component.afterCheck();
6293
+ }
6294
+ }
6295
+ }
5776
6296
  return () => {
5777
6297
  const { rootRef } = props;
5778
- 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() }) }));
6298
+ return (jsx("div", { class: "xnote-root", onClick: checkContent, style: !readonly() ? {
6299
+ paddingBottom: '40px'
6300
+ } : {}, dir: "auto", ref: [rootRef, containerRef, ref], "data-component": props.component.name, children: jsx(SlotRender, { slot: content, tag: "div", class: "xnote-content", "data-placeholder": content.isEmpty ? '请输入内容' : '', renderEnv: readonly() || output() }) }));
5779
6301
  };
5780
6302
  }
5781
6303
  const rootComponentLoader = {
@@ -6825,7 +7347,9 @@ class Editor extends Textbus {
6825
7347
  italicFormatLoader,
6826
7348
  linkFormatLoader,
6827
7349
  strikeThroughFormatLoader,
6828
- underlineFormatLoader
7350
+ underlineFormatLoader,
7351
+ subscriptFormatLoader,
7352
+ superscriptFormatLoader
6829
7353
  ], attributeLoaders: [
6830
7354
  cellBackgroundAttrLoader,
6831
7355
  cellAlignAttrLoader,
@@ -6913,7 +7437,9 @@ class Editor extends Textbus {
6913
7437
  italicFormatter,
6914
7438
  linkFormatter,
6915
7439
  strikeThroughFormatter,
6916
- underlineFormatter
7440
+ underlineFormatter,
7441
+ subscriptFormatter,
7442
+ superscriptFormatter
6917
7443
  ], attributes: [
6918
7444
  cellBackgroundAttr,
6919
7445
  cellAlignAttr,
@@ -6922,7 +7448,7 @@ class Editor extends Textbus {
6922
7448
  textIndentAttr
6923
7449
  ], plugins: [
6924
7450
  new LeftToolbarPlugin(),
6925
- new ToolbarPlugin(),
7451
+ new InlineToolbarPlugin()
6926
7452
  ], onAfterStartup(textbus) {
6927
7453
  registerBoldShortcut(textbus);
6928
7454
  registerCodeShortcut(textbus);
@@ -6976,4 +7502,4 @@ class Editor extends Textbus {
6976
7502
  }
6977
7503
  }
6978
7504
 
6979
- export { AtComponent, AtComponentView, AttrTool, BlockTool, BlockquoteComponent, BlockquoteView, BoldTool, Button, CellAlignTool, CellBackgroundTool, CodeTool, ColorPicker, 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, MergeCellsTool, Organization, OutputInjectionToken, ParagraphComponent, ParagraphView, Picker, Popup, RefreshService, RootComponent, RootView, SourceCodeComponent, SourceCodeView, SplitCellsTool, StrikeThroughTool, TableComponent, TableComponentView, TodolistComponent, TodolistView, Toolbar, ToolbarItem, ToolbarPlugin, UnderlineTool, VideoComponent, VideoView, XNoteMessageBug, atComponentLoader, backgroundColorFormatLoader, backgroundColorFormatter, blockquoteComponentLoader, boldFormatLoader, boldFormatter, cellAlignAttr, cellAlignAttrLoader, cellBackgroundAttr, cellBackgroundAttrLoader, 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 };
7505
+ export { AtComponent, AtComponentView, AttrTool, BlockTool, BlockquoteComponent, BlockquoteView, BoldTool, Button, CellAlignTool, CellBackgroundTool, CleanFormatsTool, CodeTool, ColorPicker, ColorTool, ComponentToolbar, Divider, DragResize, Dropdown, DropdownContextService, DropdownMenuContainer, DropdownMenuPortal, DropdownService, Editor, EditorService, FileUploader, FontFamilyTool, FontSizeTool, HighlightBoxComponent, HighlightBoxView, ImageComponent, ImageView, InlineToolbar, InlineToolbarPlugin, InsertMenu, InsertTool, ItalicTool, KatexComponent, KatexComponentView, Keymap, LeftToolbar, LeftToolbarPlugin, LinkJump, LinkTool, ListComponent, ListComponentView, Matcher, MenuHeading, MenuItem, MergeCellsTool, Organization, OutputInjectionToken, ParagraphComponent, ParagraphView, Picker, Popup, RedoTool, RefreshService, RootComponent, RootView, SourceCodeComponent, SourceCodeView, SplitCellsTool, SplitLine, StaticToolbar, StaticToolbarPlugin, StrikeThroughTool, SubscriptTool, SuperscriptTool, SuspensionToolbar, SuspensionToolbarPlugin, TableComponent, TableComponentView, TodolistComponent, TodolistView, ToolbarItem, UnderlineTool, UndoTool, VideoComponent, VideoView, XNoteMessageBug, atComponentLoader, backgroundColorFormatLoader, backgroundColorFormatter, blockquoteComponentLoader, boldFormatLoader, boldFormatter, cellAlignAttr, cellAlignAttrLoader, cellBackgroundAttr, cellBackgroundAttrLoader, 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, subscriptFormatLoader, subscriptFormatter, superscriptFormatLoader, superscriptFormatter, tableComponentLoader, textAlignAttr, textAlignAttrLoader, textIndentAttr, textIndentAttrLoader, toBlockquote, toList, todolistComponentLoader, toggleBold, toggleCode, toggleItalic, toggleStrikeThrough, toggleUnderline, underlineFormatLoader, underlineFormatter, useActiveBlock, useBlockContent, useBlockTransform, useOutput, useReadonly, videoComponentLoader };