@agnos-ui/core 0.0.1-alpha.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 +15 -0
- package/dist/lib/accordion.d.ts +318 -0
- package/dist/lib/accordion.js +263 -0
- package/dist/lib/alert.d.ts +100 -0
- package/dist/lib/alert.js +66 -0
- package/dist/lib/config.d.ts +71 -0
- package/dist/lib/config.js +53 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.js +11 -0
- package/dist/lib/modal/modal.d.ts +318 -0
- package/dist/lib/modal/modal.js +156 -0
- package/dist/lib/modal/scrollbars.d.ts +2 -0
- package/dist/lib/modal/scrollbars.js +27 -0
- package/dist/lib/pagination.d.ts +464 -0
- package/dist/lib/pagination.js +148 -0
- package/dist/lib/pagination.utils.d.ts +8 -0
- package/dist/lib/pagination.utils.js +110 -0
- package/dist/lib/rating.d.ts +209 -0
- package/dist/lib/rating.js +141 -0
- package/dist/lib/select.d.ts +199 -0
- package/dist/lib/select.js +240 -0
- package/dist/lib/services/checks.d.ts +32 -0
- package/dist/lib/services/checks.js +43 -0
- package/dist/lib/services/directiveUtils.d.ts +95 -0
- package/dist/lib/services/directiveUtils.js +190 -0
- package/dist/lib/services/focustrack.d.ts +19 -0
- package/dist/lib/services/focustrack.js +46 -0
- package/dist/lib/services/index.d.ts +6 -0
- package/dist/lib/services/index.js +6 -0
- package/dist/lib/services/portal.d.ts +6 -0
- package/dist/lib/services/portal.js +33 -0
- package/dist/lib/services/siblingsInert.d.ts +7 -0
- package/dist/lib/services/siblingsInert.js +40 -0
- package/dist/lib/services/stores.d.ts +140 -0
- package/dist/lib/services/stores.js +219 -0
- package/dist/lib/services/writables.d.ts +7 -0
- package/dist/lib/services/writables.js +16 -0
- package/dist/lib/transitions/baseTransitions.d.ts +136 -0
- package/dist/lib/transitions/baseTransitions.js +171 -0
- package/dist/lib/transitions/bootstrap/collapse.d.ts +2 -0
- package/dist/lib/transitions/bootstrap/collapse.js +15 -0
- package/dist/lib/transitions/bootstrap/fade.d.ts +1 -0
- package/dist/lib/transitions/bootstrap/fade.js +7 -0
- package/dist/lib/transitions/bootstrap/index.d.ts +2 -0
- package/dist/lib/transitions/bootstrap/index.js +2 -0
- package/dist/lib/transitions/collapse.d.ts +29 -0
- package/dist/lib/transitions/collapse.js +39 -0
- package/dist/lib/transitions/cssTransitions.d.ts +15 -0
- package/dist/lib/transitions/cssTransitions.js +38 -0
- package/dist/lib/transitions/index.d.ts +5 -0
- package/dist/lib/transitions/index.js +5 -0
- package/dist/lib/transitions/simpleClassTransition.d.ts +29 -0
- package/dist/lib/transitions/simpleClassTransition.js +28 -0
- package/dist/lib/transitions/utils.d.ts +20 -0
- package/dist/lib/transitions/utils.js +83 -0
- package/dist/lib/tsdoc-metadata.json +11 -0
- package/dist/lib/types.d.ts +58 -0
- package/dist/lib/types.js +7 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.js +2 -0
- package/package.json +52 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const portal = (content, newArg) => {
|
|
2
|
+
let arg;
|
|
3
|
+
let replaceComment;
|
|
4
|
+
const removeReplaceComment = () => {
|
|
5
|
+
if (replaceComment) {
|
|
6
|
+
replaceComment.parentNode?.replaceChild(content, replaceComment);
|
|
7
|
+
replaceComment = null;
|
|
8
|
+
}
|
|
9
|
+
};
|
|
10
|
+
const update = (newArg) => {
|
|
11
|
+
if (newArg !== arg) {
|
|
12
|
+
arg = newArg;
|
|
13
|
+
const container = arg?.container ?? arg?.insertBefore?.parentElement;
|
|
14
|
+
if (container) {
|
|
15
|
+
if (!replaceComment) {
|
|
16
|
+
replaceComment = content.parentNode?.insertBefore(content.ownerDocument.createComment('portal'), content);
|
|
17
|
+
}
|
|
18
|
+
container.insertBefore(content, arg?.insertBefore ?? null);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
removeReplaceComment();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
update(newArg);
|
|
26
|
+
return {
|
|
27
|
+
update,
|
|
28
|
+
destroy: () => {
|
|
29
|
+
removeReplaceComment();
|
|
30
|
+
content.parentNode?.removeChild(content);
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sliblingsInert directive
|
|
3
|
+
* When used on an element, all siblings of the element and of its ancestors will be inert with the inert attribute.
|
|
4
|
+
* In case it is used on multiple elements, only the last one has an effect (the directive keeps a stack of elements
|
|
5
|
+
* on which it is used, so when the last one disappears, the previous one in the list becomes the one in effect).
|
|
6
|
+
*/
|
|
7
|
+
export declare const sliblingsInert: import("..").Directive<void>;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { computed } from '@amadeus-it-group/tansu';
|
|
2
|
+
import { noop } from '../utils';
|
|
3
|
+
import { createStoreArrayDirective, directiveSubscribe, mergeDirectives } from './directiveUtils';
|
|
4
|
+
const internalSetSiblingsInert = (element) => {
|
|
5
|
+
const inertValues = new Map();
|
|
6
|
+
const recursiveHelper = (element) => {
|
|
7
|
+
const parent = element.parentElement;
|
|
8
|
+
if (parent && element !== document.body) {
|
|
9
|
+
Array.from(parent.children).forEach((sibling) => {
|
|
10
|
+
if (sibling !== element && sibling.nodeName !== 'SCRIPT') {
|
|
11
|
+
inertValues.set(sibling, sibling.hasAttribute('inert'));
|
|
12
|
+
sibling.toggleAttribute('inert', true);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
recursiveHelper(parent);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
recursiveHelper(element);
|
|
19
|
+
return () => inertValues.forEach((value, element) => {
|
|
20
|
+
element.toggleAttribute('inert', value);
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
let internalRevert = noop;
|
|
24
|
+
const setSiblingsInert = (element) => {
|
|
25
|
+
internalRevert();
|
|
26
|
+
internalRevert = element ? internalSetSiblingsInert(element) : noop;
|
|
27
|
+
};
|
|
28
|
+
const { directive: storeArrayDirective, elements$ } = createStoreArrayDirective();
|
|
29
|
+
const lastElement$ = computed(() => {
|
|
30
|
+
const elements = elements$();
|
|
31
|
+
return elements[elements.length - 1];
|
|
32
|
+
}, { equal: Object.is });
|
|
33
|
+
const inertAction$ = computed(() => setSiblingsInert(lastElement$()));
|
|
34
|
+
/**
|
|
35
|
+
* sliblingsInert directive
|
|
36
|
+
* When used on an element, all siblings of the element and of its ancestors will be inert with the inert attribute.
|
|
37
|
+
* In case it is used on multiple elements, only the last one has an effect (the directive keeps a stack of elements
|
|
38
|
+
* on which it is used, so when the last one disappears, the previous one in the list becomes the one in effect).
|
|
39
|
+
*/
|
|
40
|
+
export const sliblingsInert = mergeDirectives(storeArrayDirective, directiveSubscribe(inertAction$));
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import type { ReadableSignal, WritableSignal, StoreOptions, StoreInput, StoresInputValues } from '@amadeus-it-group/tansu';
|
|
2
|
+
export type ToWritableSignal<P, V = P> = {
|
|
3
|
+
[K in keyof P & keyof V as `${K & string}$`]-?: WritableSignal<P[K], V[K] | undefined>;
|
|
4
|
+
};
|
|
5
|
+
export type ValuesOrStores<T extends object> = {
|
|
6
|
+
[K in keyof T]?: ReadableSignal<T[K]> | T[K];
|
|
7
|
+
};
|
|
8
|
+
export type WithoutDollar<S extends `${string}$`> = S extends `${infer U}$` ? U : never;
|
|
9
|
+
export type ValueOfStore<S extends ReadableSignal<any>> = S extends ReadableSignal<infer U> ? U : never;
|
|
10
|
+
export type ToState<S extends {
|
|
11
|
+
[K in keyof S & `${string}$`]: ReadableSignal<any>;
|
|
12
|
+
}> = {
|
|
13
|
+
[K in keyof S & `${string}$` as WithoutDollar<K>]: ValueOfStore<S[K]>;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
*
|
|
17
|
+
* Utility function designed to create a `patch` function related to the provided stores.
|
|
18
|
+
* Any key given to the patch function which is not in the original object will be ignored.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
*
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const storeA$ = writable(1);
|
|
24
|
+
* const storeB$ = writable(1);
|
|
25
|
+
* const patch = createPatch({a: storeA$, b: storeB$});
|
|
26
|
+
*
|
|
27
|
+
* patch({a: 2}) // will perform storeA$.set(2)
|
|
28
|
+
* patch({a: 2, b: 2}) // will perform storeA$.set(2) and storeB$.set(2) in the same batch.
|
|
29
|
+
* patch({a: 2, c: 2}) // will perform storeA$.set(2), c is ignored.
|
|
30
|
+
*
|
|
31
|
+
* ```
|
|
32
|
+
* @param stores - object of stores
|
|
33
|
+
* @returns the patch function
|
|
34
|
+
*/
|
|
35
|
+
export declare function createPatch<T extends object, V extends object = T>(stores: ToWritableSignal<T, V>): <U extends Partial<T>>(storesValues?: void | U | undefined) => void;
|
|
36
|
+
/**
|
|
37
|
+
* This utility function is designed to compare the first level of two objects.
|
|
38
|
+
*
|
|
39
|
+
* It returns a new object which has all the keys for which the values in `obj1`
|
|
40
|
+
* and `obj2` are different, with the values from `obj2`, or null if objects
|
|
41
|
+
* are identical.
|
|
42
|
+
*
|
|
43
|
+
* @param obj1 - First object
|
|
44
|
+
* @param obj2 - Second object
|
|
45
|
+
* @returns the object with changed properties
|
|
46
|
+
*/
|
|
47
|
+
export declare function findChangedProperties<T extends Record<string, any>>(obj1: Partial<T>, obj2: Partial<T>): Partial<T> | null;
|
|
48
|
+
export declare const INVALID_VALUE: unique symbol;
|
|
49
|
+
export type NormalizeValue<T, U = T> = (value: U) => T | typeof INVALID_VALUE;
|
|
50
|
+
export interface WritableWithDefaultOptions<T, U = T> {
|
|
51
|
+
/**
|
|
52
|
+
* the normalize value function. should return the invalidValue symbol when the provided value is invalid
|
|
53
|
+
*/
|
|
54
|
+
normalizeValue?: NormalizeValue<T, U>;
|
|
55
|
+
/**
|
|
56
|
+
* the equal function, allowing to compare two values. used to check if a previous and current values are equals.
|
|
57
|
+
*/
|
|
58
|
+
equal?: StoreOptions<T>['equal'];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Returns a writable store whose value is either its own value (when it is not undefined) or a default value
|
|
62
|
+
* that comes either from the `config$` store (when it is not undefined) or from `defValue`.
|
|
63
|
+
* If a normalizeValue function is passed in the options, it is called to normalize non-undefined values coming
|
|
64
|
+
* either from the `config$` store or from the `set` or `update` functions. If a value is invalid (i.e. normalizeValue
|
|
65
|
+
* returns the `invalidValue` symbol), an error is logged on the console and it is either not set (if it comes from the
|
|
66
|
+
* `set` or `update` functions), or the `defValue` is used instead (if the invalid value comes from the `config$` store).
|
|
67
|
+
*
|
|
68
|
+
* @param defValue - Default value used when both the own value and the config$ value are undefined.
|
|
69
|
+
* @param config$ - Default value used when the own value is undefined
|
|
70
|
+
* @param options - Object which can contain the following optional functions: normalizeValue and equal
|
|
71
|
+
* @returns a writable store with the extra default value and normalization logic described above
|
|
72
|
+
*/
|
|
73
|
+
export declare function writableWithDefault<T, U = T>(defValue: T, config$?: ReadableSignal<U | undefined>, { normalizeValue, equal }?: WritableWithDefaultOptions<T, U>): WritableSignal<T, U | undefined>;
|
|
74
|
+
export type ConfigValidator<T extends object, U extends object = T> = {
|
|
75
|
+
[K in keyof T & keyof U]?: WritableWithDefaultOptions<T[K], U[K]>;
|
|
76
|
+
};
|
|
77
|
+
/**
|
|
78
|
+
* Returns an object containing, for each property of `defConfig`, a corresponding writable with the normalization and default value logic
|
|
79
|
+
* described in {@link writableWithDefault}. Keys in the returned object are the same as the ones present in `defConfig`,
|
|
80
|
+
* with the exta `$` suffix (showing that they are stores).
|
|
81
|
+
*
|
|
82
|
+
* @param defConfig - object containing, for each property, a default value to use in case `config$` does not provide the suitable default
|
|
83
|
+
* value for that property
|
|
84
|
+
* @param config - either a store of objects containing, for each property of `defConfig`, the default value or an object containing
|
|
85
|
+
* for each property of `defConfig` either a store containing the default value or the default value itself
|
|
86
|
+
* @param options - object containing, for each property of `defConfig`, an optional object with the following optional functions: normalizeValue and equal
|
|
87
|
+
* @returns an object containing writables
|
|
88
|
+
*
|
|
89
|
+
* @example With a store
|
|
90
|
+
* ```ts
|
|
91
|
+
* const defConfig = {propA: 1};
|
|
92
|
+
* const validation = {propA: {normalizeValue: value => +value}};
|
|
93
|
+
* const config$ = writable({propA: 5});
|
|
94
|
+
* const {propA$} = writablesWithDefault(defConfig, config$, validation);
|
|
95
|
+
* ```
|
|
96
|
+
*
|
|
97
|
+
* @example With an object containing a value and a store
|
|
98
|
+
* ```ts
|
|
99
|
+
* const defConfig = {propA: 1, propB: 2};
|
|
100
|
+
* const validation = {propA: {normalizeValue: value => +value}};
|
|
101
|
+
* const config = {propA: 5, propB: writable(3)};
|
|
102
|
+
* const {propA$, propB$} = writablesWithDefault(defConfig, config, validation);
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export declare const writablesWithDefault: <T extends object, U extends object = T>(defConfig: T, config?: PropsConfig<U> | undefined, options?: ConfigValidator<T, U> | undefined) => ToWritableSignal<T, U>;
|
|
106
|
+
/**
|
|
107
|
+
* Shortcut for calling both {@link writablesWithDefault} and {@link createPatch} in one call.
|
|
108
|
+
* @param defConfig - object containing, for each property, a default value to use in case `config` does not provide the suitable default
|
|
109
|
+
* value for that property
|
|
110
|
+
* @param config - either a store of objects containing, for each property of `defConfig`, the default value or an object containing
|
|
111
|
+
* for each property of `defConfig` either a store containing the default value or the default value itself
|
|
112
|
+
* @param options - object containing, for each property of `defConfig`, an optional object with the following optional functions: normalizeValue and equal
|
|
113
|
+
* @returns an array with two items: the first one containing the writables (returned by {@link writablesWithDefault}),
|
|
114
|
+
* and the second one containing the patch function (returned by {@link createPatch})
|
|
115
|
+
*
|
|
116
|
+
* @example With a store
|
|
117
|
+
* ```ts
|
|
118
|
+
* const defConfig = {propA: 1};
|
|
119
|
+
* const validation = {propA: {normalizeValue: value => +value}};
|
|
120
|
+
* const config$ = writable({propA: 5});
|
|
121
|
+
* const [{propA$}, patch] = writablesForProps(defConfig, config$, validation);
|
|
122
|
+
* ```
|
|
123
|
+
*
|
|
124
|
+
* @example With an object containing a value and a store
|
|
125
|
+
* ```ts
|
|
126
|
+
* const defConfig = {propA: 1, propB: 2};
|
|
127
|
+
* const validation = {propA: {normalizeValue: value => +value}};
|
|
128
|
+
* const config = {propA: 5, propB: writable(3)};
|
|
129
|
+
* const [{propA$, propB$}, patch] = writablesForProps(defConfig, config, validation);
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export declare const writablesForProps: <T extends object, U extends object = T>(defConfig: T, config?: PropsConfig<U> | undefined, options?: { [K in keyof T & keyof U]?: WritableWithDefaultOptions<T[K], U[K]> | undefined; } | undefined) => [ToWritableSignal<T, U>, <U_1 extends Partial<T>>(storesValues?: void | U_1 | undefined) => void];
|
|
133
|
+
export type PropsConfig<T extends object> = ReadableSignal<Partial<T>> | ValuesOrStores<T>;
|
|
134
|
+
export declare const stateStores: <A extends {
|
|
135
|
+
[x: `${string}$`]: ReadableSignal<any>;
|
|
136
|
+
}>(inputStores: A) => {
|
|
137
|
+
state$: ReadableSignal<ToState<A>>;
|
|
138
|
+
stores: { [key in `${string}$` & keyof A]: ReadableSignal<ValueOfStore<A[key]>>; };
|
|
139
|
+
};
|
|
140
|
+
export declare const bindableDerived: <T, U extends [WritableSignal<T, T>, ...StoreInput<any>[]]>(onChange$: ReadableSignal<(value: T) => void>, stores: U, adjustValue: (arg: StoresInputValues<U>) => T) => ReadableSignal<T>;
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { batch, computed, derived, get, readable, writable, asReadable } from '@amadeus-it-group/tansu';
|
|
2
|
+
import { identity } from '../utils';
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* Utility function designed to create a `patch` function related to the provided stores.
|
|
6
|
+
* Any key given to the patch function which is not in the original object will be ignored.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
*
|
|
10
|
+
* ```typescript
|
|
11
|
+
* const storeA$ = writable(1);
|
|
12
|
+
* const storeB$ = writable(1);
|
|
13
|
+
* const patch = createPatch({a: storeA$, b: storeB$});
|
|
14
|
+
*
|
|
15
|
+
* patch({a: 2}) // will perform storeA$.set(2)
|
|
16
|
+
* patch({a: 2, b: 2}) // will perform storeA$.set(2) and storeB$.set(2) in the same batch.
|
|
17
|
+
* patch({a: 2, c: 2}) // will perform storeA$.set(2), c is ignored.
|
|
18
|
+
*
|
|
19
|
+
* ```
|
|
20
|
+
* @param stores - object of stores
|
|
21
|
+
* @returns the patch function
|
|
22
|
+
*/
|
|
23
|
+
export function createPatch(stores) {
|
|
24
|
+
return function (storesValues) {
|
|
25
|
+
batch(() => {
|
|
26
|
+
for (const [name, value] of Object.entries(storesValues ?? {})) {
|
|
27
|
+
stores[`${name}$`]?.set(value);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* This utility function is designed to compare the first level of two objects.
|
|
34
|
+
*
|
|
35
|
+
* It returns a new object which has all the keys for which the values in `obj1`
|
|
36
|
+
* and `obj2` are different, with the values from `obj2`, or null if objects
|
|
37
|
+
* are identical.
|
|
38
|
+
*
|
|
39
|
+
* @param obj1 - First object
|
|
40
|
+
* @param obj2 - Second object
|
|
41
|
+
* @returns the object with changed properties
|
|
42
|
+
*/
|
|
43
|
+
export function findChangedProperties(obj1, obj2) {
|
|
44
|
+
if (obj1 === obj2) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
let hasUpdate = false;
|
|
48
|
+
const changedValues = {};
|
|
49
|
+
const keys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
|
|
50
|
+
for (const key of keys) {
|
|
51
|
+
const value = obj2[key];
|
|
52
|
+
if (obj1[key] !== value) {
|
|
53
|
+
changedValues[key] = value;
|
|
54
|
+
hasUpdate = true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return hasUpdate ? changedValues : null;
|
|
58
|
+
}
|
|
59
|
+
const update = function (updater) {
|
|
60
|
+
this.set(updater(this()));
|
|
61
|
+
};
|
|
62
|
+
export const INVALID_VALUE = Symbol();
|
|
63
|
+
/* eslint-disable jsdoc/check-param-names, jsdoc/require-param */
|
|
64
|
+
/**
|
|
65
|
+
* Returns a writable store whose value is either its own value (when it is not undefined) or a default value
|
|
66
|
+
* that comes either from the `config$` store (when it is not undefined) or from `defValue`.
|
|
67
|
+
* If a normalizeValue function is passed in the options, it is called to normalize non-undefined values coming
|
|
68
|
+
* either from the `config$` store or from the `set` or `update` functions. If a value is invalid (i.e. normalizeValue
|
|
69
|
+
* returns the `invalidValue` symbol), an error is logged on the console and it is either not set (if it comes from the
|
|
70
|
+
* `set` or `update` functions), or the `defValue` is used instead (if the invalid value comes from the `config$` store).
|
|
71
|
+
*
|
|
72
|
+
* @param defValue - Default value used when both the own value and the config$ value are undefined.
|
|
73
|
+
* @param config$ - Default value used when the own value is undefined
|
|
74
|
+
* @param options - Object which can contain the following optional functions: normalizeValue and equal
|
|
75
|
+
* @returns a writable store with the extra default value and normalization logic described above
|
|
76
|
+
*/
|
|
77
|
+
export function writableWithDefault(defValue, config$ = readable(undefined), { normalizeValue = identity, equal = Object.is } = {}) {
|
|
78
|
+
const own$ = writable(undefined);
|
|
79
|
+
const validatedDefConfig$ = computed(() => {
|
|
80
|
+
const value = config$();
|
|
81
|
+
const normalizedValue = value === undefined ? undefined : normalizeValue(value);
|
|
82
|
+
if (normalizedValue === INVALID_VALUE) {
|
|
83
|
+
console.error('Not using invalid value from default config', value);
|
|
84
|
+
return defValue;
|
|
85
|
+
}
|
|
86
|
+
if (normalizedValue === undefined) {
|
|
87
|
+
return defValue;
|
|
88
|
+
}
|
|
89
|
+
return normalizedValue;
|
|
90
|
+
}, { equal });
|
|
91
|
+
return asReadable(computed(() => {
|
|
92
|
+
const ownValue = own$();
|
|
93
|
+
return ownValue !== undefined ? ownValue : validatedDefConfig$();
|
|
94
|
+
}, { equal }), {
|
|
95
|
+
set(value) {
|
|
96
|
+
const normalizedValue = value === undefined ? undefined : normalizeValue(value);
|
|
97
|
+
if (normalizedValue === INVALID_VALUE) {
|
|
98
|
+
console.error('Not setting invalid value', value);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
own$.set(normalizedValue);
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
update,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
const isStore = (x) => !!(x && typeof x === 'function' && 'subscribe' in x);
|
|
108
|
+
/**
|
|
109
|
+
* Returns an object containing, for each property of `defConfig`, a corresponding writable with the normalization and default value logic
|
|
110
|
+
* described in {@link writableWithDefault}. Keys in the returned object are the same as the ones present in `defConfig`,
|
|
111
|
+
* with the exta `$` suffix (showing that they are stores).
|
|
112
|
+
*
|
|
113
|
+
* @param defConfig - object containing, for each property, a default value to use in case `config$` does not provide the suitable default
|
|
114
|
+
* value for that property
|
|
115
|
+
* @param config - either a store of objects containing, for each property of `defConfig`, the default value or an object containing
|
|
116
|
+
* for each property of `defConfig` either a store containing the default value or the default value itself
|
|
117
|
+
* @param options - object containing, for each property of `defConfig`, an optional object with the following optional functions: normalizeValue and equal
|
|
118
|
+
* @returns an object containing writables
|
|
119
|
+
*
|
|
120
|
+
* @example With a store
|
|
121
|
+
* ```ts
|
|
122
|
+
* const defConfig = {propA: 1};
|
|
123
|
+
* const validation = {propA: {normalizeValue: value => +value}};
|
|
124
|
+
* const config$ = writable({propA: 5});
|
|
125
|
+
* const {propA$} = writablesWithDefault(defConfig, config$, validation);
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* @example With an object containing a value and a store
|
|
129
|
+
* ```ts
|
|
130
|
+
* const defConfig = {propA: 1, propB: 2};
|
|
131
|
+
* const validation = {propA: {normalizeValue: value => +value}};
|
|
132
|
+
* const config = {propA: 5, propB: writable(3)};
|
|
133
|
+
* const {propA$, propB$} = writablesWithDefault(defConfig, config, validation);
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export const writablesWithDefault = (defConfig, config, options) => {
|
|
137
|
+
const res = {};
|
|
138
|
+
const configIsStore = isStore(config);
|
|
139
|
+
for (const key of Object.keys(defConfig)) {
|
|
140
|
+
let store = configIsStore ? computed(() => config()[key]) : undefined;
|
|
141
|
+
if (!configIsStore && config) {
|
|
142
|
+
const value = config[key];
|
|
143
|
+
store = isStore(value) ? value : readable(value);
|
|
144
|
+
}
|
|
145
|
+
res[`${key}$`] = writableWithDefault(defConfig[key], store, options?.[key]);
|
|
146
|
+
}
|
|
147
|
+
return res;
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Shortcut for calling both {@link writablesWithDefault} and {@link createPatch} in one call.
|
|
151
|
+
* @param defConfig - object containing, for each property, a default value to use in case `config` does not provide the suitable default
|
|
152
|
+
* value for that property
|
|
153
|
+
* @param config - either a store of objects containing, for each property of `defConfig`, the default value or an object containing
|
|
154
|
+
* for each property of `defConfig` either a store containing the default value or the default value itself
|
|
155
|
+
* @param options - object containing, for each property of `defConfig`, an optional object with the following optional functions: normalizeValue and equal
|
|
156
|
+
* @returns an array with two items: the first one containing the writables (returned by {@link writablesWithDefault}),
|
|
157
|
+
* and the second one containing the patch function (returned by {@link createPatch})
|
|
158
|
+
*
|
|
159
|
+
* @example With a store
|
|
160
|
+
* ```ts
|
|
161
|
+
* const defConfig = {propA: 1};
|
|
162
|
+
* const validation = {propA: {normalizeValue: value => +value}};
|
|
163
|
+
* const config$ = writable({propA: 5});
|
|
164
|
+
* const [{propA$}, patch] = writablesForProps(defConfig, config$, validation);
|
|
165
|
+
* ```
|
|
166
|
+
*
|
|
167
|
+
* @example With an object containing a value and a store
|
|
168
|
+
* ```ts
|
|
169
|
+
* const defConfig = {propA: 1, propB: 2};
|
|
170
|
+
* const validation = {propA: {normalizeValue: value => +value}};
|
|
171
|
+
* const config = {propA: 5, propB: writable(3)};
|
|
172
|
+
* const [{propA$, propB$}, patch] = writablesForProps(defConfig, config, validation);
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
export const writablesForProps = (defConfig, config, options) => {
|
|
176
|
+
const stores = writablesWithDefault(defConfig, config, options);
|
|
177
|
+
return [stores, createPatch(stores)];
|
|
178
|
+
};
|
|
179
|
+
export const stateStores = (inputStores) => {
|
|
180
|
+
const storesNames = [];
|
|
181
|
+
const storesArray = [];
|
|
182
|
+
const stores = {};
|
|
183
|
+
for (const key of Object.keys(inputStores)) {
|
|
184
|
+
if (key.endsWith('$')) {
|
|
185
|
+
const store = inputStores[key];
|
|
186
|
+
storesNames.push(key.substring(0, key.length - 1));
|
|
187
|
+
storesArray.push(store);
|
|
188
|
+
stores[key] = asReadable(store);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
stores,
|
|
193
|
+
state$: computed(() => {
|
|
194
|
+
const values = storesArray.map(get);
|
|
195
|
+
const res = {};
|
|
196
|
+
storesNames.forEach((name, index) => {
|
|
197
|
+
res[name] = values[index];
|
|
198
|
+
});
|
|
199
|
+
return res;
|
|
200
|
+
}),
|
|
201
|
+
};
|
|
202
|
+
};
|
|
203
|
+
export const bindableDerived = (onChange$, stores, adjustValue) => {
|
|
204
|
+
let currentValue = stores[0]();
|
|
205
|
+
return derived(stores, (values) => {
|
|
206
|
+
const newValue = adjustValue(values);
|
|
207
|
+
const rectifiedValue = newValue !== values[0];
|
|
208
|
+
if (rectifiedValue) {
|
|
209
|
+
stores[0].set(newValue);
|
|
210
|
+
}
|
|
211
|
+
if (rectifiedValue || newValue !== currentValue) {
|
|
212
|
+
currentValue = newValue;
|
|
213
|
+
// TODO check if we should do this async to avoid issue
|
|
214
|
+
// with angular and react only when rectifiedValue is true?
|
|
215
|
+
onChange$()(newValue);
|
|
216
|
+
}
|
|
217
|
+
return newValue;
|
|
218
|
+
});
|
|
219
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { WritableWithDefaultOptions } from './stores';
|
|
2
|
+
import { INVALID_VALUE } from './stores';
|
|
3
|
+
export declare const testToNormalizeValue: <T>(filter: (value: T) => boolean) => (value: T) => typeof INVALID_VALUE | T;
|
|
4
|
+
export declare const typeNumber: WritableWithDefaultOptions<number>;
|
|
5
|
+
export declare const typeBoolean: WritableWithDefaultOptions<boolean>;
|
|
6
|
+
export declare const typeString: WritableWithDefaultOptions<string, any>;
|
|
7
|
+
export declare const typeFunction: WritableWithDefaultOptions<(...args: any[]) => any>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { isBoolean, isFunction, isNumber, isString } from './checks';
|
|
2
|
+
import { INVALID_VALUE } from './stores';
|
|
3
|
+
export const testToNormalizeValue = (filter) => (value) => filter(value) ? value : INVALID_VALUE;
|
|
4
|
+
export const typeNumber = {
|
|
5
|
+
normalizeValue: testToNormalizeValue(isNumber),
|
|
6
|
+
};
|
|
7
|
+
export const typeBoolean = {
|
|
8
|
+
normalizeValue: testToNormalizeValue(isBoolean),
|
|
9
|
+
};
|
|
10
|
+
export const typeString = {
|
|
11
|
+
normalizeValue: testToNormalizeValue(isString),
|
|
12
|
+
};
|
|
13
|
+
export const typeFunction = {
|
|
14
|
+
normalizeValue: testToNormalizeValue(isFunction),
|
|
15
|
+
equal: Object.is,
|
|
16
|
+
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { PropsConfig } from '../services';
|
|
2
|
+
import type { Directive, Widget } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Function that implements a transition.
|
|
5
|
+
*/
|
|
6
|
+
export type TransitionFn = (
|
|
7
|
+
/**
|
|
8
|
+
* Element on which the transition should be applied.
|
|
9
|
+
*/
|
|
10
|
+
element: HTMLElement,
|
|
11
|
+
/**
|
|
12
|
+
* Whether the element should be shown or hidden.
|
|
13
|
+
*/
|
|
14
|
+
direction: 'show' | 'hide',
|
|
15
|
+
/**
|
|
16
|
+
* Whether the transition should be animated.
|
|
17
|
+
*/
|
|
18
|
+
animation: boolean,
|
|
19
|
+
/**
|
|
20
|
+
* Signal allowing to stop the transition while running.
|
|
21
|
+
*/
|
|
22
|
+
signal: AbortSignal,
|
|
23
|
+
/**
|
|
24
|
+
* Context of the current transition. It is reused between calls if the previous transition was stopped while running on the same element.
|
|
25
|
+
*/
|
|
26
|
+
context: object) => Promise<void>;
|
|
27
|
+
export interface TransitionProps {
|
|
28
|
+
/**
|
|
29
|
+
* Transition to be called.
|
|
30
|
+
*/
|
|
31
|
+
transition: TransitionFn;
|
|
32
|
+
/**
|
|
33
|
+
* Whether the element should be visible when the transition is completed.
|
|
34
|
+
*/
|
|
35
|
+
visible: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Whether the transition should be animated.
|
|
38
|
+
*/
|
|
39
|
+
animation: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* If the element is initially visible, whether the element should be animated when first displayed.
|
|
42
|
+
*/
|
|
43
|
+
animationOnInit: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Whether initialization is finished. It determines which setting between {@link TransitionProps.animation}
|
|
46
|
+
* and {@link TransitionProps.animationOnInit} is used to enable or disable animations.
|
|
47
|
+
* @remarks
|
|
48
|
+
* If it is `true`, initialization is considered finished, and {@link TransitionProps.animationOnInit} is no longer used.
|
|
49
|
+
* Otherwise, initialization is considered unfinished and {@link TransitionProps.animationOnInit} is used instead of {@link TransitionProps.animation}.
|
|
50
|
+
* If it is `null`, it will be set to `true` automatically when the directive is called with a DOM element.
|
|
51
|
+
* If it is `false`, it will not be updated automatically.
|
|
52
|
+
*/
|
|
53
|
+
initDone: boolean | null;
|
|
54
|
+
/**
|
|
55
|
+
* Function to be called when the transition is completed and the element is visible.
|
|
56
|
+
*/
|
|
57
|
+
onShown: () => void;
|
|
58
|
+
/**
|
|
59
|
+
* Function to be called when the transition is completed and the element is not visible.
|
|
60
|
+
*/
|
|
61
|
+
onHidden: () => void;
|
|
62
|
+
/**
|
|
63
|
+
* Function to be called when the visible property changes.
|
|
64
|
+
*
|
|
65
|
+
* @param visible - new value of the visible propery
|
|
66
|
+
*/
|
|
67
|
+
onVisibleChange: (visible: boolean) => void;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Transition state.
|
|
71
|
+
*/
|
|
72
|
+
export interface TransitionState {
|
|
73
|
+
/**
|
|
74
|
+
* Whether the element is visible or will be visible when the transition is completed.
|
|
75
|
+
*/
|
|
76
|
+
visible: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Whether the element to be animated is present in the DOM.
|
|
79
|
+
*/
|
|
80
|
+
elementPresent: boolean;
|
|
81
|
+
/**
|
|
82
|
+
* Reference to the DOM element.
|
|
83
|
+
*/
|
|
84
|
+
element: HTMLElement | null;
|
|
85
|
+
/**
|
|
86
|
+
* Whether a transition is currently running.
|
|
87
|
+
*/
|
|
88
|
+
transitioning: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Equals: {@link TransitionState.visible | visible} && ! {@link TransitionState.transitioning | transitioning}
|
|
91
|
+
*/
|
|
92
|
+
shown: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* Equals: ! {@link TransitionState.visible | visible} && ! {@link TransitionState.transitioning | transitioning}
|
|
95
|
+
*/
|
|
96
|
+
hidden: boolean;
|
|
97
|
+
}
|
|
98
|
+
export interface TransitionApi {
|
|
99
|
+
/**
|
|
100
|
+
* Runs the transition to show the element. It is equivalent to {@link TransitionApi.toggle | toggle} with true as the first parameter.
|
|
101
|
+
*
|
|
102
|
+
* @param animation - whether the transition should be animated. If the parameter is not defined, the {@link TransitionProps.animation | animation } property is used.
|
|
103
|
+
*
|
|
104
|
+
* @returns A promise that is fulfilled when the transition is completed. If the transition is canceled, or if the same transition was
|
|
105
|
+
* already running, the promise never completes.
|
|
106
|
+
*/
|
|
107
|
+
show: (animation?: boolean) => Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Runs the transition to hide the element. It is equivalent to {@link TransitionApi.toggle | toggle} with false as the first parameter.
|
|
110
|
+
*
|
|
111
|
+
* @param animation - whether the transition should be animated. If the parameter is not defined, the {@link TransitionProps.animation | animation } property is used.
|
|
112
|
+
*
|
|
113
|
+
* @returns A promise that is fulfilled when the transition is completed. If the transition is canceled, or if the same transition was
|
|
114
|
+
* already running, the promise never completes.
|
|
115
|
+
*/
|
|
116
|
+
hide: (animation?: boolean) => Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Runs the transition to show or hide the element depending on the first parameter.
|
|
119
|
+
*
|
|
120
|
+
* @param visible - whether the element should be made visible or not. If the parameter is not defined, the opposite of the current {@link TransitionProps.visible | visible } property is used.
|
|
121
|
+
* @param animation - whether the transition should be animated. If the parameter is not defined, the {@link TransitionProps.animation | animation } property is used.
|
|
122
|
+
*
|
|
123
|
+
* @returns A promise that is fulfilled when the transition is completed. If the transition is canceled, or if the same transition was
|
|
124
|
+
* already running, the promise never completes.
|
|
125
|
+
*/
|
|
126
|
+
toggle: (visible?: boolean, animation?: boolean) => Promise<void>;
|
|
127
|
+
}
|
|
128
|
+
export interface TransitionDirectives {
|
|
129
|
+
/**
|
|
130
|
+
* the transition directive
|
|
131
|
+
*/
|
|
132
|
+
directive: Directive<void | Partial<TransitionProps>>;
|
|
133
|
+
}
|
|
134
|
+
export type TransitionWidget = Widget<TransitionProps, TransitionState, TransitionApi, object, TransitionDirectives>;
|
|
135
|
+
export declare const noAnimation: TransitionFn;
|
|
136
|
+
export declare const createTransition: (config?: PropsConfig<TransitionProps>) => TransitionWidget;
|