@agnos-ui/core 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/accordion-BaWN0_n-.js +330 -0
- package/accordion-BuIgxZ0S.cjs +329 -0
- package/alert-C4jCg9Pl.cjs +8 -0
- package/alert-Dlf-BV98.js +9 -0
- package/common-DRdsw5m8.js +76 -0
- package/common-nJRMXbwj.cjs +75 -0
- package/components/accordion/accordion.d.ts +57 -64
- package/components/accordion/index.cjs +7 -0
- package/components/accordion/index.js +7 -1
- package/components/alert/alert.d.ts +3 -12
- package/components/alert/common.d.ts +4 -13
- package/components/alert/index.cjs +10 -0
- package/components/alert/index.js +10 -2
- package/components/modal/index.cjs +7 -0
- package/components/modal/index.js +7 -1
- package/components/modal/modal.d.ts +7 -49
- package/components/pagination/index.cjs +5 -0
- package/components/pagination/index.d.ts +0 -1
- package/components/pagination/index.js +5 -2
- package/components/pagination/pagination.d.ts +107 -128
- package/components/progressbar/index.cjs +5 -0
- package/components/progressbar/index.js +5 -1
- package/components/progressbar/progressbar.d.ts +6 -22
- package/components/rating/index.cjs +5 -0
- package/components/rating/index.js +5 -1
- package/components/rating/rating.d.ts +16 -11
- package/components/select/index.cjs +6 -0
- package/components/select/index.js +6 -1
- package/components/select/select.d.ts +45 -57
- package/components/slider/index.cjs +5 -0
- package/components/slider/index.js +5 -1
- package/components/slider/slider.d.ts +63 -5
- package/components/toast/index.cjs +5 -0
- package/components/toast/index.d.ts +1 -0
- package/components/toast/index.js +5 -0
- package/components/toast/toast.d.ts +47 -0
- package/config.cjs +38 -0
- package/config.d.ts +6 -1
- package/config.js +35 -50
- package/directive-BTSEYLF3.cjs +404 -0
- package/directive-DCYlDznf.js +405 -0
- package/func-DR0n-ShK.js +7 -0
- package/func-Qd3cD9a3.cjs +6 -0
- package/index.cjs +119 -0
- package/index.d.ts +3 -1
- package/index.js +119 -31
- package/modal-BI2qUu1M.js +251 -0
- package/modal-rzMpATf5.cjs +250 -0
- package/package.json +30 -22
- package/pagination--GkwduJn.js +263 -0
- package/pagination-EWSWQT1I.cjs +262 -0
- package/progressbar-DH7DHYMp.cjs +83 -0
- package/progressbar-DuRX7_my.js +84 -0
- package/promise-BMJ8qhA8.cjs +118 -0
- package/promise-CY2U8bTP.js +119 -0
- package/rating-BR5wD7y2.js +173 -0
- package/rating-CmuYUSxy.cjs +172 -0
- package/select-BCs6HQWn.js +358 -0
- package/select-CCIKn8WR.cjs +357 -0
- package/services/extendWidget.cjs +32 -0
- package/services/extendWidget.d.ts +10 -5
- package/services/extendWidget.js +31 -34
- package/services/floatingUI.cjs +131 -0
- package/services/floatingUI.d.ts +30 -14
- package/services/floatingUI.js +128 -102
- package/services/focustrack.cjs +47 -0
- package/services/focustrack.js +45 -44
- package/services/hash.cjs +15 -0
- package/services/hash.d.ts +2 -0
- package/services/hash.js +15 -0
- package/services/intersection.cjs +53 -0
- package/services/intersection.js +48 -50
- package/services/matchMedia.cjs +13 -0
- package/services/matchMedia.d.ts +7 -0
- package/services/matchMedia.js +13 -0
- package/services/navManager.cjs +196 -0
- package/services/navManager.d.ts +24 -17
- package/services/navManager.js +186 -162
- package/services/portal.cjs +43 -0
- package/services/portal.js +41 -42
- package/services/resizeObserver.cjs +32 -0
- package/services/resizeObserver.d.ts +14 -0
- package/services/resizeObserver.js +32 -0
- package/services/siblingsInert.cjs +40 -0
- package/services/siblingsInert.js +31 -31
- package/services/transitions/baseTransitions.cjs +171 -0
- package/services/transitions/baseTransitions.d.ts +16 -16
- package/services/transitions/baseTransitions.js +159 -170
- package/services/transitions/collapse.cjs +44 -0
- package/services/transitions/collapse.js +41 -49
- package/services/transitions/cssTransitions.cjs +32 -0
- package/services/transitions/cssTransitions.d.ts +2 -1
- package/services/transitions/cssTransitions.js +29 -39
- package/services/transitions/simpleClassTransition.cjs +31 -0
- package/services/transitions/simpleClassTransition.js +30 -41
- package/slider-CA_fszn7.js +536 -0
- package/slider-DsLvT87U.cjs +535 -0
- package/toast-8tWp6x89.js +63 -0
- package/toast-Aw8o0Iwe.cjs +62 -0
- package/types.cjs +12 -0
- package/types.d.ts +21 -1
- package/types.js +11 -13
- package/utils/directive.cjs +26 -0
- package/utils/directive.d.ts +155 -4
- package/utils/directive.js +25 -189
- package/utils/internal/dom.d.ts +57 -3
- package/utils/internal/promise.d.ts +2 -2
- package/utils/internal/ssrHTMLElement.d.ts +7 -0
- package/utils/internal/textDirection.d.ts +1 -1
- package/utils/stores.cjs +163 -0
- package/utils/stores.d.ts +23 -20
- package/utils/stores.js +151 -269
- package/utils/writables.cjs +13 -0
- package/utils/writables.js +12 -71
- package/writables-D46sFgGK.cjs +85 -0
- package/writables-DoU_XYTX.js +86 -0
- package/components/accordion/accordion.js +0 -267
- package/components/alert/alert.js +0 -22
- package/components/alert/common.js +0 -69
- package/components/commonProps.js +0 -1
- package/components/modal/modal.js +0 -186
- package/components/pagination/bootstrap.d.ts +0 -8
- package/components/pagination/bootstrap.js +0 -110
- package/components/pagination/pagination.js +0 -149
- package/components/progressbar/progressbar.js +0 -78
- package/components/rating/rating.js +0 -138
- package/components/select/select.js +0 -266
- package/components/slider/slider.js +0 -415
- package/services/transitions/bootstrap/collapse.d.ts +0 -2
- package/services/transitions/bootstrap/collapse.js +0 -15
- package/services/transitions/bootstrap/fade.d.ts +0 -1
- package/services/transitions/bootstrap/fade.js +0 -7
- package/services/transitions/bootstrap.d.ts +0 -2
- package/services/transitions/bootstrap.js +0 -2
- package/utils/internal/checks.js +0 -60
- package/utils/internal/dom.js +0 -61
- package/utils/internal/func.js +0 -11
- package/utils/internal/isFocusable.js +0 -35
- package/utils/internal/math.js +0 -13
- package/utils/internal/promise.js +0 -169
- package/utils/internal/scrollbars.js +0 -33
- package/utils/internal/sort.js +0 -28
- package/utils/internal/textDirection.js +0 -7
- package/utils/internal/traversal.js +0 -105
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
import { asWritable, computed, writable } from '@amadeus-it-group/tansu';
|
|
2
|
-
import { autoPlacement, offset, size } from '@floating-ui/dom';
|
|
3
|
-
import { createFloatingUI } from '../../services/floatingUI';
|
|
4
|
-
import { createHasFocus } from '../../services/focustrack';
|
|
5
|
-
import { noop } from '../../utils/internal/func';
|
|
6
|
-
import { bindableDerived, stateStores, writablesForProps } from '../../utils/stores';
|
|
7
|
-
const defaultItemId = (item) => '' + item;
|
|
8
|
-
export const defaultConfig = {
|
|
9
|
-
id: undefined,
|
|
10
|
-
ariaLabel: 'Select',
|
|
11
|
-
open: false,
|
|
12
|
-
disabled: false,
|
|
13
|
-
items: [],
|
|
14
|
-
filterText: '',
|
|
15
|
-
loading: false,
|
|
16
|
-
selected: [],
|
|
17
|
-
itemIdFn: defaultItemId,
|
|
18
|
-
onOpenChange: noop,
|
|
19
|
-
onFilterTextChange: noop,
|
|
20
|
-
onSelectedChange: noop,
|
|
21
|
-
allowedPlacements: ['bottom-start', 'top-start', 'bottom-end', 'top-end'],
|
|
22
|
-
className: '',
|
|
23
|
-
menuClassName: '',
|
|
24
|
-
menuItemClassName: '',
|
|
25
|
-
badgeClassName: '',
|
|
26
|
-
slotBadgeLabel: ({ itemContext }) => itemContext.item,
|
|
27
|
-
slotItem: ({ itemContext }) => itemContext.item,
|
|
28
|
-
};
|
|
29
|
-
/**
|
|
30
|
-
* Returns a shallow copy of the default select config.
|
|
31
|
-
* @returns a copy of the default config
|
|
32
|
-
*/
|
|
33
|
-
export function getSelectDefaultConfig() {
|
|
34
|
-
return { ...defaultConfig };
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Create a SelectWidget with given config props
|
|
38
|
-
* @param config - an optional alert config
|
|
39
|
-
* @returns a SelectWidget
|
|
40
|
-
*/
|
|
41
|
-
export function createSelect(config) {
|
|
42
|
-
// Props
|
|
43
|
-
const [{ open$: _dirtyOpen$, filterText$: _dirtyFilterText$, items$, itemIdFn$, onOpenChange$, onFilterTextChange$, onSelectedChange$, allowedPlacements$, ...stateProps }, patch,] = writablesForProps(defaultConfig, config);
|
|
44
|
-
const { selected$ } = stateProps;
|
|
45
|
-
const filterText$ = bindableDerived(onFilterTextChange$, [_dirtyFilterText$]);
|
|
46
|
-
const { hasFocus$, directive: hasFocusDirective } = createHasFocus();
|
|
47
|
-
const open$ = bindableDerived(onOpenChange$, [_dirtyOpen$, hasFocus$], ([_dirtyOpen, hasFocus]) => _dirtyOpen && hasFocus);
|
|
48
|
-
const selectedContextsMap$ = computed(() => {
|
|
49
|
-
const selectedItemsContext = new Map();
|
|
50
|
-
const itemIdFn = itemIdFn$();
|
|
51
|
-
for (const item of selected$()) {
|
|
52
|
-
const id = itemIdFn(item);
|
|
53
|
-
selectedItemsContext.set(id, {
|
|
54
|
-
item,
|
|
55
|
-
id: itemIdFn(item),
|
|
56
|
-
selected: true,
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
return selectedItemsContext;
|
|
60
|
-
});
|
|
61
|
-
const selectedContexts$ = computed(() => [...selectedContextsMap$().values()]);
|
|
62
|
-
const highlightedIndex$ = (function () {
|
|
63
|
-
const store = writable(0);
|
|
64
|
-
return asWritable(store, (index) => {
|
|
65
|
-
const { length } = visibleItems$();
|
|
66
|
-
if (index != undefined) {
|
|
67
|
-
if (!length) {
|
|
68
|
-
index = undefined;
|
|
69
|
-
}
|
|
70
|
-
else if (index < 0) {
|
|
71
|
-
index = length - 1;
|
|
72
|
-
}
|
|
73
|
-
else if (index >= length) {
|
|
74
|
-
index = 0;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
store.set(index);
|
|
78
|
-
});
|
|
79
|
-
})();
|
|
80
|
-
const itemContexts$ = computed(() => {
|
|
81
|
-
const itemContexts = new Map();
|
|
82
|
-
if (open$()) {
|
|
83
|
-
const selectedContextsMap = selectedContextsMap$();
|
|
84
|
-
const itemIdFn = itemIdFn$();
|
|
85
|
-
for (const item of items$()) {
|
|
86
|
-
const id = itemIdFn(item);
|
|
87
|
-
itemContexts.set(id, {
|
|
88
|
-
item,
|
|
89
|
-
id,
|
|
90
|
-
selected: selectedContextsMap.has(id),
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return itemContexts;
|
|
95
|
-
});
|
|
96
|
-
const visibleItems$ = computed(() => (open$() ? [...itemContexts$().values()] : []));
|
|
97
|
-
const highlighted$ = computed(() => {
|
|
98
|
-
const visibleItems = visibleItems$();
|
|
99
|
-
const highlightedIndex = highlightedIndex$();
|
|
100
|
-
return visibleItems.length && highlightedIndex != undefined ? visibleItems[highlightedIndex] : undefined;
|
|
101
|
-
});
|
|
102
|
-
const { directives: { floatingDirective, referenceDirective }, stores: { placement$ }, } = createFloatingUI({
|
|
103
|
-
props: {
|
|
104
|
-
computePositionOptions: asWritable(computed(() => ({
|
|
105
|
-
middleware: [
|
|
106
|
-
offset(5),
|
|
107
|
-
autoPlacement({
|
|
108
|
-
allowedPlacements: allowedPlacements$(),
|
|
109
|
-
}),
|
|
110
|
-
size(),
|
|
111
|
-
],
|
|
112
|
-
}))),
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
|
-
const widget = {
|
|
116
|
-
...stateStores({
|
|
117
|
-
visibleItems$,
|
|
118
|
-
highlighted$,
|
|
119
|
-
open$,
|
|
120
|
-
selectedContexts$,
|
|
121
|
-
filterText$,
|
|
122
|
-
placement$,
|
|
123
|
-
...stateProps,
|
|
124
|
-
}),
|
|
125
|
-
patch,
|
|
126
|
-
api: {
|
|
127
|
-
clear() {
|
|
128
|
-
selected$.set([]);
|
|
129
|
-
},
|
|
130
|
-
select(item) {
|
|
131
|
-
widget.api.toggleItem(item, true);
|
|
132
|
-
},
|
|
133
|
-
unselect(item) {
|
|
134
|
-
widget.api.toggleItem(item, false);
|
|
135
|
-
},
|
|
136
|
-
toggleItem(item, selected) {
|
|
137
|
-
const itemIdFn = itemIdFn$();
|
|
138
|
-
const itemId = itemIdFn(item);
|
|
139
|
-
const selectedContextsMap = selectedContextsMap$();
|
|
140
|
-
const isInSelected = selectedContextsMap.has(itemId);
|
|
141
|
-
if (selected == null) {
|
|
142
|
-
selected = !isInSelected;
|
|
143
|
-
}
|
|
144
|
-
if ((selected && !itemContexts$().has(itemId)) || (!selected && !isInSelected)) {
|
|
145
|
-
// Nothing to do in this case
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
selected$.update((selectedItems) => {
|
|
149
|
-
selectedItems = [...selectedItems]; // Mutate the array
|
|
150
|
-
if (selected && !isInSelected) {
|
|
151
|
-
selectedItems.push(item);
|
|
152
|
-
}
|
|
153
|
-
else if (!selected && isInSelected) {
|
|
154
|
-
const index = selectedItems.findIndex((item) => itemIdFn(item) === itemId);
|
|
155
|
-
selectedItems.splice(index, 1);
|
|
156
|
-
}
|
|
157
|
-
onSelectedChange$()?.(selectedItems);
|
|
158
|
-
return selectedItems;
|
|
159
|
-
});
|
|
160
|
-
},
|
|
161
|
-
clearText() {
|
|
162
|
-
// FIXME: not implemented yet!
|
|
163
|
-
},
|
|
164
|
-
highlight(item) {
|
|
165
|
-
const index = visibleItems$().findIndex((itemCtx) => itemCtx.item === item);
|
|
166
|
-
highlightedIndex$.set(index === -1 ? undefined : index);
|
|
167
|
-
},
|
|
168
|
-
highlightFirst() {
|
|
169
|
-
highlightedIndex$.set(0);
|
|
170
|
-
},
|
|
171
|
-
highlightPrevious() {
|
|
172
|
-
highlightedIndex$.update((highlightedIndex) => {
|
|
173
|
-
return highlightedIndex != null ? highlightedIndex - 1 : -1;
|
|
174
|
-
});
|
|
175
|
-
},
|
|
176
|
-
highlightNext() {
|
|
177
|
-
highlightedIndex$.update((highlightedIndex) => {
|
|
178
|
-
return highlightedIndex != null ? highlightedIndex + 1 : Infinity;
|
|
179
|
-
});
|
|
180
|
-
},
|
|
181
|
-
highlightLast() {
|
|
182
|
-
highlightedIndex$.set(-1);
|
|
183
|
-
},
|
|
184
|
-
focus(item) {
|
|
185
|
-
// FIXME: not implemented yet!
|
|
186
|
-
},
|
|
187
|
-
focusFirst() {
|
|
188
|
-
// FIXME: not implemented yet!
|
|
189
|
-
},
|
|
190
|
-
focusPrevious() {
|
|
191
|
-
// FIXME: not implemented yet!
|
|
192
|
-
},
|
|
193
|
-
focusNext() {
|
|
194
|
-
// FIXME: not implemented yet!
|
|
195
|
-
},
|
|
196
|
-
focusLast() {
|
|
197
|
-
// FIXME: not implemented yet!
|
|
198
|
-
},
|
|
199
|
-
open: () => widget.api.toggle(true),
|
|
200
|
-
close: () => widget.api.toggle(false),
|
|
201
|
-
toggle(isOpen) {
|
|
202
|
-
_dirtyOpen$.update((value) => (isOpen != null ? isOpen : !value));
|
|
203
|
-
},
|
|
204
|
-
},
|
|
205
|
-
directives: {
|
|
206
|
-
hasFocusDirective,
|
|
207
|
-
floatingDirective,
|
|
208
|
-
referenceDirective,
|
|
209
|
-
},
|
|
210
|
-
actions: {
|
|
211
|
-
onInput({ target }) {
|
|
212
|
-
const value = target.value;
|
|
213
|
-
patch({
|
|
214
|
-
open: value != null && value !== '',
|
|
215
|
-
filterText: value,
|
|
216
|
-
});
|
|
217
|
-
},
|
|
218
|
-
onInputKeydown(e) {
|
|
219
|
-
const { ctrlKey, key } = e;
|
|
220
|
-
let keyManaged = true;
|
|
221
|
-
switch (key) {
|
|
222
|
-
case 'ArrowDown': {
|
|
223
|
-
const isOpen = open$();
|
|
224
|
-
if (isOpen) {
|
|
225
|
-
if (ctrlKey) {
|
|
226
|
-
widget.api.highlightLast();
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
widget.api.highlightNext();
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
widget.api.open();
|
|
234
|
-
widget.api.highlightFirst();
|
|
235
|
-
}
|
|
236
|
-
break;
|
|
237
|
-
}
|
|
238
|
-
case 'ArrowUp':
|
|
239
|
-
if (ctrlKey) {
|
|
240
|
-
widget.api.highlightFirst();
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
widget.api.highlightPrevious();
|
|
244
|
-
}
|
|
245
|
-
break;
|
|
246
|
-
case 'Enter': {
|
|
247
|
-
const itemCtx = highlighted$();
|
|
248
|
-
if (itemCtx) {
|
|
249
|
-
widget.api.toggleItem(itemCtx.item);
|
|
250
|
-
}
|
|
251
|
-
break;
|
|
252
|
-
}
|
|
253
|
-
case 'Escape':
|
|
254
|
-
_dirtyOpen$.set(false);
|
|
255
|
-
break;
|
|
256
|
-
default:
|
|
257
|
-
keyManaged = false;
|
|
258
|
-
}
|
|
259
|
-
if (keyManaged) {
|
|
260
|
-
e.preventDefault();
|
|
261
|
-
}
|
|
262
|
-
},
|
|
263
|
-
},
|
|
264
|
-
};
|
|
265
|
-
return widget;
|
|
266
|
-
}
|
|
@@ -1,415 +0,0 @@
|
|
|
1
|
-
import { computed, derived, writable } from '@amadeus-it-group/tansu';
|
|
2
|
-
import { bindableDerived, writablesForProps } from '../../utils/stores';
|
|
3
|
-
import { createStoreDirective, directiveSubscribe, mergeDirectives } from '../../utils/directive';
|
|
4
|
-
import { stateStores } from '../../utils/stores';
|
|
5
|
-
import { typeArray, typeBoolean, typeFunction, typeNumber, typeNumberInRangeFactory } from '../../utils/writables';
|
|
6
|
-
import { noop } from '../../utils/internal/func';
|
|
7
|
-
import { getDecimalPrecision } from '../../utils/internal/math';
|
|
8
|
-
const defaultSliderConfig = {
|
|
9
|
-
min: 0,
|
|
10
|
-
max: 100,
|
|
11
|
-
stepSize: 1,
|
|
12
|
-
readonly: false,
|
|
13
|
-
disabled: false,
|
|
14
|
-
vertical: false,
|
|
15
|
-
className: '',
|
|
16
|
-
ariaLabelHandle: (value, _index) => '' + value,
|
|
17
|
-
onValuesChange: noop,
|
|
18
|
-
values: [0],
|
|
19
|
-
showValueLabels: true,
|
|
20
|
-
showMinMaxLabels: true,
|
|
21
|
-
rtl: false,
|
|
22
|
-
};
|
|
23
|
-
/**
|
|
24
|
-
* Returns a shallow copy of the default slider config.
|
|
25
|
-
* @returns a copy of the default config
|
|
26
|
-
*/
|
|
27
|
-
export function getSliderDefaultConfig() {
|
|
28
|
-
return { ...defaultSliderConfig };
|
|
29
|
-
}
|
|
30
|
-
const configValidator = {
|
|
31
|
-
min: typeNumber,
|
|
32
|
-
max: typeNumber,
|
|
33
|
-
stepSize: typeNumberInRangeFactory(0, +Infinity, { strict: true }),
|
|
34
|
-
readonly: typeBoolean,
|
|
35
|
-
disabled: typeBoolean,
|
|
36
|
-
vertical: typeBoolean,
|
|
37
|
-
ariaLabelHandle: typeFunction,
|
|
38
|
-
onValuesChange: typeFunction,
|
|
39
|
-
values: typeArray,
|
|
40
|
-
showValueLabels: typeBoolean,
|
|
41
|
-
showMinMaxLabels: typeBoolean,
|
|
42
|
-
rtl: typeBoolean,
|
|
43
|
-
};
|
|
44
|
-
/**
|
|
45
|
-
* Computes slider clean value based on the input parameters
|
|
46
|
-
* @param value - dirty value
|
|
47
|
-
* @param min - minimum value
|
|
48
|
-
* @param max - maximum value
|
|
49
|
-
* @param intStepSize - step size converted to integer
|
|
50
|
-
* @param decimalPrecision - maximum decimum precision of slider values
|
|
51
|
-
* @returns adjusted clean value
|
|
52
|
-
*/
|
|
53
|
-
const computeCleanValue = (value, min, max, intStepSize, decimalPrecision) => {
|
|
54
|
-
const magnitude = Math.pow(10, decimalPrecision);
|
|
55
|
-
if (value >= max) {
|
|
56
|
-
return max;
|
|
57
|
-
}
|
|
58
|
-
else if (value <= min) {
|
|
59
|
-
return min;
|
|
60
|
-
}
|
|
61
|
-
const indexMin = Math.floor(((value - min) * magnitude) / intStepSize);
|
|
62
|
-
return +(((((value - min) * magnitude) % intStepSize < intStepSize / 2 ? indexMin : indexMin + 1) * intStepSize) / magnitude + min).toFixed(decimalPrecision);
|
|
63
|
-
};
|
|
64
|
-
/**
|
|
65
|
-
* Method to update the dirtyValues for the slider keyboard navigation
|
|
66
|
-
* @param handleIndex - index of the handle to update
|
|
67
|
-
* @param _dirtyValues$ - writable signal that contains dirtyValues
|
|
68
|
-
* @param values - slider values
|
|
69
|
-
* @param stepSize - slider step size
|
|
70
|
-
* @param updateDirection - if equals 1 - value is increased, if equals -1 values is decreased
|
|
71
|
-
*/
|
|
72
|
-
const updateDirtyValue = (handleIndex, _dirtyValues$, values, stepSize, updateDirection) => {
|
|
73
|
-
_dirtyValues$.update((value) => {
|
|
74
|
-
value = [...value];
|
|
75
|
-
value[handleIndex] = values[handleIndex] + stepSize * updateDirection;
|
|
76
|
-
return value;
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
const getUpdateDirection = (vertical, rtl, keysVertical) => {
|
|
80
|
-
if (vertical && rtl) {
|
|
81
|
-
return keysVertical ? 1 : -1;
|
|
82
|
-
}
|
|
83
|
-
else if (vertical && !rtl) {
|
|
84
|
-
return -1;
|
|
85
|
-
}
|
|
86
|
-
else if (!vertical && rtl) {
|
|
87
|
-
return keysVertical ? -1 : 1;
|
|
88
|
-
}
|
|
89
|
-
else if (!vertical && !rtl) {
|
|
90
|
-
return -1;
|
|
91
|
-
}
|
|
92
|
-
return 1;
|
|
93
|
-
};
|
|
94
|
-
/**
|
|
95
|
-
* Create a slider widget with given config props
|
|
96
|
-
* @param config - an optional slider config
|
|
97
|
-
* @returns a SliderWidget
|
|
98
|
-
*/
|
|
99
|
-
export function createSlider(config) {
|
|
100
|
-
const [{
|
|
101
|
-
// dirty inputs that need adjustment:
|
|
102
|
-
min$: _dirtyMinimum$, max$: _dirtyMaximum$, stepSize$, rtl$, values$: _dirtyValues$, ariaLabelHandle$, onValuesChange$, showValueLabels$, showMinMaxLabels$, ...stateProps }, patch,] = writablesForProps(defaultSliderConfig, config, configValidator);
|
|
103
|
-
const { vertical$, disabled$, readonly$ } = stateProps;
|
|
104
|
-
let _prevCoordinate = -1;
|
|
105
|
-
// clean inputs adjustment
|
|
106
|
-
const min$ = computed(() => {
|
|
107
|
-
const _dirtyMinimum = _dirtyMinimum$(), _dirtyMaximum = _dirtyMaximum$();
|
|
108
|
-
if (_dirtyMinimum === _dirtyMaximum) {
|
|
109
|
-
return defaultSliderConfig.min;
|
|
110
|
-
}
|
|
111
|
-
return Math.min(_dirtyMinimum, _dirtyMaximum);
|
|
112
|
-
});
|
|
113
|
-
const max$ = computed(() => {
|
|
114
|
-
const _dirtyMinimum = _dirtyMinimum$(), _dirtyMaximum = _dirtyMaximum$();
|
|
115
|
-
if (_dirtyMinimum === _dirtyMaximum) {
|
|
116
|
-
return defaultSliderConfig.max;
|
|
117
|
-
}
|
|
118
|
-
return Math.max(_dirtyMinimum, _dirtyMaximum);
|
|
119
|
-
});
|
|
120
|
-
const _decimalPrecision$ = computed(() => Math.max(getDecimalPrecision(stepSize$()), getDecimalPrecision(min$()), getDecimalPrecision(max$())));
|
|
121
|
-
const _intStepSize$ = computed(() => stepSize$() * Math.pow(10, _decimalPrecision$()));
|
|
122
|
-
const values$ = bindableDerived(onValuesChange$, [_dirtyValues$, min$, max$, _intStepSize$, _decimalPrecision$], ([dirtyValues, min, max, intStepSize, decimalPrecision]) => dirtyValues.map((dv) => computeCleanValue(dv, min, max, intStepSize, decimalPrecision)), typeArray.equal);
|
|
123
|
-
// computed
|
|
124
|
-
const { directive: sliderDirective, element$: sliderDom$ } = createStoreDirective();
|
|
125
|
-
const { directive: minLabelDirective, element$: minLabelDom$ } = createStoreDirective();
|
|
126
|
-
const { directive: maxLabelDirective, element$: maxLabelDom$ } = createStoreDirective();
|
|
127
|
-
const sliderResized$ = derived(sliderDom$, (sliderDom, set) => {
|
|
128
|
-
if (!sliderDom) {
|
|
129
|
-
set({});
|
|
130
|
-
return;
|
|
131
|
-
}
|
|
132
|
-
const resizeObserver = new ResizeObserver(() => {
|
|
133
|
-
set({});
|
|
134
|
-
});
|
|
135
|
-
resizeObserver.observe(sliderDom);
|
|
136
|
-
return () => resizeObserver.disconnect();
|
|
137
|
-
}, {});
|
|
138
|
-
const updateSliderSize$ = writable({});
|
|
139
|
-
const sliderDomRect$ = computed(() => {
|
|
140
|
-
sliderResized$();
|
|
141
|
-
updateSliderSize$();
|
|
142
|
-
return sliderDom$()?.getBoundingClientRect() ?? {};
|
|
143
|
-
}, {
|
|
144
|
-
equal: Object.is,
|
|
145
|
-
});
|
|
146
|
-
const minLabelDomRect$ = computed(() => {
|
|
147
|
-
sliderResized$();
|
|
148
|
-
updateSliderSize$();
|
|
149
|
-
return minLabelDom$()?.getBoundingClientRect() ?? {};
|
|
150
|
-
}, {
|
|
151
|
-
equal: (a, b) => Object.is(a, b),
|
|
152
|
-
});
|
|
153
|
-
const maxLabelDomRect$ = computed(() => {
|
|
154
|
-
sliderResized$();
|
|
155
|
-
updateSliderSize$();
|
|
156
|
-
return maxLabelDom$()?.getBoundingClientRect() ?? {};
|
|
157
|
-
}, {
|
|
158
|
-
equal: (a, b) => Object.is(a, b),
|
|
159
|
-
});
|
|
160
|
-
const sliderDomRectOffset$ = computed(() => (vertical$() ? sliderDomRect$().top : sliderDomRect$().left));
|
|
161
|
-
const sliderDomRectSize$ = computed(() => (vertical$() ? sliderDomRect$().height : sliderDomRect$().width));
|
|
162
|
-
const sortedValues$ = computed(() => [...values$()].sort((a, b) => a - b));
|
|
163
|
-
const _sortedHandlesValues$ = computed(() => {
|
|
164
|
-
return values$()
|
|
165
|
-
.map((val, index) => {
|
|
166
|
-
return { id: index, value: val };
|
|
167
|
-
})
|
|
168
|
-
.sort((a, b) => a.value - b.value);
|
|
169
|
-
});
|
|
170
|
-
const sortedHandles$ = computed(() => {
|
|
171
|
-
const ariaLabelHandle = ariaLabelHandle$();
|
|
172
|
-
return _sortedHandlesValues$().map((sortedValue, index) => {
|
|
173
|
-
return { ...sortedValue, ariaLabel: ariaLabelHandle(sortedValue.value, index, sortedValue.id) };
|
|
174
|
-
});
|
|
175
|
-
});
|
|
176
|
-
const valuesPercent$ = computed(() => values$().map((val) => percentCompute(val)));
|
|
177
|
-
const sortedValuesPercent$ = computed(() => [...valuesPercent$()].sort((a, b) => a - b));
|
|
178
|
-
const minLabelWidth$ = computed(() => (minLabelDomRect$().width / sliderDomRectSize$()) * 100);
|
|
179
|
-
const maxLabelWidth$ = computed(() => (maxLabelDomRect$().width / sliderDomRectSize$()) * 100);
|
|
180
|
-
const minValueLabelDisplay$ = computed(() => {
|
|
181
|
-
if (!showMinMaxLabels$()) {
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
else if (!showValueLabels$()) {
|
|
185
|
-
return true;
|
|
186
|
-
}
|
|
187
|
-
const minLabelWidth = minLabelWidth$();
|
|
188
|
-
return rtl$()
|
|
189
|
-
? !valuesPercent$().some((percent) => 100 - percent > 100 - minLabelWidth - 1)
|
|
190
|
-
: !valuesPercent$().some((percent) => percent < minLabelWidth + 1);
|
|
191
|
-
});
|
|
192
|
-
const maxValueLabelDisplay$ = computed(() => {
|
|
193
|
-
if (!showMinMaxLabels$()) {
|
|
194
|
-
return false;
|
|
195
|
-
}
|
|
196
|
-
else if (!showValueLabels$()) {
|
|
197
|
-
return true;
|
|
198
|
-
}
|
|
199
|
-
const maxLabelWidth = maxLabelWidth$();
|
|
200
|
-
return rtl$()
|
|
201
|
-
? !valuesPercent$().some((percent) => 100 - percent < maxLabelWidth + 1)
|
|
202
|
-
: !valuesPercent$().some((percent) => percent > 100 - maxLabelWidth - 1);
|
|
203
|
-
});
|
|
204
|
-
// TODO define the intersection value
|
|
205
|
-
const combinedLabelDisplay$ = computed(() => {
|
|
206
|
-
const values = values$();
|
|
207
|
-
return values.length == 2 && Math.abs(values[0] - values[1]) < 10;
|
|
208
|
-
});
|
|
209
|
-
const isInteractable$ = computed(() => !disabled$() && !readonly$());
|
|
210
|
-
const combinedLabelPositionLeft$ = computed(() => {
|
|
211
|
-
const sortedValuesPercent = sortedValuesPercent$();
|
|
212
|
-
const combinedPosition = (sortedValuesPercent[0] + sortedValuesPercent[1]) / 2;
|
|
213
|
-
return vertical$() || sortedValuesPercent.length != 2 ? 0 : rtl$() ? 100 - combinedPosition : combinedPosition;
|
|
214
|
-
});
|
|
215
|
-
const combinedLabelPositionTop$ = computed(() => {
|
|
216
|
-
const sortedValuesPercent = sortedValuesPercent$();
|
|
217
|
-
const combinedPosition = 100 - (sortedValuesPercent[0] + sortedValuesPercent[1]) / 2;
|
|
218
|
-
return vertical$() && sortedValuesPercent.length == 2 ? (rtl$() ? 100 - combinedPosition : combinedPosition) : 0;
|
|
219
|
-
});
|
|
220
|
-
const handleDisplayOptions$ = computed(() => {
|
|
221
|
-
const vertical = vertical$(), rtl = rtl$();
|
|
222
|
-
return valuesPercent$().map((vp, index) => {
|
|
223
|
-
return {
|
|
224
|
-
left: rtl ? (vertical ? null : 100 - vp) : vertical ? null : vp,
|
|
225
|
-
top: rtl ? (vertical ? vp : null) : vertical ? 100 - vp : null,
|
|
226
|
-
};
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
const progressDisplayOptions$ = computed(() => {
|
|
230
|
-
const vertical = vertical$(), sortedValuesPercent = sortedValuesPercent$(), rtl = rtl$();
|
|
231
|
-
if (sortedValuesPercent.length === 1) {
|
|
232
|
-
return [
|
|
233
|
-
{
|
|
234
|
-
left: vertical ? null : rtl ? null : 0,
|
|
235
|
-
right: vertical ? null : rtl ? 0 : null,
|
|
236
|
-
bottom: vertical ? (rtl ? null : 0) : null,
|
|
237
|
-
top: vertical ? (rtl ? 0 : null) : null,
|
|
238
|
-
width: vertical ? 100 : sortedValuesPercent[0],
|
|
239
|
-
height: vertical ? sortedValuesPercent[0] : 100,
|
|
240
|
-
},
|
|
241
|
-
];
|
|
242
|
-
}
|
|
243
|
-
else {
|
|
244
|
-
return sortedValuesPercent
|
|
245
|
-
.map((svp, index, array) => {
|
|
246
|
-
return {
|
|
247
|
-
left: vertical ? null : rtl ? null : svp,
|
|
248
|
-
right: vertical ? null : rtl ? array[index] : null,
|
|
249
|
-
bottom: vertical ? (rtl ? null : svp) : null,
|
|
250
|
-
top: vertical ? (rtl ? array[index] : null) : null,
|
|
251
|
-
width: vertical ? 100 : index === array.length - 1 ? svp : array[index + 1] - svp,
|
|
252
|
-
height: vertical ? (index === array.length - 1 ? svp : array[index + 1] - svp) : 100,
|
|
253
|
-
};
|
|
254
|
-
})
|
|
255
|
-
.slice(0, sortedValuesPercent.length - 1);
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
// functions
|
|
259
|
-
const percentCompute = (value) => {
|
|
260
|
-
const min = min$();
|
|
261
|
-
return ((value - min) * 100) / (max$() - min);
|
|
262
|
-
};
|
|
263
|
-
const getClosestSliderHandle = (clickedPercent) => {
|
|
264
|
-
const values = values$();
|
|
265
|
-
if (values.length === 1) {
|
|
266
|
-
return 0;
|
|
267
|
-
}
|
|
268
|
-
const sortedValues = sortedValues$();
|
|
269
|
-
const closestBigger = sortedValues.find((sv) => sv > clickedPercent * 100);
|
|
270
|
-
const closestBiggerIndex = closestBigger ? sortedValues.indexOf(closestBigger) : sortedValues.length - 1;
|
|
271
|
-
const midPoint = sortedValues[closestBiggerIndex - 1] + (sortedValues[closestBiggerIndex] - sortedValues[closestBiggerIndex - 1]) / 2;
|
|
272
|
-
const closestValue = sortedValues[clickedPercent * 100 <= midPoint ? closestBiggerIndex - 1 : closestBiggerIndex];
|
|
273
|
-
return values.indexOf(closestValue);
|
|
274
|
-
};
|
|
275
|
-
const adjustCoordinate = (clickedCoordinate, handleNumber) => {
|
|
276
|
-
if (isInteractable$()) {
|
|
277
|
-
const sliderDomRectSize = sliderDomRectSize$(), sliderDomRectOffset = sliderDomRectOffset$();
|
|
278
|
-
let clickedPercent = vertical$()
|
|
279
|
-
? (sliderDomRectSize - clickedCoordinate + sliderDomRectOffset) / sliderDomRectSize
|
|
280
|
-
: (clickedCoordinate - sliderDomRectOffset) / sliderDomRectSize;
|
|
281
|
-
clickedPercent = rtl$() ? 1 - clickedPercent : clickedPercent;
|
|
282
|
-
const derivedHandleIndex = handleNumber ?? getClosestSliderHandle(clickedPercent);
|
|
283
|
-
const newValue = clickedPercent * (max$() - min$()) + min$();
|
|
284
|
-
_dirtyValues$.update((dh) => {
|
|
285
|
-
dh = [...dh];
|
|
286
|
-
dh[derivedHandleIndex] = newValue;
|
|
287
|
-
return dh;
|
|
288
|
-
});
|
|
289
|
-
}
|
|
290
|
-
};
|
|
291
|
-
return {
|
|
292
|
-
...stateStores({
|
|
293
|
-
min$,
|
|
294
|
-
max$,
|
|
295
|
-
stepSize$,
|
|
296
|
-
values$,
|
|
297
|
-
sortedValues$,
|
|
298
|
-
sortedHandles$,
|
|
299
|
-
minValueLabelDisplay$,
|
|
300
|
-
maxValueLabelDisplay$,
|
|
301
|
-
combinedLabelDisplay$,
|
|
302
|
-
isInteractable$,
|
|
303
|
-
combinedLabelPositionLeft$,
|
|
304
|
-
combinedLabelPositionTop$,
|
|
305
|
-
progressDisplayOptions$,
|
|
306
|
-
handleDisplayOptions$,
|
|
307
|
-
showValueLabels$,
|
|
308
|
-
showMinMaxLabels$,
|
|
309
|
-
rtl$,
|
|
310
|
-
...stateProps,
|
|
311
|
-
}),
|
|
312
|
-
patch,
|
|
313
|
-
api: {},
|
|
314
|
-
directives: {
|
|
315
|
-
sliderDirective: mergeDirectives(sliderDirective, directiveSubscribe(sliderResized$)),
|
|
316
|
-
minLabelDirective,
|
|
317
|
-
maxLabelDirective,
|
|
318
|
-
},
|
|
319
|
-
actions: {
|
|
320
|
-
click(event) {
|
|
321
|
-
adjustCoordinate(vertical$() ? event.clientY : event.clientX);
|
|
322
|
-
},
|
|
323
|
-
keydown(event, handleIndex) {
|
|
324
|
-
const { key } = event;
|
|
325
|
-
const rtl = rtl$(), values = values$(), stepSize = stepSize$(), min = min$(), max = max$(), vertical = vertical$();
|
|
326
|
-
if (isInteractable$()) {
|
|
327
|
-
switch (key) {
|
|
328
|
-
case 'ArrowDown':
|
|
329
|
-
updateDirtyValue(handleIndex, _dirtyValues$, values, stepSize, getUpdateDirection(vertical, rtl, true));
|
|
330
|
-
break;
|
|
331
|
-
case 'ArrowLeft':
|
|
332
|
-
updateDirtyValue(handleIndex, _dirtyValues$, values, stepSize, getUpdateDirection(vertical, rtl, false));
|
|
333
|
-
break;
|
|
334
|
-
case 'ArrowUp':
|
|
335
|
-
updateDirtyValue(handleIndex, _dirtyValues$, values, stepSize, -1 * getUpdateDirection(vertical, rtl, true));
|
|
336
|
-
break;
|
|
337
|
-
case 'ArrowRight':
|
|
338
|
-
updateDirtyValue(handleIndex, _dirtyValues$, values, stepSize, -1 * getUpdateDirection(vertical, rtl, false));
|
|
339
|
-
break;
|
|
340
|
-
case 'Home':
|
|
341
|
-
_dirtyValues$.update((value) => {
|
|
342
|
-
value = [...value];
|
|
343
|
-
value[handleIndex] = min;
|
|
344
|
-
return value;
|
|
345
|
-
});
|
|
346
|
-
break;
|
|
347
|
-
case 'End':
|
|
348
|
-
_dirtyValues$.update((value) => {
|
|
349
|
-
value = [...value];
|
|
350
|
-
value[handleIndex] = max;
|
|
351
|
-
return value;
|
|
352
|
-
});
|
|
353
|
-
break;
|
|
354
|
-
case 'PageUp':
|
|
355
|
-
// TODO it is optional in accessibility guidelines, so define the skip value for steps and write unit test
|
|
356
|
-
break;
|
|
357
|
-
case 'PageDown':
|
|
358
|
-
// TODO it is optional in accessibility guidelines, so define the skip value for steps and write unit test
|
|
359
|
-
break;
|
|
360
|
-
default:
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
event.preventDefault();
|
|
364
|
-
event.stopPropagation();
|
|
365
|
-
}
|
|
366
|
-
},
|
|
367
|
-
mouseDown(event, handleId) {
|
|
368
|
-
event.preventDefault();
|
|
369
|
-
const handleDrag = (e) => {
|
|
370
|
-
e.preventDefault();
|
|
371
|
-
const newCoord = vertical$() ? e.clientY : e.clientX;
|
|
372
|
-
event.target.focus();
|
|
373
|
-
if (_prevCoordinate !== newCoord) {
|
|
374
|
-
_prevCoordinate = newCoord;
|
|
375
|
-
adjustCoordinate(newCoord, handleId);
|
|
376
|
-
}
|
|
377
|
-
};
|
|
378
|
-
if (isInteractable$()) {
|
|
379
|
-
updateSliderSize$.set({});
|
|
380
|
-
event.target.focus();
|
|
381
|
-
document.addEventListener('mousemove', handleDrag);
|
|
382
|
-
// TODO mouse up doesn't work outside the handle area
|
|
383
|
-
document.addEventListener('mouseup', () => {
|
|
384
|
-
document.removeEventListener('mousemove', handleDrag);
|
|
385
|
-
}, { once: true });
|
|
386
|
-
}
|
|
387
|
-
},
|
|
388
|
-
touchStart(event, handleId) {
|
|
389
|
-
event.preventDefault();
|
|
390
|
-
const handleDrag = (e) => {
|
|
391
|
-
e.preventDefault();
|
|
392
|
-
const newCoord = vertical$() ? e.touches[0].clientY : e.touches[0].clientX;
|
|
393
|
-
event.target.focus();
|
|
394
|
-
if (_prevCoordinate !== newCoord) {
|
|
395
|
-
_prevCoordinate = newCoord;
|
|
396
|
-
adjustCoordinate(newCoord, handleId);
|
|
397
|
-
}
|
|
398
|
-
};
|
|
399
|
-
if (isInteractable$()) {
|
|
400
|
-
updateSliderSize$.set({});
|
|
401
|
-
event.target.focus();
|
|
402
|
-
document.addEventListener('touchmove', handleDrag);
|
|
403
|
-
document.addEventListener('touchend', () => {
|
|
404
|
-
document.removeEventListener('touchmove', handleDrag);
|
|
405
|
-
document.removeEventListener('touchcancel', handleDrag);
|
|
406
|
-
}, { once: true });
|
|
407
|
-
document.addEventListener('touchcancel', () => {
|
|
408
|
-
document.removeEventListener('touchmove', handleDrag);
|
|
409
|
-
document.removeEventListener('touchend', handleDrag);
|
|
410
|
-
}, { once: true });
|
|
411
|
-
}
|
|
412
|
-
},
|
|
413
|
-
},
|
|
414
|
-
};
|
|
415
|
-
}
|