@agnos-ui/core 0.0.1-alpha.4 → 0.0.1-alpha.6

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.
Files changed (97) hide show
  1. package/{accordion.d.ts → components/accordion/accordion.d.ts} +3 -4
  2. package/{accordion.js → components/accordion/accordion.js} +10 -9
  3. package/components/alert/alert.d.ts +32 -0
  4. package/components/alert/alert.js +23 -0
  5. package/{alert.d.ts → components/alert/common.d.ts} +17 -21
  6. package/{alert.js → components/alert/common.js} +12 -12
  7. package/{modal → components/modal}/modal.d.ts +28 -21
  8. package/{modal → components/modal}/modal.js +39 -13
  9. package/{pagination.d.ts → components/pagination/pagination.d.ts} +3 -3
  10. package/{pagination.js → components/pagination/pagination.js} +6 -4
  11. package/{progressbar.d.ts → components/progressbar/progressbar.d.ts} +2 -3
  12. package/{progressbar.js → components/progressbar/progressbar.js} +6 -6
  13. package/{rating.d.ts → components/rating/rating.d.ts} +2 -3
  14. package/{rating.js → components/rating/rating.js} +6 -9
  15. package/components/select/select.d.ts +337 -0
  16. package/components/select/select.js +266 -0
  17. package/{slider.d.ts → components/slider/slider.d.ts} +60 -14
  18. package/components/slider/slider.js +389 -0
  19. package/config.d.ts +9 -9
  20. package/config.js +3 -3
  21. package/index.d.ts +23 -13
  22. package/index.js +29 -13
  23. package/package.json +30 -3
  24. package/services/extendWidget.d.ts +23 -0
  25. package/{extendWidget.js → services/extendWidget.js} +8 -1
  26. package/services/floatingUI.d.ts +48 -0
  27. package/services/floatingUI.js +97 -0
  28. package/services/focustrack.js +1 -1
  29. package/services/intersection.d.ts +1 -1
  30. package/services/intersection.js +2 -2
  31. package/services/navManager.d.ts +83 -1
  32. package/services/navManager.js +153 -37
  33. package/services/portal.js +8 -4
  34. package/services/siblingsInert.d.ts +2 -1
  35. package/services/siblingsInert.js +2 -2
  36. package/{transitions → services/transitions}/baseTransitions.d.ts +1 -2
  37. package/{transitions → services/transitions}/baseTransitions.js +7 -10
  38. package/services/transitions/bootstrap/collapse.d.ts +2 -0
  39. package/services/transitions/bootstrap/fade.d.ts +1 -0
  40. package/services/transitions/bootstrap.d.ts +2 -0
  41. package/services/transitions/bootstrap.js +2 -0
  42. package/{transitions → services/transitions}/collapse.js +1 -1
  43. package/{transitions → services/transitions}/cssTransitions.js +2 -4
  44. package/{transitions → services/transitions}/simpleClassTransition.js +1 -1
  45. package/types.d.ts +37 -4
  46. package/types.js +1 -0
  47. package/{services/directiveUtils.js → utils/directive.js} +1 -1
  48. package/{services → utils/internal}/checks.d.ts +12 -0
  49. package/{services → utils/internal}/checks.js +12 -0
  50. package/utils/internal/dom.d.ts +13 -0
  51. package/utils/internal/dom.js +49 -0
  52. package/utils/internal/math.d.ts +5 -0
  53. package/utils/internal/math.js +13 -0
  54. package/utils/internal/promise.d.ts +31 -0
  55. package/utils/internal/promise.js +113 -0
  56. package/{modal → utils/internal}/scrollbars.js +1 -1
  57. package/utils/internal/textDirection.d.ts +1 -0
  58. package/utils/internal/textDirection.js +1 -0
  59. package/utils/internal/traversal.d.ts +54 -0
  60. package/utils/internal/traversal.js +105 -0
  61. package/{services → utils}/stores.d.ts +11 -35
  62. package/{services → utils}/stores.js +21 -19
  63. package/utils/writables.d.ts +26 -0
  64. package/utils/writables.js +66 -0
  65. package/extendWidget.d.ts +0 -3
  66. package/select.d.ts +0 -196
  67. package/select.js +0 -240
  68. package/services/index.d.ts +0 -9
  69. package/services/index.js +0 -9
  70. package/services/writables.d.ts +0 -8
  71. package/services/writables.js +0 -30
  72. package/slider.js +0 -289
  73. package/transitions/bootstrap/collapse.d.ts +0 -2
  74. package/transitions/bootstrap/fade.d.ts +0 -1
  75. package/transitions/bootstrap/index.d.ts +0 -2
  76. package/transitions/bootstrap/index.js +0 -2
  77. package/transitions/index.d.ts +0 -5
  78. package/transitions/index.js +0 -5
  79. package/transitions/utils.d.ts +0 -20
  80. package/transitions/utils.js +0 -83
  81. /package/{commonProps.d.ts → components/commonProps.d.ts} +0 -0
  82. /package/{commonProps.js → components/commonProps.js} +0 -0
  83. /package/{pagination.utils.d.ts → components/pagination/bootstrap.d.ts} +0 -0
  84. /package/{pagination.utils.js → components/pagination/bootstrap.js} +0 -0
  85. /package/{transitions → services/transitions}/bootstrap/collapse.js +0 -0
  86. /package/{transitions → services/transitions}/bootstrap/fade.js +0 -0
  87. /package/{transitions → services/transitions}/collapse.d.ts +0 -0
  88. /package/{transitions → services/transitions}/cssTransitions.d.ts +0 -0
  89. /package/{transitions → services/transitions}/simpleClassTransition.d.ts +0 -0
  90. /package/{services/directiveUtils.d.ts → utils/directive.d.ts} +0 -0
  91. /package/{utils.d.ts → utils/internal/func.d.ts} +0 -0
  92. /package/{utils.js → utils/internal/func.js} +0 -0
  93. /package/{services → utils/internal}/isFocusable.d.ts +0 -0
  94. /package/{services → utils/internal}/isFocusable.js +0 -0
  95. /package/{modal → utils/internal}/scrollbars.d.ts +0 -0
  96. /package/{services/sortUtils.d.ts → utils/internal/sort.d.ts} +0 -0
  97. /package/{services/sortUtils.js → utils/internal/sort.js} +0 -0
