@agnos-ui/core 0.0.1-alpha.0 → 0.0.1-alpha.10

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 (126) hide show
  1. package/README.md +4 -4
  2. package/{dist/lib → components/accordion}/accordion.d.ts +29 -25
  3. package/{dist/lib → components/accordion}/accordion.js +81 -77
  4. package/components/accordion/index.d.ts +1 -0
  5. package/components/accordion/index.js +1 -0
  6. package/components/alert/alert.d.ts +31 -0
  7. package/components/alert/alert.js +22 -0
  8. package/{dist/lib/alert.d.ts → components/alert/common.d.ts} +17 -20
  9. package/{dist/lib/alert.js → components/alert/common.js} +22 -19
  10. package/components/alert/index.d.ts +2 -0
  11. package/components/alert/index.js +2 -0
  12. package/components/commonProps.d.ts +6 -0
  13. package/components/commonProps.js +1 -0
  14. package/components/modal/index.d.ts +1 -0
  15. package/components/modal/index.js +1 -0
  16. package/{dist/lib → components}/modal/modal.d.ts +30 -29
  17. package/{dist/lib → components}/modal/modal.js +59 -29
  18. package/components/pagination/index.d.ts +2 -0
  19. package/components/pagination/index.js +2 -0
  20. package/{dist/lib → components/pagination}/pagination.d.ts +5 -14
  21. package/{dist/lib → components/pagination}/pagination.js +6 -5
  22. package/components/progressbar/index.d.ts +1 -0
  23. package/components/progressbar/index.js +1 -0
  24. package/components/progressbar/progressbar.d.ts +86 -0
  25. package/components/progressbar/progressbar.js +78 -0
  26. package/components/rating/index.d.ts +1 -0
  27. package/components/rating/index.js +1 -0
  28. package/{dist/lib → components/rating}/rating.d.ts +6 -13
  29. package/{dist/lib → components/rating}/rating.js +6 -9
  30. package/components/select/index.d.ts +1 -0
  31. package/components/select/index.js +1 -0
  32. package/components/select/select.d.ts +337 -0
  33. package/components/select/select.js +266 -0
  34. package/components/slider/index.d.ts +1 -0
  35. package/components/slider/index.js +1 -0
  36. package/components/slider/slider.d.ts +245 -0
  37. package/components/slider/slider.js +413 -0
  38. package/{dist/lib/config.d.ts → config.d.ts} +17 -7
  39. package/{dist/lib/config.js → config.js} +3 -3
  40. package/index.d.ts +25 -0
  41. package/index.js +31 -0
  42. package/package.json +42 -28
  43. package/services/extendWidget.d.ts +23 -0
  44. package/services/extendWidget.js +35 -0
  45. package/services/floatingUI.d.ts +56 -0
  46. package/services/floatingUI.js +105 -0
  47. package/{dist/lib/services → services}/focustrack.js +5 -5
  48. package/services/intersection.d.ts +34 -0
  49. package/services/intersection.js +55 -0
  50. package/services/navManager.d.ts +93 -0
  51. package/services/navManager.js +172 -0
  52. package/{dist/lib/services → services}/portal.d.ts +7 -0
  53. package/services/portal.js +44 -0
  54. package/{dist/lib/services → services}/siblingsInert.d.ts +2 -1
  55. package/{dist/lib/services → services}/siblingsInert.js +2 -2
  56. package/{dist/lib → services}/transitions/baseTransitions.d.ts +15 -2
  57. package/{dist/lib → services}/transitions/baseTransitions.js +21 -10
  58. package/services/transitions/bootstrap/collapse.d.ts +2 -0
  59. package/services/transitions/bootstrap/fade.d.ts +1 -0
  60. package/services/transitions/bootstrap.d.ts +2 -0
  61. package/services/transitions/bootstrap.js +2 -0
  62. package/services/transitions/collapse.d.ts +43 -0
  63. package/{dist/lib → services}/transitions/collapse.js +15 -2
  64. package/{dist/lib → services}/transitions/cssTransitions.d.ts +6 -0
  65. package/{dist/lib → services}/transitions/cssTransitions.js +8 -4
  66. package/{dist/lib → services}/transitions/simpleClassTransition.d.ts +12 -1
  67. package/services/transitions/simpleClassTransition.js +42 -0
  68. package/{dist/lib/types.d.ts → types.d.ts} +43 -4
  69. package/types.js +14 -0
  70. package/{dist/lib/services/directiveUtils.js → utils/directive.js} +1 -1
  71. package/utils/internal/checks.d.ts +49 -0
  72. package/utils/internal/checks.js +60 -0
  73. package/utils/internal/dom.d.ts +25 -0
  74. package/utils/internal/dom.js +61 -0
  75. package/utils/internal/func.d.ts +11 -0
  76. package/utils/internal/func.js +11 -0
  77. package/utils/internal/isFocusable.d.ts +9 -0
  78. package/utils/internal/isFocusable.js +35 -0
  79. package/utils/internal/math.d.ts +5 -0
  80. package/utils/internal/math.js +13 -0
  81. package/utils/internal/promise.d.ts +87 -0
  82. package/utils/internal/promise.js +169 -0
  83. package/utils/internal/scrollbars.d.ts +8 -0
  84. package/{dist/lib/modal → utils/internal}/scrollbars.js +7 -1
  85. package/utils/internal/sort.d.ts +16 -0
  86. package/utils/internal/sort.js +28 -0
  87. package/utils/internal/textDirection.d.ts +7 -0
  88. package/utils/internal/textDirection.js +7 -0
  89. package/utils/internal/traversal.d.ts +54 -0
  90. package/utils/internal/traversal.js +105 -0
  91. package/{dist/lib/services → utils}/stores.d.ts +67 -33
  92. package/{dist/lib/services → utils}/stores.js +121 -59
  93. package/utils/writables.d.ts +32 -0
  94. package/utils/writables.js +72 -0
  95. package/dist/lib/index.d.ts +0 -11
  96. package/dist/lib/index.js +0 -11
  97. package/dist/lib/modal/scrollbars.d.ts +0 -2
  98. package/dist/lib/select.d.ts +0 -199
  99. package/dist/lib/select.js +0 -240
  100. package/dist/lib/services/checks.d.ts +0 -32
  101. package/dist/lib/services/checks.js +0 -43
  102. package/dist/lib/services/index.d.ts +0 -6
  103. package/dist/lib/services/index.js +0 -6
  104. package/dist/lib/services/portal.js +0 -33
  105. package/dist/lib/services/writables.d.ts +0 -7
  106. package/dist/lib/services/writables.js +0 -16
  107. package/dist/lib/transitions/bootstrap/collapse.d.ts +0 -2
  108. package/dist/lib/transitions/bootstrap/fade.d.ts +0 -1
  109. package/dist/lib/transitions/bootstrap/index.d.ts +0 -2
  110. package/dist/lib/transitions/bootstrap/index.js +0 -2
  111. package/dist/lib/transitions/collapse.d.ts +0 -29
  112. package/dist/lib/transitions/index.d.ts +0 -5
  113. package/dist/lib/transitions/index.js +0 -5
  114. package/dist/lib/transitions/simpleClassTransition.js +0 -28
  115. package/dist/lib/transitions/utils.d.ts +0 -20
  116. package/dist/lib/transitions/utils.js +0 -83
  117. package/dist/lib/tsdoc-metadata.json +0 -11
  118. package/dist/lib/types.js +0 -7
  119. package/dist/lib/utils.d.ts +0 -2
  120. package/dist/lib/utils.js +0 -2
  121. /package/{dist/lib/pagination.utils.d.ts → components/pagination/bootstrap.d.ts} +0 -0
  122. /package/{dist/lib/pagination.utils.js → components/pagination/bootstrap.js} +0 -0
  123. /package/{dist/lib/services → services}/focustrack.d.ts +0 -0
  124. /package/{dist/lib → services}/transitions/bootstrap/collapse.js +0 -0
  125. /package/{dist/lib → services}/transitions/bootstrap/fade.js +0 -0
  126. /package/{dist/lib/services/directiveUtils.d.ts → utils/directive.d.ts} +0 -0
