@reforgium/internal 1.2.0 → 1.3.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/README.md CHANGED
@@ -1,82 +1,139 @@
1
- # @reforgium/internal
2
-
3
- [![npm version](https://badge.fury.io/js/%40reforgium%2Finternal.svg)](https://www.npmjs.com/package/@reforgium/internal)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
-
6
- Shared infrastructure package for Reforgium Angular libraries.
7
-
8
- ## Install
9
-
10
- ```bash
11
- npm i @reforgium/internal
12
- ```
13
-
14
- ## Public API
15
-
16
- `@reforgium/internal` exports:
17
- - `models`
18
- - `tokens`
19
- - `utils`
20
-
21
- ### Models
22
-
23
- Main model groups:
24
- - `api.ts`: `RestMethods`, `SortToken`, `PageableRequest`, `PageableResponse<T>`, `ErrorResponse`, `QueryParams`, `Query`
25
- - `components.ts`: `Appearance`, `SelectOption`, `SelectIconOption`
26
- - `elements.ts`: `Direction`, `ElementRect`, `ElementSize`, `ElementPosition`, `ElementEdges`
27
- - `util.ts`: `AnyType`, `AnyDict`, `LiteralOf`, `ValueOf`, `Nullable`, `Nullish`, `NullableProps`, `OptionalExcept`, `RequiredExcept`, `Mutable`, JSON helper types
28
-
29
- ### Tokens
30
-
31
- Language tokens:
32
- - `SELECTED_LANG: InjectionToken<Signal<Langs>>`
33
- - `CHANGE_LANG: InjectionToken<(lang: Langs) => void>`
34
- - `TRANSLATION`
35
- - `REGISTER_LANG` (multi-token)
36
- - `BUILTIN_LANGS`
37
- - `provideLangs(...langs: string[])`
38
- - `Langs = BuiltInLangs | (string & {})`
39
-
40
- Theme/device/validation tokens:
41
- - `SELECTED_THEME`, `CHANGE_THEME`, `Themes`
42
- - `CURRENT_DEVICE`, `Devices`
43
- - `VALIDATION_MESSAGES`, `ValidationMessages`, `ValidationErrorData`
44
-
45
- Example:
46
-
47
- ```ts
48
- import { provideLangs } from '@reforgium/internal';
49
-
50
- export const appConfig = {
51
- providers: [provideLangs('de', 'fr')],
52
- };
53
- ```
54
-
55
- ### Utilities
56
-
57
- Exported utilities:
58
- - `web.utils.ts`: `downloadByBlob`, `downloadByUrl`, `copyText`, `base64ToBlob`
59
- - `timers.utils.ts`: `throttleSignal`, `debounceSignal`
60
- - `date.utils.ts`: `toDate`, `formatDate`, `formatToLocaledDate`, `parseToDate`, `parseToDatePeriod`, `isDatePeriod`, `reformatDateToISO`
61
- - `types.utils.ts`: `isNumber`, `isNullable`, `isObject`, `parseQueryArray`, `concatArray`
62
- - `format.utils.ts`: `formatToSpacedNumber`, `truncate`
63
- - `positions.utils.ts`: `getCorrectedPosition`
64
- - `available-height.utils.ts`: `getAvailableHeight`
65
- - `get-chained-value.utils.ts`: `getChainedValue`
66
- - `urls.utils.ts`: `normalizeUrl`, `fillUrlWithParams`, `appendQueryParams`, `parseQueryParams`
67
- - `routes.utils.ts`: `materializeRoutePath`, `compareRoutes`, `makeQuery`
68
- - `deep-equal.utils.ts`: `deepEqual`
69
- - `generate.utils.ts`: `generateId`
70
-
71
- `makeQuery(..., 'multi')` behavior:
72
-
73
- ```ts
74
- import { makeQuery } from '@reforgium/internal';
75
-
76
- makeQuery({ ids: [1, 2, 3], q: 'ok' }, 'multi');
77
- // ids=1&ids=2&ids=3&q=ok
78
- ```
79
-
80
- ## License
81
-
1
+ # @reforgium/internal
2
+
3
+ [![npm version](https://badge.fury.io/js/%40reforgium%2Finternal.svg)](https://www.npmjs.com/package/@reforgium/internal)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Shared infrastructure package for Reforgium Angular libraries.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm i @reforgium/internal
12
+ ```
13
+
14
+ ## Public API
15
+
16
+ `@reforgium/internal` exports:
17
+
18
+ - `models`
19
+ - `tokens`
20
+ - `utils`
21
+
22
+ ### Models
23
+
24
+ Main model groups:
25
+
26
+ - `api.ts`: `RestMethods`, `SortToken`, `PageableRequest`, `PageableResponse<T>`, `ErrorResponse`, `QueryParams`, `Query`
27
+ - `components.ts`: `Appearance`, `SelectOption`, `SelectIconOption`
28
+ - `elements.ts`: `Direction`, `ElementRect`, `ElementSize`, `ElementPosition`, `ElementEdges`
29
+ - `util.ts`: `AnyType`, `AnyDict`, `LiteralOf`, `ValueOf`, `Nullable`, `Nullish`, `NullableProps`, `OptionalExcept`, `RequiredExcept`, `Mutable`, JSON helper types
30
+
31
+ ### Tokens
32
+
33
+ Language tokens:
34
+
35
+ - `SELECTED_LANG: InjectionToken<Signal<Langs>>`
36
+ - `CHANGE_LANG: InjectionToken<(lang: Langs) => void>`
37
+ - `TRANSLATION`
38
+ - `REGISTER_LANG` (multi-token)
39
+ - `BUILTIN_LANGS`
40
+ - `provideLangs(...langs: string[])`
41
+ - `Langs = BuiltInLangs | (string & {})`
42
+
43
+ Theme/device/validation tokens:
44
+
45
+ - `SELECTED_THEME`, `CHANGE_THEME`, `Themes`
46
+ - `CURRENT_DEVICE`, `Devices`
47
+ - `VALIDATION_MESSAGES`, `ValidationMessages`, `ValidationErrorData`
48
+
49
+ Example:
50
+
51
+ ```ts
52
+ import { provideLangs } from '@reforgium/internal';
53
+
54
+ export const appConfig = {
55
+ providers: [provideLangs('de', 'fr')],
56
+ };
57
+ ```
58
+
59
+ ### Utilities
60
+
61
+ Exported utilities:
62
+
63
+ - `web.utils.ts`: `downloadByBlob`, `downloadByUrl`, `copyText`, `base64ToBlob`
64
+ - `timers.utils.ts`: `throttleSignal`, `debounceSignal`
65
+ - `date.utils.ts`: `toDate`, `formatDate`, `formatToLocaledDate`, `parseToDate`, `parseToDatePeriod`, `isDatePeriod`, `reformatDateToISO`
66
+ - `types.utils.ts`: `isNumber`, `isNullable`, `isObject`, `parseQueryArray`, `concatArray`
67
+ - `format.utils.ts`: `formatToSpacedNumber`, `truncate`
68
+ - `positions.utils.ts`: `getCorrectedPosition`
69
+ - `available-height.utils.ts`: `getAvailableHeight`
70
+ - `get-chained-value.utils.ts`: `getChainedValue`
71
+ - `query.utils.ts`: `buildQueryParams`, `appendQueryParamsByMode`, `parseQueryParams`, `parseQueryParamsByMode`, `mergeQueryParams`, `makeQuery`
72
+ - `sort.utils.ts`: `toSortToken`, `sortRuleToToken`, `parseSortToken`, `normalizeSortInput`, `sortInputToTokens`
73
+ - `urls.utils.ts`: `normalizeUrl`, `fillUrlWithParams`, `appendQueryParams`, `parseQueryParams`
74
+ - `routes.utils.ts`: `materializeRoutePath`, `compareRoutes`, `makeQuery`
75
+ - `deep-equal.utils.ts`: `deepEqual`
76
+ - `generate.utils.ts`: `generateId`
77
+
78
+ Recommended entrypoints:
79
+
80
+ - prefer `query.utils.ts` for new query-string work;
81
+ - prefer `sort.utils.ts` for new sort serialization/parsing work;
82
+ - keep `urls.utils.ts` and `routes.utils.ts` for narrower low-level cases.
83
+
84
+ `query.utils.ts` example:
85
+
86
+ ```ts
87
+ import { buildQueryParams, mergeQueryParams, parseQueryParamsByMode } from '@reforgium/internal';
88
+
89
+ const query = buildQueryParams(
90
+ {
91
+ tags: ['angular', 'signals'],
92
+ sort: ['name,asc', 'createdAt,desc'],
93
+ page: 2,
94
+ },
95
+ 'comma',
96
+ { sort: 'multi' },
97
+ );
98
+ // tags=angular%2Csignals&page=2&sort=name%2Casc&sort=createdAt%2Cdesc
99
+
100
+ const next = mergeQueryParams(
101
+ { page: 1, tags: ['angular'], tenant: 'kg' },
102
+ { page: 2, tenant: null, sort: ['name,asc'] },
103
+ );
104
+ // { page: 2, tags: ['angular'], sort: ['name,asc'] }
105
+
106
+ const parsed = parseQueryParamsByMode(query, 'comma', { sort: 'multi' });
107
+ // { tags: ['angular', 'signals'], sort: ['name,asc', 'createdAt,desc'], page: '2' }
108
+ ```
109
+
110
+ `sort.utils.ts` example:
111
+
112
+ ```ts
113
+ import { parseSortToken, sortInputToTokens, toSortToken } from '@reforgium/internal';
114
+
115
+ toSortToken('name', 'asc');
116
+ // 'name,asc'
117
+
118
+ sortInputToTokens([
119
+ { sort: 'name', order: 'asc' },
120
+ { sort: 'createdAt', order: 'desc' },
121
+ ]);
122
+ // ['name,asc', 'createdAt,desc']
123
+
124
+ parseSortToken('createdAt,desc');
125
+ // { sort: 'createdAt', order: 'desc' }
126
+ ```
127
+
128
+ Low-level `makeQuery(..., 'multi')` behavior:
129
+
130
+ ```ts
131
+ import { makeQuery } from '@reforgium/internal';
132
+
133
+ makeQuery({ ids: [1, 2, 3], q: 'ok' }, 'multi');
134
+ // ids=1&ids=2&ids=3&q=ok
135
+ ```
136
+
137
+ ## License
138
+
82
139
  MIT
@@ -95,7 +95,7 @@ const VALIDATION_MESSAGES = new InjectionToken('RE_VALIDATION_MESSAGES', {
95
95
  });
96
96
 
97
97
  /**
98
- * Downloads a file from a Blob object and prompts the user to save it.
98
+ * Browser-only helper that downloads a file from a Blob object and prompts the user to save it.
99
99
  *
100
100
  * @param {Blob} blob - Blob object representing the file to download.
101
101
  * @param {string} [fileName] - Optional. Name for the downloaded file.
@@ -114,7 +114,7 @@ function downloadByBlob(blob, fileName) {
114
114
  }
115
115
  }
116
116
  /**
117
- * Initiates a file download for the given URL. Optionally, a custom filename can be specified.
117
+ * Browser-only helper that initiates a file download for the given URL.
118
118
  *
119
119
  * @param {string} url - URL of the file to download.
120
120
  * @param {string} [filename] - Desired name for the downloaded file.
@@ -133,8 +133,8 @@ function downloadByUrl(url, filename) {
133
133
  win.document.body.removeChild(a);
134
134
  }
135
135
  /**
136
- * Copies the specified text to the clipboard. Uses the Clipboard API if available,
137
- * otherwise falls back to `document.execCommand`.
136
+ * Browser-only helper that copies text to the clipboard.
137
+ * Uses the Clipboard API if available, otherwise falls back to `document.execCommand`.
138
138
  *
139
139
  * @param {string} text - The text to copy to the clipboard.
140
140
  * @return {Promise<boolean>} A promise that resolves to a boolean indicating whether
@@ -164,7 +164,7 @@ async function copyText(text) {
164
164
  return ok;
165
165
  }
166
166
  /**
167
- * Converts a Base64 encoded string to a Blob object.
167
+ * Browser-oriented helper that converts a Base64 encoded string to a Blob object.
168
168
  *
169
169
  * @param {string} base64 - Base64 encoded string. Can optionally include a MIME type
170
170
  * in the format `data:<mimeType>;base64,<data>`.
@@ -323,11 +323,13 @@ const formatDate = (date, format = 'yyyy-MM-dd') => {
323
323
  return formatted;
324
324
  };
325
325
  /**
326
- * Formats the given date into a localized string representation in the format 'day month year'.
327
- * The month is localized for 'ru-RU' locale and abbreviated.
326
+ * Formats the given date into a `day month year` string using the `ru-RU` locale.
327
+ * The month is abbreviated and normalized without a trailing dot.
328
+ *
329
+ * Despite the generic name, this helper is intentionally Russian-locale-specific.
328
330
  *
329
331
  * @param {Date} date - Date object to format.
330
- * @return {string} A string representing the formatted date in the format 'day month year'.
332
+ * @return {string} A string representing the formatted date in the format `day month year`.
331
333
  */
332
334
  function formatToLocaledDate(date) {
333
335
  const day = date.getDate();
@@ -712,41 +714,85 @@ function fillUrlWithParams(template, params) {
712
714
  return template.replace(/:([a-zA-Z0-9_]+)/g, (_, k) => encodeURIComponent(params[k] ?? ''));
713
715
  }
714
716
  /**
715
- * Appends query parameters to the specified URL.
717
+ * Low-level URL helper for appending query parameters to an existing URL.
718
+ *
719
+ * Prefer `query.utils` for new code that needs a query-focused API, mixed per-field
720
+ * array modes, or object-level query merging. Use this helper directly when you already
721
+ * work with a concrete URL string and only need to append serialized params.
716
722
  *
717
723
  * @param {string} url Base URL to which query parameters will be added.
718
724
  * @param {Record<string, unknown>} [params] Optional object containing query parameter key-value pairs.
719
725
  * Keys with null or undefined values will be ignored.
726
+ * Array values are serialized according to `arrayMode`.
727
+ * @param {QueryArrayMode} [arrayMode='comma'] Array serialization strategy:
728
+ * - `comma`: stores arrays as `tags=a,b`
729
+ * - `json`: stores arrays as `tags=["a","b"]`
730
+ * - `multi`: stores arrays as `tags=a&tags=b`
720
731
  * @return {string} URL with appended query parameters.
721
732
  */
722
- function appendQueryParams(url, params) {
733
+ function appendQueryParams(url, params, arrayMode = 'comma') {
723
734
  if (!params || !Object.keys(params).length)
724
735
  return url;
725
- const [base, query] = url.split('?', 2);
736
+ const hashIndex = url.indexOf('#');
737
+ const hash = hashIndex >= 0 ? url.slice(hashIndex) : '';
738
+ const withoutHash = hashIndex >= 0 ? url.slice(0, hashIndex) : url;
739
+ const [base, query] = withoutHash.split('?', 2);
726
740
  const searchParams = new URLSearchParams(query || '');
727
741
  for (const [key, value] of Object.entries(params)) {
728
- if (value == null)
742
+ if (isNullable(value))
743
+ continue;
744
+ searchParams.delete(key);
745
+ if (Array.isArray(value)) {
746
+ if (arrayMode === 'multi') {
747
+ value.forEach((item) => searchParams.append(key, String(item)));
748
+ }
749
+ else {
750
+ searchParams.set(key, concatArray(value, arrayMode));
751
+ }
729
752
  continue;
753
+ }
730
754
  searchParams.set(key, String(value));
731
755
  }
732
- return `${base}?${searchParams.toString()}`;
756
+ const nextQuery = searchParams.toString();
757
+ return `${base}${nextQuery ? `?${nextQuery}` : ''}${hash}`;
733
758
  }
734
759
  /**
735
- * Parses a query string into an object containing key-value pairs.
760
+ * Low-level query-string parser.
761
+ *
762
+ * Prefer `query.utils` for new code that needs mixed per-field parsing modes or query-object
763
+ * workflows. Use this helper directly when parsing a plain query string with one shared array mode.
736
764
  *
737
765
  * @param {string} query - The query string to parse. May start with '?'.
738
- * @return {Record<string, string>} An object where each key is a query parameter name,
739
- * and the value is the corresponding value.
766
+ * @param {QueryArrayMode} [arrayMode] Optional array parsing mode. When provided, array-shaped values are
767
+ * parsed according to the specified encoding strategy.
768
+ * @return {Record<string, string | string[]>} An object where each key is a query parameter name,
769
+ * and the value is either a scalar string or an array of strings when array parsing is enabled.
740
770
  */
741
- function parseQueryParams(query) {
771
+ const parseQueryParams = ((query, arrayMode) => {
742
772
  const search = query.startsWith('?') ? query.slice(1) : query;
743
773
  const params = new URLSearchParams(search);
744
774
  const result = {};
745
- params.forEach((v, k) => {
746
- result[k] = v;
775
+ const keys = new Set();
776
+ params.forEach((_value, key) => {
777
+ keys.add(key);
747
778
  });
779
+ for (const key of keys) {
780
+ const values = params.getAll(key);
781
+ if (values.length <= 1) {
782
+ const value = values[0] ?? '';
783
+ if (!arrayMode) {
784
+ result[key] = value;
785
+ }
786
+ else {
787
+ const parsed = parseQueryArray(arrayMode === 'multi' ? `${key}=${value}` : value, arrayMode, key);
788
+ result[key] = parsed.length ? parsed : value;
789
+ }
790
+ continue;
791
+ }
792
+ result[key] = arrayMode === 'multi' ? values : parseQueryArray(values[0] ?? '', arrayMode ?? 'comma', key);
793
+ }
748
794
  return result;
749
- }
795
+ });
750
796
 
751
797
  /**
752
798
  * Constructs a query string from a given object and concatenation type.
@@ -757,17 +803,21 @@ function parseQueryParams(query) {
757
803
  * - 'comma': Joins array elements with a comma.
758
804
  * - 'json': Serializes the array as a JSON string.
759
805
  * - 'multi': Creates multiple entries for array elements, each associated with the same key.
806
+ * @param {(key: string, value: unknown) => QueryArrayMode | undefined} [resolveConcatType] - Optional per-field
807
+ * array mode resolver. When it returns a mode for a specific key, that mode overrides `concatType`
808
+ * only for that field.
760
809
  * @returns {string} - Formed query string with keys and values encoded as URI components.
761
810
  */
762
- const makeQuery = (object, concatType) => {
811
+ const makeQuery = (object, concatType, resolveConcatType) => {
763
812
  return Object.entries(object)
764
813
  .filter(([, value]) => !isNullable(value))
765
814
  .flatMap(([key, value]) => {
766
815
  if (Array.isArray(value)) {
767
- if (concatType === 'multi') {
816
+ const arrayConcatType = resolveConcatType?.(key, value) ?? concatType;
817
+ if (arrayConcatType === 'multi') {
768
818
  return value.map((item) => `${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);
769
819
  }
770
- const val = concatArray(value, concatType, key);
820
+ const val = concatArray(value, arrayConcatType, key);
771
821
  return `${encodeURIComponent(key)}=${encodeURIComponent(val)}`;
772
822
  }
773
823
  return `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
@@ -824,10 +874,179 @@ const fillRouteTemplate = (actualRoute, pureRoute) => {
824
874
  return prefix + segments.join('/');
825
875
  };
826
876
 
877
+ /**
878
+ * Recommended high-level entrypoint for query-string work in `internal`.
879
+ *
880
+ * Prefer this module for new code when you need to:
881
+ * - build query strings with mixed per-field array modes,
882
+ * - parse mixed query strings back into object form,
883
+ * - merge query param objects before serialization.
884
+ *
885
+ * Low-level helpers from `urls.utils` / `routes.utils` remain available for narrow cases.
886
+ */
887
+ /**
888
+ * Alias for `appendQueryParams` to keep query-related API discoverable from one module.
889
+ */
890
+ const appendQueryParamsByMode = appendQueryParams;
891
+ /**
892
+ * Builds a query string using a default array mode with optional per-field overrides.
893
+ *
894
+ * @example
895
+ * ```ts
896
+ * buildQueryParams(
897
+ * { tags: ['a', 'b'], sort: ['name,asc', 'createdAt,desc'], page: 2 },
898
+ * 'comma',
899
+ * { sort: 'multi' },
900
+ * );
901
+ * // => 'tags=a%2Cb&page=2&sort=name%2Casc&sort=createdAt%2Cdesc'
902
+ * ```
903
+ */
904
+ function buildQueryParams(params, defaultArrayMode = 'comma', fieldModes = {}) {
905
+ const scalarParams = {};
906
+ const chunks = [];
907
+ for (const [key, value] of Object.entries(params ?? {})) {
908
+ const mode = fieldModes[key];
909
+ if (Array.isArray(value) && mode && mode !== defaultArrayMode) {
910
+ chunks.push(appendQueryParams('', { [key]: value }, mode).replace(/^\?/, ''));
911
+ continue;
912
+ }
913
+ scalarParams[key] = value;
914
+ }
915
+ const baseChunk = appendQueryParams('', scalarParams, defaultArrayMode).replace(/^\?/, '');
916
+ if (baseChunk) {
917
+ chunks.unshift(baseChunk);
918
+ }
919
+ return chunks.filter(Boolean).join('&');
920
+ }
921
+ /**
922
+ * Parses query params using a default array mode with optional per-field overrides.
923
+ *
924
+ * @example
925
+ * ```ts
926
+ * parseQueryParamsByMode('tags=a%2Cb&sort=name%2Casc&sort=createdAt%2Cdesc&page=2', 'comma', {
927
+ * sort: 'multi',
928
+ * });
929
+ * // => { tags: ['a', 'b'], sort: ['name,asc', 'createdAt,desc'], page: '2' }
930
+ * ```
931
+ */
932
+ function parseQueryParamsByMode(query, defaultArrayMode, fieldModes = {}) {
933
+ const search = query.startsWith('?') ? query.slice(1) : query;
934
+ const searchParams = new URLSearchParams(search);
935
+ const keys = new Set();
936
+ const scalarResult = parseQueryParams(query);
937
+ const mixedResult = { ...scalarResult };
938
+ searchParams.forEach((_value, key) => {
939
+ keys.add(key);
940
+ });
941
+ for (const [key, mode] of Object.entries(fieldModes)) {
942
+ if (!mode) {
943
+ continue;
944
+ }
945
+ const parsed = parseQueryParams(query, mode);
946
+ if (key in parsed) {
947
+ mixedResult[key] = parsed[key];
948
+ }
949
+ }
950
+ if (!defaultArrayMode) {
951
+ return mixedResult;
952
+ }
953
+ for (const key of keys) {
954
+ if (key in fieldModes) {
955
+ continue;
956
+ }
957
+ const values = searchParams.getAll(key);
958
+ const value = values[0] ?? '';
959
+ if (defaultArrayMode === 'multi') {
960
+ if (values.length > 1) {
961
+ mixedResult[key] = values;
962
+ }
963
+ continue;
964
+ }
965
+ if (defaultArrayMode === 'comma' && value.includes(',')) {
966
+ mixedResult[key] = parseQueryArray(value, 'comma', key);
967
+ continue;
968
+ }
969
+ if (defaultArrayMode === 'json' && value.trim().startsWith('[')) {
970
+ mixedResult[key] = parseQueryArray(value, 'json', key);
971
+ }
972
+ }
973
+ return mixedResult;
974
+ }
975
+ /**
976
+ * Merges query param objects without mutating the inputs.
977
+ *
978
+ * Rules:
979
+ * - `next` overrides `base` by key,
980
+ * - `null` / `undefined` in `next` remove the key from the result,
981
+ * - arrays are replaced, not concatenated.
982
+ *
983
+ * @example
984
+ * ```ts
985
+ * mergeQueryParams(
986
+ * { page: 1, tags: ['a', 'b'], tenant: 'kg' },
987
+ * { page: 2, tenant: null, sort: ['name,asc'] },
988
+ * );
989
+ * // => { page: 2, tags: ['a', 'b'], sort: ['name,asc'] }
990
+ * ```
991
+ */
992
+ function mergeQueryParams(base = {}, next = {}) {
993
+ const result = { ...base };
994
+ for (const [key, value] of Object.entries(next)) {
995
+ if (value === null || value === undefined) {
996
+ delete result[key];
997
+ }
998
+ else {
999
+ result[key] = value;
1000
+ }
1001
+ }
1002
+ return result;
1003
+ }
1004
+
1005
+ /**
1006
+ * Builds a typed sort token from a field name and direction.
1007
+ */
1008
+ function toSortToken(sort, order) {
1009
+ return `${sort},${order}`;
1010
+ }
1011
+ /**
1012
+ * Converts a sort rule object into a typed sort token.
1013
+ */
1014
+ function sortRuleToToken(rule) {
1015
+ return toSortToken(rule.sort, rule.order);
1016
+ }
1017
+ /**
1018
+ * Parses a sort token into a sort rule object.
1019
+ * Returns `null` for invalid or unsupported tokens.
1020
+ */
1021
+ function parseSortToken(token) {
1022
+ const [sort, order, ...rest] = token.split(',');
1023
+ if (!sort || rest.length > 0 || (order !== 'asc' && order !== 'desc')) {
1024
+ return null;
1025
+ }
1026
+ return { sort: sort, order };
1027
+ }
1028
+ /**
1029
+ * Normalizes single or multi-sort input into an array of valid sort rules.
1030
+ */
1031
+ function normalizeSortInput(sort) {
1032
+ const list = !sort ? [] : Array.isArray(sort) ? sort : [sort];
1033
+ return list.filter((item) => !!item?.sort && !!item?.order);
1034
+ }
1035
+ /**
1036
+ * Converts single or multi-sort input into typed sort tokens.
1037
+ */
1038
+ function sortInputToTokens(sort) {
1039
+ return normalizeSortInput(sort).map((item) => sortRuleToToken(item));
1040
+ }
1041
+
827
1042
  /**
828
1043
  * Recursively checks the equality of two objects, including nested structures and special cases
829
1044
  * such as arrays, sets, maps, dates, and NaN.
830
1045
  *
1046
+ * `Map` and `Set` values are compared in iteration order because they are materialized into arrays
1047
+ * before comparison. This keeps the helper predictable for transport/state snapshots, but it is not
1048
+ * a mathematical set-equivalence check.
1049
+ *
831
1050
  * @param {AnyType} a - The first object to compare.
832
1051
  * @param {AnyType} b - The second object to compare.
833
1052
  * @param {Map} [seen=new Map()] - A map used to detect cyclic references
@@ -877,6 +1096,17 @@ function deepEqual(a, b, seen = new Map()) {
877
1096
  return false;
878
1097
  }
879
1098
 
1099
+ /**
1100
+ * Generates a short pseudo-random identifier.
1101
+ *
1102
+ * This helper is intended for lightweight client-side use cases such as temporary
1103
+ * DOM ids or ephemeral UI keys. It does not guarantee uniqueness and must not be
1104
+ * treated as a secure or globally unique identifier.
1105
+ *
1106
+ * @param {number} [limit=15] Desired identifier length.
1107
+ * @param {number} [radix=36] Radix passed to `Number.prototype.toString`.
1108
+ * @returns {string} Pseudo-random identifier string.
1109
+ */
880
1110
  const generateId = (limit = 15, radix = 36) => Math.random()
881
1111
  .toString(radix)
882
1112
  .substring(2, limit + 2);
@@ -885,5 +1115,5 @@ const generateId = (limit = 15, radix = 36) => Math.random()
885
1115
  * Generated bundle index. Do not edit.
886
1116
  */
887
1117
 
888
- export { BUILTIN_LANGS, CHANGE_LANG, CHANGE_THEME, CURRENT_DEVICE, REGISTER_LANG, SELECTED_LANG, SELECTED_THEME, TRANSLATION, VALIDATION_MESSAGES, appendQueryParams, base64ToBlob, compareRoutes, concatArray, copyText, debounceSignal, deepEqual, downloadByBlob, downloadByUrl, fillUrlWithParams, formatDate, formatToLocaledDate, formatToSpacedNumber, generateId, getAvailableHeight, getChainedValue, getCorrectedPosition, isDatePeriod, isNullable, isNumber, isObject, makeQuery, materializeRoutePath, normalizeUrl, parseQueryArray, parseQueryParams, parseToDate, parseToDatePeriod, provideLangs, reformatDateToISO, throttleSignal, toDate, truncate };
1118
+ export { BUILTIN_LANGS, CHANGE_LANG, CHANGE_THEME, CURRENT_DEVICE, REGISTER_LANG, SELECTED_LANG, SELECTED_THEME, TRANSLATION, VALIDATION_MESSAGES, appendQueryParams, appendQueryParamsByMode, base64ToBlob, buildQueryParams, compareRoutes, concatArray, copyText, debounceSignal, deepEqual, downloadByBlob, downloadByUrl, fillUrlWithParams, formatDate, formatToLocaledDate, formatToSpacedNumber, generateId, getAvailableHeight, getChainedValue, getCorrectedPosition, isDatePeriod, isNullable, isNumber, isObject, makeQuery, materializeRoutePath, mergeQueryParams, normalizeSortInput, normalizeUrl, parseQueryArray, parseQueryParams, parseQueryParamsByMode, parseSortToken, parseToDate, parseToDatePeriod, provideLangs, reformatDateToISO, sortInputToTokens, sortRuleToToken, throttleSignal, toDate, toSortToken, truncate };
889
1119
  //# sourceMappingURL=reforgium-internal.mjs.map
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.2.0",
2
+ "version": "1.3.0",
3
3
  "name": "@reforgium/internal",
4
4
  "description": "reforgium Libs Internal package. Shared libs models and tokens.",
5
5
  "author": "rtommievich",
@@ -8,9 +8,17 @@
8
8
  "repository": {
9
9
  "type": "git"
10
10
  },
11
+ "bugs": {
12
+ "email": "rtommievich@gmail.com"
13
+ },
11
14
  "publishConfig": {
12
15
  "access": "public"
13
16
  },
17
+ "sideEffects": false,
18
+ "engines": {
19
+ "node": ">=18.0.0",
20
+ "npm": ">=9.0.0"
21
+ },
14
22
  "keywords": [
15
23
  "reforgium",
16
24
  "common",
@@ -18,15 +26,23 @@
18
26
  "angular",
19
27
  "signal"
20
28
  ],
21
- "types": "../../dist/@reforgium/internal/index.d.ts",
29
+ "types": "../../dist/@reforgium/internal/types/reforgium-internal.d.ts",
30
+ "typings": "types/reforgium-internal.d.ts",
31
+ "module": "fesm2022/reforgium-internal.mjs",
32
+ "files": [
33
+ "fesm2022/*.mjs",
34
+ "types/*.d.ts",
35
+ "package.json",
36
+ "README.md",
37
+ "CHANGELOG.md",
38
+ "LICENSE*"
39
+ ],
22
40
  "dependencies": {
23
41
  "tslib": "^2.8.1"
24
42
  },
25
43
  "peerDependencies": {
26
44
  "@angular/core": ">=19.0.0"
27
45
  },
28
- "module": "fesm2022/reforgium-internal.mjs",
29
- "typings": "types/reforgium-internal.d.ts",
30
46
  "exports": {
31
47
  "./package.json": {
32
48
  "default": "./package.json"
@@ -35,6 +51,5 @@
35
51
  "types": "./types/reforgium-internal.d.ts",
36
52
  "default": "./fesm2022/reforgium-internal.mjs"
37
53
  }
38
- },
39
- "sideEffects": false
54
+ }
40
55
  }
@@ -233,6 +233,14 @@ type RestMethods = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
233
233
  * ```
234
234
  */
235
235
  type SortToken<F extends string = string> = `${F},${'asc' | 'desc'}`;
236
+ type SortDirection = 'asc' | 'desc';
237
+ type SortRule<F extends string = string> = {
238
+ sort: F;
239
+ order: SortDirection;
240
+ };
241
+ type SortInput<F extends string = string> = SortRule<F> | ReadonlyArray<SortRule<F>> | null | undefined;
242
+ type QueryArrayMode = 'comma' | 'json' | 'multi';
243
+ type QueryFieldModes = Partial<Record<string, QueryArrayMode>>;
236
244
  /**
237
245
  * Pagination request with optional multi-field sorting.
238
246
  * Used to request paginated data from API endpoints.
@@ -254,7 +262,7 @@ type PageableRequest = {
254
262
  * Format: "field,direction" where direction is "asc" or "desc".
255
263
  * @example ["name,asc", "createdAt,desc"]
256
264
  */
257
- sort?: string | ReadonlyArray<string>;
265
+ sort?: SortToken | ReadonlyArray<SortToken>;
258
266
  };
259
267
  /**
260
268
  * Paginated response structure.
@@ -336,7 +344,7 @@ interface QueryParams<Filters = unknown> {
336
344
  * Optional sorting criteria.
337
345
  * Can be a single sort token or an array of sort tokens for multi-field sorting.
338
346
  */
339
- sort?: string | ReadonlyArray<string>;
347
+ sort?: SortToken | ReadonlyArray<SortToken>;
340
348
  /**
341
349
  * Optional filters as a partial subset of the domain model.
342
350
  * Allows filtering by any combination of model properties.
@@ -557,7 +565,7 @@ type ValidationMessages = Record<string, (error: ValidationErrorData) => string>
557
565
  declare const VALIDATION_MESSAGES: InjectionToken<ValidationMessages>;
558
566
 
559
567
  /**
560
- * Downloads a file from a Blob object and prompts the user to save it.
568
+ * Browser-only helper that downloads a file from a Blob object and prompts the user to save it.
561
569
  *
562
570
  * @param {Blob} blob - Blob object representing the file to download.
563
571
  * @param {string} [fileName] - Optional. Name for the downloaded file.
@@ -566,7 +574,7 @@ declare const VALIDATION_MESSAGES: InjectionToken<ValidationMessages>;
566
574
  */
567
575
  declare function downloadByBlob(blob: Blob, fileName?: string | undefined): void;
568
576
  /**
569
- * Initiates a file download for the given URL. Optionally, a custom filename can be specified.
577
+ * Browser-only helper that initiates a file download for the given URL.
570
578
  *
571
579
  * @param {string} url - URL of the file to download.
572
580
  * @param {string} [filename] - Desired name for the downloaded file.
@@ -575,8 +583,8 @@ declare function downloadByBlob(blob: Blob, fileName?: string | undefined): void
575
583
  */
576
584
  declare function downloadByUrl(url: string, filename?: string): void;
577
585
  /**
578
- * Copies the specified text to the clipboard. Uses the Clipboard API if available,
579
- * otherwise falls back to `document.execCommand`.
586
+ * Browser-only helper that copies text to the clipboard.
587
+ * Uses the Clipboard API if available, otherwise falls back to `document.execCommand`.
580
588
  *
581
589
  * @param {string} text - The text to copy to the clipboard.
582
590
  * @return {Promise<boolean>} A promise that resolves to a boolean indicating whether
@@ -584,7 +592,7 @@ declare function downloadByUrl(url: string, filename?: string): void;
584
592
  */
585
593
  declare function copyText(text: string): Promise<boolean>;
586
594
  /**
587
- * Converts a Base64 encoded string to a Blob object.
595
+ * Browser-oriented helper that converts a Base64 encoded string to a Blob object.
588
596
  *
589
597
  * @param {string} base64 - Base64 encoded string. Can optionally include a MIME type
590
598
  * in the format `data:<mimeType>;base64,<data>`.
@@ -662,11 +670,13 @@ declare const throttleSignal: <T>(src: Signal<T>, ms?: number, opts?: {
662
670
  */
663
671
  declare const formatDate: (date: Date, format?: string) => string;
664
672
  /**
665
- * Formats the given date into a localized string representation in the format 'day month year'.
666
- * The month is localized for 'ru-RU' locale and abbreviated.
673
+ * Formats the given date into a `day month year` string using the `ru-RU` locale.
674
+ * The month is abbreviated and normalized without a trailing dot.
675
+ *
676
+ * Despite the generic name, this helper is intentionally Russian-locale-specific.
667
677
  *
668
678
  * @param {Date} date - Date object to format.
669
- * @return {string} A string representing the formatted date in the format 'day month year'.
679
+ * @return {string} A string representing the formatted date in the format `day month year`.
670
680
  */
671
681
  declare function formatToLocaledDate(date: Date): string;
672
682
  /**
@@ -742,11 +752,11 @@ declare const isObject: (val: unknown) => val is AnyDict;
742
752
  * - `json`: "[\"a\",\"b\"]" -> ["a", "b"]
743
753
  * - `multi`: reads repeated key values from query string (requires `key`)
744
754
  */
745
- declare const parseQueryArray: (val: unknown, mode: "comma" | "json" | "multi", key?: string) => string[];
755
+ declare const parseQueryArray: (val: unknown, mode: QueryArrayMode, key?: string) => string[];
746
756
  /**
747
757
  * Concatenates an array into a string according to selected mode.
748
758
  */
749
- declare const concatArray: (value: AnyType[], mode: "comma" | "json" | "multi", key?: string) => string;
759
+ declare const concatArray: (value: AnyType[], mode: QueryArrayMode, key?: string) => string;
750
760
 
751
761
  /**
752
762
  * Formats a number or a string containing a number by adding spaces as thousands separators.
@@ -791,6 +801,11 @@ declare function getAvailableHeight(el: Element, margin?: number): number;
791
801
  */
792
802
  declare function getChainedValue<T = unknown>(obj: unknown, path: string): T | undefined;
793
803
 
804
+ type AppendableQueryValue = QueryScalar | ReadonlyArray<QueryScalar> | null | undefined;
805
+ type ParseQueryParams = {
806
+ (query: string): Record<string, string>;
807
+ (query: string, arrayMode: QueryArrayMode): Record<string, string | string[]>;
808
+ };
794
809
  /**
795
810
  * Normalizes a given URL by removing redundant slashes, resolving dot segments,
796
811
  * and ensuring there are no trailing slashes at the end of the URL.
@@ -811,22 +826,36 @@ declare function normalizeUrl(url: string): string;
811
826
  */
812
827
  declare function fillUrlWithParams(template: string, params?: AnyDict): string;
813
828
  /**
814
- * Appends query parameters to the specified URL.
829
+ * Low-level URL helper for appending query parameters to an existing URL.
830
+ *
831
+ * Prefer `query.utils` for new code that needs a query-focused API, mixed per-field
832
+ * array modes, or object-level query merging. Use this helper directly when you already
833
+ * work with a concrete URL string and only need to append serialized params.
815
834
  *
816
835
  * @param {string} url Base URL to which query parameters will be added.
817
836
  * @param {Record<string, unknown>} [params] Optional object containing query parameter key-value pairs.
818
837
  * Keys with null or undefined values will be ignored.
838
+ * Array values are serialized according to `arrayMode`.
839
+ * @param {QueryArrayMode} [arrayMode='comma'] Array serialization strategy:
840
+ * - `comma`: stores arrays as `tags=a,b`
841
+ * - `json`: stores arrays as `tags=["a","b"]`
842
+ * - `multi`: stores arrays as `tags=a&tags=b`
819
843
  * @return {string} URL with appended query parameters.
820
844
  */
821
- declare function appendQueryParams(url: string, params?: Record<string, unknown>): string;
845
+ declare function appendQueryParams(url: string, params?: Record<string, AppendableQueryValue> | Query, arrayMode?: QueryArrayMode): string;
822
846
  /**
823
- * Parses a query string into an object containing key-value pairs.
847
+ * Low-level query-string parser.
848
+ *
849
+ * Prefer `query.utils` for new code that needs mixed per-field parsing modes or query-object
850
+ * workflows. Use this helper directly when parsing a plain query string with one shared array mode.
824
851
  *
825
852
  * @param {string} query - The query string to parse. May start with '?'.
826
- * @return {Record<string, string>} An object where each key is a query parameter name,
827
- * and the value is the corresponding value.
853
+ * @param {QueryArrayMode} [arrayMode] Optional array parsing mode. When provided, array-shaped values are
854
+ * parsed according to the specified encoding strategy.
855
+ * @return {Record<string, string | string[]>} An object where each key is a query parameter name,
856
+ * and the value is either a scalar string or an array of strings when array parsing is enabled.
828
857
  */
829
- declare function parseQueryParams(query: string): Record<string, string>;
858
+ declare const parseQueryParams: ParseQueryParams;
830
859
 
831
860
  /**
832
861
  * Constructs a query string from a given object and concatenation type.
@@ -837,9 +866,12 @@ declare function parseQueryParams(query: string): Record<string, string>;
837
866
  * - 'comma': Joins array elements with a comma.
838
867
  * - 'json': Serializes the array as a JSON string.
839
868
  * - 'multi': Creates multiple entries for array elements, each associated with the same key.
869
+ * @param {(key: string, value: unknown) => QueryArrayMode | undefined} [resolveConcatType] - Optional per-field
870
+ * array mode resolver. When it returns a mode for a specific key, that mode overrides `concatType`
871
+ * only for that field.
840
872
  * @returns {string} - Formed query string with keys and values encoded as URI components.
841
873
  */
842
- declare const makeQuery: (object: AnyDict, concatType: "comma" | "json" | "multi") => string;
874
+ declare const makeQuery: (object: AnyDict, concatType: QueryArrayMode, resolveConcatType?: (key: string, value: unknown) => QueryArrayMode | undefined) => string;
843
875
  /**
844
876
  * Compares two routes to determine if the actual route matches the route template.
845
877
  * Supports static and dynamic route matching with optional subroute consideration.
@@ -863,10 +895,95 @@ declare const compareRoutes: (actualRoute: string, pureRoute: string, withSubrou
863
895
  */
864
896
  declare const materializeRoutePath: (actualRoute: string, pureRoute: string) => string;
865
897
 
898
+ /**
899
+ * Recommended high-level entrypoint for query-string work in `internal`.
900
+ *
901
+ * Prefer this module for new code when you need to:
902
+ * - build query strings with mixed per-field array modes,
903
+ * - parse mixed query strings back into object form,
904
+ * - merge query param objects before serialization.
905
+ *
906
+ * Low-level helpers from `urls.utils` / `routes.utils` remain available for narrow cases.
907
+ */
908
+ /**
909
+ * Alias for `appendQueryParams` to keep query-related API discoverable from one module.
910
+ */
911
+ declare const appendQueryParamsByMode: typeof appendQueryParams;
912
+ /**
913
+ * Builds a query string using a default array mode with optional per-field overrides.
914
+ *
915
+ * @example
916
+ * ```ts
917
+ * buildQueryParams(
918
+ * { tags: ['a', 'b'], sort: ['name,asc', 'createdAt,desc'], page: 2 },
919
+ * 'comma',
920
+ * { sort: 'multi' },
921
+ * );
922
+ * // => 'tags=a%2Cb&page=2&sort=name%2Casc&sort=createdAt%2Cdesc'
923
+ * ```
924
+ */
925
+ declare function buildQueryParams(params: AnyDict, defaultArrayMode?: QueryArrayMode, fieldModes?: QueryFieldModes): string;
926
+ /**
927
+ * Parses query params using a default array mode with optional per-field overrides.
928
+ *
929
+ * @example
930
+ * ```ts
931
+ * parseQueryParamsByMode('tags=a%2Cb&sort=name%2Casc&sort=createdAt%2Cdesc&page=2', 'comma', {
932
+ * sort: 'multi',
933
+ * });
934
+ * // => { tags: ['a', 'b'], sort: ['name,asc', 'createdAt,desc'], page: '2' }
935
+ * ```
936
+ */
937
+ declare function parseQueryParamsByMode(query: string, defaultArrayMode?: QueryArrayMode, fieldModes?: QueryFieldModes): Record<string, string | string[]>;
938
+ /**
939
+ * Merges query param objects without mutating the inputs.
940
+ *
941
+ * Rules:
942
+ * - `next` overrides `base` by key,
943
+ * - `null` / `undefined` in `next` remove the key from the result,
944
+ * - arrays are replaced, not concatenated.
945
+ *
946
+ * @example
947
+ * ```ts
948
+ * mergeQueryParams(
949
+ * { page: 1, tags: ['a', 'b'], tenant: 'kg' },
950
+ * { page: 2, tenant: null, sort: ['name,asc'] },
951
+ * );
952
+ * // => { page: 2, tags: ['a', 'b'], sort: ['name,asc'] }
953
+ * ```
954
+ */
955
+ declare function mergeQueryParams(base?: AnyDict, next?: AnyDict): AnyDict;
956
+
957
+ /**
958
+ * Builds a typed sort token from a field name and direction.
959
+ */
960
+ declare function toSortToken<Field extends string>(sort: Field, order: SortDirection): SortToken<Field>;
961
+ /**
962
+ * Converts a sort rule object into a typed sort token.
963
+ */
964
+ declare function sortRuleToToken<Field extends string>(rule: SortRule<Field>): SortToken<Field>;
965
+ /**
966
+ * Parses a sort token into a sort rule object.
967
+ * Returns `null` for invalid or unsupported tokens.
968
+ */
969
+ declare function parseSortToken<Field extends string = string>(token: string): SortRule<Field> | null;
970
+ /**
971
+ * Normalizes single or multi-sort input into an array of valid sort rules.
972
+ */
973
+ declare function normalizeSortInput<Field extends string = string>(sort: SortInput<Field>): SortRule<Field>[];
974
+ /**
975
+ * Converts single or multi-sort input into typed sort tokens.
976
+ */
977
+ declare function sortInputToTokens<Field extends string = string>(sort: SortInput<Field>): SortToken<Field>[];
978
+
866
979
  /**
867
980
  * Recursively checks the equality of two objects, including nested structures and special cases
868
981
  * such as arrays, sets, maps, dates, and NaN.
869
982
  *
983
+ * `Map` and `Set` values are compared in iteration order because they are materialized into arrays
984
+ * before comparison. This keeps the helper predictable for transport/state snapshots, but it is not
985
+ * a mathematical set-equivalence check.
986
+ *
870
987
  * @param {AnyType} a - The first object to compare.
871
988
  * @param {AnyType} b - The second object to compare.
872
989
  * @param {Map} [seen=new Map()] - A map used to detect cyclic references
@@ -875,8 +992,19 @@ declare const materializeRoutePath: (actualRoute: string, pureRoute: string) =>
875
992
  */
876
993
  declare function deepEqual(a: AnyType, b: AnyType, seen?: Map<any, any>): boolean;
877
994
 
995
+ /**
996
+ * Generates a short pseudo-random identifier.
997
+ *
998
+ * This helper is intended for lightweight client-side use cases such as temporary
999
+ * DOM ids or ephemeral UI keys. It does not guarantee uniqueness and must not be
1000
+ * treated as a secure or globally unique identifier.
1001
+ *
1002
+ * @param {number} [limit=15] Desired identifier length.
1003
+ * @param {number} [radix=36] Radix passed to `Number.prototype.toString`.
1004
+ * @returns {string} Pseudo-random identifier string.
1005
+ */
878
1006
  declare const generateId: (limit?: number, radix?: number) => string;
879
1007
 
880
- export { BUILTIN_LANGS, CHANGE_LANG, CHANGE_THEME, CURRENT_DEVICE, REGISTER_LANG, SELECTED_LANG, SELECTED_THEME, TRANSLATION, VALIDATION_MESSAGES, appendQueryParams, base64ToBlob, compareRoutes, concatArray, copyText, debounceSignal, deepEqual, downloadByBlob, downloadByUrl, fillUrlWithParams, formatDate, formatToLocaledDate, formatToSpacedNumber, generateId, getAvailableHeight, getChainedValue, getCorrectedPosition, isDatePeriod, isNullable, isNumber, isObject, makeQuery, materializeRoutePath, normalizeUrl, parseQueryArray, parseQueryParams, parseToDate, parseToDatePeriod, provideLangs, reformatDateToISO, throttleSignal, toDate, truncate };
881
- export type { AnyDict, AnyType, Appearance, Devices, Direction, ElementEdges, ElementPosition, ElementRect, ElementSize, ErrorResponse, JsonObject, JsonPrimitive, JsonValue, Langs, LiteralOf, Mutable, Nullable, NullableProps, Nullish, OptionalExcept, PageableRequest, PageableResponse, Query, QueryParams, QueryScalar, RequiredExcept, RestMethods, SelectIconOption, SelectOption, SortToken, Themes, ValidationErrorData, ValidationMessages, ValueOf };
1008
+ export { BUILTIN_LANGS, CHANGE_LANG, CHANGE_THEME, CURRENT_DEVICE, REGISTER_LANG, SELECTED_LANG, SELECTED_THEME, TRANSLATION, VALIDATION_MESSAGES, appendQueryParams, appendQueryParamsByMode, base64ToBlob, buildQueryParams, compareRoutes, concatArray, copyText, debounceSignal, deepEqual, downloadByBlob, downloadByUrl, fillUrlWithParams, formatDate, formatToLocaledDate, formatToSpacedNumber, generateId, getAvailableHeight, getChainedValue, getCorrectedPosition, isDatePeriod, isNullable, isNumber, isObject, makeQuery, materializeRoutePath, mergeQueryParams, normalizeSortInput, normalizeUrl, parseQueryArray, parseQueryParams, parseQueryParamsByMode, parseSortToken, parseToDate, parseToDatePeriod, provideLangs, reformatDateToISO, sortInputToTokens, sortRuleToToken, throttleSignal, toDate, toSortToken, truncate };
1009
+ export type { AnyDict, AnyType, Appearance, Devices, Direction, ElementEdges, ElementPosition, ElementRect, ElementSize, ErrorResponse, JsonObject, JsonPrimitive, JsonValue, Langs, LiteralOf, Mutable, Nullable, NullableProps, Nullish, OptionalExcept, PageableRequest, PageableResponse, Query, QueryArrayMode, QueryFieldModes, QueryParams, QueryScalar, RequiredExcept, RestMethods, SelectIconOption, SelectOption, SortDirection, SortInput, SortRule, SortToken, Themes, ValidationErrorData, ValidationMessages, ValueOf };
882
1010
  //# sourceMappingURL=reforgium-internal.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"reforgium-internal.mjs","sources":["../../../../libs/internal/src/tokens/locale.token.ts","../../../../libs/internal/src/tokens/theme.token.ts","../../../../libs/internal/src/tokens/device.token.ts","../../../../libs/internal/src/tokens/validation-messages.token.ts","../../../../libs/internal/src/utils/web.utils.ts","../../../../libs/internal/src/utils/timers.utils.ts","../../../../libs/internal/src/utils/date.utils.ts","../../../../libs/internal/src/utils/types.utils.ts","../../../../libs/internal/src/utils/format.utils.ts","../../../../libs/internal/src/utils/positions.utils.ts","../../../../libs/internal/src/utils/available-height.utils.ts","../../../../libs/internal/src/utils/get-chained-value.utils.ts","../../../../libs/internal/src/utils/urls.utils.ts","../../../../libs/internal/src/utils/routes.utils.ts","../../../../libs/internal/src/utils/deep-equal.utils.ts","../../../../libs/internal/src/utils/generate.utils.ts","../../../../libs/internal/src/reforgium-internal.ts"],"sourcesContent":["import { EnvironmentProviders, InjectionToken, makeEnvironmentProviders, Signal } from '@angular/core';\n\r\n/**\n * Built-in language codes.\n *\n * @type {'ru' | 'kg' | 'en'}\n * 'ru' - Russian language\n * 'kg' - Kyrgyz language\n * 'en' - English language\n */\nexport type BuiltInLangs = 'ru' | 'kg' | 'en';\n\n/**\n * Extensible language code type.\n *\n * Includes built-in languages and allows registering custom codes via providers.\n */\nexport type Langs = BuiltInLangs | (string & {});\n\n/**\n * Built-in languages always available in the registry.\n */\nexport const BUILTIN_LANGS: readonly BuiltInLangs[] = ['ru', 'kg', 'en'];\n\n/**\n * Multi-token for registering additional language codes.\n *\n * Example:\n * ```ts\n * providers: [provideLangs('de', 'fr')]\n * ```\n */\nexport const REGISTER_LANG = new InjectionToken<string[]>('RE_REGISTER_LANG', { factory: () => [] });\n\n/**\n * Registers additional language codes in DI.\n */\nexport function provideLangs(...langs: string[]): EnvironmentProviders {\n return makeEnvironmentProviders(langs.map((lang) => ({ provide: REGISTER_LANG, useValue: lang, multi: true })));\n}\n\r\n/**\r\n * Translation provider interface for managing translations and namespaces.\r\n * Provides methods to retrieve translated messages and load translation namespaces.\r\n */\r\ntype TranslationProvider = {\r\n /**\r\n * Retrieves translated message by key with optional parameter interpolation.\r\n *\r\n * @param {string} message - Translation key to retrieve.\r\n * @param {Record<string, string>} [params] - Optional parameters for interpolation in translation.\r\n * @return {string} Translated message with applied parameters or original key if translation not found.\r\n */\r\n get: (message: string, params?: Record<string, string>) => string;\r\n /**\r\n * Loads translation namespace asynchronously.\r\n *\r\n * @param {string} ns - Namespace identifier to load.\r\n * @return {Promise<void>} Promise that resolves when namespace is loaded successfully.\r\n */\r\n loadNamespace: (ns: string) => Promise<void>;\r\n};\r\n\r\n/**\r\n * Provider for changing the application lang.\r\n *\r\n * Supplies a method to programmatically switch between supported languages.\r\n *\r\n * @example\r\n * ```ts\r\n * const changeLang = inject(CHANGE_LANGE);\r\n * changeLang('ru');\r\n * ```\r\n */\r\ntype ChangeLangProvider = (lang: Langs) => void;\r\n\r\n/**\r\n * Injection token for the current application language as a Signal.\r\n * Provides reactive access to the currently selected language.\r\n * Can be overridden in app.config with a custom provider.\r\n *\r\n * @type {InjectionToken<Signal<Langs>>}\r\n */\r\nexport const SELECTED_LANG = new InjectionToken<Signal<Langs>>('RE_SELECTED_LANG');\r\n\r\n/**\r\n * Injection token for language change provider.\r\n * Provides access to method for changing the current application language.\r\n * Can be overridden in app.config with a custom provider.\r\n *\r\n * @type {InjectionToken<ChangeLangProvider>}\r\n */\r\nexport const CHANGE_LANG = new InjectionToken<ChangeLangProvider>('RE_CHANGE_LANG');\r\n\r\n/**\r\n * Injection token for translation provider.\r\n * Provides access to translation methods for message retrieval and namespace loading.\r\n *\r\n * @type {InjectionToken<TranslationProvider>}\r\n */\r\nexport const TRANSLATION = new InjectionToken<TranslationProvider>('RE_GET_LANG');\r\n","import { InjectionToken, Signal } from '@angular/core';\r\n\r\n/**\r\n * List of supported application themes.\r\n *\r\n * `'light'` — light theme\r\n * `'dark'` — dark theme\r\n */\r\nexport type Themes = 'light' | 'dark';\r\n\r\n/**\r\n * Provider for changing the application theme.\r\n *\r\n * Supplies a method to programmatically switch between supported themes.\r\n *\r\n * @example\r\n * ```ts\r\n * const changeTheme = inject(CHANGE_THEME);\r\n * changeTheme('dark');\r\n * ```\r\n */\r\ntype ChangeThemeProvider = (lang: Themes) => void;\r\n\r\n/**\r\n * Current application theme as Signal.\r\n * Can be overridden in app.config with a custom provider.\r\n */\r\nexport const SELECTED_THEME = new InjectionToken<Signal<Themes>>('RE_SELECTED_THEME');\r\nexport const CHANGE_THEME = new InjectionToken<ChangeThemeProvider>('RE_CHANGE_THEME');\r\n","import { InjectionToken, Signal } from '@angular/core';\r\n\r\n/**\r\n * Supported device types for responsive design and device-specific logic.\r\n *\r\n * @typedef {('mobile' | 'tablet' | 'desktop-s' | 'desktop')} Devices\r\n *\r\n * Possible values:\r\n * - 'mobile' - Mobile devices (smartphones)\r\n * - 'tablet' - Tablet devices\r\n * - 'desktop-s' - Small desktop screens\r\n * - 'desktop' - Standard desktop screens\r\n */\r\nexport type Devices = 'mobile' | 'tablet' | 'desktop-s' | 'desktop';\r\n\r\n/**\r\n * Injection token for the current device type as a Signal.\r\n *\r\n * Provides reactive access to the current device type throughout the application.\r\n * Can be overridden in app.config with a custom provider to supply device detection logic.\r\n *\r\n * @example\r\n * ```typescript\r\n * // In app.config.ts\r\n * providers: [\r\n * {\r\n * provide: CURRENT_DEVICE,\r\n * useValue: signal<Devices>('mobile')\r\n * }\r\n * ]\r\n *\r\n * // In a component or service\r\n * private readonly currentDevice = inject(CURRENT_DEVICE);\r\n * ```\r\n */\r\nexport const CURRENT_DEVICE = new InjectionToken<Signal<Devices>>('RE_CURRENT_DEVICE');\r\n","import { InjectionToken } from '@angular/core';\r\n\r\n/**\r\n * Represents flexible validation error data without enforced fields.\r\n * Contains common properties like requiredLength and actualLength\r\n * and allows additional string properties through index signature.\r\n *\r\n * @property {string} requiredLength - The required length for validation.\r\n * @property {string} actualLength - The actual length of the validated value.\r\n */\r\nexport type ValidationErrorData = {\r\n requiredLength: string;\r\n actualLength: string;\r\n [key: string]: string;\r\n};\r\n\r\n/**\r\n * Map of validation error names to message generator functions.\r\n * Each key represents an error name, and the value is a function\r\n * that takes validation error data and returns a formatted error message.\r\n *\r\n * @example\r\n * const messages: ValidationMessages = {\r\n * minlength: (error) => `Minimum length is ${error.requiredLength}`\r\n * };\r\n */\r\nexport type ValidationMessages = Record<string, (error: ValidationErrorData) => string>;\r\n\r\n/**\r\n * Injection token for a validation messages map.\r\n * Can be overridden in feature modules to provide custom validation messages.\r\n * Defaults to an empty object when not provided.\r\n *\r\n * @example\r\n * // In a feature module:\r\n * providers: [\r\n * {\r\n * provide: VALIDATION_MESSAGES,\r\n * useValue: {\r\n * required: () => 'This field is required',\r\n * minlength: (error) => `Min length: ${error.requiredLength}`\r\n * }\r\n * }\r\n * ]\r\n */\r\nexport const VALIDATION_MESSAGES = new InjectionToken<ValidationMessages>('RE_VALIDATION_MESSAGES', {\r\n providedIn: 'root',\r\n factory: () => ({}),\r\n});\r\n","/**\r\n * Downloads a file from a Blob object and prompts the user to save it.\r\n *\r\n * @param {Blob} blob - Blob object representing the file to download.\r\n * @param {string} [fileName] - Optional. Name for the downloaded file.\r\n * If not specified, the current timestamp will be used as the filename.\r\n * @return {void} Does not return a value.\r\n */\r\nexport function downloadByBlob(blob: Blob, fileName?: string | undefined): void {\r\n const win = window;\r\n\r\n try {\n const url = win.URL.createObjectURL(blob);\n\n downloadByUrl(url, fileName);\n setTimeout(() => win.URL.revokeObjectURL(url), 200);\n } catch (e) {\n throw new Error(`Download error: ${String(e)}`);\n }\n}\n\r\n/**\r\n * Initiates a file download for the given URL. Optionally, a custom filename can be specified.\r\n *\r\n * @param {string} url - URL of the file to download.\r\n * @param {string} [filename] - Desired name for the downloaded file.\r\n * If not specified, a timestamp-based name will be used.\r\n * @return {void} The function does not return a value.\r\n */\r\nexport function downloadByUrl(url: string, filename?: string): void {\r\n const win = window;\r\n const a = document.createElement('a');\r\n\r\n a.style.display = 'none';\r\n a.href = url;\r\n a.download = filename || `${new Date().toISOString()}`;\r\n a.rel = 'noopener';\r\n\r\n win.document.body.appendChild(a);\r\n a.click();\r\n win.document.body.removeChild(a);\r\n}\r\n\r\n/**\r\n * Copies the specified text to the clipboard. Uses the Clipboard API if available,\r\n * otherwise falls back to `document.execCommand`.\r\n *\r\n * @param {string} text - The text to copy to the clipboard.\r\n * @return {Promise<boolean>} A promise that resolves to a boolean indicating whether\r\n * the text copying was successful.\r\n */\r\nexport async function copyText(text: string): Promise<boolean> {\r\n const win = window;\r\n\r\n try {\r\n if (win.navigator.clipboard?.['writeText']) {\r\n await win.navigator.clipboard.writeText(text);\r\n\r\n return true;\r\n }\r\n } catch (err) {\r\n // eslint-disable-next-line no-console\r\n console.warn('Clipboard API failed, fallback to execCommand', err);\r\n }\r\n\r\n const ta = win.document.createElement('textarea');\r\n\r\n ta.value = text;\r\n ta.style.position = 'fixed';\r\n ta.style.opacity = '0';\r\n win.document.body.appendChild(ta);\r\n ta.focus();\r\n ta.select();\r\n\r\n const ok = win.document.execCommand?.('copy') ?? false;\r\n\r\n win.document.body.removeChild(ta);\r\n\r\n return ok;\r\n}\r\n\r\n/**\r\n * Converts a Base64 encoded string to a Blob object.\r\n *\r\n * @param {string} base64 - Base64 encoded string. Can optionally include a MIME type\r\n * in the format `data:<mimeType>;base64,<data>`.\r\n * @param {string} [mimeType=''] - MIME type of the data. Optional parameter, will be overridden\r\n * if the `base64` string includes a MIME type.\r\n * @return {Blob} A Blob object created from the Base64 string.\r\n */\r\nexport function base64ToBlob(base64: string, mimeType: string = ''): Blob {\r\n const matches = base64.match(/^data:(.+);base64,(.*)$/);\r\n const data = matches ? matches[2] : base64;\r\n const mime = matches ? matches[1] : mimeType;\r\n\r\n const byteChars = atob(data);\r\n const byteNumbers = new Array(byteChars.length);\r\n\r\n for (let i = 0; i < byteChars.length; i++) {\r\n byteNumbers[i] = byteChars.charCodeAt(i);\r\n }\r\n\r\n const byteArray = new Uint8Array(byteNumbers);\r\n\r\n return new Blob([byteArray], { type: mime });\r\n}\r\n","import { effect, Injector, Signal, signal, untracked } from '@angular/core';\r\n\r\nimport { AnyType } from '../models';\r\n\r\n/**\r\n * Creates a debounced signal that delays updates from the source signal.\r\n * The output signal will only update after the specified delay has passed without new values.\r\n *\r\n * @template T - The type of the signal value\r\n * @param {Signal<T>} src - The source signal to debounce\r\n * @param {number} [ms=150] - The debounce delay in milliseconds (default: 150ms)\r\n * @param {Object} [opts] - Optional configuration\r\n * @param {Injector} [opts.injector] - Optional injector for the effect context\r\n * @returns {Signal<T>} A readonly signal that emits debounced values from the source\r\n *\r\n * @example\r\n * ```typescript\r\n * const searchQuery = signal('');\r\n * const debouncedQuery = debounceSignal(searchQuery, 300);\r\n *\r\n * effect(() => {\r\n * console.log('Debounced value:', debouncedQuery());\r\n * });\r\n * ```\r\n */\r\nexport const debounceSignal = <T>(src: Signal<T>, ms = 150, opts?: { injector?: Injector }): Signal<T> => {\r\n const out = signal(src());\r\n let timeoutRef: AnyType;\r\n\r\n effect(\r\n (onCleanup) => {\r\n const v = src();\r\n\r\n if (Object.is(v, out())) {\r\n return;\r\n }\r\n\r\n untracked(() => {\r\n clearTimeout(timeoutRef);\r\n timeoutRef = setTimeout(() => out.set(v), ms);\r\n });\r\n\r\n onCleanup(() => clearTimeout(timeoutRef));\r\n },\r\n { injector: opts?.injector },\r\n );\r\n\r\n return out.asReadonly();\r\n};\r\n\r\n/**\r\n * Creates a throttled signal that limits the rate of updates from the source signal.\r\n * The output signal will emit the first value immediately, then wait for the specified delay\r\n * before allowing subsequent updates. If values are emitted during the waiting period,\r\n * the last value will be queued and emitted after the delay.\r\n *\r\n * @template T - The type of the signal value\r\n * @param {Signal<T>} src - The source signal to throttle\r\n * @param {number} [ms=100] - The throttle delay in milliseconds (default: 100ms)\r\n * @param {Object} [opts] - Optional configuration\r\n * @param {Injector} [opts.injector] - Optional injector for the effect context\r\n * @returns {Signal<T>} A readonly signal that emits throttled values from the source\r\n *\r\n * @example\r\n * ```typescript\r\n * const scrollPosition = signal(0);\r\n * const throttledPosition = throttleSignal(scrollPosition, 200);\r\n *\r\n * effect(() => {\r\n * console.log('Throttled position:', throttledPosition());\r\n * });\r\n * ```\r\n */\r\nexport const throttleSignal = <T>(src: Signal<T>, ms = 100, opts?: { injector?: Injector }): Signal<T> => {\r\n const out = signal(src());\r\n let last = 0;\r\n let queued: T | undefined;\r\n let timeoutRef: AnyType;\r\n\r\n const flush = () => {\r\n if (queued !== undefined) {\r\n out.set(queued);\r\n queued = undefined;\r\n last = performance.now();\r\n }\r\n\r\n timeoutRef = 0;\r\n };\r\n\r\n effect(\r\n (onCleanup) => {\r\n const v = src();\r\n\r\n if (Object.is(v, out())) {\r\n return;\r\n }\r\n\r\n untracked(() => {\r\n const now = performance.now();\r\n\r\n if (now - last >= ms) {\r\n out.set(v);\r\n last = now;\r\n\r\n clearTimeout(timeoutRef);\r\n timeoutRef = null;\r\n queued = undefined;\r\n } else {\r\n queued = v;\r\n timeoutRef = setTimeout(flush, ms - (now - last));\r\n }\r\n });\r\n\r\n onCleanup(() => {\r\n if (timeoutRef) {\r\n clearTimeout(timeoutRef);\r\n timeoutRef = null;\r\n }\r\n\r\n queued = undefined;\r\n });\r\n },\r\n { injector: opts?.injector },\r\n );\r\n\r\n return out.asReadonly();\r\n};\r\n","const pad = (n: number) => n.toString().padStart(2, '0');\r\n\r\n/**\r\n * Formats a Date object into a string of the given format.\r\n *\r\n * @param {Date} date - Date object to format.\r\n * @param {string} [format='yyyy-MM-dd'] - String format to apply. Defaults to 'yyyy-MM-dd'.\r\n * Supported tokens in the format string:\r\n * - yyyy: Full year (e.g., 2023)\r\n * - MM: Month with leading zero (01-12)\r\n * - dd: Day of the month with leading zero (01-31)\r\n * - HH: Hour in 24-hour format with leading zero (00-23)\r\n * - mm: Minutes with leading zero (00-59)\r\n * - ss: Seconds with leading zero (00-59)\r\n *\r\n * @returns {string} Formatted date string. Returns an empty string if the input date is invalid.\r\n */\r\nexport const formatDate = (date: Date, format: string = 'yyyy-MM-dd'): string => {\r\n if (isNaN(date['getTime']?.())) {\r\n return '';\r\n }\r\n\r\n const tokens: Record<string, string> = {\r\n yyyy: date.getFullYear().toString(),\r\n MM: pad(date.getMonth() + 1),\r\n dd: pad(date.getDate()),\r\n HH: pad(date.getHours()),\r\n mm: pad(date.getMinutes()),\r\n ss: pad(date.getSeconds()),\r\n };\r\n let formatted = format;\r\n\r\n for (const [token, value] of Object.entries(tokens)) {\r\n formatted = formatted.replace(new RegExp(token, 'g'), value);\r\n }\r\n\r\n return formatted;\r\n};\r\n\r\n/**\r\n * Formats the given date into a localized string representation in the format 'day month year'.\r\n * The month is localized for 'ru-RU' locale and abbreviated.\r\n *\r\n * @param {Date} date - Date object to format.\r\n * @return {string} A string representing the formatted date in the format 'day month year'.\r\n */\r\nexport function formatToLocaledDate(date: Date): string {\r\n const day = date.getDate();\r\n const month = date.toLocaleString('ru-RU', { month: 'short' }).replace('.', '');\r\n const year = date.getFullYear();\r\n\r\n return `${day} ${month} ${year}`;\r\n}\r\n\r\n/**\r\n * Parses a date from a string based on the given mask.\r\n * Supports dd, MM, yyyy, HH, mm, ss.\r\n * Any delimiters: '.', '/', '-', ' '.\r\n *\r\n * @param {string} value - source date string\r\n * @param {string} format - mask, e.g., \"dd.MM.yyyy\"\r\n * @returns {Date|null}\r\n */\r\nexport const parseToDate = (value: unknown, format: string = 'dd.MM.yyyy'): Date | null => {\r\n if (typeof value !== 'string' || !format) {\r\n return null;\r\n }\r\n\r\n const tokens = format.match(/(yyyy|MM|dd|HH|mm|ss)/g);\r\n const parts = value.split(/\\D+/).filter(Boolean);\r\n\r\n if (!tokens || tokens.length !== parts.length) {\r\n return null;\r\n }\r\n\r\n let year = 1970,\r\n month = 0,\r\n day = 1,\r\n hours = 0,\r\n minutes = 0,\r\n seconds = 0;\r\n\r\n const map: Record<string, (index: number) => void> = {\r\n yyyy: (index: number) => (year = +parts[index]),\r\n MM: (index: number) => (month = +parts[index] - 1),\r\n dd: (index: number) => (day = +parts[index]),\r\n HH: (index: number) => (hours = +parts[index]),\r\n mm: (index: number) => (minutes = +parts[index]),\r\n ss: (index: number) => (seconds = +parts[index]),\r\n };\r\n\r\n tokens.forEach((token, i) => map[token]?.(i));\r\n\r\n const date = new Date(year, month, day, hours, minutes, seconds);\r\n\r\n if (date.getFullYear() !== year || date.getMonth() !== month || date.getDate() !== day) {\r\n return null;\r\n }\r\n\r\n return date;\r\n};\r\n\r\n/**\r\n * Parses a string representation of two dates into a tuple of `Date` objects or `null` values.\r\n *\r\n * This function attempts to extract and parse two date values from the input string\r\n * based on the provided date format. If parsing is unsuccessful, the returned tuple will\r\n * consist of `null` values. The default expected date format is `dd.MM.yyyy`, but it\r\n * can be changed.\r\n *\r\n * @param {string | null} value - String containing date representations to parse.\r\n * If `null`, the function will return `[null, null]`.\r\n * @param {string} [format='dd.MM.yyyy'] - Date format used for parsing.\r\n * Supports `yyyy`, `MM`, `dd`, `HH`, `mm`, and `ss`.\r\n * @returns {[Date | null, Date | null]} A tuple where the first element is the parsed start date\r\n * and the second element is the parsed end date. If parsing fails, both elements will be `null`.\r\n */\r\nexport const parseToDatePeriod = (value: unknown, format: string = 'dd.MM.yyyy'): [Date | null, Date | null] => {\r\n if (typeof value !== 'string' || !format) {\r\n return [null, null];\r\n }\r\n\r\n const pattern = format\r\n .replace('yyyy', '\\\\d{4}')\r\n .replace('MM', '\\\\d{2}')\r\n .replace('dd', '\\\\d{2}')\r\n .replace('HH', '\\\\d{2}')\r\n .replace('mm', '\\\\d{2}')\r\n .replace('ss', '\\\\d{2}');\r\n const regex = new RegExp(`(${pattern})[^0-9]+(${pattern})`);\r\n const match = value.match(regex);\r\n\r\n if (match) {\r\n const from = parseToDate(match[1], format);\r\n const to = parseToDate(match[2], format);\r\n\r\n return [from, to];\r\n } else {\r\n return [null, null];\r\n }\r\n};\r\n\r\n/**\r\n * Determines if the given value is a date period.\r\n *\r\n * A date period is represented as an array containing exactly two Date instances.\r\n * Both elements of the array must be valid Date objects (i.e., not `Invalid Date`).\r\n *\r\n * @param {unknown} value - Value to check.\r\n * @returns {value is [Date, Date]} - Returns `true` if the value is a valid date period, otherwise `false`.\r\n */\r\nexport const isDatePeriod = (value: unknown): value is [Date, Date] =>\r\n Array.isArray(value) && value.length === 2 && value.every((it) => it instanceof Date && !isNaN(it.getTime()));\r\n\r\n/**\r\n * Converts various data types to a Date object.\r\n *\r\n * @param {unknown} v - Value to convert. Can be a Date object,\r\n * a number (timestamp), or a string containing a valid date.\r\n * @returns {Date} Date object. If conversion is impossible, returns Invalid Date.\r\n */\r\nexport const toDate = (v: unknown): Date => {\r\n if (v instanceof Date) return v;\r\n if (typeof v === 'number') return new Date(v);\r\n if (typeof v === 'string') return new Date(v);\r\n\r\n return new Date(NaN);\r\n};\r\n\r\n/**\r\n * Converts a date string from a given format to ISO (UTC).\r\n * Example:\r\n * reformatDateToISO(\"24.11.2025\", \"dd.MM.yyyy\")\r\n * → \"2025-11-24T00:00:00.000Z\"\r\n */\r\nexport function reformatDateToISO(dateStr: string, mask: string): string | null {\r\n if (!dateStr || !mask) {\r\n return null;\r\n }\r\n\r\n const partsFmt = mask.split(/[^A-Za-z]+/g);\r\n const partsVal = dateStr.split(/[^0-9]+/g);\r\n\r\n if (!partsFmt.length || partsFmt.length !== partsVal.length) {\r\n return null;\r\n }\r\n\r\n let day = 1;\r\n let month = 1;\r\n let year = 1970;\r\n\r\n for (let i = 0; i < partsFmt.length; i++) {\r\n const fmt = partsFmt[i];\r\n const raw = partsVal[i];\r\n const val = Number.parseInt(raw, 10);\r\n\r\n if (Number.isNaN(val)) return null;\r\n\r\n switch (fmt) {\r\n case 'dd':\r\n day = val;\r\n break;\r\n case 'MM':\r\n month = val;\r\n break;\r\n case 'yyyy':\r\n year = val;\r\n break;\r\n case 'yy':\r\n year = 2000 + val;\r\n break;\r\n default:\r\n return null;\r\n }\r\n }\r\n\r\n if (month < 1 || month > 12 || day < 1 || day > 31) {\r\n return null;\r\n }\r\n\r\n const date = new Date(Date.UTC(year, month - 1, day));\r\n\r\n if (date.getUTCFullYear() !== year || date.getUTCMonth() !== month - 1 || date.getUTCDate() !== day) {\r\n return null;\r\n }\r\n\r\n return date.toISOString();\r\n}\r\n","import { AnyDict, AnyType } from '../models';\n\n/**\n * Determines if the given value is null/undefined.\n * Optionally treats an empty string as nullable.\n */\nexport const isNullable = (value: unknown, withEmptyString: boolean = false): value is null | undefined =>\n value === null || value === undefined || (withEmptyString ? value === '' : false);\n\n/**\n * Checks if the value is numeric.\n * If `fromString=true`, also accepts numeric strings.\n */\nexport const isNumber = (value: unknown, fromString: boolean = false): value is number => {\n if (typeof value === 'number') {\n return !isNaN(value) && isFinite(value);\n }\n\n if (fromString && typeof value === 'string' && value.trim() !== '') {\n return !isNaN(Number(value));\n }\n\n return false;\n};\n\n/**\n * Checks whether a value is a plain object (non-null and not an array).\n */\nexport const isObject = (val: unknown): val is AnyDict =>\n typeof val === 'object' && val !== null && !Array.isArray(val);\n\n/**\n * Parses an array from a query value using selected mode.\n *\n * - `comma`: \"a,b,c\" -> [\"a\", \"b\", \"c\"]\n * - `json`: \"[\\\"a\\\",\\\"b\\\"]\" -> [\"a\", \"b\"]\n * - `multi`: reads repeated key values from query string (requires `key`)\n */\nexport const parseQueryArray = (val: unknown, mode: 'comma' | 'json' | 'multi', key?: string): string[] => {\n if (!val || typeof val !== 'string') {\n return [];\n }\n\n if (mode === 'comma') {\n return val\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n }\n\n if (mode === 'json') {\n try {\n const parsed = JSON.parse(val);\n\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n }\n\n if (mode === 'multi') {\n if (!key) {\n throw new Error('Key required for multi-part mode');\n }\n\n const params = new URLSearchParams(val);\n\n return params.getAll(key);\n }\n\n throw new Error('Unknown mode');\n};\n\n/**\n * Concatenates an array into a string according to selected mode.\n */\nexport const concatArray = (value: AnyType[], mode: 'comma' | 'json' | 'multi', key?: string): string => {\n if (mode === 'multi' && !key) {\n throw new Error('Key required for multi-part mode');\n }\n\n return mode === 'json'\n ? JSON.stringify(value)\n : mode === 'comma'\n ? value.join(',')\n : value.map((item) => `${key}=${item}`).join('&');\n};\r\n","/**\r\n * Formats a number or a string containing a number by adding spaces as thousands separators.\r\n *\r\n * @param {number|string} num - The number or string to format.\r\n * If the input value is null, undefined, or an invalid number, an empty string is returned.\r\n * @return {string} Formatted string with spaces as thousands separators, or an empty string\r\n * if the input is invalid.\r\n */\r\nexport function formatToSpacedNumber(num: number | string): string {\r\n const stringed = String(num).replaceAll(' ', '');\r\n\r\n if (num === null || num === undefined || Number.isNaN(+stringed)) {\r\n return '';\r\n }\r\n\r\n const str = String(num).replace(/\\s+/g, '');\r\n\r\n return str.replace(/\\B(?=(\\d{3})+(?!\\d))/g, ' ');\r\n}\r\n\r\n/**\r\n * Truncates a string to the specified number of characters and adds an ellipsis ('…')\r\n * if the string exceeds the limit.\r\n *\r\n * @param {string} text - The text to truncate.\r\n * @param {number} limit - Maximum allowed string length.\r\n * @returns {string} Truncated string with an ellipsis if length exceeds the limit,\r\n * or the original string otherwise.\r\n */\r\nexport const truncate = (text: string, limit: number): string => {\r\n return text.length > limit ? text.slice(0, limit) + '…' : text;\r\n};\r\n","import { Direction, ElementEdges, ElementPosition, ElementSize } from '../models';\r\n\r\ntype Directions = Direction | [Direction] | [Direction, Direction];\r\n\r\nexport const getCorrectedPosition = (\r\n anchor: ElementPosition & Partial<ElementSize>,\r\n triggerSize: ElementSize,\r\n boundBox: ElementEdges,\r\n directions: Directions,\r\n offset: number,\r\n): ElementPosition => {\r\n const directionsArray = Array.isArray(directions) ? directions : [directions];\r\n const dir = getDirMap(directionsArray);\r\n const x = anchor.x;\r\n const y = anchor.y;\r\n\r\n anchor.width = anchor.width ?? 0;\r\n anchor.height = anchor.height ?? 0;\r\n\r\n const anchorBottom = y + anchor.height;\r\n const anchorRight = x + anchor.width;\r\n\r\n const yTop = dir.horizontal ? y : y - offset - triggerSize.height;\r\n const yBottom = dir.horizontal ? anchorBottom - triggerSize.height : anchorBottom + offset;\r\n const yCenter = anchor.y + anchor.height / 2 - triggerSize.height / 2;\r\n\r\n const xLeft = x - offset - triggerSize.width;\r\n const xRight = anchorRight + offset;\r\n const xCenter = anchor.x + anchor.width / 2 - triggerSize.width / 2;\r\n\r\n if (dir.top) {\r\n const canFit = yTop > boundBox.top;\r\n\r\n dir.top = canFit;\r\n dir.bottom = !canFit;\r\n }\r\n\r\n if (dir.bottom) {\r\n const canFit = yBottom + triggerSize.height < boundBox.bottom;\r\n\r\n dir.top = !canFit;\r\n dir.bottom = canFit;\r\n }\r\n\r\n if (dir.left) {\r\n const canFit = xLeft > boundBox.left;\r\n\r\n dir.left = canFit;\r\n dir.right = !canFit;\r\n }\r\n\r\n if (dir.right) {\r\n const canFit = xRight + triggerSize.width < boundBox.right;\r\n\r\n dir.left = !canFit;\r\n dir.right = canFit;\r\n }\r\n\r\n const xCorrected = dir.left ? xLeft : dir.right ? xRight : xCenter;\r\n const yCorrected = dir.top ? yTop : dir.bottom ? yBottom : yCenter;\r\n\r\n return { x: xCorrected, y: yCorrected };\r\n};\r\n\r\nconst getDirMap = (directions: Direction[]) => {\r\n const top = directions.includes('top');\r\n const right = directions.includes('right');\r\n const bottom = directions.includes('bottom');\r\n const left = directions.includes('left');\r\n\r\n return {\r\n top,\r\n right,\r\n bottom,\r\n left,\r\n vertical: top || bottom,\r\n horizontal: right || left,\r\n };\r\n};\r\n","/**\r\n * Calculates the available vertical space below the given element in the viewport.\r\n *\r\n * @param {Element} el - DOM element for which to calculate the available height below.\r\n * @param {number} [margin=20] - Optional margin subtracted from the calculated available height.\r\n * @return {number} Available height in pixels below the element, taking margin into account.\r\n * Returns 0 if there is no available space.\r\n */\r\nexport function getAvailableHeight(el: Element, margin: number = 20): number {\r\n const rect = el.getBoundingClientRect();\r\n const bottom = rect.bottom;\r\n const windowHeight = window.innerHeight;\r\n const available = windowHeight - bottom - margin;\r\n\r\n return available > 0 ? available : 0;\r\n}\r\n","/**\r\n * Retrieves a value by a nested path within an object or array.\r\n * The path is specified as a dot-delimited string.\r\n *\r\n * @param obj The object or array to traverse.\r\n * @param path A dot-delimited string specifying the path to retrieve the value.\r\n * @return The value found at the specified path, or undefined if the path does not exist or is invalid.\r\n */\r\nexport function getChainedValue<T = unknown>(obj: unknown, path: string): T | undefined {\r\n if (!obj) {\r\n return undefined;\r\n }\r\n\r\n return path.split('.').reduce((acc, key) => {\r\n if (acc == null) {\r\n return undefined;\r\n }\r\n\r\n if (Array.isArray(acc)) {\r\n const index = Number(key);\r\n\r\n return isNaN(index) ? undefined : acc[index];\r\n }\r\n\r\n if (typeof acc === 'object') {\r\n return (acc as Record<string, unknown>)[key];\r\n }\r\n\r\n return undefined;\r\n }, obj as unknown) as T | undefined;\r\n}\r\n","import { AnyDict } from '../models';\r\n\r\n/**\r\n * Normalizes a given URL by removing redundant slashes, resolving dot segments,\r\n * and ensuring there are no trailing slashes at the end of the URL.\r\n *\r\n * @param {string} url - The URL string to normalize.\r\n * @return {string} - The normalized URL string.\r\n */\r\nexport function normalizeUrl(url: string): string {\r\n const [protocol, rest] = url.split('://');\r\n const cleaned = (rest ?? protocol)\r\n .replace(/\\/{2,}/g, '/')\r\n .replace(/\\/\\.\\//g, '/')\r\n .replace(/\\/$/, '');\r\n\r\n return rest ? `${protocol}://${cleaned}` : cleaned;\r\n}\r\n\r\n/**\r\n * Replaces placeholders in the provided URL template with corresponding values from the params object.\r\n * Placeholders are defined as `:key` in the template string.\r\n *\r\n * @param {string} template URL template containing placeholders to replace.\r\n * @param {AnyDict} [params] Optional dictionary containing key-value pairs.\r\n * Keys correspond to placeholders in the template, and values will replace them.\r\n * @return {string} URL with placeholders replaced by corresponding values from the params object.\r\n * Defaults to the original template if params is not provided.\r\n */\r\nexport function fillUrlWithParams(template: string, params?: AnyDict): string {\r\n if (!params) {\r\n return template;\r\n }\r\n\r\n return template.replace(/:([a-zA-Z0-9_]+)/g, (_, k) => encodeURIComponent(params[k] ?? ''));\r\n}\r\n\r\n/**\r\n * Appends query parameters to the specified URL.\r\n *\r\n * @param {string} url Base URL to which query parameters will be added.\r\n * @param {Record<string, unknown>} [params] Optional object containing query parameter key-value pairs.\r\n * Keys with null or undefined values will be ignored.\r\n * @return {string} URL with appended query parameters.\r\n */\r\nexport function appendQueryParams(url: string, params?: Record<string, unknown>): string {\r\n if (!params || !Object.keys(params).length) return url;\r\n\r\n const [base, query] = url.split('?', 2);\r\n const searchParams = new URLSearchParams(query || '');\r\n\r\n for (const [key, value] of Object.entries(params)) {\r\n if (value == null) continue;\r\n searchParams.set(key, String(value));\r\n }\r\n\r\n return `${base}?${searchParams.toString()}`;\r\n}\r\n\r\n/**\r\n * Parses a query string into an object containing key-value pairs.\r\n *\r\n * @param {string} query - The query string to parse. May start with '?'.\r\n * @return {Record<string, string>} An object where each key is a query parameter name,\r\n * and the value is the corresponding value.\r\n */\r\nexport function parseQueryParams(query: string): Record<string, string> {\r\n const search = query.startsWith('?') ? query.slice(1) : query;\r\n const params = new URLSearchParams(search);\r\n const result: Record<string, string> = {};\r\n\r\n params.forEach((v, k) => {\r\n result[k] = v;\r\n });\r\n\r\n return result;\r\n}\r\n","import { AnyDict } from '../models';\nimport { concatArray, isNullable } from './types.utils';\n\r\n/**\r\n * Constructs a query string from a given object and concatenation type.\r\n *\r\n * @param {Record<string, any>} object - Object with key-value pairs to convert into a query string.\r\n * Keys represent parameter names, and values represent parameter values.\r\n * @param {'comma' | 'json' | 'multi'} concatType - Method for handling array values:\r\n * - 'comma': Joins array elements with a comma.\r\n * - 'json': Serializes the array as a JSON string.\r\n * - 'multi': Creates multiple entries for array elements, each associated with the same key.\r\n * @returns {string} - Formed query string with keys and values encoded as URI components.\r\n */\r\nexport const makeQuery = (object: AnyDict, concatType: 'comma' | 'json' | 'multi'): string => {\n return Object.entries(object)\n .filter(([, value]) => !isNullable(value))\n .flatMap(([key, value]) => {\n if (Array.isArray(value)) {\n if (concatType === 'multi') {\n return value.map((item) => `${encodeURIComponent(key)}=${encodeURIComponent(String(item))}`);\n }\n\n const val = concatArray(value, concatType, key);\n\n return `${encodeURIComponent(key)}=${encodeURIComponent(val!)}`;\n }\n\n return `${encodeURIComponent(key)}=${encodeURIComponent(value!)}`;\n })\n .join('&');\n};\n\r\n/**\r\n * Compares two routes to determine if the actual route matches the route template.\r\n * Supports static and dynamic route matching with optional subroute consideration.\r\n *\r\n * @param {string} actualRoute - Actual route path to compare.\r\n * @param {string} pureRoute - Template route path to match, which may include placeholders\r\n * (e.g., `:id`).\r\n * @param {boolean} [withSubroute=false] - Determines whether to allow subroute matching. If true,\r\n * actualRoute must start with the filled pureRoute.\r\n * @return {boolean} Returns true if the actual route matches the template\r\n * route (and optional subroute condition if enabled), otherwise false.\r\n */\r\nexport const compareRoutes = (actualRoute: string, pureRoute: string, withSubroute: boolean = false): boolean => {\r\n if (!pureRoute.includes(':')) {\r\n return withSubroute ? actualRoute.startsWith(pureRoute) : pureRoute === actualRoute;\r\n } else {\r\n const filled = fillRouteTemplate(actualRoute, pureRoute);\r\n\r\n return withSubroute ? actualRoute.startsWith(filled) : filled === actualRoute;\r\n }\r\n};\r\n\r\n/**\r\n * Processes and materializes a route path by decoding and, if necessary, replacing route parameters.\r\n *\r\n * @param {string} actualRoute - Actual route path, usually provided\r\n * as a source for dynamic parameter values.\r\n * @param {string} pureRoute - Route path template, may include dynamic segments denoted by `:`.\r\n * @returns {string} Fully materialized and decoded route path.\r\n */\r\nexport const materializeRoutePath = (actualRoute: string, pureRoute: string): string => {\r\n if (!pureRoute.includes(':')) {\r\n return decodeURIComponent(pureRoute);\r\n } else {\r\n return decodeURIComponent(fillRouteTemplate(actualRoute, pureRoute));\r\n }\r\n};\r\n\r\nconst fillRouteTemplate = (actualRoute: string, pureRoute: string) => {\r\n const actualSegments = actualRoute.split('/').filter(Boolean);\r\n const templateSegments = pureRoute.split('/').filter(Boolean);\r\n const prefix = actualRoute.startsWith('/') ? '/' : '';\r\n\r\n const segments: string[] = [];\r\n\r\n for (let i = 0; i < templateSegments.length; i++) {\r\n const tempSegment = templateSegments[i];\r\n const actSegment = actualSegments[i];\r\n\r\n segments.push(tempSegment.startsWith(':') ? actSegment : tempSegment);\r\n }\r\n\r\n return prefix + segments.join('/');\r\n};\r\n","// noinspection ES6PreferShortImport\r\nimport { AnyType } from '../models/util';\r\n\r\n/**\r\n * Recursively checks the equality of two objects, including nested structures and special cases\r\n * such as arrays, sets, maps, dates, and NaN.\r\n *\r\n * @param {AnyType} a - The first object to compare.\r\n * @param {AnyType} b - The second object to compare.\r\n * @param {Map} [seen=new Map()] - A map used to detect cyclic references\r\n * during deep equality check.\r\n * @return {boolean} - Returns true if the objects are deeply equal, otherwise returns false.\r\n */\r\nexport function deepEqual(a: AnyType, b: AnyType, seen = new Map()): boolean {\r\n if (a === b) {\r\n return true;\r\n }\r\n\r\n if (Number.isNaN(a) && Number.isNaN(b)) {\r\n return true;\r\n }\r\n\r\n if (a && b && typeof a === 'object' && typeof b === 'object') {\r\n if (seen.get(a) === b) {\r\n return true;\r\n }\r\n\r\n seen.set(a, b);\r\n\r\n if (Array.isArray(a)) {\r\n if (!Array.isArray(b) || a.length !== b.length) {\r\n return false;\r\n }\r\n\r\n for (let i = 0; i < a.length; i++) {\r\n if (!deepEqual(a[i], b[i], seen)) {\r\n return false;\r\n }\r\n }\r\n\r\n return true;\r\n }\r\n\r\n if (a instanceof Date || a instanceof RegExp) {\r\n return String(a) === String(b);\r\n }\r\n\r\n if (a instanceof Map) {\r\n return deepEqual(Array.from(a.entries()), Array.from(b.entries()), seen);\r\n }\r\n\r\n if (a instanceof Set) {\r\n return deepEqual(Array.from(a.values()), Array.from(b.values()), seen);\r\n }\r\n\r\n const keysA = Object.keys(a);\r\n\r\n if (keysA.length !== Object.keys(b).length) return false;\r\n for (const k of keysA)\r\n if (!Object.prototype.hasOwnProperty.call(b, k) || !deepEqual(a[k], b[k], seen)) return false;\r\n\r\n return true;\r\n }\r\n\r\n return false;\r\n}\r\n","export const generateId = (limit: number = 15, radix: number = 36) =>\r\n Math.random()\r\n .toString(radix)\r\n .substring(2, limit + 2);\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"reforgium-internal.d.ts","sources":["../../../../libs/internal/src/models/components.ts","../../../../libs/internal/src/models/elements.ts","../../../../libs/internal/src/models/util.ts","../../../../libs/internal/src/models/api.ts","../../../../libs/internal/src/tokens/locale.token.ts","../../../../libs/internal/src/tokens/theme.token.ts","../../../../libs/internal/src/tokens/device.token.ts","../../../../libs/internal/src/tokens/validation-messages.token.ts","../../../../libs/internal/src/utils/web.utils.ts","../../../../libs/internal/src/utils/timers.utils.ts","../../../../libs/internal/src/utils/date.utils.ts","../../../../libs/internal/src/utils/types.utils.ts","../../../../libs/internal/src/utils/format.utils.ts","../../../../libs/internal/src/utils/positions.utils.ts","../../../../libs/internal/src/utils/available-height.utils.ts","../../../../libs/internal/src/utils/get-chained-value.utils.ts","../../../../libs/internal/src/utils/urls.utils.ts","../../../../libs/internal/src/utils/routes.utils.ts","../../../../libs/internal/src/utils/deep-equal.utils.ts","../../../../libs/internal/src/utils/generate.utils.ts"],"sourcesContent":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null],"names":[],"mappings":"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"}