@@ -0,0 +1,2 @@
1
+ export * from './bootstrap/collapse';
2
+ export * from './bootstrap/fade';
@@ -1,5 +1,5 @@
1
1
  import { createCSSTransition } from './cssTransitions';
2
- import { addClasses, reflow, removeClasses } from './utils';
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 { promiseFromEvent, promiseFromTimeout } from './utils';
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 './utils';
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
- import type { PropsConfig } from './services';
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: Pick<W, 'actions' | 'api' | 'directives' | 'state$' | 'stores'>;
58
+ widget: ContextWidget<W>;
41
59
  }
42
- export declare const toSlotContextWidget: <W extends Widget<object, object, object, object, object>>(w: W) => Pick<W, "actions" | "api" | "directives" | "state$" | "stores">;
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
@@ -5,3 +5,4 @@ export const toSlotContextWidget = (w) => ({
5
5
  state$: w.state$,
6
6
  stores: w.stores,
7
7
  });
8
+ export const INVALID_VALUE = Symbol();
@@ -1,5 +1,5 @@
1
1
  import { asReadable, batch, readable, writable } from '@amadeus-it-group/tansu';
2
- import { noop } from '../utils';
2
+ import { noop } from './internal/func';
3
3
  /**
4
4
  * Binds the given directive to a store that provides its argument.
5
5
  *
@@ -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,5 @@
1
+ /**
2
+ * @param number - decimal number
3
+ * @returns the decimal precision of the number
4
+ */
5
+ export declare function getDecimalPrecision(number: number): number;
@@ -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
+ };
@@ -1,4 +1,4 @@
1
- import { noop } from '../utils';
1
+ import { noop } from './func';
2
2
  const internalRemoveScrollbars = () => {
3
3
  const scrollbarWidth = Math.abs(window.innerWidth - document.documentElement.clientWidth);
4
4
  const body = document.body;
@@ -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, StoreOptions, StoresInputValues, WritableSignal } from '@amadeus-it-group/tansu';
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
- 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>;
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>;