@rettangoli/ui 0.1.20 → 0.1.22
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/dist/rettangoli-iife-layout.min.js +74 -39
- package/dist/rettangoli-iife-ui.min.js +72 -37
- package/package.json +1 -1
- package/src/components/form/form.handlers.js +5 -25
- package/src/components/form/form.store.js +6 -0
- package/src/components/form/form.view.yaml +20 -11
- package/src/components/select/select.store.js +1 -1
- package/src/components/select/select.view.yaml +2 -0
- package/src/entry-iife-layout.js +2 -0
- package/src/entry-iife-ui.js +2 -0
- package/src/index.js +2 -0
- package/src/primitives/input-number.js +288 -0
- package/src/primitives/textarea.js +128 -17
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@ const updateAttributes = ({ form, defaultValues = {}, refs }) => {
|
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
if (['inputText', 'colorPicker', 'slider', 'slider-input', 'popover-input'].includes(field.inputType)) {
|
|
11
|
+
if (['input-textarea', 'inputText', 'input-text', 'input-number', 'colorPicker', 'slider', 'slider-input', 'popover-input'].includes(field.inputType)) {
|
|
12
12
|
const defaultValue = defaultValues[field.name];
|
|
13
13
|
if (defaultValue === undefined || defaultValue === null) {
|
|
14
14
|
ref.removeAttribute('value')
|
|
@@ -16,7 +16,7 @@ const updateAttributes = ({ form, defaultValues = {}, refs }) => {
|
|
|
16
16
|
ref.setAttribute('value', defaultValue)
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
if (
|
|
19
|
+
if (['inputText', 'input-text', 'input-textarea'].includes(field.inputType) && field.placeholder) {
|
|
20
20
|
const currentPlaceholder = ref.getAttribute('placeholder')
|
|
21
21
|
if (currentPlaceholder !== field.placeholder) {
|
|
22
22
|
if (field.placeholder === undefined || field.placeholder === null) {
|
|
@@ -26,27 +26,6 @@ const updateAttributes = ({ form, defaultValues = {}, refs }) => {
|
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
if (field.inputType === 'select' && field.placeholder) {
|
|
30
|
-
if (ref.placeholder !== field.placeholder) {
|
|
31
|
-
ref.placeholder = field.placeholder;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
if (field.inputType === 'select') {
|
|
35
|
-
if (field.placeholder !== ref.getAttribute('placeholder')) {
|
|
36
|
-
if (field.placeholder !== undefined) {
|
|
37
|
-
ref.setAttribute('placeholder', field.placeholder)
|
|
38
|
-
} else {
|
|
39
|
-
ref.removeAttribute('placeholder');
|
|
40
|
-
}
|
|
41
|
-
ref.render();
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const defaultValue = defaultValues[field.name]
|
|
45
|
-
if (defaultValue !== ref.selectedValue) {
|
|
46
|
-
ref.selectedValue = defaultValue;
|
|
47
|
-
ref.render();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
29
|
})
|
|
51
30
|
}
|
|
52
31
|
|
|
@@ -108,14 +87,15 @@ export const handleInputChange = (deps, payload) => {
|
|
|
108
87
|
const event = payload._event;
|
|
109
88
|
let name = event.currentTarget.id.replace("field-", "");
|
|
110
89
|
if (name && event.detail.value !== undefined) {
|
|
90
|
+
const value = event.detail.value
|
|
111
91
|
store.setFormFieldValue({
|
|
112
92
|
name: name,
|
|
113
|
-
value
|
|
93
|
+
value,
|
|
114
94
|
props,
|
|
115
95
|
});
|
|
116
96
|
dispatchFormChange(
|
|
117
97
|
name,
|
|
118
|
-
|
|
98
|
+
value,
|
|
119
99
|
store.selectFormValues(),
|
|
120
100
|
dispatchEvent,
|
|
121
101
|
);
|
|
@@ -113,6 +113,12 @@ export const selectViewData = ({ state, props, attrs }) => {
|
|
|
113
113
|
if (["read-only-text"].includes(field.inputType)) {
|
|
114
114
|
field.defaultValue = defaultValue
|
|
115
115
|
}
|
|
116
|
+
if (["select"].includes(field.inputType)) {
|
|
117
|
+
const defaultValues = props?.defaultValues;
|
|
118
|
+
if (defaultValues && defaultValues[field.name] !== undefined) {
|
|
119
|
+
field.selectedValue = defaultValues[field.name];
|
|
120
|
+
}
|
|
121
|
+
}
|
|
116
122
|
if (field.inputType === "image") {
|
|
117
123
|
const src = field.src;
|
|
118
124
|
// Only set imageSrc if src exists and is not empty
|
|
@@ -303,25 +303,34 @@ events:
|
|
|
303
303
|
template:
|
|
304
304
|
- rtgl-view w=f p=md g=lg ${containerAttrString}:
|
|
305
305
|
- rtgl-view g=sm w=f:
|
|
306
|
-
-
|
|
307
|
-
|
|
306
|
+
- $if title:
|
|
307
|
+
- rtgl-text s=lg: ${title}
|
|
308
|
+
- $if description:
|
|
309
|
+
- rtgl-text c=mu-fg: ${description}
|
|
308
310
|
- rtgl-view g=lg w=f:
|
|
309
311
|
- $for field, i in fields:
|
|
310
312
|
- rtgl-view g=md w=f:
|
|
311
|
-
-
|
|
312
|
-
- rtgl-view
|
|
313
|
-
- rtgl-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
313
|
+
- $if field.label || field.description:
|
|
314
|
+
- rtgl-view g=sm:
|
|
315
|
+
- rtgl-view d=h g=md av=c:
|
|
316
|
+
- $if field.label:
|
|
317
|
+
- rtgl-text: ${field.label}
|
|
318
|
+
- $if field.label && field.tooltip:
|
|
319
|
+
- rtgl-svg#tooltip-icon-${field.name} svg="info" wh=16 c=mu-fg cur=help ml=xs:
|
|
320
|
+
- $if field.description:
|
|
321
|
+
- rtgl-text s=sm c=mu-fg: ${field.description}
|
|
317
322
|
- $if field.inputType == "read-only-text":
|
|
318
323
|
- rtgl-text s=sm: ${field.defaultValue}
|
|
319
|
-
- $if field.inputType == "inputText":
|
|
320
|
-
- rtgl-input#field-${field.name} w=f:
|
|
324
|
+
- $if field.inputType == "inputText" || field.inputType == 'input-text':
|
|
325
|
+
- rtgl-input#field-${field.name} w=f min=${field.min} max=${field.max} step=${field.step}:
|
|
326
|
+
- $if field.inputType == "input-number":
|
|
327
|
+
- rtgl-input-number#field-${field.name} w=f:
|
|
328
|
+
- $if field.inputType == "input-textarea":
|
|
329
|
+
- rtgl-textarea#field-${field.name} w=f rows=${field.rows} w=f:
|
|
321
330
|
- $if field.inputType == "popover-input":
|
|
322
331
|
- rtgl-popover-input#field-${field.name} label="${field.label}":
|
|
323
332
|
- $if field.inputType == "select":
|
|
324
|
-
- rtgl-select#field-${field.name} key=${key} w=f .options=fields[${i}].options ?no-clear=fields[${i}].noClear .addOption=fields[${i}].addOption:
|
|
333
|
+
- rtgl-select#field-${field.name} key=${key} w=f .options=fields[${i}].options ?no-clear=fields[${i}].noClear .addOption=fields[${i}].addOption .selectedValue=#{field.selectedValue} .placeholder=#{field.placeholder}:
|
|
325
334
|
- $if field.inputType == "colorPicker":
|
|
326
335
|
- rtgl-color-picker#field-${field.name} key=${key}:
|
|
327
336
|
- $if field.inputType == "slider":
|
|
@@ -42,7 +42,7 @@ export const selectViewData = ({ state, props, attrs }) => {
|
|
|
42
42
|
const currentValue = state.selectedValue !== null ? state.selectedValue : props.selectedValue;
|
|
43
43
|
|
|
44
44
|
// Calculate display label from value
|
|
45
|
-
let displayLabel = attrs.placeholder || 'Select an option';
|
|
45
|
+
let displayLabel = props.placeholder || attrs.placeholder || 'Select an option';
|
|
46
46
|
let isPlaceholderLabel = true;
|
|
47
47
|
|
|
48
48
|
const options = props.options || [];
|
package/src/entry-iife-layout.js
CHANGED
|
@@ -4,6 +4,7 @@ import RettangoliText from './primitives/text.js';
|
|
|
4
4
|
import RettangoliImage from './primitives/image.js';
|
|
5
5
|
import RettangoliSvg from './primitives/svg.js';
|
|
6
6
|
import RettangoliInput from './primitives/input.js';
|
|
7
|
+
import RettangoliInputNumber from './primitives/input-number.js';
|
|
7
8
|
import RettangoliTextArea from './primitives/textarea.js';
|
|
8
9
|
import RettangoliDialog from './primitives/dialog.js';
|
|
9
10
|
|
|
@@ -14,5 +15,6 @@ customElements.define("rtgl-text", RettangoliText({}));
|
|
|
14
15
|
customElements.define("rtgl-image", RettangoliImage({}));
|
|
15
16
|
customElements.define("rtgl-svg", RettangoliSvg({}));
|
|
16
17
|
customElements.define("rtgl-input", RettangoliInput({}));
|
|
18
|
+
customElements.define("rtgl-input-number", RettangoliInputNumber({}));
|
|
17
19
|
customElements.define("rtgl-textarea", RettangoliTextArea({}));
|
|
18
20
|
customElements.define("rtgl-dialog", RettangoliDialog({}));
|
package/src/entry-iife-ui.js
CHANGED
|
@@ -4,6 +4,7 @@ import RettangoliText from './primitives/text.js';
|
|
|
4
4
|
import RettangoliImage from './primitives/image.js';
|
|
5
5
|
import RettangoliSvg from './primitives/svg.js';
|
|
6
6
|
import RettangoliInput from './primitives/input.js';
|
|
7
|
+
import RettangoliInputNumber from './primitives/input-number.js';
|
|
7
8
|
import RettangoliTextArea from './primitives/textarea.js';
|
|
8
9
|
import RettangoliColorPicker from './primitives/colorPicker.js';
|
|
9
10
|
import RettangoliSlider from './primitives/slider.js';
|
|
@@ -16,6 +17,7 @@ customElements.define("rtgl-text", RettangoliText({}));
|
|
|
16
17
|
customElements.define("rtgl-image", RettangoliImage({}));
|
|
17
18
|
customElements.define("rtgl-svg", RettangoliSvg({}));
|
|
18
19
|
customElements.define("rtgl-input", RettangoliInput({}));
|
|
20
|
+
customElements.define("rtgl-input-number", RettangoliInputNumber({}));
|
|
19
21
|
customElements.define("rtgl-textarea", RettangoliTextArea({}));
|
|
20
22
|
customElements.define("rtgl-color-picker", RettangoliColorPicker({}));
|
|
21
23
|
customElements.define("rtgl-slider", RettangoliSlider({}));
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import RettangoliText from './primitives/text.js';
|
|
|
4
4
|
import RettangoliImage from './primitives/image.js';
|
|
5
5
|
import RettangoliSvg from './primitives/svg.js';
|
|
6
6
|
import RettangoliInput from './primitives/input.js';
|
|
7
|
+
import RettangoliInputNumber from './primitives/input-number.js';
|
|
7
8
|
import RettangoliTextArea from './primitives/textarea.js';
|
|
8
9
|
import RettangoliDialog from './primitives/dialog.js';
|
|
9
10
|
import RettangoliPopover from './primitives/popover.js';
|
|
@@ -16,6 +17,7 @@ export {
|
|
|
16
17
|
RettangoliImage,
|
|
17
18
|
RettangoliSvg,
|
|
18
19
|
RettangoliInput,
|
|
20
|
+
RettangoliInputNumber,
|
|
19
21
|
RettangoliTextArea,
|
|
20
22
|
RettangoliDialog,
|
|
21
23
|
RettangoliPopover,
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import {
|
|
2
|
+
css,
|
|
3
|
+
dimensionWithUnit,
|
|
4
|
+
convertObjectToCssString,
|
|
5
|
+
styleMapKeys,
|
|
6
|
+
permutateBreakpoints,
|
|
7
|
+
} from "../common.js";
|
|
8
|
+
import cursorStyles from "../styles/cursorStyles.js";
|
|
9
|
+
import marginStyles from "../styles/marginStyles.js";
|
|
10
|
+
|
|
11
|
+
// Internal implementation without uhtml
|
|
12
|
+
class RettangoliInputNumberElement extends HTMLElement {
|
|
13
|
+
static styleSheet = null;
|
|
14
|
+
|
|
15
|
+
static initializeStyleSheet() {
|
|
16
|
+
if (!RettangoliInputNumberElement.styleSheet) {
|
|
17
|
+
RettangoliInputNumberElement.styleSheet = new CSSStyleSheet();
|
|
18
|
+
RettangoliInputNumberElement.styleSheet.replaceSync(css`
|
|
19
|
+
:host {
|
|
20
|
+
display: contents;
|
|
21
|
+
}
|
|
22
|
+
input {
|
|
23
|
+
background-color: var(--background);
|
|
24
|
+
font-size: var(--sm-font-size);
|
|
25
|
+
font-weight: var(--sm-font-weight);
|
|
26
|
+
line-height: var(--sm-line-height);
|
|
27
|
+
letter-spacing: var(--sm-letter-spacing);
|
|
28
|
+
border: 1px solid var(--ring);
|
|
29
|
+
border-radius: var(--border-radius-lg);
|
|
30
|
+
padding-left: var(--spacing-md);
|
|
31
|
+
padding-right: var(--spacing-md);
|
|
32
|
+
height: 32px;
|
|
33
|
+
color: var(--foreground);
|
|
34
|
+
outline: none;
|
|
35
|
+
}
|
|
36
|
+
:host([s="sm"]) input {
|
|
37
|
+
font-size: var(--xs-font-size);
|
|
38
|
+
font-weight: var(--xs-font-weight);
|
|
39
|
+
line-height: var(--xs-line-height);
|
|
40
|
+
letter-spacing: var(--xs-letter-spacing);
|
|
41
|
+
padding-left: var(--spacing-md);
|
|
42
|
+
padding-right: var(--spacing-md);
|
|
43
|
+
height: 24px;
|
|
44
|
+
}
|
|
45
|
+
input:focus {
|
|
46
|
+
border-color: var(--foreground);
|
|
47
|
+
}
|
|
48
|
+
input:disabled {
|
|
49
|
+
cursor: not-allowed;
|
|
50
|
+
}
|
|
51
|
+
${marginStyles}
|
|
52
|
+
${cursorStyles}
|
|
53
|
+
`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
constructor() {
|
|
58
|
+
super();
|
|
59
|
+
RettangoliInputNumberElement.initializeStyleSheet();
|
|
60
|
+
this.shadow = this.attachShadow({ mode: "closed" });
|
|
61
|
+
this.shadow.adoptedStyleSheets = [RettangoliInputNumberElement.styleSheet];
|
|
62
|
+
|
|
63
|
+
// Initialize style tracking properties
|
|
64
|
+
this._styles = {
|
|
65
|
+
default: {},
|
|
66
|
+
sm: {},
|
|
67
|
+
md: {},
|
|
68
|
+
lg: {},
|
|
69
|
+
xl: {},
|
|
70
|
+
};
|
|
71
|
+
this._lastStyleString = "";
|
|
72
|
+
|
|
73
|
+
// Create initial DOM structure
|
|
74
|
+
this._inputElement = document.createElement('input');
|
|
75
|
+
this._styleElement = document.createElement('style');
|
|
76
|
+
|
|
77
|
+
this.shadow.appendChild(this._styleElement);
|
|
78
|
+
this.shadow.appendChild(this._inputElement);
|
|
79
|
+
|
|
80
|
+
// Bind event handler
|
|
81
|
+
this._inputElement.addEventListener('input', this._onChange);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
static get observedAttributes() {
|
|
85
|
+
return [
|
|
86
|
+
"key",
|
|
87
|
+
"type",
|
|
88
|
+
"placeholder",
|
|
89
|
+
"disabled",
|
|
90
|
+
"value",
|
|
91
|
+
"step",
|
|
92
|
+
"min",
|
|
93
|
+
"max",
|
|
94
|
+
"s",
|
|
95
|
+
...permutateBreakpoints([
|
|
96
|
+
...styleMapKeys,
|
|
97
|
+
"wh",
|
|
98
|
+
"w",
|
|
99
|
+
"h",
|
|
100
|
+
"hide",
|
|
101
|
+
"show",
|
|
102
|
+
"op",
|
|
103
|
+
"z",
|
|
104
|
+
])
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
get value() {
|
|
109
|
+
return this._inputElement.value;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
set value(newValue) {
|
|
113
|
+
this._inputElement.value = newValue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
focus() {
|
|
117
|
+
this._inputElement.focus();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
_onChange = (event) => {
|
|
121
|
+
const inputValue = this._inputElement.value;
|
|
122
|
+
let numericValue = parseFloat(inputValue);
|
|
123
|
+
|
|
124
|
+
// Only process if the value is a valid number (not NaN)
|
|
125
|
+
if (!isNaN(numericValue)) {
|
|
126
|
+
// Enforce minimum value if set
|
|
127
|
+
const minAttr = this.getAttribute("min");
|
|
128
|
+
if (minAttr !== null) {
|
|
129
|
+
const minValue = parseFloat(minAttr);
|
|
130
|
+
if (!isNaN(minValue) && numericValue < minValue) {
|
|
131
|
+
numericValue = minValue;
|
|
132
|
+
this._inputElement.value = minValue.toString();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Enforce maximum value if set
|
|
137
|
+
const maxAttr = this.getAttribute("max");
|
|
138
|
+
if (maxAttr !== null) {
|
|
139
|
+
const maxValue = parseFloat(maxAttr);
|
|
140
|
+
if (!isNaN(maxValue) && numericValue > maxValue) {
|
|
141
|
+
numericValue = maxValue;
|
|
142
|
+
this._inputElement.value = maxValue.toString();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
this.dispatchEvent(new CustomEvent('input-change', {
|
|
147
|
+
detail: {
|
|
148
|
+
value: numericValue,
|
|
149
|
+
},
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
155
|
+
if (name === 'value') {
|
|
156
|
+
requestAnimationFrame((() => {
|
|
157
|
+
const value = this.getAttribute("value");
|
|
158
|
+
this._inputElement.value = value ?? "";
|
|
159
|
+
}))
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (name === 'placeholder') {
|
|
163
|
+
requestAnimationFrame((() => {
|
|
164
|
+
const placeholder = this.getAttribute("placeholder");
|
|
165
|
+
if (placeholder === undefined || placeholder === 'null') {
|
|
166
|
+
this._inputElement.removeAttribute('placeholder');
|
|
167
|
+
} else {
|
|
168
|
+
this._inputElement.setAttribute('placeholder', placeholder ?? "");
|
|
169
|
+
}
|
|
170
|
+
}))
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Handle input-specific attributes first
|
|
174
|
+
if (["type", "disabled", "step", "min", "max", "s"].includes(name)) {
|
|
175
|
+
this._updateInputAttributes();
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Reset styles for fresh calculation
|
|
180
|
+
this._styles = {
|
|
181
|
+
default: {},
|
|
182
|
+
sm: {},
|
|
183
|
+
md: {},
|
|
184
|
+
lg: {},
|
|
185
|
+
xl: {},
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
["default", "sm", "md", "lg", "xl"].forEach((size) => {
|
|
189
|
+
const addSizePrefix = (tag) => {
|
|
190
|
+
return `${size === "default" ? "" : `${size}-`}${tag}`;
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const wh = this.getAttribute(addSizePrefix("wh"));
|
|
194
|
+
const width = dimensionWithUnit(
|
|
195
|
+
wh === null ? this.getAttribute(addSizePrefix("w")) : wh,
|
|
196
|
+
);
|
|
197
|
+
const height = dimensionWithUnit(
|
|
198
|
+
wh === null ? this.getAttribute(addSizePrefix("h")) : wh,
|
|
199
|
+
);
|
|
200
|
+
const opacity = this.getAttribute(addSizePrefix("op"));
|
|
201
|
+
const zIndex = this.getAttribute(addSizePrefix("z"));
|
|
202
|
+
|
|
203
|
+
if (zIndex !== null) {
|
|
204
|
+
this._styles[size]["z-index"] = zIndex;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (opacity !== null) {
|
|
208
|
+
this._styles[size].opacity = opacity;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
if (width === "f") {
|
|
212
|
+
this._styles[size].width = "var(--width-stretch)";
|
|
213
|
+
} else if (width !== undefined) {
|
|
214
|
+
this._styles[size].width = width;
|
|
215
|
+
this._styles[size]["min-width"] = width;
|
|
216
|
+
this._styles[size]["max-width"] = width;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (height === "f") {
|
|
220
|
+
this._styles[size].height = "100%";
|
|
221
|
+
} else if (height !== undefined) {
|
|
222
|
+
this._styles[size].height = height;
|
|
223
|
+
this._styles[size]["min-height"] = height;
|
|
224
|
+
this._styles[size]["max-height"] = height;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (this.hasAttribute(addSizePrefix("hide"))) {
|
|
228
|
+
this._styles[size].display = "none !important";
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
if (this.hasAttribute(addSizePrefix("show"))) {
|
|
232
|
+
this._styles[size].display = "block !important";
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Update styles only if changed - targeting input element
|
|
237
|
+
const newStyleString = convertObjectToCssString(this._styles, 'input');
|
|
238
|
+
if (newStyleString !== this._lastStyleString) {
|
|
239
|
+
this._styleElement.textContent = newStyleString;
|
|
240
|
+
this._lastStyleString = newStyleString;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
_updateInputAttributes() {
|
|
245
|
+
const type = this.getAttribute("type") || "number";
|
|
246
|
+
const step = this.getAttribute("step");
|
|
247
|
+
const min = this.getAttribute("min");
|
|
248
|
+
const max = this.getAttribute("max");
|
|
249
|
+
const isDisabled = this.hasAttribute('disabled');
|
|
250
|
+
|
|
251
|
+
this._inputElement.setAttribute("type", type);
|
|
252
|
+
|
|
253
|
+
if (step !== null) {
|
|
254
|
+
this._inputElement.setAttribute("step", step);
|
|
255
|
+
} else {
|
|
256
|
+
this._inputElement.removeAttribute("step");
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (min !== null) {
|
|
260
|
+
this._inputElement.setAttribute("min", min);
|
|
261
|
+
} else {
|
|
262
|
+
this._inputElement.removeAttribute("min");
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (max !== null) {
|
|
266
|
+
this._inputElement.setAttribute("max", max);
|
|
267
|
+
} else {
|
|
268
|
+
this._inputElement.removeAttribute("max");
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (isDisabled) {
|
|
272
|
+
this._inputElement.setAttribute("disabled", "");
|
|
273
|
+
} else {
|
|
274
|
+
this._inputElement.removeAttribute("disabled");
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
connectedCallback() {
|
|
279
|
+
this._updateInputAttributes();
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Export factory function to maintain API compatibility
|
|
284
|
+
export default ({ render, html }) => {
|
|
285
|
+
// Note: render and html parameters are accepted but not used
|
|
286
|
+
// This maintains backward compatibility with existing code
|
|
287
|
+
return RettangoliInputNumberElement;
|
|
288
|
+
};
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
css,
|
|
3
|
+
dimensionWithUnit,
|
|
4
|
+
convertObjectToCssString,
|
|
5
|
+
styleMapKeys,
|
|
6
|
+
permutateBreakpoints,
|
|
7
|
+
} from "../common.js";
|
|
2
8
|
import cursorStyles from "../styles/cursorStyles.js";
|
|
3
9
|
import marginStyles from "../styles/marginStyles.js";
|
|
4
10
|
|
|
@@ -43,10 +49,23 @@ class RettangoliTextAreaElement extends HTMLElement {
|
|
|
43
49
|
RettangoliTextAreaElement.initializeStyleSheet();
|
|
44
50
|
this.shadow = this.attachShadow({ mode: "closed" });
|
|
45
51
|
this.shadow.adoptedStyleSheets = [RettangoliTextAreaElement.styleSheet];
|
|
46
|
-
|
|
52
|
+
|
|
53
|
+
// Initialize style tracking properties
|
|
54
|
+
this._styles = {
|
|
55
|
+
default: {},
|
|
56
|
+
sm: {},
|
|
57
|
+
md: {},
|
|
58
|
+
lg: {},
|
|
59
|
+
xl: {},
|
|
60
|
+
};
|
|
61
|
+
this._lastStyleString = "";
|
|
62
|
+
|
|
47
63
|
// Create initial DOM structure
|
|
48
64
|
this._textareaElement = document.createElement('textarea');
|
|
49
65
|
this._textareaElement.setAttribute('type', 'text');
|
|
66
|
+
this._styleElement = document.createElement('style');
|
|
67
|
+
|
|
68
|
+
this.shadow.appendChild(this._styleElement);
|
|
50
69
|
this.shadow.appendChild(this._textareaElement);
|
|
51
70
|
|
|
52
71
|
// Bind event handler
|
|
@@ -62,7 +81,26 @@ class RettangoliTextAreaElement extends HTMLElement {
|
|
|
62
81
|
};
|
|
63
82
|
|
|
64
83
|
static get observedAttributes() {
|
|
65
|
-
return [
|
|
84
|
+
return [
|
|
85
|
+
"key",
|
|
86
|
+
"type",
|
|
87
|
+
"placeholder",
|
|
88
|
+
"disabled",
|
|
89
|
+
"value",
|
|
90
|
+
"cols",
|
|
91
|
+
"rows",
|
|
92
|
+
"ellipsis",
|
|
93
|
+
...permutateBreakpoints([
|
|
94
|
+
...styleMapKeys,
|
|
95
|
+
"wh",
|
|
96
|
+
"w",
|
|
97
|
+
"h",
|
|
98
|
+
"hide",
|
|
99
|
+
"show",
|
|
100
|
+
"op",
|
|
101
|
+
"z",
|
|
102
|
+
])
|
|
103
|
+
];
|
|
66
104
|
}
|
|
67
105
|
|
|
68
106
|
get value() {
|
|
@@ -78,22 +116,99 @@ class RettangoliTextAreaElement extends HTMLElement {
|
|
|
78
116
|
}
|
|
79
117
|
|
|
80
118
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
requestAnimationFrame(() => {
|
|
119
|
+
if (name === 'value') {
|
|
120
|
+
requestAnimationFrame((() => {
|
|
84
121
|
const value = this.getAttribute("value");
|
|
85
122
|
this._textareaElement.value = value ?? "";
|
|
86
|
-
})
|
|
123
|
+
}))
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (name === 'placeholder') {
|
|
127
|
+
requestAnimationFrame((() => {
|
|
128
|
+
const placeholder = this.getAttribute("placeholder");
|
|
129
|
+
if (placeholder === undefined || placeholder === 'null') {
|
|
130
|
+
this._textareaElement.removeAttribute('placeholder');
|
|
131
|
+
} else {
|
|
132
|
+
this._textareaElement.setAttribute('placeholder', placeholder ?? "");
|
|
133
|
+
}
|
|
134
|
+
}))
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Handle textarea-specific attributes first
|
|
138
|
+
if (["cols", "rows", "disabled"].includes(name)) {
|
|
139
|
+
this._updateTextareaAttributes();
|
|
87
140
|
return;
|
|
88
141
|
}
|
|
89
|
-
|
|
142
|
+
|
|
143
|
+
// Reset styles for fresh calculation
|
|
144
|
+
this._styles = {
|
|
145
|
+
default: {},
|
|
146
|
+
sm: {},
|
|
147
|
+
md: {},
|
|
148
|
+
lg: {},
|
|
149
|
+
xl: {},
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
["default", "sm", "md", "lg", "xl"].forEach((size) => {
|
|
153
|
+
const addSizePrefix = (tag) => {
|
|
154
|
+
return `${size === "default" ? "" : `${size}-`}${tag}`;
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const wh = this.getAttribute(addSizePrefix("wh"));
|
|
158
|
+
const width = dimensionWithUnit(
|
|
159
|
+
wh === null ? this.getAttribute(addSizePrefix("w")) : wh,
|
|
160
|
+
);
|
|
161
|
+
const height = dimensionWithUnit(
|
|
162
|
+
wh === null ? this.getAttribute(addSizePrefix("h")) : wh,
|
|
163
|
+
);
|
|
164
|
+
const opacity = this.getAttribute(addSizePrefix("op"));
|
|
165
|
+
const zIndex = this.getAttribute(addSizePrefix("z"));
|
|
166
|
+
|
|
167
|
+
if (zIndex !== null) {
|
|
168
|
+
this._styles[size]["z-index"] = zIndex;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (opacity !== null) {
|
|
172
|
+
this._styles[size].opacity = opacity;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (width === "f") {
|
|
176
|
+
this._styles[size].width = "var(--width-stretch)";
|
|
177
|
+
} else if (width !== undefined) {
|
|
178
|
+
this._styles[size].width = width;
|
|
179
|
+
this._styles[size]["min-width"] = width;
|
|
180
|
+
this._styles[size]["max-width"] = width;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (height === "f") {
|
|
184
|
+
this._styles[size].height = "100%";
|
|
185
|
+
} else if (height !== undefined) {
|
|
186
|
+
this._styles[size].height = height;
|
|
187
|
+
this._styles[size]["min-height"] = height;
|
|
188
|
+
this._styles[size]["max-height"] = height;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (this.hasAttribute(addSizePrefix("hide"))) {
|
|
192
|
+
this._styles[size].display = "none !important";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (this.hasAttribute(addSizePrefix("show"))) {
|
|
196
|
+
this._styles[size].display = "block !important";
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
// Update styles only if changed - targeting textarea element
|
|
201
|
+
const newStyleString = convertObjectToCssString(this._styles, 'textarea');
|
|
202
|
+
if (newStyleString !== this._lastStyleString) {
|
|
203
|
+
this._styleElement.textContent = newStyleString;
|
|
204
|
+
this._lastStyleString = newStyleString;
|
|
205
|
+
}
|
|
90
206
|
}
|
|
91
207
|
|
|
92
208
|
_updateTextareaAttributes() {
|
|
93
209
|
const cols = this.getAttribute("cols");
|
|
94
210
|
const rows = this.getAttribute("rows");
|
|
95
|
-
const
|
|
96
|
-
const value = this.getAttribute("value");
|
|
211
|
+
const isDisabled = this.hasAttribute('disabled');
|
|
97
212
|
|
|
98
213
|
if (cols !== null) {
|
|
99
214
|
this._textareaElement.setAttribute("cols", cols);
|
|
@@ -107,14 +222,10 @@ class RettangoliTextAreaElement extends HTMLElement {
|
|
|
107
222
|
this._textareaElement.removeAttribute("rows");
|
|
108
223
|
}
|
|
109
224
|
|
|
110
|
-
if (
|
|
111
|
-
this._textareaElement.setAttribute("
|
|
225
|
+
if (isDisabled) {
|
|
226
|
+
this._textareaElement.setAttribute("disabled", "");
|
|
112
227
|
} else {
|
|
113
|
-
this._textareaElement.removeAttribute("
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
if (value !== null) {
|
|
117
|
-
this._textareaElement.value = value;
|
|
228
|
+
this._textareaElement.removeAttribute("disabled");
|
|
118
229
|
}
|
|
119
230
|
}
|
|
120
231
|
}
|