@rettangoli/ui 0.1.19 → 0.1.21
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 -4
- package/src/components/form/form.view.yaml +10 -4
- package/src/components/select/select.handlers.js +4 -4
- package/src/components/select/select.store.js +7 -7
- 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) {
|
|
@@ -108,14 +108,15 @@ export const handleInputChange = (deps, payload) => {
|
|
|
108
108
|
const event = payload._event;
|
|
109
109
|
let name = event.currentTarget.id.replace("field-", "");
|
|
110
110
|
if (name && event.detail.value !== undefined) {
|
|
111
|
+
const value = event.detail.value
|
|
111
112
|
store.setFormFieldValue({
|
|
112
113
|
name: name,
|
|
113
|
-
value
|
|
114
|
+
value,
|
|
114
115
|
props,
|
|
115
116
|
});
|
|
116
117
|
dispatchFormChange(
|
|
117
118
|
name,
|
|
118
|
-
|
|
119
|
+
value,
|
|
119
120
|
store.selectFormValues(),
|
|
120
121
|
dispatchEvent,
|
|
121
122
|
);
|
|
@@ -303,8 +303,10 @@ 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:
|
|
@@ -316,8 +318,12 @@ template:
|
|
|
316
318
|
- rtgl-text s=sm c=mu-fg: ${field.description}
|
|
317
319
|
- $if field.inputType == "read-only-text":
|
|
318
320
|
- rtgl-text s=sm: ${field.defaultValue}
|
|
319
|
-
- $if field.inputType == "inputText":
|
|
320
|
-
- rtgl-input#field-${field.name} w=f:
|
|
321
|
+
- $if field.inputType == "inputText" || field.inputType == 'input-text':
|
|
322
|
+
- rtgl-input#field-${field.name} w=f min=${field.min} max=${field.max} step=${field.step}:
|
|
323
|
+
- $if field.inputType == "input-number":
|
|
324
|
+
- rtgl-input-number#field-${field.name} w=f:
|
|
325
|
+
- $if field.inputType == "input-textarea":
|
|
326
|
+
- rtgl-textarea#field-${field.name} w=f rows=${field.rows} w=f:
|
|
321
327
|
- $if field.inputType == "popover-input":
|
|
322
328
|
- rtgl-popover-input#field-${field.name} label="${field.label}":
|
|
323
329
|
- $if field.inputType == "select":
|
|
@@ -16,7 +16,7 @@ export const handleBeforeMount = (deps) => {
|
|
|
16
16
|
|
|
17
17
|
export const handleOnUpdate = (deps, payload) => {
|
|
18
18
|
const { oldAttrs, newAttrs, oldProps, newProps } = payload;
|
|
19
|
-
const { store,
|
|
19
|
+
const { store, render } = deps;
|
|
20
20
|
|
|
21
21
|
// Check if key changed
|
|
22
22
|
if (oldAttrs?.key !== newAttrs?.key && newAttrs?.key) {
|
|
@@ -24,8 +24,8 @@ export const handleOnUpdate = (deps, payload) => {
|
|
|
24
24
|
store.resetSelection();
|
|
25
25
|
|
|
26
26
|
// Re-apply the prop value if available
|
|
27
|
-
const selectedValue = newProps?.selectedValue
|
|
28
|
-
const options = newProps?.options ||
|
|
27
|
+
const selectedValue = newProps?.selectedValue;
|
|
28
|
+
const options = newProps?.options || [];
|
|
29
29
|
|
|
30
30
|
if (selectedValue !== null && selectedValue !== undefined && options) {
|
|
31
31
|
const selectedOption = options.find(opt => deepEqual(opt.value, selectedValue));
|
|
@@ -37,7 +37,7 @@ export const handleOnUpdate = (deps, payload) => {
|
|
|
37
37
|
}
|
|
38
38
|
render();
|
|
39
39
|
} else if (oldProps.selectedValue !== newProps.selectedValue) {
|
|
40
|
-
store.updateSelectedValue(newProps.selectedValue);
|
|
40
|
+
store.updateSelectedValue({ value: newProps.selectedValue });
|
|
41
41
|
render();
|
|
42
42
|
}
|
|
43
43
|
}
|
|
@@ -44,16 +44,16 @@ export const selectViewData = ({ state, props, attrs }) => {
|
|
|
44
44
|
// Calculate display label from value
|
|
45
45
|
let displayLabel = attrs.placeholder || 'Select an option';
|
|
46
46
|
let isPlaceholderLabel = true;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
|
|
48
|
+
const options = props.options || [];
|
|
49
|
+
const selectedOption = options.find(opt => deepEqual(opt.value, currentValue));
|
|
50
|
+
if (selectedOption) {
|
|
51
|
+
displayLabel = selectedOption.label;
|
|
52
|
+
isPlaceholderLabel = false;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
// Map options to include isSelected flag and computed background color
|
|
56
|
-
const optionsWithSelection =
|
|
56
|
+
const optionsWithSelection = options.map((option, index) => {
|
|
57
57
|
const isSelected = deepEqual(option.value, currentValue);
|
|
58
58
|
const isHovered = state.hoveredOptionId === index;
|
|
59
59
|
return {
|
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
|
}
|