@sveltia/ui 0.6.1 → 0.6.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.
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
<!--
|
|
2
2
|
@component
|
|
3
|
-
A multi-line text field
|
|
3
|
+
A multi-line text field based on the HTML `<textarea>` element, providing the auto-resize support.
|
|
4
4
|
@see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea
|
|
5
5
|
@see https://w3c.github.io/aria/#textbox
|
|
6
|
+
@see https://css-tricks.com/the-cleanest-trick-for-autogrowing-textareas/
|
|
6
7
|
-->
|
|
7
8
|
<svelte:options accessors={true} />
|
|
8
9
|
|
|
9
10
|
<script>
|
|
10
|
-
import { onMount, tick } from 'svelte';
|
|
11
|
-
|
|
12
11
|
/**
|
|
13
12
|
* CSS class name on the button.
|
|
14
13
|
* @type {string}
|
|
@@ -26,80 +25,32 @@
|
|
|
26
25
|
export let value = undefined;
|
|
27
26
|
|
|
28
27
|
export let autoResize = false;
|
|
29
|
-
|
|
30
|
-
/** @type {string?} */
|
|
31
|
-
let height;
|
|
32
|
-
/** @type {HTMLElement?} */
|
|
33
|
-
let outer = undefined;
|
|
34
|
-
let resizing = false;
|
|
35
|
-
let lastWidth = 0;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Resize the `<textarea>` based on the filled text content.
|
|
39
|
-
*/
|
|
40
|
-
const resizeTextarea = async () => {
|
|
41
|
-
resizing = true;
|
|
42
|
-
height = 'auto';
|
|
43
|
-
|
|
44
|
-
await tick();
|
|
45
|
-
|
|
46
|
-
height = value && element?.scrollHeight ? `${element.scrollHeight + 4}px` : undefined;
|
|
47
|
-
resizing = false;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Call {@link resizeTextarea} whenever the text content is updated.
|
|
52
|
-
*/
|
|
53
|
-
$: {
|
|
54
|
-
if (autoResize) {
|
|
55
|
-
// @ts-ignore
|
|
56
|
-
resizeTextarea(value);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
/**
|
|
61
|
-
* Call {@link resizeTextarea} whenever it’s horizontally resized.
|
|
62
|
-
*/
|
|
63
|
-
onMount(() => {
|
|
64
|
-
const observer = new ResizeObserver(([{ contentRect }]) => {
|
|
65
|
-
const { width } = contentRect;
|
|
66
|
-
|
|
67
|
-
if (autoResize && lastWidth !== width) {
|
|
68
|
-
lastWidth = width;
|
|
69
|
-
resizeTextarea();
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
observer.observe(outer);
|
|
74
|
-
|
|
75
|
-
// onUnmount
|
|
76
|
-
return () => {
|
|
77
|
-
observer.disconnect();
|
|
78
|
-
};
|
|
79
|
-
});
|
|
80
28
|
</script>
|
|
81
29
|
|
|
82
|
-
<div class="sui text-area {className}"
|
|
30
|
+
<div class="sui text-area {className}">
|
|
83
31
|
<textarea
|
|
84
32
|
name={name || undefined}
|
|
85
33
|
{...$$restProps}
|
|
86
|
-
|
|
87
|
-
class:resizing
|
|
34
|
+
class:auto-resize={autoResize}
|
|
88
35
|
bind:this={element}
|
|
89
36
|
bind:value
|
|
90
37
|
on:click
|
|
91
38
|
on:input
|
|
92
39
|
on:keypress
|
|
93
40
|
/>
|
|
41
|
+
{#if autoResize}
|
|
42
|
+
<div class="clone" aria-hidden="true">{value}</div>
|
|
43
|
+
{/if}
|
|
94
44
|
</div>
|
|
95
45
|
|
|
96
46
|
<style>.text-area {
|
|
47
|
+
display: inline-grid;
|
|
97
48
|
width: 100%;
|
|
98
|
-
display: inline-flex;
|
|
99
|
-
align-items: center;
|
|
100
49
|
}
|
|
101
50
|
|
|
102
|
-
textarea
|
|
51
|
+
textarea,
|
|
52
|
+
.clone {
|
|
53
|
+
grid-area: 1/1/2/2;
|
|
103
54
|
display: block;
|
|
104
55
|
margin: 0;
|
|
105
56
|
border-width: 1px;
|
|
@@ -113,17 +64,32 @@ textarea {
|
|
|
113
64
|
font-family: var(--sui-textbox-font-family);
|
|
114
65
|
font-size: var(--sui-textbox-font-size);
|
|
115
66
|
line-height: var(--sui-textbox-multiline-line-height);
|
|
116
|
-
resize: vertical;
|
|
117
67
|
transition: all 200ms;
|
|
118
68
|
}
|
|
119
|
-
textarea.resizing
|
|
69
|
+
textarea.resizing,
|
|
70
|
+
.clone.resizing {
|
|
120
71
|
transition-duration: 0ms;
|
|
121
72
|
}
|
|
122
|
-
textarea:focus
|
|
73
|
+
textarea:focus,
|
|
74
|
+
.clone:focus {
|
|
123
75
|
border-color: var(--sui-primary-accent-color);
|
|
124
76
|
}
|
|
125
|
-
textarea:disabled
|
|
77
|
+
textarea:disabled,
|
|
78
|
+
.clone:disabled {
|
|
126
79
|
background-color: var(--sui-disabled-background-color);
|
|
127
80
|
opacity: 0.4;
|
|
128
81
|
cursor: default;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
textarea {
|
|
85
|
+
resize: vertical;
|
|
86
|
+
}
|
|
87
|
+
textarea.auto-resize {
|
|
88
|
+
overflow: hidden;
|
|
89
|
+
resize: none;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.clone {
|
|
93
|
+
visibility: hidden;
|
|
94
|
+
white-space: pre-wrap;
|
|
129
95
|
}</style>
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
/** @typedef {typeof __propDef.events} TextAreaEvents */
|
|
3
3
|
/** @typedef {typeof __propDef.slots} TextAreaSlots */
|
|
4
4
|
/**
|
|
5
|
-
* A multi-line text field
|
|
5
|
+
* A multi-line text field based on the HTML `<textarea>` element, providing the auto-resize support.
|
|
6
6
|
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea
|
|
7
7
|
* @see https://w3c.github.io/aria/#textbox
|
|
8
|
+
* @see https://css-tricks.com/the-cleanest-trick-for-autogrowing-textareas/
|
|
8
9
|
*/
|
|
9
10
|
export default class TextArea extends SvelteComponent<{
|
|
10
11
|
[x: string]: any;
|