@markput/react 0.10.1 → 0.11.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.
package/index.js CHANGED
@@ -392,11 +392,11 @@ var NodeProxy = class NodeProxy {
392
392
  return this.target?.isContentEditable ?? false;
393
393
  }
394
394
  get isCaretAtBeginning() {
395
- if (!this.target) return;
395
+ if (!this.target) return false;
396
396
  return Caret.getCaretIndex(this.target) === 0;
397
397
  }
398
398
  get isCaretAtEnd() {
399
- if (!this.target) return;
399
+ if (!this.target) return false;
400
400
  return Caret.getCaretIndex(this.target) === this.target.textContent.length;
401
401
  }
402
402
  get index() {
@@ -443,16 +443,6 @@ var NodeProxy = class NodeProxy {
443
443
  }
444
444
  };
445
445
  //#endregion
446
- //#region ../../core/src/shared/signals/registry.ts
447
- let _factory;
448
- function setUseHookFactory(f) {
449
- _factory = f;
450
- }
451
- function getUseHookFactory() {
452
- if (!_factory) throw new Error("[markput] setUseHookFactory() must be called before using signal.use()");
453
- return _factory;
454
- }
455
- //#endregion
456
446
  //#region ../../core/src/shared/signals/alien-signals/system.ts
457
447
  let ReactiveFlags = /* @__PURE__ */ function(ReactiveFlags) {
458
448
  ReactiveFlags[ReactiveFlags["None"] = 0] = "None";
@@ -633,17 +623,19 @@ function createReactiveSystem({ update, notify, unwatched }) {
633
623
  }
634
624
  }
635
625
  //#endregion
636
- //#region ../../core/src/shared/signals/alien-signals/index.ts
626
+ //#region ../../core/src/shared/signals/signal.ts
637
627
  let cycle = 0;
638
628
  let batchDepth = 0;
639
629
  let notifyIndex = 0;
640
630
  let queuedLength = 0;
641
631
  let activeSub;
632
+ let mutableScope = false;
642
633
  const queued = [];
