@hexdspace/react 0.1.50 → 0.1.52

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/dist/index.d.ts CHANGED
@@ -926,13 +926,13 @@ declare class VimController {
926
926
  private readonly regions;
927
927
  private readonly handleKey;
928
928
  private readonly selection;
929
- private readonly modifierMovementActionsByScope;
929
+ private readonly modifierMovementActionsByRegion;
930
930
  constructor(selection: SelectionController, regions?: VimRegionRegistry, handleKey?: VimHandleKeyUseCase);
931
931
  handleRegisterRegionMeta(meta: VimRegionMeta): void;
932
932
  handleUnregisterRegionMeta(key: RegionKey): void;
933
933
  handleCharKey(char: string, e: KeyboardEvent): void;
934
934
  handleEscape(e: KeyboardEvent): void;
935
- setModifierMovementActions(scopeId: ScopeId, actions: VimModifierMovementActions | null): void;
935
+ setModifierMovementActions(key: RegionKey, actions: VimModifierMovementActions | null): void;
936
936
  handleModifiedMovement(dir: VimDirection, modifier: VimMovementModifier, e: KeyboardEvent): void;
937
937
  resetActiveScope(): void;
938
938
  getSelection(): SelectionController;
@@ -956,7 +956,7 @@ type VimBindingOptions = {
956
956
  allowArrowKeys?: boolean;
957
957
  modifierMovementActions?: VimModifierMovementActions;
958
958
  };
959
- declare function useVimBindings(keyboardScopeId: string, options?: VimBindingOptions): void;
959
+ declare function useVimBindings(regionKey: RegionKey, keyboardScopeId: string, options?: VimBindingOptions): void;
960
960
 
961
961
  type UseVimRegionArgs = {
962
962
  key: RegionKey;
package/dist/index.js CHANGED
@@ -3576,7 +3576,7 @@ var VimController = class {
3576
3576
  regions;
3577
3577
  handleKey;
3578
3578
  selection;
3579
- modifierMovementActionsByScope = /* @__PURE__ */ new Map();
3579
+ modifierMovementActionsByRegion = /* @__PURE__ */ new Map();
3580
3580
  constructor(selection, regions = new VimRegionRegistry(), handleKey = new VimHandleKeyUseCase(
3581
3581
  selection.getHandle(),
3582
3582
  selection.getQuery(),
@@ -3599,19 +3599,20 @@ var VimController = class {
3599
3599
  handleEscape(e) {
3600
3600
  this.handleKey.handleEscape(e);
3601
3601
  }
3602
- setModifierMovementActions(scopeId, actions) {
3602
+ setModifierMovementActions(key, actions) {
3603
+ const regionKey = toRegionKeyString(key);
3603
3604
  if (!actions) {
3604
- this.modifierMovementActionsByScope.delete(scopeId);
3605
+ this.modifierMovementActionsByRegion.delete(regionKey);
3605
3606
  return;
3606
3607
  }
3607
- this.modifierMovementActionsByScope.set(scopeId, actions);
3608
+ this.modifierMovementActionsByRegion.set(regionKey, actions);
3608
3609
  }
3609
3610
  handleModifiedMovement(dir, modifier, e) {
3610
3611
  const scopeId = this.selection.getActiveScope();
3611
3612
  if (!scopeId) return;
3612
3613
  const activeKey = this.selection.getActiveRegion(scopeId);
3613
3614
  if (!activeKey) return;
3614
- const actions = this.modifierMovementActionsByScope.get(scopeId);
3615
+ const actions = this.modifierMovementActionsByRegion.get(toRegionKeyString(activeKey));
3615
3616
  const action = actions?.[modifier]?.[dir];
3616
3617
  if (!action) return;
3617
3618
  const itemId = this.selection.getActiveItem(activeKey);
@@ -3648,6 +3649,9 @@ var createVimController = controllerFactory(
3648
3649
  };
3649
3650
  }
3650
3651
  );
3652
+ function toRegionKeyString(key) {
3653
+ return `${key.scopeId}.${key.regionId}`;
3654
+ }
3651
3655
 
3652
3656
  // src/feature/vim-navigation/infra/web/react/VimControllerProvider.tsx
3653
3657
  import { createContext as createContext5, useContext as useContext6 } from "react";
@@ -3667,30 +3671,40 @@ import { useCallback as useCallback5, useEffect as useEffect7, useMemo as useMem
3667
3671
  var scopeBindings = /* @__PURE__ */ new Map();
3668
3672
  function notify(entry) {
3669
3673
  for (const notifySub of entry.subscribers.values()) {
3670
- notifySub(entry.ownerId);
3674
+ notifySub(entry);
3671
3675
  }
3672
3676
  }
3673
- function useVimBindings(keyboardScopeId, options = {}) {
3677
+ function getScopeEntry(keyboardScopeId) {
3678
+ const existing = scopeBindings.get(keyboardScopeId);
3679
+ if (existing) return existing;
3680
+ const entry = {
3681
+ ownerId: null,
3682
+ subscribers: /* @__PURE__ */ new Map(),
3683
+ modifierActionsByOwner: /* @__PURE__ */ new Map(),
3684
+ modifierActionsVersion: 0
3685
+ };
3686
+ scopeBindings.set(keyboardScopeId, entry);
3687
+ return entry;
3688
+ }
3689
+ function useVimBindings(regionKey, keyboardScopeId, options = {}) {
3674
3690
  const vim = useVimController();
3675
3691
  const enabled = options.enabled ?? true;
3676
3692
  const allowArrowKeys = options.allowArrowKeys ?? true;
3677
3693
  const modifierMovementActions = options.modifierMovementActions;
3678
3694
  const ownerIdRef = useRef3(Symbol("vim-binding-owner"));
3679
3695
  const [isOwner, setIsOwner] = useState5(false);
3680
- const handleOwnerChange = useCallback5((ownerId) => {
3681
- setIsOwner(ownerId === ownerIdRef.current);
3696
+ const [modifierActionsVersion, setModifierActionsVersion] = useState5(0);
3697
+ const handleEntryChange = useCallback5((entry) => {
3698
+ setIsOwner(entry.ownerId === ownerIdRef.current);
3699
+ setModifierActionsVersion(entry.modifierActionsVersion);
3682
3700
  }, []);
3683
3701
  useEffect7(() => {
3684
3702
  if (!enabled) {
3685
3703
  setIsOwner(false);
3686
3704
  return;
3687
3705
  }
3688
- const entry = scopeBindings.get(keyboardScopeId) ?? {
3689
- ownerId: null,
3690
- subscribers: /* @__PURE__ */ new Map()
3691
- };
3692
- scopeBindings.set(keyboardScopeId, entry);
3693
- entry.subscribers.set(ownerIdRef.current, handleOwnerChange);
3706
+ const entry = getScopeEntry(keyboardScopeId);
3707
+ entry.subscribers.set(ownerIdRef.current, handleEntryChange);
3694
3708
  if (!entry.ownerId) {
3695
3709
  entry.ownerId = ownerIdRef.current;
3696
3710
  }
@@ -3700,25 +3714,46 @@ function useVimBindings(keyboardScopeId, options = {}) {
3700
3714
  if (entry.ownerId === ownerIdRef.current) {
3701
3715
  const nextOwner = entry.subscribers.keys().next().value ?? null;
3702
3716
  entry.ownerId = nextOwner;
3703
- if (!nextOwner && entry.subscribers.size === 0) {
3717
+ if (!nextOwner && entry.subscribers.size === 0 && entry.modifierActionsByOwner.size === 0) {
3704
3718
  scopeBindings.delete(keyboardScopeId);
3705
3719
  return;
3706
3720
  }
3707
3721
  notify(entry);
3708
3722
  return;
3709
3723
  }
3710
- if (entry.subscribers.size === 0) {
3724
+ if (entry.subscribers.size === 0 && entry.modifierActionsByOwner.size === 0) {
3711
3725
  scopeBindings.delete(keyboardScopeId);
3712
3726
  }
3713
3727
  };
3714
- }, [enabled, handleOwnerChange, keyboardScopeId]);
3728
+ }, [enabled, handleEntryChange, keyboardScopeId]);
3715
3729
  useEffect7(() => {
3716
- if (!enabled || !isOwner) {
3730
+ if (!enabled) {
3717
3731
  return;
3718
3732
  }
3719
- vim.setModifierMovementActions(keyboardScopeId, modifierMovementActions ?? null);
3720
- return () => vim.setModifierMovementActions(keyboardScopeId, null);
3721
- }, [enabled, isOwner, keyboardScopeId, modifierMovementActions, vim]);
3733
+ const entry = getScopeEntry(keyboardScopeId);
3734
+ entry.modifierActionsByOwner.set(ownerIdRef.current, modifierMovementActions ?? null);
3735
+ entry.modifierActionsVersion += 1;
3736
+ notify(entry);
3737
+ return () => {
3738
+ const existing = scopeBindings.get(keyboardScopeId);
3739
+ if (!existing) return;
3740
+ existing.modifierActionsByOwner.delete(ownerIdRef.current);
3741
+ existing.modifierActionsVersion += 1;
3742
+ if (!existing.ownerId && existing.subscribers.size === 0 && existing.modifierActionsByOwner.size === 0) {
3743
+ scopeBindings.delete(keyboardScopeId);
3744
+ return;
3745
+ }
3746
+ notify(existing);
3747
+ };
3748
+ }, [enabled, keyboardScopeId, modifierMovementActions]);
3749
+ useEffect7(() => {
3750
+ if (!enabled) {
3751
+ vim.setModifierMovementActions(regionKey, null);
3752
+ return;
3753
+ }
3754
+ vim.setModifierMovementActions(regionKey, modifierMovementActions ?? null);
3755
+ return () => vim.setModifierMovementActions(regionKey, null);
3756
+ }, [enabled, modifierMovementActions, regionKey, vim]);
3722
3757
  const bindings = useMemo6(() => {
3723
3758
  if (!enabled || !isOwner) {
3724
3759
  return [];
@@ -3752,11 +3787,12 @@ function useVimBindings(keyboardScopeId, options = {}) {
3752
3787
  shift: { label: "Shift", prefix: "Shift" },
3753
3788
  ctrlShift: { label: "Ctrl+Shift", prefix: "Control+Shift" }
3754
3789
  };
3790
+ const modifierAvailability = getModifierAvailability(keyboardScopeId);
3755
3791
  const modifierBindings = (modifier, actions) => {
3756
3792
  if (!actions) return [];
3757
3793
  const { label, prefix } = modifierLabels[modifier];
3758
3794
  return movementEntries.flatMap((entry) => {
3759
- if (!actions?.[entry.dir]) return [];
3795
+ if (!actions[entry.dir]) return [];
3760
3796
  const combos = [`${prefix}+${entry.char.toUpperCase()}`];
3761
3797
  if (entry.arrow) {
3762
3798
  combos.push(`${prefix}+${entry.arrow}`);
@@ -3812,13 +3848,44 @@ function useVimBindings(keyboardScopeId, options = {}) {
3812
3848
  group: "vim"
3813
3849
  },
3814
3850
  { combos: ["Escape"], handler: (e) => vim.handleEscape(e), description: "vim: escape", group: "vim" },
3815
- ...modifierBindings("ctrl", modifierMovementActions?.ctrl),
3816
- ...modifierBindings("shift", modifierMovementActions?.shift),
3817
- ...modifierBindings("ctrlShift", modifierMovementActions?.ctrlShift)
3851
+ ...modifierBindings("ctrl", modifierAvailability?.ctrl),
3852
+ ...modifierBindings("shift", modifierAvailability?.shift),
3853
+ ...modifierBindings("ctrlShift", modifierAvailability?.ctrlShift)
3818
3854
  ];
3819
- }, [allowArrowKeys, enabled, isOwner, modifierMovementActions, vim]);
3855
+ }, [allowArrowKeys, enabled, isOwner, keyboardScopeId, modifierActionsVersion, vim]);
3820
3856
  useShortcut(keyboardScopeId, bindings, { ignoreTyping: true, preventDefault: true });
3821
3857
  }
3858
+ function getModifierAvailability(keyboardScopeId) {
3859
+ const entry = scopeBindings.get(keyboardScopeId);
3860
+ if (!entry) return null;
3861
+ const result = {
3862
+ ctrl: {},
3863
+ shift: {},
3864
+ ctrlShift: {}
3865
+ };
3866
+ for (const actions of entry.modifierActionsByOwner.values()) {
3867
+ if (!actions) continue;
3868
+ const ctrl = actions.ctrl;
3869
+ if (ctrl) {
3870
+ for (const dir of Object.keys(ctrl)) {
3871
+ if (ctrl[dir]) result.ctrl[dir] = true;
3872
+ }
3873
+ }
3874
+ const shift = actions.shift;
3875
+ if (shift) {
3876
+ for (const dir of Object.keys(shift)) {
3877
+ if (shift[dir]) result.shift[dir] = true;
3878
+ }
3879
+ }
3880
+ const ctrlShift = actions.ctrlShift;
3881
+ if (ctrlShift) {
3882
+ for (const dir of Object.keys(ctrlShift)) {
3883
+ if (ctrlShift[dir]) result.ctrlShift[dir] = true;
3884
+ }
3885
+ }
3886
+ }
3887
+ return result;
3888
+ }
3822
3889
 
3823
3890
  // src/feature/vim-navigation/infra/web/react/hook/use-vim-region.tsx
3824
3891
  import { useEffect as useEffect9, useMemo as useMemo8, useRef as useRef4, useSyncExternalStore } from "react";
@@ -3899,7 +3966,7 @@ function useVimRegion(containerRef, args) {
3899
3966
  keyboard.handleEnableScope(keyboardScopeId);
3900
3967
  return () => keyboard.handleDisableScope(keyboardScopeId);
3901
3968
  }, [bindKeys, keyboard, keyboardScopeId]);
3902
- useVimBindings(keyboardScopeId, {
3969
+ useVimBindings(args.key, keyboardScopeId, {
3903
3970
  enabled: bindKeys,
3904
3971
  allowArrowKeys: args.allowArrowKeys,
3905
3972
  modifierMovementActions: args.modifierMovementActions
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexdspace/react",
3
- "version": "0.1.50",
3
+ "version": "0.1.52",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",