@@ -1,5 +1,5 @@
1
- import { asReadable, computed, writable } from '@amadeus-it-group/tansu';
2
- import { identity } from './utils';
1
+ import { asWritable, computed, writable } from '@amadeus-it-group/tansu';
2
+ import { identity } from './utils/internal/func';
3
3
  /**
4
4
  * Merges source object into destination object, up to the provided number of levels.
5
5
  * @param destination - destination object
@@ -44,7 +44,7 @@ export const mergeInto = (destination, source, levels = Infinity) => {
44
44
  export const createWidgetsConfig = (parent$, adaptParentConfig = identity) => {
45
45
  const own$ = writable({});
46
46
  const adaptedParent$ = adaptParentConfig === identity ? parent$ : computed(() => adaptParentConfig(mergeInto({}, parent$?.(), 2)));
47
- return asReadable(computed(() => mergeInto(mergeInto({}, adaptedParent$?.(), 2), own$(), 2)), {
47
+ return asWritable(computed(() => mergeInto(mergeInto({}, adaptedParent$?.(), 2), own$(), 2)), {
48
48
  ...own$,
49
49
  own$,
50
50
  adaptedParent$,
package/index.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ export * from './components/commonProps';
2
+ export * from './types';
3
+ export * from './components/accordion';
4
+ export * from './components/alert';
5
+ export * from './components/modal';
6
+ export * from './components/pagination';
7
+ export * from './components/progressbar';
8
+ export * from './components/rating';
9
+ export * from './components/select';
10
+ export * from './components/slider';
11
+ export * from './config';
12
+ export * from './services/extendWidget';
13
+ export * from './services/floatingUI';
14
+ export * from './services/focustrack';
15
+ export * from './services/intersection';
16
+ export * from './services/navManager';
17
+ export * from './services/portal';
18
+ export * from './services/siblingsInert';
19
+ export * from './services/transitions/baseTransitions';
20
+ export * from './services/transitions/cssTransitions';
21
+ export * from './services/transitions/simpleClassTransition';
22
+ export * from './services/transitions/bootstrap';
23
+ export * from './utils/directive';
24
+ export * from './utils/stores';
25
+ export * from './utils/writables';
package/index.js ADDED
@@ -0,0 +1,31 @@
1
+ // types
2
+ export * from './components/commonProps';
3
+ export * from './types';
4
+ // components
5
+ export * from './components/accordion';
6
+ export * from './components/alert';
7
+ export * from './components/modal';
8
+ export * from './components/pagination';
9
+ export * from './components/progressbar';
10
+ export * from './components/rating';
11
+ export * from './components/select';
12
+ export * from './components/slider';
13
+ // config
14
+ export * from './config';
15
+ // services
16
+ export * from './services/extendWidget';
17
+ export * from './services/floatingUI';
18
+ export * from './services/focustrack';
19
+ export * from './services/intersection';
20
+ export * from './services/navManager';
21
+ export * from './services/portal';
22
+ export * from './services/siblingsInert';
23
+ // services transitions
24
+ export * from './services/transitions/baseTransitions';
25
+ export * from './services/transitions/cssTransitions';
26
+ export * from './services/transitions/simpleClassTransition';
27
+ export * from './services/transitions/bootstrap';
28
+ // public utils
29
+ export * from './utils/directive';
30
+ export * from './utils/stores';
31
+ export * from './utils/writables';
package/package.json CHANGED
@@ -1,52 +1,66 @@
1
1
  {
2
2
  "name": "@agnos-ui/core",
3
3
  "description": "Framework-agnostic headless widget library.",
4
- "homepage": "https://amadeusitgroup.github.io/AgnosUI/latest/",
5
4
  "keywords": [
6
5
  "headless",
7
6
  "agnostic",
8
7
  "components",
9
8
  "widgets",
9
+ "accordion",
10
10
  "alert",
11
11
  "modal",
12
12
  "pagination",
13
- "rating"
13
+ "rating",
14
+ "slider"
14
15
  ],
15
16
  "type": "module",
16
- "main": "./dist/lib/index.js",
17
- "module": "./dist/lib/index.js",
18
- "types": "./dist/lib/index.d.ts",
17
+ "main": "./index.js",
18
+ "module": "./index.js",
19
+ "types": "./index.d.ts",
19
20
  "exports": {
20
21
  ".": {
21
- "types": "./dist/lib/index.d.ts",
22
- "default": "./dist/lib/index.js"
22
+ "types": "./index.d.ts",
23
+ "default": "./index.js"
24
+ },
25
+ "./components/*": {
26
+ "types": "./components/*/*.d.ts",
27
+ "default": "./components/*/*.js"
28
+ },
29
+ "./config": {
30
+ "types": "./config.d.ts",
31
+ "default": "./config.js"
32
+ },
33
+ "./types": {
34
+ "types": "./types.d.ts",
35
+ "default": "./types.js"
36
+ },
37
+ "./services/*": {
38
+ "types": "./services/*.d.ts",
39
+ "default": "./services/*.js"
40
+ },
41
+ "./services/transitions/*": {
42
+ "types": "./services/transitions/*.d.ts",
43
+ "default": "./services/transitions/*.js"
44
+ },
45
+ "./utils/*": {
46
+ "types": "./utils/*.d.ts",
47
+ "default": "./utils/*.js"
23
48
  }
