Skip to content

Instantly share code, notes, and snippets.

View khasky's full-sized avatar
💭
Находи в себе силы делать то, на что другие просто не способны.

Khasky khasky

💭
Находи в себе силы делать то, на что другие просто не способны.
View GitHub Profile
@khasky
khasky / useScrollDirection.ts
Created April 8, 2026 06:41
useScrollDirection React Hook
// Subscribes to `scroll` (passive) and exposes whether the user is moving
// down the page, up, or still in the “top” band (y === 0 or within ~40px while settling).
import { useEffect, useState } from 'react';
export enum ScrollDirection {
Top = -1,
Initial = 0,
Bottom = 1,
}
@khasky
khasky / useHeadingAnchors.ts
Created April 8, 2026 06:40
useHeadingAnchors React Hook
// After mount, collects linked headings (`a > h2`–`h6`) into `{ id, text }` pairs
// from the parent anchors `id`; state updates only when there are at least two (for TOC-style UI).
import React from 'react';
export interface HeadingAnchor {
id: string;
text: string;
}
export const useHeadingAnchors = () => {
@khasky
khasky / useHashChange.ts
Created April 8, 2026 06:39
useHashChange React Hook
// Keeps React state in sync with `window.location.hash` (fragment without `#`)
// via `hashchange`, and seeds from the initial hash on mount.
import React from 'react';
export function useHashChange() {
const [activeItemId, setActiveItemId] = React.useState<string | null>(null);
React.useEffect(() => {
if (!activeItemId && window.location.hash) {
setActiveItemId(window.location.hash.substring(1));
@khasky
khasky / useDisableBodyScroll.ts
Created April 8, 2026 06:38
useDisableBodyScroll React Hook
// When `open` is true, sets `document.body.style.overflow` to `hidden` so
// the page behind modals/drawers does not scroll; restores `unset` when closed.
import { useEffect } from 'react';
export const useDisableBodyScroll = (open: boolean) => {
useEffect(() => {
if (open) {
document.body.style.overflow = 'hidden';
} else {
document.body.style.overflow = 'unset';
@khasky
khasky / useDirectionTransform.ts
Created April 8, 2026 06:38
useDirectionTransform React Hook
// Builds Theme UI `sx` transforms so a sticky/floating bar slides in on scroll-up or near the top
// and slides away on scroll-down; optional burger-menu attrs keep it visible while the menu is open.
import React from 'react';
import { BoxProps } from 'theme-ui';
import { useScrollDirection, ScrollDirection } from '@/hooks/useScrollDirection';
const SCROLL_Y_OFFSET_PX = 500;
interface DirectionTransformProps {
@khasky
khasky / useCursorEffect.ts
Created April 8, 2026 06:37
useCursorEffect React Hook
// On non-touch devices, adds a custom dual-layer cursor (ring + lagging dot with difference blend)
// that grows over links, buttons, and form controls.
import React from 'react';
export function useCursorEffect() {
React.useEffect(() => {
const isMobileDevice = () => {
return (
window.matchMedia('(pointer: coarse)').matches || /Mobi|Android/i.test(navigator.userAgent)
);
@khasky
khasky / useCopyright.ts
Created April 8, 2026 06:36
useCopyright React Hook
// On copy, rewrites clipboard text to append a random copyright line from the list (skips URLs, IP:port, and selections inside code/inputs).
import React from 'react';
import sample from 'lodash/sample';
const IP_ADDR_PORT_REGEX = /^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}:\d{1,5})$/;
const URL_REGEX =
/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g;
const isURL = (str: string) => URL_REGEX.test(str);
@khasky
khasky / useCallbackOnEscape.ts
Created April 8, 2026 06:35
useCallbackOnEscape React Hook
// Calls the given handler when the user presses Escape (keydown on document.body). Handy for closing modals, menus, and overlays.
import { useEffect } from 'react';
export const useCallbackOnEscape = (handleClose?: () => void) => {
useEffect(() => {
if (typeof handleClose === 'function') {
const closeOnEscapeKey = (e: KeyboardEvent) => (e.key === 'Escape' ? handleClose() : null);
document.body.addEventListener('keydown', closeOnEscapeKey);
return () => {
document.body.removeEventListener('keydown', closeOnEscapeKey);
@khasky
khasky / useActiveAnchor.ts
Created April 8, 2026 06:34
useActiveAnchor React Hook
// Tracks which heading (by id) is most visible in the viewport via IntersectionObserver.
import { useEffect, useRef, useState } from 'react';
interface UseIntersectionOptions {
root?: HTMLElement | null;
rootMargin?: string;
threshold?: number | number[];
}
export const useActiveAnchor = (ids: string[], options: UseIntersectionOptions = {}) => {
@khasky
khasky / fix.txt
Created April 8, 2026 06:21
Fix for "No supported authentication methods available"
1) Open TortoiseGit -> Settings -> Network
2) SSH Client -> change to "C:\Program Files\Git\usr\bin\ssh.exe" instead of "TortoiseGitPlink.exe"