web-manager 4.0.22 → 4.0.23
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/README.md +25 -1
- package/dist/modules/bindings.js +82 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -379,13 +379,37 @@ When an element is bound, Web Manager automatically adds the `wm-bound` class to
|
|
|
379
379
|
}
|
|
380
380
|
```
|
|
381
381
|
|
|
382
|
+
#### Style Bindings
|
|
383
|
+
Set CSS custom properties (CSS variables) or inline styles dynamically:
|
|
384
|
+
|
|
385
|
+
```html
|
|
386
|
+
<!-- Set CSS custom property -->
|
|
387
|
+
<div data-wm-bind="@style --rating-percent site.ratings.starWidth"></div>
|
|
388
|
+
|
|
389
|
+
<!-- Set regular style property -->
|
|
390
|
+
<div data-wm-bind="@style width user.profile.width"></div>
|
|
391
|
+
|
|
392
|
+
<!-- Multiple styles -->
|
|
393
|
+
<div data-wm-bind="@style --primary-color theme.primaryColor, @style --secondary-color theme.secondaryColor"></div>
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Then use the custom property in your CSS:
|
|
397
|
+
|
|
398
|
+
```css
|
|
399
|
+
.rating-stars::before {
|
|
400
|
+
width: var(--rating-percent, 0%);
|
|
401
|
+
background: var(--primary-color, #007bff);
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
382
405
|
#### Supported Actions
|
|
383
406
|
- **`@text`** (default): Sets the text content of the element
|
|
384
407
|
- **`@show`**: Shows the element when condition is true
|
|
385
408
|
- **`@hide`**: Hides the element when condition is true
|
|
386
409
|
- **`@attr`**: Sets an attribute value (format: `@attr attributeName expression`)
|
|
410
|
+
- **`@style`**: Sets a CSS custom property or inline style (format: `@style propertyName expression`)
|
|
387
411
|
|
|
388
|
-
Future actions like `@class`
|
|
412
|
+
Future actions like `@class` can be easily added.
|
|
389
413
|
|
|
390
414
|
### Firebase Authentication
|
|
391
415
|
|
package/dist/modules/bindings.js
CHANGED
|
@@ -13,7 +13,10 @@ class Bindings {
|
|
|
13
13
|
...data
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// Get the top-level keys that were updated
|
|
17
|
+
const updatedKeys = Object.keys(data);
|
|
18
|
+
|
|
19
|
+
this._updateBindings(this._context, updatedKeys);
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
// Get current context
|
|
@@ -24,11 +27,11 @@ class Bindings {
|
|
|
24
27
|
// Clear all context
|
|
25
28
|
clear() {
|
|
26
29
|
this._context = {};
|
|
27
|
-
this._updateBindings(this._context);
|
|
30
|
+
this._updateBindings(this._context, null); // null = update all bindings
|
|
28
31
|
}
|
|
29
32
|
|
|
30
33
|
// Main binding update system
|
|
31
|
-
_updateBindings(context) {
|
|
34
|
+
_updateBindings(context, updatedKeys = null) {
|
|
32
35
|
// Find all elements with data-wm-bind attribute
|
|
33
36
|
const bindElements = document.querySelectorAll('[data-wm-bind]');
|
|
34
37
|
|
|
@@ -40,16 +43,16 @@ class Bindings {
|
|
|
40
43
|
|
|
41
44
|
// Execute each action
|
|
42
45
|
bindings.forEach(({ action, expression }) => {
|
|
43
|
-
this._executeAction(element, action, expression, context);
|
|
46
|
+
this._executeAction(element, action, expression, context, updatedKeys);
|
|
44
47
|
});
|
|
45
48
|
|
|
46
|
-
//
|
|
47
|
-
element.classList.
|
|
49
|
+
// Add bound class to trigger fade out
|
|
50
|
+
element.classList.add('wm-bound');
|
|
48
51
|
|
|
49
|
-
//
|
|
52
|
+
// Remove skeleton class after fade completes
|
|
50
53
|
setTimeout(() => {
|
|
51
|
-
element.classList.
|
|
52
|
-
},
|
|
54
|
+
element.classList.remove('wm-binding-skeleton');
|
|
55
|
+
}, 300);
|
|
53
56
|
});
|
|
54
57
|
}
|
|
55
58
|
|
|
@@ -85,10 +88,16 @@ class Bindings {
|
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
// Execute a single action on an element
|
|
88
|
-
_executeAction(element, action, expression, context) {
|
|
91
|
+
_executeAction(element, action, expression, context, updatedKeys = null) {
|
|
89
92
|
switch (action) {
|
|
90
93
|
case '@show':
|
|
91
94
|
// Show element if condition is true (or always if no condition)
|
|
95
|
+
|
|
96
|
+
// Check if this path should be updated
|
|
97
|
+
if (!this._shouldUpdatePath(expression, updatedKeys)) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
92
101
|
const shouldShow = expression ? this._evaluateCondition(expression, context) : true;
|
|
93
102
|
if (shouldShow) {
|
|
94
103
|
element.removeAttribute('hidden');
|
|
@@ -99,6 +108,12 @@ class Bindings {
|
|
|
99
108
|
|
|
100
109
|
case '@hide':
|
|
101
110
|
// Hide element if condition is true (or always if no condition)
|
|
111
|
+
|
|
112
|
+
// Check if this path should be updated
|
|
113
|
+
if (!this._shouldUpdatePath(expression, updatedKeys)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
102
117
|
const shouldHide = expression ? this._evaluateCondition(expression, context) : true;
|
|
103
118
|
if (shouldHide) {
|
|
104
119
|
element.setAttribute('hidden', '');
|
|
@@ -113,6 +128,12 @@ class Bindings {
|
|
|
113
128
|
const attrParts = expression.split(' ');
|
|
114
129
|
const attrName = attrParts[0];
|
|
115
130
|
const attrExpression = attrParts.slice(1).join(' ');
|
|
131
|
+
|
|
132
|
+
// Check if this path should be updated
|
|
133
|
+
if (!this._shouldUpdatePath(attrExpression, updatedKeys)) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
116
137
|
const attrValue = this._resolvePath(context, attrExpression) || '';
|
|
117
138
|
|
|
118
139
|
if (attrValue) {
|
|
@@ -122,9 +143,47 @@ class Bindings {
|
|
|
122
143
|
}
|
|
123
144
|
break;
|
|
124
145
|
|
|
146
|
+
case '@style':
|
|
147
|
+
// Set CSS custom property or style
|
|
148
|
+
// Format: @style propertyName expression
|
|
149
|
+
const styleParts = expression.split(' ');
|
|
150
|
+
const styleName = styleParts[0];
|
|
151
|
+
const styleExpression = styleParts.slice(1).join(' ');
|
|
152
|
+
|
|
153
|
+
// Check if this path should be updated
|
|
154
|
+
if (!this._shouldUpdatePath(styleExpression, updatedKeys)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const styleValue = this._resolvePath(context, styleExpression);
|
|
159
|
+
|
|
160
|
+
if (styleValue !== null && styleValue !== undefined && styleValue !== '') {
|
|
161
|
+
// If it starts with --, it's a CSS custom property
|
|
162
|
+
if (styleName.startsWith('--')) {
|
|
163
|
+
element.style.setProperty(styleName, styleValue);
|
|
164
|
+
} else {
|
|
165
|
+
// Regular style property
|
|
166
|
+
element.style[styleName] = styleValue;
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
// Remove the style if value is empty
|
|
170
|
+
if (styleName.startsWith('--')) {
|
|
171
|
+
element.style.removeProperty(styleName);
|
|
172
|
+
} else {
|
|
173
|
+
element.style[styleName] = '';
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
|
|
125
178
|
case '@text':
|
|
126
179
|
default:
|
|
127
180
|
// Set text content (default behavior)
|
|
181
|
+
|
|
182
|
+
// Check if this path should be updated
|
|
183
|
+
if (!this._shouldUpdatePath(expression, updatedKeys)) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
128
187
|
const value = this._resolvePath(context, expression) || '';
|
|
129
188
|
|
|
130
189
|
if (element.tagName === 'INPUT' || element.tagName === 'TEXTAREA') {
|
|
@@ -133,11 +192,21 @@ class Bindings {
|
|
|
133
192
|
element.textContent = value;
|
|
134
193
|
}
|
|
135
194
|
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
136
197
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
198
|
+
// Check if a path should be updated based on updatedKeys
|
|
199
|
+
_shouldUpdatePath(path, updatedKeys) {
|
|
200
|
+
// If no updatedKeys filter, always update
|
|
201
|
+
if (updatedKeys === null || !path) {
|
|
202
|
+
return true;
|
|
140
203
|
}
|
|
204
|
+
|
|
205
|
+
// Extract the root key from the path
|
|
206
|
+
const rootKey = path.trim().split('.')[0];
|
|
207
|
+
|
|
208
|
+
// Only update if the root key is in updatedKeys
|
|
209
|
+
return updatedKeys.includes(rootKey);
|
|
141
210
|
}
|
|
142
211
|
|
|
143
212
|
// Resolve nested object path
|
package/package.json
CHANGED