@alacris/ui 0.4.1 → 0.4.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/base.js +1 -1
- package/src/components/ui-autocomplete.js +10 -0
- package/src/components/ui-dialog.js +4 -1
- package/src/components/ui-drawer.js +4 -1
- package/src/components/ui-sheet.js +4 -1
- package/src/components/ui-side-sheet.js +4 -1
- package/src/components/ui-switch.js +1 -1
- package/src/components/ui-text-field.js +12 -0
- package/src/util/focus.js +2 -2
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.4.
|
|
51
|
-
"@alacris/ui/theme": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.4.
|
|
52
|
-
"@alacris/ui/components/": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.4.
|
|
49
|
+
"@alacris/core": "https://cdn.jsdelivr.net/npm/@alacris/core@0.11.4/dist/alacris.js",
|
|
50
|
+
"@alacris/ui": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.4.2/src/index.js",
|
|
51
|
+
"@alacris/ui/theme": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.4.2/src/theme/index.js",
|
|
52
|
+
"@alacris/ui/components/": "https://cdn.jsdelivr.net/npm/@alacris/ui@0.4.2/src/components/"
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
</script>
|
package/package.json
CHANGED
package/src/components/base.js
CHANGED
|
@@ -13,7 +13,7 @@ export const base = css`
|
|
|
13
13
|
font-synthesis: none;
|
|
14
14
|
-webkit-tap-highlight-color: transparent;
|
|
15
15
|
}
|
|
16
|
-
:host([hidden]) { display: none; }
|
|
16
|
+
:host([hidden]) { display: none !important; }
|
|
17
17
|
@media (prefers-reduced-motion: reduce) {
|
|
18
18
|
*, *::before, *::after {
|
|
19
19
|
transition-duration: 0.01ms;
|
|
@@ -276,8 +276,16 @@ define('ui-autocomplete', {
|
|
|
276
276
|
open.set(false);
|
|
277
277
|
};
|
|
278
278
|
|
|
279
|
+
let isComposing = false;
|
|
280
|
+
const onCompositionStart = () => { isComposing = true; };
|
|
281
|
+
const onCompositionEnd = (e) => {
|
|
282
|
+
isComposing = false;
|
|
283
|
+
onInput(e);
|
|
284
|
+
};
|
|
285
|
+
|
|
279
286
|
const onInput = (e) => {
|
|
280
287
|
e.stopPropagation();
|
|
288
|
+
if (isComposing) return;
|
|
281
289
|
query.set(e.target.value);
|
|
282
290
|
open.set(true);
|
|
283
291
|
host.emit('input', { value: e.target.value });
|
|
@@ -358,6 +366,8 @@ define('ui-autocomplete', {
|
|
|
358
366
|
.value=${query}
|
|
359
367
|
placeholder=${() => placeholder() || null}
|
|
360
368
|
?disabled=${disabled} ?required=${required}
|
|
369
|
+
@compositionstart=${onCompositionStart}
|
|
370
|
+
@compositionend=${onCompositionEnd}
|
|
361
371
|
@input=${onInput} @change=${(e) => e.stopPropagation()} @keydown=${onKeydown}
|
|
362
372
|
@focus=${onFocus} @blur=${onBlur}>
|
|
363
373
|
<ui-icon class="arrow" name="arrow-drop-down"></ui-icon>
|
|
@@ -111,19 +111,22 @@ define('ui-dialog', {
|
|
|
111
111
|
};
|
|
112
112
|
|
|
113
113
|
// Trap focus + lock scroll exactly while open; presence handles the DOM.
|
|
114
|
+
let prevActive = null;
|
|
114
115
|
effect(() => {
|
|
115
116
|
if (open()) {
|
|
117
|
+
prevActive = document.activeElement;
|
|
116
118
|
document.addEventListener('keydown', onDocKeydown, true);
|
|
117
119
|
unlock = scrollLock();
|
|
118
120
|
// The surface renders synchronously with the signal write, but wait a
|
|
119
121
|
// microtask so slotted content is distributed before we look for it.
|
|
120
122
|
queueMicrotask(() => {
|
|
121
|
-
if (open() && !releaseTrap) releaseTrap = focusTrap(host);
|
|
123
|
+
if (open() && !releaseTrap) releaseTrap = focusTrap(host, { restore: prevActive });
|
|
122
124
|
});
|
|
123
125
|
} else {
|
|
124
126
|
document.removeEventListener('keydown', onDocKeydown, true);
|
|
125
127
|
releaseTrap?.();
|
|
126
128
|
releaseTrap = null;
|
|
129
|
+
prevActive = null;
|
|
127
130
|
unlock?.();
|
|
128
131
|
unlock = null;
|
|
129
132
|
if (surfaceEl?.isConnected) {
|
|
@@ -105,17 +105,20 @@ define('ui-drawer', {
|
|
|
105
105
|
};
|
|
106
106
|
|
|
107
107
|
// Trap focus + lock scroll exactly while the modal drawer is open.
|
|
108
|
+
let prevActive = null;
|
|
108
109
|
effect(() => {
|
|
109
110
|
if (open() && variant() === 'modal') {
|
|
111
|
+
prevActive = document.activeElement;
|
|
110
112
|
document.addEventListener('keydown', onDocKeydown, true);
|
|
111
113
|
if (!unlock) unlock = scrollLock();
|
|
112
114
|
queueMicrotask(() => {
|
|
113
|
-
if (open.peek() && !releaseTrap) releaseTrap = focusTrap(host);
|
|
115
|
+
if (open.peek() && !releaseTrap) releaseTrap = focusTrap(host, { restore: prevActive });
|
|
114
116
|
});
|
|
115
117
|
} else {
|
|
116
118
|
document.removeEventListener('keydown', onDocKeydown, true);
|
|
117
119
|
releaseTrap?.();
|
|
118
120
|
releaseTrap = null;
|
|
121
|
+
prevActive = null;
|
|
119
122
|
unlock?.();
|
|
120
123
|
unlock = null;
|
|
121
124
|
}
|
|
@@ -126,17 +126,20 @@ define('ui-sheet', {
|
|
|
126
126
|
if (e.key === 'Escape') requestClose('esc');
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
+
let prevActive = null;
|
|
129
130
|
effect(() => {
|
|
130
131
|
if (open() && variant() !== 'standard') {
|
|
132
|
+
prevActive = document.activeElement;
|
|
131
133
|
document.addEventListener('keydown', onDocKeydown, true);
|
|
132
134
|
unlock = scrollLock();
|
|
133
135
|
queueMicrotask(() => {
|
|
134
|
-
if (open() && !releaseTrap) releaseTrap = focusTrap(host);
|
|
136
|
+
if (open() && !releaseTrap) releaseTrap = focusTrap(host, { restore: prevActive });
|
|
135
137
|
});
|
|
136
138
|
} else {
|
|
137
139
|
document.removeEventListener('keydown', onDocKeydown, true);
|
|
138
140
|
releaseTrap?.();
|
|
139
141
|
releaseTrap = null;
|
|
142
|
+
prevActive = null;
|
|
140
143
|
unlock?.();
|
|
141
144
|
unlock = null;
|
|
142
145
|
if (surfaceEl?.isConnected) {
|
|
@@ -130,17 +130,20 @@ define('ui-side-sheet', {
|
|
|
130
130
|
if (e.key === 'Escape') requestClose('esc');
|
|
131
131
|
};
|
|
132
132
|
|
|
133
|
+
let prevActive = null;
|
|
133
134
|
effect(() => {
|
|
134
135
|
if (open() && variant() !== 'standard') {
|
|
136
|
+
prevActive = document.activeElement;
|
|
135
137
|
document.addEventListener('keydown', onDocKeydown, true);
|
|
136
138
|
unlock = scrollLock();
|
|
137
139
|
queueMicrotask(() => {
|
|
138
|
-
if (open() && !releaseTrap) releaseTrap = focusTrap(host);
|
|
140
|
+
if (open() && !releaseTrap) releaseTrap = focusTrap(host, { restore: prevActive });
|
|
139
141
|
});
|
|
140
142
|
} else {
|
|
141
143
|
document.removeEventListener('keydown', onDocKeydown, true);
|
|
142
144
|
releaseTrap?.();
|
|
143
145
|
releaseTrap = null;
|
|
146
|
+
prevActive = null;
|
|
144
147
|
unlock?.();
|
|
145
148
|
unlock = null;
|
|
146
149
|
}
|
|
@@ -144,7 +144,7 @@ define('ui-switch', {
|
|
|
144
144
|
${() => (icons() ? html`<ui-icon name=${() => (checked() ? 'check' : 'close')}></ui-icon>` : null)}
|
|
145
145
|
</span>
|
|
146
146
|
</button>
|
|
147
|
-
${() => (label() ? html`<span id="label">${label}</span>` :
|
|
147
|
+
${() => (label() ? html`<span id="label" part="label">${label}</span>` : html`<slot></slot>`)}
|
|
148
148
|
</label>`;
|
|
149
149
|
},
|
|
150
150
|
});
|
|
@@ -320,7 +320,15 @@ define('ui-text-field', {
|
|
|
320
320
|
hasLeading() && 'with-leading', type() === 'textarea' && 'multiline',
|
|
321
321
|
type() === 'number' && 'numeric'].filter(Boolean).join(' '));
|
|
322
322
|
|
|
323
|
+
let isComposing = false;
|
|
324
|
+
const onCompositionStart = () => { isComposing = true; };
|
|
325
|
+
const onCompositionEnd = (e) => {
|
|
326
|
+
isComposing = false;
|
|
327
|
+
onInput(e);
|
|
328
|
+
};
|
|
329
|
+
|
|
323
330
|
const onInput = (e) => {
|
|
331
|
+
if (isComposing) return;
|
|
324
332
|
value.set(e.target.value);
|
|
325
333
|
host.emit('input', { value: value() });
|
|
326
334
|
};
|
|
@@ -350,6 +358,8 @@ define('ui-text-field', {
|
|
|
350
358
|
spellcheck=${attr(spellcheck)}
|
|
351
359
|
inputmode=${attr(inputmode)}
|
|
352
360
|
enterkeyhint=${attr(enterkeyhint)}
|
|
361
|
+
@compositionstart=${onCompositionStart}
|
|
362
|
+
@compositionend=${onCompositionEnd}
|
|
353
363
|
@input=${onInput} @change=${commit}
|
|
354
364
|
@focus=${() => focused.set(true)} @blur=${() => focused.set(false)}></textarea></span>`
|
|
355
365
|
: html`<input part="input" ref=${(el) => (input = el)}
|
|
@@ -364,6 +374,8 @@ define('ui-text-field', {
|
|
|
364
374
|
spellcheck=${attr(spellcheck)}
|
|
365
375
|
inputmode=${attr(inputmode)}
|
|
366
376
|
enterkeyhint=${attr(enterkeyhint)}
|
|
377
|
+
@compositionstart=${onCompositionStart}
|
|
378
|
+
@compositionend=${onCompositionEnd}
|
|
367
379
|
@input=${onInput} @change=${commit}
|
|
368
380
|
@focus=${() => focused.set(true)} @blur=${() => focused.set(false)}>`)}
|
|
369
381
|
${() => (clearable() && value() !== '' && !disabled()
|
package/src/util/focus.js
CHANGED
|
@@ -32,8 +32,8 @@ export function focusables(host) {
|
|
|
32
32
|
*
|
|
33
33
|
* const release = focusTrap(host, { initial: shadowCloseButton });
|
|
34
34
|
*/
|
|
35
|
-
export function focusTrap(host, { initial } = {}) {
|
|
36
|
-
const previous = document.activeElement;
|
|
35
|
+
export function focusTrap(host, { initial, restore } = {}) {
|
|
36
|
+
const previous = restore || document.activeElement;
|
|
37
37
|
|
|
38
38
|
const first = initial || focusables(host)[0] || host;
|
|
39
39
|
first.focus?.();
|