@cocreate/state 1.24.8 → 1.25.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/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/src/index.js +224 -200
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [1.25.0](https://github.com/CoCreate-app/CoCreate-state/compare/v1.24.9...v1.25.0) (2026-02-28)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* state suports local and session storage ([fab140f](https://github.com/CoCreate-app/CoCreate-state/commit/fab140f9c660d55a0d3819c18bf99635f5e024f5))
|
|
7
|
+
|
|
8
|
+
## [1.24.9](https://github.com/CoCreate-app/CoCreate-state/compare/v1.24.8...v1.24.9) (2026-02-25)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* Update logo image source in menu component ([aa18b61](https://github.com/CoCreate-app/CoCreate-state/commit/aa18b615d1753373dc1f710696f4c9dd11d957d6))
|
|
14
|
+
|
|
1
15
|
## [1.24.8](https://github.com/CoCreate-app/CoCreate-state/compare/v1.24.7...v1.24.8) (2026-02-15)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cocreate/state",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.25.0",
|
|
4
4
|
"description": "Data attributes which can be used for components in CoCreate framework combined as a group of attributes that dynamically change attributes & fetch custom data.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"state",
|
package/src/index.js
CHANGED
|
@@ -2,250 +2,274 @@ import "@cocreate/element-prototype";
|
|
|
2
2
|
import Observer from "@cocreate/observer";
|
|
3
3
|
import Action from "@cocreate/actions";
|
|
4
4
|
import uid from "@cocreate/uuid";
|
|
5
|
-
import
|
|
5
|
+
import storage from "@cocreate/local-storage";
|
|
6
|
+
|
|
7
|
+
const { localStorage, sessionStorage } = storage;
|
|
6
8
|
|
|
7
9
|
function init() {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
10
|
+
let elements = document.querySelectorAll("[state-id]");
|
|
11
|
+
initElements(elements);
|
|
12
|
+
|
|
13
|
+
window.addEventListener("storage", function (e) {
|
|
14
|
+
if (e.key == "state") {
|
|
15
|
+
// Re-initialize only elements that are explicitly listening to storage changes
|
|
16
|
+
elements = document.querySelectorAll(
|
|
17
|
+
'[state-id][state-onstoragechange]:not([state-onstoragechange="false"])'
|
|
18
|
+
);
|
|
19
|
+
initElements(elements);
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
document.addEventListener("click", function (e) {
|
|
24
|
+
const target = e.target.closest("[state-to]");
|
|
25
|
+
if (target) {
|
|
26
|
+
if (target.closest('[actions*="state"]')) return;
|
|
27
|
+
stateAttributes(target);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
25
30
|
}
|
|
26
31
|
|
|
27
32
|
function initElements(elements) {
|
|
28
|
-
|
|
33
|
+
for (let element of elements) initElement(element);
|
|
29
34
|
}
|
|
30
35
|
|
|
31
36
|
function initElement(element) {
|
|
32
|
-
|
|
33
|
-
|
|
37
|
+
let state_id = element.getAttribute("state-id");
|
|
38
|
+
if (!state_id) return;
|
|
39
|
+
|
|
40
|
+
// Determine target storage based on attributes
|
|
41
|
+
let isLocal = element.hasAttribute("state-localstorage") || element.hasAttribute("state-onstoragechange");
|
|
42
|
+
let storageObj = isLocal ? localStorage : sessionStorage;
|
|
34
43
|
|
|
35
|
-
|
|
44
|
+
let statedAttributes = storageObj.getItem("state");
|
|
36
45
|
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
if (!statedAttributes || statedAttributes.length == 0) return;
|
|
47
|
+
|
|
48
|
+
try {
|
|
49
|
+
statedAttributes = JSON.parse(statedAttributes);
|
|
50
|
+
} catch(e) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
39
53
|
|
|
40
|
-
|
|
54
|
+
if (state_id.includes(",")) state_id = state_id.split(",");
|
|
41
55
|
|
|
42
|
-
|
|
56
|
+
if (!Array.isArray(state_id)) state_id = [state_id];
|
|
43
57
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
58
|
+
for (let i = 0; i < state_id.length; i++) {
|
|
59
|
+
let attrValues = statedAttributes[`${state_id[i].trim()}`];
|
|
60
|
+
if (!attrValues) continue; // Use continue to ensure other IDs in the array still process
|
|
61
|
+
_setAttributeValues(element, attrValues);
|
|
62
|
+
}
|
|
49
63
|
}
|
|
50
64
|
|
|
51
65
|
function _setAttributeValues(el, attrValues) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
66
|
+
let isOverwrite = el.getAttribute("state-overwrite");
|
|
67
|
+
if (isOverwrite === null || isOverwrite === undefined)
|
|
68
|
+
isOverwrite = attrValues["overwrite"];
|
|
55
69
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
70
|
+
if ((isOverwrite && isOverwrite != "false") || isOverwrite === "")
|
|
71
|
+
isOverwrite = true;
|
|
72
|
+
else if (!isOverwrite || isOverwrite === "false") isOverwrite = false;
|
|
59
73
|
|
|
60
|
-
|
|
74
|
+
// delete attrValues["overwrite"];
|
|
61
75
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
76
|
+
for (const key of Object.keys(attrValues)) {
|
|
77
|
+
_setAttributeValue(el, key, attrValues[key], isOverwrite);
|
|
78
|
+
}
|
|
65
79
|
}
|
|
66
80
|
|
|
67
81
|
async function _setAttributeValue(element, attribute, value, isOverwrite) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
82
|
+
// TODO: if (value !== undefined)???
|
|
83
|
+
if (!element.getAttribute(attribute) || isOverwrite) {
|
|
84
|
+
if (attribute == "value") {
|
|
85
|
+
if (element.value == "" || (element.value && isOverwrite))
|
|
86
|
+
element.value = value;
|
|
87
|
+
else if (
|
|
88
|
+
isOverwrite ||
|
|
89
|
+
(element.hasAttribute("value") && !(await element.getValue()))
|
|
90
|
+
)
|
|
91
|
+
element.setValue(value);
|
|
92
|
+
} else if (element.hasAttribute(attribute) && (value || value === "")) {
|
|
93
|
+
element.setAttribute(attribute, value);
|
|
94
|
+
} else if (attribute.startsWith("$")) {
|
|
95
|
+
// Handle using operators.js
|
|
96
|
+
const prop = attribute.substring(1);
|
|
97
|
+
if (element[prop]) {
|
|
98
|
+
if (typeof element[prop] === "function") {
|
|
99
|
+
element[prop](value);
|
|
100
|
+
} else {
|
|
101
|
+
element[prop] = value;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
92
106
|
}
|
|
93
107
|
|
|
94
108
|
async function stateAttributes(element) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
109
|
+
let sessionState = {};
|
|
110
|
+
let localState = {};
|
|
111
|
+
|
|
112
|
+
try { sessionState = JSON.parse(sessionStorage.getItem("state") || "{}"); } catch(e) {}
|
|
113
|
+
try { localState = JSON.parse(localStorage.getItem("state") || "{}"); } catch(e) {}
|
|
114
|
+
|
|
115
|
+
let elements = [];
|
|
116
|
+
|
|
117
|
+
// let form = element.closest("form");
|
|
118
|
+
// if (form) {
|
|
119
|
+
// elements = form.querySelectorAll("[state_to]");
|
|
120
|
+
// } else {
|
|
121
|
+
if (element.hasAttribute("state-to")) elements.push(element);
|
|
122
|
+
let nestedElements = element.querySelectorAll("[state-to]");
|
|
123
|
+
elements.push(...nestedElements);
|
|
124
|
+
let current = element;
|
|
125
|
+
while (current) {
|
|
126
|
+
if (current.hasAttribute("state-to") && !elements.includes(current)) {
|
|
127
|
+
elements.push(current);
|
|
128
|
+
}
|
|
129
|
+
current = current.parentElement;
|
|
130
|
+
}
|
|
131
|
+
// }
|
|
132
|
+
|
|
133
|
+
let changeState = false;
|
|
134
|
+
let sessionChanged = false;
|
|
135
|
+
let localChanged = false;
|
|
136
|
+
let triggerIsLocal = element.hasAttribute("state-localstorage") || element.hasAttribute("state-onstoragechange");
|
|
137
|
+
|
|
138
|
+
for (let i = 0; i < elements.length; i++) {
|
|
139
|
+
let attrValues = await _getAttributeValues(elements[i]);
|
|
140
|
+
if (attrValues.src === "$back" || attrValues.href === "$back") {
|
|
141
|
+
changeState = true;
|
|
142
|
+
window.history.back();
|
|
143
|
+
break;
|
|
144
|
+
} else if (
|
|
145
|
+
attrValues.src === "$forward" ||
|
|
146
|
+
attrValues.href === "$forward"
|
|
147
|
+
) {
|
|
148
|
+
changeState = true;
|
|
149
|
+
window.history.forward();
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let state_to = elements[i].getAttribute("state-to");
|
|
154
|
+
|
|
155
|
+
let isLocal = triggerIsLocal || elements[i].hasAttribute("state-localstorage") || elements[i].hasAttribute("state-onstoragechange");
|
|
156
|
+
|
|
157
|
+
if (isLocal) {
|
|
158
|
+
Object.assign(localState, { [`${state_to}`]: attrValues });
|
|
159
|
+
localChanged = true;
|
|
160
|
+
} else {
|
|
161
|
+
Object.assign(sessionState, { [`${state_to}`]: attrValues });
|
|
162
|
+
sessionChanged = true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
_getStateId(attrValues, state_to);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
let href = element.closest("href");
|
|
169
|
+
if (!changeState && !href) {
|
|
170
|
+
// TODO: Handle $title when adding statedAttributes
|
|
171
|
+
let title = element.getAttribute("title") || document.title || "";
|
|
172
|
+
|
|
173
|
+
history.pushState(
|
|
174
|
+
{ sessionState: JSON.stringify(sessionState), localState: JSON.stringify(localState), title, url: location.href },
|
|
175
|
+
title,
|
|
176
|
+
location.href
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (!changeState) {
|
|
181
|
+
if (sessionChanged) sessionStorage.setItem("state", JSON.stringify(sessionState));
|
|
182
|
+
if (localChanged) localStorage.setItem("state", JSON.stringify(localState));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
element.dispatchEvent(
|
|
186
|
+
new CustomEvent("stateEnd", {
|
|
187
|
+
detail: {}
|
|
188
|
+
})
|
|
189
|
+
);
|
|
163
190
|
}
|
|
164
191
|
|
|
165
192
|
async function _getAttributeValues(element) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
element.value !== undefined &&
|
|
182
|
-
!element.hasAttribute("state.value") &&
|
|
183
|
-
element.getValue
|
|
184
|
-
)
|
|
185
|
-
Object.assign(attributeValues, { value: await element.getValue() });
|
|
186
|
-
|
|
187
|
-
return attributeValues;
|
|
193
|
+
let attributeValues = {};
|
|
194
|
+
let attributes = element.attributes;
|
|
195
|
+
for (let attribute of attributes) {
|
|
196
|
+
if (attribute.name.startsWith("state.")) {
|
|
197
|
+
const key = attribute.name.slice(6);
|
|
198
|
+
if (attribute.value == "$uid") {
|
|
199
|
+
Object.assign(attributeValues, { [key]: uid.generate(6) });
|
|
200
|
+
} else if (key === "value" && !attribute.value) {
|
|
201
|
+
Object.assign(attributeValues, { value: await element.getValue() });
|
|
202
|
+
} else {
|
|
203
|
+
Object.assign(attributeValues, { [key]: element.getAttribute(attribute.name) });
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return attributeValues;
|
|
188
208
|
}
|
|
189
209
|
|
|
190
210
|
function _getStateId(attrValues, state_to) {
|
|
191
|
-
|
|
192
|
-
|
|
211
|
+
const elements = document.querySelectorAll(`[state-id="${state_to}"]`);
|
|
212
|
+
for (let element of elements) _setAttributeValues(element, attrValues);
|
|
193
213
|
}
|
|
194
214
|
|
|
195
215
|
window.onload = function () {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
216
|
+
if (!history.length) {
|
|
217
|
+
const sessionState = sessionStorage.getItem("state") || "";
|
|
218
|
+
const localState = localStorage.getItem("state") || "";
|
|
219
|
+
history.replaceState(
|
|
220
|
+
{ sessionState, localState, url: location.href, title: document.title },
|
|
221
|
+
document.title,
|
|
222
|
+
location.href
|
|
223
|
+
);
|
|
224
|
+
} else if (!history.state || history.state.url !== location.href) {
|
|
225
|
+
const sessionState = sessionStorage.getItem("state") || "";
|
|
226
|
+
const localState = localStorage.getItem("state") || "";
|
|
227
|
+
history.pushState(
|
|
228
|
+
{ sessionState, localState, url: location.href, title: document.title },
|
|
229
|
+
document.title,
|
|
230
|
+
location.href
|
|
231
|
+
);
|
|
232
|
+
}
|
|
211
233
|
};
|
|
212
234
|
|
|
213
235
|
window.addEventListener("popstate", function (event) {
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
236
|
+
if (event.state) {
|
|
237
|
+
if (event.state.sessionState || event.state.localState) {
|
|
238
|
+
if (event.state.sessionState) sessionStorage.setItem("state", event.state.sessionState);
|
|
239
|
+
if (event.state.localState) localStorage.setItem("state", event.state.localState);
|
|
240
|
+
|
|
241
|
+
let elements = document.querySelectorAll("[state-id]");
|
|
242
|
+
initElements(elements);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (event.state.url && event.state.url !== window.location.href) {
|
|
246
|
+
if (event.state.title)
|
|
247
|
+
sessionStorage.setItem("currentPageTitle", event.state.title); // Store title using the wrapper
|
|
248
|
+
|
|
249
|
+
location.href = event.state.url; // Navigate if the URL is different
|
|
250
|
+
} else if (event.state.title) {
|
|
251
|
+
document.title = event.state.title; // Update the title if provided
|
|
252
|
+
}
|
|
253
|
+
}
|
|
230
254
|
});
|
|
231
255
|
|
|
232
256
|
Observer.init({
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
257
|
+
name: "CoCreateState",
|
|
258
|
+
types: ["addedNodes"],
|
|
259
|
+
selector: "[state-id]",
|
|
260
|
+
callback: function (mutation) {
|
|
261
|
+
initElement(mutation.target);
|
|
262
|
+
}
|
|
239
263
|
});
|
|
240
264
|
|
|
241
265
|
Action.init({
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
266
|
+
name: "state",
|
|
267
|
+
endEvent: "stateEnd",
|
|
268
|
+
callback: (action) => {
|
|
269
|
+
stateAttributes(action.element);
|
|
270
|
+
}
|
|
247
271
|
});
|
|
248
272
|
|
|
249
273
|
init();
|
|
250
274
|
|
|
251
|
-
export default { initElements, initElement, stateAttributes };
|
|
275
|
+
export default { initElements, initElement, stateAttributes };
|