@design-factory/core 22.0.0-next.0 → 22.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,8 +16,8 @@ function adjustItemsCloseOthers(items, openItems, oldOpen) {
16
16
  }
17
17
  if (keepOpen) {
18
18
  items.forEach((item) => {
19
- if (item.stores.id$() !== keepOpen && item.stores.visible$()) {
20
- item.patch({ visible: false });
19
+ if (item.stores.id$() !== keepOpen && item.stores.expanded$()) {
20
+ item.patch({ expanded: false });
21
21
  }
22
22
  });
23
23
  }
@@ -58,12 +58,12 @@ const defaultItemConfig = {
58
58
  id: "",
59
59
  destroyOnHide: defaultAccordionConfig.itemDestroyOnHide,
60
60
  disabled: false,
61
- visible: false,
61
+ expanded: false,
62
62
  animated: defaultAccordionConfig.animated,
63
63
  transition: defaultAccordionConfig.itemTransition,
64
64
  onShown: noop,
65
65
  onHidden: noop,
66
- onVisibleChange: noop,
66
+ onExpandedChange: noop,
67
67
  className: defaultAccordionConfig.itemClassName,
68
68
  headerClassName: defaultAccordionConfig.itemHeaderClassName,
69
69
  buttonClassName: defaultAccordionConfig.itemButtonClassName,
@@ -102,12 +102,12 @@ const configItemValidator = {
102
102
  id: typeString,
103
103
  destroyOnHide: typeBoolean,
104
104
  disabled: typeBoolean,
105
- visible: typeBoolean,
105
+ expanded: typeBoolean,
106
106
  animated: typeBoolean,
107
107
  transition: typeFunction,
108
108
  onShown: typeFunction,
109
109
  onHidden: typeFunction,
110
- onVisibleChange: typeFunction,
110
+ onExpandedChange: typeFunction,
111
111
  className: typeString,
112
112
  headerClassName: typeString,
113
113
  buttonClassName: typeString,
@@ -127,8 +127,8 @@ function createAccordionItem(config) {
127
127
  destroyOnHide$,
128
128
  onShown$,
129
129
  onHidden$,
130
- onVisibleChange$,
131
- visible$,
130
+ onExpandedChange$,
131
+ expanded$: requestedExpanded$,
132
132
  id$: _dirtyId$,
133
133
  disabled$,
134
134
  ...stateProps
@@ -140,8 +140,8 @@ function createAccordionItem(config) {
140
140
  const transition = createTransition({
141
141
  props: {
142
142
  transition: transition$,
143
- visible: visible$,
144
- onVisibleChange: onVisibleChange$,
143
+ visible: requestedExpanded$,
144
+ onVisibleChange: onExpandedChange$,
145
145
  animated: animated$,
146
146
  animatedOnInit: false,
147
147
  initDone: initDone$,
@@ -153,16 +153,17 @@ function createAccordionItem(config) {
153
153
  }
154
154
  }
155
155
  });
156
+ const expanded$ = transition.stores.visible$;
156
157
  const shouldBeInDOM$ = computed(() => !destroyOnHide$() || !transition.stores.hidden$());
157
158
  const toggleDirective = createAttributesDirective(() => ({
158
159
  attributes: {
159
160
  id: computed(() => `${id$()}-toggle`),
160
- "aria-expanded": computed(() => `${visible$()}`),
161
+ "aria-expanded": computed(() => `${expanded$()}`),
161
162
  "aria-disabled": computed(() => `${disabled$()}`),
162
163
  "aria-controls": computed(() => `${id$()}-body-container`),
163
164
  disabled: disabled$
164
165
  },
165
- classNames: { "df-collapsed": computed(() => !visible$()) },
166
+ classNames: { "df-collapsed": computed(() => !expanded$()) },
166
167
  events: {
167
168
  click: () => {
168
169
  if (!disabled$()) {
@@ -182,7 +183,7 @@ function createAccordionItem(config) {
182
183
  }));
183
184
  return {
184
185
  ...stateStores({
185
- visible$,
186
+ expanded$,
186
187
  id$,
187
188
  shouldBeInDOM$,
188
189
  disabled$,
@@ -252,7 +253,7 @@ function factoryCreateAccordion(itemFactory = createAccordionItem, accordionItem
252
253
  const openItems$ = computed(() => {
253
254
  const openItems = [];
254
255
  itemWidgets$().forEach((item) => {
255
- if (item.stores.visible$()) {
256
+ if (item.stores.expanded$()) {
256
257
  openItems.push(item.stores.id$());
257
258
  }
258
259
  });
@@ -71,6 +71,7 @@ const createExtendedAlert = extendWidgetProps(
71
71
  alertDefaultConfig,
72
72
  alertConfigValidator,
73
73
  {
74
+ dismissible: false,
74
75
  transition: alertFadeTransition
75
76
  }
76
77
  );
@@ -42,7 +42,7 @@ interface AccordionCommonPropsAndState extends WidgetsCommonPropsAndState {
42
42
  */
43
43
  addon: 'none' | 'icon' | 'number';
44
44
  /**
45
- * When an item is visible (expanded), a separator line is shown below the item header.
45
+ * When an item is expanded, a separator line is shown below the item header.
46
46
  *
47
47
  * @defaultValue `false`
48
48
  */
@@ -183,7 +183,7 @@ export interface AccordionApi {
183
183
  * @returns A promise that resolves when the toggle operation is completed.
184
184
  * If the itemId is not valid, nothing will happen.
185
185
  */
186
- toggle(itemId: string): Promise<void>;
186
+ toggle(itemId: string, animated?: boolean): Promise<void>;
187
187
  /**
188
188
  * It will expand all the items in the accordion.
189
189
  *
@@ -282,9 +282,9 @@ export interface AccordionItemDirectives {
282
282
  */
283
283
  interface AccordionItemCommonPropsAndState extends WidgetsCommonPropsAndState {
284
284
  /**
285
- * If `true`, the accordion-item will be visible (expanded). Otherwise, it will be hidden (collapsed).
285
+ * If `true`, the accordion-item will be expanded. Otherwise, it will be collapsed.
286
286
  */
287
- visible: boolean;
287
+ expanded: boolean;
288
288
  /**
289
289
  * If `true`, the accordion-item will be disabled.
290
290
  * It will not react to user's clicks, but still will be possible to toggle programmatically.
@@ -341,11 +341,11 @@ export interface AccordionItemProps extends AccordionItemCommonPropsAndState {
341
341
  */
342
342
  onHidden: () => void;
343
343
  /**
344
- * An event fired when the `visible` value changes.
344
+ * An event fired when the `expanded` value changes.
345
345
  *
346
- * Event payload is the new value of visible.
346
+ * Event payload is the new value of expanded.
347
347
  */
348
- onVisibleChange: (visible: boolean) => void;
348
+ onExpandedChange: (expanded: boolean) => void;
349
349
  }
350
350
  /**
351
351
  * Represents the state of an accordion item.
@@ -353,7 +353,7 @@ export interface AccordionItemProps extends AccordionItemCommonPropsAndState {
353
353
  export interface AccordionItemState extends AccordionItemCommonPropsAndState {
354
354
  /**
355
355
  * If `true` the content of the accordion-item collapse should be in DOM. Its value depends on the
356
- * value of the `visible` and `destroyOnHide`.
356
+ * value of the `expanded` and `destroyOnHide`.
357
357
  */
358
358
  shouldBeInDOM: boolean;
359
359
  }
@@ -1,4 +1,4 @@
1
- import { c, a, f, g } from "../../accordion-B5RqDwi3.js";
1
+ import { c, a, f, g } from "../../accordion-DUFLBQkV.js";
2
2
  export {
3
3
  c as createAccordion,
4
4
  a as createAccordionItem,
@@ -74,6 +74,12 @@ export interface AlertState extends CommonAlertState, AlertExtraPropsAndState {
74
74
  * Represents the properties for the alert component.
75
75
  */
76
76
  export interface AlertProps extends CommonAlertProps, AlertExtraProps {
77
+ /**
78
+ * If `true`, alert can be dismissed by the user.
79
+ *
80
+ * @defaultValue `false`
81
+ */
82
+ dismissible: boolean;
77
83
  }
78
84
  /**
79
85
  * Represents the API for an alert component.
@@ -1,4 +1,4 @@
1
- import { c } from "../../alert-Db6cG6JE.js";
1
+ import { c } from "../../alert-klFrSyNy.js";
2
2
  export {
3
3
  c as createAlert
4
4
  };
@@ -107,6 +107,13 @@ export interface DrawerProps extends DrawerCommonPropsAndState {
107
107
  * @defaultValue `true`
108
108
  */
109
109
  animated: boolean;
110
+ /**
111
+ * If `true` the backdrop fade in / out will be animated.
112
+ * Will use the `animated` property if set to `null`.
113
+ *
114
+ * @defaultValue `null`
115
+ */
116
+ backdropAnimated: boolean | null;
110
117
  /**
111
118
  * aria-labelledby attribute to use for the drawer element.
112
119
  *
@@ -1,4 +1,4 @@
1
- import { c, g } from "../../drawer-CpGnS2ln.js";
1
+ import { c, g } from "../../drawer-D4xSbhcT.js";
2
2
  export {
3
3
  c as createDrawer,
4
4
  g as getDrawerDefaultConfig
@@ -1,4 +1,4 @@
1
- import { c, g } from "../../dropdown-Bjj2ql6d.js";
1
+ import { c, g } from "../../dropdown-BZiBfdNu.js";
2
2
  export {
3
3
  c as createDropdown,
4
4
  g as getDropdownDefaultConfig
@@ -1,4 +1,4 @@
1
- import { c, g } from "../../slider-b9cVFNAL.js";
1
+ import { c, g } from "../../slider-tH5g55yQ.js";
2
2
  export {
3
3
  c as createSlider,
4
4
  g as getSliderDefaultConfig
@@ -1,174 +1,6 @@
1
- import { writable, derived, computed, readable } from "@amadeus-it-group/tansu";
2
- import { createHasFocus, activeElement$ } from "../../services/focustrack.js";
3
- import { createHasMouseInside } from "../../services/mousetrack.js";
4
- import { typePlacement, createPositioning } from "../../services/positioning.js";
5
- import { createTransition } from "../../services/transitions/baseTransitions.js";
6
- import { createSimpleClassTransition } from "../../services/transitions/simpleClassTransition.js";
7
- import { debounceSignal } from "../../utils/debounceSignal.js";
8
- import { w as addEvent, s as mergeDirectives, g as createAttributesDirective, o as directiveSubscribe } from "../../directive-CMT2vEDg.js";
9
- import { createEdgeState } from "../../utils/edgeState.js";
10
- import { generateId } from "../../utils/id.js";
11
- import { writablesForProps, stateStores } from "../../utils/stores.js";
12
- import { createWidgetFactory } from "../../utils/widget.js";
13
- import { a as createTypeStringSpacedArray, d as typeBoolean, l as typeStringOrNull, c as createTypeEnum } from "../../writables-_7BriMb2.js";
14
- const verticalPlacement = ["top", "top-start", "top-end", "bottom", "bottom-start", "bottom-end"];
15
- const horizontalPlacement = ["end", "end-end", "end-start", "start", "start-end", "start-start"];
16
- const defaultPlacement = [...verticalPlacement, ...horizontalPlacement];
17
- const fadeTransition = createSimpleClassTransition({
18
- animationPendingClasses: ["df-fade"],
19
- animationPendingShowClasses: ["df-show"],
20
- showClasses: ["df-show", "df-fade"],
21
- hideClasses: ["df-hidden", "df-fade"]
22
- });
23
- const defaultTooltipConfig = {
24
- animated: true,
25
- content: "",
26
- disabled: false,
27
- placement: defaultPlacement,
28
- size: "md"
29
- };
30
- const tooltipConfigValidator = {
31
- animated: typeBoolean,
32
- content: typeStringOrNull,
33
- disabled: typeBoolean,
34
- placement: createTypeStringSpacedArray((placement) => {
35
- if (placement === "auto") {
36
- return defaultPlacement;
37
- } else if (placement === "vertical") {
38
- return verticalPlacement;
39
- } else if (placement === "horizontal") {
40
- return horizontalPlacement;
41
- }
42
- return typePlacement.normalizeValue(placement);
43
- }),
44
- size: createTypeEnum(["sm", "md", "lg"])
45
- };
46
- const DEBOUNCE_DELAY = 200;
47
- const createTooltip = createWidgetFactory(
48
- "tooltip",
49
- (config) => {
50
- const [{ placement$, animated$, disabled$, content$, ...stateProps }, patch] = writablesForProps(
51
- defaultTooltipConfig,
52
- config,
53
- tooltipConfigValidator
54
- );
55
- const floating = createPositioning({
56
- props: {
57
- placement: placement$
58
- }
59
- });
60
- const { directive: hasFocusDirective, hasFocus$ } = createHasFocus();
61
- const forceVisibleOnFocus$ = writable(false);
62
- const hasVisibleFocus$ = derived(
63
- [hasFocus$, activeElement$, forceVisibleOnFocus$],
64
- ([hasFocus, activeElement, forceVisibleOnFocus], set) => {
65
- if (hasFocus) {
66
- if (forceVisibleOnFocus || activeElement?.matches(":focus-visible")) {
67
- set(true);
68
- }
69
- } else {
70
- set(false);
71
- }
72
- },
73
- false
74
- );
75
- const debouncedHasVisibleFocus$ = debounceSignal(hasVisibleFocus$, (value) => value ? DEBOUNCE_DELAY : -1);
76
- const { directive: hasMouseInsideDirective, hasMouseInside$ } = createHasMouseInside();
77
- const debouncedHasMouseInside$ = debounceSignal(hasMouseInside$, DEBOUNCE_DELAY);
78
- const visible$ = createEdgeState(
79
- {
80
- mouseInside: debouncedHasMouseInside$,
81
- hasVisibleFocus: debouncedHasVisibleFocus$
82
- },
83
- computed(() => disabled$() || !content$() || floating.stores.referenceHidden$())
84
- );
85
- const transition = createTransition({
86
- props: {
87
- transition: fadeTransition,
88
- visible: visible$,
89
- animated: animated$,
90
- animatedOnInit: true
91
- }
92
- });
93
- const escDismiss$ = readable(void 0, {
94
- onUse: () => addEvent(
95
- document.documentElement,
96
- "keydown",
97
- (event) => {
98
- if (visible$() && event.key === "Escape") {
99
- visible$.set(false);
100
- event.preventDefault();
101
- event.stopPropagation();
102
- }
103
- },
104
- { capture: true }
105
- )
106
- });
107
- const id$ = computed(generateId);
108
- return {
109
- ...stateStores({
110
- ...stateProps,
111
- content$,
112
- animated$,
113
- disabled$,
114
- placement$,
115
- visible$: transition.stores.visible$,
116
- hidden$: transition.stores.hidden$
117
- }),
118
- patch,
119
- api: {},
120
- directives: {
121
- referenceDirective: mergeDirectives(
122
- floating.directives.referenceDirective,
123
- hasFocusDirective,
124
- hasMouseInsideDirective,
125
- createAttributesDirective(() => ({
126
- attributes: {
127
- "aria-describedby": computed(() => transition.stores.hidden$() ? void 0 : id$())
128
- },
129
- styles: {
130
- // prevents the trigger element from being selected when long-pressing on touch devices
131
- userSelect: computed(() => disabled$() ? void 0 : "none")
132
- },
133
- events: {
134
- contextmenu: (event) => {
135
- if (event.pointerType === "touch" && !disabled$()) {
136
- event.preventDefault();
137
- if (hasVisibleFocus$()) {
138
- visible$.set(true);
139
- } else {
140
- forceVisibleOnFocus$.set(true);
141
- event.currentTarget?.focus?.();
142
- forceVisibleOnFocus$.set(false);
143
- }
144
- }
145
- }
146
- }
147
- }))
148
- ),
149
- floatingDirective: mergeDirectives(
150
- floating.directives.floatingDirective,
151
- transition.directives.directive,
152
- hasMouseInsideDirective,
153
- directiveSubscribe(escDismiss$),
154
- createAttributesDirective(() => ({
155
- attributes: {
156
- role: readable("tooltip"),
157
- id: id$
158
- },
159
- events: {
160
- mousedown: (event) => {
161
- if (hasVisibleFocus$() && debouncedHasMouseInside$() && !event.defaultPrevented) {
162
- visible$.skipNextSourceValue("hasVisibleFocus", false);
163
- }
164
- }
165
- }
166
- }))
167
- )
168
- }
169
- };
170
- }
171
- );
1
+ import { c, d, t } from "../../tooltip-Cl7tQomt.js";
172
2
  export {
173
- createTooltip
3
+ c as createTooltip,
4
+ d as defaultPlacement,
5
+ t as tooltipPlacementValidator
174
6
  };
@@ -1,5 +1,5 @@
1
1
  import { type Placement } from '../../services/positioning';
2
- import type { Directive, SSRHTMLElement, Widget, WidgetFactory } from '../../types';
2
+ import type { Directive, PickRequired, SSRHTMLElement, Widget, WidgetFactory, WritableWithDefaultOptions } from '../../types';
3
3
  /**
4
4
  * Valid placement values for the tooltip.
5
5
  * Includes all individual {@link Placement} values plus `'auto'`, `'vertical'` and `'horizontal'` shortcuts.
@@ -9,6 +9,10 @@ import type { Directive, SSRHTMLElement, Widget, WidgetFactory } from '../../typ
9
9
  * - `'horizontal'` expands to `'end end-end end-start start start-end start-start'`
10
10
  */
11
11
  export type TooltipPlacement = Placement | 'auto' | 'vertical' | 'horizontal';
12
+ /**
13
+ * Default tooltip placements, in order of preference (vertical first, then horizontal).
14
+ */
15
+ export declare const defaultPlacement: Placement[];
12
16
  export type TooltipSize = 'sm' | 'md' | 'lg';
13
17
  export interface TooltipCommonPropsAndState {
14
18
  /**
@@ -55,6 +59,11 @@ export interface TooltipDirectives {
55
59
  floatingDirective: Directive<void, SSRHTMLElement>;
56
60
  }
57
61
  export type TooltipWidget = Widget<TooltipProps, TooltipState, Record<string, never>, TooltipDirectives>;
62
+ /**
63
+ * Validator for the tooltip `placement` prop. Normalizes a space-separated string or array of placements, expanding the
64
+ * `'auto'`, `'vertical'` and `'horizontal'` shortcuts to their respective placement lists.
65
+ */
66
+ export declare const tooltipPlacementValidator: PickRequired<WritableWithDefaultOptions<Placement[]>, 'normalizeValue' | 'equal'>;
58
67
  /**
59
68
  * Create a TooltipWidget with given config props
60
69
  * @param config - an optional tooltip config
@@ -0,0 +1 @@
1
+ export * from './tooltip-overflow';
@@ -0,0 +1,78 @@
1
+ import { derived, computed, asWritable } from "@amadeus-it-group/tansu";
2
+ import { createResizeObserver } from "../../services/resizeObserver.js";
3
+ import { i as createBrowserStoreDirective, s as mergeDirectives } from "../../directive-CMT2vEDg.js";
4
+ import { noop } from "../../utils/func.js";
5
+ import { writablesForProps, stateStores } from "../../utils/stores.js";
6
+ import { createWidgetFactory } from "../../utils/widget.js";
7
+ import { k as typeString, l as typeStringOrNull, d as typeBoolean, c as createTypeEnum } from "../../writables-_7BriMb2.js";
8
+ import { t as tooltipPlacementValidator, d as defaultPlacement } from "../../tooltip-Cl7tQomt.js";
9
+ const defaultOverflowTooltipConfig = {
10
+ animated: true,
11
+ content: "",
12
+ placement: defaultPlacement,
13
+ size: "md",
14
+ iconAriaLabel: "Show full text"
15
+ };
16
+ const overflowTooltipConfigValidator = {
17
+ animated: typeBoolean,
18
+ content: typeStringOrNull,
19
+ placement: tooltipPlacementValidator,
20
+ size: createTypeEnum(["sm", "md", "lg"]),
21
+ iconAriaLabel: typeString
22
+ };
23
+ const createOverflowTooltip = createWidgetFactory(
24
+ "tooltip",
25
+ // reuses the same config as the tooltip widget
26
+ (config) => {
27
+ const [{ content$, ...stateProps }, patch] = writablesForProps(
28
+ defaultOverflowTooltipConfig,
29
+ config,
30
+ overflowTooltipConfigValidator
31
+ );
32
+ const { directive: elementDirective, element$ } = createBrowserStoreDirective();
33
+ const textContent$ = derived(
34
+ element$,
35
+ (el, set) => {
36
+ if (!el) {
37
+ set("");
38
+ return noop;
39
+ }
40
+ set(el.textContent?.trim() ?? "");
41
+ const observer = new MutationObserver(() => set(el.textContent?.trim() ?? ""));
42
+ observer.observe(el, { childList: true, characterData: true, subtree: true });
43
+ return () => observer.disconnect();
44
+ },
45
+ ""
46
+ );
47
+ const { directive: resizeDirective, dimensions$ } = createResizeObserver();
48
+ const overflowing$ = computed(() => {
49
+ dimensions$();
50
+ textContent$();
51
+ const el = element$();
52
+ if (!el) {
53
+ return false;
54
+ }
55
+ return el.offsetWidth < el.scrollWidth;
56
+ });
57
+ const resolvedContent$ = asWritable(
58
+ computed(() => content$() || textContent$()),
59
+ content$.set
60
+ );
61
+ const referenceDirective = mergeDirectives(elementDirective, resizeDirective);
62
+ return {
63
+ ...stateStores({
64
+ ...stateProps,
65
+ content$: resolvedContent$,
66
+ overflowing$
67
+ }),
68
+ patch,
69
+ api: {},
70
+ directives: {
71
+ referenceDirective
72
+ }
73
+ };
74
+ }
75
+ );
76
+ export {
77
+ createOverflowTooltip
78
+ };
@@ -0,0 +1,34 @@
1
+ import type { Directive, Widget, WidgetFactory } from '../../types';
2
+ import { TooltipCommonPropsAndState } from '../tooltip/tooltip';
3
+ export interface OverflowTooltipCommonPropsAndState extends Omit<TooltipCommonPropsAndState, 'disabled'> {
4
+ /**
5
+ * Text content to be displayed inside the tooltip.
6
+ * When empty, defaults to the element's textContent.
7
+ */
8
+ content: string | null;
9
+ /**
10
+ * Aria label for the tooltip ellipsis icon.
11
+ */
12
+ iconAriaLabel: string;
13
+ }
14
+ export interface OverflowTooltipState extends OverflowTooltipCommonPropsAndState {
15
+ /**
16
+ * Whether the element is currently overflowing.
17
+ */
18
+ overflowing: boolean;
19
+ }
20
+ export interface OverflowTooltipProps extends OverflowTooltipCommonPropsAndState {
21
+ }
22
+ export interface OverflowTooltipDirectives {
23
+ /**
24
+ * Directive to apply to the reference element.
25
+ */
26
+ referenceDirective: Directive;
27
+ }
28
+ export type OverflowTooltipWidget = Widget<OverflowTooltipProps, OverflowTooltipState, Record<string, never>, OverflowTooltipDirectives>;
29
+ /**
30
+ * Create a OverflowTooltipWidget with given config props
31
+ * @param config - an optional overflow-tooltip config
32
+ * @returns a OverflowTooltipWidget
33
+ */
34
+ export declare const createOverflowTooltip: WidgetFactory<OverflowTooltipWidget>;
@@ -9,7 +9,7 @@ import { noop } from "./utils/func.js";
9
9
  import { a as revertScrollbars, r as removeScrollbars } from "./scrollbars-ChGk75QR.js";
10
10
  import { writablesForProps, bindableProp, stateStores, true$ } from "./utils/stores.js";
11
11
  import { createWidgetFactory } from "./utils/widget.js";
12
- import { d as typeBoolean, j as typeNumberOrNull, f as typeFunction, g as typeHTMLElementOrNull, k as typeString, c as createTypeEnum } from "./writables-_7BriMb2.js";
12
+ import { d as typeBoolean, j as typeNumberOrNull, f as typeFunction, g as typeHTMLElementOrNull, k as typeString, e as typeBooleanOrNull, c as createTypeEnum } from "./writables-_7BriMb2.js";
13
13
  import { g as getTextDirection } from "./textDirection-cNgt24LJ.js";
14
14
  function getDrawerDefaultConfig() {
15
15
  return {
@@ -18,6 +18,7 @@ function getDrawerDefaultConfig() {
18
18
  }
19
19
  const defaultDrawerConfig = {
20
20
  animated: true,
21
+ backdropAnimated: null,
21
22
  ariaDescribedBy: "",
22
23
  ariaLabelledBy: "",
23
24
  backdropClass: "",
@@ -45,6 +46,7 @@ const defaultDrawerConfig = {
45
46
  };
46
47
  const configValidator = {
47
48
  animated: typeBoolean,
49
+ backdropAnimated: typeBooleanOrNull,
48
50
  ariaDescribedBy: typeString,
49
51
  ariaLabelledBy: typeString,
50
52
  backdropClass: typeString,
@@ -75,6 +77,7 @@ const createDrawer = createWidgetFactory(
75
77
  (config) => {
76
78
  const [
77
79
  {
80
+ backdropAnimated$: _backdropAnimated$,
78
81
  backdrop$: _backdrop$,
79
82
  backdropTransition$,
80
83
  backdropClass$,
@@ -159,9 +162,13 @@ const createDrawer = createWidgetFactory(
159
162
  }
160
163
  }))
161
164
  );
165
+ const backdropAnimated$ = asWritable(
166
+ computed(() => _backdropAnimated$() ?? animated$()),
167
+ (val) => _backdropAnimated$.set(val)
168
+ );
162
169
  const backdropTransition = createTransition({
163
170
  props: {
164
- animated: animated$,
171
+ animated: backdropAnimated$,
165
172
  transition: backdropTransition$
166
173
  }
167
174
  });
@@ -1,8 +1,8 @@
1
- import { computed, readable, derived } from "@amadeus-it-group/tansu";
1
+ import { computed, readable } from "@amadeus-it-group/tansu";
2
2
  import { createHasFocus } from "./services/focustrack.js";
3
3
  import { createNavManager } from "./services/navManager.js";
4
4
  import { typePlacementArray, createPositioning } from "./services/positioning.js";
5
- import { s as mergeDirectives, g as createAttributesDirective, d as browserDirective, o as directiveSubscribe, b as bindDirective } from "./directive-CMT2vEDg.js";
5
+ import { s as mergeDirectives, g as createAttributesDirective, d as browserDirective, b as bindDirective, w as addEvent } from "./directive-CMT2vEDg.js";
6
6
  import { noop } from "./utils/func.js";
7
7
  import { generateId } from "./utils/id.js";
8
8
  import { i as isFocusable, f as findPreviousFocusableElement, a as findNextFocusableElement, b as findNextElementSkippingSubtree, c as findNextElement } from "./isFocusable-C2iRr0zh.js";
@@ -83,11 +83,6 @@ const createDropdown = createWidgetFactory(
83
83
  End: ({ event }) => {
84
84
  event.preventDefault();
85
85
  focusLast({ event });
86
- },
87
- Escape: ({ event }) => {
88
- event.preventDefault();
89
- toggle(false);
90
- anchorElement?.focus();
91
86
  }
92
87
  },
93
88
  selector: (menuElement) => menuElement.querySelectorAll(menuItemSelector)
@@ -100,18 +95,54 @@ const createDropdown = createWidgetFactory(
100
95
  });
101
96
  const positioningBeforeRef$ = computed(() => positioning.stores.placement$()?.startsWith("top"));
102
97
  const { directive: hasFocusDirective, hasFocus$ } = createHasFocus();
103
- let previousHasFocus = false;
104
- const autoClose$ = derived(hasFocus$, (hasFocus) => {
105
- if (previousHasFocus && !hasFocus) {
106
- toggle(false);
107
- }
108
- previousHasFocus = hasFocus;
109
- });
110
98
  function toggle(opened) {
111
99
  opened$.update((currentOpened) => {
112
100
  return opened !== void 0 ? opened : !currentOpened;
113
101
  });
114
102
  }
103
+ const menuDismissDirective = browserDirective((menuElement) => {
104
+ let hadFocus = hasFocus$();
105
+ const unsubscribeFocus = hasFocus$.subscribe((hasFocus) => {
106
+ if (hadFocus && !hasFocus) {
107
+ toggle(false);
108
+ }
109
+ hadFocus = hasFocus;
110
+ });
111
+ const isInsideDropdown = (event) => {
112
+ const eventPath = event.composedPath();
113
+ return eventPath.includes(menuElement) || !!anchorElement && eventPath.includes(anchorElement);
114
+ };
115
+ const removeClickEvent = addEvent(
116
+ document.documentElement,
117
+ "click",
118
+ (event) => {
119
+ if (opened$() && !isInsideDropdown(event)) {
120
+ toggle(false);
121
+ }
122
+ },
123
+ { capture: true }
124
+ );
125
+ const removeKeydownEvent = addEvent(
126
+ document.documentElement,
127
+ "keydown",
128
+ (event) => {
129
+ if (opened$() && event.key === "Escape") {
130
+ toggle(false);
131
+ anchorElement?.focus();
132
+ event.preventDefault();
133
+ event.stopPropagation();
134
+ }
135
+ },
136
+ { capture: true }
137
+ );
138
+ return {
139
+ destroy: () => {
140
+ unsubscribeFocus();
141
+ removeClickEvent();
142
+ removeKeydownEvent();
143
+ }
144
+ };
145
+ });
115
146
  const menuIdIfNeeded$ = computed(() => opened$() && container$() === "body" ? menuId$() : void 0);
116
147
  const idIfOpen$ = computed(() => opened$() ? id$() : void 0);
117
148
  return {
@@ -127,7 +158,7 @@ const createDropdown = createWidgetFactory(
127
158
  positioning.directives.floatingDirective,
128
159
  bindDirective(navDirective, navManagerConfig$),
129
160
  hasFocusDirective,
130
- directiveSubscribe(autoClose$),
161
+ menuDismissDirective,
131
162
  createAttributesDirective(() => ({
132
163
  events: {
133
164
  // Clicking a non-interactive region of the menu (separator, padding, headers, aria-disabled items)
@@ -200,9 +231,6 @@ const createDropdown = createWidgetFactory(
200
231
  event.preventDefault();
201
232
  refreshElements(true);
202
233
  focusLast();
203
- } else if (key === "Escape") {
204
- event.preventDefault();
205
- toggle(false);
206
234
  } else if (key === "Tab") {
207
235
  const before = positioningBeforeRef$();
208
236
  if (!!event.shiftKey === before) {
package/index.js CHANGED
@@ -1,16 +1,16 @@
1
1
  import { FACTORY_WIDGET_NAME, INVALID_VALUE } from "./types.js";
2
- import { c, a, f, g } from "./accordion-B5RqDwi3.js";
3
- import { c as c2 } from "./alert-Db6cG6JE.js";
2
+ import { c, a, f, g } from "./accordion-DUFLBQkV.js";
3
+ import { c as c2 } from "./alert-klFrSyNy.js";
4
4
  import { c as c3, g as g2 } from "./collapse-D8Jo56k9.js";
5
- import { c as c4, g as g3 } from "./dropdown-Bjj2ql6d.js";
5
+ import { c as c4, g as g3 } from "./dropdown-BZiBfdNu.js";
6
6
  import { c as c5, g as g4, m, a as a2, b } from "./modal-CQWh2Sm5.js";
7
7
  import { c as c6, g as g5 } from "./pagination-DIRcpdRE.js";
8
8
  import { c as c7, g as g6 } from "./progressbar-Bth8r3Qu.js";
9
9
  import { c as c8, g as g7 } from "./rating-DLsgFSyB.js";
10
- import { c as c9, g as g8 } from "./slider-b9cVFNAL.js";
10
+ import { c as c9, g as g8 } from "./slider-tH5g55yQ.js";
11
11
  import { T, c as c10, d, g as g9 } from "./toaster-BS9qeRLF.js";
12
12
  import { c as c11, g as g10 } from "./tree-DW6iLxdw.js";
13
- import { c as c12, g as g11 } from "./drawer-CpGnS2ln.js";
13
+ import { c as c12, g as g11 } from "./drawer-D4xSbhcT.js";
14
14
  import { createWidgetsConfig, mergeInto } from "./config.js";
15
15
  import { extendWidgetProps } from "./services/extendWidget.js";
16
16
  import { activeElement$, createHasFocus } from "./services/focustrack.js";
@@ -27,7 +27,7 @@ import { createTransition, noAnimation } from "./services/transitions/baseTransi
27
27
  import { createCSSTransition, getTransitionDurationMs, hasTransition } from "./services/transitions/cssTransitions.js";
28
28
  import { createSimpleClassTransition } from "./services/transitions/simpleClassTransition.js";
29
29
  import { a as a3, b as b2, c as c13, d as d2, e, f as f2, g as g12, h, i, j, k, l, m as m2, n, o, p, q, r, s, t, u, v } from "./directive-CMT2vEDg.js";
30
- import { bindableDerived, bindableProp, createPatch, false$, findChangedProperties, idWithDefault, isStore, mergeConfigStores, normalizeConfigStores, stateStores, toReadableStore, toWritableStore, true$, writableWithDefault, writablesForProps, writablesWithDefault } from "./utils/stores.js";
30
+ import { bindableProp, createPatch, false$, findChangedProperties, idWithDefault, isStore, mergeConfigStores, normalizeConfigStores, stateStores, toReadableStore, toWritableStore, true$, writableWithDefault, writablesForProps, writablesWithDefault } from "./utils/stores.js";
31
31
  import { c as c14, a as a4, t as t2, b as b3, d as d3, e as e2, f as f3, g as g13, h as h2, i as i2, j as j2, k as k2, l as l2 } from "./writables-_7BriMb2.js";
32
32
  export {
33
33
  FACTORY_WIDGET_NAME,
@@ -37,7 +37,6 @@ export {
37
37
  a3 as attributesData,
38
38
  b2 as bindDirective,
39
39
  c13 as bindDirectiveNoArg,
40
- bindableDerived,
41
40
  bindableProp,
42
41
  d2 as browserDirective,
43
42
  e as classDirective,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@design-factory/core",
3
3
  "description": "Internal package used by the Design Factory.",
4
- "version": "22.0.0-next.0",
4
+ "version": "22.0.0",
5
5
  "type": "module",
6
6
  "main": "./index.cjs",
7
7
  "module": "./index.js",
@@ -2,7 +2,7 @@ import { computed, writable, derived, batch } from "@amadeus-it-group/tansu";
2
2
  import { e as typeBooleanOrNull, f as typeFunction, d as typeBoolean } from "../../writables-_7BriMb2.js";
3
3
  import { b as promiseWithResolve } from "../../promise-CkIc0KKt.js";
4
4
  import { noop } from "../../utils/func.js";
5
- import { writablesForProps, bindableDerived, stateStores } from "../../utils/stores.js";
5
+ import { writablesForProps, bindableProp, stateStores } from "../../utils/stores.js";
6
6
  import { m as createStoreDirective, s as mergeDirectives, o as directiveSubscribe } from "../../directive-CMT2vEDg.js";
7
7
  const neverEndingPromise = new Promise(noop);
8
8
  const noAnimation = (element, direction) => {
@@ -44,7 +44,7 @@ const createTransition = (config) => {
44
44
  ] = writablesForProps(defaultValues, config, configValidator);
45
45
  const { element$, directive: storeDirective } = createStoreDirective();
46
46
  const elementPresent$ = computed(() => !!element$());
47
- const visible$ = bindableDerived(onVisibleChange$, [requestedVisible$], ([visible]) => visible);
47
+ const visible$ = bindableProp(requestedVisible$, onVisibleChange$);
48
48
  const currentTransition$ = writable(
49
49
  null
50
50
  );
@@ -91,7 +91,7 @@ const createTransition = (config) => {
91
91
  const effectiveAnimation$ = computed(() => initDone$() ? animated$() : animatedOnInit$());
92
92
  const animationFromToggle$ = writable(null);
93
93
  let previousElement;
94
- let previousVisible = requestedVisible$();
94
+ let previousVisible = visible$();
95
95
  let pendingTransition = null;
96
96
  const visibleAction$ = derived(
97
97
  [visible$, element$, effectiveAnimation$, animationFromToggle$, transition$, currentTransition$],
@@ -132,14 +132,14 @@ const createTransition = (config) => {
132
132
  }
133
133
  );
134
134
  let lastToggle = {};
135
- const toggle = async (visible = !requestedVisible$(), animated = effectiveAnimation$()) => {
135
+ const toggle = async (visible = !visible$(), animated = effectiveAnimation$()) => {
136
136
  const currentToggle = {};
137
137
  lastToggle = currentToggle;
138
138
  try {
139
139
  await batch(() => {
140
140
  try {
141
141
  animationFromToggle$.set(animated);
142
- requestedVisible$.set(visible);
142
+ visible$.set(visible);
143
143
  return visibleAction$();
144
144
  } finally {
145
145
  animationFromToggle$.set(null);
@@ -3,6 +3,10 @@ import type { TransitionFn } from './baseTransitions';
3
3
  * Represents the context for a collapsible element.
4
4
  */
5
5
  export interface CollapseContext {
6
+ /**
7
+ * Whether the previous transition using this context was interrupted.
8
+ */
9
+ interrupted?: boolean;
6
10
  /**
7
11
  * the maximum size of the collapseable content.
8
12
  */
@@ -7,22 +7,29 @@ const createCollapseTransition = ({
7
7
  animationPendingClasses
8
8
  } = {}) => createCSSTransition((element, direction, animated, context) => {
9
9
  if (animated && isBrowserHTMLElement(element)) {
10
- removeClasses(element, animationPendingClasses);
11
- removeClasses(element, hideClasses);
12
- addClasses(element, showClasses);
13
- context.maxSize = element.getBoundingClientRect()[dimension] + "px";
14
- removeClasses(element, animationPendingClasses);
15
- removeClasses(element, showClasses);
16
- addClasses(element, hideClasses);
17
- context.minSize = element.getBoundingClientRect()[dimension] + "px";
18
- removeClasses(element, showClasses);
19
- removeClasses(element, hideClasses);
10
+ const interrupted = context.interrupted;
11
+ if (!context.maxSize || !context.minSize) {
12
+ element.style[dimension] = "";
13
+ removeClasses(element, animationPendingClasses);
14
+ removeClasses(element, hideClasses);
15
+ addClasses(element, showClasses);
16
+ context.maxSize = element.getBoundingClientRect()[dimension] + "px";
17
+ removeClasses(element, animationPendingClasses);
18
+ removeClasses(element, showClasses);
19
+ addClasses(element, hideClasses);
20
+ context.minSize = element.getBoundingClientRect()[dimension] + "px";
21
+ removeClasses(element, showClasses);
22
+ removeClasses(element, hideClasses);
23
+ }
20
24
  const values = direction === "show" ? [context.minSize, context.maxSize] : [context.maxSize, context.minSize];
21
- element.style[dimension] = values[0];
22
- reflow(element);
23
- addClasses(element, animationPendingClasses);
24
- reflow(element);
25
+ if (!interrupted) {
26
+ element.style[dimension] = values[0];
27
+ reflow(element);
28
+ addClasses(element, animationPendingClasses);
29
+ reflow(element);
30
+ }
25
31
  element.style[dimension] = values[1];
32
+ context.interrupted = true;
26
33
  } else {
27
34
  removeClasses(element, direction === "show" ? hideClasses : showClasses);
28
35
  }
@@ -131,13 +131,6 @@ const computeCleanValue = (value, min, max, intStepSize, decimalPrecision) => {
131
131
  const indexMin = Math.floor((value - min) * magnitude / intStepSize);
132
132
  return +(((value - min) * magnitude % intStepSize < intStepSize / 2 ? indexMin : indexMin + 1) * intStepSize / magnitude + min).toFixed(decimalPrecision);
133
133
  };
134
- const updateValue = (handleIndex, values$, stepSize, updateDirection) => {
135
- values$.update((value) => {
136
- value = [...value];
137
- value[handleIndex] = value[handleIndex] + stepSize * updateDirection;
138
- return value;
139
- });
140
- };
141
134
  const getUpdateDirection = (vertical, rtl, keysVertical) => {
142
135
  if (vertical && rtl) {
143
136
  return keysVertical ? 1 : -1;
@@ -215,7 +208,6 @@ const createSlider = createWidgetFactory(
215
208
  () => Math.max(getDecimalPrecision(stepSize$()), getDecimalPrecision(min$()), getDecimalPrecision(max$()))
216
209
  );
217
210
  const _intStepSize$ = computed(() => stepSize$() * Math.pow(10, _decimalPrecision$()));
218
- let previousValues = _dirtyValues$();
219
211
  const values$ = bindableProp(
220
212
  _dirtyValues$,
221
213
  onValuesChange$,
@@ -224,23 +216,28 @@ const createSlider = createWidgetFactory(
224
216
  const max = max$();
225
217
  const intStepSize = _intStepSize$();
226
218
  const decimalPrecision = _decimalPrecision$();
227
- const newValues = dirtyValues.map((dv) => computeCleanValue(dv, min, max, intStepSize, decimalPrecision));
228
- if (dirtyValues.length > 1) {
219
+ return dirtyValues.map((dv) => computeCleanValue(dv, min, max, intStepSize, decimalPrecision));
220
+ },
221
+ typeArray.equal
222
+ );
223
+ const updateValueAtIndex = (index, newValue) => {
224
+ values$.update((vals) => {
225
+ const min = min$();
226
+ const max = max$();
227
+ const intStepSize = _intStepSize$();
228
+ const decimalPrecision = _decimalPrecision$();
229
+ const newVals = [...vals];
230
+ newVals[index] = computeCleanValue(newValue, min, max, intStepSize, decimalPrecision);
231
+ if (newVals.length > 1) {
229
232
  const minRange = minRange$();
230
233
  const maxRange = maxRange$();
231
234
  if (minRange || maxRange) {
232
- const pushRange = pushRange$();
233
- const changedIndex = newValues.findIndex((dv, index) => dv !== previousValues[index]);
234
- if (changedIndex !== -1) {
235
- manageMinMaxRange(newValues, changedIndex, minRange, maxRange, min, max, pushRange);
236
- }
235
+ manageMinMaxRange(newVals, index, minRange, maxRange, min, max, pushRange$());
237
236
  }
238
237
  }
239
- previousValues = newValues;
240
- return newValues;
241
- },
242
- typeArray.equal
243
- );
238
+ return newVals;
239
+ });
240
+ };
244
241
  const { directive: sliderDirective, element$: sliderDom$ } = createBrowserStoreDirective();
245
242
  const { directive: minLabelDomDirective, element$: minLabelDom$ } = createBrowserStoreDirective();
246
243
  const { directive: maxLabelDomDirective, element$: maxLabelDom$ } = createBrowserStoreDirective();
@@ -516,11 +513,7 @@ const createSlider = createWidgetFactory(
516
513
  const clickedPercent = getClickedPercent(clickedCoordinate);
517
514
  const derivedHandleIndex = handleNumber ?? getClosestSliderHandle(clickedPercent);
518
515
  const newValue = clickedPercent * (max$() - min$()) + min$();
519
- values$.update((dh) => {
520
- dh = [...dh];
521
- dh[derivedHandleIndex] = newValue;
522
- return dh;
523
- });
516
+ updateValueAtIndex(derivedHandleIndex, newValue);
524
517
  }
525
518
  };
526
519
  const horizontal$ = computed(() => !vertical$());
@@ -621,30 +614,34 @@ const createSlider = createWidgetFactory(
621
614
  if (interactive$()) {
622
615
  switch (key) {
623
616
  case "ArrowDown":
624
- updateValue(handleIndex, values$, stepSize, getUpdateDirection(vertical, rtl, true));
617
+ updateValueAtIndex(
618
+ handleIndex,
619
+ values$()[handleIndex] + stepSize * getUpdateDirection(vertical, rtl, true)
620
+ );
625
621
  break;
626
622
  case "ArrowLeft":
627
- updateValue(handleIndex, values$, stepSize, getUpdateDirection(vertical, rtl, false));
623
+ updateValueAtIndex(
624
+ handleIndex,
625
+ values$()[handleIndex] + stepSize * getUpdateDirection(vertical, rtl, false)
626
+ );
628
627
  break;
629
628
  case "ArrowUp":
630
- updateValue(handleIndex, values$, stepSize, -1 * getUpdateDirection(vertical, rtl, true));
629
+ updateValueAtIndex(
630
+ handleIndex,
631
+ values$()[handleIndex] + stepSize * -1 * getUpdateDirection(vertical, rtl, true)
632
+ );
631
633
  break;
632
634
  case "ArrowRight":
633
- updateValue(handleIndex, values$, stepSize, -1 * getUpdateDirection(vertical, rtl, false));
635
+ updateValueAtIndex(
636
+ handleIndex,
637
+ values$()[handleIndex] + stepSize * -1 * getUpdateDirection(vertical, rtl, false)
638
+ );
634
639
  break;
635
640
  case "Home":
636
- values$.update((value) => {
637
- value = [...value];
638
- value[handleIndex] = min;
639
- return value;
640
- });
641
+ updateValueAtIndex(handleIndex, min);
641
642
  break;
642
643
  case "End":
643
- values$.update((value) => {
644
- value = [...value];
645
- value[handleIndex] = max;
646
- return value;
647
- });
644
+ updateValueAtIndex(handleIndex, max);
648
645
  break;
649
646
  case "PageUp":
650
647
  break;
@@ -0,0 +1,177 @@
1
+ import { writable, derived, computed, readable } from "@amadeus-it-group/tansu";
2
+ import { createHasFocus, activeElement$ } from "./services/focustrack.js";
3
+ import { createHasMouseInside } from "./services/mousetrack.js";
4
+ import { typePlacement, createPositioning } from "./services/positioning.js";
5
+ import { createTransition } from "./services/transitions/baseTransitions.js";
6
+ import { createSimpleClassTransition } from "./services/transitions/simpleClassTransition.js";
7
+ import { debounceSignal } from "./utils/debounceSignal.js";
8
+ import { w as addEvent, s as mergeDirectives, g as createAttributesDirective, o as directiveSubscribe } from "./directive-CMT2vEDg.js";
9
+ import { createEdgeState } from "./utils/edgeState.js";
10
+ import { generateId } from "./utils/id.js";
11
+ import { writablesForProps, stateStores } from "./utils/stores.js";
12
+ import { createWidgetFactory } from "./utils/widget.js";
13
+ import { a as createTypeStringSpacedArray, d as typeBoolean, l as typeStringOrNull, c as createTypeEnum } from "./writables-_7BriMb2.js";
14
+ const verticalPlacement = ["top", "top-start", "top-end", "bottom", "bottom-start", "bottom-end"];
15
+ const horizontalPlacement = ["end", "end-end", "end-start", "start", "start-end", "start-start"];
16
+ const defaultPlacement = [...verticalPlacement, ...horizontalPlacement];
17
+ const fadeTransition = createSimpleClassTransition({
18
+ animationPendingClasses: ["df-fade"],
19
+ animationPendingShowClasses: ["df-show"],
20
+ showClasses: ["df-show", "df-fade"],
21
+ hideClasses: ["df-hidden", "df-fade"]
22
+ });
23
+ const defaultTooltipConfig = {
24
+ animated: true,
25
+ content: "",
26
+ disabled: false,
27
+ placement: defaultPlacement,
28
+ size: "md"
29
+ };
30
+ const tooltipPlacementValidator = createTypeStringSpacedArray((placement) => {
31
+ if (placement === "auto") {
32
+ return defaultPlacement;
33
+ } else if (placement === "vertical") {
34
+ return verticalPlacement;
35
+ } else if (placement === "horizontal") {
36
+ return horizontalPlacement;
37
+ }
38
+ return typePlacement.normalizeValue(placement);
39
+ });
40
+ const tooltipConfigValidator = {
41
+ animated: typeBoolean,
42
+ content: typeStringOrNull,
43
+ disabled: typeBoolean,
44
+ placement: tooltipPlacementValidator,
45
+ size: createTypeEnum(["sm", "md", "lg"])
46
+ };
47
+ const DEBOUNCE_DELAY = 200;
48
+ const createTooltip = createWidgetFactory(
49
+ "tooltip",
50
+ (config) => {
51
+ const [{ placement$, animated$, disabled$, content$, ...stateProps }, patch] = writablesForProps(
52
+ defaultTooltipConfig,
53
+ config,
54
+ tooltipConfigValidator
55
+ );
56
+ const floating = createPositioning({
57
+ props: {
58
+ placement: placement$
59
+ }
60
+ });
61
+ const { directive: hasFocusDirective, hasFocus$ } = createHasFocus();
62
+ const forceVisibleOnFocus$ = writable(false);
63
+ const hasVisibleFocus$ = derived(
64
+ [hasFocus$, activeElement$, forceVisibleOnFocus$],
65
+ ([hasFocus, activeElement, forceVisibleOnFocus], set) => {
66
+ if (hasFocus) {
67
+ if (forceVisibleOnFocus || activeElement?.matches(":focus-visible")) {
68
+ set(true);
69
+ }
70
+ } else {
71
+ set(false);
72
+ }
73
+ },
74
+ false
75
+ );
76
+ const debouncedHasVisibleFocus$ = debounceSignal(hasVisibleFocus$, (value) => value ? DEBOUNCE_DELAY : -1);
77
+ const { directive: hasMouseInsideDirective, hasMouseInside$ } = createHasMouseInside();
78
+ const debouncedHasMouseInside$ = debounceSignal(hasMouseInside$, DEBOUNCE_DELAY);
79
+ const visible$ = createEdgeState(
80
+ {
81
+ mouseInside: debouncedHasMouseInside$,
82
+ hasVisibleFocus: debouncedHasVisibleFocus$
83
+ },
84
+ computed(() => disabled$() || !content$() || floating.stores.referenceHidden$())
85
+ );
86
+ const transition = createTransition({
87
+ props: {
88
+ transition: fadeTransition,
89
+ visible: visible$,
90
+ animated: animated$,
91
+ animatedOnInit: true
92
+ }
93
+ });
94
+ const escDismiss$ = readable(void 0, {
95
+ onUse: () => addEvent(
96
+ document.documentElement,
97
+ "keydown",
98
+ (event) => {
99
+ if (visible$() && event.key === "Escape") {
100
+ void transition.api.toggle(false);
101
+ event.preventDefault();
102
+ event.stopPropagation();
103
+ }
104
+ },
105
+ { capture: true }
106
+ )
107
+ });
108
+ const id$ = computed(generateId);
109
+ return {
110
+ ...stateStores({
111
+ ...stateProps,
112
+ content$,
113
+ animated$,
114
+ disabled$,
115
+ placement$,
116
+ visible$: transition.stores.visible$,
117
+ hidden$: transition.stores.hidden$
118
+ }),
119
+ patch,
120
+ api: {},
121
+ directives: {
122
+ referenceDirective: mergeDirectives(
123
+ floating.directives.referenceDirective,
124
+ hasFocusDirective,
125
+ hasMouseInsideDirective,
126
+ createAttributesDirective(() => ({
127
+ attributes: {
128
+ "aria-describedby": computed(() => transition.stores.hidden$() ? void 0 : id$())
129
+ },
130
+ styles: {
131
+ // prevents the trigger element from being selected when long-pressing on touch devices
132
+ userSelect: computed(() => disabled$() ? void 0 : "none")
133
+ },
134
+ events: {
135
+ contextmenu: (event) => {
136
+ if (event.pointerType === "touch" && !disabled$()) {
137
+ event.preventDefault();
138
+ if (hasVisibleFocus$()) {
139
+ void transition.api.toggle(true);
140
+ } else {
141
+ forceVisibleOnFocus$.set(true);
142
+ event.currentTarget?.focus?.();
143
+ forceVisibleOnFocus$.set(false);
144
+ }
145
+ }
146
+ }
147
+ }
148
+ }))
149
+ ),
150
+ floatingDirective: mergeDirectives(
151
+ floating.directives.floatingDirective,
152
+ transition.directives.directive,
153
+ hasMouseInsideDirective,
154
+ directiveSubscribe(escDismiss$),
155
+ createAttributesDirective(() => ({
156
+ attributes: {
157
+ role: readable("tooltip"),
158
+ id: id$
159
+ },
160
+ events: {
161
+ mousedown: (event) => {
162
+ if (hasVisibleFocus$() && debouncedHasMouseInside$() && !event.defaultPrevented) {
163
+ visible$.skipNextSourceValue("hasVisibleFocus", false);
164
+ }
165
+ }
166
+ }
167
+ }))
168
+ )
169
+ }
170
+ };
171
+ }
172
+ );
173
+ export {
174
+ createTooltip as c,
175
+ defaultPlacement as d,
176
+ tooltipPlacementValidator as t
177
+ };
package/utils/stores.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ReadableSignal, StoreInput, StoresInputValues, WritableSignal } from '@amadeus-it-group/tansu';
1
+ import type { ReadableSignal, WritableSignal } from '@amadeus-it-group/tansu';
2
2
  import type { ConfigValidator, PropsConfig, ValuesOrReadableSignals, WritableWithDefaultOptions } from '../types';
3
3
  /**
4
4
  * Transforms the properties of a given type `P` into writable signals.
@@ -188,20 +188,6 @@ export declare const stateStores: <A extends object>(inputStores: { [K in keyof
188
188
  state$: ReadableSignal<A>;
189
189
  stores: { [K in keyof A as `${K & string}$`]: ReadableSignal<A[K]>; };
190
190
  };
191
- /**
192
- * Creates a writable signal that derives its value from multiple stores and allows for custom adjustment and equality checks.
193
- *
194
- * @template T - The type of the derived value.
195
- * @template U - A tuple type where the first element is a writable signal of type T and the rest are store inputs.
196
- *
197
- * @param onChange$ - A readable signal that emits a function to be called when the derived value changes.
198
- * @param stores - A tuple of stores where the first element is a writable signal of type T and the rest are store inputs.
199
- * @param adjustValue - A function to adjust the derived value based on the input values from the stores.
200
- * @param equal - A function to compare the current and new values for equality.
201
- *
202
- * @returns A writable signal that derives its value from the provided stores and allows for custom adjustment and equality checks.
203
- */
204
- export declare const bindableDerived: <T, U extends [WritableSignal<T>, ...StoreInput<any>[]]>(onChange$: ReadableSignal<(value: T) => void>, stores: U, adjustValue?: (arg: StoresInputValues<U>) => T, equal?: (currentValue: T, newValue: T) => boolean) => WritableSignal<T>;
205
191
  /**
206
192
  * Creates a bindable property that synchronizes a writable signal with an optional adjustment function and equality check.
207
193
  *
package/utils/stores.js CHANGED
@@ -1,4 +1,4 @@
1
- import { readable, equal, asWritable, derived, computed, batch, asReadable, get, writable } from "@amadeus-it-group/tansu";
1
+ import { readable, equal, asWritable, computed, batch, asReadable, get, writable } from "@amadeus-it-group/tansu";
2
2
  import { INVALID_VALUE } from "../types.js";
3
3
  import { identity } from "./func.js";
4
4
  import { generateId } from "./id.js";
@@ -118,27 +118,6 @@ const stateStores = (inputStores) => {
118
118
  })
119
119
  };
120
120
  };
121
- const bindableDerived = (onChange$, stores, adjustValue = (arg) => arg[0], equal2 = (currentValue, newValue) => newValue === currentValue) => {
122
- let currentValue = stores[0]();
123
- return asWritable(
124
- derived(stores, {
125
- derive(values) {
126
- const newValue = adjustValue(values);
127
- const rectifiedValue = !equal2(values[0], newValue);
128
- if (rectifiedValue) {
129
- stores[0].set(newValue);
130
- }
131
- if (rectifiedValue || !equal2(currentValue, newValue)) {
132
- currentValue = newValue;
133
- onChange$()(newValue);
134
- }
135
- return newValue;
136
- },
137
- equal: equal2
138
- }),
139
- stores[0].set.bind(stores[0])
140
- );
141
- };
142
121
  const bindableProp = (store$, onChange$, adjustValue = identity, equal$1 = equal) => asWritable(
143
122
  computed(() => adjustValue(store$()), { equal: equal$1 }),
144
123
  (newValue) => {
@@ -156,7 +135,6 @@ function idWithDefault(id$) {
156
135
  const true$ = readable(true);
157
136
  const false$ = readable(false);
158
137
  export {
159
- bindableDerived,
160
138
  bindableProp,
161
139
  createPatch,
162
140
  false$,