@hexdspace/react 0.1.48 → 0.1.50

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
@@ -894,6 +894,7 @@ declare class VimHandleKeyUseCase {
894
894
  reset(scopeId?: ScopeId): void;
895
895
  handleChar(char: string, e: KeyboardEvent): void;
896
896
  handleEscape(e: KeyboardEvent): void;
897
+ consumeCount(scopeId: ScopeId, def: number): number;
897
898
  private applyDirectional;
898
899
  private goToLast;
899
900
  private goToIndex;
@@ -906,15 +907,33 @@ declare class VimHandleKeyUseCase {
906
907
  private resolveInterRegionFallback;
907
908
  }
908
909
 
910
+ type VimMovementModifier = 'ctrl' | 'shift' | 'ctrlShift';
911
+ type VimModifierMovementActionArgs = {
912
+ scopeId: ScopeId;
913
+ key: RegionKey;
914
+ itemId: ItemId | null;
915
+ direction: VimDirection;
916
+ count: number;
917
+ event: KeyboardEvent;
918
+ };
919
+ type VimModifierMovementAction = (args: VimModifierMovementActionArgs) => void;
920
+ type VimModifierMovementActions = {
921
+ ctrl?: Partial<Record<VimDirection, VimModifierMovementAction>>;
922
+ shift?: Partial<Record<VimDirection, VimModifierMovementAction>>;
923
+ ctrlShift?: Partial<Record<VimDirection, VimModifierMovementAction>>;
924
+ };
909
925
  declare class VimController {
910
926
  private readonly regions;
911
927
  private readonly handleKey;
912
928
  private readonly selection;
929
+ private readonly modifierMovementActionsByScope;
913
930
  constructor(selection: SelectionController, regions?: VimRegionRegistry, handleKey?: VimHandleKeyUseCase);
914
931
  handleRegisterRegionMeta(meta: VimRegionMeta): void;
915
932
  handleUnregisterRegionMeta(key: RegionKey): void;
916
933
  handleCharKey(char: string, e: KeyboardEvent): void;
917
934
  handleEscape(e: KeyboardEvent): void;
935
+ setModifierMovementActions(scopeId: ScopeId, actions: VimModifierMovementActions | null): void;
936
+ handleModifiedMovement(dir: VimDirection, modifier: VimMovementModifier, e: KeyboardEvent): void;
918
937
  resetActiveScope(): void;
919
938
  getSelection(): SelectionController;
920
939
  }
@@ -935,6 +954,7 @@ declare function useVimController(): VimController;
935
954
  type VimBindingOptions = {
936
955
  enabled?: boolean;
937
956
  allowArrowKeys?: boolean;
957
+ modifierMovementActions?: VimModifierMovementActions;
938
958
  };
939
959
  declare function useVimBindings(keyboardScopeId: string, options?: VimBindingOptions): void;
940
960
 
@@ -952,6 +972,7 @@ type UseVimRegionArgs = {
952
972
  keyboardScopeId?: string;
953
973
  bindKeys?: boolean;
954
974
  allowArrowKeys?: boolean;
975
+ modifierMovementActions?: VimModifierMovementActions;
955
976
  refreshDeps?: React__default.DependencyList;
956
977
  };
957
978
  type UseVimRegionResult = {
@@ -1139,4 +1160,4 @@ declare const Kbd: React.ForwardRefExoticComponent<KbdProps & React.RefAttribute
1139
1160
 
1140
1161
  declare function useMotionDuration(varName: string, fallbackSeconds: number): number;
1141
1162
 
1142
- export { AuthController, AuthControllerCtx, type AuthControllerDeps, AuthControllerProvider, AuthDispatchCtx, AuthProvider, type AuthState, AuthStateCtx, Button, type ButtonProps, type CacheInstruction, type ClearSelectionArgs, type ClearTarget, type CombineMode, ConfirmDialog, type ConfirmDialogProps, type ConfirmPayload, type CursorFallback, CustomDialog, type CustomDialogPayload, type CustomDialogProps, type CustomInstruction, DEFAULT_NOTIFICATION_CHANNEL, type DefaultDialogPayloads, type DefaultDialogTemplateKey, DefaultDialogTemplateKeys, Dialog, DialogContent, DialogController, DialogHost, type DialogInstance, type DialogOptions, type DialogProps, type DialogTemplate, type DisableScope, DisableScopeUseCase, DropdownMenu, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuProps, DropdownMenuSeparator, type EnableScope, EnableScopeUseCase, type ErrorResponse, Field, type FieldProps, type GenericResponse, type GroupedShortcuts, type HandleSelection, type HttpClient, HttpError, type HttpMethod, type HttpResponse, InMemorySelectionStore, InfoDialog, type InfoDialogProps, type InfoPayload, Input, type InputProps, type Instruction, type InstructionContext, type ItemId, Kbd, type KbdProps, KeyboardController, KeyboardProvider, type ListShortcuts, ListShortcutsUseCase, type ListedShortcut, MockAuthHttpClient, MockHttpClient, type Mode, type MutationFn, type Notification, type NotificationAction, NotificationHost, type NotificationInstruction, type NotificationVariant, NotifierController, type OnSuccessFn, type OptimisticSnapshot, type OptimisticUpdateFn, Popover, type PopoverProps, type QuerySelection, RedirectIfAuthed, type RedirectIfAuthedProps, type RegionId, type RegionKey, type RegionSelection, type RegisterRegionArgs, type RegisterShortcut, RegisterShortcutUseCase, type RequestConfig, RequireAuth, type RequireAuthProps, type ResolvedToastTheme, type ResponsiveMutation, type ScopeId, ScopeManager, type ScopeState, SelectionController, type SelectionControllerDeps, SelectionControllerProvider, type SelectionState, type SelectionStore, type ShortcutBinding, type ShortcutHandler, type ShortcutRegistration, type ShortcutScope, Skeleton, type SkeletonProps, Textarea, type TextareaProps, type ToastActionTheme, type ToastTheme, type ToastTransition, type ToastifyCSSVars, Tooltip, type UIFail, type UIOk, type UIResult, type UnregisterShortcut, UnregisterShortcutUseCase, type UseVimRegionArgs, type UseVimRegionResult, type User, VimController, type VimControllerDeps, VimControllerProvider, type VimDirection, type VimInterDirection, type VimKeyState, type VimPending, type VimRegionMeta, VimRegionRegistry, authController, controllerFactory, createAuthController, createSelectionController, createVimController, dialogController, httpClient as fetchHttpClient, getDialogTemplate, keyboardController, notifierController, registerDefaultDialogs, registerDialogTemplate, resolveToastTheme, ui, unregisterDialogTemplate, useAuth, useAuthActions, useAuthController, useAuthDispatch, useAuthedUser, useDialog, useKeyboardController, useMotionDuration, useResponsiveMutation, useSelectionController, useShortcut, useShortcutScope, useVimBindings, useVimController, useVimRegion };
1163
+ export { AuthController, AuthControllerCtx, type AuthControllerDeps, AuthControllerProvider, AuthDispatchCtx, AuthProvider, type AuthState, AuthStateCtx, Button, type ButtonProps, type CacheInstruction, type ClearSelectionArgs, type ClearTarget, type CombineMode, ConfirmDialog, type ConfirmDialogProps, type ConfirmPayload, type CursorFallback, CustomDialog, type CustomDialogPayload, type CustomDialogProps, type CustomInstruction, DEFAULT_NOTIFICATION_CHANNEL, type DefaultDialogPayloads, type DefaultDialogTemplateKey, DefaultDialogTemplateKeys, Dialog, DialogContent, DialogController, DialogHost, type DialogInstance, type DialogOptions, type DialogProps, type DialogTemplate, type DisableScope, DisableScopeUseCase, DropdownMenu, DropdownMenuItem, type DropdownMenuItemProps, type DropdownMenuProps, DropdownMenuSeparator, type EnableScope, EnableScopeUseCase, type ErrorResponse, Field, type FieldProps, type GenericResponse, type GroupedShortcuts, type HandleSelection, type HttpClient, HttpError, type HttpMethod, type HttpResponse, InMemorySelectionStore, InfoDialog, type InfoDialogProps, type InfoPayload, Input, type InputProps, type Instruction, type InstructionContext, type ItemId, Kbd, type KbdProps, KeyboardController, KeyboardProvider, type ListShortcuts, ListShortcutsUseCase, type ListedShortcut, MockAuthHttpClient, MockHttpClient, type Mode, type MutationFn, type Notification, type NotificationAction, NotificationHost, type NotificationInstruction, type NotificationVariant, NotifierController, type OnSuccessFn, type OptimisticSnapshot, type OptimisticUpdateFn, Popover, type PopoverProps, type QuerySelection, RedirectIfAuthed, type RedirectIfAuthedProps, type RegionId, type RegionKey, type RegionSelection, type RegisterRegionArgs, type RegisterShortcut, RegisterShortcutUseCase, type RequestConfig, RequireAuth, type RequireAuthProps, type ResolvedToastTheme, type ResponsiveMutation, type ScopeId, ScopeManager, type ScopeState, SelectionController, type SelectionControllerDeps, SelectionControllerProvider, type SelectionState, type SelectionStore, type ShortcutBinding, type ShortcutHandler, type ShortcutRegistration, type ShortcutScope, Skeleton, type SkeletonProps, Textarea, type TextareaProps, type ToastActionTheme, type ToastTheme, type ToastTransition, type ToastifyCSSVars, Tooltip, type UIFail, type UIOk, type UIResult, type UnregisterShortcut, UnregisterShortcutUseCase, type UseVimRegionArgs, type UseVimRegionResult, type User, VimController, type VimControllerDeps, VimControllerProvider, type VimDirection, type VimInterDirection, type VimKeyState, type VimModifierMovementAction, type VimModifierMovementActionArgs, type VimModifierMovementActions, type VimMovementModifier, type VimPending, type VimRegionMeta, VimRegionRegistry, authController, controllerFactory, createAuthController, createSelectionController, createVimController, dialogController, httpClient as fetchHttpClient, getDialogTemplate, keyboardController, notifierController, registerDefaultDialogs, registerDialogTemplate, resolveToastTheme, ui, unregisterDialogTemplate, useAuth, useAuthActions, useAuthController, useAuthDispatch, useAuthedUser, useDialog, useKeyboardController, useMotionDuration, useResponsiveMutation, useSelectionController, useShortcut, useShortcutScope, useVimBindings, useVimController, useVimRegion };
package/dist/index.js CHANGED
@@ -3383,6 +3383,13 @@ var VimHandleKeyUseCase = class {
3383
3383
  st.pending = null;
3384
3384
  }
3385
3385
  }
3386
+ consumeCount(scopeId, def) {
3387
+ const st = this.stateByScope.get(scopeId);
3388
+ if (!st) return def;
3389
+ const count = consumeCount(st, def);
3390
+ st.pending = null;
3391
+ return count;
3392
+ }
3386
3393
  applyDirectional(scopeId, activeKey, dir, count) {
3387
3394
  const meta = this.regions.get(activeKey);
3388
3395
  if (meta?.intra.has(dir)) {
@@ -3569,6 +3576,7 @@ var VimController = class {
3569
3576
  regions;
3570
3577
  handleKey;
3571
3578
  selection;
3579
+ modifierMovementActionsByScope = /* @__PURE__ */ new Map();
3572
3580
  constructor(selection, regions = new VimRegionRegistry(), handleKey = new VimHandleKeyUseCase(
3573
3581
  selection.getHandle(),
3574
3582
  selection.getQuery(),
@@ -3591,6 +3599,25 @@ var VimController = class {
3591
3599
  handleEscape(e) {
3592
3600
  this.handleKey.handleEscape(e);
3593
3601
  }
3602
+ setModifierMovementActions(scopeId, actions) {
3603
+ if (!actions) {
3604
+ this.modifierMovementActionsByScope.delete(scopeId);
3605
+ return;
3606
+ }
3607
+ this.modifierMovementActionsByScope.set(scopeId, actions);
3608
+ }
3609
+ handleModifiedMovement(dir, modifier, e) {
3610
+ const scopeId = this.selection.getActiveScope();
3611
+ if (!scopeId) return;
3612
+ const activeKey = this.selection.getActiveRegion(scopeId);
3613
+ if (!activeKey) return;
3614
+ const actions = this.modifierMovementActionsByScope.get(scopeId);
3615
+ const action = actions?.[modifier]?.[dir];
3616
+ if (!action) return;
3617
+ const itemId = this.selection.getActiveItem(activeKey);
3618
+ const count = this.handleKey.consumeCount(scopeId, 1);
3619
+ action({ scopeId, key: activeKey, itemId, direction: dir, count, event: e });
3620
+ }
3594
3621
  resetActiveScope() {
3595
3622
  const scopeId = this.selection.getActiveScope();
3596
3623
  if (!scopeId) return;
@@ -3647,6 +3674,7 @@ function useVimBindings(keyboardScopeId, options = {}) {
3647
3674
  const vim = useVimController();
3648
3675
  const enabled = options.enabled ?? true;
3649
3676
  const allowArrowKeys = options.allowArrowKeys ?? true;
3677
+ const modifierMovementActions = options.modifierMovementActions;
3650
3678
  const ownerIdRef = useRef3(Symbol("vim-binding-owner"));
3651
3679
  const [isOwner, setIsOwner] = useState5(false);
3652
3680
  const handleOwnerChange = useCallback5((ownerId) => {
@@ -3684,6 +3712,13 @@ function useVimBindings(keyboardScopeId, options = {}) {
3684
3712
  }
3685
3713
  };
3686
3714
  }, [enabled, handleOwnerChange, keyboardScopeId]);
3715
+ useEffect7(() => {
3716
+ if (!enabled || !isOwner) {
3717
+ return;
3718
+ }
3719
+ vim.setModifierMovementActions(keyboardScopeId, modifierMovementActions ?? null);
3720
+ return () => vim.setModifierMovementActions(keyboardScopeId, null);
3721
+ }, [enabled, isOwner, keyboardScopeId, modifierMovementActions, vim]);
3687
3722
  const bindings = useMemo6(() => {
3688
3723
  if (!enabled || !isOwner) {
3689
3724
  return [];
@@ -3706,6 +3741,36 @@ function useVimBindings(keyboardScopeId, options = {}) {
3706
3741
  up: "ArrowUp",
3707
3742
  right: "ArrowRight"
3708
3743
  } : { left: null, down: null, up: null, right: null };
3744
+ const movementEntries = [
3745
+ { dir: "left", char: "h", arrow: arrowCombos.left },
3746
+ { dir: "down", char: "j", arrow: arrowCombos.down },
3747
+ { dir: "up", char: "k", arrow: arrowCombos.up },
3748
+ { dir: "right", char: "l", arrow: arrowCombos.right }
3749
+ ];
3750
+ const modifierLabels = {
3751
+ ctrl: { label: "Ctrl", prefix: "Control" },
3752
+ shift: { label: "Shift", prefix: "Shift" },
3753
+ ctrlShift: { label: "Ctrl+Shift", prefix: "Control+Shift" }
3754
+ };
3755
+ const modifierBindings = (modifier, actions) => {
3756
+ if (!actions) return [];
3757
+ const { label, prefix } = modifierLabels[modifier];
3758
+ return movementEntries.flatMap((entry) => {
3759
+ if (!actions?.[entry.dir]) return [];
3760
+ const combos = [`${prefix}+${entry.char.toUpperCase()}`];
3761
+ if (entry.arrow) {
3762
+ combos.push(`${prefix}+${entry.arrow}`);
3763
+ }
3764
+ return [
3765
+ {
3766
+ combos,
3767
+ handler: (e) => vim.handleModifiedMovement(entry.dir, modifier, e),
3768
+ description: `vim: ${label.toLowerCase()}+${entry.dir}`,
3769
+ group: "vim"
3770
+ }
3771
+ ];
3772
+ });
3773
+ };
3709
3774
  return [
3710
3775
  ...digitBindings,
3711
3776
  {
@@ -3746,9 +3811,12 @@ function useVimBindings(keyboardScopeId, options = {}) {
3746
3811
  description: "vim: toggle item",
3747
3812
  group: "vim"
3748
3813
  },
3749
- { combos: ["Escape"], handler: (e) => vim.handleEscape(e), description: "vim: escape", group: "vim" }
3814
+ { 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)
3750
3818
  ];
3751
- }, [allowArrowKeys, enabled, isOwner, vim]);
3819
+ }, [allowArrowKeys, enabled, isOwner, modifierMovementActions, vim]);
3752
3820
  useShortcut(keyboardScopeId, bindings, { ignoreTyping: true, preventDefault: true });
3753
3821
  }
3754
3822
 
@@ -3831,7 +3899,11 @@ function useVimRegion(containerRef, args) {
3831
3899
  keyboard.handleEnableScope(keyboardScopeId);
3832
3900
  return () => keyboard.handleDisableScope(keyboardScopeId);
3833
3901
  }, [bindKeys, keyboard, keyboardScopeId]);
3834
- useVimBindings(keyboardScopeId, { enabled: bindKeys, allowArrowKeys: args.allowArrowKeys });
3902
+ useVimBindings(keyboardScopeId, {
3903
+ enabled: bindKeys,
3904
+ allowArrowKeys: args.allowArrowKeys,
3905
+ modifierMovementActions: args.modifierMovementActions
3906
+ });
3835
3907
  useSyncExternalStore(
3836
3908
  (listener) => selection.subscribe(listener),
3837
3909
  () => selection.getVersion(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexdspace/react",
3
- "version": "0.1.48",
3
+ "version": "0.1.50",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",