@nemigo/helpers 0.0.13 → 0.0.19

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.
@@ -0,0 +1,44 @@
1
+ import type { Timestamp } from "./types.js";
2
+ /**
3
+ * Русифицированные названия месяцев в родительском падеже
4
+ */
5
+ export declare const months: string[];
6
+ /**
7
+ * Русифицированные сокращённые названия месяцев в родительском падеже
8
+ */
9
+ export declare const abbs: string[];
10
+ /**
11
+ * Шаблонизатор вывода даты и времени из {@link Timestamp}
12
+ *
13
+ * TS - секунды
14
+ *
15
+ * TM - минуты
16
+ *
17
+ * DD - дни
18
+ *
19
+ * DM - месяц числом
20
+ *
21
+ * DFM - месяц полным названием
22
+ *
23
+ * DAM - месяц сокращённым названием
24
+ *
25
+ * DY - год
26
+ *
27
+ * @example
28
+ * const formatted = dateTimeFormatter(new Date(), 'DD.DM.DY TH:TM:TS');
29
+ * console.log(formatted); // "09.10.2023 14:30:59"
30
+ */
31
+ export declare const formatDateTime: (datetime?: Date | Timestamp | string, format?: string) => string;
32
+ /**
33
+ * Конвертирует строковые представления даты и времени в {@link Timestamp}
34
+ *
35
+ * @param date - Строка даты в формате "DD.MM.YYYY"
36
+ * @param [time="00:00"] - Строка времени в формате "HH:MM"
37
+ *
38
+ * @returns TimeStamp соответствующий указанной дате и времени или 0 при неверном формате
39
+ *
40
+ * @example
41
+ * const timestamp = toTimeStamp("11.02.2012", "13:45");
42
+ * console.log(timestamp); // Выведет {@link Timestamp} для "11.02.2012 13:45"
43
+ */
44
+ export declare const toTimeStamp: (date: string, time?: string) => Timestamp | 0;
@@ -0,0 +1,109 @@
1
+ import { pad } from "./index.js";
2
+ /**
3
+ * Русифицированные названия месяцев в родительском падеже
4
+ */
5
+ export const months = [
6
+ "января",
7
+ "февраля",
8
+ "марта",
9
+ "апреля",
10
+ "мая",
11
+ "июня",
12
+ "июля",
13
+ "августа",
14
+ "сентября",
15
+ "октября",
16
+ "ноября",
17
+ "декабря",
18
+ ];
19
+ /**
20
+ * Русифицированные сокращённые названия месяцев в родительском падеже
21
+ */
22
+ export const abbs = [
23
+ "янв",
24
+ "фев",
25
+ "марта",
26
+ "апр",
27
+ "мая",
28
+ "июня",
29
+ "июля",
30
+ "авг",
31
+ "сен",
32
+ "окт",
33
+ "ноя",
34
+ "дек",
35
+ ];
36
+ /**
37
+ * Шаблонизатор вывода даты и времени из {@link Timestamp}
38
+ *
39
+ * TS - секунды
40
+ *
41
+ * TM - минуты
42
+ *
43
+ * DD - дни
44
+ *
45
+ * DM - месяц числом
46
+ *
47
+ * DFM - месяц полным названием
48
+ *
49
+ * DAM - месяц сокращённым названием
50
+ *
51
+ * DY - год
52
+ *
53
+ * @example
54
+ * const formatted = dateTimeFormatter(new Date(), 'DD.DM.DY TH:TM:TS');
55
+ * console.log(formatted); // "09.10.2023 14:30:59"
56
+ */
57
+ export const formatDateTime = (datetime = Date.now(), format = "DD.DM.DY TH:TM") => {
58
+ const date = new Date(datetime);
59
+ const replacements = {
60
+ TS: pad(date.getSeconds()),
61
+ TM: pad(date.getMinutes()),
62
+ TH: pad(date.getHours()),
63
+ //...
64
+ DD: pad(date.getDate()),
65
+ DM: pad(date.getMonth() + 1),
66
+ DFM: months[date.getMonth()],
67
+ DAM: abbs[date.getMonth()],
68
+ DY: date.getFullYear().toString(),
69
+ };
70
+ const result = [];
71
+ let i = 0;
72
+ while (i < format.length) {
73
+ let found = false;
74
+ for (const key in replacements) {
75
+ if (format.startsWith(key, i)) {
76
+ result.push(replacements[key]);
77
+ i += key.length;
78
+ found = true;
79
+ break;
80
+ }
81
+ }
82
+ if (!found) {
83
+ result.push(format[i]);
84
+ i++;
85
+ }
86
+ }
87
+ return result.join("");
88
+ };
89
+ /**
90
+ * Конвертирует строковые представления даты и времени в {@link Timestamp}
91
+ *
92
+ * @param date - Строка даты в формате "DD.MM.YYYY"
93
+ * @param [time="00:00"] - Строка времени в формате "HH:MM"
94
+ *
95
+ * @returns TimeStamp соответствующий указанной дате и времени или 0 при неверном формате
96
+ *
97
+ * @example
98
+ * const timestamp = toTimeStamp("11.02.2012", "13:45");
99
+ * console.log(timestamp); // Выведет {@link Timestamp} для "11.02.2012 13:45"
100
+ */
101
+ export const toTimeStamp = (date, time = "00:00") => {
102
+ const [day, month, year] = date.split(".").map(Number);
103
+ const [hours, minutes] = time.split(":").map(Number);
104
+ // Проверка на корректность ввода (если хотя бы одно значение не число)
105
+ // prettier-ignore
106
+ if ([day, month, year, hours, minutes].some(isNaN))
107
+ return 0;
108
+ return new Date(year, month - 1, day, hours, minutes).valueOf();
109
+ };
@@ -0,0 +1,31 @@
1
+ import type { CanBeNullable } from "./types.js";
2
+ interface FormatNumberConfig {
3
+ /**
4
+ * @default 2
5
+ */
6
+ fraction?: number;
7
+ /**
8
+ * @default "---"
9
+ */
10
+ fallback?: string;
11
+ /**
12
+ * @example "₽"
13
+ */
14
+ postfix?: string;
15
+ /**
16
+ * - "always" - "0" для всех исключительных ситуаций
17
+ * - "value" - "0" только при значении равном нулю, иначе `fallback`
18
+ * - "never" - `fallback` всегда
19
+ *
20
+ * @default value
21
+ */
22
+ zero?: "always" | "value" | "never";
23
+ }
24
+ export declare const FormatNumberRegExp: RegExp;
25
+ /**
26
+ * Форматирование числа по тысячам
27
+ *
28
+ * @example "1 234" или "1 234,56"
29
+ */
30
+ export declare const formatNumber: (amount: CanBeNullable<number | string>, { fraction, fallback, zero, postfix }?: FormatNumberConfig) => string;
31
+ export {};
package/dist/format.js ADDED
@@ -0,0 +1,20 @@
1
+ import { caseNumber } from "./cases.js";
2
+ import { toRound } from "./phymath.js";
3
+ export const FormatNumberRegExp = /\B(?=(\d{3})+(?!\d))/g;
4
+ /**
5
+ * Форматирование числа по тысячам
6
+ *
7
+ * @example "1 234" или "1 234,56"
8
+ */
9
+ export const formatNumber = (amount, { fraction = 2, fallback = "---", zero = "value", postfix } = {}) => caseNumber(amount, (v) => {
10
+ if (v === undefined)
11
+ return zero === "always" ? (postfix ? "0 " + postfix : "0") : fallback;
12
+ if (v === 0)
13
+ return zero === "never" ? fallback : postfix ? "0 " + postfix : "0";
14
+ if (fraction === 0)
15
+ return Math.round(v).toString().replace(FormatNumberRegExp, " ");
16
+ const { 0: integer, 1: fractional = "" } = toRound(v, fraction).toString().split(".");
17
+ const result = integer.replace(FormatNumberRegExp, " ");
18
+ const formatted = fractional ? `${result},${fractional}` : result;
19
+ return postfix ? formatted + " " + postfix : formatted;
20
+ });
package/dist/html.d.ts ADDED
@@ -0,0 +1,58 @@
1
+ import type { CanBeNullable, CanBePromise, KEYS } from "./types";
2
+ /**
3
+ * Проверка по глобальному `window`
4
+ */
5
+ export declare const isSSR: boolean;
6
+ /**
7
+ * Предотвращает дефолтное поведение события и останавливает всплытие
8
+ */
9
+ export declare const preventStop: (e: Event) => void;
10
+ /**
11
+ * Создаёт обработчик события с {@link preventStop}, который выполняется всегда.
12
+ * Коллбэк выполняется только, если load вернёт `false` (при его наличии)
13
+ */
14
+ export declare const preventStopHook: <T extends Event = Event>(call?: CanBeNullable<(e: T) => CanBePromise>, load?: () => boolean | undefined) => ((e: T) => void);
15
+ /**
16
+ * Возвращает обработчик клавиатурных событий, который:
17
+ *
18
+ * 1. Если `usePreventStop === true`, вызывает {@link preventStop}
19
+ * 2. Если load вернёт `false` (при его наличии), то выполнение остановится
20
+ * 3. Вызывает переданный **prepare-коллбэк** (при его наличии), если он вернёт `false`, то выполнение остановится
21
+ * 4. Вызывает основной коллбэк только при нажатии `Enter`.
22
+ */
23
+ export declare const enterKeyHook: <T extends KeyboardEvent = KeyboardEvent>(call?: CanBeNullable<(e: T) => CanBePromise>, config?: {
24
+ usePreventStop?: "enter" | boolean | ((e: T, isEnter: boolean) => boolean);
25
+ prepare?: (e: T) => CanBePromise<boolean>;
26
+ load?: () => boolean | undefined;
27
+ }) => (e: T) => void;
28
+ /**
29
+ * Создаёт обработчик событий для указанного элемента или окна
30
+ *
31
+ * @template T - Тип события из `WindowEventMap`
32
+ * @template E - Тип объекта события (по умолчанию `WindowEventMap[T]`)
33
+ *
34
+ * @param {T} event - Ключ события
35
+ * @param {(e: E) => CanBePromise} call - Функция-обработчик события
36
+ * @param {AddEventListenerOptions} [options] - Дополнительные параметры
37
+ * @param {HTMLElement | Window} [target=window] - Целевой элемент для привязки события
38
+ *
39
+ * @returns Функция для удаления обработчика события
40
+ */
41
+ export declare const createEventListener: <const M = WindowEventMap, const T extends KEYS<M> = KEYS<M>, const E = M[T]>(event: T, call: (e: E) => CanBePromise, options?: AddEventListenerOptions, target?: HTMLElement | Window | Document) => (() => void);
42
+ /**
43
+ * Убирает все выделения текста на странице
44
+ */
45
+ export declare const unselect: () => void;
46
+ /**
47
+ * Создаёт once-обработчик события "mousedown" с {@link unselect}
48
+ *
49
+ * @returns Функция для удаления обработчика события
50
+ */
51
+ export declare const unselectByMousedown: () => (() => void);
52
+ /**
53
+ * Преобразование `{@link FormData}` в объект
54
+ *
55
+ * @param form - данные формы
56
+ * @param multi - поддержка массивов значений
57
+ */
58
+ export declare const formon: <D = any>(form: FormData, multi?: boolean) => D;
package/dist/html.js ADDED
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Проверка по глобальному `window`
3
+ */
4
+ export const isSSR = typeof window === "undefined";
5
+ /**
6
+ * Предотвращает дефолтное поведение события и останавливает всплытие
7
+ */
8
+ export const preventStop = (e) => (e.preventDefault(), e.stopPropagation());
9
+ /**
10
+ * Создаёт обработчик события с {@link preventStop}, который выполняется всегда.
11
+ * Коллбэк выполняется только, если load вернёт `false` (при его наличии)
12
+ */
13
+ export const preventStopHook = (call, load) => (e) => {
14
+ preventStop(e);
15
+ if (!load || !load())
16
+ call?.(e);
17
+ };
18
+ //...
19
+ /**
20
+ * Возвращает обработчик клавиатурных событий, который:
21
+ *
22
+ * 1. Если `usePreventStop === true`, вызывает {@link preventStop}
23
+ * 2. Если load вернёт `false` (при его наличии), то выполнение остановится
24
+ * 3. Вызывает переданный **prepare-коллбэк** (при его наличии), если он вернёт `false`, то выполнение остановится
25
+ * 4. Вызывает основной коллбэк только при нажатии `Enter`.
26
+ */
27
+ export const enterKeyHook = (call, config = { usePreventStop: "enter" }) => (e) => {
28
+ const isEnter = e.key === "Enter";
29
+ if (config?.usePreventStop === "enter") {
30
+ if (isEnter)
31
+ preventStop(e);
32
+ }
33
+ else {
34
+ if (config?.usePreventStop !== undefined) {
35
+ if (typeof config?.usePreventStop === "boolean") {
36
+ if (config?.usePreventStop)
37
+ preventStop(e);
38
+ }
39
+ else {
40
+ if (config?.usePreventStop(e, isEnter))
41
+ preventStop(e);
42
+ }
43
+ }
44
+ }
45
+ if (config?.load?.())
46
+ return;
47
+ if (config?.prepare) {
48
+ Promise.resolve(config?.prepare?.(e)).then((next) => {
49
+ if (next && isEnter)
50
+ call?.(e);
51
+ });
52
+ }
53
+ else {
54
+ if (isEnter)
55
+ call?.(e);
56
+ }
57
+ };
58
+ //...
59
+ /**
60
+ * Создаёт обработчик событий для указанного элемента или окна
61
+ *
62
+ * @template T - Тип события из `WindowEventMap`
63
+ * @template E - Тип объекта события (по умолчанию `WindowEventMap[T]`)
64
+ *
65
+ * @param {T} event - Ключ события
66
+ * @param {(e: E) => CanBePromise} call - Функция-обработчик события
67
+ * @param {AddEventListenerOptions} [options] - Дополнительные параметры
68
+ * @param {HTMLElement | Window} [target=window] - Целевой элемент для привязки события
69
+ *
70
+ * @returns Функция для удаления обработчика события
71
+ */
72
+ export const createEventListener = (event, call, options = {}, target = window) => {
73
+ target.addEventListener(event, call, options);
74
+ return () => target.removeEventListener(event, call);
75
+ };
76
+ //...
77
+ /**
78
+ * Убирает все выделения текста на странице
79
+ */
80
+ export const unselect = () => document.getSelection()?.removeAllRanges();
81
+ /**
82
+ * Создаёт once-обработчик события "mousedown" с {@link unselect}
83
+ *
84
+ * @returns Функция для удаления обработчика события
85
+ */
86
+ export const unselectByMousedown = () => createEventListener("mousedown", unselect, { once: true });
87
+ //...
88
+ /**
89
+ * Преобразование `{@link FormData}` в объект
90
+ *
91
+ * @param form - данные формы
92
+ * @param multi - поддержка массивов значений
93
+ */
94
+ export const formon = (form, multi = false) => {
95
+ if (multi) {
96
+ const result = {};
97
+ for (const { 0: key, 1: value } of form.entries()) {
98
+ if (result[key] !== undefined) {
99
+ if (!Array.isArray(result[key])) {
100
+ result[key] = [result[key]];
101
+ }
102
+ result[key].push(value);
103
+ }
104
+ else {
105
+ result[key] = value;
106
+ }
107
+ }
108
+ return result;
109
+ }
110
+ else {
111
+ return Object.fromEntries(form.entries());
112
+ }
113
+ };
@@ -0,0 +1,5 @@
1
+ export type RU_CASES = "nominative" | "genitive" | "dative" | "accusative" | "ablative";
2
+ /**
3
+ * Форма слова 'рубль' в правильном падеже и числе в зависимости от количества
4
+ */
5
+ export declare const Rubles: (value: number, form?: RU_CASES) => string;
@@ -0,0 +1,46 @@
1
+ //...
2
+ /**
3
+ * Основные формы слова 'рубль'
4
+ */
5
+ const RublesMainSwitch = (form) => {
6
+ switch (form) {
7
+ case "dative":
8
+ return "рублям";
9
+ case "ablative":
10
+ return "рублями";
11
+ default:
12
+ return "рублей";
13
+ }
14
+ };
15
+ /**
16
+ * Форма слова 'рубль' в правильном падеже и числе в зависимости от количества
17
+ */
18
+ export const Rubles = (value, form = "nominative") => {
19
+ const lastTwoDigits = Math.abs(value % 100);
20
+ if (lastTwoDigits > 4 && lastTwoDigits < 21)
21
+ return RublesMainSwitch(form);
22
+ const lastDigit = Math.abs(value % 10);
23
+ if (lastDigit >= 2 && lastDigit <= 4) {
24
+ switch (form) {
25
+ case "nominative":
26
+ case "accusative":
27
+ return "рубля";
28
+ default:
29
+ return RublesMainSwitch(form);
30
+ }
31
+ }
32
+ if (lastDigit === 1) {
33
+ switch (form) {
34
+ case "nominative":
35
+ case "accusative":
36
+ return "рубль";
37
+ case "genitive":
38
+ return "рубля";
39
+ case "dative":
40
+ return "рублю";
41
+ case "ablative":
42
+ return "рублём";
43
+ }
44
+ }
45
+ return RublesMainSwitch(form);
46
+ };
@@ -0,0 +1,33 @@
1
+ import type { CanBeArray } from "./types.js";
2
+ /**
3
+ * Добавляет ведущие нули к числу для достижения указанной длины
4
+ *
5
+ * @example pad(123, 5) => "00123"
6
+ */
7
+ export declare const pad: (v: number, l?: number) => string;
8
+ /**
9
+ * JSON-клонирование объектов посредством `JSON.parse(JSON.stringify(v))`
10
+ * Если значение не `object` вернётся как есть
11
+ */
12
+ export declare const parsify: <T>(v: T) => T;
13
+ /**
14
+ * Приведение значения к массиву
15
+ */
16
+ export declare const arrayble: <T>(v: CanBeArray<T>) => T[];
17
+ /**
18
+ * Тип разделения для функции {@link partition}
19
+ */
20
+ export interface Partition<T> {
21
+ /**
22
+ * Элементы, удовлетворяющие условию
23
+ */
24
+ result: T[];
25
+ /**
26
+ * Исключённые элементы
27
+ */
28
+ excluded: T[];
29
+ }
30
+ /**
31
+ * Разделяет массив на два по условию
32
+ */
33
+ export declare const partition: <T>(arr: T[], filter: (item: T) => boolean, initial?: Partition<T>) => Partition<T>;
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Добавляет ведущие нули к числу для достижения указанной длины
3
+ *
4
+ * @example pad(123, 5) => "00123"
5
+ */
6
+ export const pad = (v, l = 2) => String(v).padStart(l, "0");
7
+ /**
8
+ * JSON-клонирование объектов посредством `JSON.parse(JSON.stringify(v))`
9
+ * Если значение не `object` вернётся как есть
10
+ */
11
+ export const parsify = (v) => {
12
+ if (typeof v !== "object")
13
+ return v;
14
+ return JSON.parse(JSON.stringify(v));
15
+ };
16
+ /**
17
+ * Приведение значения к массиву
18
+ */
19
+ export const arrayble = (v) => (Array.isArray(v) ? v : [v]);
20
+ /**
21
+ * Разделяет массив на два по условию
22
+ */
23
+ export const partition = (arr, filter, initial = { result: [], excluded: [] }) => arr.reduce((acc, item) => (acc[filter(item) ? "result" : "excluded"].push(item), acc), initial);
@@ -0,0 +1,35 @@
1
+ import type { Timestamp } from "./types.js";
2
+ /**
3
+ * Абстрактный класс очереди
4
+ *
5
+ * @template T - Тип элементов в очереди
6
+ */
7
+ export declare abstract class Queue<T> {
8
+ _queue: T[];
9
+ _delay: number;
10
+ private timeout;
11
+ /**
12
+ * @param [delay=25] - Задержка (в миллисекундах) между обработкой элементов очереди
13
+ */
14
+ constructor(delay?: Timestamp);
15
+ /**
16
+ * Добавляет элемент в очередь и запускает обработку
17
+ *
18
+ * @param item - Элемент для добавления в очередь
19
+ */
20
+ protected push(item: T): void;
21
+ /**
22
+ * Запускает обработку очереди с задержкой
23
+ */
24
+ private run;
25
+ /**
26
+ * Метод для обработки элемента очереди
27
+ *
28
+ * @param item - Элемент для обработки
29
+ */
30
+ protected abstract handle(item: T): void;
31
+ /**
32
+ * Сброс очереди
33
+ */
34
+ reset(): void;
35
+ }
package/dist/queue.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Абстрактный класс очереди
3
+ *
4
+ * @template T - Тип элементов в очереди
5
+ */
6
+ export class Queue {
7
+ _queue = [];
8
+ _delay;
9
+ timeout = 0;
10
+ // noinspection TypeScriptAbstractClassConstructorCanBeMadeProtected
11
+ /**
12
+ * @param [delay=25] - Задержка (в миллисекундах) между обработкой элементов очереди
13
+ */
14
+ constructor(delay = 25) {
15
+ this._delay = delay;
16
+ }
17
+ /**
18
+ * Добавляет элемент в очередь и запускает обработку
19
+ *
20
+ * @param item - Элемент для добавления в очередь
21
+ */
22
+ push(item) {
23
+ this._queue.push(item);
24
+ this.run();
25
+ }
26
+ /**
27
+ * Запускает обработку очереди с задержкой
28
+ */
29
+ run() {
30
+ this.reset();
31
+ this.timeout = setTimeout(() => {
32
+ if (this._queue.length === 0)
33
+ return this.reset();
34
+ const item = this._queue.shift();
35
+ this.handle(item);
36
+ this._queue.length > 0 ? this.run() : this.reset();
37
+ }, this._delay);
38
+ }
39
+ /**
40
+ * Сброс очереди
41
+ */
42
+ reset() {
43
+ if (this.timeout)
44
+ clearTimeout(this.timeout);
45
+ this.timeout = 0;
46
+ this._queue.length = 0;
47
+ }
48
+ }
package/dist/string.d.ts CHANGED
@@ -14,10 +14,30 @@ export declare const spaceRegExp: RegExp;
14
14
  * Заменяет все двойные, тройные и т. д. пробелы на один
