@hexdspace/react 0.1.47 → 0.1.49

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
@@ -901,19 +901,37 @@ declare class VimHandleKeyUseCase {
901
901
  private afterCursorChange;
902
902
  private applyFallbackCursor;
903
903
  private getCursorIndex;
904
+ private hasSelection;
904
905
  private findNextNonEmptyRegion;
905
906
  private resolveInterRegionFallback;
906
907
  }
907
908
 
909
+ type VimMovementModifier = 'ctrl' | 'shift' | 'ctrlShift';
910
+ type VimModifierMovementActionArgs = {
911
+ scopeId: ScopeId;
912
+ key: RegionKey;
913
+ itemId: ItemId | null;
914
+ direction: VimDirection;
915
+ event: KeyboardEvent;
916
+ };
917
+ type VimModifierMovementAction = (args: VimModifierMovementActionArgs) => void;
918
+ type VimModifierMovementActions = {
919
+ ctrl?: Partial<Record<VimDirection, VimModifierMovementAction>>;
920
+ shift?: Partial<Record<VimDirection, VimModifierMovementAction>>;
921
+ ctrlShift?: Partial<Record<VimDirection, VimModifierMovementAction>>;
922
+ };
908
923
  declare class VimController {
909
924
  private readonly regions;
910
925
  private readonly handleKey;
911
926
  private readonly selection;
927
+ private readonly modifierMovementActionsByScope;
912
928
  constructor(selection: SelectionController, regions?: VimRegionRegistry, handleKey?: VimHandleKeyUseCase);
913
929
  handleRegisterRegionMeta(meta: VimRegionMeta): void;
914
930
  handleUnregisterRegionMeta(key: RegionKey): void;
915
931
  handleCharKey(char: string, e: KeyboardEvent): void;
916
932
  handleEscape(e: KeyboardEvent): void;
933
+ setModifierMovementActions(scopeId: ScopeId, actions: VimModifierMovementActions | null): void;
934
+ handleModifiedMovement(dir: VimDirection, modifier: VimMovementModifier, e: KeyboardEvent): void;
917
935
  resetActiveScope(): void;
918
936
  getSelection(): SelectionController;
919
937
  }
@@ -934,6 +952,7 @@ declare function useVimController(): VimController;
934
952
  type VimBindingOptions = {
935
953
  enabled?: boolean;
936
954
  allowArrowKeys?: boolean;
955
+ modifierMovementActions?: VimModifierMovementActions;
937
956
  };
938
957
  declare function useVimBindings(keyboardScopeId: string, options?: VimBindingOptions): void;
939
958
 
@@ -951,6 +970,7 @@ type UseVimRegionArgs = {
951
970
  keyboardScopeId?: string;
952
971
  bindKeys?: boolean;
953
972
  allowArrowKeys?: boolean;
973
+ modifierMovementActions?: VimModifierMovementActions;
954
974
  refreshDeps?: React__default.DependencyList;
955
975
  };
