arrmatura 4.2.2 → 5.0.2
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 +30 -25
- package/commons/auth/UserService.ts +107 -0
- package/commons/auth/index.ts +4 -0
- package/commons/auth/user.xml +66 -0
- package/commons/components/buttons.xml +23 -0
- package/commons/components/index.ts +13 -0
- package/commons/components/inputs.xml +33 -0
- package/commons/components/layouts.xml +77 -0
- package/commons/components/media.xml +21 -0
- package/commons/components/modal.xml +37 -0
- package/commons/components/navigation.xml +59 -0
- package/commons/components/popups.xml +12 -0
- package/commons/components/searchbar.xml +40 -0
- package/commons/components/table.xml +120 -0
- package/commons/components/toasts.xml +13 -0
- package/commons/components/viewport.xml +48 -0
- package/commons/forms/FieldItem.xml +20 -0
- package/commons/forms/FormController.ts +73 -0
- package/commons/forms/Item.ts +68 -0
- package/commons/forms/ItemCollection.ts +152 -0
- package/commons/forms/ItemController.ts +62 -0
- package/commons/forms/MetadataService.ts +45 -0
- package/commons/forms/MultiEnumField.xml +44 -0
- package/commons/forms/MultivalueController.ts +49 -0
- package/commons/forms/SmartareaField.xml +51 -0
- package/commons/forms/SuggestionController.ts +80 -0
- package/commons/forms/SuggestionField.xml +28 -0
- package/commons/forms/fields.xml +138 -0
- package/commons/forms/form.xml +37 -0
- package/commons/forms/index.ts +29 -0
- package/commons/index.ts +6 -0
- package/commons/pipes/index.ts +21 -0
- package/commons/pipes/showCounts.ts +16 -0
- package/commons/services/ErrorHandlingService.ts +11 -0
- package/commons/services/FirebaseService.ts +185 -0
- package/commons/services/GSheetsService.ts +92 -0
- package/commons/services/HeartbeatService.ts +35 -0
- package/commons/services/Invoke.ts +13 -0
- package/commons/services/JsonpService.ts +18 -0
- package/commons/services/Loader.ts +17 -0
- package/commons/services/LocalStorage.ts +46 -0
- package/commons/services/NavigationService.ts +55 -0
- package/commons/services/Service.ts +68 -0
- package/commons/services/ServiceWorker.ts +111 -0
- package/commons/services/ToastService.ts +49 -0
- package/commons/services/index.ts +14 -0
- package/core/Arrmatura.ts +79 -0
- package/core/CNode.ts +112 -0
- package/core/Component.ts +431 -0
- package/core/Platform.ts +3 -0
- package/core/cnodes/composition.ts +100 -0
- package/core/cnodes/conditionals.ts +51 -0
- package/core/cnodes/elementary.ts +45 -0
- package/core/cnodes/iterations.ts +94 -0
- package/core/cnodes/routing.ts +25 -0
- package/core/compileNode.ts +39 -0
- package/core/expression.ts +73 -0
- package/core/index.ts +2 -0
- package/core/register.ts +43 -0
- package/core/utils.ts +25 -0
- package/core-web/WebPlatform.ts +25 -0
- package/core-web/attributes.ts +197 -0
- package/core-web/elements.ts +64 -0
- package/core-web/index.ts +19 -0
- package/core-web/reflow.ts +30 -0
- package/core-web/type.ts +19 -0
- package/docs/index.js +191 -4077
- package/lib/arrayGroupBy.ts +19 -0
- package/lib/arraySortBy.ts +49 -0
- package/lib/arrayToObject.ts +18 -0
- package/lib/codus.ts +25 -0
- package/lib/consts.ts +3 -0
- package/lib/createListeners.ts +12 -0
- package/lib/curry.ts +8 -0
- package/lib/dateFormat.ts +69 -0
- package/lib/dateOf.ts +31 -0
- package/lib/dateParseISO8601.ts +27 -0
- package/lib/fx.ts +62 -0
- package/lib/guid.ts +7 -0
- package/lib/index.ts +19 -0
- package/lib/l10n.ts +40 -0
- package/lib/nextId.ts +9 -0
- package/lib/noop.ts +8 -0
- package/lib/obj.ts +62 -0
- package/lib/predicat.ts +26 -0
- package/lib/resources.ru.ts +20 -0
- package/lib/resources.ts +20 -0
- package/lib/scalar.ts +25 -0
- package/lib/str.ts +76 -0
- package/lib/urls.ts +91 -0
- package/lib/xml.ts +117 -0
- package/package.json +17 -8
- package/docs/index.js.map +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { gettus } from 'obj';
|
|
2
|
+
|
|
3
|
+
type GroupOf<T> = { id: string; count: number; items: T[] };
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Builds histogram on given field for given list.
|
|
7
|
+
*
|
|
8
|
+
* @param {*} list source
|
|
9
|
+
* @param {*} field to be used as group key
|
|
10
|
+
*/
|
|
11
|
+
export const arrayGroupBy = function <T extends Obj>(list: T[], field = 'type', result: Hash<GroupOf<T>> = {}) {
|
|
12
|
+
const iter = (v: string, entry: T) => {
|
|
13
|
+
const slot = result[v] || (result[v] = { id: v, count: 0, items: [] });
|
|
14
|
+
slot.count++;
|
|
15
|
+
(slot.items || (slot.items = [])).push(entry);
|
|
16
|
+
};
|
|
17
|
+
list?.forEach((e: T) => iter(gettus(e, field) as string, e));
|
|
18
|
+
return result;
|
|
19
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export enum ComparatorDirection {
|
|
2
|
+
DESC = -1,
|
|
3
|
+
ASC = 1,
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export enum ComparatorResult {
|
|
7
|
+
EQ = 0,
|
|
8
|
+
LESS = -1,
|
|
9
|
+
MORE = 1,
|
|
10
|
+
}
|
|
11
|
+
type Comparable = Hash<number | string>;
|
|
12
|
+
type Comparator<T> = (a: T, b: T) => ComparatorResult;
|
|
13
|
+
|
|
14
|
+
const sortByComparator = <T extends Comparable>(
|
|
15
|
+
fn: string | ((e: T) => number | string),
|
|
16
|
+
dir: ComparatorDirection = 1
|
|
17
|
+
): Comparator<T> => {
|
|
18
|
+
let order: ComparatorResult = dir === 1 ? 1 : -1;
|
|
19
|
+
let negOrder: ComparatorResult = dir === 1 ? -1 : 1;
|
|
20
|
+
if (typeof fn === 'string') {
|
|
21
|
+
let key = fn;
|
|
22
|
+
if (key[0] === '-') {
|
|
23
|
+
order = -1;
|
|
24
|
+
negOrder = 1;
|
|
25
|
+
key = fn.substr(1);
|
|
26
|
+
}
|
|
27
|
+
return (a: T, b: T): ComparatorResult => {
|
|
28
|
+
const aa = a[fn];
|
|
29
|
+
const bb = b[fn];
|
|
30
|
+
return aa < bb ? negOrder : aa > bb ? order : 0;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return (a: T, b: T): ComparatorResult => {
|
|
34
|
+
const aa = fn(a);
|
|
35
|
+
const bb = fn(b);
|
|
36
|
+
return aa < bb ? negOrder : aa > bb ? order : 0;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Sorts array by element property
|
|
42
|
+
*/
|
|
43
|
+
export const arraySortBy = function sortBy(
|
|
44
|
+
arr: Comparable[],
|
|
45
|
+
property = 'name',
|
|
46
|
+
order: ComparatorDirection = ComparatorDirection.ASC
|
|
47
|
+
) {
|
|
48
|
+
return (arr || []).slice(0).sort(sortByComparator(property, order));
|
|
49
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Produces key/value index on given array.
|
|
3
|
+
*
|
|
4
|
+
* @param {*} arr source array
|
|
5
|
+
* @param {*} idKey id key
|
|
6
|
+
* @param {*} valKey value key
|
|
7
|
+
*/
|
|
8
|
+
export const arrayToObject = (arr: unknown[], idKey: string | Function = 'id', valKey?: string | Function) => {
|
|
9
|
+
const r: Obj = {};
|
|
10
|
+
if (arr) {
|
|
11
|
+
const idFn = typeof idKey === 'string' ? (e: Obj) => e[idKey] : idKey;
|
|
12
|
+
const valFn = typeof valKey === 'string' ? (e: Obj) => e[valKey] : valKey;
|
|
13
|
+
arr.forEach((e) => {
|
|
14
|
+
r[idFn(e)] = valFn ? valFn(e) : e;
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return r;
|
|
18
|
+
};
|
package/lib/codus.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { scalarParse } from 'scalar';
|
|
2
|
+
|
|
3
|
+
export const decodus = (val: string): unknown => {
|
|
4
|
+
if (!val) return undefined;
|
|
5
|
+
|
|
6
|
+
const value = decodeURIComponent(val);
|
|
7
|
+
if ('{['.indexOf(value[0]) > -1) {
|
|
8
|
+
try {
|
|
9
|
+
return JSON.parse(value);
|
|
10
|
+
} catch (e) {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return scalarParse(value);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const encodus = (value: unknown): string => {
|
|
18
|
+
if (typeof value === 'undefined') {
|
|
19
|
+
return '';
|
|
20
|
+
}
|
|
21
|
+
if (typeof value === 'object') {
|
|
22
|
+
return value ? encodeURIComponent(JSON.stringify(value)) : 'null';
|
|
23
|
+
}
|
|
24
|
+
return encodeURIComponent(String(value));
|
|
25
|
+
};
|
package/lib/consts.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export function createListeners<T = void>(): Listeners<T> {
|
|
2
|
+
const listeners = new Set<(event: T) => void>();
|
|
3
|
+
return {
|
|
4
|
+
add(fn) {
|
|
5
|
+
listeners.add(fn);
|
|
6
|
+
return () => listeners.delete(fn);
|
|
7
|
+
},
|
|
8
|
+
notify(event) {
|
|
9
|
+
listeners.forEach((fn) => fn(event));
|
|
10
|
+
},
|
|
11
|
+
};
|
|
12
|
+
}
|
package/lib/curry.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
const _curry = <S>(fn: (...args: unknown[]) => S, args0: unknown[], lengthLimit: number): (() => S) => {
|
|
2
|
+
const fx = (args: unknown[]) =>
|
|
3
|
+
args.length >= lengthLimit ? fn(...args) : _curry(fn, args, lengthLimit - args.length);
|
|
4
|
+
|
|
5
|
+
return (...args: unknown[]) => fx([...args0, ...args]);
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const curry = <S>(fn: () => S, ...args: S[]): S | (() => S) => _curry<S>(fn, args, fn.length);
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { dateOf } from 'dateOf';
|
|
2
|
+
import { t } from 'l10n';
|
|
3
|
+
import { padLeft } from 'str';
|
|
4
|
+
|
|
5
|
+
export const daysInMonth = (month: number, year: number) => new Date(year, month + 1, 0).getDate();
|
|
6
|
+
|
|
7
|
+
export const firstOfWeek = (x: Dateable) => {
|
|
8
|
+
const d = dateOf(x);
|
|
9
|
+
return !d ? null : new Date(d.getFullYear(), d.getMonth(), d.getDate() - d.getDay());
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export const monthName = (m: number, mode = ''): string => t(`monthNames${mode}.${m}`) as string;
|
|
13
|
+
|
|
14
|
+
export const fractions = (d: Date = new Date()) => [
|
|
15
|
+
d.getFullYear(),
|
|
16
|
+
d.getMonth(),
|
|
17
|
+
d.getDate(),
|
|
18
|
+
d.getHours(),
|
|
19
|
+
d.getMinutes(),
|
|
20
|
+
d.getSeconds(),
|
|
21
|
+
d.getMilliseconds(),
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
export const formatTimezone = (tzOffset: string | number) => {
|
|
25
|
+
const toNumber = Number(tzOffset);
|
|
26
|
+
return toNumber
|
|
27
|
+
? toNumber >= 0
|
|
28
|
+
? `+${padLeft(toNumber / 60)}:${padLeft(toNumber % 60)}`
|
|
29
|
+
: `-${padLeft(-toNumber / 60)}:${padLeft(-toNumber % 60)}`
|
|
30
|
+
: '';
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const DATE_FORMATTERS: Hash<(date: Date) => string> = {
|
|
34
|
+
hh: (date: Date) => padLeft(date.getHours()),
|
|
35
|
+
ii: (date: Date) => padLeft(date.getMinutes()),
|
|
36
|
+
hi: (date: Date) => padLeft(date.getHours()) + ':' + padLeft(date.getMinutes()),
|
|
37
|
+
dd: (date: Date) => padLeft(date.getDate()),
|
|
38
|
+
w: (date: Date) => '' + t(`dayNames.${date.getDay()}`),
|
|
39
|
+
ww: (date: Date) => '' + t(`dayNamesShort.${date.getDay()}`),
|
|
40
|
+
d: (date: Date) => '' + date.getDate(),
|
|
41
|
+
mmmm: (date: Date) => monthName(date.getMonth() + 1, ''),
|
|
42
|
+
mmm: (date: Date) => monthName(date.getMonth() + 1, 'Short'),
|
|
43
|
+
mm: (date: Date) => padLeft(date.getMonth() + 1),
|
|
44
|
+
MM: (date: Date) => padLeft(date.getMonth() + 1),
|
|
45
|
+
yyyy: (date: Date) => `${date.getFullYear()}`,
|
|
46
|
+
ll: (date: Date) => `${date.getTime()}`,
|
|
47
|
+
z: (date: Date) => `Z${formatTimezone(date.getTimezoneOffset())}`,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
var DEFAULT_DATE_FORMAT = 'yyyy-mm-dd';
|
|
51
|
+
|
|
52
|
+
export function setDefaultDateFormat(f: string) {
|
|
53
|
+
DEFAULT_DATE_FORMAT = f;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const dateFormat = (x: Dateable | null, format = DEFAULT_DATE_FORMAT) => {
|
|
57
|
+
if (!x) {
|
|
58
|
+
return '';
|
|
59
|
+
}
|
|
60
|
+
const date = dateOf(x);
|
|
61
|
+
return !date
|
|
62
|
+
? ''
|
|
63
|
+
: format.replace(/[_]/g, '\n').replace(/[hidwmylz]+/g, (key: string) => {
|
|
64
|
+
if (key in DATE_FORMATTERS) {
|
|
65
|
+
return DATE_FORMATTERS[key as keyof typeof DATE_FORMATTERS](date);
|
|
66
|
+
}
|
|
67
|
+
return key;
|
|
68
|
+
});
|
|
69
|
+
};
|
package/lib/dateOf.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { dateParseISO8601 } from 'dateParseISO8601';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Universal converter to Date.
|
|
5
|
+
*
|
|
6
|
+
* @returns Date instance or null
|
|
7
|
+
*/
|
|
8
|
+
export function dateOf(x: Dateable | null): Date | null {
|
|
9
|
+
if (x == null) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
if (typeof x === 'number') {
|
|
13
|
+
return new Date(x);
|
|
14
|
+
}
|
|
15
|
+
if (typeof x === 'object') {
|
|
16
|
+
// Date or has time
|
|
17
|
+
const dx = x as { getTime?: () => number };
|
|
18
|
+
if (dx.getTime) {
|
|
19
|
+
return new Date(dx.getTime());
|
|
20
|
+
}
|
|
21
|
+
// having a date representation
|
|
22
|
+
const ddx = x as { toDate?: () => Date };
|
|
23
|
+
if (ddx.toDate) {
|
|
24
|
+
return ddx.toDate();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
if (typeof x === 'string') {
|
|
28
|
+
return dateParseISO8601(x);
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const dateParseISO8601 = function (x: string, TZ = new Date().getTimezoneOffset()) {
|
|
2
|
+
if (!x) {
|
|
3
|
+
return null;
|
|
4
|
+
}
|
|
5
|
+
if (x.length === 10) {
|
|
6
|
+
x += 'T12:00';
|
|
7
|
+
}
|
|
8
|
+
const timebits =
|
|
9
|
+
/^([0-9]{4})-([0-9]{2})-([0-9]{2})[ T]([0-9]{2}):([0-9]{2})(?::([0-9]*)(\.[0-9]*)?)?(Z?)(([+-])([0-9]{2})([0-9]{2}))?/;
|
|
10
|
+
const m = timebits.exec(x);
|
|
11
|
+
if (!m) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const tz = m[8] ? (!m[9] ? 0 : (m[10] === '+' ? -1 : +1) * (parseInt(m[11]) * 60 + parseInt(m[12]))) : TZ;
|
|
15
|
+
// utcdate is milliseconds since the epoch
|
|
16
|
+
const utcdate = Date.UTC(
|
|
17
|
+
parseInt(m[1]),
|
|
18
|
+
parseInt(m[2]) - 1, // months are zero-offset (!)
|
|
19
|
+
parseInt(m[3]),
|
|
20
|
+
parseInt(m[4]),
|
|
21
|
+
parseInt(m[5]), // hh:mm
|
|
22
|
+
(m[6] && parseInt(m[6])) || 0, // optional seconds
|
|
23
|
+
(m[7] && parseFloat(m[7])) || 0
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
return new Date(utcdate + tz * 60000);
|
|
27
|
+
};
|
package/lib/fx.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export * from './obj';
|
|
6
|
+
|
|
7
|
+
export const assert = (b: unknown, error: string | Error, ErrorType = Error) => {
|
|
8
|
+
if (!b) {
|
|
9
|
+
throw typeof error === 'string' ? new ErrorType(error) : error;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const log = (x: any, pre: string) => {
|
|
14
|
+
console.log(pre || 'pipe', x);
|
|
15
|
+
return x;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const nextTick = (fn: any, lag: number) => {
|
|
19
|
+
return () => setTimeout(fn, lag);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export const callFn = (fn: any, ...args: number[]) => {
|
|
23
|
+
return fn(...args);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// arrayish:
|
|
27
|
+
export const includes = (x: any, p: string) => x?.includes?.(p);
|
|
28
|
+
export const slice = <T>(x: T[], b = 0, e?: number): T[] => (x ? x.slice(b, e) : []);
|
|
29
|
+
|
|
30
|
+
// checks
|
|
31
|
+
export const isTrue = (x: any) => x === true;
|
|
32
|
+
export const isFalse = (x: any) => x === false;
|
|
33
|
+
export const isUndefined = <T = unknown>(x: T): boolean => typeof x === 'undefined';
|
|
34
|
+
|
|
35
|
+
// logical
|
|
36
|
+
export const then = (x: any, p = '', n = '') => (x ? p : n);
|
|
37
|
+
export const truthy = (x: any) => !!x;
|
|
38
|
+
export const not = (x: any) => !x;
|
|
39
|
+
export const or = (x: any, s: any) => x || s;
|
|
40
|
+
export const and = (x: any, s: any) => x && s;
|
|
41
|
+
|
|
42
|
+
// math
|
|
43
|
+
// eslint-disable-next-line eqeqeq
|
|
44
|
+
export const equals = (x: any, p: any) => x == p;
|
|
45
|
+
export const greater = (x: any, p: any) => x > p;
|
|
46
|
+
export const less = (x: any, p: any) => x < p;
|
|
47
|
+
export const plus = (x: any, alt: any) => +x + +alt;
|
|
48
|
+
export const minus = (x: any, alt: any) => +x - +alt;
|
|
49
|
+
export const multiply = (x: any, alt: any) => +x * +alt;
|
|
50
|
+
export const swap = (f: BinaryOp) => (a: unknown, b: unknown) => f(b, a);
|
|
51
|
+
|
|
52
|
+
export const compose =
|
|
53
|
+
(...ff: ((e: unknown) => unknown)[]) =>
|
|
54
|
+
(x0: unknown) =>
|
|
55
|
+
ff.reduceRight((x: unknown, fn) => fn(x), x0);
|
|
56
|
+
|
|
57
|
+
export const bindArgs = (fn: () => unknown, ...args: never[]) => fn?.bind(null, ...args);
|
|
58
|
+
|
|
59
|
+
export const assignFirstArgKeyValue =
|
|
60
|
+
(fn: () => unknown, key: string, val: unknown) =>
|
|
61
|
+
(x: object, ...args: unknown[]) =>
|
|
62
|
+
fn(Object.assign(x || {}, { [key]: val }), ...args.slice(1));
|
package/lib/guid.ts
ADDED
package/lib/index.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from './arrayGroupBy';
|
|
2
|
+
export { arraySortBy } from './arraySortBy';
|
|
3
|
+
export * from './arrayToObject';
|
|
4
|
+
export * from './createListeners';
|
|
5
|
+
export * from './curry';
|
|
6
|
+
export * from './dateFormat';
|
|
7
|
+
export * from './dateOf';
|
|
8
|
+
export * from './dateParseISO8601';
|
|
9
|
+
export * from './codus';
|
|
10
|
+
export * from './fx';
|
|
11
|
+
export * from './guid';
|
|
12
|
+
export * from './l10n';
|
|
13
|
+
export * from './nextId';
|
|
14
|
+
export * from './noop';
|
|
15
|
+
export * from './obj';
|
|
16
|
+
export * from './scalar';
|
|
17
|
+
export * from './str';
|
|
18
|
+
export * from './urls';
|
|
19
|
+
export * from './xml';
|
package/lib/l10n.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import en from 'resources';
|
|
2
|
+
import ru from 'resources.ru';
|
|
3
|
+
|
|
4
|
+
const R = { en, ru };
|
|
5
|
+
|
|
6
|
+
let LANG: keyof typeof R = 'en';
|
|
7
|
+
|
|
8
|
+
export function setLang(lang: keyof typeof R = 'en'): void {
|
|
9
|
+
LANG = lang;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const deep = (path?: string[], lang = LANG) => {
|
|
13
|
+
let r: Bundle | Hash<string> | string = R[lang] as unknown as Bundle;
|
|
14
|
+
if (!path?.length) return r;
|
|
15
|
+
for (const k of path) {
|
|
16
|
+
r = r[k];
|
|
17
|
+
if (typeof r !== 'object') {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return typeof r === 'object' ? r : undefined;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const t = (key: string, lang?: keyof typeof R) => {
|
|
26
|
+
const path = key ? key.split('.') : [];
|
|
27
|
+
const last = path.pop();
|
|
28
|
+
if (!last) return undefined;
|
|
29
|
+
const target = deep(path, lang);
|
|
30
|
+
|
|
31
|
+
return target ? target[last] : undefined;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const appendResourceBundle = (bundle: Bundle, key?: string, lang = LANG) => {
|
|
35
|
+
const path = key ? key.split('.') : undefined;
|
|
36
|
+
const target = deep(path, lang);
|
|
37
|
+
if (target) {
|
|
38
|
+
Object.assign(target, bundle);
|
|
39
|
+
}
|
|
40
|
+
};
|
package/lib/nextId.ts
ADDED
package/lib/noop.ts
ADDED
package/lib/obj.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if argument is empty .
|
|
3
|
+
*/
|
|
4
|
+
export const isEmpty = (x: unknown): boolean => {
|
|
5
|
+
if (!x) {
|
|
6
|
+
return true;
|
|
7
|
+
}
|
|
8
|
+
if (typeof x === 'object') {
|
|
9
|
+
if (x === null) {
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
// (zero-length array)
|
|
13
|
+
if (Array.isArray(x)) {
|
|
14
|
+
return x.length === 0;
|
|
15
|
+
}
|
|
16
|
+
// (zero-size map)
|
|
17
|
+
if (x instanceof Map) {
|
|
18
|
+
return x.size === 0;
|
|
19
|
+
}
|
|
20
|
+
// (has no props)
|
|
21
|
+
return Object.keys(x).length === 0;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// data structures
|
|
27
|
+
export const dot = (x: any, k: string) => (x ? x[k] : null);
|
|
28
|
+
|
|
29
|
+
export const assignKeyValue = (o: Obj, key: string, value: unknown): object => {
|
|
30
|
+
return Object.assign(o || {}, { [key]: value });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export const pack = (x?: unknown, key = 'value'): object => {
|
|
34
|
+
return { [key]: x };
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const gettus = (o: Obj, key: string | string[] | ((e: Obj) => unknown)): unknown => {
|
|
38
|
+
if (!o || !key || typeof o !== 'object') return undefined;
|
|
39
|
+
if (typeof key === 'function') return key(o);
|
|
40
|
+
if (typeof key === 'string') {
|
|
41
|
+
if (!key.includes('.')) return o[key];
|
|
42
|
+
key = key.split('.');
|
|
43
|
+
}
|
|
44
|
+
return key.reduce<Obj | undefined>((r, e) => (r ? (r[e] as Obj) : undefined), o);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const settus = (o: Obj, key: string | string[] | ((e: Obj, v: unknown) => unknown), value: unknown): void => {
|
|
48
|
+
if (!o || !key || typeof o !== 'object') return;
|
|
49
|
+
|
|
50
|
+
if (typeof key === 'function') {
|
|
51
|
+
key(o, value);
|
|
52
|
+
} else {
|
|
53
|
+
const keys = typeof key === 'string' ? key.split('.') : key;
|
|
54
|
+
if (keys.length) {
|
|
55
|
+
const last = keys.pop();
|
|
56
|
+
const target = keys.reduce<Obj | undefined>((r, e) => (r ? (r[e] as Obj) : undefined), o);
|
|
57
|
+
if (last && target && typeof o === 'object') {
|
|
58
|
+
target[last] = value;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
};
|
package/lib/predicat.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const compilePredicatChunk = (s: string): Predicat<Data> => {
|
|
2
|
+
const tokens = s.match(/(\w+)\s*(!?)=\s*([,\wа-яА-Я]+)/);
|
|
3
|
+
if (!tokens) {
|
|
4
|
+
return s[0] === '!' ? (d) => !d[s.slice(1)] : (d) => !!d[s];
|
|
5
|
+
}
|
|
6
|
+
const [_, key, neg, val] = tokens;
|
|
7
|
+
const fn = (d: Data) => val.includes(String(d[key]));
|
|
8
|
+
return neg ? (d) => !!d[key] && !fn(d) : fn;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const compilePredicat = (s: string | boolean): Predicat<Data> => {
|
|
12
|
+
if (!s || s === 'FALSE' || s === 'false') return () => false;
|
|
13
|
+
if (s === 'ALWAYS' || s === 'TRUE' || s === 'true' || s === true) return () => true;
|
|
14
|
+
|
|
15
|
+
const expr = String(s)
|
|
16
|
+
.split('&&')
|
|
17
|
+
.map((s) => s.trim())
|
|
18
|
+
.filter(Boolean)
|
|
19
|
+
.map(compilePredicatChunk);
|
|
20
|
+
|
|
21
|
+
return (data) => !!expr.find((fn) => fn(data));
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const PREDICATS: Hash<Predicat<Data>> = {};
|
|
25
|
+
|
|
26
|
+
export const getPredicat = (s: string | boolean = '') => PREDICATS['' + s] || (PREDICATS['' + s] = compilePredicat(s));
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
monthNames: [
|
|
3
|
+
'',
|
|
4
|
+
'Январь',
|
|
5
|
+
'Февраль',
|
|
6
|
+
'Март',
|
|
7
|
+
'Апрель',
|
|
8
|
+
'Май',
|
|
9
|
+
'Июнь',
|
|
10
|
+
'Июль',
|
|
11
|
+
'Август',
|
|
12
|
+
'Сентябрь',
|
|
13
|
+
'Октябрь',
|
|
14
|
+
'Ноябрь',
|
|
15
|
+
'Декабрь',
|
|
16
|
+
],
|
|
17
|
+
monthNamesShort: ['', 'Янв', 'Фев', 'Мар', 'Апр', 'Май', 'Июн', 'Июл', 'Авг', 'Сен', 'Окт', 'Ноя', 'Дек'],
|
|
18
|
+
dayNames: ['Воскресенье', 'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота'],
|
|
19
|
+
dayNamesShort: ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'],
|
|
20
|
+
};
|
package/lib/resources.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
monthNames: [
|
|
3
|
+
'',
|
|
4
|
+
'January',
|
|
5
|
+
'February',
|
|
6
|
+
'March',
|
|
7
|
+
'April',
|
|
8
|
+
'May',
|
|
9
|
+
'June',
|
|
10
|
+
'July',
|
|
11
|
+
'August',
|
|
12
|
+
'September',
|
|
13
|
+
'October',
|
|
14
|
+
'November',
|
|
15
|
+
'December',
|
|
16
|
+
],
|
|
17
|
+
monthNamesShort: ['', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
|
18
|
+
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
|
19
|
+
dayNamesShort: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
|
|
20
|
+
};
|
package/lib/scalar.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const scalarParse = (s?: string): Scalar | undefined => {
|
|
2
|
+
if (s === 'undefined') {
|
|
3
|
+
return undefined;
|
|
4
|
+
}
|
|
5
|
+
if (s === 'null') {
|
|
6
|
+
return null;
|
|
7
|
+
}
|
|
8
|
+
if (s === 'true') {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
if (s === 'false') {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
if (s === '0') {
|
|
15
|
+
return 0;
|
|
16
|
+
}
|
|
17
|
+
if (s === '') {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
if (s && '1234567890+-'.includes(s[0]) && s.length <= 17) {
|
|
21
|
+
const num = +s;
|
|
22
|
+
return isNaN(num) ? s : num;
|
|
23
|
+
}
|
|
24
|
+
return s;
|
|
25
|
+
};
|
package/lib/str.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export function str(x: unknown) {
|
|
2
|
+
return x == null ? '' : String(x);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function capitalize(x: unknown) {
|
|
6
|
+
const s = str(x);
|
|
7
|
+
return s ? s[0].toUpperCase() + s.slice(1) : '';
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function camelize(x: unknown, sep = '_') {
|
|
11
|
+
return str(x)
|
|
12
|
+
.split(sep)
|
|
13
|
+
.map((t, i) => (i ? capitalize(t) : t))
|
|
14
|
+
.join('');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const snakeCase = (x: string) => str(x).replace(/([a-z])([A-Z])/g, '$1_$2');
|
|
18
|
+
export const properCase = (x: string) => capitalize(camelize(x));
|
|
19
|
+
export const upperCase = (x: string) => str(x).toUpperCase();
|
|
20
|
+
export const lowerCase = (x: string) => str(x).toLowerCase();
|
|
21
|
+
|
|
22
|
+
export function strFormat(template: string, params: Hash) {
|
|
23
|
+
return str(template).replace(/\{([\S]+)\}/i, (_, key) => ((params && params[key]) != null ? str(params[key]) : ''));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const strEnhance = (x: string, template: string) => {
|
|
27
|
+
return !x ? '' : `${template || '*'}`.replace('*', x);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const tail = (x: string, sep = '.') => {
|
|
31
|
+
if (!x) {
|
|
32
|
+
return '';
|
|
33
|
+
}
|
|
34
|
+
const pos = x.lastIndexOf(sep);
|
|
35
|
+
return pos === -1 ? x : x.slice(pos + sep.length);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export const head = (x: string, sep = '.') => {
|
|
39
|
+
if (!x) {
|
|
40
|
+
return '';
|
|
41
|
+
}
|
|
42
|
+
const pos = x.indexOf(sep);
|
|
43
|
+
|
|
44
|
+
return pos === -1 ? x : x.slice(0, pos);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export const mirror = (x: string) =>
|
|
48
|
+
str(x)
|
|
49
|
+
.split('')
|
|
50
|
+
.reduce((r, c) => c + r, '');
|
|
51
|
+
|
|
52
|
+
/* Simple hash function. */
|
|
53
|
+
export const hash = (s: string) => {
|
|
54
|
+
let a = 1,
|
|
55
|
+
c = 0,
|
|
56
|
+
h,
|
|
57
|
+
o;
|
|
58
|
+
if (s) {
|
|
59
|
+
a = 0;
|
|
60
|
+
for (h = s.length - 1; h >= 0; h--) {
|
|
61
|
+
o = s.charCodeAt(h);
|
|
62
|
+
a = ((a << 6) & 268435455) + o + (o << 14);
|
|
63
|
+
c = a & 266338304;
|
|
64
|
+
a = c !== 0 ? a ^ (c >> 21) : a;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return String(a);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export function padLeft(x: string | number, size = 2, fill = '0') {
|
|
71
|
+
let s = str(x);
|
|
72
|
+
while (s.length < size) {
|
|
73
|
+
s = `${fill}${s}`;
|
|
74
|
+
}
|
|
75
|
+
return s;
|
|
76
|
+
}
|