15
15
  */
16
16
  export declare const spaceClean: (v?: string) => string;
17
+ /**
18
+ * Очистка от плейсхолдеров
19
+ */
20
+ export declare const clearPH: (str?: string, placeholder?: string | RegExp) => string;
17
21
  /**
18
22
  * Приводит первый символ слова к верхнему регистру
19
23
  */
20
24
  export declare const toCapital: (word?: string) => string;
25
+ /**
26
+ * Приводит первый символ каждого слова к верхнему регистру
27
+ */
28
+ export declare const toCapitalMap: (str?: string) => string;
29
+ /**
30
+ * Повторяет строку указанное количество раз с разделителем
31
+ *
32
+ * @param {string} str - Исходная строка
33
+ * @param {number} length - Количество повторений
34
+ * @param {string} [separator=""] - Разделитель между повторениями (по умолчанию пустая строка)
35
+ */
36
+ export declare const repeat: (str: string, length: number, separator?: string) => string;
37
+ /**
38
+ * Приводит всё к нижнему регистру и корректирует пробелы
39
+ */
40
+ export declare const toFlat: (str?: string) => string;
21
41
  /**
22
42
  * Готовая {@link Map} для перевода кириллицы нижнего регистра в латиницу
23
43
  */
package/dist/string.js CHANGED
@@ -15,12 +15,33 @@ export const spaceRegExp = /\s+/g;
15
15
  * Заменяет все двойные, тройные и т. д. пробелы на один