956
976
  type UseVimRegionResult = {
@@ -1138,4 +1158,4 @@ declare const Kbd: React.ForwardRefExoticComponent<KbdProps & React.RefAttribute
1138
1158
 
1139
1159
  declare function useMotionDuration(varName: string, fallbackSeconds: number): number;
1140
1160
 
1141
- 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 };
1161
+ 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
@@ -3370,7 +3370,13 @@ var VimHandleKeyUseCase = class {
3370
3370
  if (e.ctrlKey || e.metaKey || e.altKey) return;
3371
3371
  const scopeId = this.query.getActiveScope();
3372
3372
  if (!scopeId) return;
3373
+ const activeKey = this.query.getActiveRegion(scopeId);
3374
+ if (!activeKey) return;
3375
+ const hasSelection = this.hasSelection(activeKey);
3373
3376
  this.selection.clearSelection({ kind: "activeScope" });
3377
+ if (!hasSelection) {
3378
+ this.selection.setCursor(activeKey, null);
3379
+ }
3374
3380
  const st = this.stateByScope.get(scopeId);
3375
3381
  if (st) {
3376
3382
  st.count = "";
@@ -3451,6 +3457,9 @@ var VimHandleKeyUseCase = class {
3451
3457
  const index = items.indexOf(cursor);
3452
3458
  return index >= 0 ? index : null;
3453
3459
  }
3460
+ hasSelection(key) {
3461
+ return this.query.getSelectedIds(key).length > 0 || this.query.getToggledIds(key).length > 0 || this.query.getRangeIds(key).length > 0;
3462
+ }
3454
3463
  findNextNonEmptyRegion(scopeId, activeKey, dir, count) {
3455
3464
  const regs = this.regions.list(scopeId);
3456
3465
  if (regs.length === 0) return null;
@@ -3560,6 +3569,7 @@ var VimController = class {
3560
3569
  regions;
3561
3570
  handleKey;
3562
3571
  selection;
3572
+ modifierMovementActionsByScope = /* @__PURE__ */ new Map();
3563
3573
  constructor(selection, regions = new VimRegionRegistry(), handleKey = new VimHandleKeyUseCase(
3564
3574
  selection.getHandle(),
3565
3575
  selection.getQuery(),
@@ -3582,6 +3592,24 @@ var VimController = class {
3582
3592
  handleEscape(e) {
3583
3593
  this.handleKey.handleEscape(e);
3584
3594
  }
3595
+ setModifierMovementActions(scopeId, actions) {
3596
+ if (!actions) {
3597
+ this.modifierMovementActionsByScope.delete(scopeId);
3598
+ return;
3599
+ }
3600
+ this.modifierMovementActionsByScope.set(scopeId, actions);
3601
+ }
3602
+ handleModifiedMovement(dir, modifier, e) {
3603
+ const scopeId = this.selection.getActiveScope();
3604
+ if (!scopeId) return;
3605
+ const activeKey = this.selection.getActiveRegion(scopeId);
3606
+ if (!activeKey) return;
3607
+ const actions = this.modifierMovementActionsByScope.get(scopeId);
3608
+ const action = actions?.[modifier]?.[dir];
3609
+ if (!action) return;
3610
+ const itemId = this.selection.getActiveItem(activeKey);
3611
+ action({ scopeId, key: activeKey, itemId, direction: dir, event: e });
3612
+ }
3585
3613
  resetActiveScope() {
3586
3614
  const scopeId = this.selection.getActiveScope();
3587
3615
  if (!scopeId) return;
@@ -3638,6 +3666,7 @@ function useVimBindings(keyboardScopeId, options = {}) {
3638
3666
  const vim = useVimController();
3639
3667
  const enabled = options.enabled ?? true;
3640
3668
  const allowArrowKeys = options.allowArrowKeys ?? true;
3669
+ const modifierMovementActions = options.modifierMovementActions;
3641
3670
  const ownerIdRef = useRef3(Symbol("vim-binding-owner"));
3642
3671
  const [isOwner, setIsOwner] = useState5(false);
3643
3672
  const handleOwnerChange = useCallback5((ownerId) => {
@@ -3675,6 +3704,13 @@ function useVimBindings(keyboardScopeId, options = {}) {
3675
3704
  }
3676
3705
  };
3677
3706
  }, [enabled, handleOwnerChange, keyboardScopeId]);
3707
+ useEffect7(() => {
3708
+ if (!enabled || !isOwner) {
3709
+ return;
3710
+ }
3711
+ vim.setModifierMovementActions(keyboardScopeId, modifierMovementActions ?? null);
3712
+ return () => vim.setModifierMovementActions(keyboardScopeId, null);
3713
+ }, [enabled, isOwner, keyboardScopeId, modifierMovementActions, vim]);
3678
3714
  const bindings = useMemo6(() => {
3679
3715
  if (!enabled || !isOwner) {
3680
3716
  return [];
@@ -3697,6 +3733,36 @@ function useVimBindings(keyboardScopeId, options = {}) {
3697
3733
  up: "ArrowUp",
3698
3734
  right: "ArrowRight"
3699
3735
  } : { left: null, down: null, up: null, right: null };
3736
+ const movementEntries = [
3737
+ { dir: "left", char: "h", arrow: arrowCombos.left },
3738
+ { dir: "down", char: "j", arrow: arrowCombos.down },
3739
+ { dir: "up", char: "k", arrow: arrowCombos.up },
3740
+ { dir: "right", char: "l", arrow: arrowCombos.right }
3741
+ ];
3742
+ const modifierLabels = {
3743
+ ctrl: { label: "Ctrl", prefix: "Control" },
3744
+ shift: { label: "Shift", prefix: "Shift" },
3745
+ ctrlShift: { label: "Ctrl+Shift", prefix: "Control+Shift" }
3746
+ };
3747
+ const modifierBindings = (modifier, actions) => {
3748
+ if (!actions) return [];
3749
+ const { label, prefix } = modifierLabels[modifier];
3750
+ return movementEntries.flatMap((entry) => {
3751
+ if (!actions?.[entry.dir]) return [];
3752
+ const combos = [`${prefix}+${entry.char.toUpperCase()}`];
3753
+ if (entry.arrow) {
3754
+ combos.push(`${prefix}+${entry.arrow}`);
3755
+ }
3756
+ return [
3757
+ {
3758
+ combos,
3759
+ handler: (e) => vim.handleModifiedMovement(entry.dir, modifier, e),
3760
+ description: `vim: ${label.toLowerCase()}+${entry.dir}`,
3761
+ group: "vim"
3762
+ }
3763
+ ];
3764
+ });
3765
+ };
3700
3766
  return [
3701
3767
  ...digitBindings,
3702
3768
  {
@@ -3737,9 +3803,12 @@ function useVimBindings(keyboardScopeId, options = {}) {
3737
3803
  description: "vim: toggle item",
3738
3804
  group: "vim"
3739
3805
  },
3740
- { combos: ["Escape"], handler: (e) => vim.handleEscape(e), description: "vim: escape", group: "vim" }
3806
+ { combos: ["Escape"], handler: (e) => vim.handleEscape(e), description: "vim: escape", group: "vim" },
3807
+ ...modifierBindings("ctrl", modifierMovementActions?.ctrl),
3808
+ ...modifierBindings("shift", modifierMovementActions?.shift),
3809
+ ...modifierBindings("ctrlShift", modifierMovementActions?.ctrlShift)
3741
3810
  ];
3742
- }, [allowArrowKeys, enabled, isOwner, vim]);
3811
+ }, [allowArrowKeys, enabled, isOwner, modifierMovementActions, vim]);
3743
3812
  useShortcut(keyboardScopeId, bindings, { ignoreTyping: true, preventDefault: true });
3744
3813
  }
3745
3814
 
@@ -3822,7 +3891,11 @@ function useVimRegion(containerRef, args) {
3822
3891
  keyboard.handleEnableScope(keyboardScopeId);
3823
3892
  return () => keyboard.handleDisableScope(keyboardScopeId);
3824
3893
  }, [bindKeys, keyboard, keyboardScopeId]);
3825
- useVimBindings(keyboardScopeId, { enabled: bindKeys, allowArrowKeys: args.allowArrowKeys });
3894
+ useVimBindings(keyboardScopeId, {
3895
+ enabled: bindKeys,
3896
+ allowArrowKeys: args.allowArrowKeys,
3897
+ modifierMovementActions: args.modifierMovementActions
3898
+ });
3826
3899
  useSyncExternalStore(
3827
3900
  (listener) => selection.subscribe(listener),
3828
3901
  () => selection.getVersion(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hexdspace/react",
3
- "version": "0.1.47",
3
+ "version": "0.1.49",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",