24
49
  },
25
- "scripts": {
26
- "build": "npm run build:lib && npm run build:tsc && npm run build:api-extractor",
27
- "build:lib": "node ../scripts/rm.js dist/lib && tsc -p tsconfig.lib.json",
28
- "build:tsc": "tsc",
29
- "build:api-extractor": "api-extractor run",
30
- "test": "vitest run",
31
- "tdd": "vitest",
32
- "tdd:ui": "vitest --ui",
33
- "test:coverage": "vitest run --coverage"
34
- },
35
50
  "dependencies": {
36
- "@amadeus-it-group/tansu": "0.0.22"
51
+ "@amadeus-it-group/tansu": "1.0.0"
37
52
  },
38
- "files": [
39
- "dist/lib"
40
- ],
41
- "license": "MIT",
53
+ "peerDependencies": {
54
+ "@floating-ui/dom": "*"
55
+ },
56
+ "sideEffects": false,
57
+ "version": "0.0.1-alpha.10",
58
+ "homepage": "https://amadeusitgroup.github.io/AgnosUI/latest/",
42
59
  "bugs": "https://github.com/AmadeusITGroup/AgnosUI/issues",
60
+ "license": "MIT",
43
61
  "repository": {
44
62
  "type": "git",
45
63
  "url": "https://github.com/AmadeusITGroup/AgnosUI.git",
46
64
  "directory": "core"
47
- },
48
- "devDependencies": {
49
- "eslint-plugin-jsdoc": "^46.4.6"
50
- },
51
- "version": "0.0.1-alpha.0"
52
- }
65
+ }
66
+ }
@@ -0,0 +1,23 @@
1
+ import type { ConfigValidator, SlotContent, Widget, WidgetFactory, WidgetProps, WidgetSlotContext, WidgetState } from '../types';
2
+ /**
3
+ * Type extending the original Widget props and state with ExtraProps
4
+ */
5
+ export type ExtendWidgetProps<W extends Widget, ExtraProps extends object> = Widget<ExtendWidgetAdaptSlotWidgetProps<WidgetProps<W>, ExtraProps>, ExtendWidgetAdaptSlotWidgetProps<WidgetState<W>, ExtraProps>, W['api'], W['actions'], W['directives']>;
6
+ /**
7
+ * Type replacing the original Props with WidgetSlotContext contaning ExtraProps
8
+ */
9
+ export type ExtendWidgetAdaptSlotContentProps<Props extends Record<string, any>, ExtraProps extends object> = Props extends WidgetSlotContext<infer U> ? WidgetSlotContext<ExtendWidgetProps<U, ExtraProps>> & Omit<Props, keyof WidgetSlotContext<any>> : Props;
10
+ /**
11
+ * Type enriching the original widget slot Props with ExtraProps slots
12
+ */
13
+ export type ExtendWidgetAdaptSlotWidgetProps<Props, ExtraProps extends object> = Omit<Props, `slot${string}`> & ExtraProps & {
14
+ [K in keyof Props & `slot${string}`]: Props[K] extends SlotContent<infer U> ? SlotContent<ExtendWidgetAdaptSlotContentProps<U, ExtraProps>> : Props[K];
15
+ };
16
+ /**
17
+ * Method to extend the original widget with extra props with validator
18
+ * @param factory - original widget factory
19
+ * @param extraPropsDefaults - object containing default value for each extra prop
20
+ * @param extraPropsConfig - object verifying the type of each extra prop
21
+ * @returns widget factory with the extra props
22
+ */
23
+ export declare const extendWidgetProps: <W extends Widget<object, object, object, object, object>, ExtraProps extends object>(factory: WidgetFactory<W>, extraPropsDefaults: ExtraProps, extraPropsConfig?: ConfigValidator<ExtraProps> | undefined) => WidgetFactory<ExtendWidgetProps<W, ExtraProps>>;
@@ -0,0 +1,35 @@
1
+ import { batch } from '@amadeus-it-group/tansu';
2
+ import { stateStores, writablesWithDefault } from '../utils/stores';
3
+ /**
4
+ * Method to extend the original widget with extra props with validator
5
+ * @param factory - original widget factory
6
+ * @param extraPropsDefaults - object containing default value for each extra prop
7
+ * @param extraPropsConfig - object verifying the type of each extra prop
8
+ * @returns widget factory with the extra props
9
+ */
10
+ export const extendWidgetProps = (factory, extraPropsDefaults, extraPropsConfig) => (propsConfig) => {
11
+ const extraPropsWritables = writablesWithDefault(extraPropsDefaults, propsConfig, extraPropsConfig);
12
+ const widget = factory(propsConfig);
13
+ return {
14
+ ...widget,
15
+ ...stateStores({ ...widget.stores, ...extraPropsWritables }),
16
+ patch: (storesValues) => batch(() => {
17
+ let widgetProps;
18
+ for (const [name, value] of Object.entries(storesValues ?? {})) {
19
+ const extraPropsStore = extraPropsWritables[`${name}$`];
20
+ if (extraPropsStore) {
21
+ extraPropsStore.set(value);
22
+ }
23
+ else {
24
+ if (!widgetProps) {
25
+ widgetProps = {};
26
+ }
27
+ widgetProps[name] = value;
28
+ }
29
+ }
30
+ if (widgetProps) {
31
+ widget.patch(widgetProps);
32
+ }
33
+ }),
34
+ };
35
+ };
@@ -0,0 +1,56 @@
1
+ import type { ArrowOptions, AutoUpdateOptions, ComputePositionConfig, Derivable } from '@floating-ui/dom';
2
+ import type { PropsConfig } from '../types';
3
+ export interface FloatingUIProps {
4
+ /**
5
+ * Options to use when calling computePosition from Floating UI
6
+ */
7
+ computePositionOptions: ComputePositionConfig;
8
+ /**
9
+ * Options to use when calling autoUpdate from Floating UI
10
+ */
11
+ autoUpdateOptions: AutoUpdateOptions;
12
+ /**
13
+ * Options to use when calling the arrow middleware from Floating UI
14
+ */
15
+ arrowOptions: Omit<ArrowOptions, 'element'> | Derivable<Omit<ArrowOptions, 'element'>>;
16
+ }
17
+ export type FloatingUI = ReturnType<typeof createFloatingUI>;
18
+ /**
19
+ * Create a floating UI service.
20
+ *
21
+ * The returned service includes the patch method to patch the states, the stores to track the states and directives to apply.
22
+ *
23
+ * @param propsConfig - the props config for the floating UI service
24
+ * @returns the floating UI service
25
+ */
26
+ export declare const createFloatingUI: (propsConfig?: PropsConfig<FloatingUIProps>) => {
27
+ directives: {
28
+ /**
29
+ * Directive to be used on the reference element from where the floating element will be positioned
30
+ */
31
+ referenceDirective: import("../types").Directive;
32
+ /**
33
+ * Directive to be used on the floating element
34
+ */
35
+ floatingDirective: import("../types").Directive<void>;
36
+ /**
37
+ * Directive to be used on the arrow element, if any
38
+ */
39
+ arrowDirective: import("../types").Directive<void>;
40
+ };
41
+ state$: import("@amadeus-it-group/tansu").ReadableSignal<import("../utils/stores").ToState<{
42
+ x$: import("@amadeus-it-group/tansu").ReadableSignal<number | undefined>;
43
+ y$: import("@amadeus-it-group/tansu").ReadableSignal<number | undefined>;
44
+ strategy$: import("@amadeus-it-group/tansu").ReadableSignal<import("@floating-ui/utils").Strategy | undefined>;
45
+ placement$: import("@amadeus-it-group/tansu").ReadableSignal<import("@floating-ui/utils").Placement | undefined>;
46
+ middlewareData$: import("@amadeus-it-group/tansu").ReadableSignal<import("@floating-ui/core").MiddlewareData | undefined>;
47
+ }>>;
48
+ stores: {
49
+ x$: import("@amadeus-it-group/tansu").ReadableSignal<number | undefined>;
50
+ y$: import("@amadeus-it-group/tansu").ReadableSignal<number | undefined>;
51
+ strategy$: import("@amadeus-it-group/tansu").ReadableSignal<import("@floating-ui/utils").Strategy | undefined>;
52
+ placement$: import("@amadeus-it-group/tansu").ReadableSignal<import("@floating-ui/utils").Placement | undefined>;
53
+ middlewareData$: import("@amadeus-it-group/tansu").ReadableSignal<import("@floating-ui/core").MiddlewareData | undefined>;
54
+ };
55
+ patch: <U extends Partial<FloatingUIProps>>(storesValues?: void | U | undefined) => void;
56
+ };
@@ -0,0 +1,105 @@
1
+ import { computed, derived } from '@amadeus-it-group/tansu';
2
+ import { arrow, autoUpdate, computePosition } from '@floating-ui/dom';
3
+ import { createStoreDirective, directiveSubscribe, mergeDirectives } from '../utils/directive';
4
+ import { promiseStoreToValueStore } from '../utils/internal/promise';
5
+ import { stateStores, writablesForProps } from '../utils/stores';
6
+ const defaultConfig = {
7
+ computePositionOptions: {},
8
+ autoUpdateOptions: {},
9
+ arrowOptions: {},
10
+ };
11
+ /**
12
+ * Create a floating UI service.
13
+ *
14
+ * The returned service includes the patch method to patch the states, the stores to track the states and directives to apply.
15
+ *
16
+ * @param propsConfig - the props config for the floating UI service
17
+ * @returns the floating UI service
18
+ */
19
+ export const createFloatingUI = (propsConfig) => {
20
+ const [{ autoUpdateOptions$, computePositionOptions$: computePositionInputOptions$, arrowOptions$: arrowInputOptions$ }, patch] = writablesForProps(defaultConfig, propsConfig);
21
+ const { directive: floatingDirective, element$: floatingElement$ } = createStoreDirective();
22
+ const { directive: referenceDirective, element$: referenceElement$ } = createStoreDirective();
23
+ const { directive: arrowDirective, element$: arrowElement$ } = createStoreDirective();
24
+ const arrowOptions$ = computed(() => {
25
+ const arrowElement = arrowElement$();
26
+ if (!arrowElement) {
27
+ return null;
28
+ }
29
+ const arrowInputOptions = arrowInputOptions$();
30
+ return typeof arrowInputOptions === 'function'
31
+ ? (state) => ({ ...arrowInputOptions(state), element: arrowElement })
32
+ : { ...arrowInputOptions, element: arrowElement };
33
+ });
34
+ const computePositionOptions$ = computed(() => {
35
+ let options = computePositionInputOptions$();
36
+ const arrowOptions = arrowOptions$();
37
+ if (arrowOptions) {
38
+ options = {
39
+ ...options,
40
+ middleware: [...(options.middleware ?? []), arrow(arrowOptions)],
41
+ };
42
+ }
43
+ return options;
44
+ });
45
+ const promisePosition$ = derived([floatingElement$, referenceElement$, computePositionOptions$, autoUpdateOptions$], ([floatingElement, referenceElement, computePositionOptions, autoUpdateOptions], set) => {
46
+ if (floatingElement && referenceElement) {
47
+ const clean = autoUpdate(referenceElement, floatingElement, () => {
48
+ set(computePosition(referenceElement, floatingElement, computePositionOptions));
49
+ }, autoUpdateOptions);
50
+ return () => {
51
+ set(null);
52
+ clean();
53
+ };
54
+ }
55
+ return undefined;
56
+ }, null);
57
+ const position$ = promiseStoreToValueStore(promisePosition$, null);
58
+ const placement$ = computed(() => position$()?.placement);
59
+ const middlewareData$ = computed(() => position$()?.middlewareData);
60
+ const x$ = computed(() => position$()?.x);
61
+ const y$ = computed(() => position$()?.y);
62
+ const strategy$ = computed(() => position$()?.strategy);
63
+ const arrowX$ = computed(() => middlewareData$()?.arrow?.x);
64
+ const arrowY$ = computed(() => middlewareData$()?.arrow?.y);
65
+ const floatingStyleApplyAction$ = computed(() => {
66
+ const floatingElement = floatingElement$();
67
+ if (floatingElement) {
68
+ floatingElement.style.left = `${x$() ?? 0}px`;
69
+ floatingElement.style.top = `${y$() ?? 0}px`;
70
+ }
71
+ });
72
+ const arrowStyleApplyAction$ = computed(() => {
73
+ const arrowElement = arrowElement$();
74
+ if (arrowElement) {
75
+ const arrowX = arrowX$();
76
+ const arrowY = arrowY$();
77
+ arrowElement.style.left = arrowX != null ? `${arrowX}px` : '';
78
+ arrowElement.style.top = arrowY != null ? `${arrowY}px` : '';
79
+ }
80
+ });
81
+ return {
82
+ patch,
83
+ ...stateStores({
84
+ x$,
85
+ y$,
86
+ strategy$,
87
+ placement$,
88
+ middlewareData$,
89
+ }),
90
+ directives: {
91
+ /**
92
+ * Directive to be used on the reference element from where the floating element will be positioned
93
+ */
94
+ referenceDirective,
95
+ /**
96
+ * Directive to be used on the floating element
97
+ */
98
+ floatingDirective: mergeDirectives(floatingDirective, directiveSubscribe(floatingStyleApplyAction$)),
99
+ /**
100
+ * Directive to be used on the arrow element, if any
101
+ */
102
+ arrowDirective: mergeDirectives(arrowDirective, directiveSubscribe(arrowStyleApplyAction$)),
103
+ },
104
+ };
105
+ };
@@ -1,5 +1,5 @@
1
1
  import { computed, readable } from '@amadeus-it-group/tansu';