16
16
  */
17
17
  export const spaceClean = (v = "") => v.replace(spaceRegExp, " ").trim();
18
+ /**
19
+ * Очистка от плейсхолдеров
20
+ */
21
+ export const clearPH = (str = "", placeholder = "_") => str.replaceAll(placeholder, "");
18
22
  //...
19
23
  /**
20
24
  * Приводит первый символ слова к верхнему регистру
21
25
  */
22
26
  export const toCapital = (word = "") => word.charAt(0).toUpperCase() + word.slice(1);
27
+ /**
28
+ * Приводит первый символ каждого слова к верхнему регистру
29
+ */
30
+ export const toCapitalMap = (str = "") => str.split(" ").map(toCapital).join(" ");
23
31
  //...
32
+ /**
33
+ * Повторяет строку указанное количество раз с разделителем
34
+ *
35
+ * @param {string} str - Исходная строка
36
+ * @param {number} length - Количество повторений
37
+ * @param {string} [separator=""] - Разделитель между повторениями (по умолчанию пустая строка)
38
+ */
39
+ export const repeat = (str, length, separator = "") => Array.from({ length }).fill(str).join(separator);
40
+ //...
41
+ /**
42
+ * Приводит всё к нижнему регистру и корректирует пробелы
43
+ */
44
+ export const toFlat = (str = "") => spaceClean(str.toLowerCase());
24
45
  /**
25
46
  * Готовая {@link Map} для перевода кириллицы нижнего регистра в латиницу
26
47
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nemigo/helpers",
3
- "version": "0.0.13",
3
+ "version": "0.0.19",
4
4
  "private": false,
5
5
  "author": {
6
6
  "name": "Vlad Logvin",
@@ -15,6 +15,10 @@
15
15
  "format": "prettier --write ./"
16
16
  },
17
17
  "exports": {
18
+ ".": {
19
+ "types": "./dist/index.d.ts",
20
+ "default": "./dist/index.js"
21
+ },
18
22
  "./async": {
19
23
  "types": "./dist/async.d.ts",
20
24
  "default": "./dist/async.js"
@@ -27,6 +31,10 @@
27
31
  "types": "./dist/clean.d.ts",
28
32
  "default": "./dist/clean.js"
29
33
  },
34
+ "./datetime": {
35
+ "types": "./dist/datetime.d.ts",
36
+ "default": "./dist/datetime.js"
37
+ },
30
38
  "./explorer": {
31
39
  "types": "./dist/explorer.d.ts",
32
40
  "default": "./dist/explorer.js"
@@ -35,6 +43,18 @@
35
43
  "types": "./dist/files.d.ts",
36
44
  "default": "./dist/files.js"
37
45
  },
46
+ "./format": {
47
+ "types": "./dist/format.d.ts",
48
+ "default": "./dist/format.js"
49
+ },
50
+ "./html": {
51
+ "types": "./dist/html.d.ts",
52
+ "default": "./dist/html.js"
53
+ },
54
+ "./humanly": {
55
+ "types": "./dist/humanly.d.ts",
56
+ "default": "./dist/humanly.js"
57
+ },
38
58
  "./lens": {
39
59
  "types": "./dist/lens.d.ts",
40
60
  "default": "./dist/lens.js"
@@ -47,6 +67,10 @@
47
67
  "types": "./dist/phymath.d.ts",
48
68
  "default": "./dist/phymath.js"
49
69
  },
70
+ "./queue": {
71
+ "types": "./dist/queue.d.ts",
72
+ "default": "./dist/queue.js"
73
+ },
50
74
  "./random": {
51
75
  "types": "./dist/random.d.ts",
52
76
  "default": "./dist/random.js"
@@ -55,6 +79,10 @@
55
79
  "types": "./dist/script.d.ts",
56
80
  "default": "./dist/script.js"
57
81
  },
82
+ "./string": {
83
+ "types": "./dist/string.d.ts",
84
+ "default": "./dist/string.js"
85
+ },
58
86
  "./types": {
59
87
  "types": "./dist/types.d.ts",
60
88
  "default": "./dist/types.js"
@@ -64,10 +92,19 @@
64
92
  "default": "./dist/url.js"
65
93
  }
66
94
  },
95
+ "peerDependencies": {
96
+ "zod": "^4.0.0"
97
+ },
98
+ "peerDependenciesMeta": {
99
+ "zod": {
100
+ "optional": true
101
+ }
102
+ },
67
103
  "dependencies": {
68
104
  "@std/msgpack": "jsr:^1.0.0"
69
105
  },
70
106
  "devDependencies": {
71
- "@nemigo/configs": "workspace:*"
107
+ "@nemigo/configs": "workspace:*",
108
+ "zod": "4.1.5"
72
109
  }
73
110
  }