@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rettangoli/ui",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "A UI component library for building web interfaces.",
5
5
  "main": "dist/rettangoli-esm.min.js",
6
6
  "type": "module",
@@ -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 (field.inputType === 'inputText' && field.placeholder) {
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: event.detail.value,
93
+ value,
114
94
  props,
115
95
  });
116
96
  dispatchFormChange(
117
97
  name,
118
- event.detail.value,
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
- - rtgl-text s=lg: ${title}
307
- - rtgl-text c=mu-fg: ${description}
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
- - rtgl-view g=sm:
312
- - rtgl-view d=h g=md av=c:
313
- - rtgl-text: ${field.label}
314
- - $if field.tooltip:
315
- - rtgl-svg#tooltip-icon-${field.name} svg="info" wh=16 c=mu-fg cur=help ml=xs:
316
- - rtgl-text s=sm c=mu-fg: ${field.description}
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 || [];
@@ -12,6 +12,8 @@ attrsSchema:
12
12
  propsSchema:
13
13
  type: object
14
14
  properties:
15
+ placeholder:
16
+ type: string
15
17
  options:
16
18
  type: array
17
19
  items:
@@ -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({}));
@@ -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 { css, dimensionWithUnit } from "../common.js";
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 ["key", "w", "ellipsis", "cols", "rows", "placeholder", "value"];
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
- // Handle key attribute change - reset value
82
- if (name === "key" && oldValue !== newValue) {
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
- this._updateTextareaAttributes();
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 placeholder = this.getAttribute("placeholder");
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 (placeholder !== null) {
111
- this._textareaElement.setAttribute("placeholder", placeholder);
225
+ if (isDisabled) {
226
+ this._textareaElement.setAttribute("disabled", "");
112
227
  } else {
113
- this._textareaElement.removeAttribute("placeholder");
114
- }
115
-
116
- if (value !== null) {
117
- this._textareaElement.value = value;
228
+ this._textareaElement.removeAttribute("disabled");
118
229
  }
119
230
  }
120
231
  }