643
634
  const { link, unlink, propagate, checkDirty, shallowPropagate } = createReactiveSystem({
644
635
  update(node) {
645
- if (node.depsTail !== void 0) return updateComputed(node);
646
- else return updateSignal(node);
636
+ if ("getter" in node) return updateComputed(node);
637
+ if ("seq" in node) return updateEvent(node);
638
+ return updateSignal(node);
647
639
  },
648
640
  notify(effect) {
649
641
  let insertIndex = queuedLength;
@@ -662,8 +654,16 @@ const { link, unlink, propagate, checkDirty, shallowPropagate } = createReactive
662
654
  }
663
655
  },
664
656
  unwatched(node) {
665
- if (!(node.flags & ReactiveFlags.Mutable)) effectScopeOper.call(node);
666
- else if (node.depsTail !== void 0) {
657
+ if (!(node.flags & ReactiveFlags.Mutable)) {
658
+ if ("fn" in node) {
659
+ const e = node;
660
+ if (e.cleanup !== void 0) {
661
+ e.cleanup();
662
+ e.cleanup = void 0;
663
+ }
664
+ }
665
+ effectScopeOper.call(node);
666
+ } else if (node.depsTail !== void 0) {
667
667
  node.depsTail = void 0;
668
668
  node.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
669
669
  purgeDeps(node);
@@ -675,67 +675,9 @@ function setActiveSub(sub) {
675
675
  activeSub = sub;
676
676
  return prevSub;
677
677
  }
678
- function startBatch() {
679
- ++batchDepth;
680
- }
681
- function endBatch() {
682
- if (!--batchDepth) flush();
683
- }
684
- function signal$1(initialValue) {
685
- return signalOper.bind({
686
- currentValue: initialValue,
687
- pendingValue: initialValue,
688
- subs: void 0,
689
- subsTail: void 0,
690
- flags: ReactiveFlags.Mutable
691
- });
692
- }
693
- function computed$1(getter) {
694
- return computedOper.bind({
695
- value: void 0,
696
- subs: void 0,
697
- subsTail: void 0,
698
- deps: void 0,
699
- depsTail: void 0,
700
- flags: ReactiveFlags.None,
701
- getter
702
- });
703
- }
704
- function effect(fn) {
705
- const e = {
706
- fn,
707
- subs: void 0,
708
- subsTail: void 0,
709
- deps: void 0,
710
- depsTail: void 0,
711
- flags: ReactiveFlags.Watching | ReactiveFlags.RecursedCheck
712
- };
713
- const prevSub = setActiveSub(e);
714
- if (prevSub !== void 0) link(e, prevSub, 0);
715
- try {
716
- e.fn();
717
- } finally {
718
- activeSub = prevSub;
719
- e.flags &= ~ReactiveFlags.RecursedCheck;
720
- }
721
- return effectOper.bind(e);
722
- }
723
- function effectScope(fn) {
724
- const e = {
725
- deps: void 0,
726
- depsTail: void 0,
727
- subs: void 0,
728
- subsTail: void 0,
729
- flags: ReactiveFlags.None
730
- };
731
- const prevSub = setActiveSub(e);
732
- if (prevSub !== void 0) link(e, prevSub, 0);
733
- try {
734
- fn();
735
- } finally {
736
- activeSub = prevSub;
737
- }
738
- return effectScopeOper.bind(e);
678
+ function updateSignal(s) {
679
+ s.flags = ReactiveFlags.Mutable;
680
+ return s.currentValue !== (s.currentValue = s.pendingValue);
739
681
  }
740
682
  function updateComputed(c) {
741
683
  ++cycle;
@@ -744,26 +686,33 @@ function updateComputed(c) {
744
686
  const prevSub = setActiveSub(c);
745
687
  try {
746
688
  const oldValue = c.value;
747
- return oldValue !== (c.value = c.getter(oldValue));
689
+ const newValue = c.getter(oldValue);
690
+ if (c.equalsFn !== void 0 && oldValue !== void 0 && c.equalsFn(oldValue, newValue)) return false;
691
+ return oldValue !== (c.value = newValue);
748
692
  } finally {
749
693
  activeSub = prevSub;
750
694
  c.flags &= ~ReactiveFlags.RecursedCheck;
751
695
  purgeDeps(c);
752
696
  }
753
697
  }
754
- function updateSignal(s) {
755
- s.flags = ReactiveFlags.Mutable;
756
- return s.currentValue !== (s.currentValue = s.pendingValue);
698
+ function updateEvent(e) {
699
+ e.flags = ReactiveFlags.Mutable;
700
+ return true;
757
701
  }
758
702
  function run(e) {
759
703
  const flags = e.flags;
760
704
  if (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && checkDirty(e.deps, e)) {
705
+ if (e.cleanup !== void 0) {
706
+ e.cleanup();
707
+ e.cleanup = void 0;
708
+ }
761
709
  ++cycle;
762
710
  e.depsTail = void 0;
763
711
  e.flags = ReactiveFlags.Watching | ReactiveFlags.RecursedCheck;
764
712
  const prevSub = setActiveSub(e);
765
713
  try {
766
- e.fn();
714
+ const result = e.fn();
715
+ if (typeof result === "function") e.cleanup = result;
767
716
  } finally {
768
717
  activeSub = prevSub;
769
718
  e.flags &= ~ReactiveFlags.RecursedCheck;
@@ -788,36 +737,31 @@ function flush() {
788
737
  queuedLength = 0;
789
738
  }
790
739
  }
791
- function computedOper() {
792
- const flags = this.flags;
793
- if (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && (checkDirty(this.deps, this) || (this.flags = flags & ~ReactiveFlags.Pending, false))) {
794
- if (updateComputed(this)) {
795
- const subs = this.subs;
796
- if (subs !== void 0) shallowPropagate(subs);
797
- }
798
- } else if (!flags) {
799
- this.flags = ReactiveFlags.Mutable | ReactiveFlags.RecursedCheck;
800
- const prevSub = setActiveSub(this);
801
- try {
802
- this.value = this.getter();
803
- } finally {
804
- activeSub = prevSub;
805
- this.flags &= ~ReactiveFlags.RecursedCheck;
806
- }
807
- }
808
- const sub = activeSub;
809
- if (sub !== void 0) link(this, sub, cycle);
810
- return this.value;
740
+ function purgeDeps(sub) {
741
+ const depsTail = sub.depsTail;
742
+ let dep = depsTail !== void 0 ? depsTail.nextDep : sub.deps;
743
+ while (dep !== void 0) dep = unlink(dep, sub);
811
744
  }
812
745
  function signalOper(...value) {
813
746
  if (value.length) {
814
- if (this.pendingValue !== (this.pendingValue = value[0])) {
815
- this.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
816
- const subs = this.subs;
817
- if (subs !== void 0) {
818
- propagate(subs);
819
- if (!batchDepth) flush();
820
- }
747
+ if (this.isReadonly && !mutableScope) return;
748
+ const v = value[0];
749
+ if (v === void 0) {
750
+ if (this.hasDefault ? this.pendingValue === void 0 || this.pendingValue === this.defaultValue : this.pendingValue === void 0) return;
751
+ this.pendingValue = void 0;
752
+ } else {
753
+ const current = this.pendingValue;
754
+ const effectiveCurrent = current === void 0 && this.hasDefault ? this.defaultValue : current;
755
+ if (this.equalsFn !== void 0) {
756
+ if (this.equalsFn(effectiveCurrent, v)) return;
757
+ } else if (effectiveCurrent === v) return;
758
+ this.pendingValue = v;
759
+ }
760
+ this.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
761
+ const subs = this.subs;
762
+ if (subs !== void 0) {
763
+ propagate(subs);
764
+ if (!batchDepth) flush();
821
765
  }
822
766
  } else {
823
767
  if (this.flags & ReactiveFlags.Dirty) {
@@ -834,10 +778,44 @@ function signalOper(...value) {
834
778
  }
835
779
  sub = sub.subs?.sub;
836
780
  }
837
- return this.currentValue;
781
+ const v = this.currentValue;
782
+ if (v === void 0 && this.hasDefault) return this.defaultValue;
783
+ return v;
784
+ }
785
+ }
786
+ function computedOper() {
787
+ const flags = this.flags;
788
+ const deps = this.deps;
789
+ if (flags & ReactiveFlags.Dirty || flags & ReactiveFlags.Pending && (checkDirty(deps, this) || (this.flags = flags & ~ReactiveFlags.Pending, false))) {
790
+ if (updateComputed(this)) {
791
+ const subs = this.subs;
792
+ if (subs !== void 0) shallowPropagate(subs);
793
+ }
794
+ } else if (!flags) {
795
+ this.flags = ReactiveFlags.Mutable | ReactiveFlags.RecursedCheck;
796
+ const prevSub = setActiveSub(this);
797
+ try {
798
+ this.value = this.getter();
799
+ } finally {
800
+ activeSub = prevSub;
801
+ this.flags &= ~ReactiveFlags.RecursedCheck;
802
+ }
838
803
  }
804
+ const sub = activeSub;
805
+ if (sub !== void 0) link(this, sub, cycle);
806
+ return this.value;
807
+ }
808
+ function eventReadOper() {
809
+ if (this.flags & ReactiveFlags.Dirty) updateEvent(this);
810
+ const sub = activeSub;
811
+ if (sub !== void 0) link(this, sub, cycle);
812
+ return this.payload;
839
813
  }
840
814
  function effectOper() {
815
+ if (this.cleanup !== void 0) {
816
+ this.cleanup();
817
+ this.cleanup = void 0;
818
+ }
841
819
  effectScopeOper.call(this);
842
820
  }
843
821
  function effectScopeOper() {
@@ -847,111 +825,101 @@ function effectScopeOper() {
847
825
  const sub = this.subs;
848
826
  if (sub !== void 0) unlink(sub);
849
827
  }
850
- function purgeDeps(sub) {
851
- const depsTail = sub.depsTail;
852
- let dep = depsTail !== void 0 ? depsTail.nextDep : sub.deps;
853
- while (dep !== void 0) dep = unlink(dep, sub);
828
+ function isReactive(fn) {
829
+ if (typeof fn !== "function") return false;
830
+ const name = fn.name;
831
+ return name === "bound " + signalOper.name || name === "bound " + computedOper.name;
854
832
  }
855
- //#endregion
856
- //#region ../../core/src/shared/signals/signal.ts
857
833
  function signal(initial, opts) {
858
- const hasCustomEquals = opts?.equals !== void 0;
859
- const equalsOpt = hasCustomEquals ? opts.equals : void 0;
860
- if (hasCustomEquals && equalsOpt === false) {
861
- const _default = initial;
862
- const hasDefault = initial !== void 0;
863
- let seq = 0;
864
- const inner = signal$1(void 0);
865
- const read = () => {
866
- const box = inner();
867
- if (box === void 0) return hasDefault ? _default : void 0;
868
- return box.v;
869
- };
870
- const callable = function signalCallable(...args) {
871
- if (args.length) if (args[0] === void 0) {
872
- if (hasDefault && inner() === void 0) return;
873
- inner(void 0);
874
- } else inner({
875
- v: args[0],
876
- seq: seq++
877
- });
878
- else return read();
879
- };
880
- callable.use = (() => getUseHookFactory()(callable)());
881
- return callable;
882
- }
883
- if (hasCustomEquals && typeof equalsOpt === "function") {
884
- const equalsFn = equalsOpt;
885
- const _default = initial;
886
- const hasDefault = initial !== void 0;
887
- const inner = signal$1(void 0);
888
- const read = () => {
889
- const v = inner();
890
- if (v === void 0 && hasDefault) return _default;
891
- return v;
892
- };
893
- const callable = function signalCallable(...args) {
894
- if (args.length) {
895
- if (args[0] === void 0) {
896
- if (hasDefault && inner() === void 0) return;
897
- inner(void 0);
898
- } else if (!equalsFn(read(), args[0])) inner(args[0]);
899
- } else return read();
900
- };
901
- callable.use = (() => getUseHookFactory()(callable)());
902
- return callable;
903
- }
904
- const _default = initial;
905
- const hasDefault = initial !== void 0;
906
- const inner = signal$1(void 0);
907
- const read = () => {
908
- const v = inner();
909
- if (v === void 0 && hasDefault) return _default;
910
- return v;
911
- };
912
- const callable = function signalCallable(...args) {
913
- if (args.length) {
914
- const v = args[0];
915
- if (v === void 0 && hasDefault) {
916
- if (inner() === void 0) return;
917
- inner(void 0);
918
- } else {
919
- const current = inner();
920
- if ((current === void 0 && hasDefault ? _default : current) !== v) inner(v);
921
- }
922
- } else return read();
834
+ const node = {
835
+ currentValue: initial,
836
+ pendingValue: initial,
837
+ defaultValue: initial,
838
+ hasDefault: initial !== void 0,
839
+ equalsFn: opts?.equals ?? void 0,
840
+ isReadonly: !!opts?.readonly,
841
+ subs: void 0,
842
+ subsTail: void 0,
843
+ flags: ReactiveFlags.Mutable
923
844
  };
924
- callable.use = (() => getUseHookFactory()(callable)());
925
- return callable;
845
+ return signalOper.bind(node);
926
846
  }
927
- function computed(getter) {
928
- const inner = computed$1(getter);
929
- const callable = function computedCallable() {
930
- return inner();
847
+ function computed(getter, opts) {
848
+ const node = {
849
+ value: void 0,
850
+ subs: void 0,
851
+ subsTail: void 0,
852
+ deps: void 0,
853
+ depsTail: void 0,
854
+ flags: ReactiveFlags.None,
855
+ getter,
856
+ equalsFn: opts?.equals ?? void 0
931
857
  };
932
- callable.use = (() => getUseHookFactory()(callable)());
933
- return callable;
858
+ return computedOper.bind(node);
934
859
  }
935
860
  function event() {
936
- let seq = 0;
937
- const inner = signal$1(void 0);
938
- const callable = function eventCallable(payload) {
939
- inner({
940
- v: payload,
941
- id: ++seq
942
- });
861
+ const node = {
862
+ payload: void 0,
863
+ seq: 0,
864
+ subs: void 0,
865
+ subsTail: void 0,
866
+ flags: ReactiveFlags.Mutable
943
867
  };
944
- callable.read = () => {
945
- const box = inner();
946
- return box !== void 0 ? box.v : void 0;
868
+ const callable = function eventCallable(payload) {
869
+ node.payload = payload;
870
+ node.seq++;
871
+ node.flags = ReactiveFlags.Mutable | ReactiveFlags.Dirty;
872
+ const subs = node.subs;
873
+ if (subs !== void 0) {
874
+ propagate(subs);
875
+ if (!batchDepth) flush();
876
+ }
947
877
  };
948
- callable.use = () => getUseHookFactory()(callable.read)();
878
+ callable.read = eventReadOper.bind(node);
949
879
  return callable;
950
880
  }
881
+ function alienEffect(fn) {
882
+ const e = {
883
+ fn,
884
+ cleanup: void 0,
885
+ subs: void 0,
886
+ subsTail: void 0,
887
+ deps: void 0,
888
+ depsTail: void 0,
889
+ flags: ReactiveFlags.Watching | ReactiveFlags.RecursedCheck
890
+ };
891
+ const prevSub = setActiveSub(e);
892
+ if (prevSub !== void 0) link(e, prevSub, 0);
893
+ try {
894
+ const result = e.fn();
895
+ if (typeof result === "function") e.cleanup = result;
896
+ } finally {
897
+ activeSub = prevSub;
898
+ e.flags &= ~ReactiveFlags.RecursedCheck;
899
+ }
900
+ return effectOper.bind(e);
901
+ }
902
+ function effectScope(fn) {
903
+ const e = {
904
+ deps: void 0,
905
+ depsTail: void 0,
906
+ subs: void 0,
907
+ subsTail: void 0,
908
+ flags: ReactiveFlags.None
909
+ };
910
+ const prevSub = setActiveSub(e);
911
+ if (prevSub !== void 0) link(e, prevSub, 0);
912
+ try {
913
+ fn();
914
+ } finally {
915
+ activeSub = prevSub;
916
+ }
917
+ return effectScopeOper.bind(e);
918
+ }
951
919
  function watch(dep, fn) {
952
920
  let initialized = false;
953
921
  let oldValue;
954
- return effect(() => {
922
+ return alienEffect(() => {
955
923
  const newValue = "read" in dep ? dep.read() : dep();
956
924
  if (!initialized) {
957
925
  initialized = true;
@@ -960,22 +928,34 @@ function watch(dep, fn) {
960
928
  }
961
929
  const prev = oldValue;
962
930
  oldValue = newValue;
963
- const prevSub = setActiveSub(void 0);
964
- try {
965
- fn(newValue, prev);
966
- } finally {
967
- setActiveSub(prevSub);
968
- }
931
+ untracked(() => fn(newValue, prev));
969
932
  });
970
933
  }
971
- function batch(fn) {
972
- startBatch();
934
+ function batch(fn, opts) {
935
+ const prevMutable = mutableScope;
936
+ if (opts?.mutable) mutableScope = true;
937
+ ++batchDepth;
973
938
  try {
974
939
  fn();
975
940
  } finally {
976
- endBatch();
941
+ if (!--batchDepth) flush();
942
+ mutableScope = prevMutable;
977
943
  }
978
944
  }
945
+ function untracked(fn) {
946
+ const prev = setActiveSub(void 0);
947
+ try {
948
+ return fn();
949
+ } finally {
950
+ setActiveSub(prev);
951
+ }
952
+ }
953
+ function listen(target, event, handler, options) {
954
+ return alienEffect(() => {
955
+ target.addEventListener(event, handler, options);
956
+ return () => target.removeEventListener(event, handler, options);
957
+ });
958
+ }
979
959
  //#endregion
980
960
  //#region ../../core/src/features/parsing/parser/constants.ts
981
961
  /**
@@ -2170,23 +2150,30 @@ function getTokensByUI(store) {
2170
2150
  const tokens = store.state.tokens();
2171
2151
  if (!parser) return tokens;
2172
2152
  const parsed = parser.parse(focus.content);
2173
- if (parsed.length === 1) return tokens;
2153
+ if (parsed.length <= 1) return tokens;
2174
2154
  return tokens.toSpliced(focus.index, 1, ...parsed);
2175
2155
  }
2176
- function getTokensByValue(store) {
2177
- const value = store.state.value();
2178
- const ranges = getRangeMap(store);
2179
- const gap = findGap(store.state.previousValue(), value);
2156
+ function computeTokensFromValue(store) {
2157
+ const value = store.props.value();
2158
+ const previousValue = store.state.previousValue();
2159
+ const gap = findGap(previousValue, value);
2180
2160
  if (!gap.left && !gap.right) {
2181
2161
  store.state.previousValue(value);
2182
2162
  return store.state.tokens();
2183
2163
  }
2164
+ if (gap.left === 0 && previousValue !== void 0 && gap.right !== void 0 && gap.right >= previousValue.length) {
2165
+ store.state.previousValue(value);
2166
+ return parseWithParser(store, value ?? "");
2167
+ }
2184
2168
  store.state.previousValue(value);
2169
+ const ranges = getRangeMap(store);
2185
2170
  const tokens = store.state.tokens();
2186
2171
  if (gap.left !== void 0 && ranges.includes(gap.left) && gap.right !== void 0 && Math.abs(gap.left - gap.right) > 1) {
2187
2172
  const updatedIndex = ranges.indexOf(gap.left);
2188
- const parsed = parseUnionLabels(store, updatedIndex - 1, updatedIndex);
2189
- return tokens.toSpliced(updatedIndex - 1, 2, ...parsed);
2173
+ if (updatedIndex > 0) {
2174
+ const parsed = parseUnionLabels(store, updatedIndex - 1, updatedIndex);
2175
+ return tokens.toSpliced(updatedIndex - 1, 2, ...parsed);
2176
+ }
2190
2177
  }
2191
2178
  if (gap.left !== void 0) {
2192
2179
  const [updatedIndex] = getClosestIndexes(ranges, gap.left);
@@ -2235,9 +2222,6 @@ function parseWithParser(store, value) {
2235
2222
  //#region ../../core/src/features/parsing/ParseFeature.ts
2236
2223
  var ParseFeature = class {
2237
2224
  #scope;
2238
- #initialized = false;
2239
- #lastValue;
2240
- #lastParser;
2241
2225
  constructor(store) {
2242
2226
  this.store = store;
2243
2227
  }
@@ -2246,30 +2230,18 @@ var ParseFeature = class {
2246
2230
  this.sync();
2247
2231
  this.#scope = effectScope(() => {
2248
2232
  this.#subscribeParse();
2249
- this.#subscribeUpdated();
2233
+ this.#subscribeReactiveParse();
2250
2234
  });
2251
2235
  }
2252
2236
  disable() {
2253
2237
  this.#scope?.();
2254
2238
  this.#scope = void 0;
2255
- this.#initialized = false;
2256
2239
  }
2257
2240
  sync() {
2258
2241
  const { store } = this;
2259
- const inputValue = store.state.value() ?? store.state.defaultValue() ?? "";
2242
+ const inputValue = store.props.value() ?? store.props.defaultValue() ?? "";
2260
2243
  store.state.tokens(parseWithParser(store, inputValue));
2261
2244
  store.state.previousValue(inputValue);
2262
- this.#lastValue = store.state.value();
2263
- this.#lastParser = store.computed.parser();
2264
- this.#initialized = true;
2265
- }
2266
- hasChanged() {
2267
- const value = this.store.state.value();
2268
- const parser = this.store.computed.parser();
2269
- if (this.#initialized && value === this.#lastValue && parser === this.#lastParser) return false;
2270
- this.#lastValue = value;
2271
- this.#lastParser = parser;
2272
- return true;
2273
2245
  }
2274
2246
  #subscribeParse() {
2275
2247
  const { store } = this;
@@ -2280,13 +2252,12 @@ var ParseFeature = class {
2280
2252
  store.state.previousValue(text);
2281
2253
  return;
2282
2254
  }
2283
- store.state.tokens(store.nodes.focus.target ? getTokensByUI(store) : getTokensByValue(store));
2255
+ store.state.tokens(store.nodes.focus.target ? getTokensByUI(store) : computeTokensFromValue(store));
2284
2256
  });
2285
2257
  }
2286
- #subscribeUpdated() {
2258
+ #subscribeReactiveParse() {
2287
2259
  const { store } = this;
2288
- watch(store.event.updated, () => {
2289
- if (!this.hasChanged()) return;
2260
+ watch(computed(() => [store.props.value(), store.computed.parser()]), () => {
2290
2261
  if (!store.state.recovery()) store.event.parse();
2291
2262
  });
2292
2263
  }
@@ -2334,7 +2305,7 @@ function isFullSelection(store) {
2334
2305
  }
2335
2306
  function selectAllText(store, event) {
2336
2307
  if ((event.ctrlKey || event.metaKey) && event.code === "KeyA") {
2337
- if (store.state.drag()) return;
2308
+ if (store.computed.isBlock()) return;
2338
2309
  event.preventDefault();
2339
2310
  const selection = window.getSelection();
2340
2311
  const anchorNode = store.refs.container?.firstChild;
@@ -2347,10 +2318,6 @@ function selectAllText(store, event) {
2347
2318
  //#endregion
2348
2319
  //#region ../../core/src/features/selection/TextSelectionFeature.ts
2349
2320
  var TextSelectionFeature = class {
2350
- #mousedownHandler;
2351
- #mousemoveHandler;
2352
- #mouseupHandler;
2353
- #selectionchangeHandler;
2354
2321
  #scope;
2355
2322
  #pressedNode = null;
2356
2323
  #isPressed = false;
@@ -2358,61 +2325,47 @@ var TextSelectionFeature = class {
2358
2325
  this.store = store;
2359
2326
  }
2360
2327
  enable() {
2361
- if (this.#mousedownHandler) return;
2362
- this.#mousedownHandler = (e) => {
2363
- this.#pressedNode = nodeTarget(e);
2364
- this.#isPressed = true;
2365
- };
2366
- this.#mousemoveHandler = (e) => {
2367
- const container = this.store.refs.container;
2368
- if (!container) return;
2369
- const isPressed = this.#isPressed;
2370
- const isNotInnerSome = !container.contains(this.#pressedNode) || this.#pressedNode !== e.target;
2371
- const isInside = window.getSelection()?.containsNode(container, true);
2372
- if (isPressed && isNotInnerSome && isInside) {
2373
- if (this.store.state.selecting() !== "drag") this.store.state.selecting("drag");
2374
- }
2375
- };
2376
- this.#mouseupHandler = () => {
2377
- this.#isPressed = false;
2378
- this.#pressedNode = null;
2379
- if (this.store.state.selecting() === "drag") {
2328
+ if (this.#scope) return;
2329
+ this.#scope = effectScope(() => {
2330
+ listen(document, "mousedown", (e) => {
2331
+ this.#pressedNode = nodeTarget(e);
2332
+ this.#isPressed = true;
2333
+ });
2334
+ listen(document, "mousemove", (e) => {
2335
+ const container = this.store.refs.container;
2336
+ if (!container) return;
2337
+ const isPressed = this.#isPressed;
2338
+ const isNotInnerSome = !container.contains(this.#pressedNode) || this.#pressedNode !== e.target;
2339
+ const isInside = window.getSelection()?.containsNode(container, true);
2340
+ if (isPressed && isNotInnerSome && isInside) {
2341
+ if (this.store.state.selecting() !== "drag") this.store.state.selecting("drag");
2342
+ }
2343
+ });
2344
+ listen(document, "mouseup", () => {
2345
+ this.#isPressed = false;
2346
+ this.#pressedNode = null;
2347
+ if (this.store.state.selecting() === "drag") {
2348
+ const sel = window.getSelection();
2349
+ if (!sel || sel.isCollapsed) this.store.state.selecting(void 0);
2350
+ }
2351
+ });
2352
+ listen(document, "selectionchange", () => {
2353
+ if (this.store.state.selecting() !== "drag") return;
2380
2354
  const sel = window.getSelection();
2381
2355
  if (!sel || sel.isCollapsed) this.store.state.selecting(void 0);
2382
- }
2383
- };
2384
- this.#selectionchangeHandler = () => {
2385
- if (this.store.state.selecting() !== "drag") return;
2386
- const sel = window.getSelection();
2387
- if (!sel || sel.isCollapsed) this.store.state.selecting(void 0);
2388
- };
2389
- this.#scope = effectScope(() => {
2390
- effect(() => {
2356
+ });
2357
+ alienEffect(() => {
2391
2358
  if (this.store.state.selecting() !== "drag") return;
2392
2359
  const container = this.store.refs.container;
2393
2360
  if (!container) return;
2394
2361
  container.querySelectorAll("[contenteditable=\"true\"]").forEach((el) => el.contentEditable = "false");
2395
2362
  });
2396
2363
  });
2397
- document.addEventListener("mousedown", this.#mousedownHandler);
2398
- document.addEventListener("mousemove", this.#mousemoveHandler);
2399
- document.addEventListener("mouseup", this.#mouseupHandler);
2400
- document.addEventListener("selectionchange", this.#selectionchangeHandler);
2401
2364
  }
2402
2365
  disable() {
2403
2366
  if (this.store.state.selecting() === "drag") this.store.state.selecting(void 0);
2404
2367
  this.#scope?.();
2405
2368
  this.#scope = void 0;
2406
- if (this.#mousedownHandler) {
2407
- document.removeEventListener("mousedown", this.#mousedownHandler);
2408
- if (this.#mousemoveHandler) document.removeEventListener("mousemove", this.#mousemoveHandler);
2409
- if (this.#mouseupHandler) document.removeEventListener("mouseup", this.#mouseupHandler);
2410
- if (this.#selectionchangeHandler) document.removeEventListener("selectionchange", this.#selectionchangeHandler);
2411
- this.#mousedownHandler = void 0;
2412
- this.#mousemoveHandler = void 0;
2413
- this.#mouseupHandler = void 0;
2414
- this.#selectionchangeHandler = void 0;
2415
- }
2416
2369
  this.#pressedNode = null;
2417
2370
  this.#isPressed = false;
2418
2371
  }
@@ -2420,28 +2373,27 @@ var TextSelectionFeature = class {
2420
2373
  //#endregion
2421
2374
  //#region ../../core/src/features/arrownav/ArrowNavFeature.ts
2422
2375
  var ArrowNavFeature = class {
2423
- #keydownHandler;
2376
+ #scope;
2424
2377
  constructor(store) {
2425
2378
  this.store = store;
2426
2379
  }
2427
2380
  enable() {
2428
- if (this.#keydownHandler) return;
2381
+ if (this.#scope) return;
2429
2382
  const container = this.store.refs.container;
2430
2383
  if (!container) return;
2431
- this.#keydownHandler = (e) => {
2432
- if (this.store.state.drag()) return;
2433
- if (!this.store.nodes.focus.target) return;
2434
- if (e.key === KEYBOARD.LEFT) shiftFocusPrev(this.store, e);
2435
- else if (e.key === KEYBOARD.RIGHT) shiftFocusNext(this.store, e);
2436
- selectAllText(this.store, e);
2437
- };
2438
- container.addEventListener("keydown", this.#keydownHandler);
2384
+ this.#scope = effectScope(() => {
2385
+ listen(container, "keydown", (e) => {
2386
+ if (this.store.computed.isBlock()) return;
2387
+ if (!this.store.nodes.focus.target) return;
2388
+ if (e.key === KEYBOARD.LEFT) shiftFocusPrev(this.store, e);
2389
+ else if (e.key === KEYBOARD.RIGHT) shiftFocusNext(this.store, e);
2390
+ selectAllText(this.store, e);
2391
+ });
2392
+ });
2439
2393
  }
2440
2394
  disable() {
2441
- const container = this.store.refs.container;
2442
- if (!container || !this.#keydownHandler) return;
2443
- container.removeEventListener("keydown", this.#keydownHandler);
2444
- this.#keydownHandler = void 0;
2395
+ this.#scope?.();
2396
+ this.#scope = void 0;
2445
2397
  }
2446
2398
  };
2447
2399
  //#endregion
@@ -2567,53 +2519,46 @@ function trimBoundaryTokens({ tokens, startOffset, endOffset }) {
2567
2519
  });
2568
2520
  }
2569
2521
  var CopyFeature = class {
2570
- #copyHandler;
2571
- #cutHandler;
2522
+ #scope;
2572
2523
  constructor(store) {
2573
2524
  this.store = store;
2574
2525
  }
2575
2526
  enable() {
2576
- if (this.#copyHandler) return;
2577
- this.#copyHandler = (e) => {
2578
- this.#handleCopy(e);
2579
- };
2580
- this.#cutHandler = (e) => {
2581
- if (!this.#handleCopy(e)) return;
2582
- const result = selectionToTokens(this.store);
2583
- if (!result || result.tokens.length === 0) return;
2584
- const first = result.tokens[0];
2585
- const last = result.tokens[result.tokens.length - 1];
2586
- const rawStart = first.type === "text" ? first.position.start + result.startOffset : first.position.start;
2587
- const rawEnd = last.type === "text" ? last.position.start + result.endOffset : last.position.end;
2588
- const value = this.store.state.previousValue() ?? this.store.state.value() ?? "";
2589
- if (rawStart === rawEnd) return;
2590
- const newValue = value.slice(0, rawStart) + value.slice(rawEnd);
2591
- this.store.state.innerValue(newValue);
2592
- const newTokens = this.store.state.tokens();
2593
- let targetIdx = newTokens.findIndex((t) => t.type === "text" && rawStart >= t.position.start && rawStart <= t.position.end);
2594
- if (targetIdx === -1) targetIdx = newTokens.length - 1;
2595
- const caretWithinToken = rawStart - newTokens[targetIdx].position.start;
2596
- this.store.state.recovery({
2597
- anchor: this.store.nodes.focus,
2598
- caret: caretWithinToken,
2599
- isNext: true,
2600
- childIndex: targetIdx - 2
2601
- });
2602
- };
2527
+ if (this.#scope) return;
2603
2528
  const container = this.store.refs.container;
2604
- container?.addEventListener("copy", this.#copyHandler);
2605
- container?.addEventListener("cut", this.#cutHandler);
2529
+ if (!container) return;
2530
+ this.#scope = effectScope(() => {
2531
+ listen(container, "copy", (e) => {
2532
+ this.#handleCopy(e);
2533
+ });
2534
+ listen(container, "cut", (e) => {
2535
+ if (!this.#handleCopy(e)) return;
2536
+ const result = selectionToTokens(this.store);
2537
+ if (!result || result.tokens.length === 0) return;
2538
+ const first = result.tokens[0];
2539
+ const last = result.tokens[result.tokens.length - 1];
2540
+ const rawStart = first.type === "text" ? first.position.start + result.startOffset : first.position.start;
2541
+ const rawEnd = last.type === "text" ? last.position.start + result.endOffset : last.position.end;
2542
+ const value = this.store.computed.currentValue();
2543
+ if (rawStart === rawEnd) return;
2544
+ const newValue = value.slice(0, rawStart) + value.slice(rawEnd);
2545
+ this.store.state.innerValue(newValue);
2546
+ const newTokens = this.store.state.tokens();
2547
+ let targetIdx = newTokens.findIndex((t) => t.type === "text" && rawStart >= t.position.start && rawStart <= t.position.end);
2548
+ if (targetIdx === -1) targetIdx = newTokens.length - 1;
2549
+ const caretWithinToken = rawStart - newTokens[targetIdx].position.start;
2550
+ this.store.state.recovery({
2551
+ anchor: this.store.nodes.focus,
2552
+ caret: caretWithinToken,
2553
+ isNext: true,
2554
+ childIndex: targetIdx - 2
2555
+ });
2556
+ });
2557
+ });
2606
2558
  }
2607
2559
  disable() {
2608
- const container = this.store.refs.container;
2609
- if (this.#copyHandler) {
2610
- container?.removeEventListener("copy", this.#copyHandler);
2611
- this.#copyHandler = void 0;
2612
- }
2613
- if (this.#cutHandler) {
2614
- container?.removeEventListener("cut", this.#cutHandler);
2615
- this.#cutHandler = void 0;
2616
- }
2560
+ this.#scope?.();
2561
+ this.#scope = void 0;
2617
2562
  }
2618
2563
  #handleCopy(e) {
2619
2564
  const container = this.store.refs.container;
@@ -2771,7 +2716,7 @@ function deleteMark(place, store) {
2771
2716
  anchor: caretAnchor.prev,
2772
2717
  caret
2773
2718
  });
2774
- store.state.onChange()?.(toString(store.state.tokens()));
2719
+ store.event.change();
2775
2720
  queueMicrotask(() => {
2776
2721
  const target = childAt(store.refs.container, targetIndex);
2777
2722
  if (!target) return;
@@ -2795,11 +2740,11 @@ var ContentEditableFeature = class {
2795
2740
  enable() {
2796
2741
  if (this.#scope) return;
2797
2742
  this.#scope = effectScope(() => {
2798
- effect(() => {
2799
- this.store.state.readOnly();
2743
+ alienEffect(() => {
2744
+ this.store.props.readOnly();
2800
2745
  this.sync();
2801
2746
  });
2802
- effect(() => {
2747
+ alienEffect(() => {
2803
2748
  if (this.store.state.selecting() === void 0) this.sync();
2804
2749
  });
2805
2750
  watch(this.store.event.sync, () => {
@@ -2814,11 +2759,11 @@ var ContentEditableFeature = class {
2814
2759
  sync() {
2815
2760
  const container = this.store.refs.container;
2816
2761
  if (!container) return;
2817
- const readOnly = this.store.state.readOnly();
2762
+ const readOnly = this.store.props.readOnly();
2818
2763
  const value = readOnly ? "false" : "true";
2819
2764
  const children = container.children;
2820
- const isDrag = !!this.store.state.drag();
2821
- if (isDrag) {
2765
+ const isBlock = this.store.computed.isBlock();
2766
+ if (isBlock) {
2822
2767
  const tokens = this.store.state.tokens();
2823
2768
  for (let i = 0; i < tokens.length && i < children.length; i++) {
2824
2769
  const el = childAt(container, i);
@@ -2832,7 +2777,7 @@ var ContentEditableFeature = class {
2832
2777
  if (el) el.contentEditable = value;
2833
2778
  }
2834
2779
  const tokens = this.store.state.tokens();
2835
- if (isDrag) this.#syncDragTextContent(tokens, container, readOnly);
2780
+ if (isBlock) this.#syncDragTextContent(tokens, container, readOnly);
2836
2781
  else this.#syncTextContent(tokens, container);
2837
2782
  }
2838
2783
  #syncTextContent(tokens, parent) {
@@ -3025,37 +2970,32 @@ function isTextLikeRow(token) {
3025
2970
  return token.descriptor.hasSlot && token.descriptor.segments.length === 1;
3026
2971
  }
3027
2972
  var BlockEditFeature = class {
3028
- #keydownHandler;
3029
- #beforeInputHandler;
2973
+ #scope;
3030
2974
  constructor(store) {
3031
2975
  this.store = store;
3032
2976
  }
3033
2977
  enable() {
3034
- if (this.#keydownHandler) return;
2978
+ if (this.#scope) return;
3035
2979
  const container = this.store.refs.container;
3036
2980
  if (!container) return;
3037
- this.#keydownHandler = (e) => {
3038
- if (!this.store.state.drag()) return;
3039
- if (e.key === KEYBOARD.LEFT || e.key === KEYBOARD.RIGHT) this.#handleBlockArrowLeftRight(e, e.key === KEYBOARD.LEFT ? "left" : "right");
3040
- else if (e.key === KEYBOARD.UP || e.key === KEYBOARD.DOWN) this.#handleArrowUpDown(e);
3041
- this.#handleDelete(e);
3042
- this.#handleEnter(e);
3043
- };
3044
- this.#beforeInputHandler = (e) => {
3045
- if (!this.store.state.drag()) return;
3046
- if (e.defaultPrevented) return;
3047
- this.#handleBlockBeforeInput(e);
3048
- };
3049
- container.addEventListener("keydown", this.#keydownHandler);
3050
- container.addEventListener("beforeinput", this.#beforeInputHandler, true);
2981
+ this.#scope = effectScope(() => {
2982
+ listen(container, "keydown", (e) => {
2983
+ if (!this.store.computed.isBlock()) return;
2984
+ if (e.key === KEYBOARD.LEFT || e.key === KEYBOARD.RIGHT) this.#handleBlockArrowLeftRight(e, e.key === KEYBOARD.LEFT ? "left" : "right");
2985
+ else if (e.key === KEYBOARD.UP || e.key === KEYBOARD.DOWN) this.#handleArrowUpDown(e);
2986
+ this.#handleDelete(e);
2987
+ this.#handleEnter(e);
2988
+ });
2989
+ listen(container, "beforeinput", (e) => {
2990
+ if (!this.store.computed.isBlock()) return;
2991
+ if (e.defaultPrevented) return;
2992
+ this.#handleBlockBeforeInput(e);
2993
+ }, true);
2994
+ });
3051
2995
  }
3052
2996
  disable() {
3053
- const container = this.store.refs.container;
3054
- if (!container || !this.#keydownHandler) return;
3055
- container.removeEventListener("keydown", this.#keydownHandler);
3056
- if (this.#beforeInputHandler) container.removeEventListener("beforeinput", this.#beforeInputHandler, true);
3057
- this.#keydownHandler = void 0;
3058
- this.#beforeInputHandler = void 0;
2997
+ this.#scope?.();
2998
+ this.#scope = void 0;
3059
2999
  }
3060
3000
  #handleDelete(event) {
3061
3001
  const container = this.store.refs.container;
@@ -3066,8 +3006,8 @@ var BlockEditFeature = class {
3066
3006
  const rows = this.store.state.tokens();
3067
3007
  if (blockIndex >= rows.length) return;
3068
3008
  const token = rows[blockIndex];
3069
- const value = this.store.state.previousValue() ?? this.store.state.value() ?? "";
3070
- if (!this.store.state.onChange()) return;
3009
+ const value = this.store.computed.currentValue();
3010
+ if (!this.store.props.onChange()) return;
3071
3011
  if (event.key === KEYBOARD.BACKSPACE) {
3072
3012
  const blockDiv = blockDivs[blockIndex];
3073
3013
  const caretAtStart = Caret.getCaretIndex(blockDiv) === 0;
@@ -3190,9 +3130,9 @@ var BlockEditFeature = class {
3190
3130
  const rows = this.store.state.tokens();
3191
3131
  const token = rows[blockIndex];
3192
3132
  const blockDiv = blockDivs[blockIndex];
3193
- const value = this.store.state.previousValue() ?? this.store.state.value() ?? "";
3194
- if (!this.store.state.onChange()) return;
3195
- const newRowContent = createRowContent(this.store.state.options());
3133
+ const value = this.store.computed.currentValue();
3134
+ if (!this.store.props.onChange()) return;
3135
+ const newRowContent = createRowContent(this.store.props.options());
3196
3136
  if (!isTextLikeRow(token)) {
3197
3137
  const newValue = addDragRow(value, rows, blockIndex, newRowContent);
3198
3138
  this.store.state.innerValue(newValue);
@@ -3289,7 +3229,7 @@ var BlockEditFeature = class {
3289
3229
  const rows = this.store.state.tokens();
3290
3230
  if (blockIndex >= rows.length) return;
3291
3231
  const token = rows[blockIndex];
3292
- const value = this.store.state.previousValue() ?? this.store.state.value() ?? "";
3232
+ const value = this.store.computed.currentValue();
3293
3233
  const focusAndSetCaret = (newRawPos) => {
3294
3234
  queueMicrotask(() => {
3295
3235
  const target = childAt(container, blockIndex);
@@ -3369,6 +3309,7 @@ var DragFeature = class {
3369
3309
  }
3370
3310
  #unsub;
3371
3311
  enable() {
3312
+ if (this.#unsub) return;
3372
3313
  this.#unsub = watch(this.store.event.dragAction, (action) => {
3373
3314
  switch (action.type) {
3374
3315
  case "reorder":
@@ -3391,17 +3332,17 @@ var DragFeature = class {
3391
3332
  this.#unsub = void 0;
3392
3333
  }
3393
3334
  #reorder(sourceIndex, targetIndex) {
3394
- const value = this.store.state.value();
3395
- if (value == null || !this.store.state.onChange()) return;
3335
+ const value = this.store.props.value();
3336
+ if (value == null || !this.store.props.onChange()) return;
3396
3337
  const newValue = reorderDragRows(value, this.store.state.tokens(), sourceIndex, targetIndex);
3397
3338
  if (newValue !== value) this.store.state.innerValue(newValue);
3398
3339
  }
3399
3340
  #add(afterIndex) {
3400
- const value = this.store.state.value();
3401
- if (value == null || !this.store.state.onChange()) return;
3341
+ const value = this.store.props.value();
3342
+ if (value == null || !this.store.props.onChange()) return;
3402
3343
  const rawRows = this.store.state.tokens();
3403
3344
  const rows = rawRows.length > 0 ? rawRows : [EMPTY_TEXT_TOKEN];
3404
- const newRowContent = createRowContent(this.store.state.options());
3345
+ const newRowContent = createRowContent(this.store.props.options());
3405
3346
  this.store.state.innerValue(addDragRow(value, rows, afterIndex, newRowContent));
3406
3347
  queueMicrotask(() => {
3407
3348
  const container = this.store.refs.container;
@@ -3410,14 +3351,14 @@ var DragFeature = class {
3410
3351
  });
3411
3352
  }
3412
3353
  #delete(index) {
3413
- const value = this.store.state.value();
3414
- if (value == null || !this.store.state.onChange()) return;
3354
+ const value = this.store.props.value();
3355
+ if (value == null || !this.store.props.onChange()) return;
3415
3356
  const rows = this.store.state.tokens();
3416
3357
  this.store.state.innerValue(deleteDragRow(value, rows, index));
3417
3358
  }
3418
3359
  #duplicate(index) {
3419
- const value = this.store.state.value();
3420
- if (value == null || !this.store.state.onChange()) return;
3360
+ const value = this.store.props.value();
3361
+ if (value == null || !this.store.props.onChange()) return;
3421
3362
  const rows = this.store.state.tokens();
3422
3363
  this.store.state.innerValue(duplicateDragRow(value, rows, index));
3423
3364
  }
@@ -3436,8 +3377,8 @@ function getDragTargetIndex(blockIndex, position) {
3436
3377
  }
3437
3378
  //#endregion
3438
3379
  //#region ../../core/src/features/drag/config.ts
3439
- function getAlwaysShowHandleDrag(drag) {
3440
- return typeof drag === "object" && !!drag.alwaysShowHandle;
3380
+ function getAlwaysShowHandle(draggable) {
3381
+ return typeof draggable === "object" && !!draggable.alwaysShowHandle;
3441
3382
  }
3442
3383
  //#endregion
3443
3384
  //#region ../../core/src/features/events/SystemListenerFeature.ts
@@ -3450,17 +3391,17 @@ var SystemListenerFeature = class {
3450
3391
  if (this.#scope) return;
3451
3392
  this.#scope = effectScope(() => {
3452
3393
  watch(this.store.event.change, () => {
3453
- const onChange = this.store.state.onChange();
3394
+ const onChange = this.store.props.onChange();
3454
3395
  const { focus } = this.store.nodes;
3455
3396
  if (!focus.target || !focus.target.isContentEditable) {
3456
- const tokens = this.store.state.tokens();
3457
- const serialized = toString(tokens);
3397
+ const serialized = toString(this.store.state.tokens());
3458
3398
  onChange?.(serialized);
3459
3399
  this.store.state.previousValue(serialized);
3460
- this.store.state.tokens([...tokens]);
3400
+ this.store.bumpTokens();
3461
3401
  return;
3462
3402
  }
3463
3403
  const tokens = this.store.state.tokens();
3404
+ if (focus.index >= tokens.length) return;
3464
3405
  const token = tokens[focus.index];
3465
3406
  if (token.type === "text") token.content = focus.content;
3466
3407
  else token.value = focus.content;
@@ -3482,11 +3423,11 @@ var SystemListenerFeature = class {
3482
3423
  this.store.state.tokens(newTokens);
3483
3424
  this.store.state.previousValue(newValue);
3484
3425
  });
3485
- this.store.state.onChange()?.(newValue);
3426
+ this.store.props.onChange()?.(newValue);
3486
3427
  });
3487
3428
  watch(this.store.event.select, (event) => {
3488
- const Mark = this.store.state.Mark();
3489
- const onChange = this.store.state.onChange();
3429
+ const Mark = this.store.props.Mark();
3430
+ const onChange = this.store.props.onChange();
3490
3431
  const { mark, match: { option, span, index, source } } = event;
3491
3432
  const markup = option.markup;
3492
3433
  if (!markup) return;
@@ -3525,51 +3466,43 @@ var SystemListenerFeature = class {
3525
3466
  //#endregion
3526
3467
  //#region ../../core/src/features/focus/FocusFeature.ts
3527
3468
  var FocusFeature = class {
3528
- #focusinHandler;
3529
- #focusoutHandler;
3530
- #clickHandler;
3469
+ #scope;
3531
3470
  constructor(store) {
3532
3471
  this.store = store;
3533
3472
  }
3534
3473
  enable() {
3535
- if (this.#focusinHandler) return;
3474
+ if (this.#scope) return;
3536
3475
  const container = this.store.refs.container;
3537
3476
  if (!container) return;
3538
- this.#focusinHandler = (e) => {
3539
- const target = isHtmlElement(e.target) ? e.target : void 0;
3540
- this.store.nodes.focus.target = target;
3541
- };
3542
- this.#focusoutHandler = () => {
3543
- this.store.nodes.focus.target = void 0;
3544
- };
3545
- this.#clickHandler = () => {
3546
- const tokens = this.store.state.tokens();
3547
- if (tokens.length === 1 && tokens[0].type === "text" && tokens[0].content === "") {
3548
- const container = this.store.refs.container;
3549
- (container ? firstHtmlChild(container) : null)?.focus();
3550
- }
3551
- };
3552
- container.addEventListener("focusin", this.#focusinHandler);
3553
- container.addEventListener("focusout", this.#focusoutHandler);
3554
- container.addEventListener("click", this.#clickHandler);
3555
- watch(this.store.event.recoverFocus, () => {
3556
- this.#recover();
3557
- });
3558
- watch(this.store.event.afterTokensRendered, () => {
3559
- this.store.event.sync();
3560
- if (!this.store.state.Mark()) return;
3561
- this.store.event.recoverFocus();
3477
+ this.#scope = effectScope(() => {
3478
+ listen(container, "focusin", (e) => {
3479
+ const target = isHtmlElement(e.target) ? e.target : void 0;
3480
+ this.store.nodes.focus.target = target;
3481
+ });
3482
+ listen(container, "focusout", () => {
3483
+ this.store.nodes.focus.target = void 0;
3484
+ });
3485
+ listen(container, "click", () => {
3486
+ const tokens = this.store.state.tokens();
3487
+ if (tokens.length === 1 && tokens[0].type === "text" && tokens[0].content === "") {
3488
+ const container = this.store.refs.container;
3489
+ (container ? firstHtmlChild(container) : null)?.focus();
3490
+ }
3491
+ });
3492
+ watch(this.store.event.recoverFocus, () => {
3493
+ this.#recover();
3494
+ });
3495
+ watch(this.store.event.afterTokensRendered, () => {
3496
+ this.store.event.sync();
3497
+ if (!this.store.props.Mark()) return;
3498
+ this.store.event.recoverFocus();
3499
+ });
3562
3500
  });
3563
3501
  }
3564
3502
  disable() {
3565
- const container = this.store.refs.container;
3566
- if (!container || !this.#focusinHandler) return;
3567
- container.removeEventListener("focusin", this.#focusinHandler);
3568
- if (this.#focusoutHandler) container.removeEventListener("focusout", this.#focusoutHandler);
3569
- if (this.#clickHandler) container.removeEventListener("click", this.#clickHandler);
3570
- this.#focusinHandler = void 0;
3571
- this.#focusoutHandler = void 0;
3572
- this.#clickHandler = void 0;
3503
+ this.#scope?.();
3504
+ this.#scope = void 0;
3505
+ this.store.nodes.focus.clear();
3573
3506
  }
3574
3507
  #recover() {
3575
3508
  const recovery = this.store.state.recovery();
@@ -3604,40 +3537,31 @@ var FocusFeature = class {
3604
3537
  //#endregion
3605
3538
  //#region ../../core/src/features/input/InputFeature.ts
3606
3539
  var InputFeature = class {
3607
- #keydownHandler;
3608
- #pasteHandler;
3609
- #beforeInputHandler;
3540
+ #scope;
3610
3541
  constructor(store) {
3611
3542
  this.store = store;
3612
3543
  }
3613
3544
  enable() {
3614
- if (this.#keydownHandler) return;
3545
+ if (this.#scope) return;
3615
3546
  const container = this.store.refs.container;
3616
3547
  if (!container) return;
3617
- this.#keydownHandler = (e) => {
3618
- if (!this.store.state.drag()) this.#handleDelete(e);
3619
- };
3620
- this.#pasteHandler = (e) => {
3621
- const c = this.store.refs.container;
3622
- if (c) captureMarkupPaste(e, c);
3623
- handlePaste(this.store, e);
3624
- };
3625
- this.#beforeInputHandler = (e) => {
3626
- handleBeforeInput(this.store, e);
3627
- };
3628
- container.addEventListener("keydown", this.#keydownHandler);
3629
- container.addEventListener("paste", this.#pasteHandler);
3630
- container.addEventListener("beforeinput", this.#beforeInputHandler, true);
3548
+ this.#scope = effectScope(() => {
3549
+ listen(container, "keydown", (e) => {
3550
+ if (!this.store.computed.isBlock()) this.#handleDelete(e);
3551
+ });
3552
+ listen(container, "paste", (e) => {
3553
+ const c = this.store.refs.container;
3554
+ if (c) captureMarkupPaste(e, c);
3555
+ handlePaste(this.store, e);
3556
+ });
3557
+ listen(container, "beforeinput", (e) => {
3558
+ handleBeforeInput(this.store, e);
3559
+ }, true);
3560
+ });
3631
3561
  }
3632
3562
  disable() {
3633
- const container = this.store.refs.container;
3634
- if (!container || !this.#keydownHandler) return;
3635
- container.removeEventListener("keydown", this.#keydownHandler);
3636
- if (this.#pasteHandler) container.removeEventListener("paste", this.#pasteHandler);
3637
- if (this.#beforeInputHandler) container.removeEventListener("beforeinput", this.#beforeInputHandler, true);
3638
- this.#keydownHandler = void 0;
3639
- this.#pasteHandler = void 0;
3640
- this.#beforeInputHandler = void 0;
3563
+ this.#scope?.();
3564
+ this.#scope = void 0;
3641
3565
  }
3642
3566
  #handleDelete(event) {
3643
3567
  const { focus } = this.store.nodes;
@@ -3697,7 +3621,7 @@ function handleBeforeInput(store, event) {
3697
3621
  return;
3698
3622
  }
3699
3623
  if (selecting === "all") store.state.selecting(void 0);
3700
- if (store.state.drag()) return;
3624
+ if (store.computed.isBlock()) return;
3701
3625
  const { focus } = store.nodes;
3702
3626
  if (!focus.target || !focus.isEditable) return;
3703
3627
  if ((event.inputType === "insertFromPaste" || event.inputType === "insertReplacementText") && handleMarkputSpanPaste(store, focus, event)) return;
@@ -3711,7 +3635,7 @@ function handleMarkputSpanPaste(store, focus, event) {
3711
3635
  event.preventDefault();
3712
3636
  const token = store.state.tokens()[focus.index];
3713
3637
  const offset = focus.caret;
3714
- const currentValue = store.state.previousValue() ?? store.state.value() ?? "";
3638
+ const currentValue = store.computed.currentValue();
3715
3639
  const ranges = event.getTargetRanges();
3716
3640
  const childElement = container.children[focus.index];
3717
3641
  let rawInsertPos;
@@ -3806,8 +3730,9 @@ function handlePaste(store, event) {
3806
3730
  function replaceAllContentWith(store, newContent) {
3807
3731
  store.nodes.focus.target = null;
3808
3732
  store.state.selecting(void 0);
3809
- store.state.onChange()?.(newContent);
3810
- if (store.state.value() === void 0) store.state.tokens(store.computed.parser()?.parse(newContent) ?? [{
3733
+ store.state.previousValue(newContent);
3734
+ store.props.onChange()?.(newContent);
3735
+ if (store.props.value() === void 0) store.state.tokens(store.computed.parser()?.parse(newContent) ?? [{
3811
3736
  type: "text",
3812
3737
  content: newContent,
3813
3738
  position: {
@@ -3864,93 +3789,50 @@ function createMarkFromOverlay(match, value, meta) {
3864
3789
  //#region ../../core/src/features/overlay/OverlayFeature.ts
3865
3790
  var OverlayFeature = class {
3866
3791
  #scope;
3867
- #selectionChangeHandler;
3868
- #focusinHandler;
3869
- #focusoutHandler;
3870
- #escHandler;
3871
- #clickHandler;
3872
3792
  constructor(store) {
3873
3793
  this.store = store;
3874
3794
  }
3875
3795
  enable() {
3876
3796
  if (this.#scope) return;
3877
- this.store.state.overlayTrigger((option) => option.overlay?.trigger);
3878
3797
  this.#scope = effectScope(() => {
3879
3798
  watch(this.store.event.clearOverlay, () => {
3880
3799
  this.store.state.overlayMatch(void 0);
3881
3800
  });
3882
3801
  watch(this.store.event.checkOverlay, () => {
3883
- const getTrigger = this.store.state.overlayTrigger();
3884
- if (!getTrigger) return;
3885
- const match = TriggerFinder.find(this.store.state.options(), getTrigger);
3802
+ const match = TriggerFinder.find(this.store.props.options(), (option) => option.overlay?.trigger);
3886
3803
  this.store.state.overlayMatch(match);
3887
3804
  });
3888
3805
  watch(this.store.event.change, () => {
3889
- const showOverlayOn = this.store.state.showOverlayOn();
3806
+ const showOverlayOn = this.store.props.showOverlayOn();
3890
3807
  const type = "change";
3891
3808
  if (showOverlayOn === type || Array.isArray(showOverlayOn) && showOverlayOn.includes(type)) this.store.event.checkOverlay();
3892
3809
  });
3893
- watch(this.store.state.overlayMatch, (match) => {
3894
- if (match) {
3810
+ alienEffect(() => {
3811
+ if (this.store.state.overlayMatch()) {
3895
3812
  this.store.nodes.input.target = this.store.nodes.focus.target;
3896
- this.#enableClose();
3897
- } else this.#disableClose();
3813
+ listen(window, "keydown", (e) => {
3814
+ if (e.key === KEYBOARD.ESC) this.store.event.clearOverlay();
3815
+ });
3816
+ listen(document, "click", (e) => {
3817
+ const target = e.target instanceof HTMLElement ? e.target : null;
3818
+ if (this.store.refs.overlay?.contains(target)) return;
3819
+ if (this.store.refs.container?.contains(target)) return;
3820
+ this.store.event.clearOverlay();
3821
+ }, true);
3822
+ }
3898
3823
  });
3824
+ const selectionChangeHandler = () => {
3825
+ if (!this.store.refs.container?.contains(document.activeElement)) return;
3826
+ const showOverlayOn = this.store.props.showOverlayOn();
3827
+ const type = "selectionChange";
3828
+ if (showOverlayOn === type || Array.isArray(showOverlayOn) && showOverlayOn.includes(type)) this.store.event.checkOverlay();
3829
+ };
3830
+ listen(document, "selectionchange", selectionChangeHandler);
3899
3831
  });
3900
- const selectionChangeHandler = () => {
3901
- const showOverlayOn = this.store.state.showOverlayOn();
3902
- const type = "selectionChange";
3903
- if (showOverlayOn === type || Array.isArray(showOverlayOn) && showOverlayOn.includes(type)) this.store.event.checkOverlay();
3904
- };
3905
- this.#selectionChangeHandler = selectionChangeHandler;
3906
- this.#focusinHandler = () => {
3907
- document.addEventListener("selectionchange", selectionChangeHandler);
3908
- };
3909
- this.#focusoutHandler = () => {
3910
- document.removeEventListener("selectionchange", selectionChangeHandler);
3911
- };
3912
- const container = this.store.refs.container;
3913
- if (container) {
3914
- container.addEventListener("focusin", this.#focusinHandler);
3915
- container.addEventListener("focusout", this.#focusoutHandler);
3916
- }
3917
3832
  }
3918
3833
  disable() {
3919
- const container = this.store.refs.container;
3920
- if (container && this.#focusinHandler) {
3921
- container.removeEventListener("focusin", this.#focusinHandler);
3922
- if (this.#focusoutHandler) container.removeEventListener("focusout", this.#focusoutHandler);
3923
- }
3924
- if (this.#selectionChangeHandler) document.removeEventListener("selectionchange", this.#selectionChangeHandler);
3925
- this.#disableClose();
3926
- this.store.state.overlayTrigger(void 0);
3927
3834
  this.#scope?.();
3928
3835
  this.#scope = void 0;
3929
- this.#selectionChangeHandler = void 0;
3930
- this.#focusinHandler = void 0;
3931
- this.#focusoutHandler = void 0;
3932
- }
3933
- #enableClose() {
3934
- if (this.#escHandler) return;
3935
- this.#escHandler = (e) => {
3936
- if (e.key === KEYBOARD.ESC) this.store.event.clearOverlay();
3937
- };
3938
- this.#clickHandler = (e) => {
3939
- const target = e.target instanceof HTMLElement ? e.target : null;
3940
- if (this.store.refs.overlay?.contains(target)) return;
3941
- if (this.store.refs.container?.contains(target)) return;
3942
- this.store.event.clearOverlay();
3943
- };
3944
- window.addEventListener("keydown", this.#escHandler);
3945
- document.addEventListener("click", this.#clickHandler, true);
3946
- }
3947
- #disableClose() {
3948
- if (this.#escHandler) {
3949
- window.removeEventListener("keydown", this.#escHandler);
3950
- if (this.#clickHandler) document.removeEventListener("click", this.#clickHandler, true);
3951
- this.#escHandler = void 0;
3952
- this.#clickHandler = void 0;
3953
- }
3954
3836
  }
3955
3837
  };
3956
3838
  //#endregion
@@ -4046,35 +3928,6 @@ function resolveMarkSlot(token, tokenOptions, GlobalMark, GlobalSpan) {
4046
3928
  return [Component, props];
4047
3929
  }
4048
3930
  //#endregion
4049
- //#region ../../core/src/features/slots/createSlots.ts
4050
- function createNamedSlot(slots, slotProps, name) {
4051
- return {
4052
- use: () => [resolveSlot(name, slots.use()), resolveSlotProps(name, slotProps.use())],
4053
- get: () => [resolveSlot(name, slots()), resolveSlotProps(name, slotProps())]
4054
- };
4055
- }
4056
- function createOverlaySlot(overlay) {
4057
- return {
4058
- use: (option, defaultComponent) => resolveOverlaySlot(overlay.use(), option, defaultComponent),
4059
- get: (option, defaultComponent) => resolveOverlaySlot(overlay(), option, defaultComponent)
4060
- };
4061
- }
4062
- function createMarkSlot(options, mark, span) {
4063
- return {
4064
- use: (token) => resolveMarkSlot(token, options(), mark.use(), span.use()),
4065
- get: (token) => resolveMarkSlot(token, options(), mark(), span())
4066
- };
4067
- }
4068
- function createSlots(signals) {
4069
- return {
4070
- container: createNamedSlot(signals.slots, signals.slotProps, "container"),
4071
- block: createNamedSlot(signals.slots, signals.slotProps, "block"),
4072
- span: createNamedSlot(signals.slots, signals.slotProps, "span"),
4073
- overlay: createOverlaySlot(signals.Overlay),
4074
- mark: createMarkSlot(signals.options, signals.Mark, signals.Span)
4075
- };
4076
- }
4077
- //#endregion
4078
3931
  //#region ../../core/src/shared/utils/menuUtils.ts
4079
3932
  /**
4080
3933
  * Returns true when `target` is outside `element` (i.e. not contained by it).
@@ -4245,6 +4098,21 @@ var BlockRegistry = class {
4245
4098
  };
4246
4099
  //#endregion
4247
4100
  //#region ../../core/src/store/Store.ts
4101
+ const DRAG_HANDLE_WIDTH = 24;
4102
+ function buildContainerProps(isDraggableBlock, readOnly, className, style, slotProps) {
4103
+ const containerSlotProps = slotProps?.container;
4104
+ const baseStyle = merge(style, containerSlotProps?.style);
4105
+ const mergedStyle = isDraggableBlock && !readOnly ? {
4106
+ paddingLeft: DRAG_HANDLE_WIDTH,
4107
+ ...baseStyle
4108
+ } : baseStyle;
4109
+ const { className: _, style: __, ...otherSlotProps } = resolveSlotProps("container", slotProps) ?? {};
4110
+ return {
4111
+ className: cx(styles.Container, className, containerSlotProps?.className),
4112
+ style: mergedStyle,
4113
+ ...otherSlotProps
4114
+ };
4115
+ }
4248
4116
  var Store = class {
4249
4117
  key = new KeyGenerator();
4250
4118
  blocks = new BlockRegistry();
@@ -4252,54 +4120,65 @@ var Store = class {
4252
4120
  focus: new NodeProxy(void 0, this),
4253
4121
  input: new NodeProxy(void 0, this)
4254
4122
  };
4123
+ props = {
4124
+ value: signal(void 0, { readonly: true }),
4125
+ defaultValue: signal(void 0, { readonly: true }),
4126
+ onChange: signal(void 0, { readonly: true }),
4127
+ options: signal(DEFAULT_OPTIONS, { readonly: true }),
4128
+ readOnly: signal(false, { readonly: true }),
4129
+ layout: signal("inline", { readonly: true }),
4130
+ draggable: signal(false, { readonly: true }),
4131
+ showOverlayOn: signal("change", { readonly: true }),
4132
+ Span: signal(void 0, { readonly: true }),
4133
+ Mark: signal(void 0, { readonly: true }),
4134
+ Overlay: signal(void 0, { readonly: true }),
4135
+ className: signal(void 0, { readonly: true }),
4136
+ style: signal(void 0, {
4137
+ equals: shallow,
4138
+ readonly: true
4139
+ }),
4140
+ slots: signal(void 0, { readonly: true }),
4141
+ slotProps: signal(void 0, { readonly: true })
4142
+ };
4255
4143
  state = {
4256
4144
  tokens: signal([]),
4257
- value: signal(void 0),
4258
- defaultValue: signal(void 0),
4259
4145
  previousValue: signal(void 0),
4260
4146
  innerValue: signal(void 0),
4261
4147
  recovery: signal(void 0),
4262
4148
  selecting: signal(void 0),
4263
- drag: signal(false),
4264
- overlayMatch: signal(void 0),
4265
- overlayTrigger: signal(void 0),
4266
- showOverlayOn: signal("change"),
4267
- onChange: signal(void 0),
4268
- options: signal(DEFAULT_OPTIONS),
4269
- readOnly: signal(false),
4270
- Span: signal(void 0),
4271
- Mark: signal(void 0),
4272
- Overlay: signal(void 0),
4273
- className: signal(void 0),
4274
- style: signal(void 0, { equals: shallow }),
4275
- slots: signal(void 0),
4276
- slotProps: signal(void 0)
4149
+ overlayMatch: signal(void 0)
4277
4150
  };
4278
4151
  computed = {
4279
4152
  hasMark: computed(() => {
4280
- if (this.state.Mark()) return true;
4281
- return this.state.options().some((opt) => "Mark" in opt && opt.Mark != null);
4153
+ if (this.props.Mark()) return true;
4154
+ return this.props.options().some((opt) => "Mark" in opt && opt.Mark != null);
4282
4155
  }),
4156
+ isBlock: computed(() => this.props.layout() === "block"),
4157
+ isDraggable: computed(() => !!this.props.draggable()),
4283
4158
  parser: computed(() => {
4284
4159
  if (!this.computed.hasMark()) return;
4285
- const markups = this.state.options().map((opt) => opt.markup);
4160
+ const markups = this.props.options().map((opt) => opt.markup);
4286
4161
  if (!markups.some(Boolean)) return;
4287
- return new Parser(markups, !!this.state.drag() ? { skipEmptyText: true } : void 0);
4162
+ return new Parser(markups, this.computed.isBlock() ? { skipEmptyText: true } : void 0);
4288
4163
  }),
4289
- containerClass: computed(() => cx(styles.Container, this.state.className(), this.state.slotProps()?.container?.className)),
4290
- containerStyle: computed((prev) => {
4291
- const next = merge(this.state.style(), this.state.slotProps()?.container?.style);
4292
- return prev && shallow(prev, next) ? prev : next;
4164
+ currentValue: computed(() => this.state.previousValue() ?? this.props.value() ?? ""),
4165
+ containerComponent: computed(() => resolveSlot("container", this.props.slots())),
4166
+ containerProps: computed(() => buildContainerProps(this.computed.isDraggable() && this.computed.isBlock(), this.props.readOnly(), this.props.className(), this.props.style(), this.props.slotProps()), { equals: shallow }),
4167
+ blockComponent: computed(() => resolveSlot("block", this.props.slots())),
4168
+ blockProps: computed(() => resolveSlotProps("block", this.props.slotProps())),
4169
+ spanComponent: computed(() => resolveSlot("span", this.props.slots())),
4170
+ spanProps: computed(() => resolveSlotProps("span", this.props.slotProps())),
4171
+ overlay: computed(() => {
4172
+ const Overlay = this.props.Overlay();
4173
+ return (option, defaultComponent) => resolveOverlaySlot(Overlay, option, defaultComponent);
4174
+ }),
4175
+ mark: computed(() => {
4176
+ const options = this.props.options();
4177
+ const Mark = this.props.Mark();
4178
+ const Span = this.props.Span();
4179
+ return (token) => resolveMarkSlot(token, options, Mark, Span);
4293
4180
  })
4294
4181
  };
4295
- slot = createSlots({
4296
- slots: this.state.slots,
4297
- slotProps: this.state.slotProps,
4298
- Overlay: this.state.Overlay,
4299
- options: this.state.options,
4300
- Mark: this.state.Mark,
4301
- Span: this.state.Span
4302
- });
4303
4182
  event = {
4304
4183
  change: event(),
4305
4184
  parse: event(),
@@ -4337,14 +4216,17 @@ var Store = class {
4337
4216
  watch(this.event.mounted, () => Object.values(this.features).forEach((f) => f.enable()));
4338
4217
  watch(this.event.unmounted, () => Object.values(this.features).forEach((f) => f.disable()));
4339
4218
  }
4340
- setState(values) {
4219
+ setProps(values) {
4341
4220
  batch(() => {
4342
- const state = this.state;
4221
+ const props = this.props;
4343
4222
  for (const key of Object.keys(values)) {
4344
- if (!(key in state)) continue;
4345
- state[key](values[key]);
4223
+ if (!(key in props)) continue;
4224
+ props[key](values[key]);
4346
4225
  }
4347
- });
4226
+ }, { mutable: true });
4227
+ }
4228
+ bumpTokens() {
4229
+ this.state.tokens([...this.state.tokens()]);
4348
4230
  }
4349
4231
  };
4350
4232
  //#endregion
@@ -4389,14 +4271,17 @@ var MarkHandler = class {
4389
4271
  get slot() {
4390
4272
  return this.#token.slot?.content;
4391
4273
  }
4274
+ get #tokenInfo() {
4275
+ return findToken(this.#store.state.tokens(), this.#token);
4276
+ }
4392
4277
  get depth() {
4393
- return findToken(this.#store.state.tokens(), this.#token)?.depth ?? 0;
4278
+ return this.#tokenInfo?.depth ?? 0;
4394
4279
  }
4395
4280
  get hasChildren() {
4396
4281
  return this.#token.children.some((child) => child.type === "mark");
4397
4282
  }
4398
4283
  get parent() {
4399
- return findToken(this.#store.state.tokens(), this.#token)?.parent;
4284
+ return this.#tokenInfo?.parent;
4400
4285
  }
4401
4286
  get tokens() {
4402
4287
  return this.#token.children;
@@ -4413,14 +4298,6 @@ var MarkHandler = class {
4413
4298
  }
4414
4299
  };
4415
4300
  //#endregion
4416
- //#region src/lib/hooks/createUseHook.ts
4417
- setUseHookFactory((sig) => {
4418
- const s = sig;
4419
- const subscribe = (cb) => watch(s, cb);
4420
- const getSnapshot = () => s();
4421
- return () => useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
4422
- });
4423
- //#endregion
4424
4301
  //#region src/lib/providers/StoreContext.ts
4425
4302
  const StoreContext = createContext(void 0);
4426
4303
  StoreContext.displayName = "StoreContext";
@@ -4430,6 +4307,31 @@ function useStore() {
4430
4307
  return store;
4431
4308
  }
4432
4309
  //#endregion
4310
+ //#region src/lib/hooks/useMarkput.ts
4311
+ function useMarkput(selector) {
4312
+ const store = useStore();
4313
+ const stableRef = useRef(null);
4314
+ if (stableRef.current === null) {
4315
+ const target = selector(store);
4316
+ const derived = computed(() => {
4317
+ if (typeof target === "function") return target();
4318
+ const out = {};
4319
+ for (const k in target) {
4320
+ const val = target[k];
4321
+ out[k] = isReactive(val) ? val() : val;
4322
+ }
4323
+ return out;
4324
+ });
4325
+ stableRef.current = {
4326
+ derived,
4327
+ subscribe: (cb) => watch(derived, cb),
4328
+ getSnapshot: () => derived()
4329
+ };
4330
+ }
4331
+ const { subscribe, getSnapshot } = stableRef.current;
4332
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
4333
+ }
4334
+ //#endregion
4433
4335
  //#region src/components/Popup/List.tsx
4434
4336
  const List = ({ children }) => /* @__PURE__ */ jsx("ul", {
4435
4337
  className: styles$1.PopupList,
@@ -4464,8 +4366,10 @@ const Popup = ({ ref, style, children }) => {
4464
4366
  //#region src/components/BlockMenu.tsx
4465
4367
  const BlockMenu = memo(({ token }) => {
4466
4368
  const blockStore = useStore().blocks.get(token);
4467
- const menuOpen = blockStore.state.menuOpen.use();
4468
- const menuPosition = blockStore.state.menuPosition.use();
4369
+ const { menuOpen, menuPosition } = useMarkput(() => ({
4370
+ menuOpen: blockStore.state.menuOpen,
4371
+ menuPosition: blockStore.state.menuPosition
4372
+ }));
4469
4373
  if (!menuOpen) return null;
4470
4374
  return /* @__PURE__ */ jsx(Popup, {
4471
4375
  ref: (el) => blockStore.attachMenu(el),
@@ -4495,12 +4399,14 @@ BlockMenu.displayName = "BlockMenu";
4495
4399
  const iconGrip = `${styles$1.Icon} ${styles$1.IconGrip}`;
4496
4400
  const DragHandle = memo(({ token, blockIndex }) => {
4497
4401
  const store = useStore();
4498
- const readOnly = store.state.readOnly.use();
4499
- const drag = store.state.drag.use();
4500
4402
  const blockStore = store.blocks.get(token);
4501
- const isDragging = blockStore.state.isDragging.use();
4502
- const isHovered = blockStore.state.isHovered.use();
4503
- const alwaysShowHandle = useMemo(() => getAlwaysShowHandleDrag(drag), [drag]);
4403
+ const { readOnly, draggable } = useMarkput((s) => ({
4404
+ readOnly: s.props.readOnly,
4405
+ draggable: s.props.draggable
4406
+ }));
4407
+ const isDragging = useMarkput(() => blockStore.state.isDragging);
4408
+ const isHovered = useMarkput(() => blockStore.state.isHovered);
4409
+ const alwaysShowHandle = useMemo(() => getAlwaysShowHandle(draggable), [draggable]);
4504
4410
  if (readOnly) return null;
4505
4411
  return /* @__PURE__ */ jsx("div", {
4506
4412
  className: cx(styles$1.SidePanel, alwaysShowHandle ? styles$1.SidePanelAlways : isHovered && !isDragging && styles$1.SidePanelVisible),
@@ -4518,7 +4424,8 @@ DragHandle.displayName = "DragHandle";
4518
4424
  //#endregion
4519
4425
  //#region src/components/DropIndicator.tsx
4520
4426
  const DropIndicator = memo(({ token, position }) => {
4521
- if (useStore().blocks.get(token).state.dropPosition.use() !== position) return null;
4427
+ const blockStore = useStore().blocks.get(token);
4428
+ if (useMarkput(() => blockStore.state.dropPosition) !== position) return null;
4522
4429
  return /* @__PURE__ */ jsx("div", {
4523
4430
  className: styles$1.DropIndicator,
4524
4431
  style: position === "before" ? { top: -1 } : { bottom: -1 }
@@ -4538,7 +4445,7 @@ function useToken() {
4538
4445
  //#region src/components/Token.tsx
4539
4446
  const Token = memo(({ mark }) => {
4540
4447
  const store = useStore();
4541
- const [Component, props] = store.slot.mark.use(mark);
4448
+ const [Component, props] = useMarkput((s) => s.computed.mark)(mark);
4542
4449
  return /* @__PURE__ */ jsx(TokenContext, {
4543
4450
  value: mark,
4544
4451
  children: /* @__PURE__ */ jsx(Component, {
@@ -4552,15 +4459,19 @@ Token.displayName = "Token";
4552
4459
  //#region src/components/Block.tsx
4553
4460
  const Block = memo(({ token, blockIndex }) => {
4554
4461
  const store = useStore();
4555
- const [ContainerComponent, containerProps] = store.slot.block.use();
4556
4462
  const blockStore = store.blocks.get(token);
4557
- const isDragging = blockStore.state.isDragging.use();
4558
- return /* @__PURE__ */ jsxs(ContainerComponent, {
4463
+ const Component = useMarkput((s) => s.computed.blockComponent);
4464
+ const slotProps = useMarkput((s) => s.computed.blockProps);
4465
+ const isDragging = useMarkput(() => blockStore.state.isDragging);
4466
+ return /* @__PURE__ */ jsxs(Component, {
4559
4467
  ref: (el) => blockStore.attachContainer(el, blockIndex, store.event),
4560
4468
  "data-testid": "block",
4561
- ...containerProps,
4562
- className: styles$1.Block,
4563
- style: { opacity: isDragging ? .4 : 1 },
4469
+ ...slotProps,
4470
+ className: cx(styles$1.Block, slotProps?.className),
4471
+ style: {
4472
+ opacity: isDragging ? .4 : 1,
4473
+ ...slotProps?.style
4474
+ },
4564
4475
  children: [
4565
4476
  /* @__PURE__ */ jsx(DropIndicator, {
4566
4477
  token,
@@ -4583,28 +4494,22 @@ Block.displayName = "Block";
4583
4494
  //#endregion
4584
4495
  //#region src/components/Container.tsx
4585
4496
  const Container = memo(() => {
4586
- const store = useStore();
4587
- const drag = store.state.drag.use();
4588
- const tokens = store.state.tokens.use();
4497
+ const { layout, tokens, key, refs, event } = useMarkput((s) => ({
4498
+ layout: s.props.layout,
4499
+ tokens: s.state.tokens,
4500
+ key: s.key,
4501
+ refs: s.refs,
4502
+ event: s.event
4503
+ }));
4504
+ const Component = useMarkput((s) => s.computed.containerComponent);
4505
+ const props = useMarkput((s) => s.computed.containerProps);
4589
4506
  useLayoutEffect(() => {
4590
- store.event.afterTokensRendered();
4591
- }, [tokens]);
4592
- const className = store.computed.containerClass.use();
4593
- const style = store.computed.containerStyle.use();
4594
- const readOnly = store.state.readOnly.use();
4595
- const key = store.key;
4596
- const refs = store.refs;
4597
- const [ContainerComponent, containerProps] = store.slot.container.use();
4598
- const containerStyle = drag && !readOnly ? style ? {
4599
- paddingLeft: 24,
4600
- ...style
4601
- } : { paddingLeft: 24 } : style;
4602
- return /* @__PURE__ */ jsx(ContainerComponent, {
4507
+ event.afterTokensRendered();
4508
+ }, [tokens, event]);
4509
+ return /* @__PURE__ */ jsx(Component, {
4603
4510
  ref: (el) => refs.container = el,
4604
- ...containerProps,
4605
- className,
4606
- style: containerStyle,
4607
- children: drag ? tokens.map((t, i) => /* @__PURE__ */ jsx(Block, {
4511
+ ...props,
4512
+ children: layout === "block" ? tokens.map((t, i) => /* @__PURE__ */ jsx(Block, {
4608
4513
  token: t,
4609
4514
  blockIndex: i
4610
4515
  }, key.get(t))) : tokens.map((t) => /* @__PURE__ */ jsx(Token, { mark: t }, key.get(t)))
@@ -4615,14 +4520,20 @@ Container.displayName = "Container";
4615
4520
  //#region src/lib/hooks/useOverlay.tsx
4616
4521
  function useOverlay() {
4617
4522
  const store = useStore();
4618
- const match = store.state.overlayMatch.use();
4619
- if (!match) throw new Error("useOverlay requires an active overlay match");
4620
- const style = useMemo(() => Caret.getAbsolutePosition(), [match]);
4523
+ const match = useMarkput((s) => s.state.overlayMatch);
4524
+ const style = useMemo(() => {
4525
+ if (!match) return {
4526
+ left: 0,
4527
+ top: 0
4528
+ };
4529
+ return Caret.getAbsolutePosition();
4530
+ }, [match]);
4621
4531
  const close = useCallback(() => store.event.clearOverlay(), []);
4622
4532
  return {
4623
4533
  match,
4624
4534
  style,
4625
4535
  select: useCallback((value) => {
4536
+ if (!match) return;
4626
4537
  const mark = createMarkFromOverlay(match, value.value, value.meta);
4627
4538
  store.event.select({
4628
4539
  mark,
@@ -4647,8 +4558,8 @@ const Suggestions = () => {
4647
4558
  const store = useStore();
4648
4559
  const { match, select, style, ref } = useOverlay();
4649
4560
  const [active, setActive] = useState(NaN);
4650
- const data = match.option.overlay?.data ?? [];
4651
- const filtered = useMemo(() => filterSuggestions(data, match.value), [match.value, data]);
4561
+ const data = match?.option.overlay?.data ?? [];
4562
+ const filtered = useMemo(() => match ? filterSuggestions(data, match.value) : [], [match, data]);
4652
4563
  const length = filtered.length;
4653
4564
  const activeRef = useRef(active);
4654
4565
  activeRef.current = active;
@@ -4698,9 +4609,9 @@ const Suggestions = () => {
4698
4609
  //#region src/components/OverlayRenderer.tsx
4699
4610
  const OverlayRenderer = memo(() => {
4700
4611
  const store = useStore();
4701
- const overlayMatch = store.state.overlayMatch.use();
4612
+ const overlayMatch = useMarkput((s) => s.state.overlayMatch);
4702
4613
  const key = useMemo(() => overlayMatch ? store.key.get(overlayMatch.option) : void 0, [overlayMatch]);
4703
- const [Overlay, props] = store.slot.overlay.use(overlayMatch?.option, Suggestions);
4614
+ const [Overlay, props] = useMarkput((s) => s.computed.overlay)(overlayMatch?.option, Suggestions);
4704
4615
  if (!key) return;
4705
4616
  return /* @__PURE__ */ jsx(Overlay, { ...props }, key);
4706
4617
  });
@@ -4709,10 +4620,12 @@ OverlayRenderer.displayName = "OverlayRenderer";
4709
4620
  //#region src/components/MarkedInput.tsx
4710
4621
  function MarkedInput(props) {
4711
4622
  const [store] = useState(() => new Store());
4712
- store.setState(props);
4713
- useLayoutEffect(() => store.event.mounted());
4623
+ store.setProps(props);
4624
+ useLayoutEffect(() => {
4625
+ store.event.mounted();
4626
+ return () => store.event.unmounted();
4627
+ }, []);
4714
4628
  useLayoutEffect(() => store.event.updated());
4715
- useEffect(() => () => store.event.unmounted(), [store]);
4716
4629
  useImperativeHandle(props.ref, () => store.handler, [store]);
4717
4630
  return /* @__PURE__ */ jsxs(StoreContext, {
4718
4631
  value: store,
@@ -4732,7 +4645,7 @@ const useMark = (options = {}) => {
4732
4645
  token
4733
4646
  }), [store, token]);
4734
4647
  useUncontrolledInit(ref, options, token);
4735
- const readOnly = store.state.readOnly.use();
4648
+ const readOnly = useMarkput((s) => s.props.readOnly);
4736
4649
  useEffect(() => {
4737
4650
  mark.readOnly = readOnly;
4738
4651
  }, [mark, readOnly]);
@@ -4744,6 +4657,6 @@ function useUncontrolledInit(ref, options, token) {
4744
4657
  }, []);
4745
4658
  }
4746
4659
  //#endregion
4747
- export { MarkHandler, MarkedInput, MarkputHandler, annotate, denote, useMark, useOverlay };
4660
+ export { MarkHandler, MarkedInput, MarkputHandler, annotate, denote, useMark, useMarkput, useOverlay };
4748
4661
 
4749
4662
  //# sourceMappingURL=index.js.map