@kws3/ui 1.7.3 → 1.8.1
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/CHANGELOG.mdx +15 -0
- package/buttons/ConfirmButton.svelte +0 -2
- package/charts/AreaChart.svelte +59 -2
- package/charts/BarChart.svelte +66 -3
- package/charts/Chart.svelte +57 -13
- package/charts/DonutChart.svelte +60 -2
- package/charts/LineChart.svelte +59 -2
- package/charts/MixedChart.svelte +59 -2
- package/charts/PieChart.svelte +59 -2
- package/charts/RadialChart.svelte +59 -2
- package/charts/utils.js +5 -0
- package/controls/NumberInput.svelte +0 -2
- package/forms/select/MultiSelect.svelte +201 -80
- package/forms/select/SearchableSelect.svelte +29 -0
- package/helpers/ActionSheet.svelte +3 -1
- package/helpers/CardModal.svelte +11 -1
- package/helpers/Dialog/index.js +2 -0
- package/helpers/Modal.svelte +12 -3
- package/helpers/ScrollableList.svelte +231 -0
- package/index.js +1 -0
- package/package.json +4 -3
- package/sliding-panes/SlidingPane.svelte +13 -20
- package/styles/ActionSheet.scss +10 -0
- package/utils/resizeObserver.js +24 -0
|
@@ -16,9 +16,16 @@ this property of each object will be returned as the value, Default: `"id"`
|
|
|
16
16
|
@param {''|'primary'|'success'|'warning'|'info'|'danger'|'dark'|'light'} [color=""] - Color of the input, Default: `""`
|
|
17
17
|
@param {string} [style=""] - Inline CSS for input container, Default: `""`
|
|
18
18
|
@param {boolean} [readonly=false] - Marks component as read-only, Default: `false`
|
|
19
|
+
@param {function|null} [search=null] - Async function to fetch options
|
|
20
|
+
|
|
21
|
+
Only send this prop if you want to fetch `options` asynchronously.
|
|
22
|
+
`options` prop will be ignored if this prop is set., Default: `null`
|
|
23
|
+
@param {'fuzzy'|'strict'} [search_strategy="fuzzy"] - Filtered options to be displayed strictly based on search text or perform a fuzzy match.
|
|
24
|
+
Fuzzy match will not work if `search` function is set, as the backend service is meant to do the matching., Default: `"fuzzy"`
|
|
19
25
|
@param {boolean} [disabled=false] - Disables the component, Default: `false`
|
|
20
26
|
@param {string} [selected_icon="check"] - Icon used to mark selected items in dropdown list, Default: `"check"`
|
|
21
27
|
@param {string} [no_options_msg="No matching options"] - Message to display when no matching options are found, Default: `"No matching options"`
|
|
28
|
+
@param {string} [async_search_prompt="Start typing to search..."] - Message to display in dropdown when async search can be performed, Default: `"Start typing to search..."`
|
|
22
29
|
@param {string} [remove_all_tip="Clear Selection"] - Tooltip text for the Clear selection button, Default: `"Clear Selection"`
|
|
23
30
|
@param {HTMLElement|string} [dropdown_portal=undefined] - Where to render the dropdown list.
|
|
24
31
|
Can be a DOM element or a `string` with the CSS selector of the element.
|
|
@@ -44,13 +51,16 @@ Default value: `<span>{option[search_key] || option}</span>`
|
|
|
44
51
|
{options}
|
|
45
52
|
{search_key}
|
|
46
53
|
{value_key}
|
|
54
|
+
{search_strategy}
|
|
47
55
|
{size}
|
|
48
56
|
{color}
|
|
49
57
|
{style}
|
|
50
58
|
{readonly}
|
|
51
59
|
{disabled}
|
|
60
|
+
{search}
|
|
52
61
|
{selected_icon}
|
|
53
62
|
{remove_all_tip}
|
|
63
|
+
async_search_prompt={value ? "Backspace to clear" : async_search_prompt}
|
|
54
64
|
{no_options_msg}
|
|
55
65
|
{dropdown_portal}
|
|
56
66
|
on:change={change}
|
|
@@ -118,6 +128,21 @@ Default value: `<span>{option[search_key] || option}</span>`
|
|
|
118
128
|
* Marks component as read-only
|
|
119
129
|
*/
|
|
120
130
|
export let readonly = false;
|
|
131
|
+
/**
|
|
132
|
+
* Async function to fetch options
|
|
133
|
+
*
|
|
134
|
+
* Only send this prop if you want to fetch `options` asynchronously.
|
|
135
|
+
* `options` prop will be ignored if this prop is set.
|
|
136
|
+
*
|
|
137
|
+
* @type {function|null}
|
|
138
|
+
*/
|
|
139
|
+
export let search = null;
|
|
140
|
+
/**
|
|
141
|
+
* Filtered options to be displayed strictly based on search text or perform a fuzzy match.
|
|
142
|
+
* Fuzzy match will not work if `search` function is set, as the backend service is meant to do the matching.
|
|
143
|
+
* @type {'fuzzy'|'strict'}
|
|
144
|
+
*/
|
|
145
|
+
export let search_strategy = "fuzzy";
|
|
121
146
|
/**
|
|
122
147
|
* Disables the component
|
|
123
148
|
*/
|
|
@@ -130,6 +155,10 @@ Default value: `<span>{option[search_key] || option}</span>`
|
|
|
130
155
|
* Message to display when no matching options are found
|
|
131
156
|
*/
|
|
132
157
|
export let no_options_msg = "No matching options";
|
|
158
|
+
/**
|
|
159
|
+
* Message to display in dropdown when async search can be performed
|
|
160
|
+
*/
|
|
161
|
+
export let async_search_prompt = "Start typing to search...";
|
|
133
162
|
/**
|
|
134
163
|
* Tooltip text for the Clear selection button
|
|
135
164
|
*/
|
|
@@ -19,7 +19,9 @@ If `false` , the component won't have a close button, and will not close on clic
|
|
|
19
19
|
|
|
20
20
|
-->
|
|
21
21
|
|
|
22
|
-
<div
|
|
22
|
+
<div
|
|
23
|
+
class="modal kws-action-sheet-outer {klass} {is_active ? 'is-active' : ''}"
|
|
24
|
+
{style}>
|
|
23
25
|
{#if is_active}<div
|
|
24
26
|
transition:fade={{ duration: transitionDuration }}
|
|
25
27
|
class="modal-background"
|
package/helpers/CardModal.svelte
CHANGED
|
@@ -34,7 +34,6 @@ Only visible when the
|
|
|
34
34
|
transition:fade={{ duration: transitionDuration }}
|
|
35
35
|
class="modal-background"
|
|
36
36
|
on:click={clickOutside} />
|
|
37
|
-
|
|
38
37
|
<div
|
|
39
38
|
transition:scale={{
|
|
40
39
|
duration: transitionDuration,
|
|
@@ -83,6 +82,17 @@ Only visible when the
|
|
|
83
82
|
</div>
|
|
84
83
|
|
|
85
84
|
<style lang="scss">
|
|
85
|
+
.modal {
|
|
86
|
+
display: flex;
|
|
87
|
+
visibility: hidden;
|
|
88
|
+
&.is-active {
|
|
89
|
+
visibility: visible;
|
|
90
|
+
}
|
|
91
|
+
.modal-card,
|
|
92
|
+
.modal-background {
|
|
93
|
+
transition: all 0.3s;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
86
96
|
@media screen and (min-width: 769px), print {
|
|
87
97
|
.modal-card {
|
|
88
98
|
min-width: 640px;
|
package/helpers/Dialog/index.js
CHANGED
package/helpers/Modal.svelte
CHANGED
|
@@ -26,7 +26,6 @@ Only programmatic closing is possible, Default: `true`
|
|
|
26
26
|
transition:fade={{ duration: transitionDuration }}
|
|
27
27
|
class="modal-background"
|
|
28
28
|
on:click={clickOutside} />
|
|
29
|
-
|
|
30
29
|
<div
|
|
31
30
|
transition:scale={{
|
|
32
31
|
duration: transitionDuration,
|
|
@@ -47,9 +46,19 @@ Only programmatic closing is possible, Default: `true`
|
|
|
47
46
|
</div>
|
|
48
47
|
|
|
49
48
|
<style lang="scss">
|
|
50
|
-
|
|
49
|
+
.modal {
|
|
50
|
+
display: flex;
|
|
51
|
+
visibility: hidden;
|
|
52
|
+
&.is-active {
|
|
53
|
+
visibility: visible;
|
|
54
|
+
}
|
|
51
55
|
.modal-content,
|
|
52
|
-
.modal-
|
|
56
|
+
.modal-background {
|
|
57
|
+
transition: all 0.3s;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
@media screen and (min-width: 769px), print {
|
|
61
|
+
.modal-content {
|
|
53
62
|
min-width: 640px;
|
|
54
63
|
&.is-medium {
|
|
55
64
|
width: 70%;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
@component
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@param {array} [items=[]] - Array of items, Default: `[]`
|
|
6
|
+
@param {string} [height="100%"] - Height of the wrapper, CSS String, Default: `"100%"`
|
|
7
|
+
@param {number | null} [item_height=null] - Height of each list item. If not set, height will be calculated automatically based on each item's offsetHeight, Default: `null`
|
|
8
|
+
@param {number} [start=0] - First item index rendered inside viewport - readonly, Default: `0`
|
|
9
|
+
@param {number} [end=0] - Last item index rendered inside viewport - readonly, Default: `0`
|
|
10
|
+
@param {number} [end_threshold=10] - `end` event will be fired when the list reaches this many items before the end of the list., Default: `10`
|
|
11
|
+
@param {string} [style=""] - Inline CSS for scroller container, Default: `""`
|
|
12
|
+
@param {string} [class=""] - CSS classes for scroller container, Default: `""`
|
|
13
|
+
|
|
14
|
+
### Events
|
|
15
|
+
- `end` - Fired when the list reaches `end_threshold` items before the end of the list.
|
|
16
|
+
|
|
17
|
+
### Slots
|
|
18
|
+
- `<slot name="default" {item} {index} />` - Default slot for list view items
|
|
19
|
+
- `<slot name="loader" />` - Optional slot to display a loading graphic at the bottom of the list
|
|
20
|
+
while more items are loading
|
|
21
|
+
|
|
22
|
+
-->
|
|
23
|
+
{#if hasResizeObserver}
|
|
24
|
+
<div
|
|
25
|
+
bind:this={viewport}
|
|
26
|
+
class="kws-scrollable-list with-resize-observer {klass}"
|
|
27
|
+
on:scroll={handle_scroll}
|
|
28
|
+
style="height:{height};{style}"
|
|
29
|
+
use:resizeObserver
|
|
30
|
+
on:resize={resize}>
|
|
31
|
+
<div
|
|
32
|
+
bind:this={contents}
|
|
33
|
+
style="padding-top: {top}px; padding-bottom: {bottom}px;">
|
|
34
|
+
{#each visible as item (item.index)}
|
|
35
|
+
<div class="row">
|
|
36
|
+
<!--Default slot for list view items-->
|
|
37
|
+
<slot item={item.data} index={item.index} />
|
|
38
|
+
</div>
|
|
39
|
+
{/each}
|
|
40
|
+
<!--Optional slot to display a loading graphic at the bottom of the list
|
|
41
|
+
while more items are loading-->
|
|
42
|
+
<slot name="loader" />
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
{:else}
|
|
46
|
+
<div
|
|
47
|
+
bind:this={viewport}
|
|
48
|
+
class="kws-scrollable-list {klass}"
|
|
49
|
+
on:scroll={handle_scroll}
|
|
50
|
+
style="height:{height};{style}"
|
|
51
|
+
bind:offsetHeight={viewport_height}>
|
|
52
|
+
<div
|
|
53
|
+
bind:this={contents}
|
|
54
|
+
style="padding-top: {top}px; padding-bottom: {bottom}px;">
|
|
55
|
+
{#each visible as item (item.index)}
|
|
56
|
+
<div class="row">
|
|
57
|
+
<!--Default slot for list view items-->
|
|
58
|
+
<slot item={item.data} index={item.index} />
|
|
59
|
+
</div>
|
|
60
|
+
{/each}
|
|
61
|
+
<!--Optional slot to display a loading graphic at the bottom of the list
|
|
62
|
+
while more items are loading-->
|
|
63
|
+
<slot name="loader" />
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
{/if}
|
|
67
|
+
|
|
68
|
+
<style>
|
|
69
|
+
.kws-scrollable-list {
|
|
70
|
+
overflow: auto;
|
|
71
|
+
-webkit-overflow-scrolling: touch;
|
|
72
|
+
position: relative;
|
|
73
|
+
height: 100%;
|
|
74
|
+
}
|
|
75
|
+
</style>
|
|
76
|
+
|
|
77
|
+
<script>
|
|
78
|
+
import { onMount, tick } from "svelte";
|
|
79
|
+
import { createEventDispatcher } from "svelte";
|
|
80
|
+
import {
|
|
81
|
+
resizeObserver,
|
|
82
|
+
hasResizeObserver,
|
|
83
|
+
} from "@kws3/ui/utils/resizeObserver";
|
|
84
|
+
|
|
85
|
+
const fire = createEventDispatcher();
|
|
86
|
+
/**
|
|
87
|
+
* Array of items
|
|
88
|
+
*/
|
|
89
|
+
export let items = [],
|
|
90
|
+
/**
|
|
91
|
+
* Height of the wrapper, CSS String
|
|
92
|
+
*/
|
|
93
|
+
height = "100%",
|
|
94
|
+
/**
|
|
95
|
+
* Height of each list item. If not set, height will be calculated automatically based on each item's offsetHeight
|
|
96
|
+
* @type {number | null}
|
|
97
|
+
*/
|
|
98
|
+
item_height = null,
|
|
99
|
+
/**
|
|
100
|
+
* First item index rendered inside viewport - readonly
|
|
101
|
+
*/
|
|
102
|
+
start = 0,
|
|
103
|
+
/**
|
|
104
|
+
* Last item index rendered inside viewport - readonly
|
|
105
|
+
*/
|
|
106
|
+
end = 0,
|
|
107
|
+
/**
|
|
108
|
+
* `end` event will be fired when the list reaches this many items before the end of the list.
|
|
109
|
+
*/
|
|
110
|
+
end_threshold = 10,
|
|
111
|
+
/**
|
|
112
|
+
* Inline CSS for scroller container
|
|
113
|
+
*/
|
|
114
|
+
style = "";
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* CSS classes for scroller container
|
|
118
|
+
*/
|
|
119
|
+
let klass = "";
|
|
120
|
+
export { klass as class };
|
|
121
|
+
|
|
122
|
+
// local state
|
|
123
|
+
let height_map = [],
|
|
124
|
+
rows,
|
|
125
|
+
viewport,
|
|
126
|
+
contents,
|
|
127
|
+
viewport_height = 0,
|
|
128
|
+
visible,
|
|
129
|
+
mounted,
|
|
130
|
+
top = 0,
|
|
131
|
+
bottom = 0,
|
|
132
|
+
average_height,
|
|
133
|
+
items_count = 0;
|
|
134
|
+
|
|
135
|
+
$: visible = items.slice(start, end).map((data, i) => {
|
|
136
|
+
return { index: i + start, data };
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// whenever `items` changes, invalidate the current heightmap
|
|
140
|
+
$: items, viewport_height, item_height, mounted, refresh();
|
|
141
|
+
|
|
142
|
+
async function refresh() {
|
|
143
|
+
if (!mounted) return;
|
|
144
|
+
const scrollTop = viewport.scrollTop;
|
|
145
|
+
await tick(); // wait until the DOM is up to date
|
|
146
|
+
let content_height = top - scrollTop;
|
|
147
|
+
let i = start;
|
|
148
|
+
while (content_height < viewport_height && i < items.length) {
|
|
149
|
+
let row = rows[i - start];
|
|
150
|
+
if (!row) {
|
|
151
|
+
end = i + 1;
|
|
152
|
+
await tick(); // render the newly visible row
|
|
153
|
+
row = rows[i - start];
|
|
154
|
+
}
|
|
155
|
+
const row_height = (height_map[i] =
|
|
156
|
+
item_height || (row ? row.offsetHeight : 0));
|
|
157
|
+
content_height += row_height;
|
|
158
|
+
i += 1;
|
|
159
|
+
}
|
|
160
|
+
end = i;
|
|
161
|
+
const remaining = items.length - end;
|
|
162
|
+
average_height = (top + content_height) / end;
|
|
163
|
+
bottom = remaining * average_height;
|
|
164
|
+
height_map.length = items.length;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
async function handle_scroll() {
|
|
168
|
+
const scrollTop = viewport.scrollTop;
|
|
169
|
+
const old_start = start;
|
|
170
|
+
for (let v = 0; v < rows.length; v += 1) {
|
|
171
|
+
height_map[start + v] = item_height || rows[v].offsetHeight;
|
|
172
|
+
}
|
|
173
|
+
let i = 0;
|
|
174
|
+
let y = 0;
|
|
175
|
+
while (i < items.length) {
|
|
176
|
+
const row_height = height_map[i] || average_height;
|
|
177
|
+
if (y + row_height > scrollTop) {
|
|
178
|
+
start = i;
|
|
179
|
+
top = y;
|
|
180
|
+
break;
|
|
181
|
+
}
|
|
182
|
+
y += row_height;
|
|
183
|
+
i += 1;
|
|
184
|
+
}
|
|
185
|
+
while (i < items.length) {
|
|
186
|
+
y += height_map[i] || average_height;
|
|
187
|
+
i += 1;
|
|
188
|
+
if (y > scrollTop + viewport_height) break;
|
|
189
|
+
}
|
|
190
|
+
end = i;
|
|
191
|
+
const remaining = items.length - end;
|
|
192
|
+
average_height = y / end;
|
|
193
|
+
while (i < items.length) height_map[i++] = average_height;
|
|
194
|
+
bottom = remaining * average_height;
|
|
195
|
+
// prevent jumping if we scrolled up into unknown territory
|
|
196
|
+
if (start < old_start) {
|
|
197
|
+
await tick();
|
|
198
|
+
let expected_height = 0;
|
|
199
|
+
let actual_height = 0;
|
|
200
|
+
for (let i = start; i < old_start; i += 1) {
|
|
201
|
+
if (rows[i - start]) {
|
|
202
|
+
expected_height += height_map[i];
|
|
203
|
+
actual_height += item_height || rows[i - start].offsetHeight;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
const d = actual_height - expected_height;
|
|
207
|
+
viewport.scrollTo(0, scrollTop + d);
|
|
208
|
+
}
|
|
209
|
+
// fire on:end event if we scrolled past the end of the list
|
|
210
|
+
if (end > items.length - end_threshold) {
|
|
211
|
+
if (items_count !== items.length) {
|
|
212
|
+
items_count = items.length;
|
|
213
|
+
await tick();
|
|
214
|
+
/**
|
|
215
|
+
* Fired when the list reaches `end_threshold` items before the end of the list.
|
|
216
|
+
*/
|
|
217
|
+
fire("end", { start, end });
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const resize = () => {
|
|
223
|
+
viewport_height = viewport.offsetHeight;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// trigger initial refresh
|
|
227
|
+
onMount(() => {
|
|
228
|
+
rows = contents.getElementsByClassName("row");
|
|
229
|
+
mounted = true;
|
|
230
|
+
});
|
|
231
|
+
</script>
|
package/index.js
CHANGED
|
@@ -17,6 +17,7 @@ export { default as TimelineItem } from "./helpers/Timeline/TimelineItem.svelte"
|
|
|
17
17
|
export { default as TimelineHeader } from "./helpers/Timeline/TimelineHeader.svelte";
|
|
18
18
|
export { default as Nl2br } from "./helpers/Nl2br.svelte";
|
|
19
19
|
export { default as ClipboardCopier } from "./helpers/ClipboardCopier.svelte";
|
|
20
|
+
export { default as ScrollableList } from "./helpers/ScrollableList.svelte";
|
|
20
21
|
export { alert, confirm, prompt, default as Dialog } from "./helpers/Dialog";
|
|
21
22
|
export {
|
|
22
23
|
Notifications,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kws3/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "UI components for use with Svelte v3 applications.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -23,11 +23,12 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"apexcharts": "
|
|
26
|
+
"apexcharts": "3.33.2",
|
|
27
27
|
"flatpickr": "^4.5.2",
|
|
28
|
+
"fuzzysearch": "^1.0.3",
|
|
28
29
|
"svelte-portal": "^2.1.2",
|
|
29
30
|
"text-mask-core": "^5.1.2",
|
|
30
31
|
"tippy.js": "^6.3.1"
|
|
31
32
|
},
|
|
32
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "2fdaba3e13397494f06b5881bf92f68b1c7c695d"
|
|
33
34
|
}
|
|
@@ -25,6 +25,8 @@ This will work only when `track_height` is set to `true`
|
|
|
25
25
|
: ''} {h_center ? 'h-centered' : ''} {active ? 'is-active' : ''} {klass}"
|
|
26
26
|
{style}>
|
|
27
27
|
<div
|
|
28
|
+
use:resizeObserver
|
|
29
|
+
on:resize={debouncedFireSizeChange}
|
|
28
30
|
bind:this={slideInner}
|
|
29
31
|
class="sliding-pane-inner {v_center ? 'v-centered' : ''} {h_center
|
|
30
32
|
? 'h-centered'
|
|
@@ -52,6 +54,10 @@ This will work only when `track_height` is set to `true`
|
|
|
52
54
|
<script>
|
|
53
55
|
import { onMount, createEventDispatcher } from "svelte";
|
|
54
56
|
import { debounce } from "@kws3/ui/utils";
|
|
57
|
+
import {
|
|
58
|
+
resizeObserver,
|
|
59
|
+
hasResizeObserver,
|
|
60
|
+
} from "@kws3/ui/utils/resizeObserver";
|
|
55
61
|
|
|
56
62
|
const fire = createEventDispatcher();
|
|
57
63
|
|
|
@@ -76,8 +82,7 @@ This will work only when `track_height` is set to `true`
|
|
|
76
82
|
*/
|
|
77
83
|
track_height = true;
|
|
78
84
|
|
|
79
|
-
|
|
80
|
-
let _height, slideInner, Observer;
|
|
85
|
+
let _height, slideInner;
|
|
81
86
|
|
|
82
87
|
/**
|
|
83
88
|
* CSS classes for the panel
|
|
@@ -91,18 +96,22 @@ This will work only when `track_height` is set to `true`
|
|
|
91
96
|
}
|
|
92
97
|
}
|
|
93
98
|
|
|
99
|
+
const max_retries_for_render = 10;
|
|
100
|
+
let try_count = 0;
|
|
94
101
|
function pollForRender() {
|
|
95
102
|
if (slideInner && typeof slideInner != "undefined") {
|
|
96
103
|
init();
|
|
97
104
|
} else {
|
|
98
105
|
setTimeout(() => {
|
|
99
|
-
|
|
106
|
+
try_count++;
|
|
107
|
+
if (try_count < max_retries_for_render) {
|
|
108
|
+
pollForRender();
|
|
109
|
+
}
|
|
100
110
|
}, 50);
|
|
101
111
|
}
|
|
102
112
|
}
|
|
103
113
|
|
|
104
114
|
function init() {
|
|
105
|
-
setupResizeObserver();
|
|
106
115
|
fireSizeChange();
|
|
107
116
|
}
|
|
108
117
|
|
|
@@ -129,23 +138,7 @@ This will work only when `track_height` is set to `true`
|
|
|
129
138
|
|
|
130
139
|
const debouncedFireSizeChange = debounce(fireSizeChange, 150, false);
|
|
131
140
|
|
|
132
|
-
const setupResizeObserver = () => {
|
|
133
|
-
if (hasResizeObserver) {
|
|
134
|
-
if (!slideInner || typeof slideInner == "undefined") {
|
|
135
|
-
pollForRender();
|
|
136
|
-
} else {
|
|
137
|
-
Observer = new ResizeObserver(() => {
|
|
138
|
-
debouncedFireSizeChange();
|
|
139
|
-
});
|
|
140
|
-
Observer.observe(slideInner);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
|
|
145
141
|
onMount(() => {
|
|
146
142
|
pollForRender();
|
|
147
|
-
return () => {
|
|
148
|
-
Observer && Observer.disconnect();
|
|
149
|
-
};
|
|
150
143
|
});
|
|
151
144
|
</script>
|
package/styles/ActionSheet.scss
CHANGED
|
@@ -2,6 +2,16 @@ $kws-actionsheet-background: $background !default;
|
|
|
2
2
|
$kws-actionsheet-box-shadow: $card-shadow !default;
|
|
3
3
|
$kws-actionsheet-box-radius: $radius !default;
|
|
4
4
|
|
|
5
|
+
.kws-action-sheet-outer {
|
|
6
|
+
display: flex;
|
|
7
|
+
visibility: hidden;
|
|
8
|
+
&.is-active {
|
|
9
|
+
visibility: visible;
|
|
10
|
+
}
|
|
11
|
+
.modal-background {
|
|
12
|
+
transition: all 0.3s;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
5
15
|
.kws-action-sheet {
|
|
6
16
|
border-radius: $kws-actionsheet-box-radius $kws-actionsheet-box-radius 0 0;
|
|
7
17
|
box-shadow: $kws-actionsheet-box-shadow;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const hasResizeObserver = typeof window.ResizeObserver != "undefined";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Usage: `<div use:resizeObserver on:resize={resizeHandler}>`
|
|
5
|
+
* @param {HTMLElement} node
|
|
6
|
+
* @returns {Object}
|
|
7
|
+
*/
|
|
8
|
+
export function resizeObserver(node) {
|
|
9
|
+
let ro;
|
|
10
|
+
if (hasResizeObserver) {
|
|
11
|
+
ro = new ResizeObserver(() => {
|
|
12
|
+
const e = new CustomEvent("resize", { bubbles: false });
|
|
13
|
+
node.dispatchEvent(e);
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
ro.observe(node);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return {
|
|
20
|
+
destroy() {
|
|
21
|
+
hasResizeObserver && ro.disconnect();
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|