@customviews-js/customviews 1.1.7 → 1.1.9
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/custom-views.core.cjs.js +300 -50
- package/dist/custom-views.core.cjs.js.map +1 -1
- package/dist/custom-views.core.esm.js +300 -50
- package/dist/custom-views.core.esm.js.map +1 -1
- package/dist/custom-views.esm.js +300 -50
- package/dist/custom-views.esm.js.map +1 -1
- package/dist/custom-views.js +300 -50
- package/dist/custom-views.js.map +1 -1
- package/dist/custom-views.min.js +2 -2
- package/dist/custom-views.min.js.map +1 -1
- package/dist/types/core/core.d.ts +8 -0
- package/dist/types/core/core.d.ts.map +1 -1
- package/dist/types/core/persistence.d.ts +8 -0
- package/dist/types/core/persistence.d.ts.map +1 -1
- package/dist/types/core/widget.d.ts.map +1 -1
- package/dist/types/entry/browser-entry.d.ts.map +1 -1
- package/dist/types/styles/widget-styles.d.ts +1 -1
- package/dist/types/styles/widget-styles.d.ts.map +1 -1
- package/dist/types/utils/icons.d.ts +9 -2
- package/dist/types/utils/icons.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/custom-views.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* @customviews-js/customviews v1.1.
|
|
2
|
+
* @customviews-js/customviews v1.1.8
|
|
3
3
|
* (c) 2025 Chan Ger Teck
|
|
4
4
|
* Released under the MIT License.
|
|
5
5
|
*/
|
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
class PersistenceManager {
|
|
16
16
|
// Storage keys for localStorage
|
|
17
17
|
static STORAGE_KEYS = {
|
|
18
|
-
STATE: 'customviews-state'
|
|
18
|
+
STATE: 'customviews-state',
|
|
19
|
+
TAB_NAV_VISIBILITY: 'cv-tab-navs-visible'
|
|
19
20
|
};
|
|
20
21
|
/**
|
|
21
22
|
* Check if localStorage is available in the current environment
|
|
@@ -52,6 +53,35 @@
|
|
|
52
53
|
if (!this.isStorageAvailable())
|
|
53
54
|
return;
|
|
54
55
|
localStorage.removeItem(PersistenceManager.STORAGE_KEYS.STATE);
|
|
56
|
+
localStorage.removeItem(PersistenceManager.STORAGE_KEYS.TAB_NAV_VISIBILITY);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Persist tab nav visibility preference
|
|
60
|
+
*/
|
|
61
|
+
persistTabNavVisibility(visible) {
|
|
62
|
+
if (!this.isStorageAvailable())
|
|
63
|
+
return;
|
|
64
|
+
try {
|
|
65
|
+
localStorage.setItem(PersistenceManager.STORAGE_KEYS.TAB_NAV_VISIBILITY, visible ? 'true' : 'false');
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.warn('Failed to persist tab nav visibility:', error);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Get persisted tab nav visibility preference
|
|
73
|
+
*/
|
|
74
|
+
getPersistedTabNavVisibility() {
|
|
75
|
+
if (!this.isStorageAvailable())
|
|
76
|
+
return null;
|
|
77
|
+
try {
|
|
78
|
+
const raw = localStorage.getItem(PersistenceManager.STORAGE_KEYS.TAB_NAV_VISIBILITY);
|
|
79
|
+
return raw === null ? null : raw === 'true';
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
console.warn('Failed to get persisted tab nav visibility:', error);
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
55
85
|
}
|
|
56
86
|
/**
|
|
57
87
|
* Check if any persistence data exists
|
|
@@ -1103,14 +1133,10 @@ ${TAB_STYLES}
|
|
|
1103
1133
|
this.applyState(newState);
|
|
1104
1134
|
});
|
|
1105
1135
|
// Apply stored nav visibility preference on page load
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
const visible = navPref === 'true';
|
|
1110
|
-
TabManager.setNavsVisibility(this.rootEl, visible);
|
|
1111
|
-
}
|
|
1136
|
+
const navPref = this.persistenceManager.getPersistedTabNavVisibility();
|
|
1137
|
+
if (navPref !== null) {
|
|
1138
|
+
TabManager.setNavsVisibility(this.rootEl, navPref);
|
|
1112
1139
|
}
|
|
1113
|
-
catch (e) { /* ignore */ }
|
|
1114
1140
|
// For session history, clicks on back/forward button
|
|
1115
1141
|
window.addEventListener("popstate", () => {
|
|
1116
1142
|
this.loadAndCallApplyState();
|
|
@@ -1177,6 +1203,8 @@ ${TAB_STYLES}
|
|
|
1177
1203
|
else {
|
|
1178
1204
|
console.warn("No configuration loaded, cannot reset to default state");
|
|
1179
1205
|
}
|
|
1206
|
+
// Reset tab nav visibility to default (visible)
|
|
1207
|
+
TabManager.setNavsVisibility(this.rootEl, true);
|
|
1180
1208
|
// Clear URL
|
|
1181
1209
|
URLStateManager.clearURL();
|
|
1182
1210
|
}
|
|
@@ -1255,6 +1283,18 @@ ${TAB_STYLES}
|
|
|
1255
1283
|
}
|
|
1256
1284
|
});
|
|
1257
1285
|
}
|
|
1286
|
+
/**
|
|
1287
|
+
* Persist tab nav visibility preference
|
|
1288
|
+
*/
|
|
1289
|
+
persistTabNavVisibility(visible) {
|
|
1290
|
+
this.persistenceManager.persistTabNavVisibility(visible);
|
|
1291
|
+
}
|
|
1292
|
+
/**
|
|
1293
|
+
* Get persisted tab nav visibility preference
|
|
1294
|
+
*/
|
|
1295
|
+
getPersistedTabNavVisibility() {
|
|
1296
|
+
return this.persistenceManager.getPersistedTabNavVisibility();
|
|
1297
|
+
}
|
|
1258
1298
|
cloneState(state) {
|
|
1259
1299
|
if (!state)
|
|
1260
1300
|
return {};
|
|
@@ -2073,6 +2113,57 @@ ${TAB_STYLES}
|
|
|
2073
2113
|
gap: 1rem;
|
|
2074
2114
|
}
|
|
2075
2115
|
|
|
2116
|
+
/* Navigation toggle icon container */
|
|
2117
|
+
.cv-nav-toggle-container {
|
|
2118
|
+
display: flex;
|
|
2119
|
+
align-items: center;
|
|
2120
|
+
gap: 0.5rem;
|
|
2121
|
+
}
|
|
2122
|
+
|
|
2123
|
+
.cv-nav-icon {
|
|
2124
|
+
width: 2rem;
|
|
2125
|
+
height: 2rem;
|
|
2126
|
+
color: rgba(0, 0, 0, 0.8);
|
|
2127
|
+
display: flex;
|
|
2128
|
+
align-items: center;
|
|
2129
|
+
justify-content: center;
|
|
2130
|
+
flex-shrink: 0;
|
|
2131
|
+
transition: color 0.2s ease;
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
/* Logo box - centered grey box on its own row */
|
|
2135
|
+
.cv-tabgroup-logo-box {
|
|
2136
|
+
width: 3.5rem;
|
|
2137
|
+
height: 3.5rem;
|
|
2138
|
+
background: rgba(0, 0, 0, 0.08);
|
|
2139
|
+
border-radius: 0.5rem;
|
|
2140
|
+
display: flex;
|
|
2141
|
+
align-items: center;
|
|
2142
|
+
justify-content: center;
|
|
2143
|
+
flex-shrink: 0;
|
|
2144
|
+
margin-bottom: 0.5rem;
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
/* Title container for title alignment (without icon) */
|
|
2148
|
+
.cv-tabgroup-title-container {
|
|
2149
|
+
display: flex;
|
|
2150
|
+
align-items: center;
|
|
2151
|
+
gap: 0.5rem;
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
/* Hover state for icon - apply to the entire tabgroup-row */
|
|
2155
|
+
.cv-tabgroup-card.cv-tabgroup-header:hover .cv-nav-icon {
|
|
2156
|
+
color: #3e84f4;
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
.cv-widget-theme-dark .cv-nav-icon {
|
|
2160
|
+
color: rgba(255, 255, 255, 0.8);
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
.cv-widget-theme-dark .cv-tabgroup-card.cv-tabgroup-header:hover .cv-nav-icon {
|
|
2164
|
+
color: #60a5fa;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2076
2167
|
/* Tab Group Card - Items */
|
|
2077
2168
|
.cv-tabgroup-card.cv-tabgroup-item {
|
|
2078
2169
|
display: flex;
|
|
@@ -2090,13 +2181,16 @@ ${TAB_STYLES}
|
|
|
2090
2181
|
/* Tab Group Info */
|
|
2091
2182
|
.cv-tabgroup-info {
|
|
2092
2183
|
flex: 1;
|
|
2184
|
+
display: flex;
|
|
2185
|
+
flex-direction: column;
|
|
2186
|
+
gap: 0.25rem;
|
|
2093
2187
|
}
|
|
2094
2188
|
|
|
2095
2189
|
.cv-tabgroup-title {
|
|
2096
2190
|
font-weight: 500;
|
|
2097
2191
|
font-size: 0.875rem;
|
|
2098
2192
|
color: rgba(0, 0, 0, 0.9);
|
|
2099
|
-
margin: 0 0 0
|
|
2193
|
+
margin: 0 0 0 0;
|
|
2100
2194
|
}
|
|
2101
2195
|
|
|
2102
2196
|
.cv-tabgroup-description {
|
|
@@ -2287,6 +2381,10 @@ ${TAB_STYLES}
|
|
|
2287
2381
|
.cv-btn-icon {
|
|
2288
2382
|
width: 1rem;
|
|
2289
2383
|
height: 1rem;
|
|
2384
|
+
display: flex;
|
|
2385
|
+
align-items: center;
|
|
2386
|
+
justify-content: center;
|
|
2387
|
+
transition: transform 0.2s ease;
|
|
2290
2388
|
}
|
|
2291
2389
|
|
|
2292
2390
|
/* Dark theme custom state styles */
|
|
@@ -2412,6 +2510,32 @@ ${TAB_STYLES}
|
|
|
2412
2510
|
.cv-widget-theme-dark .cv-welcome-widget-label {
|
|
2413
2511
|
color: #e2e8f0;
|
|
2414
2512
|
}
|
|
2513
|
+
|
|
2514
|
+
/* Dark theme logo box */
|
|
2515
|
+
.cv-widget-theme-dark .cv-tabgroup-logo-box {
|
|
2516
|
+
background: rgba(255, 255, 255, 0.1);
|
|
2517
|
+
}
|
|
2518
|
+
|
|
2519
|
+
/* Spinning animation for reset button icon */
|
|
2520
|
+
@keyframes cv-spin {
|
|
2521
|
+
from {
|
|
2522
|
+
transform: rotate(0deg);
|
|
2523
|
+
}
|
|
2524
|
+
to {
|
|
2525
|
+
transform: rotate(-360deg);
|
|
2526
|
+
}
|
|
2527
|
+
}
|
|
2528
|
+
|
|
2529
|
+
.cv-spinning {
|
|
2530
|
+
animation: cv-spin 0.6s ease-in-out;
|
|
2531
|
+
}
|
|
2532
|
+
|
|
2533
|
+
/* Hide widget icon in print view */
|
|
2534
|
+
@media print {
|
|
2535
|
+
.cv-widget-icon {
|
|
2536
|
+
display: none !important;
|
|
2537
|
+
}
|
|
2538
|
+
}
|
|
2415
2539
|
`;
|
|
2416
2540
|
/**
|
|
2417
2541
|
* Inject widget styles into the document head
|
|
@@ -2456,13 +2580,80 @@ ${TAB_STYLES}
|
|
|
2456
2580
|
</svg>`;
|
|
2457
2581
|
}
|
|
2458
2582
|
/**
|
|
2459
|
-
*
|
|
2583
|
+
* Copy icon for sharing URL button
|
|
2460
2584
|
*/
|
|
2461
|
-
function
|
|
2462
|
-
return `<svg
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2585
|
+
function getCopyIcon() {
|
|
2586
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="18" height="18" viewBox="0 0 18 18" version="1.1" fill="currentColor">
|
|
2587
|
+
<g id="surface1">
|
|
2588
|
+
<path d="M 11.273438 0 L 2.546875 0 C 1.746094 0 1.089844 0.613281 1.089844
|
|
2589
|
+
1.363281 L 1.089844 10.910156 L 2.546875 10.910156 L 2.546875 1.363281 L 11.273438
|
|
2590
|
+
1.363281 Z M 13.453125 2.726562 L 5.453125 2.726562 C 4.65625 2.726562 4 3.339844 4
|
|
2591
|
+
4.089844 L 4 13.636719 C 4 14.386719 4.65625 15 5.453125 15 L 13.453125 15 C 14.253906
|
|
2592
|
+
15 14.910156 14.386719 14.910156 13.636719 L 14.910156 4.089844 C 14.910156 3.339844
|
|
2593
|
+
14.253906 2.726562 13.453125 2.726562 Z M 13.453125 13.636719 L 5.453125 13.636719 L
|
|
2594
|
+
5.453125 4.089844 L 13.453125 4.089844 Z M 13.453125 13.636719 "></path>
|
|
2595
|
+
</g>
|
|
2596
|
+
</svg>`;
|
|
2597
|
+
}
|
|
2598
|
+
function getTickIcon() {
|
|
2599
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="2 2 22 22" fill="currentColor">
|
|
2600
|
+
<path d="M 19.28125 5.28125 L 9 15.5625 L 4.71875 11.28125 L 3.28125 12.71875 L 8.28125 17.71875
|
|
2601
|
+
L 9 18.40625 L 9.71875 17.71875 L 20.71875 6.71875 Z"></path>
|
|
2602
|
+
</svg>`;
|
|
2603
|
+
}
|
|
2604
|
+
function getNavHeadingOnIcon() {
|
|
2605
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="250" height="181" viewBox="0 0 250 181">
|
|
2606
|
+
<rect y="34.5001" width="250" height="146" rx="4" stroke="currentColor" stroke-width="10" fill="none"/>
|
|
2607
|
+
<line x1="27" y1="62.0001" x2="77" y2="62.0001" stroke="currentColor" stroke-width="5"/>
|
|
2608
|
+
<line x1="27" y1="77.8888" x2="77" y2="77.8888" stroke="currentColor" stroke-width="5"/>
|
|
2609
|
+
<line x1="27" y1="97.4454" x2="221" y2="97.4454" stroke="currentColor" stroke-width="5"/>
|
|
2610
|
+
<line x1="27" y1="114.555" x2="221" y2="114.555" stroke="currentColor" stroke-width="5"/>
|
|
2611
|
+
<line x1="27" y1="132.889" x2="221" y2="132.889" stroke="currentColor" stroke-width="5"/>
|
|
2612
|
+
<line x1="27" y1="150" x2="221" y2="150" stroke="currentColor" stroke-width="5"/>
|
|
2613
|
+
<line x1="247.5" y1="43.0001" x2="247.5" y2="13.0001" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
|
|
2614
|
+
<path d="M185 12.5001L247 12.5001" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
|
|
2615
|
+
<line x1="204.09" y1="36.6095" x2="181.698" y2="10.0228" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
|
|
2616
|
+
<path d="M125 9.50012L181 9.50012" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
|
|
2617
|
+
<path d="M144.305 35.2579L120.095 6.56679" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
|
|
2618
|
+
<path d="M120 6.50037L64 6.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
|
|
2619
|
+
<path d="M87.1957 36.1024L59 2.50008" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
|
|
2620
|
+
<path d="M59 2.50037L3 2.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
|
|
2621
|
+
<path d="M2.5 38.5001L2.5 3.00012" stroke="currentColor" stroke-width="5" stroke-linecap="round"/>
|
|
2622
|
+
</svg>`;
|
|
2623
|
+
}
|
|
2624
|
+
function getNavHeadingOffIcon() {
|
|
2625
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="250" height="181" viewBox="0 0 250 181" fill="currentColor">
|
|
2626
|
+
<rect y="34.5001" width="250" height="146" rx="4" stroke="currentColor" stroke-width="10" fill="none"/>
|
|
2627
|
+
<line x1="27" y1="62" x2="77" y2="62" stroke="currentColor" stroke-width="5"/>
|
|
2628
|
+
<line x1="27" y1="77.8887" x2="77" y2="77.8887" stroke="currentColor" stroke-width="5"/>
|
|
2629
|
+
<line x1="27" y1="97.4453" x2="221" y2="97.4453" stroke="currentColor" stroke-width="5"/>
|
|
2630
|
+
<line x1="27" y1="114.555" x2="221" y2="114.555" stroke="currentColor" stroke-width="5"/>
|
|
2631
|
+
<line x1="27" y1="132.889" x2="221" y2="132.889" stroke="currentColor" stroke-width="5"/>
|
|
2632
|
+
<line x1="27" y1="150" x2="221" y2="150" stroke="currentColor" stroke-width="5"/>
|
|
2633
|
+
</svg>`;
|
|
2634
|
+
}
|
|
2635
|
+
/**
|
|
2636
|
+
* Transition Icon for Navigation Headings
|
|
2637
|
+
*/
|
|
2638
|
+
function getNavDashed() {
|
|
2639
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" width="250" height="181" viewBox="0 0 250 181">
|
|
2640
|
+
<rect y="34.5001" width="250" height="146" rx="4" stroke="currentColor" stroke-width="10" fill="none"/>
|
|
2641
|
+
<line x1="27" y1="62.0001" x2="77" y2="62.0001" stroke="currentColor" stroke-width="5"/>
|
|
2642
|
+
<line x1="27" y1="77.8888" x2="77" y2="77.8888" stroke="currentColor" stroke-width="5"/>
|
|
2643
|
+
<line x1="27" y1="97.4454" x2="221" y2="97.4454" stroke="currentColor" stroke-width="5"/>
|
|
2644
|
+
<line x1="27" y1="114.555" x2="221" y2="114.555" stroke="currentColor" stroke-width="5"/>
|
|
2645
|
+
<line x1="27" y1="132.889" x2="221" y2="132.889" stroke="currentColor" stroke-width="5"/>
|
|
2646
|
+
<line x1="27" y1="150" x2="221" y2="150" stroke="currentColor" stroke-width="5"/>
|
|
2647
|
+
<path d="M245 37.0001V39.5001H250V37.0001H247.5H245ZM250 13.0001C250 11.6194 248.881 10.5001 247.5 10.5001C246.119 10.5001 245 11.6194 245 13.0001H247.5H250ZM250 31.0001C250 29.6194 248.881 28.5001 247.5 28.5001C246.119 28.5001 245 29.6194 245 31.0001H247.5H250ZM245 19.0001C245 20.3808 246.119 21.5001 247.5 21.5001C248.881 21.5001 250 20.3808 250 19.0001H247.5H245ZM247.5 37.0001H250V31.0001H247.5H245V37.0001H247.5ZM247.5 19.0001H250V13.0001H247.5H245V19.0001H247.5Z" fill="currentColor"/>
|
|
2648
|
+
<line x1="204.09" y1="36.6095" x2="181.698" y2="10.0228" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"/>
|
|
2649
|
+
<path d="M125 9.50012L181 9.50012" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"/>
|
|
2650
|
+
<path d="M144.305 35.2579L120.095 6.56679" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"/>
|
|
2651
|
+
<path d="M120 6.50037L64 6.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"/>
|
|
2652
|
+
<path d="M87.1957 36.1024L59 2.50008" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"/>
|
|
2653
|
+
<path d="M59 2.50037L3 2.50037" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"/>
|
|
2654
|
+
<path d="M2.5 38.5001L2.5 3.00012" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"/>
|
|
2655
|
+
<path d="M185 12.5001L247 12.5001" stroke="currentColor" stroke-width="5" stroke-linecap="round" stroke-dasharray="10 10"/>
|
|
2656
|
+
</svg>`;
|
|
2466
2657
|
}
|
|
2467
2658
|
|
|
2468
2659
|
class CustomViewsWidget {
|
|
@@ -2584,15 +2775,22 @@ ${TAB_STYLES}
|
|
|
2584
2775
|
const tabGroups = this.core.getTabGroups();
|
|
2585
2776
|
let tabGroupControlsHTML = '';
|
|
2586
2777
|
if (this.options.showTabGroups && tabGroups && tabGroups.length > 0) {
|
|
2778
|
+
// Determine initial nav visibility state
|
|
2779
|
+
const initialNavsVisible = TabManager.areNavsVisible(document.body);
|
|
2587
2780
|
tabGroupControlsHTML = `
|
|
2588
2781
|
<div class="cv-tabgroup-card cv-tabgroup-header">
|
|
2589
2782
|
<div class="cv-tabgroup-row">
|
|
2783
|
+
<div class="cv-tabgroup-logo-box" id="cv-nav-icon-box">
|
|
2784
|
+
<div class="cv-nav-icon" id="cv-nav-icon">${initialNavsVisible ? getNavHeadingOnIcon() : getNavHeadingOffIcon()}</div>
|
|
2785
|
+
</div>
|
|
2590
2786
|
<div class="cv-tabgroup-info">
|
|
2591
|
-
<
|
|
2787
|
+
<div class="cv-tabgroup-title-container">
|
|
2788
|
+
<p class="cv-tabgroup-title">Navigation Headers</p>
|
|
2789
|
+
</div>
|
|
2592
2790
|
<p class="cv-tabgroup-description">Show or hide navigation headers</p>
|
|
2593
2791
|
</div>
|
|
2594
2792
|
<label class="cv-toggle-switch cv-nav-toggle">
|
|
2595
|
-
<input class="cv-nav-pref-input" type="checkbox" aria-label="Show or hide navigation headers" />
|
|
2793
|
+
<input class="cv-nav-pref-input" type="checkbox" ${initialNavsVisible ? 'checked' : ''} aria-label="Show or hide navigation headers" />
|
|
2596
2794
|
<span class="cv-switch-bg"></span>
|
|
2597
2795
|
<span class="cv-switch-knob"></span>
|
|
2598
2796
|
</label>
|
|
@@ -2650,13 +2848,13 @@ ${TAB_STYLES}
|
|
|
2650
2848
|
<footer class="cv-modal-footer">
|
|
2651
2849
|
${this.options.showReset ? `
|
|
2652
2850
|
<button class="cv-reset-btn">
|
|
2653
|
-
|
|
2851
|
+
<span class="cv-reset-btn-icon">${getResetIcon()}</span>
|
|
2654
2852
|
<span>Reset to Default</span>
|
|
2655
2853
|
</button>
|
|
2656
2854
|
` : ''}
|
|
2657
2855
|
<button class="cv-share-btn">
|
|
2658
|
-
${getShareIcon()}
|
|
2659
2856
|
<span>Copy Shareable URL</span>
|
|
2857
|
+
<span class="cv-share-btn-icon">${getCopyIcon()}</span>
|
|
2660
2858
|
</button>
|
|
2661
2859
|
</footer>
|
|
2662
2860
|
</div>
|
|
@@ -2684,14 +2882,35 @@ ${TAB_STYLES}
|
|
|
2684
2882
|
if (copyUrlBtn) {
|
|
2685
2883
|
copyUrlBtn.addEventListener('click', () => {
|
|
2686
2884
|
this.copyShareableURL();
|
|
2885
|
+
// Visual feedback: change icon to tick for 3 seconds
|
|
2886
|
+
const iconContainer = copyUrlBtn.querySelector('.cv-share-btn-icon');
|
|
2887
|
+
if (iconContainer) {
|
|
2888
|
+
const originalIcon = iconContainer.innerHTML;
|
|
2889
|
+
iconContainer.innerHTML = getTickIcon();
|
|
2890
|
+
// Revert after 3 seconds
|
|
2891
|
+
setTimeout(() => {
|
|
2892
|
+
iconContainer.innerHTML = originalIcon;
|
|
2893
|
+
}, 3000);
|
|
2894
|
+
}
|
|
2687
2895
|
});
|
|
2688
2896
|
}
|
|
2689
2897
|
// Reset to default button
|
|
2690
2898
|
const resetBtn = this.modal.querySelector('.cv-reset-btn');
|
|
2691
2899
|
if (resetBtn) {
|
|
2692
2900
|
resetBtn.addEventListener('click', () => {
|
|
2901
|
+
// Add spinning animation to icon
|
|
2902
|
+
const resetIcon = resetBtn.querySelector('.cv-reset-btn-icon');
|
|
2903
|
+
if (resetIcon) {
|
|
2904
|
+
resetIcon.classList.add('cv-spinning');
|
|
2905
|
+
}
|
|
2693
2906
|
this.core.resetToDefault();
|
|
2694
2907
|
this.loadCurrentStateIntoForm();
|
|
2908
|
+
// Remove spinning animation after it completes
|
|
2909
|
+
setTimeout(() => {
|
|
2910
|
+
if (resetIcon) {
|
|
2911
|
+
resetIcon.classList.remove('cv-spinning');
|
|
2912
|
+
}
|
|
2913
|
+
}, 600); // 600ms matches the animation duration
|
|
2695
2914
|
});
|
|
2696
2915
|
}
|
|
2697
2916
|
// Listen to toggle switches
|
|
@@ -2725,14 +2944,34 @@ ${TAB_STYLES}
|
|
|
2725
2944
|
});
|
|
2726
2945
|
// Listener for show/hide tab navs
|
|
2727
2946
|
const tabNavToggle = this.modal.querySelector('.cv-nav-pref-input');
|
|
2728
|
-
|
|
2947
|
+
const navIcon = this.modal?.querySelector('#cv-nav-icon');
|
|
2948
|
+
const navHeaderCard = this.modal?.querySelector('.cv-tabgroup-card.cv-tabgroup-header');
|
|
2949
|
+
if (tabNavToggle && navIcon && navHeaderCard) {
|
|
2950
|
+
// Helper to update icon based on state
|
|
2951
|
+
const updateIcon = (isVisible, isHovering = false) => {
|
|
2952
|
+
if (isHovering) {
|
|
2953
|
+
// On hover, show the transition icon
|
|
2954
|
+
navIcon.innerHTML = getNavDashed();
|
|
2955
|
+
}
|
|
2956
|
+
else {
|
|
2957
|
+
// Normal state, show the status icon (on if visible, off if hidden)
|
|
2958
|
+
navIcon.innerHTML = isVisible ? getNavHeadingOnIcon() : getNavHeadingOffIcon();
|
|
2959
|
+
}
|
|
2960
|
+
};
|
|
2961
|
+
// Add hover listeners to entire header card
|
|
2962
|
+
navHeaderCard.addEventListener('mouseenter', () => {
|
|
2963
|
+
updateIcon(tabNavToggle.checked, true);
|
|
2964
|
+
});
|
|
2965
|
+
navHeaderCard.addEventListener('mouseleave', () => {
|
|
2966
|
+
updateIcon(tabNavToggle.checked, false);
|
|
2967
|
+
});
|
|
2968
|
+
// Add change listener
|
|
2729
2969
|
tabNavToggle.addEventListener('change', () => {
|
|
2730
2970
|
const visible = tabNavToggle.checked;
|
|
2731
|
-
//
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
catch (e) { /* ignore */ }
|
|
2971
|
+
// Update the icon based on new state (not hovering)
|
|
2972
|
+
updateIcon(visible, false);
|
|
2973
|
+
// Persist preference via core
|
|
2974
|
+
this.core.persistTabNavVisibility(visible);
|
|
2736
2975
|
// Apply to DOM using TabManager via core
|
|
2737
2976
|
try {
|
|
2738
2977
|
const rootEl = document.body;
|
|
@@ -2844,21 +3083,22 @@ ${TAB_STYLES}
|
|
|
2844
3083
|
});
|
|
2845
3084
|
// Load tab nav visibility preference
|
|
2846
3085
|
const navPref = (() => {
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
return TabManager.areNavsVisible(document.body);
|
|
2851
|
-
return raw === 'true';
|
|
2852
|
-
}
|
|
2853
|
-
catch (e) {
|
|
2854
|
-
return TabManager.areNavsVisible(document.body);
|
|
3086
|
+
const persisted = this.core.getPersistedTabNavVisibility();
|
|
3087
|
+
if (persisted !== null) {
|
|
3088
|
+
return persisted;
|
|
2855
3089
|
}
|
|
3090
|
+
return TabManager.areNavsVisible(document.body);
|
|
2856
3091
|
})();
|
|
2857
3092
|
const tabNavToggle = this.modal.querySelector('.cv-nav-pref-input');
|
|
3093
|
+
const navIcon = this.modal?.querySelector('#cv-nav-icon');
|
|
2858
3094
|
if (tabNavToggle) {
|
|
2859
3095
|
tabNavToggle.checked = navPref;
|
|
2860
3096
|
// Ensure UI matches actual visibility
|
|
2861
3097
|
TabManager.setNavsVisibility(document.body, navPref);
|
|
3098
|
+
// Update the nav icon to reflect the current state
|
|
3099
|
+
if (navIcon) {
|
|
3100
|
+
navIcon.innerHTML = navPref ? getNavHeadingOnIcon() : getNavHeadingOffIcon();
|
|
3101
|
+
}
|
|
2862
3102
|
}
|
|
2863
3103
|
}
|
|
2864
3104
|
/**
|
|
@@ -2875,12 +3115,19 @@ ${TAB_STYLES}
|
|
|
2875
3115
|
// Check if welcome has been shown before
|
|
2876
3116
|
const hasSeenWelcome = localStorage.getItem(STORAGE_KEY);
|
|
2877
3117
|
if (!hasSeenWelcome) {
|
|
2878
|
-
//
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
3118
|
+
// Check if this page has any custom views elements
|
|
3119
|
+
const hasCustomViewElements = document.querySelector('cv-tabgroup') !== null ||
|
|
3120
|
+
document.querySelector('cv-tab') !== null ||
|
|
3121
|
+
document.querySelector('cv-toggle') !== null ||
|
|
3122
|
+
document.querySelector('[data-cv-toggle]') !== null;
|
|
3123
|
+
if (hasCustomViewElements) {
|
|
3124
|
+
// Show welcome modal after a short delay to let the page settle
|
|
3125
|
+
setTimeout(() => {
|
|
3126
|
+
this.createWelcomeModal();
|
|
3127
|
+
}, 500);
|
|
3128
|
+
// Mark as shown
|
|
3129
|
+
localStorage.setItem(STORAGE_KEY, 'true');
|
|
3130
|
+
}
|
|
2884
3131
|
}
|
|
2885
3132
|
}
|
|
2886
3133
|
/**
|
|
@@ -2979,17 +3226,20 @@ ${TAB_STYLES}
|
|
|
2979
3226
|
}
|
|
2980
3227
|
window.__customViewsInitInProgress = true;
|
|
2981
3228
|
try {
|
|
2982
|
-
// Find the script tag
|
|
3229
|
+
// Find the script tag that loaded this script
|
|
2983
3230
|
let scriptTag = document.currentScript;
|
|
2984
|
-
|
|
2985
|
-
|
|
2986
|
-
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
3231
|
+
if (!scriptTag || !scriptTag.hasAttribute('data-base-url')) {
|
|
3232
|
+
const dataAttrMatch = document.querySelector('script[data-base-url]');
|
|
3233
|
+
if (dataAttrMatch) {
|
|
3234
|
+
scriptTag = dataAttrMatch;
|
|
3235
|
+
}
|
|
3236
|
+
else {
|
|
3237
|
+
for (const script of document.scripts) {
|
|
3238
|
+
const src = script.src || '';
|
|
3239
|
+
if (/(?:custom[-_]views|@customviews-js\/customviews)(?:\.min)?\.(?:esm\.)?js($|\?)/i.test(src)) {
|
|
3240
|
+
scriptTag = script;
|
|
3241
|
+
break;
|
|
3242
|
+
}
|
|
2993
3243
|
}
|
|
2994
3244
|
}
|
|
2995
3245
|
}
|