@alacris/ui 0.5.0 → 0.5.2
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 +4 -4
- package/package.json +1 -1
- package/src/components/ui-date-picker.js +31 -8
- package/src/components/ui-dialog.js +31 -8
- package/src/components/ui-drawer.js +43 -11
- package/src/components/ui-sheet.js +42 -11
- package/src/components/ui-side-sheet.js +43 -11
- package/src/components/ui-swipe-row.js +2 -0
package/README.md
CHANGED
|
@@ -46,10 +46,10 @@ The published package is plain ESM. Point an import map at a pinned CDN build of
|
|
|
46
46
|
<script type="importmap">
|
|
47
47
|
{
|
|
48
48
|
"imports": {
|
|
49
|
-
"@alacris/core": "https://cdn.jsdelivr.net/npm/@alacris/core@0.11.
|
|
50
|
-
"@alacris/ui": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.5.
|
|
51
|
-
"@alacris/ui/theme": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.5.
|
|
52
|
-
"@alacris/ui/components/": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.5.
|
|
49
|
+
"@alacris/core": "https://cdn.jsdelivr.net/npm/@alacris/core@0.11.5/dist/alacris.js",
|
|
50
|
+
"@alacris/ui": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.5.2/src/index.js",
|
|
51
|
+
"@alacris/ui/theme": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.5.2/src/theme/index.js",
|
|
52
|
+
"@alacris/ui/components/": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.5.2/src/components/"
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
</script>
|
package/package.json
CHANGED
|
@@ -36,7 +36,7 @@ import { sys } from '../tokens/sys.js';
|
|
|
36
36
|
import { base } from './base.js';
|
|
37
37
|
import { formBind } from '../util/form.js';
|
|
38
38
|
import { presence } from '../motion/presence.js';
|
|
39
|
-
import { animate, fx } from '../motion/animate.js';
|
|
39
|
+
import { animate, fx, releaseFill } from '../motion/animate.js';
|
|
40
40
|
import { autoUpdate } from '../util/position.js';
|
|
41
41
|
import { escapeLayer } from '../util/keys.js';
|
|
42
42
|
import { popupEvent } from '../util/popup.js';
|
|
@@ -274,17 +274,27 @@ const styles = css`
|
|
|
274
274
|
.overlay {
|
|
275
275
|
position: fixed;
|
|
276
276
|
inset: 0;
|
|
277
|
+
inline-size: 100vw;
|
|
278
|
+
block-size: 100vh;
|
|
279
|
+
max-inline-size: 100vw;
|
|
280
|
+
max-block-size: 100vh;
|
|
281
|
+
margin: 0;
|
|
282
|
+
padding: 0;
|
|
283
|
+
border: none;
|
|
284
|
+
background: transparent;
|
|
285
|
+
overflow: visible;
|
|
277
286
|
z-index: ${sys.z.popup};
|
|
278
287
|
display: grid;
|
|
279
288
|
place-items: center;
|
|
280
289
|
}
|
|
281
|
-
.
|
|
282
|
-
|
|
283
|
-
from { transform: scale(0.8); }
|
|
284
|
-
to { transform: none; }
|
|
290
|
+
.overlay:popover-open {
|
|
291
|
+
display: grid;
|
|
285
292
|
}
|
|
293
|
+
.overlay::backdrop {
|
|
294
|
+
display: none;
|
|
295
|
+
}
|
|
296
|
+
.scrim { position: absolute; inset: 0; background: ${t.scrim}; }
|
|
286
297
|
.modal-surface {
|
|
287
|
-
animation: ui-date-picker-in ${sys.duration.medium2} ${sys.easing.emphasizedDecelerate};
|
|
288
298
|
position: relative;
|
|
289
299
|
display: flex;
|
|
290
300
|
flex-direction: column;
|
|
@@ -714,12 +724,25 @@ define('ui-date-picker', {
|
|
|
714
724
|
${calGrid}
|
|
715
725
|
</div>`;
|
|
716
726
|
|
|
727
|
+
const modalSurfaceRef = (el) => {
|
|
728
|
+
modalSurfaceEl = el;
|
|
729
|
+
releaseFill(animate(el, fx.scaleIn, { duration: 'medium2', easing: 'emphasizedDecelerate' }));
|
|
730
|
+
};
|
|
731
|
+
|
|
732
|
+
const modalOverlayRef = (el) => {
|
|
733
|
+
queueMicrotask(() => {
|
|
734
|
+
try {
|
|
735
|
+
if (el.isConnected) el.showPopover?.();
|
|
736
|
+
} catch {}
|
|
737
|
+
});
|
|
738
|
+
};
|
|
739
|
+
|
|
717
740
|
const modalView = () => html`
|
|
718
|
-
<div class="overlay">
|
|
741
|
+
<div class="overlay" popover="manual" ref=${modalOverlayRef}>
|
|
719
742
|
<div class="scrim" aria-hidden="true" @click=${closePanel}></div>
|
|
720
743
|
<div class="modal-surface" part="panel" role="dialog" aria-modal="true"
|
|
721
744
|
aria-label=${() => label() || 'Choose date'}
|
|
722
|
-
ref=${
|
|
745
|
+
ref=${modalSurfaceRef}>
|
|
723
746
|
<div class="headline">${() => (range() ? 'Select dates' : 'Select date')}</div>
|
|
724
747
|
<div class="picked">${pickedLabel}</div>
|
|
725
748
|
<div class="cal-header">
|
|
@@ -29,7 +29,7 @@ import { define, html, css, vars, effect, onCleanup, signal } from '@alacris/cor
|
|
|
29
29
|
import { sys } from '../tokens/sys.js';
|
|
30
30
|
import { base } from './base.js';
|
|
31
31
|
import { presence } from '../motion/presence.js';
|
|
32
|
-
import { animate, fx } from '../motion/animate.js';
|
|
32
|
+
import { animate, fx, releaseFill } from '../motion/animate.js';
|
|
33
33
|
import { focusTrap, scrollLock } from '../util/focus.js';
|
|
34
34
|
|
|
35
35
|
const t = vars('ui-dialog', {
|
|
@@ -46,17 +46,27 @@ const styles = css`
|
|
|
46
46
|
.overlay {
|
|
47
47
|
position: fixed;
|
|
48
48
|
inset: 0;
|
|
49
|
+
inline-size: 100vw;
|
|
50
|
+
block-size: 100vh;
|
|
51
|
+
max-inline-size: 100vw;
|
|
52
|
+
max-block-size: 100vh;
|
|
53
|
+
margin: 0;
|
|
54
|
+
padding: 0;
|
|
55
|
+
border: none;
|
|
56
|
+
background: transparent;
|
|
57
|
+
overflow: visible;
|
|
49
58
|
z-index: ${sys.z.modal};
|
|
50
59
|
display: grid;
|
|
51
60
|
place-items: center;
|
|
52
61
|
}
|
|
53
|
-
.
|
|
54
|
-
|
|
55
|
-
from { transform: scale(0.8); }
|
|
56
|
-
to { transform: none; }
|
|
62
|
+
.overlay:popover-open {
|
|
63
|
+
display: grid;
|
|
57
64
|
}
|
|
65
|
+
.overlay::backdrop {
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
68
|
+
.scrim { position: absolute; inset: 0; background: ${t.scrim}; }
|
|
58
69
|
.surface {
|
|
59
|
-
animation: ui-dialog-in ${sys.duration.medium2} ${sys.easing.emphasizedDecelerate};
|
|
60
70
|
position: relative;
|
|
61
71
|
display: flex;
|
|
62
72
|
flex-direction: column;
|
|
@@ -146,13 +156,26 @@ define('ui-dialog', {
|
|
|
146
156
|
sync();
|
|
147
157
|
};
|
|
148
158
|
|
|
159
|
+
const surfaceRef = (el) => {
|
|
160
|
+
surfaceEl = el;
|
|
161
|
+
releaseFill(animate(el, fx.scaleIn, { duration: 'medium2', easing: 'emphasizedDecelerate' }));
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
const overlayRef = (el) => {
|
|
165
|
+
queueMicrotask(() => {
|
|
166
|
+
try {
|
|
167
|
+
if (el.isConnected) el.showPopover?.();
|
|
168
|
+
} catch {}
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
|
|
149
172
|
const view = () => html`
|
|
150
|
-
<div class="overlay">
|
|
173
|
+
<div class="overlay" popover="manual" ref=${overlayRef}>
|
|
151
174
|
<div class="scrim" part="scrim" aria-hidden="true" @click=${() => requestClose('scrim')}></div>
|
|
152
175
|
<div class="surface" part="surface" role="dialog" aria-modal="true"
|
|
153
176
|
aria-labelledby=${() => (hasHeadline() ? 'headline' : null)}
|
|
154
177
|
aria-label=${() => (hasHeadline() ? null : (label() || 'Dialog'))}
|
|
155
|
-
tabindex="-1" ref=${
|
|
178
|
+
tabindex="-1" ref=${surfaceRef}>
|
|
156
179
|
<div class="headline" part="headline" id="headline"
|
|
157
180
|
ref=${(el) => hasSlot(el.querySelector('slot'), (has) => {
|
|
158
181
|
hasHeadline.set(has);
|
|
@@ -47,7 +47,23 @@ const styles = css`
|
|
|
47
47
|
.overlay {
|
|
48
48
|
position: fixed;
|
|
49
49
|
inset: 0;
|
|
50
|
+
inline-size: 100vw;
|
|
51
|
+
block-size: 100vh;
|
|
52
|
+
max-inline-size: 100vw;
|
|
53
|
+
max-block-size: 100vh;
|
|
54
|
+
margin: 0;
|
|
55
|
+
padding: 0;
|
|
56
|
+
border: none;
|
|
57
|
+
background: transparent;
|
|
58
|
+
overflow: visible;
|
|
50
59
|
z-index: ${sys.z.drawer};
|
|
60
|
+
display: block;
|
|
61
|
+
}
|
|
62
|
+
.overlay:popover-open {
|
|
63
|
+
display: block;
|
|
64
|
+
}
|
|
65
|
+
.overlay::backdrop {
|
|
66
|
+
display: none;
|
|
51
67
|
}
|
|
52
68
|
.scrim { position: absolute; inset: 0; background: ${t.scrim}; }
|
|
53
69
|
.surface {
|
|
@@ -116,9 +132,11 @@ define('ui-drawer', {
|
|
|
116
132
|
};
|
|
117
133
|
|
|
118
134
|
// Trap focus + lock scroll exactly while the modal drawer is open.
|
|
135
|
+
let closingViaSwipe = false;
|
|
119
136
|
let prevActive = null;
|
|
120
137
|
effect(() => {
|
|
121
138
|
if (open() && variant() === 'modal') {
|
|
139
|
+
closingViaSwipe = false;
|
|
122
140
|
prevActive = document.activeElement;
|
|
123
141
|
document.addEventListener('keydown', onDocKeydown, true);
|
|
124
142
|
if (!unlock) unlock = scrollLock();
|
|
@@ -143,7 +161,7 @@ define('ui-drawer', {
|
|
|
143
161
|
|
|
144
162
|
// The panel slides out while the presence overlay (scrim included) fades.
|
|
145
163
|
effect(() => {
|
|
146
|
-
if (!open() && surfaceEl?.isConnected) {
|
|
164
|
+
if (!open() && surfaceEl?.isConnected && !closingViaSwipe) {
|
|
147
165
|
animate(surfaceEl, slideOut(), { duration: 'short4', easing: 'emphasizedAccelerate' });
|
|
148
166
|
}
|
|
149
167
|
});
|
|
@@ -161,6 +179,7 @@ define('ui-drawer', {
|
|
|
161
179
|
return true;
|
|
162
180
|
},
|
|
163
181
|
onStart() {
|
|
182
|
+
el.getAnimations?.()?.forEach((a) => a.cancel());
|
|
164
183
|
el.style.transition = 'none';
|
|
165
184
|
},
|
|
166
185
|
onMove({ dx }) {
|
|
@@ -183,29 +202,34 @@ define('ui-drawer', {
|
|
|
183
202
|
const shouldDismiss = !cancelled && dismissDirection;
|
|
184
203
|
|
|
185
204
|
if (shouldDismiss) {
|
|
205
|
+
closingViaSwipe = true;
|
|
186
206
|
const targetTransform = isEnd ? 'translateX(100%)' : 'translateX(-100%)';
|
|
187
207
|
const remaining = Math.max(0, w - Math.abs(dx));
|
|
188
208
|
const ms = Math.min(300, Math.max(120, Math.round(remaining / (Math.max(Math.abs(vx), 0.8)))));
|
|
189
209
|
if (scrimEl) {
|
|
190
210
|
animate(scrimEl, fx.fadeOut, { duration: ms, easing: 'emphasizedAccelerate' });
|
|
191
211
|
}
|
|
192
|
-
|
|
212
|
+
animate(el, [
|
|
193
213
|
{ transform: el.style.transform || `translateX(${dx}px)` },
|
|
194
214
|
{ transform: targetTransform },
|
|
195
|
-
], { duration: ms, easing: 'emphasizedAccelerate' });
|
|
196
|
-
|
|
197
|
-
requestClose('swipe');
|
|
198
|
-
});
|
|
215
|
+
], { duration: ms, easing: 'emphasizedAccelerate', fill: 'forwards' });
|
|
216
|
+
requestClose('swipe');
|
|
199
217
|
} else {
|
|
200
218
|
if (scrimEl) {
|
|
201
|
-
animate(scrimEl, [{ opacity: scrimEl.style.opacity || '0.5' }, { opacity: 1 }], {
|
|
219
|
+
const scrimSnap = animate(scrimEl, [{ opacity: scrimEl.style.opacity || '0.5' }, { opacity: 1 }], {
|
|
202
220
|
duration: 'short4', easing: 'emphasizedDecelerate',
|
|
203
|
-
})
|
|
221
|
+
});
|
|
222
|
+
scrimSnap.finished.then(() => {
|
|
223
|
+
try { scrimSnap.cancel(); } catch {}
|
|
224
|
+
if (scrimEl) scrimEl.style.opacity = '';
|
|
225
|
+
});
|
|
204
226
|
}
|
|
205
|
-
animate(el, [
|
|
227
|
+
const snapAnim = animate(el, [
|
|
206
228
|
{ transform: el.style.transform || `translateX(${dx}px)` },
|
|
207
229
|
{ transform: 'translateX(0)' },
|
|
208
|
-
], { duration: 'short4', easing: 'emphasizedDecelerate' })
|
|
230
|
+
], { duration: 'short4', easing: 'emphasizedDecelerate' });
|
|
231
|
+
snapAnim.finished.then(() => {
|
|
232
|
+
try { snapAnim.cancel(); } catch {}
|
|
209
233
|
if (el) el.style.transform = '';
|
|
210
234
|
});
|
|
211
235
|
}
|
|
@@ -213,8 +237,16 @@ define('ui-drawer', {
|
|
|
213
237
|
});
|
|
214
238
|
};
|
|
215
239
|
|
|
240
|
+
const overlayRef = (el) => {
|
|
241
|
+
queueMicrotask(() => {
|
|
242
|
+
try {
|
|
243
|
+
if (el.isConnected) el.showPopover?.();
|
|
244
|
+
} catch {}
|
|
245
|
+
});
|
|
246
|
+
};
|
|
247
|
+
|
|
216
248
|
const overlay = () => html`
|
|
217
|
-
<div class="overlay">
|
|
249
|
+
<div class="overlay" popover="manual" ref=${overlayRef}>
|
|
218
250
|
<div class="scrim" part="scrim" aria-hidden="true"
|
|
219
251
|
ref=${(el) => { scrimEl = el; }}
|
|
220
252
|
@click=${() => requestClose('scrim')}></div>
|
|
@@ -48,11 +48,26 @@ const styles = css`
|
|
|
48
48
|
.overlay {
|
|
49
49
|
position: fixed;
|
|
50
50
|
inset: 0;
|
|
51
|
+
inline-size: 100vw;
|
|
52
|
+
block-size: 100vh;
|
|
53
|
+
max-inline-size: 100vw;
|
|
54
|
+
max-block-size: 100vh;
|
|
55
|
+
margin: 0;
|
|
56
|
+
padding: 0;
|
|
57
|
+
border: none;
|
|
58
|
+
background: transparent;
|
|
59
|
+
overflow: visible;
|
|
51
60
|
z-index: ${sys.z.modal};
|
|
52
61
|
display: flex;
|
|
53
62
|
align-items: flex-end;
|
|
54
63
|
justify-content: center;
|
|
55
64
|
}
|
|
65
|
+
.overlay:popover-open {
|
|
66
|
+
display: flex;
|
|
67
|
+
}
|
|
68
|
+
.overlay::backdrop {
|
|
69
|
+
display: none;
|
|
70
|
+
}
|
|
56
71
|
.scrim { position: absolute; inset: 0; background: ${t.scrim}; }
|
|
57
72
|
.surface {
|
|
58
73
|
position: relative;
|
|
@@ -134,9 +149,11 @@ define('ui-sheet', {
|
|
|
134
149
|
if (e.key === 'Escape') requestClose('esc');
|
|
135
150
|
};
|
|
136
151
|
|
|
152
|
+
let closingViaSwipe = false;
|
|
137
153
|
let prevActive = null;
|
|
138
154
|
effect(() => {
|
|
139
155
|
if (open() && variant() !== 'standard') {
|
|
156
|
+
closingViaSwipe = false;
|
|
140
157
|
prevActive = document.activeElement;
|
|
141
158
|
document.addEventListener('keydown', onDocKeydown, true);
|
|
142
159
|
unlock = scrollLock();
|
|
@@ -150,7 +167,7 @@ define('ui-sheet', {
|
|
|
150
167
|
prevActive = null;
|
|
151
168
|
unlock?.();
|
|
152
169
|
unlock = null;
|
|
153
|
-
if (surfaceEl?.isConnected) {
|
|
170
|
+
if (surfaceEl?.isConnected && !closingViaSwipe) {
|
|
154
171
|
animate(surfaceEl, fx.sheetOut, { duration: 'short4', easing: 'emphasizedAccelerate' });
|
|
155
172
|
}
|
|
156
173
|
}
|
|
@@ -185,6 +202,7 @@ define('ui-sheet', {
|
|
|
185
202
|
return true;
|
|
186
203
|
},
|
|
187
204
|
onStart() {
|
|
205
|
+
el.getAnimations?.()?.forEach((a) => a.cancel());
|
|
188
206
|
el.style.transition = 'none';
|
|
189
207
|
},
|
|
190
208
|
onMove({ dy }) {
|
|
@@ -204,28 +222,33 @@ define('ui-sheet', {
|
|
|
204
222
|
const shouldDismiss = !cancelled && (vy > 0.4 || dy > h * 0.35);
|
|
205
223
|
|
|
206
224
|
if (shouldDismiss) {
|
|
225
|
+
closingViaSwipe = true;
|
|
207
226
|
const remaining = Math.max(0, h - dy);
|
|
208
227
|
const ms = Math.min(300, Math.max(120, Math.round(remaining / (Math.max(vy, 0.8)))));
|
|
209
228
|
if (scrimEl) {
|
|
210
229
|
animate(scrimEl, fx.fadeOut, { duration: ms, easing: 'emphasizedAccelerate' });
|
|
211
230
|
}
|
|
212
|
-
|
|
231
|
+
animate(el, [
|
|
213
232
|
{ transform: el.style.transform || `translateY(${dy}px)` },
|
|
214
233
|
{ transform: 'translateY(100%)' },
|
|
215
|
-
], { duration: ms, easing: 'emphasizedAccelerate' });
|
|
216
|
-
|
|
217
|
-
requestClose('swipe');
|
|
218
|
-
});
|
|
234
|
+
], { duration: ms, easing: 'emphasizedAccelerate', fill: 'forwards' });
|
|
235
|
+
requestClose('swipe');
|
|
219
236
|
} else {
|
|
220
237
|
if (scrimEl) {
|
|
221
|
-
animate(scrimEl, [{ opacity: scrimEl.style.opacity || '0.5' }, { opacity: 1 }], {
|
|
238
|
+
const scrimSnap = animate(scrimEl, [{ opacity: scrimEl.style.opacity || '0.5' }, { opacity: 1 }], {
|
|
222
239
|
duration: 'short4', easing: 'emphasizedDecelerate',
|
|
223
|
-
})
|
|
240
|
+
});
|
|
241
|
+
scrimSnap.finished.then(() => {
|
|
242
|
+
try { scrimSnap.cancel(); } catch {}
|
|
243
|
+
if (scrimEl) scrimEl.style.opacity = '';
|
|
244
|
+
});
|
|
224
245
|
}
|
|
225
|
-
animate(el, [
|
|
246
|
+
const snapAnim = animate(el, [
|
|
226
247
|
{ transform: el.style.transform || `translateY(${dy}px)` },
|
|
227
248
|
{ transform: 'translateY(0)' },
|
|
228
|
-
], { duration: 'short4', easing: 'emphasizedDecelerate' })
|
|
249
|
+
], { duration: 'short4', easing: 'emphasizedDecelerate' });
|
|
250
|
+
snapAnim.finished.then(() => {
|
|
251
|
+
try { snapAnim.cancel(); } catch {}
|
|
229
252
|
if (el) el.style.transform = '';
|
|
230
253
|
});
|
|
231
254
|
}
|
|
@@ -233,8 +256,16 @@ define('ui-sheet', {
|
|
|
233
256
|
});
|
|
234
257
|
};
|
|
235
258
|
|
|
259
|
+
const overlayRef = (el) => {
|
|
260
|
+
queueMicrotask(() => {
|
|
261
|
+
try {
|
|
262
|
+
if (el.isConnected) el.showPopover?.();
|
|
263
|
+
} catch {}
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
|
|
236
267
|
const modalView = () => html`
|
|
237
|
-
<div class="overlay">
|
|
268
|
+
<div class="overlay" popover="manual" ref=${overlayRef}>
|
|
238
269
|
<div class="scrim" part="scrim" aria-hidden="true"
|
|
239
270
|
ref=${(el) => { scrimEl = el; }}
|
|
240
271
|
@click=${() => requestClose('scrim')}></div>
|
|
@@ -48,7 +48,23 @@ const styles = css`
|
|
|
48
48
|
.overlay {
|
|
49
49
|
position: fixed;
|
|
50
50
|
inset: 0;
|
|
51
|
+
inline-size: 100vw;
|
|
52
|
+
block-size: 100vh;
|
|
53
|
+
max-inline-size: 100vw;
|
|
54
|
+
max-block-size: 100vh;
|
|
55
|
+
margin: 0;
|
|
56
|
+
padding: 0;
|
|
57
|
+
border: none;
|
|
58
|
+
background: transparent;
|
|
59
|
+
overflow: visible;
|
|
51
60
|
z-index: ${sys.z.modal};
|
|
61
|
+
display: block;
|
|
62
|
+
}
|
|
63
|
+
.overlay:popover-open {
|
|
64
|
+
display: block;
|
|
65
|
+
}
|
|
66
|
+
.overlay::backdrop {
|
|
67
|
+
display: none;
|
|
52
68
|
}
|
|
53
69
|
.scrim { position: absolute; inset: 0; background: ${t.scrim}; }
|
|
54
70
|
.surface {
|
|
@@ -136,9 +152,11 @@ define('ui-side-sheet', {
|
|
|
136
152
|
if (e.key === 'Escape') requestClose('esc');
|
|
137
153
|
};
|
|
138
154
|
|
|
155
|
+
let closingViaSwipe = false;
|
|
139
156
|
let prevActive = null;
|
|
140
157
|
effect(() => {
|
|
141
158
|
if (open() && variant() !== 'standard') {
|
|
159
|
+
closingViaSwipe = false;
|
|
142
160
|
prevActive = document.activeElement;
|
|
143
161
|
document.addEventListener('keydown', onDocKeydown, true);
|
|
144
162
|
unlock = scrollLock();
|
|
@@ -155,7 +173,7 @@ define('ui-side-sheet', {
|
|
|
155
173
|
}
|
|
156
174
|
});
|
|
157
175
|
effect(() => {
|
|
158
|
-
if (!open() && surfaceEl?.isConnected) {
|
|
176
|
+
if (!open() && surfaceEl?.isConnected && !closingViaSwipe) {
|
|
159
177
|
animate(surfaceEl, slideOut(), { duration: 'short4', easing: 'emphasizedAccelerate' });
|
|
160
178
|
}
|
|
161
179
|
});
|
|
@@ -179,6 +197,7 @@ define('ui-side-sheet', {
|
|
|
179
197
|
return true;
|
|
180
198
|
},
|
|
181
199
|
onStart() {
|
|
200
|
+
el.getAnimations?.()?.forEach((a) => a.cancel());
|
|
182
201
|
el.style.transition = 'none';
|
|
183
202
|
},
|
|
184
203
|
onMove({ dx }) {
|
|
@@ -201,29 +220,34 @@ define('ui-side-sheet', {
|
|
|
201
220
|
const shouldDismiss = !cancelled && dismissDirection;
|
|
202
221
|
|
|
203
222
|
if (shouldDismiss) {
|
|
223
|
+
closingViaSwipe = true;
|
|
204
224
|
const targetTransform = isEnd ? 'translateX(100%)' : 'translateX(-100%)';
|
|
205
225
|
const remaining = Math.max(0, w - Math.abs(dx));
|
|
206
226
|
const ms = Math.min(300, Math.max(120, Math.round(remaining / (Math.max(Math.abs(vx), 0.8)))));
|
|
207
227
|
if (scrimEl) {
|
|
208
228
|
animate(scrimEl, fx.fadeOut, { duration: ms, easing: 'emphasizedAccelerate' });
|
|
209
229
|
}
|
|
210
|
-
|
|
230
|
+
animate(el, [
|
|
211
231
|
{ transform: el.style.transform || `translateX(${dx}px)` },
|
|
212
232
|
{ transform: targetTransform },
|
|
213
|
-
], { duration: ms, easing: 'emphasizedAccelerate' });
|
|
214
|
-
|
|
215
|
-
requestClose('swipe');
|
|
216
|
-
});
|
|
233
|
+
], { duration: ms, easing: 'emphasizedAccelerate', fill: 'forwards' });
|
|
234
|
+
requestClose('swipe');
|
|
217
235
|
} else {
|
|
218
236
|
if (scrimEl) {
|
|
219
|
-
animate(scrimEl, [{ opacity: scrimEl.style.opacity || '0.5' }, { opacity: 1 }], {
|
|
237
|
+
const scrimSnap = animate(scrimEl, [{ opacity: scrimEl.style.opacity || '0.5' }, { opacity: 1 }], {
|
|
220
238
|
duration: 'short4', easing: 'emphasizedDecelerate',
|
|
221
|
-
})
|
|
239
|
+
});
|
|
240
|
+
scrimSnap.finished.then(() => {
|
|
241
|
+
try { scrimSnap.cancel(); } catch {}
|
|
242
|
+
if (scrimEl) scrimEl.style.opacity = '';
|
|
243
|
+
});
|
|
222
244
|
}
|
|
223
|
-
animate(el, [
|
|
245
|
+
const snapAnim = animate(el, [
|
|
224
246
|
{ transform: el.style.transform || `translateX(${dx}px)` },
|
|
225
247
|
{ transform: 'translateX(0)' },
|
|
226
|
-
], { duration: 'short4', easing: 'emphasizedDecelerate' })
|
|
248
|
+
], { duration: 'short4', easing: 'emphasizedDecelerate' });
|
|
249
|
+
snapAnim.finished.then(() => {
|
|
250
|
+
try { snapAnim.cancel(); } catch {}
|
|
227
251
|
if (el) el.style.transform = '';
|
|
228
252
|
});
|
|
229
253
|
}
|
|
@@ -237,8 +261,16 @@ define('ui-side-sheet', {
|
|
|
237
261
|
sync();
|
|
238
262
|
};
|
|
239
263
|
|
|
264
|
+
const overlayRef = (el) => {
|
|
265
|
+
queueMicrotask(() => {
|
|
266
|
+
try {
|
|
267
|
+
if (el.isConnected) el.showPopover?.();
|
|
268
|
+
} catch {}
|
|
269
|
+
});
|
|
270
|
+
};
|
|
271
|
+
|
|
240
272
|
const modalView = () => html`
|
|
241
|
-
<div class="overlay">
|
|
273
|
+
<div class="overlay" popover="manual" ref=${overlayRef}>
|
|
242
274
|
<div class="scrim" part="scrim" aria-hidden="true"
|
|
243
275
|
ref=${(el) => { scrimEl = el; }}
|
|
244
276
|
@click=${() => requestClose('scrim')}></div>
|
|
@@ -97,6 +97,7 @@ define('ui-swipe-row', {
|
|
|
97
97
|
{ transform: targetTransform },
|
|
98
98
|
], { duration: ms, easing });
|
|
99
99
|
return anim.finished.then(() => {
|
|
100
|
+
try { anim.cancel(); } catch {}
|
|
100
101
|
if (contentEl) contentEl.style.transform = targetTransform;
|
|
101
102
|
});
|
|
102
103
|
};
|
|
@@ -163,6 +164,7 @@ define('ui-swipe-row', {
|
|
|
163
164
|
return true;
|
|
164
165
|
},
|
|
165
166
|
onStart() {
|
|
167
|
+
el.getAnimations?.()?.forEach((a) => a.cancel());
|
|
166
168
|
if (currentOpen === 'end') startOffset = -getEndWidth();
|
|
167
169
|
else if (currentOpen === 'start') startOffset = getStartWidth();
|
|
168
170
|
else startOffset = 0;
|