@threadlabs/looma 0.25.1 → 0.25.3
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/components/ui-input-group/ui-input-group.html +21 -0
- package/components/ui-input-group/ui-input-group.js +17 -0
- package/components/ui-textarea/ui-textarea.html +7 -0
- package/components/ui-tree-item/ui-tree-item.html +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/styles/ui-input-group.css +21 -0
- package/styles/ui-textarea.css +7 -0
- package/styles/ui-tree-item.css +1 -1
- package/vanilla/UiInputGroup.d.ts +1 -0
- package/vanilla/UiInputGroup.js +1 -1
- package/vue/UiInputGroup.d.ts +9 -0
- package/vue/UiInputGroup.vue +48 -1
- package/vue/UiTextarea.vue +16 -0
- package/vue/UiTreeItem.vue +1 -1
- package/vue/chunks/UiInputGroup.js +27 -2
- package/vue/chunks/UiTextarea.js +1 -1
- package/vue/chunks/UiTreeItem.js +1 -1
- package/vue/components.css +176 -140
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
<template component="ui-input-group" controller="./ui-input-group.js">
|
|
2
2
|
<defs>
|
|
3
3
|
<prop name="multiline" type="boolean" default="false">Groups a Textarea with an action below its text inside the shared frame.</prop>
|
|
4
|
+
<prop name="actionPosition" type="keyword" values="below, top-end" default="below"
|
|
5
|
+
>In a multiline group, below keeps the action under the text. top-end places it inside the textarea at its upper end and reserves text padding for its
|
|
6
|
+
measured width.</prop>
|
|
4
7
|
<prop name="prefixKind" type="keyword" values="text, icon" default="text"
|
|
5
8
|
>Text affixes have their own framing. An icon prefix shares the field surface and uses one compact icon-to-value gap.</prop>
|
|
6
9
|
<prop name="disabled" type="boolean" default="false">Fades the group's framing to match a disabled input inside it. Disable the input itself too.</prop>
|
|
@@ -201,6 +204,24 @@
|
|
|
201
204
|
padding-block-start: 0;
|
|
202
205
|
}
|
|
203
206
|
|
|
207
|
+
/* The same textarea keeps its full resizeable box. Its text reserves the action's live width,
|
|
208
|
+
so a translated label or pending indicator cannot cover what the person types. */
|
|
209
|
+
:host([multiline][actionPosition="top-end"]) {
|
|
210
|
+
--_ui-default-textarea-padding-inline-end: calc(var(--_ui-input-group-action-inline-size, 7rem) + var(--ui-space-3));
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
:host([multiline][actionPosition="top-end"]) .field {
|
|
214
|
+
grid-row: 1;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
:host([multiline][actionPosition="top-end"]) .action {
|
|
218
|
+
grid-column: 2;
|
|
219
|
+
grid-row: 1;
|
|
220
|
+
align-self: start;
|
|
221
|
+
justify-self: end;
|
|
222
|
+
padding: var(--ui-space-2);
|
|
223
|
+
}
|
|
224
|
+
|
|
204
225
|
.affix:empty,
|
|
205
226
|
.action:empty {
|
|
206
227
|
display: none;
|
|
@@ -20,7 +20,22 @@ function connect(host) {
|
|
|
20
20
|
let owned = [];
|
|
21
21
|
let described = null;
|
|
22
22
|
const warned = new Set();
|
|
23
|
+
let action = null;
|
|
24
|
+
const measureAction = () => {
|
|
25
|
+
const width = action?.getBoundingClientRect().width ?? 0;
|
|
26
|
+
element.style.setProperty("--_ui-input-group-action-inline-size", `${width}px`);
|
|
27
|
+
};
|
|
28
|
+
// Observe the actual slot surface rather than estimating a label's width. This also catches
|
|
29
|
+
// pending indicators, font loading, touch target sizing and translated labels.
|
|
30
|
+
const actionObserver = new ResizeObserver(measureAction);
|
|
23
31
|
const wire = () => {
|
|
32
|
+
const nextAction = element.querySelector(":scope > .action");
|
|
33
|
+
if (action !== nextAction) {
|
|
34
|
+
if (action) actionObserver.unobserve(action);
|
|
35
|
+
action = nextAction;
|
|
36
|
+
if (action) actionObserver.observe(action);
|
|
37
|
+
}
|
|
38
|
+
measureAction();
|
|
24
39
|
const input = element.querySelector(".field :is(input, textarea)");
|
|
25
40
|
const affixes = Array.from(element.querySelectorAll(":scope > .affix")).filter((affix) => {
|
|
26
41
|
const text = affix.textContent.trim() !== "" && !affix.querySelector(INTERACTIVE);
|
|
@@ -61,6 +76,8 @@ function connect(host) {
|
|
|
61
76
|
wire();
|
|
62
77
|
return () => {
|
|
63
78
|
observer.disconnect();
|
|
79
|
+
actionObserver.disconnect();
|
|
80
|
+
element.style.removeProperty("--_ui-input-group-action-inline-size");
|
|
64
81
|
element.removeEventListener("mousedown", onMousedown);
|
|
65
82
|
element.removeEventListener("click", onClick);
|
|
66
83
|
};
|
|
@@ -70,6 +70,10 @@
|
|
|
70
70
|
syntax: "*";
|
|
71
71
|
inherits: false;
|
|
72
72
|
}
|
|
73
|
+
@property --ui-textarea-padding-inline-end {
|
|
74
|
+
syntax: "*";
|
|
75
|
+
inherits: false;
|
|
76
|
+
}
|
|
73
77
|
|
|
74
78
|
:host {
|
|
75
79
|
box-sizing: border-box;
|
|
@@ -80,6 +84,7 @@
|
|
|
80
84
|
margin: 0;
|
|
81
85
|
--_padding-block: var(--ui-space-2);
|
|
82
86
|
padding: var(--ui-space-2) var(--ui-space-3);
|
|
87
|
+
padding-inline-end: var(--ui-textarea-padding-inline-end, var(--_ui-default-textarea-padding-inline-end, var(--ui-space-3)));
|
|
83
88
|
appearance: none;
|
|
84
89
|
resize: vertical;
|
|
85
90
|
border: var(--ui-textarea-border-width, var(--_ui-default-textarea-border-width, var(--ui-border-width))) solid
|
|
@@ -148,12 +153,14 @@
|
|
|
148
153
|
:host([size="sm"]) {
|
|
149
154
|
--_padding-block: var(--ui-space-1);
|
|
150
155
|
padding: var(--ui-space-1) var(--ui-space-2);
|
|
156
|
+
padding-inline-end: var(--ui-textarea-padding-inline-end, var(--_ui-default-textarea-padding-inline-end, var(--ui-space-2)));
|
|
151
157
|
font-size: var(--ui-font-size-sm);
|
|
152
158
|
}
|
|
153
159
|
|
|
154
160
|
:host([size="lg"]) {
|
|
155
161
|
--_padding-block: var(--ui-space-3);
|
|
156
162
|
padding: var(--ui-space-3) var(--ui-space-4);
|
|
163
|
+
padding-inline-end: var(--ui-textarea-padding-inline-end, var(--_ui-default-textarea-padding-inline-end, var(--ui-space-4)));
|
|
157
164
|
font-size: var(--ui-font-size-md);
|
|
158
165
|
}
|
|
159
166
|
|