2
- import { createStoreArrayDirective } from './directiveUtils';
2
+ import { createStoreArrayDirective } from '../utils/directive';
3
3
  const evtFocusIn = 'focusin';
4
4
  const evtFocusOut = 'focusout';
5
5
  export const activeElement$ = readable(null, {
@@ -12,11 +12,11 @@ export const activeElement$ = readable(null, {
12
12
  function onFocusOut() {
13
13
  setTimeout(setActiveElement);
14
14
  }
15
- container.addEventListener(evtFocusIn, setActiveElement);
16
- container.addEventListener(evtFocusOut, onFocusOut);
15
+ container.addEventListener(evtFocusIn, setActiveElement, { capture: true });
16
+ container.addEventListener(evtFocusOut, onFocusOut, { capture: true });
17
17
  return () => {
18
- container.removeEventListener(evtFocusIn, setActiveElement);
19
- container.removeEventListener(evtFocusOut, onFocusOut);
18
+ container.removeEventListener(evtFocusIn, setActiveElement, { capture: true });
19
+ container.removeEventListener(evtFocusOut, onFocusOut, { capture: true });
20
20
  };
21
21
  },
22
22
  equal: Object.is,
@@ -0,0 +1,34 @@
1
+ import type { PropsConfig } from '../types';
2
+ export interface IntersectionProps {
3
+ /**
4
+ * elements to observe
5
+ */
6
+ elements: HTMLElement[];
7
+ /**
8
+ * IntersectionObserverInit used in the IntersectionObserver
9
+ *
10
+ * See the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/IntersectionObserver#options)
11
+ */
12
+ options: Partial<IntersectionObserverInit> | undefined;
13
+ }
14
+ /**
15
+ * Create an intersection service.
16
+ *
17
+ * The returned service includes the patch method to set the elements to observe / intersection options and the states to track the visible elements.
18
+ *
19
+ * @param config - the props config for the intersection service
20
+ * @returns the intersection service
21
+ */
22
+ export declare const createIntersection: (config?: PropsConfig<IntersectionProps>) => {
23
+ /**
24
+ * Readable of observed elements
25
+ */
26
+ elements$: import("@amadeus-it-group/tansu").ReadableSignal<HTMLElement[]>;
27
+ /**
28
+ * Store of map that contains the visible elements (for the key) and the corresponding entries
29
+ *
30
+ * See the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry)
31
+ */
32
+ visibleElements$: import("@amadeus-it-group/tansu").ReadableSignal<Map<Element, IntersectionObserverEntry>>;
33
+ patch: <U extends Partial<IntersectionProps>>(storesValues?: void | U | undefined) => void;
34
+ };
@@ -0,0 +1,55 @@
1
+ import { asReadable, derived } from '@amadeus-it-group/tansu';
2
+ import { noop } from '../utils/internal/func';
3
+ import { writablesForProps } from '../utils/stores';
4
+ const defaultValues = {
5
+ elements: [],
6
+ options: undefined,
7
+ };
8
+ /**
9
+ * Create an intersection service.
10
+ *
11
+ * The returned service includes the patch method to set the elements to observe / intersection options and the states to track the visible elements.
12
+ *
13
+ * @param config - the props config for the intersection service
14
+ * @returns the intersection service
15
+ */
16
+ export const createIntersection = (config) => {
17
+ const [{ elements$, options$ }, patch] = writablesForProps(defaultValues, config);
18
+ const visibleElements$ = derived([elements$, options$], ([elements, options], set) => {
19
+ if (elements.length) {
20
+ const visibleElements = new Map();
21
+ const observer = new IntersectionObserver((entries) => {
22
+ for (const entry of entries) {
23
+ const { target, isIntersecting } = entry;
24
+ if (isIntersecting) {
25
+ visibleElements.set(target, entry);
26
+ }
27
+ else {
28
+ visibleElements.delete(target);
29
+ }
30
+ }
31
+ set(visibleElements);
32
+ }, options);
33
+ for (const element of elements) {
34
+ observer.observe(element);
35
+ }
36
+ return () => {
37
+ observer.disconnect();
38
+ };
39
+ }
40
+ return noop;
41
+ }, new Map());
42
+ return {
43
+ /**
44
+ * Readable of observed elements
45
+ */
46
+ elements$: asReadable(elements$),
47
+ /**
48
+ * Store of map that contains the visible elements (for the key) and the corresponding entries
49
+ *
50
+ * See the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry)
51
+ */
52
+ visibleElements$: asReadable(visibleElements$),
53
+ patch,
54
+ };
55
+ };
@@ -0,0 +1,93 @@
1
+ import type { Directive } from '../types';
2
+ export type NavManager = ReturnType<typeof createNavManager>;
3
+ /**
4
+ * Returns the key name given the keyboard event. The key name is built using event.key (such as ArrowLeft, PageDown...),
5
+ * prefixed with the modifiers. If present, modifiers are always in the same order: Meta+Ctrl+Alt+Shift+...
6
+ * @param event - keyboard event
7
+ * @returns the name of the key, including modifiers
8
+ */
9
+ export declare const getKeyName: (event: KeyboardEvent) => string;
10
+ /**
11
+ * Returns true if the keyboard event is an ArrowLeft, ArrowRight, Home or End key press that should make the cursor move inside
12
+ * the input and false otherwise (i.e. the key is not ArrowLeft, ArrowRight, Home or End key, or that would not make the cursor move
13
+ * because it is already at one end of the input)
14
+ * @param event - keyboard event
15
+ * @returns true if the keyboard event is an ArrowLeft, ArrowRight, Home or End key press that should make the cursor move inside
16
+ * the input and false otherwise.
17
+ */
18
+ export declare const isInternalInputNavigation: (event: KeyboardEvent) => boolean;
19
+ /**
20
+ * Type of a key handler of the navigation manager.
21
+ * A key handler receives an object as its parameter, with the following properties:
22
+ * - event: key event
23
+ * - directiveElement: DOM element which has the navigation manager directive
24
+ * - navManager: navigation manager instance
25
+ */
26
+ export type NavManagerKeyHandler = (info: {
27
+ directiveElement: HTMLElement;
28
+ event: KeyboardEvent;
29
+ navManager: NavManager;
30
+ }) => void;
31
+ /**
32
+ * Type of the parameter of the navigation manager directive.
33
+ */
34
+ export interface NavManagerItemConfig {
35
+ /**
36
+ * Map of key handlers.
37
+ * The key in the map should match the result of calling {@link getKeyName} on the key event (for example "ArrowLeft" or "Ctrl+PageDown").
38
+ * The value in the map is the corresponding key handler.
39
+ */
40
+ keys?: Record<string, NavManagerKeyHandler>;
41
+ /**
42
+ * Function returning DOM elements to include in the navigation manager.
43
+ * It receives as a parameter the DOM element on which the navigation manager directive is used.
44
+ * If not specified, the default selector function only returns the element on which the navigation manager directive is used.
45
+ */
46
+ selector?: (directiveElement: HTMLElement) => Iterable<HTMLElement>;
47
+ }
48
+ /**
49
+ * Returns a new instance of the navigation manager.
50
+ *
51
+ * The navigation manager simplifies keyboard navigation for a set of DOM elements.
52
+ * It provides a directive to use on some DOM elements, both to add the keydown event handler and to specify which elements should be managed
53
+ * (either by directly putting the directive on those elements, or by putting the directive on a parent element and
54
+ * specifying which child elements should be included through a selector function).
55
+ *
56
+ * It provides some utilities to move the focus between those elements (focusFirst/focusLast, focusLeft/focusRight, focusPrevious/focusNext).
57
+ *
58
+ * @returns a new instance of the navigation manager
59
+ */
60
+ export declare const createNavManager: () => {
61
+ elementsInDomOrder$: import("@amadeus-it-group/tansu").ReadableSignal<HTMLElement[]>;
62
+ directive: Directive<NavManagerItemConfig>;
63
+ focusIndex: (index: number, moveDirection?: -1 | 0 | 1) => HTMLElement | null;
64
+ focusPrevious: ({ event, referenceElement, }?: {
65
+ event?: KeyboardEvent | undefined;
66
+ referenceElement?: HTMLElement | null | undefined;
67
+ }) => HTMLElement | null;
68
+ focusNext: ({ event, referenceElement, }?: {
69
+ event?: KeyboardEvent | undefined;
70
+ referenceElement?: HTMLElement | null | undefined;
71
+ }) => HTMLElement | null;
72
+ focusFirst: ({ event }?: {
73
+ event?: KeyboardEvent | undefined;
74
+ }) => HTMLElement | null;
75
+ focusFirstLeft: (args_0?: {
76
+ event?: KeyboardEvent | undefined;
77
+ } | undefined) => HTMLElement | null;
78
+ focusFirstRight: (args_0?: {
79
+ event?: KeyboardEvent | undefined;
80
+ } | undefined) => HTMLElement | null;
81
+ focusLast: ({ event }?: {
82
+ event?: KeyboardEvent | undefined;
83
+ }) => HTMLElement | null;
84
+ focusLeft: (args_0?: {
85
+ event?: KeyboardEvent | undefined;
86
+ referenceElement?: HTMLElement | null | undefined;
87
+ } | undefined) => HTMLElement | null;
88
+ focusRight: (args_0?: {
89
+ event?: KeyboardEvent | undefined;
90
+ referenceElement?: HTMLElement | null | undefined;
91
+ } | undefined) => HTMLElement | null;
92
+ refreshElements: () => void;
93
+ };