@agnos-ui/core 0.0.1-alpha.4 → 0.0.1-alpha.5
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/{accordion.d.ts → components/accordion/accordion.d.ts} +3 -4
- package/{accordion.js → components/accordion/accordion.js} +10 -9
- package/components/alert/alert.d.ts +32 -0
- package/components/alert/alert.js +23 -0
- package/{alert.d.ts → components/alert/common.d.ts} +17 -21
- package/{alert.js → components/alert/common.js} +12 -12
- package/{modal → components/modal}/modal.d.ts +28 -21
- package/{modal → components/modal}/modal.js +39 -13
- package/{pagination.d.ts → components/pagination/pagination.d.ts} +3 -3
- package/{pagination.js → components/pagination/pagination.js} +6 -4
- package/{progressbar.d.ts → components/progressbar/progressbar.d.ts} +2 -3
- package/{progressbar.js → components/progressbar/progressbar.js} +6 -6
- package/{rating.d.ts → components/rating/rating.d.ts} +2 -3
- package/{rating.js → components/rating/rating.js} +6 -9
- package/components/select/select.d.ts +337 -0
- package/components/select/select.js +266 -0
- package/{slider.d.ts → components/slider/slider.d.ts} +60 -14
- package/components/slider/slider.js +389 -0
- package/config.d.ts +9 -9
- package/config.js +3 -3
- package/index.d.ts +23 -13
- package/index.js +29 -13
- package/package.json +30 -3
- package/services/extendWidget.d.ts +23 -0
- package/{extendWidget.js → services/extendWidget.js} +8 -1
- package/services/floatingUI.d.ts +48 -0
- package/services/floatingUI.js +97 -0
- package/services/focustrack.js +1 -1
- package/services/intersection.d.ts +1 -1
- package/services/intersection.js +2 -2
- package/services/navManager.d.ts +83 -1
- package/services/navManager.js +153 -37
- package/services/portal.js +8 -4
- package/services/siblingsInert.d.ts +2 -1
- package/services/siblingsInert.js +2 -2
- package/{transitions → services/transitions}/baseTransitions.d.ts +1 -2
- package/{transitions → services/transitions}/baseTransitions.js +7 -10
- package/services/transitions/bootstrap/collapse.d.ts +2 -0
- package/services/transitions/bootstrap/fade.d.ts +1 -0
- package/services/transitions/bootstrap.d.ts +2 -0
- package/services/transitions/bootstrap.js +2 -0
- package/{transitions → services/transitions}/collapse.js +1 -1
- package/{transitions → services/transitions}/cssTransitions.js +2 -4
- package/{transitions → services/transitions}/simpleClassTransition.js +1 -1
- package/types.d.ts +37 -4
- package/types.js +1 -0
- package/{services/directiveUtils.js → utils/directive.js} +1 -1
- package/{services → utils/internal}/checks.d.ts +12 -0
- package/{services → utils/internal}/checks.js +12 -0
- package/utils/internal/dom.d.ts +13 -0
- package/utils/internal/dom.js +49 -0
- package/utils/internal/math.d.ts +5 -0
- package/utils/internal/math.js +13 -0
- package/utils/internal/promise.d.ts +31 -0
- package/utils/internal/promise.js +113 -0
- package/{modal → utils/internal}/scrollbars.js +1 -1
- package/utils/internal/textDirection.d.ts +1 -0
- package/utils/internal/textDirection.js +1 -0
- package/utils/internal/traversal.d.ts +54 -0
- package/utils/internal/traversal.js +105 -0
- package/{services → utils}/stores.d.ts +11 -35
- package/{services → utils}/stores.js +21 -19
- package/utils/writables.d.ts +26 -0
- package/utils/writables.js +66 -0
- package/extendWidget.d.ts +0 -3
- package/select.d.ts +0 -196
- package/select.js +0 -240
- package/services/index.d.ts +0 -9
- package/services/index.js +0 -9
- package/services/writables.d.ts +0 -8
- package/services/writables.js +0 -30
- package/slider.js +0 -289
- package/transitions/bootstrap/collapse.d.ts +0 -2
- package/transitions/bootstrap/fade.d.ts +0 -1
- package/transitions/bootstrap/index.d.ts +0 -2
- package/transitions/bootstrap/index.js +0 -2
- package/transitions/index.d.ts +0 -5
- package/transitions/index.js +0 -5
- package/transitions/utils.d.ts +0 -20
- package/transitions/utils.js +0 -83
- /package/{commonProps.d.ts → components/commonProps.d.ts} +0 -0
- /package/{commonProps.js → components/commonProps.js} +0 -0
- /package/{pagination.utils.d.ts → components/pagination/bootstrap.d.ts} +0 -0
- /package/{pagination.utils.js → components/pagination/bootstrap.js} +0 -0
- /package/{transitions → services/transitions}/bootstrap/collapse.js +0 -0
- /package/{transitions → services/transitions}/bootstrap/fade.js +0 -0
- /package/{transitions → services/transitions}/collapse.d.ts +0 -0
- /package/{transitions → services/transitions}/cssTransitions.d.ts +0 -0
- /package/{transitions → services/transitions}/simpleClassTransition.d.ts +0 -0
- /package/{services/directiveUtils.d.ts → utils/directive.d.ts} +0 -0
- /package/{utils.d.ts → utils/internal/func.d.ts} +0 -0
- /package/{utils.js → utils/internal/func.js} +0 -0
- /package/{services → utils/internal}/isFocusable.d.ts +0 -0
- /package/{services → utils/internal}/isFocusable.js +0 -0
- /package/{modal → utils/internal}/scrollbars.d.ts +0 -0
- /package/{services/sortUtils.d.ts → utils/internal/sort.d.ts} +0 -0
- /package/{services/sortUtils.js → utils/internal/sort.js} +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createCSSTransition } from './cssTransitions';
|
|
2
|
-
import { addClasses, reflow, removeClasses } from '
|
|
2
|
+
import { addClasses, reflow, removeClasses } from '../../utils/internal/dom';
|
|
3
3
|
export const createCollapseTransition = ({ dimension = 'height', showClasses, hideClasses, animationPendingClasses } = {}) => createCSSTransition((element, direction, animation, context) => {
|
|
4
4
|
if (animation) {
|
|
5
5
|
let { maxSize, minSize } = context;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { noop } from '../../utils/internal/func';
|
|
2
|
+
import { promiseFromEvent, promiseFromTimeout } from '../../utils/internal/promise';
|
|
2
3
|
/**
|
|
3
4
|
* Check if the provided html element has a transition
|
|
4
5
|
* @param element - the html element
|
|
@@ -18,9 +19,6 @@ export function getTransitionDurationMs(element) {
|
|
|
18
19
|
const transitionDurationSec = parseFloat(transitionDuration);
|
|
19
20
|
return (transitionDelaySec + transitionDurationSec) * 1000;
|
|
20
21
|
}
|
|
21
|
-
const noop = () => {
|
|
22
|
-
/* do nothing */
|
|
23
|
-
};
|
|
24
22
|
export const createCSSTransition = (start) => async (element, direction, animation, signal, context) => {
|
|
25
23
|
const endFn = start(element, direction, animation, context) ?? noop;
|
|
26
24
|
if (animation && hasTransition(element)) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createCSSTransition } from './cssTransitions';
|
|
2
|
-
import { addClasses, reflow, removeClasses } from '
|
|
2
|
+
import { addClasses, reflow, removeClasses } from '../../utils/internal/dom';
|
|
3
3
|
export const createSimpleClassTransition = ({ animationPendingClasses, animationPendingShowClasses, animationPendingHideClasses, showClasses, hideClasses, }) => createCSSTransition((element, direction, animation, context) => {
|
|
4
4
|
removeClasses(element, showClasses);
|
|
5
5
|
removeClasses(element, hideClasses);
|
package/types.d.ts
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
|
-
import type { ReadableSignal, SubscribableStore } from '@amadeus-it-group/tansu';
|
|
2
|
-
|
|
1
|
+
import type { ReadableSignal, StoreOptions, SubscribableStore, WritableSignal } from '@amadeus-it-group/tansu';
|
|
2
|
+
export type ValuesOrReadableSignals<T extends object> = {
|
|
3
|
+
[K in keyof T]?: ReadableSignal<T[K] | undefined> | T[K];
|
|
4
|
+
};
|
|
5
|
+
export type ValuesOrWritableSignals<T extends object> = {
|
|
6
|
+
[K in keyof T]?: WritableSignal<T[K] | undefined> | T[K];
|
|
7
|
+
};
|
|
8
|
+
export interface PropsConfig<U extends object> {
|
|
9
|
+
/**
|
|
10
|
+
* Object containing, for each property, either its initial value, or a store that will contain the value at any time.
|
|
11
|
+
* When the value of a property is undefined or invalid, the value from the config is used.
|
|
12
|
+
*/
|
|
13
|
+
props?: ValuesOrWritableSignals<U>;
|
|
14
|
+
/**
|
|
15
|
+
* Either a store of objects containing, for each property, the default value,
|
|
16
|
+
* or an object containing, for each property, either a store containing the default value or the default value itself.
|
|
17
|
+
*/
|
|
18
|
+
config?: ReadableSignal<Partial<U>> | ValuesOrReadableSignals<Partial<U>>;
|
|
19
|
+
}
|
|
3
20
|
export interface Widget<Props extends object = object, State extends object = object, Api extends object = object, Actions extends object = object, Directives extends object = object> {
|
|
4
21
|
/**
|
|
5
22
|
* the reactive state of the widget, combining all the values served by the stores
|
|
@@ -29,6 +46,7 @@ export interface Widget<Props extends object = object, State extends object = ob
|
|
|
29
46
|
*/
|
|
30
47
|
api: Api;
|
|
31
48
|
}
|
|
49
|
+
export type ContextWidget<W extends Widget> = Pick<W, 'actions' | 'api' | 'directives' | 'state$' | 'stores'>;
|
|
32
50
|
export interface WidgetSlotContext<W extends Widget> {
|
|
33
51
|
/**
|
|
34
52
|
* the state of the widget
|
|
@@ -37,9 +55,9 @@ export interface WidgetSlotContext<W extends Widget> {
|
|
|
37
55
|
/**
|
|
38
56
|
* the widget
|
|
39
57
|
*/
|
|
40
|
-
widget:
|
|
58
|
+
widget: ContextWidget<W>;
|
|
41
59
|
}
|
|
42
|
-
export declare const toSlotContextWidget: <W extends Widget<object, object, object, object, object>>(w: W) =>
|
|
60
|
+
export declare const toSlotContextWidget: <W extends Widget<object, object, object, object, object>>(w: W) => ContextWidget<W>;
|
|
43
61
|
export type WidgetState<T extends {
|
|
44
62
|
state$: SubscribableStore<any>;
|
|
45
63
|
}> = T extends {
|
|
@@ -56,3 +74,18 @@ export type Directive<T = void> = (node: HTMLElement, args: T) => void | {
|
|
|
56
74
|
destroy?: () => void;
|
|
57
75
|
};
|
|
58
76
|
export type SlotContent<Props extends object = object> = undefined | null | string | ((props: Props) => string);
|
|
77
|
+
export declare const INVALID_VALUE: unique symbol;
|
|
78
|
+
export type NormalizeValue<T> = (value: T) => T | typeof INVALID_VALUE;
|
|
79
|
+
export interface WritableWithDefaultOptions<T> {
|
|
80
|
+
/**
|
|
81
|
+
* the normalize value function. should return the invalidValue symbol when the provided value is invalid
|
|
82
|
+
*/
|
|
83
|
+
normalizeValue?: NormalizeValue<T>;
|
|
84
|
+
/**
|
|
85
|
+
* the equal function, allowing to compare two values. used to check if a previous and current values are equals.
|
|
86
|
+
*/
|
|
87
|
+
equal?: StoreOptions<T>['equal'];
|
|
88
|
+
}
|
|
89
|
+
export type ConfigValidator<T extends object> = {
|
|
90
|
+
[K in keyof T]?: WritableWithDefaultOptions<T[K]>;
|
|
91
|
+
};
|
package/types.js
CHANGED
|
@@ -35,3 +35,15 @@ export declare const isArray: (arg: any) => arg is any[];
|
|
|
35
35
|
* @returns the clamped value
|
|
36
36
|
*/
|
|
37
37
|
export declare function clamp(value: number, max: number, min?: number): number;
|
|
38
|
+
/**
|
|
39
|
+
* an html element type guard
|
|
40
|
+
* @param value the value to check
|
|
41
|
+
* @returns true if the value is an instance of HTMLElement
|
|
42
|
+
*/
|
|
43
|
+
export declare const isHTMLElement: (value: any) => value is HTMLElement;
|
|
44
|
+
/**
|
|
45
|
+
* Returns a new type guard that is based on the provided type guard and also returns true for null values.
|
|
46
|
+
* @param isType base type guard
|
|
47
|
+
* @returns A type guard function that returns true for null values and calls the provided type guard for other values.
|
|
48
|
+
*/
|
|
49
|
+
export declare const allowNull: <T>(isType: (value: any) => value is T) => (value: any) => value is T | null;
|
|
@@ -46,3 +46,15 @@ export const isArray = Array.isArray;
|
|
|
46
46
|
export function clamp(value, max, min = 0) {
|
|
47
47
|
return Math.max(Math.min(value, max), min);
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* an html element type guard
|
|
51
|
+
* @param value the value to check
|
|
52
|
+
* @returns true if the value is an instance of HTMLElement
|
|
53
|
+
*/
|
|
54
|
+
export const isHTMLElement = (value) => value instanceof HTMLElement;
|
|
55
|
+
/**
|
|
56
|
+
* Returns a new type guard that is based on the provided type guard and also returns true for null values.
|
|
57
|
+
* @param isType base type guard
|
|
58
|
+
* @returns A type guard function that returns true for null values and calls the provided type guard for other values.
|
|
59
|
+
*/
|
|
60
|
+
export const allowNull = (isType) => (value) => value === null || isType(value);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the common ancestor of the provided DOM elements.
|
|
3
|
+
* @param elements - array of DOM elements
|
|
4
|
+
* @returns the common ancestor, or null if the array is empty or if there is no common ancestor (e.g.: if elements are detached)
|
|
5
|
+
*/
|
|
6
|
+
export declare const computeCommonAncestor: (elements: HTMLElement[]) => HTMLElement | null;
|
|
7
|
+
/**
|
|
8
|
+
* Launch a reflow using a call to the provided html element getBoudingClientRect
|
|
9
|
+
* @param element - the html element
|
|
10
|
+
*/
|
|
11
|
+
export declare function reflow(element?: HTMLElement): void;
|
|
12
|
+
export declare const addClasses: (element: HTMLElement, classes?: string[]) => void;
|
|
13
|
+
export declare const removeClasses: (element: HTMLElement, classes?: string[]) => void;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the common ancestor of the provided DOM elements.
|
|
3
|
+
* @param elements - array of DOM elements
|
|
4
|
+
* @returns the common ancestor, or null if the array is empty or if there is no common ancestor (e.g.: if elements are detached)
|
|
5
|
+
*/
|
|
6
|
+
export const computeCommonAncestor = (elements) => {
|
|
7
|
+
const length = elements.length;
|
|
8
|
+
if (length === 0)
|
|
9
|
+
return null;
|
|
10
|
+
let ancestor = elements[0];
|
|
11
|
+
for (let i = 1; i < length && ancestor; i++) {
|
|
12
|
+
const element = elements[i];
|
|
13
|
+
while (ancestor) {
|
|
14
|
+
if (ancestor === element) {
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
const comparison = ancestor.compareDocumentPosition(element);
|
|
18
|
+
if (comparison & Node.DOCUMENT_POSITION_CONTAINED_BY) {
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
else if (comparison & Node.DOCUMENT_POSITION_CONTAINS) {
|
|
22
|
+
ancestor = element;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
else if (comparison & Node.DOCUMENT_POSITION_DISCONNECTED) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
ancestor = ancestor.parentElement;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return ancestor;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Launch a reflow using a call to the provided html element getBoudingClientRect
|
|
35
|
+
* @param element - the html element
|
|
36
|
+
*/
|
|
37
|
+
export function reflow(element = document.body) {
|
|
38
|
+
element.getBoundingClientRect();
|
|
39
|
+
}
|
|
40
|
+
export const addClasses = (element, classes) => {
|
|
41
|
+
if (classes && classes.length > 0) {
|
|
42
|
+
element.classList.add(...classes);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
export const removeClasses = (element, classes) => {
|
|
46
|
+
if (classes && classes.length > 0) {
|
|
47
|
+
element.classList.remove(...classes);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const decimalRegExp = /(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/;
|
|
2
|
+
/**
|
|
3
|
+
* @param number - decimal number
|
|
4
|
+
* @returns the decimal precision of the number
|
|
5
|
+
*/
|
|
6
|
+
export function getDecimalPrecision(number) {
|
|
7
|
+
const matches = ('' + number).match(decimalRegExp);
|
|
8
|
+
return Math.max(0,
|
|
9
|
+
// Number of digits right of decimal point.
|
|
10
|
+
(matches[1]?.length ?? 0) -
|
|
11
|
+
// Adjust for exponential notation.
|
|
12
|
+
(+matches[2] || 0));
|
|
13
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ReadableSignal } from '@amadeus-it-group/tansu';
|
|
2
|
+
export interface PromisePendingResult {
|
|
3
|
+
/** Pending status */
|
|
4
|
+
status: 'pending';
|
|
5
|
+
}
|
|
6
|
+
export declare const promisePending: PromisePendingResult;
|
|
7
|
+
export type PromiseState<T> = PromiseFulfilledResult<T> | PromiseRejectedResult | PromisePendingResult;
|
|
8
|
+
export declare const promiseStateStore: <T>(value: T) => ReadableSignal<Readonly<PromiseState<Awaited<T>>>>;
|
|
9
|
+
export declare const promiseStoreToPromiseStateStore: <T>(promiseStore$: ReadableSignal<T>) => ReadableSignal<PromiseState<Awaited<T>>>;
|
|
10
|
+
export declare const promiseStateStoreToValueStore: <T>(store$: ReadableSignal<PromiseState<T>>, initialValue: T, equal?: ((a: T, b: T) => boolean) | undefined) => ReadableSignal<T>;
|
|
11
|
+
export declare const promiseStoreToValueStore: <T>(promiseStore$: ReadableSignal<T>, initialValue: Awaited<T>, equal?: ((a: Awaited<T>, b: Awaited<T>) => boolean) | undefined) => ReadableSignal<Awaited<T>>;
|
|
12
|
+
export declare const promiseFromStore: <T>(store: ReadableSignal<T>, condition?: (value: T) => boolean) => {
|
|
13
|
+
promise: Promise<T>;
|
|
14
|
+
unsubscribe(): void;
|
|
15
|
+
};
|
|
16
|
+
export declare const promiseFromEvent: (element: EventTarget, event: string) => {
|
|
17
|
+
promise: Promise<Event>;
|
|
18
|
+
unsubscribe(): void;
|
|
19
|
+
};
|
|
20
|
+
export declare const promiseFromTimeout: (delay: number) => {
|
|
21
|
+
promise: Promise<void>;
|
|
22
|
+
unsubscribe(): void;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Utility method to create a promise with resolve
|
|
26
|
+
* @returns a promise with resolve
|
|
27
|
+
*/
|
|
28
|
+
export declare const promiseWithResolve: () => {
|
|
29
|
+
promise: Promise<void>;
|
|
30
|
+
resolve: (value: void | Promise<void>) => void;
|
|
31
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { asReadable, computed, derived, equal, readable, writable } from '@amadeus-it-group/tansu';
|
|
2
|
+
import { noop } from './func';
|
|
3
|
+
export const promisePending = { status: 'pending' };
|
|
4
|
+
const isThenable = (value) => {
|
|
5
|
+
// cf https://tc39.es/ecma262/#sec-promise-resolve-functions
|
|
6
|
+
const type = typeof value;
|
|
7
|
+
return (type === 'object' && value !== null) || type === 'function' ? typeof value.then === 'function' : false;
|
|
8
|
+
};
|
|
9
|
+
const createPromiseStateStore = (promise) => {
|
|
10
|
+
const store = writable(promisePending);
|
|
11
|
+
Promise.resolve(promise).then((value) => store.set({ status: 'fulfilled', value }), (reason) => store.set({ status: 'rejected', reason }));
|
|
12
|
+
return asReadable(store);
|
|
13
|
+
};
|
|
14
|
+
const promiseWeakMap = new WeakMap();
|
|
15
|
+
export const promiseStateStore = (value) => {
|
|
16
|
+
if (!isThenable(value)) {
|
|
17
|
+
return readable({ status: 'fulfilled', value: value });
|
|
18
|
+
}
|
|
19
|
+
let response = promiseWeakMap.get(value);
|
|
20
|
+
if (!response) {
|
|
21
|
+
response = createPromiseStateStore(value);
|
|
22
|
+
promiseWeakMap.set(value, response);
|
|
23
|
+
}
|
|
24
|
+
return response;
|
|
25
|
+
};
|
|
26
|
+
const promiseStateStoreEqual = (a, b) => Object.is(a, b) ||
|
|
27
|
+
(a.status === b.status &&
|
|
28
|
+
(a.status !== 'fulfilled' || equal(a.value, b.value)) &&
|
|
29
|
+
(a.status !== 'rejected' || equal(a.reason, b.reason)));
|
|
30
|
+
export const promiseStoreToPromiseStateStore = (promiseStore$) => computed(() => promiseStateStore(promiseStore$())(), { equal: promiseStateStoreEqual });
|
|
31
|
+
export const promiseStateStoreToValueStore = (store$, initialValue, equal) => derived(store$, {
|
|
32
|
+
derive: (state, set) => {
|
|
33
|
+
if (state.status === 'fulfilled') {
|
|
34
|
+
set(state.value);
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
equal,
|
|
38
|
+
}, initialValue);
|
|
39
|
+
export const promiseStoreToValueStore = (promiseStore$, initialValue, equal) => promiseStateStoreToValueStore(promiseStoreToPromiseStateStore(promiseStore$), initialValue, equal);
|
|
40
|
+
const truthyValue = (value) => !!value;
|
|
41
|
+
export const promiseFromStore = (store, condition = truthyValue) => {
|
|
42
|
+
let resolve;
|
|
43
|
+
const promise = new Promise((r) => (resolve = r));
|
|
44
|
+
let unsubscribe = () => {
|
|
45
|
+
storeUnsubscribe();
|
|
46
|
+
unsubscribe = noop;
|
|
47
|
+
};
|
|
48
|
+
let storeUnsubscribe = noop;
|
|
49
|
+
storeUnsubscribe = store.subscribe((value) => {
|
|
50
|
+
if (condition(value)) {
|
|
51
|
+
resolve(value);
|
|
52
|
+
unsubscribe();
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
if (unsubscribe === noop) {
|
|
56
|
+
storeUnsubscribe();
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
promise,
|
|
60
|
+
unsubscribe() {
|
|
61
|
+
unsubscribe();
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
export const promiseFromEvent = (element, event) => {
|
|
66
|
+
let resolve;
|
|
67
|
+
const promise = new Promise((r) => (resolve = r));
|
|
68
|
+
let unsubscribe = () => {
|
|
69
|
+
element.removeEventListener(event, eventListener);
|
|
70
|
+
unsubscribe = noop;
|
|
71
|
+
};
|
|
72
|
+
const eventListener = (event) => {
|
|
73
|
+
if (event.target === element) {
|
|
74
|
+
resolve(event);
|
|
75
|
+
unsubscribe();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
element.addEventListener(event, eventListener);
|
|
79
|
+
return {
|
|
80
|
+
promise,
|
|
81
|
+
unsubscribe() {
|
|
82
|
+
unsubscribe();
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
export const promiseFromTimeout = (delay) => {
|
|
87
|
+
let timeout;
|
|
88
|
+
return {
|
|
89
|
+
promise: new Promise((r) => {
|
|
90
|
+
timeout = setTimeout(() => {
|
|
91
|
+
timeout = undefined;
|
|
92
|
+
r();
|
|
93
|
+
}, delay);
|
|
94
|
+
}),
|
|
95
|
+
unsubscribe() {
|
|
96
|
+
if (timeout) {
|
|
97
|
+
clearTimeout(timeout);
|
|
98
|
+
timeout = undefined;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Utility method to create a promise with resolve
|
|
105
|
+
* @returns a promise with resolve
|
|
106
|
+
*/
|
|
107
|
+
export const promiseWithResolve = () => {
|
|
108
|
+
let resolve;
|
|
109
|
+
const promise = new Promise((r) => {
|
|
110
|
+
resolve = r;
|
|
111
|
+
});
|
|
112
|
+
return { promise, resolve: resolve };
|
|
113
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getTextDirection: (element: HTMLElement) => "rtl" | "ltr";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const getTextDirection = (element) => getComputedStyle(element).direction;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
interface TraversalFnOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Remove symbol to return to remove the value
|
|
4
|
+
*/
|
|
5
|
+
removeSymbol?: symbol;
|
|
6
|
+
/**
|
|
7
|
+
* index of the array, when looping on the elements
|
|
8
|
+
*/
|
|
9
|
+
index?: number;
|
|
10
|
+
}
|
|
11
|
+
type TraversalFn = (key: string, value: any, options: TraversalFnOptions) => any;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a JSON walker function that can be used to traverse and transform
|
|
14
|
+
* the properties of a JSON object.
|
|
15
|
+
*
|
|
16
|
+
* @param fn - The callback function called for each property in the JSON object.
|
|
17
|
+
* @returns A function that takes a JSON object as input and applies the provided
|
|
18
|
+
* callback function to each property.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const json = {
|
|
23
|
+
* name: 'John',
|
|
24
|
+
* age: 30,
|
|
25
|
+
* address: {
|
|
26
|
+
* city: 'New York',
|
|
27
|
+
* country: 'USA',
|
|
28
|
+
* },
|
|
29
|
+
* useless: '',
|
|
30
|
+
* };
|
|
31
|
+
*
|
|
32
|
+
* const transform = createTraversal((key, value, {removeSymbol}) => {
|
|
33
|
+
* if (key === 'age') {
|
|
34
|
+
* return value * 2; // Double the age
|
|
35
|
+
* }
|
|
36
|
+
* if (key === 'useless') {
|
|
37
|
+
* return removeSymbol;
|
|
38
|
+
* }
|
|
39
|
+
* return value;
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* const transformedJson = transform(json);
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function createTraversal(fn: TraversalFn): (json: any) => any;
|
|
46
|
+
/**
|
|
47
|
+
* Utility method to create a promise with resolve
|
|
48
|
+
* @returns a promise with resolve
|
|
49
|
+
*/
|
|
50
|
+
export declare const promiseWithResolve: () => {
|
|
51
|
+
promise: Promise<void>;
|
|
52
|
+
resolve: (value: void | Promise<void>) => void;
|
|
53
|
+
};
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
const removeSymbol = Symbol('remove');
|
|
2
|
+
function _traversal(key, value, fn, index) {
|
|
3
|
+
const transformedValue = fn(key, value, { removeSymbol, index });
|
|
4
|
+
const type = Object.prototype.toString.call(transformedValue);
|
|
5
|
+
switch (type) {
|
|
6
|
+
case '[object Object]': {
|
|
7
|
+
const newJson = {};
|
|
8
|
+
const baseKey = key ? key + '.' : '';
|
|
9
|
+
for (const [name, objectValue] of Object.entries(transformedValue)) {
|
|
10
|
+
const newValue = _traversal(baseKey + name, objectValue, fn);
|
|
11
|
+
if (newValue !== removeSymbol) {
|
|
12
|
+
newJson[name] = newValue;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return newJson;
|
|
16
|
+
}
|
|
17
|
+
case '[object Map]': {
|
|
18
|
+
const oldMap = transformedValue;
|
|
19
|
+
const newMap = new Map();
|
|
20
|
+
const baseKey = key ? key + '.' : '';
|
|
21
|
+
for (const [mapKey, objectValue] of Object.entries(oldMap)) {
|
|
22
|
+
const newValue = _traversal(baseKey + name, objectValue, fn);
|
|
23
|
+
if (newValue !== removeSymbol) {
|
|
24
|
+
newMap.set(mapKey, newValue);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return newMap;
|
|
28
|
+
}
|
|
29
|
+
case '[object Array]': {
|
|
30
|
+
const ar = transformedValue;
|
|
31
|
+
const newArray = [];
|
|
32
|
+
const baseKey = (key ? key : '') + '[]';
|
|
33
|
+
for (let i = 0; i < ar.length; i++) {
|
|
34
|
+
const newValue = _traversal(baseKey, ar[i], fn, i);
|
|
35
|
+
if (newValue !== removeSymbol) {
|
|
36
|
+
newArray.push(newValue);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return newArray;
|
|
40
|
+
}
|
|
41
|
+
case '[object Set]': {
|
|
42
|
+
const oldSet = transformedValue;
|
|
43
|
+
const newSet = new Set();
|
|
44
|
+
const baseKey = (key ? key : '') + '[]';
|
|
45
|
+
const ar = [...oldSet];
|
|
46
|
+
for (let i = 0; i < ar.length; i++) {
|
|
47
|
+
const newValue = _traversal(baseKey, ar[i], fn, i);
|
|
48
|
+
if (newValue !== removeSymbol) {
|
|
49
|
+
newSet.add(newValue);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return newSet;
|
|
53
|
+
}
|
|
54
|
+
default:
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
return transformedValue;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Creates a JSON walker function that can be used to traverse and transform
|
|
61
|
+
* the properties of a JSON object.
|
|
62
|
+
*
|
|
63
|
+
* @param fn - The callback function called for each property in the JSON object.
|
|
64
|
+
* @returns A function that takes a JSON object as input and applies the provided
|
|
65
|
+
* callback function to each property.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* const json = {
|
|
70
|
+
* name: 'John',
|
|
71
|
+
* age: 30,
|
|
72
|
+
* address: {
|
|
73
|
+
* city: 'New York',
|
|
74
|
+
* country: 'USA',
|
|
75
|
+
* },
|
|
76
|
+
* useless: '',
|
|
77
|
+
* };
|
|
78
|
+
*
|
|
79
|
+
* const transform = createTraversal((key, value, {removeSymbol}) => {
|
|
80
|
+
* if (key === 'age') {
|
|
81
|
+
* return value * 2; // Double the age
|
|
82
|
+
* }
|
|
83
|
+
* if (key === 'useless') {
|
|
84
|
+
* return removeSymbol;
|
|
85
|
+
* }
|
|
86
|
+
* return value;
|
|
87
|
+
* });
|
|
88
|
+
*
|
|
89
|
+
* const transformedJson = transform(json);
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export function createTraversal(fn) {
|
|
93
|
+
return (json) => _traversal('', json, fn);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Utility method to create a promise with resolve
|
|
97
|
+
* @returns a promise with resolve
|
|
98
|
+
*/
|
|
99
|
+
export const promiseWithResolve = () => {
|
|
100
|
+
let resolve;
|
|
101
|
+
const promise = new Promise((r) => {
|
|
102
|
+
resolve = r;
|
|
103
|
+
});
|
|
104
|
+
return { promise, resolve: resolve };
|
|
105
|
+
};
|
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import type { ReadableSignal, StoreInput,
|
|
1
|
+
import type { ReadableSignal, StoreInput, StoresInputValues, WritableSignal } from '@amadeus-it-group/tansu';
|
|
2
|
+
import type { ConfigValidator, PropsConfig, ValuesOrReadableSignals, WritableWithDefaultOptions } from '../types';
|
|
2
3
|
export type ToWritableSignal<P> = {
|
|
3
4
|
[K in keyof P as `${K & string}$`]-?: WritableSignal<P[K], P[K] | undefined>;
|
|
4
5
|
};
|
|
5
6
|
export type ReadableSignals<T extends object> = {
|
|
6
7
|
[K in keyof T]?: ReadableSignal<T[K] | undefined>;
|
|
7
8
|
};
|
|
8
|
-
export type ValuesOrReadableSignals<T extends object> = {
|
|
9
|
-
[K in keyof T]?: ReadableSignal<T[K] | undefined> | T[K];
|
|
10
|
-
};
|
|
11
|
-
export type ValuesOrWritableSignals<T extends object> = {
|
|
12
|
-
[K in keyof T]?: WritableSignal<T[K] | undefined> | T[K];
|
|
13
|
-
};
|
|
14
9
|
export type WithoutDollar<S extends `${string}$`> = S extends `${infer U}$` ? U : never;
|
|
15
10
|
export type ValueOfStore<S extends ReadableSignal<any>> = S extends ReadableSignal<infer U> ? U : never;
|
|
16
11
|
export type ToState<S extends {
|
|
@@ -51,18 +46,6 @@ export declare function createPatch<T extends object>(stores: ToWritableSignal<T
|
|
|
51
46
|
* @returns the object with changed properties
|
|
52
47
|
*/
|
|
53
48
|
export declare function findChangedProperties<T extends Record<string, any>>(obj1: Partial<T>, obj2: Partial<T>): Partial<T> | null;
|
|
54
|
-
export declare const INVALID_VALUE: unique symbol;
|
|
55
|
-
export type NormalizeValue<T> = (value: T) => T | typeof INVALID_VALUE;
|
|
56
|
-
export interface WritableWithDefaultOptions<T> {
|
|
57
|
-
/**
|
|
58
|
-
* the normalize value function. should return the invalidValue symbol when the provided value is invalid
|
|
59
|
-
*/
|
|
60
|
-
normalizeValue?: NormalizeValue<T>;
|
|
61
|
-
/**
|
|
62
|
-
* the equal function, allowing to compare two values. used to check if a previous and current values are equals.
|
|
63
|
-
*/
|
|
64
|
-
equal?: StoreOptions<T>['equal'];
|
|
65
|
-
}
|
|
66
49
|
/**
|
|
67
50
|
* Returns a writable store whose value is either its own value (when it is not undefined) or a default value
|
|
68
51
|
* that comes either from the `config$` store (when it is not undefined) or from `defValue`.
|
|
@@ -78,9 +61,6 @@ export interface WritableWithDefaultOptions<T> {
|
|
|
78
61
|
* @returns a writable store with the extra default value and normalization logic described above
|
|
79
62
|
*/
|
|
80
63
|
export declare function writableWithDefault<T>(defValue: T, config$?: ReadableSignal<T | undefined>, options?: WritableWithDefaultOptions<T>, own$?: WritableSignal<T | undefined>): WritableSignal<T, T | undefined>;
|
|
81
|
-
export type ConfigValidator<T extends object> = {
|
|
82
|
-
[K in keyof T]?: WritableWithDefaultOptions<T[K]>;
|
|
83
|
-
};
|
|
84
64
|
/**
|
|
85
65
|
* Returns true if the provided argument is a store (ReadableSignal).
|
|
86
66
|
* @param x - argument that is tested
|
|
@@ -156,22 +136,18 @@ export declare const writablesWithDefault: <T extends object>(defConfig: T, prop
|
|
|
156
136
|
* ```
|
|
157
137
|
*/
|
|
158
138
|
export declare const writablesForProps: <T extends object>(defConfig: T, propsConfig?: PropsConfig<T> | undefined, options?: { [K in keyof T]?: WritableWithDefaultOptions<T[K]> | undefined; } | undefined) => [ToWritableSignal<T>, <U extends Partial<T>>(storesValues?: void | U | undefined) => void];
|
|
159
|
-
export interface PropsConfig<U extends object> {
|
|
160
|
-
/**
|
|
161
|
-
* Object containing, for each property, either its initial value, or a store that will contain the value at any time.
|
|
162
|
-
* When the value of a property is undefined or invalid, the value from the config is used.
|
|
163
|
-
*/
|
|
164
|
-
props?: ValuesOrWritableSignals<U>;
|
|
165
|
-
/**
|
|
166
|
-
* Either a store of objects containing, for each property, the default value,
|
|
167
|
-
* or an object containing, for each property, either a store containing the default value or the default value itself.
|
|
168
|
-
*/
|
|
169
|
-
config?: ReadableSignal<Partial<U>> | ValuesOrReadableSignals<Partial<U>>;
|
|
170
|
-
}
|
|
171
139
|
export declare const stateStores: <A extends {
|
|
172
140
|
[x: `${string}$`]: ReadableSignal<any>;
|
|
173
141
|
}>(inputStores: A) => {
|
|
174
142
|
state$: ReadableSignal<ToState<A>>;
|
|
175
143
|
stores: { [key in `${string}$` & keyof A]: ReadableSignal<ValueOfStore<A[key]>>; };
|
|
176
144
|
};
|
|
177
|
-
|
|
145
|
+
/**
|
|
146
|
+
* Creates a computed store that binds to multiple stores and triggers a callback when the value changes.
|
|
147
|
+
* @param onChange$ - A readable signal callback function to execute when the value changes.
|
|
148
|
+
* @param stores - An array of Svelte stores, with the main store at index 0.
|
|
149
|
+
* @param adjustValue - A function to adjust the value of the main store. By default, the value of the main store is returned.
|
|
150
|
+
* @param equal - A function to determine if two values are equal. Used to compare the ajusted value with the current one.
|
|
151
|
+
* @returns The derived store that reflects the combined state of the input stores.
|
|
152
|
+
*/
|
|
153
|
+
export declare const bindableDerived: <T, U extends [WritableSignal<T, T>, ...StoreInput<any>[]]>(onChange$: ReadableSignal<(value: T) => void>, stores: U, adjustValue?: (arg: StoresInputValues<U>) => T, equal?: (currentValue: T, newValue: T) => boolean) => ReadableSignal<T>;
|