@cocreate/pwa 1.20.0 → 1.21.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 CHANGED
@@ -1,3 +1,10 @@
1
+ # [1.21.0](https://github.com/CoCreate-app/CoCreate-pwa/compare/v1.20.0...v1.21.0) (2024-12-14)
2
+
3
+
4
+ ### Features
5
+
6
+ * dynamic theme handling ([c2688f2](https://github.com/CoCreate-app/CoCreate-pwa/commit/c2688f2f148f0c68e3693cf932a24976658eb475))
7
+
1
8
  # [1.20.0](https://github.com/CoCreate-app/CoCreate-pwa/compare/v1.19.4...v1.20.0) (2024-11-04)
2
9
 
3
10
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cocreate/pwa",
3
- "version": "1.20.0",
3
+ "version": "1.21.0",
4
4
  "description": "A simple pwa component in vanilla javascript. Easily configured using HTML5 data-attributes and/or JavaScript API.",
5
5
  "keywords": [
6
6
  "pwa",
package/src/index.js CHANGED
@@ -22,10 +22,10 @@
22
22
  * For details, visit <https://cocreate.app/licenses/> or contact us at sales@cocreate.app.
23
23
  */
24
24
 
25
- import observer from '@cocreate/observer'
26
- import localStorage from '@cocreate/local-storage'
27
- import './web-share'
28
-
25
+ import observer from "@cocreate/observer";
26
+ import localStorage from "@cocreate/local-storage";
27
+ import "./web-share";
28
+ // import "./theme";
29
29
 
30
30
  /**
31
31
  * Warn the page must be served over HTTPS
@@ -41,104 +41,114 @@ import './web-share'
41
41
  // }
42
42
 
43
43
  function init() {
44
- const button = document.querySelector('[actions*="install"]');
45
-
46
- window.addEventListener('beforeinstallprompt', (event) => {
47
- window.deferredPrompt = event;
48
- if (button)
49
- button.removeAttribute('hidden');
50
- });
51
-
52
- if (button) {
53
- button.addEventListener('click', async () => {
54
- // console.log('👍', 'installBtn-clicked');
55
- const promptEvent = window.deferredPrompt;
56
- if (!promptEvent) {
57
- // The deferred prompt isn't available.
58
- return;
59
- }
60
- // Show the install prompt.
61
- promptEvent.prompt();
62
- // Log the result
63
- const result = await promptEvent.userChoice;
64
- console.log('👍', 'userChoice', result);
65
- // Reset the deferred prompt variable, since
66
- // prompt() can only be called once.
67
- window.deferredPrompt = null;
68
- // Hide the install button.
69
- button.setAttribute('hidden', '');
70
- });
71
- }
72
-
73
- window.addEventListener('appinstalled', (event) => {
74
- // console.log('👍', 'appinstalled', event);
75
- // Clear the deferredPrompt so it can be garbage collected
76
- window.deferredPrompt = null;
77
- });
78
-
79
- if ('serviceWorker' in navigator) {
80
- let workerPath
81
- if (window.CoCreateConfig && window.CoCreateConfig.serviceWorker)
82
- workerPath = window.CoCreateConfig.serviceWorker
83
- else
84
- workerPath = localStorage.getItem("serviceWorker") || '/service-worker.js'
85
-
86
- localStorage.setItem("serviceWorker", workerPath);
87
-
88
- let cache
89
- if (window.CoCreateConfig && window.CoCreateConfig.cache)
90
- cache = window.CoCreateConfig.cache
91
- else
92
- cache = localStorage.getItem("cache") || 'true'
93
-
94
- localStorage.setItem("cache", cache);
95
- workerPath += `?cache=${cache}`
96
-
97
- let isPwa = true
98
- if (workerPath) {
99
- navigator.serviceWorker.getRegistrations().then(registrations => {
100
- if (registrations.length === 0 || isPwa == true)
101
- window.addEventListener("load", function () {
102
- navigator.serviceWorker.getRegistration(workerPath).then(registration => {
103
- if (registration && registration.active && registration.active.scriptURL.includes(workerPath)) {
104
- console.log('Service Worker Active')
105
- } else {
106
- navigator.serviceWorker.register(workerPath)
107
- .then(reg => {
108
- reg.onupdatefound = () => {
109
- const installingWorker = reg.installing;
110
- installingWorker.onstatechange = () => {
111
- // console.log('Service Worker', installingWorker.state);
112
- }
113
- }
114
- })
115
- .catch(err => console.log('SW ERROR', err));
116
- }
117
- });
118
- });
119
- });
120
-
121
- }
122
- }
44
+ const button = document.querySelector('[actions*="install"]');
45
+
46
+ window.addEventListener("beforeinstallprompt", (event) => {
47
+ window.deferredPrompt = event;
48
+ if (button) button.removeAttribute("hidden");
49
+ });
50
+
51
+ if (button) {
52
+ button.addEventListener("click", async () => {
53
+ // console.log('👍', 'installBtn-clicked');
54
+ const promptEvent = window.deferredPrompt;
55
+ if (!promptEvent) {
56
+ // The deferred prompt isn't available.
57
+ return;
58
+ }
59
+ // Show the install prompt.
60
+ promptEvent.prompt();
61
+ // Log the result
62
+ const result = await promptEvent.userChoice;
63
+ console.log("👍", "userChoice", result);
64
+ // Reset the deferred prompt variable, since
65
+ // prompt() can only be called once.
66
+ window.deferredPrompt = null;
67
+ // Hide the install button.
68
+ button.setAttribute("hidden", "");
69
+ });
70
+ }
71
+
72
+ window.addEventListener("appinstalled", (event) => {
73
+ // console.log('👍', 'appinstalled', event);
74
+ // Clear the deferredPrompt so it can be garbage collected
75
+ window.deferredPrompt = null;
76
+ });
77
+
78
+ if ("serviceWorker" in navigator) {
79
+ let workerPath;
80
+ if (window.CoCreateConfig && window.CoCreateConfig.serviceWorker)
81
+ workerPath = window.CoCreateConfig.serviceWorker;
82
+ else
83
+ workerPath =
84
+ localStorage.getItem("serviceWorker") || "/service-worker.js";
85
+
86
+ localStorage.setItem("serviceWorker", workerPath);
87
+
88
+ let cache;
89
+ if (window.CoCreateConfig && window.CoCreateConfig.cache)
90
+ cache = window.CoCreateConfig.cache;
91
+ else cache = localStorage.getItem("cache") || "true";
92
+
93
+ localStorage.setItem("cache", cache);
94
+ workerPath += `?cache=${cache}`;
95
+
96
+ let isPwa = true;
97
+ if (workerPath) {
98
+ navigator.serviceWorker.getRegistrations().then((registrations) => {
99
+ if (registrations.length === 0 || isPwa == true)
100
+ window.addEventListener("load", function () {
101
+ navigator.serviceWorker
102
+ .getRegistration(workerPath)
103
+ .then((registration) => {
104
+ if (
105
+ registration &&
106
+ registration.active &&
107
+ registration.active.scriptURL.includes(
108
+ workerPath
109
+ )
110
+ ) {
111
+ console.log("Service Worker Active");
112
+ } else {
113
+ navigator.serviceWorker
114
+ .register(workerPath)
115
+ .then((reg) => {
116
+ reg.onupdatefound = () => {
117
+ const installingWorker =
118
+ reg.installing;
119
+ installingWorker.onstatechange =
120
+ () => {
121
+ // console.log('Service Worker', installingWorker.state);
122
+ };
123
+ };
124
+ })
125
+ .catch((err) =>
126
+ console.log("SW ERROR", err)
127
+ );
128
+ }
129
+ });
130
+ });
131
+ });
132
+ }
133
+ }
123
134
  }
124
135
 
125
- init()
136
+ init();
126
137
 
127
138
  async function persistData() {
128
- if (navigator.storage && navigator.storage.persist) {
129
- const result = await navigator.storage.persist();
130
- // console.log(`Data persisted: ${result}`);
131
- }
139
+ if (navigator.storage && navigator.storage.persist) {
140
+ const result = await navigator.storage.persist();
141
+ // console.log(`Data persisted: ${result}`);
142
+ }
132
143
  }
133
144
 
134
145
  observer.init({
135
- name: 'initPwa',
136
- observe: ['addedNodes'],
137
- selector: '[actions="install"]',
138
- callback: (mutation) => {
139
- init()
140
- }
146
+ name: "initPwa",
147
+ observe: ["addedNodes"],
148
+ selector: '[actions="install"]',
149
+ callback: (mutation) => {
150
+ init();
151
+ }
141
152
  });
142
153
 
143
-
144
- export default { persistData }
154
+ export default { persistData };
package/src/theme.js ADDED
@@ -0,0 +1,57 @@
1
+ function applyThemeAttributes() {
2
+ // Detect the current theme (light or dark)
3
+ const isDarkMode = window.matchMedia(
4
+ "(prefers-color-scheme: dark)"
5
+ ).matches;
6
+
7
+ // Select all elements with light or dark attributes
8
+ const elements = document.querySelectorAll("[light], [dark]");
9
+
10
+ elements.forEach((element) => {
11
+ // Determine the attribute to use based on the theme
12
+ const themeAttr = isDarkMode ? "dark" : "light";
13
+ const themeValue = element.getAttribute(themeAttr);
14
+
15
+ // Determine the current value of the attribute to update
16
+ let attributeToUpdate;
17
+ if (element.tagName === "LINK" && element.rel === "manifest") {
18
+ attributeToUpdate = "href";
19
+ } else if (
20
+ element.tagName === "META" &&
21
+ element.name === "theme-color"
22
+ ) {
23
+ attributeToUpdate = "content";
24
+ }
25
+
26
+ if (attributeToUpdate && themeValue) {
27
+ const currentValue = element.getAttribute(attributeToUpdate);
28
+
29
+ // Update only if the current value does not match the new value
30
+ if (currentValue !== themeValue) {
31
+ if (element.tagName === "LINK" && element.rel === "manifest") {
32
+ // Handle manifest link replacement
33
+ const newElement = element.cloneNode(); // Clone the element
34
+ newElement.setAttribute(attributeToUpdate, themeValue); // Update href
35
+
36
+ // Replace the old link with the new one to force fetch
37
+ element.parentNode.replaceChild(newElement, element);
38
+ console.log(`Manifest updated: ${themeValue}`);
39
+ } else {
40
+ // For other elements like meta, update the attribute directly
41
+ element.setAttribute(attributeToUpdate, themeValue);
42
+ if (element.tagName === "META") {
43
+ console.log(`Theme color updated: ${themeValue}`);
44
+ }
45
+ }
46
+ }
47
+ }
48
+ });
49
+ }
50
+
51
+ // Apply theme attributes on page load
52
+ applyThemeAttributes();
53
+
54
+ // Listen for changes in the user's theme preference
55
+ window
56
+ .matchMedia("(prefers-color-scheme: dark)")
57
+ .addEventListener("change", applyThemeAttributes);