@markput/react 0.11.0 → 0.12.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
@@ -58,10 +58,10 @@ var MarkputHandler = class {
58
58
  this.store = store;
59
59
  }
60
60
  get container() {
61
- return this.store.refs.container;
61
+ return this.store.state.container();
62
62
  }
63
63
  get overlay() {
64
- return this.store.refs.overlay;
64
+ return this.store.state.overlay();
65
65
  }
66
66
  focus() {
67
67
  this.store.nodes.focus.head?.focus();
@@ -420,10 +420,10 @@ var NodeProxy = class NodeProxy {
420
420
  if (this.target) this.target.textContent = value ?? "";
421
421
  }
422
422
  get head() {
423
- return firstHtmlChild(this.#store.refs.container ?? void 0);
423
+ return firstHtmlChild(this.#store.state.container() ?? void 0);
424
424
  }
425
425
  get tail() {
426
- return lastHtmlChild(this.#store.refs.container ?? void 0);
426
+ return lastHtmlChild(this.#store.state.container() ?? void 0);
427
427
  }
428
428
  get isFocused() {
429
429
  return this.target === document.activeElement;
@@ -942,6 +942,30 @@ function batch(fn, opts) {
942
942
  mutableScope = prevMutable;
943
943
  }
944
944
  }
945
+ function trigger(fn) {
946
+ const sub = {
947
+ deps: void 0,
948
+ depsTail: void 0,
949
+ flags: ReactiveFlags.Watching
950
+ };
951
+ const prevSub = setActiveSub(sub);
952
+ try {
953
+ fn();
954
+ } finally {
955
+ activeSub = prevSub;
956
+ let dep = sub.deps;
957
+ while (dep !== void 0) {
958
+ const subs = dep.dep.subs;
959
+ dep = unlink(dep, sub);
960
+ if (subs !== void 0) {
961
+ sub.flags = ReactiveFlags.None;
962
+ propagate(subs);
963
+ shallowPropagate(subs);
964
+ }
965
+ }
966
+ if (!batchDepth) flush();
967
+ }
968
+ }
945
969
  function untracked(fn) {
946
970
  const prev = setActiveSub(void 0);
947
971
  try {
@@ -2245,7 +2269,7 @@ var ParseFeature = class {
2245
2269
  }
2246
2270
  #subscribeParse() {
2247
2271
  const { store } = this;
2248
- watch(store.event.parse, () => {
2272
+ watch(store.emit.reparse, () => {
2249
2273
  if (store.state.recovery()) {
2250
2274
  const text = toString(store.state.tokens());
2251
2275
  store.state.tokens(parseWithParser(store, text));
@@ -2258,7 +2282,7 @@ var ParseFeature = class {
2258
2282
  #subscribeReactiveParse() {
2259
2283
  const { store } = this;
2260
2284
  watch(computed(() => [store.props.value(), store.computed.parser()]), () => {
2261
- if (!store.state.recovery()) store.event.parse();
2285
+ if (!store.state.recovery()) store.emit.reparse();
2262
2286
  });
2263
2287
  }
2264
2288
  };
@@ -2294,7 +2318,7 @@ function shiftFocusNext(store, event) {
2294
2318
  //#region ../../core/src/features/selection/selectionHelpers.ts
2295
2319
  function isFullSelection(store) {
2296
2320
  const sel = window.getSelection();
2297
- const container = store.refs.container;
2321
+ const container = store.state.container();
2298
2322
  if (!sel?.rangeCount || !container?.firstChild || !container.lastChild) return false;
2299
2323
  try {
2300
2324
  const range = sel.getRangeAt(0);
@@ -2308,8 +2332,8 @@ function selectAllText(store, event) {
2308
2332
  if (store.computed.isBlock()) return;
2309
2333
  event.preventDefault();
2310
2334
  const selection = window.getSelection();
2311
- const anchorNode = store.refs.container?.firstChild;
2312
- const focusNode = store.refs.container?.lastChild;
2335
+ const anchorNode = store.state.container()?.firstChild;
2336
+ const focusNode = store.state.container()?.lastChild;
2313
2337
  if (!selection || !anchorNode || !focusNode) return;
2314
2338
  selection.setBaseAndExtent(anchorNode, 0, focusNode, 1);
2315
2339
  store.state.selecting("all");
@@ -2332,7 +2356,7 @@ var TextSelectionFeature = class {
2332
2356
  this.#isPressed = true;
2333
2357
  });
2334
2358
  listen(document, "mousemove", (e) => {
2335
- const container = this.store.refs.container;
2359
+ const container = this.store.state.container();
2336
2360
  if (!container) return;
2337
2361
  const isPressed = this.#isPressed;
2338
2362
  const isNotInnerSome = !container.contains(this.#pressedNode) || this.#pressedNode !== e.target;
@@ -2356,7 +2380,7 @@ var TextSelectionFeature = class {
2356
2380
  });
2357
2381
  alienEffect(() => {
2358
2382
  if (this.store.state.selecting() !== "drag") return;
2359
- const container = this.store.refs.container;
2383
+ const container = this.store.state.container();
2360
2384
  if (!container) return;
2361
2385
  container.querySelectorAll("[contenteditable=\"true\"]").forEach((el) => el.contentEditable = "false");
2362
2386
  });
@@ -2379,7 +2403,7 @@ var ArrowNavFeature = class {
2379
2403
  }
2380
2404
  enable() {
2381
2405
  if (this.#scope) return;
2382
- const container = this.store.refs.container;
2406
+ const container = this.store.state.container();
2383
2407
  if (!container) return;
2384
2408
  this.#scope = effectScope(() => {
2385
2409
  listen(container, "keydown", (e) => {
@@ -2467,7 +2491,7 @@ function getBoundaryOffset(range, child, isStart) {
2467
2491
  * Returns null if selection is collapsed, empty, or outside the container.
2468
2492
  */
2469
2493
  function selectionToTokens(store) {
2470
- const container = store.refs.container;
2494
+ const container = store.state.container();
2471
2495
  if (!container) return null;
2472
2496
  const sel = window.getSelection();
2473
2497
  if (!sel || sel.isCollapsed || !sel.rangeCount) return null;
@@ -2525,7 +2549,7 @@ var CopyFeature = class {
2525
2549
  }
2526
2550
  enable() {
2527
2551
  if (this.#scope) return;
2528
- const container = this.store.refs.container;
2552
+ const container = this.store.state.container();
2529
2553
  if (!container) return;
2530
2554
  this.#scope = effectScope(() => {
2531
2555
  listen(container, "copy", (e) => {
@@ -2561,7 +2585,7 @@ var CopyFeature = class {
2561
2585
  this.#scope = void 0;
2562
2586
  }
2563
2587
  #handleCopy(e) {
2564
- const container = this.store.refs.container;
2588
+ const container = this.store.state.container();
2565
2589
  if (!container) return false;
2566
2590
  const sel = window.getSelection();
2567
2591
  if (!sel || sel.isCollapsed || !sel.rangeCount) return false;
@@ -2716,9 +2740,10 @@ function deleteMark(place, store) {
2716
2740
  anchor: caretAnchor.prev,
2717
2741
  caret
2718
2742
  });
2719
- store.event.change();
2743
+ store.emit.change();
2720
2744
  queueMicrotask(() => {
2721
- const target = childAt(store.refs.container, targetIndex);
2745
+ const container = store.state.container();
2746
+ const target = container ? childAt(container, targetIndex) : null;
2722
2747
  if (!target) return;
2723
2748
  store.nodes.focus.target = target;
2724
2749
  target.focus();
@@ -2747,7 +2772,7 @@ var ContentEditableFeature = class {
2747
2772
  alienEffect(() => {
2748
2773
  if (this.store.state.selecting() === void 0) this.sync();
2749
2774
  });
2750
- watch(this.store.event.sync, () => {
2775
+ watch(this.store.emit.sync, () => {
2751
2776
  this.sync();
2752
2777
  });
2753
2778
  });
@@ -2757,7 +2782,7 @@ var ContentEditableFeature = class {
2757
2782
  this.#scope = void 0;
2758
2783
  }
2759
2784
  sync() {
2760
- const container = this.store.refs.container;
2785
+ const container = this.store.state.container();
2761
2786
  if (!container) return;
2762
2787
  const readOnly = this.store.props.readOnly();
2763
2788
  const value = readOnly ? "false" : "true";
@@ -2976,7 +3001,7 @@ var BlockEditFeature = class {
2976
3001
  }
2977
3002
  enable() {
2978
3003
  if (this.#scope) return;
2979
- const container = this.store.refs.container;
3004
+ const container = this.store.state.container();
2980
3005
  if (!container) return;
2981
3006
  this.#scope = effectScope(() => {
2982
3007
  listen(container, "keydown", (e) => {
@@ -2998,7 +3023,7 @@ var BlockEditFeature = class {
2998
3023
  this.#scope = void 0;
2999
3024
  }
3000
3025
  #handleDelete(event) {
3001
- const container = this.store.refs.container;
3026
+ const container = this.store.state.container();
3002
3027
  if (!container) return;
3003
3028
  const blockDivs = htmlChildren(container);
3004
3029
  const blockIndex = blockDivs.findIndex((div) => div === document.activeElement || div.contains(document.activeElement));
@@ -3115,7 +3140,7 @@ var BlockEditFeature = class {
3115
3140
  #handleEnter(event) {
3116
3141
  if (event.key !== KEYBOARD.ENTER) return;
3117
3142
  if (event.shiftKey) return;
3118
- const container = this.store.refs.container;
3143
+ const container = this.store.state.container();
3119
3144
  if (!container) return;
3120
3145
  const activeElement = document.activeElement;
3121
3146
  if (!isHtmlElement(activeElement) || !container.contains(activeElement)) return;
@@ -3163,7 +3188,7 @@ var BlockEditFeature = class {
3163
3188
  });
3164
3189
  }
3165
3190
  #handleBlockArrowLeftRight(event, direction) {
3166
- const container = this.store.refs.container;
3191
+ const container = this.store.state.container();
3167
3192
  if (!container) return false;
3168
3193
  const activeElement = document.activeElement;
3169
3194
  if (!isHtmlElement(activeElement) || !container.contains(activeElement)) return false;
@@ -3189,7 +3214,7 @@ var BlockEditFeature = class {
3189
3214
  return true;
3190
3215
  }
3191
3216
  #handleArrowUpDown(event) {
3192
- const container = this.store.refs.container;
3217
+ const container = this.store.state.container();
3193
3218
  if (!container) return;
3194
3219
  const activeElement = document.activeElement;
3195
3220
  if (!isHtmlElement(activeElement) || !container.contains(activeElement)) return;
@@ -3218,7 +3243,7 @@ var BlockEditFeature = class {
3218
3243
  }
3219
3244
  }
3220
3245
  #handleBlockBeforeInput(event) {
3221
- const container = this.store.refs.container;
3246
+ const container = this.store.state.container();
3222
3247
  if (!container) return;
3223
3248
  const activeElement = document.activeElement;
3224
3249
  if (!isHtmlElement(activeElement) || !container.contains(activeElement)) return;
@@ -3258,7 +3283,8 @@ var BlockEditFeature = class {
3258
3283
  case "insertFromPaste":
3259
3284
  case "insertReplacementText": {
3260
3285
  event.preventDefault();
3261
- const pasteData = (this.store.refs.container ? consumeMarkupPaste(this.store.refs.container) : void 0) ?? event.dataTransfer?.getData("text/plain") ?? "";
3286
+ const c = this.store.state.container();
3287
+ const pasteData = (c ? consumeMarkupPaste(c) : void 0) ?? event.dataTransfer?.getData("text/plain") ?? "";
3262
3288
  const ranges = event.getTargetRanges();
3263
3289
  let rawFrom;
3264
3290
  let rawTo;
@@ -3310,7 +3336,7 @@ var DragFeature = class {
3310
3336
  #unsub;
3311
3337
  enable() {
3312
3338
  if (this.#unsub) return;
3313
- this.#unsub = watch(this.store.event.dragAction, (action) => {
3339
+ this.#unsub = watch(this.store.emit.drag, (action) => {
3314
3340
  switch (action.type) {
3315
3341
  case "reorder":
3316
3342
  this.#reorder(action.source, action.target);
@@ -3345,7 +3371,7 @@ var DragFeature = class {
3345
3371
  const newRowContent = createRowContent(this.store.props.options());
3346
3372
  this.store.state.innerValue(addDragRow(value, rows, afterIndex, newRowContent));
3347
3373
  queueMicrotask(() => {
3348
- const container = this.store.refs.container;
3374
+ const container = this.store.state.container();
3349
3375
  if (!container) return;
3350
3376
  childAt(container, afterIndex + 1)?.focus();
3351
3377
  });
@@ -3390,14 +3416,14 @@ var SystemListenerFeature = class {
3390
3416
  enable() {
3391
3417
  if (this.#scope) return;
3392
3418
  this.#scope = effectScope(() => {
3393
- watch(this.store.event.change, () => {
3419
+ watch(this.store.emit.change, () => {
3394
3420
  const onChange = this.store.props.onChange();
3395
3421
  const { focus } = this.store.nodes;
3396
3422
  if (!focus.target || !focus.target.isContentEditable) {
3397
3423
  const serialized = toString(this.store.state.tokens());
3398
3424
  onChange?.(serialized);
3399
3425
  this.store.state.previousValue(serialized);
3400
- this.store.bumpTokens();
3426
+ trigger(this.store.state.tokens);
3401
3427
  return;
3402
3428
  }
3403
3429
  const tokens = this.store.state.tokens();
@@ -3406,9 +3432,9 @@ var SystemListenerFeature = class {
3406
3432
  if (token.type === "text") token.content = focus.content;
3407
3433
  else token.value = focus.content;
3408
3434
  onChange?.(toString(tokens));
3409
- this.store.event.parse();
3435
+ this.store.emit.reparse();
3410
3436
  });
3411
- watch(this.store.event.delete, (payload) => {
3437
+ watch(this.store.emit.markRemove, (payload) => {
3412
3438
  const { token } = payload;
3413
3439
  const tokens = this.store.state.tokens();
3414
3440
  if (!findToken(tokens, token)) return;
@@ -3425,7 +3451,7 @@ var SystemListenerFeature = class {
3425
3451
  });
3426
3452
  this.store.props.onChange()?.(newValue);
3427
3453
  });
3428
- watch(this.store.event.select, (event) => {
3454
+ watch(this.store.emit.overlaySelect, (event) => {
3429
3455
  const Mark = this.store.props.Mark();
3430
3456
  const onChange = this.store.props.onChange();
3431
3457
  const { mark, match: { option, span, index, source } } = event;
@@ -3453,7 +3479,7 @@ var SystemListenerFeature = class {
3453
3479
  this.store.nodes.focus.target = this.store.nodes.input.target;
3454
3480
  this.store.nodes.input.clear();
3455
3481
  onChange?.(toString(tokens));
3456
- this.store.event.parse();
3482
+ this.store.emit.reparse();
3457
3483
  }
3458
3484
  });
3459
3485
  });
@@ -3472,7 +3498,7 @@ var FocusFeature = class {
3472
3498
  }
3473
3499
  enable() {
3474
3500
  if (this.#scope) return;
3475
- const container = this.store.refs.container;
3501
+ const container = this.store.state.container();
3476
3502
  if (!container) return;
3477
3503
  this.#scope = effectScope(() => {
3478
3504
  listen(container, "focusin", (e) => {
@@ -3485,17 +3511,14 @@ var FocusFeature = class {
3485
3511
  listen(container, "click", () => {
3486
3512
  const tokens = this.store.state.tokens();
3487
3513
  if (tokens.length === 1 && tokens[0].type === "text" && tokens[0].content === "") {
3488
- const container = this.store.refs.container;
3514
+ const container = this.store.state.container();
3489
3515
  (container ? firstHtmlChild(container) : null)?.focus();
3490
3516
  }
3491
3517
  });
3492
- watch(this.store.event.recoverFocus, () => {
3493
- this.#recover();
3494
- });
3495
- watch(this.store.event.afterTokensRendered, () => {
3496
- this.store.event.sync();
3518
+ watch(this.store.emit.rendered, () => {
3519
+ this.store.emit.sync();
3497
3520
  if (!this.store.props.Mark()) return;
3498
- this.store.event.recoverFocus();
3521
+ this.#recover();
3499
3522
  });
3500
3523
  });
3501
3524
  }
@@ -3512,7 +3535,7 @@ var FocusFeature = class {
3512
3535
  let target;
3513
3536
  switch (true) {
3514
3537
  case isNext && isStale: {
3515
- const container = this.store.refs.container;
3538
+ const container = this.store.state.container();
3516
3539
  target = (recovery.childIndex != null ? childAt(container, recovery.childIndex + 2) : void 0) ?? this.store.nodes.focus.tail ?? void 0;
3517
3540
  break;
3518
3541
  }
@@ -3543,14 +3566,14 @@ var InputFeature = class {
3543
3566
  }
3544
3567
  enable() {
3545
3568
  if (this.#scope) return;
3546
- const container = this.store.refs.container;
3569
+ const container = this.store.state.container();
3547
3570
  if (!container) return;
3548
3571
  this.#scope = effectScope(() => {
3549
3572
  listen(container, "keydown", (e) => {
3550
3573
  if (!this.store.computed.isBlock()) this.#handleDelete(e);
3551
3574
  });
3552
3575
  listen(container, "paste", (e) => {
3553
- const c = this.store.refs.container;
3576
+ const c = this.store.state.container();
3554
3577
  if (c) captureMarkupPaste(e, c);
3555
3578
  handlePaste(this.store, e);
3556
3579
  });
@@ -3596,14 +3619,14 @@ var InputFeature = class {
3596
3619
  event.preventDefault();
3597
3620
  focus.content = content.slice(0, caret - 1) + content.slice(caret);
3598
3621
  focus.caret = caret - 1;
3599
- this.store.event.change();
3622
+ this.store.emit.change();
3600
3623
  return;
3601
3624
  }
3602
3625
  if (event.key === KEYBOARD.DELETE && caret >= 0 && caret < content.length) {
3603
3626
  event.preventDefault();
3604
3627
  focus.content = content.slice(0, caret) + content.slice(caret + 1);
3605
3628
  focus.caret = caret;
3606
- this.store.event.change();
3629
+ this.store.emit.change();
3607
3630
  return;
3608
3631
  }
3609
3632
  }
@@ -3625,10 +3648,10 @@ function handleBeforeInput(store, event) {
3625
3648
  const { focus } = store.nodes;
3626
3649
  if (!focus.target || !focus.isEditable) return;
3627
3650
  if ((event.inputType === "insertFromPaste" || event.inputType === "insertReplacementText") && handleMarkputSpanPaste(store, focus, event)) return;
3628
- if (applySpanInput(focus, event)) store.event.change();
3651
+ if (applySpanInput(focus, event)) store.emit.change();
3629
3652
  }
3630
3653
  function handleMarkputSpanPaste(store, focus, event) {
3631
- const container = store.refs.container;
3654
+ const container = store.state.container();
3632
3655
  if (!container) return false;
3633
3656
  const markup = consumeMarkupPaste(container);
3634
3657
  if (!markup) return false;
@@ -3725,7 +3748,8 @@ function handlePaste(store, event) {
3725
3748
  return;
3726
3749
  }
3727
3750
  event.preventDefault();
3728
- replaceAllContentWith(store, (store.refs.container ? consumeMarkupPaste(store.refs.container) : void 0) ?? event.clipboardData?.getData("text/plain") ?? "");
3751
+ const c = store.state.container();
3752
+ replaceAllContentWith(store, (c ? consumeMarkupPaste(c) : void 0) ?? event.clipboardData?.getData("text/plain") ?? "");
3729
3753
  }
3730
3754
  function replaceAllContentWith(store, newContent) {
3731
3755
  store.nodes.focus.target = null;
@@ -3741,7 +3765,7 @@ function replaceAllContentWith(store, newContent) {
3741
3765
  }
3742
3766
  }]);
3743
3767
  queueMicrotask(() => {
3744
- const rawFirstChild = store.refs.container?.firstChild;
3768
+ const rawFirstChild = store.state.container()?.firstChild;
3745
3769
  const firstChild = isHtmlElement(rawFirstChild) ? rawFirstChild : null;
3746
3770
  if (firstChild) {
3747
3771
  store.state.recovery({
@@ -3792,40 +3816,40 @@ var OverlayFeature = class {
3792
3816
  constructor(store) {
3793
3817
  this.store = store;
3794
3818
  }
3819
+ #probeTrigger() {
3820
+ const match = TriggerFinder.find(this.store.props.options(), (option) => option.overlay?.trigger);
3821
+ this.store.state.overlayMatch(match);
3822
+ }
3795
3823
  enable() {
3796
3824
  if (this.#scope) return;
3797
3825
  this.#scope = effectScope(() => {
3798
- watch(this.store.event.clearOverlay, () => {
3826
+ watch(this.store.emit.overlayClose, () => {
3799
3827
  this.store.state.overlayMatch(void 0);
3800
3828
  });
3801
- watch(this.store.event.checkOverlay, () => {
3802
- const match = TriggerFinder.find(this.store.props.options(), (option) => option.overlay?.trigger);
3803
- this.store.state.overlayMatch(match);
3804
- });
3805
- watch(this.store.event.change, () => {
3829
+ watch(this.store.emit.change, () => {
3806
3830
  const showOverlayOn = this.store.props.showOverlayOn();
3807
3831
  const type = "change";
3808
- if (showOverlayOn === type || Array.isArray(showOverlayOn) && showOverlayOn.includes(type)) this.store.event.checkOverlay();
3832
+ if (showOverlayOn === type || Array.isArray(showOverlayOn) && showOverlayOn.includes(type)) this.#probeTrigger();
3809
3833
  });
3810
3834
  alienEffect(() => {
3811
3835
  if (this.store.state.overlayMatch()) {
3812
3836
  this.store.nodes.input.target = this.store.nodes.focus.target;
3813
3837
  listen(window, "keydown", (e) => {
3814
- if (e.key === KEYBOARD.ESC) this.store.event.clearOverlay();
3838
+ if (e.key === KEYBOARD.ESC) this.store.emit.overlayClose();
3815
3839
  });
3816
3840
  listen(document, "click", (e) => {
3817
3841
  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();
3842
+ if (this.store.state.overlay()?.contains(target)) return;
3843
+ if (this.store.state.container()?.contains(target)) return;
3844
+ this.store.emit.overlayClose();
3821
3845
  }, true);
3822
3846
  }
3823
3847
  });
3824
3848
  const selectionChangeHandler = () => {
3825
- if (!this.store.refs.container?.contains(document.activeElement)) return;
3849
+ if (!this.store.state.container()?.contains(document.activeElement)) return;
3826
3850
  const showOverlayOn = this.store.props.showOverlayOn();
3827
3851
  const type = "selectionChange";
3828
- if (showOverlayOn === type || Array.isArray(showOverlayOn) && showOverlayOn.includes(type)) this.store.event.checkOverlay();
3852
+ if (showOverlayOn === type || Array.isArray(showOverlayOn) && showOverlayOn.includes(type)) this.#probeTrigger();
3829
3853
  };
3830
3854
  listen(document, "selectionchange", selectionChangeHandler);
3831
3855
  });
@@ -3963,7 +3987,7 @@ var BlockStore = class {
3963
3987
  #cleanupMenu;
3964
3988
  attachContainer(el, blockIndex, actions) {
3965
3989
  this.#blockIndex = blockIndex;
3966
- this.#dragAction = actions.dragAction;
3990
+ this.#dragAction = actions.drag;
3967
3991
  if (el === this.refs.container) return;
3968
3992
  this.#cleanupContainer?.();
3969
3993
  this.refs.container = el;
@@ -4009,7 +4033,7 @@ var BlockStore = class {
4009
4033
  }
4010
4034
  attachGrip(el, blockIndex, actions) {
4011
4035
  this.#blockIndex = blockIndex;
4012
- this.#dragAction = actions.dragAction;
4036
+ this.#dragAction = actions.drag;
4013
4037
  this.#cleanupGrip?.();
4014
4038
  if (!el) return;
4015
4039
  const onDragStart = (e) => {
@@ -4145,6 +4169,8 @@ var Store = class {
4145
4169
  previousValue: signal(void 0),
4146
4170
  innerValue: signal(void 0),
4147
4171
  recovery: signal(void 0),
4172
+ container: signal(null),
4173
+ overlay: signal(null),
4148
4174
  selecting: signal(void 0),
4149
4175
  overlayMatch: signal(void 0)
4150
4176
  };
@@ -4179,27 +4205,20 @@ var Store = class {
4179
4205
  return (token) => resolveMarkSlot(token, options, Mark, Span);
4180
4206
  })
4181
4207
  };
4182
- event = {
4208
+ emit = {
4183
4209
  change: event(),
4184
- parse: event(),
4185
- delete: event(),
4186
- select: event(),
4187
- clearOverlay: event(),
4188
- checkOverlay: event(),
4210
+ reparse: event(),
4211
+ markRemove: event(),
4212
+ overlaySelect: event(),
4213
+ overlayClose: event(),
4189
4214
  sync: event(),
4190
- recoverFocus: event(),
4191
- dragAction: event(),
4192
- updated: event(),
4193
- afterTokensRendered: event(),
4215
+ drag: event(),
4216
+ rendered: event(),
4194
4217
  mounted: event(),
4195
4218
  unmounted: event()
4196
4219
  };
4197
- refs = {
4198
- container: null,
4199
- overlay: null
4200
- };
4201
4220
  handler = new MarkputHandler(this);
4202
- features = {
4221
+ feature = {
4203
4222
  overlay: new OverlayFeature(this),
4204
4223
  focus: new FocusFeature(this),
4205
4224
  input: new InputFeature(this),
@@ -4213,8 +4232,8 @@ var Store = class {
4213
4232
  parse: new ParseFeature(this)
4214
4233
  };
4215
4234
  constructor() {
4216
- watch(this.event.mounted, () => Object.values(this.features).forEach((f) => f.enable()));
4217
- watch(this.event.unmounted, () => Object.values(this.features).forEach((f) => f.disable()));
4235
+ watch(this.emit.mounted, () => Object.values(this.feature).forEach((f) => f.enable()));
4236
+ watch(this.emit.unmounted, () => Object.values(this.feature).forEach((f) => f.disable()));
4218
4237
  }
4219
4238
  setProps(values) {
4220
4239
  batch(() => {
@@ -4225,9 +4244,6 @@ var Store = class {
4225
4244
  }
4226
4245
  }, { mutable: true });
4227
4246
  }
4228
- bumpTokens() {
4229
- this.state.tokens([...this.state.tokens()]);
4230
- }
4231
4247
  };
4232
4248
  //#endregion
4233
4249
  //#region ../../core/src/features/mark/MarkHandler.ts
@@ -4292,24 +4308,20 @@ var MarkHandler = class {
4292
4308
  if (props.meta !== void 0) this.#token.meta = props.meta;
4293
4309
  this.#emitChange();
4294
4310
  };
4295
- remove = () => this.#store.event.delete({ token: this.#token });
4311
+ remove = () => this.#store.emit.markRemove({ token: this.#token });
4296
4312
  #emitChange() {
4297
- this.#store.event.change();
4313
+ this.#store.emit.change();
4298
4314
  }
4299
4315
  };
4300
4316
  //#endregion
4301
4317
  //#region src/lib/providers/StoreContext.ts
4302
4318
  const StoreContext = createContext(void 0);
4303
4319
  StoreContext.displayName = "StoreContext";
4304
- function useStore() {
4305
- const store = useContext(StoreContext);
4306
- if (store === void 0) throw new Error("Store not found. Make sure to wrap component in StoreContext.");
4307
- return store;
4308
- }
4309
4320
  //#endregion
4310
4321
  //#region src/lib/hooks/useMarkput.ts
4311
4322
  function useMarkput(selector) {
4312
- const store = useStore();
4323
+ const store = useContext(StoreContext);
4324
+ if (store === void 0) throw new Error("Store not found. Make sure to wrap component in StoreContext.");
4313
4325
  const stableRef = useRef(null);
4314
4326
  if (stableRef.current === null) {
4315
4327
  const target = selector(store);
@@ -4365,10 +4377,10 @@ const Popup = ({ ref, style, children }) => {
4365
4377
  //#endregion
4366
4378
  //#region src/components/BlockMenu.tsx
4367
4379
  const BlockMenu = memo(({ token }) => {
4368
- const blockStore = useStore().blocks.get(token);
4369
- const { menuOpen, menuPosition } = useMarkput(() => ({
4370
- menuOpen: blockStore.state.menuOpen,
4371
- menuPosition: blockStore.state.menuPosition
4380
+ const { blockStore, menuOpen, menuPosition } = useMarkput((s) => ({
4381
+ blockStore: s.blocks.get(token),
4382
+ menuOpen: s.blocks.get(token).state.menuOpen,
4383
+ menuPosition: s.blocks.get(token).state.menuPosition
4372
4384
  }));
4373
4385
  if (!menuOpen) return null;
4374
4386
  return /* @__PURE__ */ jsx(Popup, {
@@ -4398,20 +4410,20 @@ BlockMenu.displayName = "BlockMenu";
4398
4410
  //#region src/components/DragHandle.tsx
4399
4411
  const iconGrip = `${styles$1.Icon} ${styles$1.IconGrip}`;
4400
4412
  const DragHandle = memo(({ token, blockIndex }) => {
4401
- const store = useStore();
4402
- const blockStore = store.blocks.get(token);
4403
- const { readOnly, draggable } = useMarkput((s) => ({
4413
+ const { blockStore, emit, readOnly, draggable, isDragging, isHovered } = useMarkput((s) => ({
4414
+ blockStore: s.blocks.get(token),
4415
+ emit: s.emit,
4404
4416
  readOnly: s.props.readOnly,
4405
- draggable: s.props.draggable
4417
+ draggable: s.props.draggable,
4418
+ isDragging: s.blocks.get(token).state.isDragging,
4419
+ isHovered: s.blocks.get(token).state.isHovered
4406
4420
  }));
4407
- const isDragging = useMarkput(() => blockStore.state.isDragging);
4408
- const isHovered = useMarkput(() => blockStore.state.isHovered);
4409
4421
  const alwaysShowHandle = useMemo(() => getAlwaysShowHandle(draggable), [draggable]);
4410
4422
  if (readOnly) return null;
4411
4423
  return /* @__PURE__ */ jsx("div", {
4412
4424
  className: cx(styles$1.SidePanel, alwaysShowHandle ? styles$1.SidePanelAlways : isHovered && !isDragging && styles$1.SidePanelVisible),
4413
4425
  children: /* @__PURE__ */ jsx("button", {
4414
- ref: (el) => blockStore.attachGrip(el, blockIndex, store.event),
4426
+ ref: (el) => blockStore.attachGrip(el, blockIndex, emit),
4415
4427
  type: "button",
4416
4428
  draggable: true,
4417
4429
  className: cx(styles$1.GripButton, isDragging && styles$1.GripButtonDragging),
@@ -4424,8 +4436,7 @@ DragHandle.displayName = "DragHandle";
4424
4436
  //#endregion
4425
4437
  //#region src/components/DropIndicator.tsx
4426
4438
  const DropIndicator = memo(({ token, position }) => {
4427
- const blockStore = useStore().blocks.get(token);
4428
- if (useMarkput(() => blockStore.state.dropPosition) !== position) return null;
4439
+ if (useMarkput((s) => s.blocks.get(token).state.dropPosition) !== position) return null;
4429
4440
  return /* @__PURE__ */ jsx("div", {
4430
4441
  className: styles$1.DropIndicator,
4431
4442
  style: position === "before" ? { top: -1 } : { bottom: -1 }
@@ -4444,12 +4455,15 @@ function useToken() {
4444
4455
  //#endregion
4445
4456
  //#region src/components/Token.tsx
4446
4457
  const Token = memo(({ mark }) => {
4447
- const store = useStore();
4448
- const [Component, props] = useMarkput((s) => s.computed.mark)(mark);
4458
+ const { resolveMarkSlot, key } = useMarkput((s) => ({
4459
+ resolveMarkSlot: s.computed.mark,
4460
+ key: s.key
4461
+ }));
4462
+ const [Component, props] = resolveMarkSlot(mark);
4449
4463
  return /* @__PURE__ */ jsx(TokenContext, {
4450
4464
  value: mark,
4451
4465
  children: /* @__PURE__ */ jsx(Component, {
4452
- children: mark.type === "mark" && mark.children.length > 0 ? mark.children.map((child) => /* @__PURE__ */ jsx(Token, { mark: child }, store.key.get(child))) : void 0,
4466
+ children: mark.type === "mark" && mark.children.length > 0 ? mark.children.map((child) => /* @__PURE__ */ jsx(Token, { mark: child }, key.get(child))) : void 0,
4453
4467
  ...props
4454
4468
  })
4455
4469
  });
@@ -4457,14 +4471,18 @@ const Token = memo(({ mark }) => {
4457
4471
  Token.displayName = "Token";
4458
4472
  //#endregion
4459
4473
  //#region src/components/Block.tsx
4460
- const Block = memo(({ token, blockIndex }) => {
4461
- const store = useStore();
4462
- const blockStore = store.blocks.get(token);
4463
- const Component = useMarkput((s) => s.computed.blockComponent);
4464
- const slotProps = useMarkput((s) => s.computed.blockProps);
4465
- const isDragging = useMarkput(() => blockStore.state.isDragging);
4474
+ const Block = memo(({ token }) => {
4475
+ const { blockStore, emit, Component, slotProps, isDragging, tokens } = useMarkput((s) => ({
4476
+ blockStore: s.blocks.get(token),
4477
+ emit: s.emit,
4478
+ Component: s.computed.blockComponent,
4479
+ slotProps: s.computed.blockProps,
4480
+ isDragging: s.blocks.get(token).state.isDragging,
4481
+ tokens: s.state.tokens
4482
+ }));
4483
+ const blockIndex = tokens.indexOf(token);
4466
4484
  return /* @__PURE__ */ jsxs(Component, {
4467
- ref: (el) => blockStore.attachContainer(el, blockIndex, store.event),
4485
+ ref: (el) => blockStore.attachContainer(el, blockIndex, emit),
4468
4486
  "data-testid": "block",
4469
4487
  ...slotProps,
4470
4488
  className: cx(styles$1.Block, slotProps?.className),
@@ -4494,33 +4512,33 @@ Block.displayName = "Block";
4494
4512
  //#endregion
4495
4513
  //#region src/components/Container.tsx
4496
4514
  const Container = memo(() => {
4497
- const { layout, tokens, key, refs, event } = useMarkput((s) => ({
4498
- layout: s.props.layout,
4515
+ const { isBlock, tokens, key, state, emit, Component, props } = useMarkput((s) => ({
4516
+ isBlock: s.computed.isBlock,
4499
4517
  tokens: s.state.tokens,
4500
4518
  key: s.key,
4501
- refs: s.refs,
4502
- event: s.event
4519
+ state: s.state,
4520
+ emit: s.emit,
4521
+ Component: s.computed.containerComponent,
4522
+ props: s.computed.containerProps
4503
4523
  }));
4504
- const Component = useMarkput((s) => s.computed.containerComponent);
4505
- const props = useMarkput((s) => s.computed.containerProps);
4506
4524
  useLayoutEffect(() => {
4507
- event.afterTokensRendered();
4508
- }, [tokens, event]);
4525
+ emit.rendered();
4526
+ }, [tokens, emit]);
4509
4527
  return /* @__PURE__ */ jsx(Component, {
4510
- ref: (el) => refs.container = el,
4528
+ ref: state.container,
4511
4529
  ...props,
4512
- children: layout === "block" ? tokens.map((t, i) => /* @__PURE__ */ jsx(Block, {
4513
- token: t,
4514
- blockIndex: i
4515
- }, key.get(t))) : tokens.map((t) => /* @__PURE__ */ jsx(Token, { mark: t }, key.get(t)))
4530
+ children: isBlock ? tokens.map((t) => /* @__PURE__ */ jsx(Block, { token: t }, key.get(t))) : tokens.map((t) => /* @__PURE__ */ jsx(Token, { mark: t }, key.get(t)))
4516
4531
  });
4517
4532
  });
4518
4533
  Container.displayName = "Container";
4519
4534
  //#endregion
4520
4535
  //#region src/lib/hooks/useOverlay.tsx
4521
4536
  function useOverlay() {
4522
- const store = useStore();
4523
- const match = useMarkput((s) => s.state.overlayMatch);
4537
+ const { match, emit, state } = useMarkput((s) => ({
4538
+ match: s.state.overlayMatch,
4539
+ emit: s.emit,
4540
+ state: s.state
4541
+ }));
4524
4542
  const style = useMemo(() => {
4525
4543
  if (!match) return {
4526
4544
  left: 0,
@@ -4528,26 +4546,26 @@ function useOverlay() {
4528
4546
  };
4529
4547
  return Caret.getAbsolutePosition();
4530
4548
  }, [match]);
4531
- const close = useCallback(() => store.event.clearOverlay(), []);
4549
+ const close = useCallback(() => emit.overlayClose(), []);
4532
4550
  return {
4533
4551
  match,
4534
4552
  style,
4535
4553
  select: useCallback((value) => {
4536
4554
  if (!match) return;
4537
4555
  const mark = createMarkFromOverlay(match, value.value, value.meta);
4538
- store.event.select({
4556
+ emit.overlaySelect({
4539
4557
  mark,
4540
4558
  match
4541
4559
  });
4542
- store.event.clearOverlay();
4560
+ emit.overlayClose();
4543
4561
  }, [match]),
4544
4562
  close,
4545
4563
  ref: useMemo(() => ({
4546
4564
  get current() {
4547
- return store.refs.overlay;
4565
+ return state.overlay();
4548
4566
  },
4549
4567
  set current(v) {
4550
- store.refs.overlay = v;
4568
+ state.overlay(v);
4551
4569
  }
4552
4570
  }), [])
4553
4571
  };
@@ -4555,7 +4573,7 @@ function useOverlay() {
4555
4573
  //#endregion
4556
4574
  //#region src/components/Suggestions/Suggestions.tsx
4557
4575
  const Suggestions = () => {
4558
- const store = useStore();
4576
+ const { state } = useMarkput((s) => ({ state: s.state }));
4559
4577
  const { match, select, style, ref } = useOverlay();
4560
4578
  const [active, setActive] = useState(NaN);
4561
4579
  const data = match?.option.overlay?.data ?? [];
@@ -4566,7 +4584,7 @@ const Suggestions = () => {
4566
4584
  const filteredRef = useRef(filtered);
4567
4585
  filteredRef.current = filtered;
4568
4586
  useEffect(() => {
4569
- const container = store.refs.container;
4587
+ const container = state.container();
4570
4588
  if (!container) return;
4571
4589
  const handler = (event) => {
4572
4590
  const result = navigateSuggestions(event.key, activeRef.current, length);
@@ -4608,10 +4626,13 @@ const Suggestions = () => {
4608
4626
  //#endregion
4609
4627
  //#region src/components/OverlayRenderer.tsx
4610
4628
  const OverlayRenderer = memo(() => {
4611
- const store = useStore();
4612
- const overlayMatch = useMarkput((s) => s.state.overlayMatch);
4613
- const key = useMemo(() => overlayMatch ? store.key.get(overlayMatch.option) : void 0, [overlayMatch]);
4614
- const [Overlay, props] = useMarkput((s) => s.computed.overlay)(overlayMatch?.option, Suggestions);
4629
+ const { overlayMatch, key: keyGen, resolveOverlay } = useMarkput((s) => ({
4630
+ overlayMatch: s.state.overlayMatch,
4631
+ key: s.key,
4632
+ resolveOverlay: s.computed.overlay
4633
+ }));
4634
+ const key = useMemo(() => overlayMatch ? keyGen.get(overlayMatch.option) : void 0, [overlayMatch]);
4635
+ const [Overlay, props] = resolveOverlay(overlayMatch?.option, Suggestions);
4615
4636
  if (!key) return;
4616
4637
  return /* @__PURE__ */ jsx(Overlay, { ...props }, key);
4617
4638
  });
@@ -4622,10 +4643,9 @@ function MarkedInput(props) {
4622
4643
  const [store] = useState(() => new Store());
4623
4644
  store.setProps(props);
4624
4645
  useLayoutEffect(() => {
4625
- store.event.mounted();
4626
- return () => store.event.unmounted();
4646
+ store.emit.mounted();
4647
+ return () => store.emit.unmounted();
4627
4648
  }, []);
4628
- useLayoutEffect(() => store.event.updated());
4629
4649
  useImperativeHandle(props.ref, () => store.handler, [store]);
4630
4650
  return /* @__PURE__ */ jsxs(StoreContext, {
4631
4651
  value: store,
@@ -4635,7 +4655,10 @@ function MarkedInput(props) {
4635
4655
  //#endregion
4636
4656
  //#region src/lib/hooks/useMark.tsx
4637
4657
  const useMark = (options = {}) => {
4638
- const store = useStore();
4658
+ const { store, readOnly } = useMarkput((s) => ({
4659
+ store: s,
4660
+ readOnly: s.props.readOnly
4661
+ }));
4639
4662
  const token = useToken();
4640
4663
  if (token.type !== "mark") throw new Error("useMark must be called within a mark token context");
4641
4664
  const ref = useRef(null);
@@ -4645,7 +4668,6 @@ const useMark = (options = {}) => {
4645
4668
  token
4646
4669
  }), [store, token]);
4647
4670
  useUncontrolledInit(ref, options, token);
4648
- const readOnly = useMarkput((s) => s.props.readOnly);
4649
4671
  useEffect(() => {
4650
4672
  mark.readOnly = readOnly;
4651
4673
  }, [mark, readOnly]);