@nemigo/helpers 0.13.3 → 1.5.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/dist/aggregator.d.ts +33 -0
- package/dist/aggregator.js +44 -0
- package/dist/array.d.ts +33 -0
- package/dist/array.js +24 -0
- package/dist/async/context.d.ts +73 -0
- package/dist/async/context.js +90 -0
- package/dist/async/future.d.ts +54 -0
- package/dist/async/future.js +71 -0
- package/dist/async/index.d.ts +56 -27
- package/dist/async/index.js +63 -58
- package/dist/async/loader.d.ts +67 -0
- package/dist/async/loader.js +101 -0
- package/dist/async/queue.d.ts +51 -0
- package/dist/async/queue.js +84 -0
- package/dist/cases.d.ts +31 -21
- package/dist/cases.js +41 -37
- package/dist/clean.d.ts +44 -26
- package/dist/clean.js +67 -42
- package/dist/color/types.d.ts +31 -0
- package/dist/color/types.js +1 -0
- package/dist/datetime/delta.d.ts +28 -0
- package/dist/datetime/delta.js +65 -0
- package/dist/datetime/format.d.ts +53 -0
- package/dist/datetime/format.js +119 -0
- package/dist/datetime/index.d.ts +6 -0
- package/dist/datetime/index.js +22 -0
- package/dist/datetime/plural.d.ts +77 -0
- package/dist/datetime/plural.js +78 -0
- package/dist/emitter.d.ts +29 -17
- package/dist/emitter.js +35 -21
- package/dist/explorer.d.ts +22 -29
- package/dist/explorer.js +18 -16
- package/dist/files.d.ts +31 -2
- package/dist/files.js +33 -8
- package/dist/fish.d.ts +29 -0
- package/dist/fish.js +70 -0
- package/dist/html/cookie.d.ts +48 -0
- package/dist/html/cookie.js +37 -0
- package/dist/html/events.d.ts +133 -0
- package/dist/html/events.js +139 -0
- package/dist/html/index.d.ts +31 -0
- package/dist/html/index.js +61 -0
- package/dist/index.d.ts +38 -40
- package/dist/index.js +43 -56
- package/dist/jiff/apply.d.ts +93 -0
- package/dist/jiff/apply.js +64 -0
- package/dist/jiff/extract.d.ts +7 -0
- package/dist/jiff/extract.js +82 -0
- package/dist/jiff/types.d.ts +57 -0
- package/dist/jiff/types.js +1 -0
- package/dist/lens.d.ts +20 -31
- package/dist/lens.js +22 -37
- package/dist/msgpack.d.ts +11 -26
- package/dist/msgpack.js +9 -21
- package/dist/mutate.d.ts +70 -0
- package/dist/mutate.js +130 -0
- package/dist/omitter.d.ts +54 -34
- package/dist/omitter.js +33 -25
- package/dist/path.d.ts +20 -1
- package/dist/path.js +21 -2
- package/dist/phymath/format.d.ts +60 -0
- package/dist/phymath/format.js +34 -0
- package/dist/phymath/index.d.ts +30 -30
- package/dist/phymath/index.js +41 -33
- package/dist/promoter.d.ts +20 -12
- package/dist/promoter.js +24 -17
- package/dist/random.d.ts +20 -21
- package/dist/random.js +22 -23
- package/dist/rubles.d.ts +24 -0
- package/dist/rubles.js +24 -0
- package/dist/script.d.ts +60 -13
- package/dist/script.js +46 -10
- package/dist/string.d.ts +46 -92
- package/dist/string.js +46 -171
- package/dist/types.d.ts +144 -25
- package/dist/url/index.d.ts +12 -0
- package/dist/url/index.js +17 -0
- package/dist/url/params.d.ts +141 -0
- package/dist/{url.js → url/params.js} +90 -18
- package/dist/url/slug.d.ts +28 -0
- package/dist/url/slug.js +102 -0
- package/dist/veil.d.ts +14 -0
- package/dist/veil.js +26 -0
- package/dist/xod.d.ts +237 -16
- package/dist/xod.js +192 -18
- package/dist/zipper.d.ts +22 -4
- package/dist/zipper.js +22 -5
- package/package.json +82 -34
- package/dist/async/space.d.ts +0 -8
- package/dist/async/space.js +0 -31
- package/dist/cleanup.d.ts +0 -9
- package/dist/cleanup.js +0 -18
- package/dist/colors.d.ts +0 -539
- package/dist/colors.js +0 -888
- package/dist/cookie.d.ts +0 -60
- package/dist/cookie.js +0 -48
- package/dist/datetime.d.ts +0 -82
- package/dist/datetime.js +0 -161
- package/dist/format.d.ts +0 -36
- package/dist/format.js +0 -26
- package/dist/future.d.ts +0 -51
- package/dist/future.js +0 -71
- package/dist/html.d.ts +0 -145
- package/dist/html.js +0 -205
- package/dist/humanly.d.ts +0 -9
- package/dist/humanly.js +0 -93
- package/dist/lru.d.ts +0 -77
- package/dist/lru.js +0 -128
- package/dist/queue.d.ts +0 -40
- package/dist/queue.js +0 -56
- package/dist/url.d.ts +0 -61
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { MS_IN_DAY } from "../datetime/delta.js";
|
|
2
|
+
/**
|
|
3
|
+
* @param name - Имя куки
|
|
4
|
+
* @param value - Значение куки
|
|
5
|
+
* @param [options] - Опции куки
|
|
6
|
+
* @param [options.MaxAge=21days] - {@link SetDocumentCookieOptions.MaxAge}
|
|
7
|
+
* @param [options.SameSite="Lax"] - {@link SetDocumentCookieOptions.SameSite}
|
|
8
|
+
* @param [options.Secure=true] - {@link SetDocumentCookieOptions.Secure}
|
|
9
|
+
* @param [options.Path="/"] - {@link SetDocumentCookieOptions.Path}
|
|
10
|
+
* @param [options.Domain] - {@link SetDocumentCookieOptions.Domain}
|
|
11
|
+
*/
|
|
12
|
+
export const setDocumentCookie = (name, value, options = {}) => {
|
|
13
|
+
const { MaxAge = (21 * MS_IN_DAY) / 1000, SameSite = "Lax", Secure = true, Path = "/", Domain } = options;
|
|
14
|
+
let acc = `${name}=${value}`;
|
|
15
|
+
if (Domain)
|
|
16
|
+
acc += `;Domain=${Domain}`;
|
|
17
|
+
acc += `;Path=${Path};SameSite=${SameSite}`;
|
|
18
|
+
if (Secure)
|
|
19
|
+
acc += ";Secure";
|
|
20
|
+
if (MaxAge)
|
|
21
|
+
acc += `;Max-Age=${MaxAge}`;
|
|
22
|
+
document.cookie = acc;
|
|
23
|
+
};
|
|
24
|
+
export const getDocumentCookie = (name) => {
|
|
25
|
+
const search = name + "=";
|
|
26
|
+
const cookies = document.cookie.split(";");
|
|
27
|
+
for (const raw of cookies) {
|
|
28
|
+
const cookie = raw.trim();
|
|
29
|
+
if (cookie.startsWith(search)) {
|
|
30
|
+
return cookie.slice(search.length);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Удаляет куку по имени, устанавливая Max-Age=0 через {@link setDocumentCookie}
|
|
36
|
+
*/
|
|
37
|
+
export const deleteDocumentCookie = (name, Path) => setDocumentCookie(name, "", { Path, MaxAge: 0 });
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { ConditionGuardType } from "../index.js";
|
|
2
|
+
import type { CanBeNullable, CanBePromise, KEYS } from "../types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Предотвращает стандартное поведение события и останавливает его всплытие
|
|
5
|
+
*/
|
|
6
|
+
export declare const preventStop: (e: Event) => void;
|
|
7
|
+
/**
|
|
8
|
+
* @param handler - Обработчик события
|
|
9
|
+
* @param [guards={}] - Условия выполнений
|
|
10
|
+
* @param [guards.preventStopGuard=true] - Вызов {@link preventStop} для события
|
|
11
|
+
* @param [guards.eventHandlerGuard=true] - Вызов обработчика
|
|
12
|
+
*/
|
|
13
|
+
export declare const usePreventStop: <T extends Event = Event>(handler?: CanBeNullable<(e: T) => CanBePromise>, guards?: {
|
|
14
|
+
preventStopGuard?: ConditionGuardType<{
|
|
15
|
+
event: T;
|
|
16
|
+
handler: typeof handler;
|
|
17
|
+
}>;
|
|
18
|
+
eventHandlerGuard?: ConditionGuardType<{
|
|
19
|
+
event: T;
|
|
20
|
+
handler: typeof handler;
|
|
21
|
+
}>;
|
|
22
|
+
}) => ((event: T) => void);
|
|
23
|
+
/**
|
|
24
|
+
* @param handler - Обработчик события
|
|
25
|
+
* @param [props={}] - Дополнительные возможности
|
|
26
|
+
* @param [props.preventStopGuard="enter"] - Политика вызова {@link preventStop} для события
|
|
27
|
+
* @param [props.eventHandlerGuard=true] - Вызов обработчика
|
|
28
|
+
* @param [props.secondary] - Обработчик для других клавиш
|
|
29
|
+
*/
|
|
30
|
+
export declare const createEnterHandler: <T extends KeyboardEvent = KeyboardEvent>(handler?: CanBeNullable<(e: T) => CanBePromise>, props?: {
|
|
31
|
+
preventStopGuard?: "enter" | ConditionGuardType<{
|
|
32
|
+
event: T;
|
|
33
|
+
isEnter: boolean;
|
|
34
|
+
}>;
|
|
35
|
+
eventHandlerGuard?: ConditionGuardType<T>;
|
|
36
|
+
secondary?: (e: T) => void;
|
|
37
|
+
}) => ((event: T) => void);
|
|
38
|
+
/**
|
|
39
|
+
* Тип события {@link Event} с уточнённым `currentTarget`
|
|
40
|
+
*/
|
|
41
|
+
export type TargetEvent<E extends Event, N extends HTMLElement = HTMLDivElement> = E & {
|
|
42
|
+
currentTarget: EventTarget & N;
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Тип клавиатурного события {@link KeyboardEvent} с уточнённым `currentTarget`
|
|
46
|
+
*/
|
|
47
|
+
export type TargetKeyboardEvent<N extends HTMLElement = HTMLDivElement> = TargetEvent<KeyboardEvent, N>;
|
|
48
|
+
/**
|
|
49
|
+
* Объединение {@link MouseEvent} и {@link TargetKeyboardEvent}
|
|
50
|
+
*/
|
|
51
|
+
export type MouseBoardEvent<N extends HTMLElement = HTMLDivElement> = MouseEvent | TargetKeyboardEvent<N>;
|
|
52
|
+
export declare const isKeyboardEvent: (e: any) => e is KeyboardEvent;
|
|
53
|
+
export type CtxMenuEvent<N extends HTMLElement = HTMLDivElement> = {
|
|
54
|
+
isKeyboardEvent: true;
|
|
55
|
+
event: TargetKeyboardEvent<N>;
|
|
56
|
+
position: {
|
|
57
|
+
left: number;
|
|
58
|
+
top: number;
|
|
59
|
+
};
|
|
60
|
+
} | {
|
|
61
|
+
isKeyboardEvent: false;
|
|
62
|
+
event: MouseEvent;
|
|
63
|
+
position: {
|
|
64
|
+
left: number;
|
|
65
|
+
top: number;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Создаёт обработчик события контекстного меню
|
|
70
|
+
*
|
|
71
|
+
* - Если событие вызвано клавиатурой, то координаты берутся из {@link getBoundingClientRect} текущего элемента
|
|
72
|
+
* - Если мышью - то из {@link MouseEvent.clientX} и {@link MouseEvent.clientY}
|
|
73
|
+
*
|
|
74
|
+
* @param handler - Обработчик события
|
|
75
|
+
* @param [guards={}] - Условия выполнений
|
|
76
|
+
* @param [guards.preventStopGuard="handler"] - Политика вызова {@link preventStop} для события
|
|
77
|
+
* @param [guards.eventHandlerGuard=true] - Вызов обработчика
|
|
78
|
+
*/
|
|
79
|
+
export declare const createCtxMenuHandler: <N extends HTMLElement = HTMLDivElement>(handler?: CanBeNullable<(event: CtxMenuEvent<N>) => CanBePromise>, guards?: {
|
|
80
|
+
preventStopGuard?: "handler" | ConditionGuardType<[CtxMenuEvent<N>, typeof handler]>;
|
|
81
|
+
eventHandlerGuard?: ConditionGuardType<CtxMenuEvent<N>>;
|
|
82
|
+
}) => ((event: MouseBoardEvent<N>) => void);
|
|
83
|
+
/**
|
|
84
|
+
* Чинит то, что при `ondblclick` первоначально вызывается `onclick`.
|
|
85
|
+
* Использовать **только** при реальной обработке `ondblclick`, так как создаётся input-лаг
|
|
86
|
+
*
|
|
87
|
+
* @param singleClickHandler - Обработчик для `onclick`
|
|
88
|
+
* @param doubleClickHandler - Обработчик для `ondblclick`
|
|
89
|
+
* @param [delay=65ms] - Задержка для определения, что это `ondblclick`
|
|
90
|
+
*/
|
|
91
|
+
export declare const createClickHandlers: (singleClickHandler: (e: MouseEvent) => CanBePromise, doubleClickHandler: (e: MouseEvent) => CanBePromise, delay?: number) => {
|
|
92
|
+
onclick: (e: MouseEvent) => void;
|
|
93
|
+
ondblclick: (e: MouseEvent) => void;
|
|
94
|
+
};
|
|
95
|
+
export interface CreateEventListenerOptions extends AddEventListenerOptions {
|
|
96
|
+
target?: HTMLElement | Window | Document;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* @template EventMap - Карта событий (например, {@link WindowEventMap})
|
|
100
|
+
*
|
|
101
|
+
* @param event - Ключ события
|
|
102
|
+
* @param listener - Обработчик события
|
|
103
|
+
* @param [options] - Опции создания
|
|
104
|
+
* @param [options.target=window] - У чего слушаем события
|
|
105
|
+
*
|
|
106
|
+
* @returns Функция для удаления обработчика
|
|
107
|
+
*/
|
|
108
|
+
export declare const createEventListener: <EventMap = WindowEventMap, const K extends KEYS<EventMap> = KEYS<EventMap>, E = EventMap[K]>(event: K, listener: (e: E) => CanBePromise, options?: CreateEventListenerOptions) => (() => void);
|
|
109
|
+
declare global {
|
|
110
|
+
interface WindowEventMap {
|
|
111
|
+
/**
|
|
112
|
+
* Кастомное событие для прокрутки
|
|
113
|
+
*/
|
|
114
|
+
scrollTo: CustomEvent;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
export interface CreateScrollToListenerContext extends CreateEventListenerOptions {
|
|
118
|
+
/**
|
|
119
|
+
* @default { top: 0, behavior: "smooth" }
|
|
120
|
+
*/
|
|
121
|
+
options?: ScrollToOptions;
|
|
122
|
+
element?: HTMLElement;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Создаёт обработчик события `scrollTo`
|
|
126
|
+
*
|
|
127
|
+
* @returns Функция для удаления обработчика
|
|
128
|
+
*/
|
|
129
|
+
export declare const createScrollToListener: (ctx: CreateScrollToListenerContext) => (() => void);
|
|
130
|
+
/**
|
|
131
|
+
* @param [element=window] - Что диспатчит событие `scrollTo`
|
|
132
|
+
*/
|
|
133
|
+
export declare const dispatchScrollTo: (element?: HTMLElement | Window | Document) => boolean;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { useConditionGuard } from "../index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Предотвращает стандартное поведение события и останавливает его всплытие
|
|
4
|
+
*/
|
|
5
|
+
export const preventStop = (e) => (e.preventDefault(), e.stopPropagation());
|
|
6
|
+
/**
|
|
7
|
+
* @param handler - Обработчик события
|
|
8
|
+
* @param [guards={}] - Условия выполнений
|
|
9
|
+
* @param [guards.preventStopGuard=true] - Вызов {@link preventStop} для события
|
|
10
|
+
* @param [guards.eventHandlerGuard=true] - Вызов обработчика
|
|
11
|
+
*/
|
|
12
|
+
export const usePreventStop = (handler, guards = {}) => (event) => {
|
|
13
|
+
const { preventStopGuard = true, eventHandlerGuard = true } = guards;
|
|
14
|
+
if (useConditionGuard(preventStopGuard, { event, handler }))
|
|
15
|
+
preventStop(event);
|
|
16
|
+
if (handler && useConditionGuard(eventHandlerGuard, { event, handler }))
|
|
17
|
+
void handler(event);
|
|
18
|
+
};
|
|
19
|
+
//...
|
|
20
|
+
/**
|
|
21
|
+
* @param handler - Обработчик события
|
|
22
|
+
* @param [props={}] - Дополнительные возможности
|
|
23
|
+
* @param [props.preventStopGuard="enter"] - Политика вызова {@link preventStop} для события
|
|
24
|
+
* @param [props.eventHandlerGuard=true] - Вызов обработчика
|
|
25
|
+
* @param [props.secondary] - Обработчик для других клавиш
|
|
26
|
+
*/
|
|
27
|
+
export const createEnterHandler = (handler, props = {}) => (event) => {
|
|
28
|
+
const { preventStopGuard = "enter", eventHandlerGuard = true, secondary } = props;
|
|
29
|
+
const isEnter = event.key === "Enter";
|
|
30
|
+
if (preventStopGuard === "enter") {
|
|
31
|
+
if (isEnter)
|
|
32
|
+
preventStop(event);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
if (useConditionGuard(preventStopGuard, { event, isEnter }))
|
|
36
|
+
preventStop(event);
|
|
37
|
+
}
|
|
38
|
+
if (isEnter) {
|
|
39
|
+
if (handler && useConditionGuard(eventHandlerGuard, event))
|
|
40
|
+
void handler(event);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
secondary?.(event);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export const isKeyboardEvent = (e) => !!e.code;
|
|
47
|
+
/**
|
|
48
|
+
* Создаёт обработчик события контекстного меню
|
|
49
|
+
*
|
|
50
|
+
* - Если событие вызвано клавиатурой, то координаты берутся из {@link getBoundingClientRect} текущего элемента
|
|
51
|
+
* - Если мышью - то из {@link MouseEvent.clientX} и {@link MouseEvent.clientY}
|
|
52
|
+
*
|
|
53
|
+
* @param handler - Обработчик события
|
|
54
|
+
* @param [guards={}] - Условия выполнений
|
|
55
|
+
* @param [guards.preventStopGuard="handler"] - Политика вызова {@link preventStop} для события
|
|
56
|
+
* @param [guards.eventHandlerGuard=true] - Вызов обработчика
|
|
57
|
+
*/
|
|
58
|
+
export const createCtxMenuHandler = (handler, guards = {}) => (event) => {
|
|
59
|
+
const { preventStopGuard = "handler", eventHandlerGuard = true } = guards;
|
|
60
|
+
if (preventStopGuard === "handler") {
|
|
61
|
+
if (handler)
|
|
62
|
+
preventStop(event);
|
|
63
|
+
else
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
let ctx;
|
|
67
|
+
if (isKeyboardEvent(event)) {
|
|
68
|
+
const { x, y } = event.currentTarget.getBoundingClientRect();
|
|
69
|
+
ctx = { isKeyboardEvent: true, event, position: { left: x, top: y } };
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
ctx = { isKeyboardEvent: false, event, position: { left: event.clientX, top: event.clientY } };
|
|
73
|
+
}
|
|
74
|
+
if (useConditionGuard(preventStopGuard, [ctx, handler]))
|
|
75
|
+
preventStop(event);
|
|
76
|
+
if (handler && useConditionGuard(eventHandlerGuard, ctx))
|
|
77
|
+
void handler(ctx);
|
|
78
|
+
};
|
|
79
|
+
//...
|
|
80
|
+
/**
|
|
81
|
+
* Чинит то, что при `ondblclick` первоначально вызывается `onclick`.
|
|
82
|
+
* Использовать **только** при реальной обработке `ondblclick`, так как создаётся input-лаг
|
|
83
|
+
*
|
|
84
|
+
* @param singleClickHandler - Обработчик для `onclick`
|
|
85
|
+
* @param doubleClickHandler - Обработчик для `ondblclick`
|
|
86
|
+
* @param [delay=65ms] - Задержка для определения, что это `ondblclick`
|
|
87
|
+
*/
|
|
88
|
+
export const createClickHandlers = (singleClickHandler, doubleClickHandler, delay = 65) => {
|
|
89
|
+
let clickTimer = 0;
|
|
90
|
+
let isDoubleClick = false;
|
|
91
|
+
const onclick = (e) => {
|
|
92
|
+
if (clickTimer)
|
|
93
|
+
return;
|
|
94
|
+
clickTimer = setTimeout(() => {
|
|
95
|
+
if (!isDoubleClick)
|
|
96
|
+
void singleClickHandler(e);
|
|
97
|
+
clickTimer = 0;
|
|
98
|
+
isDoubleClick = false;
|
|
99
|
+
}, delay);
|
|
100
|
+
};
|
|
101
|
+
const ondblclick = (e) => {
|
|
102
|
+
isDoubleClick = true;
|
|
103
|
+
if (clickTimer) {
|
|
104
|
+
clearTimeout(clickTimer);
|
|
105
|
+
clickTimer = 0;
|
|
106
|
+
}
|
|
107
|
+
void doubleClickHandler(e);
|
|
108
|
+
};
|
|
109
|
+
return { onclick, ondblclick };
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* @template EventMap - Карта событий (например, {@link WindowEventMap})
|
|
113
|
+
*
|
|
114
|
+
* @param event - Ключ события
|
|
115
|
+
* @param listener - Обработчик события
|
|
116
|
+
* @param [options] - Опции создания
|
|
117
|
+
* @param [options.target=window] - У чего слушаем события
|
|
118
|
+
*
|
|
119
|
+
* @returns Функция для удаления обработчика
|
|
120
|
+
*/
|
|
121
|
+
export const createEventListener = (event, listener, options = {}) => {
|
|
122
|
+
const target = options.target ?? window;
|
|
123
|
+
target.addEventListener(event, listener, options);
|
|
124
|
+
return () => target.removeEventListener(event, listener);
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Создаёт обработчик события `scrollTo`
|
|
128
|
+
*
|
|
129
|
+
* @returns Функция для удаления обработчика
|
|
130
|
+
*/
|
|
131
|
+
export const createScrollToListener = (ctx) => createEventListener("scrollTo",
|
|
132
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
133
|
+
() => ctx.element?.scrollTo?.(ctx.options ?? { top: 0, behavior: "smooth" }), ctx);
|
|
134
|
+
/**
|
|
135
|
+
* @param [element=window] - Что диспатчит событие `scrollTo`
|
|
136
|
+
*/
|
|
137
|
+
export const dispatchScrollTo = (element = window) =>
|
|
138
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
139
|
+
element?.dispatchEvent?.(new CustomEvent("scrollTo"));
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `true`, если глобальный объект `window` отсутствует
|
|
3
|
+
*/
|
|
4
|
+
export declare const isSSR: boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Убирает фокус на активном элементе страницы
|
|
7
|
+
*/
|
|
8
|
+
export declare const unfocus: () => void;
|
|
9
|
+
/**
|
|
10
|
+
* Снимает текущее выделение текста на странице
|
|
11
|
+
*/
|
|
12
|
+
export declare const unselect: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Добавляет одноразовый обработчик `mousedown`, который снимает выделение текста
|
|
15
|
+
*
|
|
16
|
+
* @returns Функция для удаления обработчика
|
|
17
|
+
*/
|
|
18
|
+
export declare const unselectByMousedown: () => (() => void);
|
|
19
|
+
/**
|
|
20
|
+
* Автоматически изменяет высоту `textarea` в зависимости от содержимого
|
|
21
|
+
*
|
|
22
|
+
* @remarks работает с {@link HTMLTextAreaElement.style.height} и {@link HTMLTextAreaElement.scrollTop}
|
|
23
|
+
*/
|
|
24
|
+
export declare const autoAreaHeight: (area?: HTMLTextAreaElement) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Преобразует {@link FormData} в объект
|
|
27
|
+
*
|
|
28
|
+
* @param form - Данные формы
|
|
29
|
+
* @param [multi=false] - Есть массивы значений для одинаковых ключей
|
|
30
|
+
*/
|
|
31
|
+
export declare const formon: <D = any>(form: FormData, multi?: boolean) => D;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { createEventListener } from "./events.js";
|
|
2
|
+
/**
|
|
3
|
+
* `true`, если глобальный объект `window` отсутствует
|
|
4
|
+
*/
|
|
5
|
+
export const isSSR = typeof window === "undefined";
|
|
6
|
+
//...
|
|
7
|
+
/**
|
|
8
|
+
* Убирает фокус на активном элементе страницы
|
|
9
|
+
*/
|
|
10
|
+
export const unfocus = () =>
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
12
|
+
document.activeElement?.blur?.();
|
|
13
|
+
/**
|
|
14
|
+
* Снимает текущее выделение текста на странице
|
|
15
|
+
*/
|
|
16
|
+
export const unselect = () => document.getSelection()?.removeAllRanges();
|
|
17
|
+
/**
|
|
18
|
+
* Добавляет одноразовый обработчик `mousedown`, который снимает выделение текста
|
|
19
|
+
*
|
|
20
|
+
* @returns Функция для удаления обработчика
|
|
21
|
+
*/
|
|
22
|
+
export const unselectByMousedown = () => createEventListener("mousedown", unselect, { once: true });
|
|
23
|
+
//...
|
|
24
|
+
/**
|
|
25
|
+
* Автоматически изменяет высоту `textarea` в зависимости от содержимого
|
|
26
|
+
*
|
|
27
|
+
* @remarks работает с {@link HTMLTextAreaElement.style.height} и {@link HTMLTextAreaElement.scrollTop}
|
|
28
|
+
*/
|
|
29
|
+
export const autoAreaHeight = (area) => {
|
|
30
|
+
if (!area)
|
|
31
|
+
return;
|
|
32
|
+
area.style.height = "auto";
|
|
33
|
+
area.style.height = `${area.scrollHeight}px`;
|
|
34
|
+
area.scrollTop = area.scrollHeight;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Преобразует {@link FormData} в объект
|
|
38
|
+
*
|
|
39
|
+
* @param form - Данные формы
|
|
40
|
+
* @param [multi=false] - Есть массивы значений для одинаковых ключей
|
|
41
|
+
*/
|
|
42
|
+
export const formon = (form, multi = false) => {
|
|
43
|
+
if (multi) {
|
|
44
|
+
const result = {};
|
|
45
|
+
for (const { 0: key, 1: value } of form.entries()) {
|
|
46
|
+
if (result[key] !== undefined) {
|
|
47
|
+
if (!Array.isArray(result[key])) {
|
|
48
|
+
result[key] = [result[key]];
|
|
49
|
+
}
|
|
50
|
+
result[key].push(value);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
result[key] = value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return Object.fromEntries(form.entries());
|
|
60
|
+
}
|
|
61
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,60 +1,58 @@
|
|
|
1
|
-
import type { CanBeArray, CanBePromise, CanBeReadonly } from "./types.js";
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
2
|
+
* Преобразует число в строку, добавляя ведущие нули для достижения указанной длины
|
|
4
3
|
*
|
|
5
|
-
* @example
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* pad(123, 5); // "00123"
|
|
7
|
+
* ```
|
|
6
8
|
*/
|
|
7
9
|
export declare const pad: (v: number, l?: number) => string;
|
|
8
10
|
/**
|
|
9
11
|
* JSON-клонирование объектов посредством `JSON.parse(JSON.stringify(v))`
|
|
10
|
-
*
|
|
12
|
+
*
|
|
13
|
+
* Если значение не `object` - возвращается как есть
|
|
11
14
|
*/
|
|
12
15
|
export declare const parsify: <T>(v: T) => T;
|
|
13
16
|
/**
|
|
14
|
-
*
|
|
15
|
-
*/
|
|
16
|
-
export declare const arrayble: <T>(v: CanBeArray<T>) => T[];
|
|
17
|
-
export declare const isObject: (obj: unknown) => obj is object;
|
|
18
|
-
export declare const isSameType: <A = unknown>(a: A, b: unknown) => b is A;
|
|
19
|
-
/**
|
|
20
|
-
* Тип разделения для функции {@link partition}
|
|
17
|
+
* Агрегация функций в одну
|
|
21
18
|
*/
|
|
22
|
-
export
|
|
23
|
-
/**
|
|
24
|
-
* Элементы, удовлетворяющие условию
|
|
25
|
-
*/
|
|
26
|
-
result: T[];
|
|
27
|
-
/**
|
|
28
|
-
* Исключённые элементы
|
|
29
|
-
*/
|
|
30
|
-
excluded: T[];
|
|
31
|
-
}
|
|
19
|
+
export declare const aggregate: (...args: (() => void)[]) => () => void;
|
|
32
20
|
/**
|
|
33
|
-
*
|
|
21
|
+
* Проверяет, является ли значение объектом (не `null`, и `typeof === "object"`)
|
|
34
22
|
*/
|
|
35
|
-
export declare const
|
|
23
|
+
export declare const isObject: (obj: unknown) => obj is object;
|
|
36
24
|
/**
|
|
37
|
-
*
|
|
25
|
+
* Проверяет, имеют ли два значения одинаковый тип (на основе {@link Object.prototype.toString})
|
|
38
26
|
*/
|
|
39
|
-
export declare const
|
|
27
|
+
export declare const isSameType: <A = unknown>(a: A, b: unknown) => b is A;
|
|
28
|
+
export type ConditionGuardValue = object | number | string | boolean | null;
|
|
29
|
+
export type ConditionGuardType<CTX> = ConditionGuardValue | ((ctx: CTX) => ConditionGuardValue);
|
|
40
30
|
/**
|
|
41
|
-
*
|
|
31
|
+
* Использование значения (или функции, возвращающей значение) и приведение его к булевому
|
|
42
32
|
*
|
|
43
|
-
* @
|
|
44
|
-
* @
|
|
45
|
-
* @param {T[]} arr - Исходный массив объектов
|
|
46
|
-
* @param {K} [key="id"] - Ключ, по которому будут удаляться дубликаты
|
|
47
|
-
* @returns {T[]} Новый массив без дубликатов
|
|
33
|
+
* @param condition - Условие для проверки
|
|
34
|
+
* @param ctx - Контекст, передаваемый в функцию-условие
|
|
48
35
|
*/
|
|
49
|
-
export declare const
|
|
50
|
-
export declare const useConditionGuard: (condition: unknown, ...args: any[]) => boolean;
|
|
36
|
+
export declare const useConditionGuard: <CTX>(condition: ConditionGuardType<CTX>, ctx: CTX) => boolean;
|
|
51
37
|
/**
|
|
52
|
-
*
|
|
38
|
+
* Создаёт новый объект и добавляет в него ключи и значения исходного в алфавитном порядке
|
|
39
|
+
*
|
|
40
|
+
* @remarks **НЕ** предназначен для работы с декларативными методами (могут потерять `this`)
|
|
53
41
|
*/
|
|
54
|
-
export declare const sortObjectByKeys: <T>(obj: T) => T;
|
|
55
|
-
export type BoundaryFallback<E> = E | ((err: unknown) => CanBePromise<E>);
|
|
42
|
+
export declare const sortObjectByKeys: <T extends object>(obj: T) => T;
|
|
56
43
|
/**
|
|
57
|
-
*
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
44
|
+
* Создаёт функцию для склонения слова по числу (для русского языка)
|
|
45
|
+
*
|
|
46
|
+
* @param one - Форма слова для одного элемента (например, "яблоко")
|
|
47
|
+
* @param few - Форма слова для двух-четырёх элементов (например, "яблока")
|
|
48
|
+
* @param many - Форма слова для пяти-девяти элементов или нуля (например, "яблок")
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* const pluralizeApple = createValuePluralizer("яблоко", "яблока", "яблок");
|
|
53
|
+
* pluralizeApple(1); // "яблоко"
|
|
54
|
+
* pluralizeApple(3); // "яблока"
|
|
55
|
+
* pluralizeApple(5); // "яблок"
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare const createValuePluralizer: (one: string, few: string, many: string) => (value: number) => string;
|
package/dist/index.js
CHANGED
|
@@ -1,64 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Преобразует число в строку, добавляя ведущие нули для достижения указанной длины
|
|
3
3
|
*
|
|
4
|
-
* @example
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* pad(123, 5); // "00123"
|
|
7
|
+
* ```
|
|
5
8
|
*/
|
|
6
9
|
export const pad = (v, l = 2) => String(v).padStart(l, "0");
|
|
7
10
|
/**
|
|
8
11
|
* JSON-клонирование объектов посредством `JSON.parse(JSON.stringify(v))`
|
|
9
|
-
*
|
|
12
|
+
*
|
|
13
|
+
* Если значение не `object` - возвращается как есть
|
|
10
14
|
*/
|
|
11
15
|
export const parsify = (v) => {
|
|
12
|
-
if (typeof v !== "object")
|
|
16
|
+
if (typeof v !== "object" || v === null)
|
|
13
17
|
return v;
|
|
14
18
|
return JSON.parse(JSON.stringify(v));
|
|
15
19
|
};
|
|
16
20
|
/**
|
|
17
|
-
*
|
|
21
|
+
* Агрегация функций в одну
|
|
18
22
|
*/
|
|
19
|
-
export const
|
|
23
|
+
export const aggregate = (...args) => () => {
|
|
24
|
+
for (const call of args)
|
|
25
|
+
call();
|
|
26
|
+
};
|
|
20
27
|
//...
|
|
21
|
-
export const isObject = (obj) => obj !== null && typeof obj === "object";
|
|
22
|
-
export const isSameType = (a, b) => Object.prototype.toString.call(a) === Object.prototype.toString.call(b);
|
|
23
28
|
/**
|
|
24
|
-
*
|
|
29
|
+
* Проверяет, является ли значение объектом (не `null`, и `typeof === "object"`)
|
|
25
30
|
*/
|
|
26
|
-
export const
|
|
27
|
-
// @ts-expect-error <оно себя неадекватно ведёт>
|
|
28
|
-
arr.reduce((acc, item) => (acc[filter(item) ? "result" : "excluded"].push(item), acc), initial);
|
|
29
|
-
//...
|
|
31
|
+
export const isObject = (obj) => obj !== null && typeof obj === "object";
|
|
30
32
|
/**
|
|
31
|
-
*
|
|
33
|
+
* Проверяет, имеют ли два значения одинаковый тип (на основе {@link Object.prototype.toString})
|
|
32
34
|
*/
|
|
33
|
-
export const
|
|
34
|
-
// @ts-expect-error <оно себя неадекватно ведёт>
|
|
35
|
-
[...new Set(arr.filter((item) => typeof item === "string"))];
|
|
35
|
+
export const isSameType = (a, b) => Object.prototype.toString.call(a) === Object.prototype.toString.call(b);
|
|
36
36
|
/**
|
|
37
|
-
*
|
|
37
|
+
* Использование значения (или функции, возвращающей значение) и приведение его к булевому
|
|
38
38
|
*
|
|
39
|
-
* @
|
|
40
|
-
* @
|
|
41
|
-
* @param {T[]} arr - Исходный массив объектов
|
|
42
|
-
* @param {K} [key="id"] - Ключ, по которому будут удаляться дубликаты
|
|
43
|
-
* @returns {T[]} Новый массив без дубликатов
|
|
39
|
+
* @param condition - Условие для проверки
|
|
40
|
+
* @param ctx - Контекст, передаваемый в функцию-условие
|
|
44
41
|
*/
|
|
45
|
-
export const
|
|
46
|
-
// @ts-expect-error <оно себя неадекватно ведёт>
|
|
47
|
-
[...new Map(arr.map((item) => [item[key], item])).values()];
|
|
48
|
-
//...
|
|
49
|
-
export const useConditionGuard = (condition, ...args) => {
|
|
50
|
-
switch (typeof condition) {
|
|
51
|
-
case "undefined":
|
|
52
|
-
return true;
|
|
53
|
-
case "function":
|
|
54
|
-
return !!condition(...args);
|
|
55
|
-
default:
|
|
56
|
-
return !!condition;
|
|
57
|
-
}
|
|
58
|
-
};
|
|
42
|
+
export const useConditionGuard = (condition, ctx) => typeof condition === "function" ? !!condition(ctx) : !!condition;
|
|
59
43
|
//...
|
|
60
44
|
/**
|
|
61
|
-
*
|
|
45
|
+
* Создаёт новый объект и добавляет в него ключи и значения исходного в алфавитном порядке
|
|
46
|
+
*
|
|
47
|
+
* @remarks **НЕ** предназначен для работы с декларативными методами (могут потерять `this`)
|
|
62
48
|
*/
|
|
63
49
|
export const sortObjectByKeys = (obj) => {
|
|
64
50
|
const keys = Object.keys(obj).sort();
|
|
@@ -68,23 +54,24 @@ export const sortObjectByKeys = (obj) => {
|
|
|
68
54
|
return result;
|
|
69
55
|
};
|
|
70
56
|
/**
|
|
71
|
-
*
|
|
57
|
+
* Создаёт функцию для склонения слова по числу (для русского языка)
|
|
58
|
+
*
|
|
59
|
+
* @param one - Форма слова для одного элемента (например, "яблоко")
|
|
60
|
+
* @param few - Форма слова для двух-четырёх элементов (например, "яблока")
|
|
61
|
+
* @param many - Форма слова для пяти-девяти элементов или нуля (например, "яблок")
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```typescript
|
|
65
|
+
* const pluralizeApple = createValuePluralizer("яблоко", "яблока", "яблок");
|
|
66
|
+
* pluralizeApple(1); // "яблоко"
|
|
67
|
+
* pluralizeApple(3); // "яблока"
|
|
68
|
+
* pluralizeApple(5); // "яблок"
|
|
69
|
+
* ```
|
|
72
70
|
*/
|
|
73
|
-
export const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
if (typeof fallback === "function") {
|
|
80
|
-
// @ts-expect-error <тут не типизировать>
|
|
81
|
-
return fallback(e);
|
|
82
|
-
}
|
|
83
|
-
return fallback;
|
|
84
|
-
}
|
|
85
|
-
};
|
|
86
|
-
//...
|
|
87
|
-
export const cleanup = (...args) => () => {
|
|
88
|
-
for (const call of args)
|
|
89
|
-
call();
|
|
71
|
+
export const createValuePluralizer = (one, few, many) => (value) => {
|
|
72
|
+
const n = Math.abs(value) % 100;
|
|
73
|
+
if (n >= 11 && n <= 19)
|
|
74
|
+
return many;
|
|
75
|
+
const d = n % 10;
|
|
76
|
+
return d === 1 ? one : d >= 2 && d <= 4 ? few : many;
|
|
90
77
|
};
|