@uistate/core 2.0.1 → 3.0.0
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 +39 -103
- package/package.json +1 -1
- package/src/cssState.js +53 -9
- package/src/index.js +282 -40
- package/src/stateInspector.js +140 -0
- package/src/stateSerializer.js +204 -0
- package/src/telemetryPlugin.js +638 -0
- package/src/templateManager.js +119 -0
package/src/templateManager.js
CHANGED
|
@@ -12,6 +12,52 @@ const createTemplateManager = (stateManager) => {
|
|
|
12
12
|
return this;
|
|
13
13
|
},
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Register multiple actions with their handlers in a declarative way
|
|
17
|
+
* @param {Object} actionsMap - Map of action names to handlers or handler configs
|
|
18
|
+
* @returns {Object} - The manager instance for chaining
|
|
19
|
+
*
|
|
20
|
+
* Example usage:
|
|
21
|
+
* templateManager.registerActions({
|
|
22
|
+
* 'add-item': addItem,
|
|
23
|
+
* 'delete-item': { fn: deleteItem, extractId: true },
|
|
24
|
+
* 'toggle-state': toggleState
|
|
25
|
+
* });
|
|
26
|
+
*/
|
|
27
|
+
registerActions(actionsMap) {
|
|
28
|
+
Object.entries(actionsMap).forEach(([action, handler]) => {
|
|
29
|
+
if (typeof handler === 'function') {
|
|
30
|
+
// Simple function handler
|
|
31
|
+
this.onAction(action, handler);
|
|
32
|
+
} else if (typeof handler === 'object' && handler !== null) {
|
|
33
|
+
// Handler with configuration
|
|
34
|
+
const { fn, extractId = true, idAttribute = 'id' } = handler;
|
|
35
|
+
|
|
36
|
+
if (typeof fn !== 'function') {
|
|
37
|
+
throw new Error(`Handler for action '${action}' must be a function`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.onAction(action, (e) => {
|
|
41
|
+
if (extractId) {
|
|
42
|
+
const target = e.target.closest('[data-action]');
|
|
43
|
+
// Look for common ID attributes in order of preference
|
|
44
|
+
const id = target.dataset[idAttribute] ||
|
|
45
|
+
target.dataset.actionId ||
|
|
46
|
+
target.dataset.cardId ||
|
|
47
|
+
target.dataset.itemId;
|
|
48
|
+
|
|
49
|
+
fn(id, e, target);
|
|
50
|
+
} else {
|
|
51
|
+
fn(e);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error(`Invalid handler for action '${action}'`);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return this;
|
|
59
|
+
},
|
|
60
|
+
|
|
15
61
|
attachDelegation(root = document.body) {
|
|
16
62
|
root.addEventListener('click', e => {
|
|
17
63
|
const target = e.target.closest('[data-action]');
|
|
@@ -31,6 +77,36 @@ const createTemplateManager = (stateManager) => {
|
|
|
31
77
|
return this;
|
|
32
78
|
},
|
|
33
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Render a template from a CSS variable
|
|
82
|
+
* @param {string} templateName - Name of the template (will be prefixed with --template-)
|
|
83
|
+
* @param {Object} data - Data to inject into the template
|
|
84
|
+
* @returns {HTMLElement} - The rendered element
|
|
85
|
+
*/
|
|
86
|
+
renderTemplateFromCss(templateName, data = {}) {
|
|
87
|
+
const cssTemplate = getComputedStyle(document.documentElement)
|
|
88
|
+
.getPropertyValue(`--template-${templateName}`)
|
|
89
|
+
.trim()
|
|
90
|
+
.replace(/^['"]|['"]$/g, ''); // Remove surrounding quotes
|
|
91
|
+
|
|
92
|
+
if (!cssTemplate) throw new Error(`Template not found in CSS: --template-${templateName}`);
|
|
93
|
+
|
|
94
|
+
let html = cssTemplate;
|
|
95
|
+
|
|
96
|
+
// Replace all placeholders with actual data
|
|
97
|
+
Object.entries(data).forEach(([key, value]) => {
|
|
98
|
+
const regex = new RegExp(`{{${key}}}`, 'g');
|
|
99
|
+
html = html.replace(regex, value);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Create a temporary container
|
|
103
|
+
const temp = document.createElement('div');
|
|
104
|
+
temp.innerHTML = html;
|
|
105
|
+
|
|
106
|
+
// Return the first child (the rendered template)
|
|
107
|
+
return temp.firstElementChild;
|
|
108
|
+
},
|
|
109
|
+
|
|
34
110
|
mount(componentName, container) {
|
|
35
111
|
const tpl = document.getElementById(`${componentName}-template`);
|
|
36
112
|
if (!tpl) throw new Error(`Template not found: ${componentName}-template`);
|
|
@@ -84,6 +160,49 @@ const createTemplateManager = (stateManager) => {
|
|
|
84
160
|
return {
|
|
85
161
|
mount: (container) => this.mount(name, container)
|
|
86
162
|
};
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Apply CSS classes to an element based on a state key stored in CSS variables
|
|
167
|
+
* @param {HTMLElement} element - Element to apply classes to
|
|
168
|
+
* @param {string} stateKey - State key to look up in CSS variables
|
|
169
|
+
* @param {Object} options - Options for class application
|
|
170
|
+
* @returns {HTMLElement} - The element for chaining
|
|
171
|
+
*
|
|
172
|
+
* Example usage:
|
|
173
|
+
* // CSS: :root { --card-primary-classes: "bg-primary text-white"; }
|
|
174
|
+
* templateManager.applyClassesFromState(cardElement, 'card-primary');
|
|
175
|
+
*/
|
|
176
|
+
applyClassesFromState(element, stateKey, options = {}) {
|
|
177
|
+
if (!element) return element;
|
|
178
|
+
|
|
179
|
+
const {
|
|
180
|
+
prefix = '',
|
|
181
|
+
clearExisting = false,
|
|
182
|
+
namespace = ''
|
|
183
|
+
} = typeof options === 'string' ? { prefix: options } : options;
|
|
184
|
+
|
|
185
|
+
const prefixPath = prefix ? `${prefix}-` : '';
|
|
186
|
+
const namespacePath = namespace ? `${namespace}-` : '';
|
|
187
|
+
|
|
188
|
+
const classString = getComputedStyle(document.documentElement)
|
|
189
|
+
.getPropertyValue(`--${namespacePath}${stateKey}-classes`)
|
|
190
|
+
.trim()
|
|
191
|
+
.replace(/^['"]|['"]$/g, '');
|
|
192
|
+
|
|
193
|
+
if (classString) {
|
|
194
|
+
// Clear existing classes if specified
|
|
195
|
+
if (clearExisting) {
|
|
196
|
+
element.className = '';
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// Add new classes
|
|
200
|
+
classString.split(' ').forEach(cls => {
|
|
201
|
+
if (cls) element.classList.add(cls);
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return element; // For chaining
|
|
87
206
|
}
|
|
88
207
|
};
|
|
89
208
|
|