@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.
Files changed (111) hide show
  1. package/dist/aggregator.d.ts +33 -0
  2. package/dist/aggregator.js +44 -0
  3. package/dist/array.d.ts +33 -0
  4. package/dist/array.js +24 -0
  5. package/dist/async/context.d.ts +73 -0
  6. package/dist/async/context.js +90 -0
  7. package/dist/async/future.d.ts +54 -0
  8. package/dist/async/future.js +71 -0
  9. package/dist/async/index.d.ts +56 -27
  10. package/dist/async/index.js +63 -58
  11. package/dist/async/loader.d.ts +67 -0
  12. package/dist/async/loader.js +101 -0
  13. package/dist/async/queue.d.ts +51 -0
  14. package/dist/async/queue.js +84 -0
  15. package/dist/cases.d.ts +31 -21
  16. package/dist/cases.js +41 -37
  17. package/dist/clean.d.ts +44 -26
  18. package/dist/clean.js +67 -42
  19. package/dist/color/types.d.ts +31 -0
  20. package/dist/color/types.js +1 -0
  21. package/dist/datetime/delta.d.ts +28 -0
  22. package/dist/datetime/delta.js +65 -0
  23. package/dist/datetime/format.d.ts +53 -0
  24. package/dist/datetime/format.js +119 -0
  25. package/dist/datetime/index.d.ts +6 -0
  26. package/dist/datetime/index.js +22 -0
  27. package/dist/datetime/plural.d.ts +77 -0
  28. package/dist/datetime/plural.js +78 -0
  29. package/dist/emitter.d.ts +29 -17
  30. package/dist/emitter.js +35 -21
  31. package/dist/explorer.d.ts +22 -29
  32. package/dist/explorer.js +18 -16
  33. package/dist/files.d.ts +31 -2
  34. package/dist/files.js +33 -8
  35. package/dist/fish.d.ts +29 -0
  36. package/dist/fish.js +70 -0
  37. package/dist/html/cookie.d.ts +48 -0
  38. package/dist/html/cookie.js +37 -0
  39. package/dist/html/events.d.ts +133 -0
  40. package/dist/html/events.js +139 -0
  41. package/dist/html/index.d.ts +31 -0
  42. package/dist/html/index.js +61 -0
  43. package/dist/index.d.ts +38 -40
  44. package/dist/index.js +43 -56
  45. package/dist/jiff/apply.d.ts +93 -0
  46. package/dist/jiff/apply.js +64 -0
  47. package/dist/jiff/extract.d.ts +7 -0
  48. package/dist/jiff/extract.js +82 -0
  49. package/dist/jiff/types.d.ts +57 -0
  50. package/dist/jiff/types.js +1 -0
  51. package/dist/lens.d.ts +20 -31
  52. package/dist/lens.js +22 -37
  53. package/dist/msgpack.d.ts +11 -26
  54. package/dist/msgpack.js +9 -21
  55. package/dist/mutate.d.ts +70 -0
  56. package/dist/mutate.js +130 -0
  57. package/dist/omitter.d.ts +54 -34
  58. package/dist/omitter.js +33 -25
  59. package/dist/path.d.ts +20 -1
  60. package/dist/path.js +21 -2
  61. package/dist/phymath/format.d.ts +60 -0
  62. package/dist/phymath/format.js +34 -0
  63. package/dist/phymath/index.d.ts +30 -30
  64. package/dist/phymath/index.js +41 -33
  65. package/dist/promoter.d.ts +20 -12
  66. package/dist/promoter.js +24 -17
  67. package/dist/random.d.ts +20 -21
  68. package/dist/random.js +22 -23
  69. package/dist/rubles.d.ts +24 -0
  70. package/dist/rubles.js +24 -0
  71. package/dist/script.d.ts +60 -13
  72. package/dist/script.js +46 -10
  73. package/dist/string.d.ts +46 -92
  74. package/dist/string.js +46 -171
  75. package/dist/types.d.ts +144 -25
  76. package/dist/url/index.d.ts +12 -0
  77. package/dist/url/index.js +17 -0
  78. package/dist/url/params.d.ts +141 -0
  79. package/dist/{url.js → url/params.js} +90 -18
  80. package/dist/url/slug.d.ts +28 -0
  81. package/dist/url/slug.js +102 -0
  82. package/dist/veil.d.ts +14 -0
  83. package/dist/veil.js +26 -0
  84. package/dist/xod.d.ts +237 -16
  85. package/dist/xod.js +192 -18
  86. package/dist/zipper.d.ts +22 -4
  87. package/dist/zipper.js +22 -5
  88. package/package.json +82 -34
  89. package/dist/async/space.d.ts +0 -8
  90. package/dist/async/space.js +0 -31
  91. package/dist/cleanup.d.ts +0 -9
  92. package/dist/cleanup.js +0 -18
  93. package/dist/colors.d.ts +0 -539
  94. package/dist/colors.js +0 -888
  95. package/dist/cookie.d.ts +0 -60
  96. package/dist/cookie.js +0 -48
  97. package/dist/datetime.d.ts +0 -82
  98. package/dist/datetime.js +0 -161
  99. package/dist/format.d.ts +0 -36
  100. package/dist/format.js +0 -26
  101. package/dist/future.d.ts +0 -51
  102. package/dist/future.js +0 -71
  103. package/dist/html.d.ts +0 -145
  104. package/dist/html.js +0 -205
  105. package/dist/humanly.d.ts +0 -9
  106. package/dist/humanly.js +0 -93
  107. package/dist/lru.d.ts +0 -77
  108. package/dist/lru.js +0 -128
  109. package/dist/queue.d.ts +0 -40
  110. package/dist/queue.js +0 -56
  111. 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 pad(123, 5) => "00123"
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
- * Если значение не `object` вернётся как есть
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 interface Partition<T> {
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 partition: <T>(arr: CanBeReadonly<T>, filter: (item: T) => boolean, initial?: Partition<T>) => Partition<T>;
23
+ export declare const isObject: (obj: unknown) => obj is object;
36
24
  /**
37
- * Удаляет `null` и `undefined` и оставляет только уникальные строки
25
+ * Проверяет, имеют ли два значения одинаковый тип (на основе {@link Object.prototype.toString})
38
26
  */
39
- export declare const setify: (arr: CanBeReadonly<string | undefined | null>) => string[];
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
- * @template T - Тип элементов массива
44
- * @template K - Ключ объекта, по которому определяется уникальность
45
- * @param {T[]} arr - Исходный массив объектов
46
- * @param {K} [key="id"] - Ключ, по которому будут удаляться дубликаты
47
- * @returns {T[]} Новый массив без дубликатов
33
+ * @param condition - Условие для проверки
34
+ * @param ctx - Контекст, передаваемый в функцию-условие
48
35
  */
49
- export declare const unify: <T, K extends keyof T>(arr: CanBeReadonly<T>, key?: K) => T[];
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
- * Приведение коллбэка к промису с отловом ошибок и fallback-ом
58
- */
59
- export declare const boundary: <R = undefined, E = R>(call: () => CanBePromise<R>, fallback?: BoundaryFallback<E>) => Promise<R | E>;
60
- export declare const cleanup: (...args: (() => void)[]) => () => void;
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 pad(123, 5) => "00123"
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
- * Если значение не `object` вернётся как есть
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 arrayble = (v) => (Array.isArray(v) ? v : [v]);
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 partition = (arr, filter, initial = { result: [], excluded: [] }) =>
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
- * Удаляет `null` и `undefined` и оставляет только уникальные строки
33
+ * Проверяет, имеют ли два значения одинаковый тип (на основе {@link Object.prototype.toString})
32
34
  */
33
- export const setify = (arr) =>
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
- * @template T - Тип элементов массива
40
- * @template K - Ключ объекта, по которому определяется уникальность
41
- * @param {T[]} arr - Исходный массив объектов
42
- * @param {K} [key="id"] - Ключ, по которому будут удаляться дубликаты
43
- * @returns {T[]} Новый массив без дубликатов
39
+ * @param condition - Условие для проверки
40
+ * @param ctx - Контекст, передаваемый в функцию-условие
44
41
  */
45
- export const unify = (arr, key = "id") =>
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
- * Приведение коллбэка к промису с отловом ошибок и fallback-ом
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 boundary = async (call, fallback) => {
74
- try {
75
- return await call();
76
- }
77
- catch (e) {
78
- console.error("boundary", e);
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
  };