@widelab-nc/widelab 1.1.26 → 1.1.28

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@widelab-nc/widelab",
3
- "version": "1.1.26",
3
+ "version": "1.1.28",
4
4
  "description": "Widelab starter template based on Finsweet template + add-ons.",
5
5
  "homepage": "https://widelab.co",
6
6
  "license": "ISC",
package/src/index.js CHANGED
@@ -928,6 +928,8 @@ window.badgeColorChange = function(e) {
928
928
  }
929
929
  }
930
930
 
931
+
932
+
931
933
  // Stats section headline animation
932
934
  window.statsHeadlineAnimation = function() {
933
935
  const statsHeadlineAnimation = gsap.timeline({
@@ -966,36 +968,250 @@ window.badgeColorChange = function(e) {
966
968
  }
967
969
 
968
970
 
971
+ // Filtering logic on Client's page
972
+ window.clientFilters = function() {
973
+ function updateCheckboxCounts(excludeField) {
974
+
975
+ const fields = ['industry', 'country', 'services'];
976
+
977
+ fields.forEach(function(field) {
978
+ if (field === excludeField) return;
979
+
980
+ const checkboxes = document.querySelectorAll(`span[fs-cmsfilter-field="${field}"]`);
981
+
982
+ checkboxes.forEach(function(checkbox) {
983
+ const originalText = checkbox.dataset.originalText || checkbox.textContent.trim();
984
+ checkbox.dataset.originalText = originalText;
985
+
986
+ let matchedCount = 0;
987
+
988
+ document.querySelectorAll(`div[fs-cmsfilter-field="${field}"]`).forEach(function(div) {
989
+ if (div.textContent.trim() === originalText) {
990
+ matchedCount++;
991
+ }
992
+ });
993
+
994
+ let countSpan = checkbox.nextElementSibling;
995
+ if (!countSpan || !countSpan.classList.contains('count')) {
996
+ countSpan = document.createElement('span');
997
+ countSpan.className = 'count';
998
+ checkbox.insertAdjacentElement('afterend', countSpan);
999
+ }
1000
+ countSpan.textContent = `(${matchedCount})`;
1001
+
1002
+ const parentDiv = checkbox.closest('div.w-dyn-item');
1003
+ if (matchedCount === 0) {
1004
+ parentDiv.classList.add('empty-category');
1005
+ } else {
1006
+ parentDiv.classList.remove('empty-category');
1007
+ }
1008
+ });
1009
+
1010
+ sortCheckboxes(field);
1011
+ });
1012
+ }
1013
+
1014
+ function sortCheckboxes(field) {
1015
+
1016
+ const parentList = document.querySelector(`span[fs-cmsfilter-field="${field}"]`).closest('.collection-list');
1017
+ const items = Array.from(parentList.children);
1018
+
1019
+ items.sort(function(a, b) {
1020
+ const countA = parseInt((a.querySelector('.count')?.textContent || '').replace(/[()]/g, '')) || 0;
1021
+ const countB = parseInt((b.querySelector('.count')?.textContent || '').replace(/[()]/g, '')) || 0;
1022
+ return countB - countA;
1023
+ });
969
1024
 
970
- // GSAP Counter Up Animation
1025
+ items.forEach(function(item) {
1026
+ parentList.appendChild(item);
1027
+ });
1028
+ }
1029
+
1030
+ updateCheckboxCounts();
1031
+
1032
+ function delayedUpdate(excludeField) {
1033
+ setTimeout(function() {
1034
+ updateCheckboxCounts(excludeField);
1035
+ }, 200);
1036
+ }
1037
+
1038
+ document.querySelectorAll('.w-checkbox').forEach(function(checkbox) {
1039
+ checkbox.addEventListener('click', function() {
1040
+ const spanElement = checkbox.closest('label').querySelector('span[fs-cmsfilter-field]');
1041
+ if (spanElement) {
1042
+ const field = spanElement.getAttribute('fs-cmsfilter-field');
1043
+ delayedUpdate(field);
1044
+ }
1045
+ });
1046
+ });
1047
+
1048
+ document.querySelectorAll('.cross-icon').forEach(function(icon) {
1049
+ icon.addEventListener('click', function() {
1050
+ delayedUpdate(null); // Update all fields with 200ms delay
1051
+ });
1052
+ });
1053
+
1054
+ document.querySelectorAll('.filters-clients_dropdown-field').forEach(function(dropdownField) {
1055
+ dropdownField.addEventListener('click', function() {
1056
+ delayedUpdate(null); // Update all fields with 200ms delay
1057
+ });
1058
+ });
1059
+
1060
+ function toggleClearButton() {
1061
+ if (document.querySelectorAll('.active-dropdown').length > 0) {
1062
+ document.querySelector('.clear-button').style.display = 'block';
1063
+ } else {
1064
+ document.querySelector('.clear-button').style.display = 'none';
1065
+ }
1066
+ }
1067
+ toggleClearButton();
1068
+ const observer = new MutationObserver(toggleClearButton);
1069
+
1070
+ observer.observe(document.body, {
1071
+ childList: true,
1072
+ subtree: true,
1073
+ attributes: true,
1074
+ attributeFilter: ['class']
1075
+ });
1076
+
1077
+ document.querySelectorAll('[fs-cmsfilter-element="dropdown"]').forEach(function(dropdown) {
1078
+ const originalText = dropdown.querySelector('[filters-clients_dropdown-field="tag-name-title"]').textContent;
1079
+ let firstCheckedText = null;
1080
+
1081
+ dropdown.querySelectorAll('input[type="checkbox"]').forEach(function(checkbox) {
1082
+ checkbox.addEventListener('change', function() {
1083
+ const checkedBoxes = dropdown.querySelectorAll('input[type="checkbox"]:checked');
1084
+ const titleField = dropdown.querySelector('[filters-clients_dropdown-field="tag-name-title"]');
1085
+ const dropdownHolder = dropdown.closest('.dropdown-holder');
1086
+ const tagNumber = dropdown.querySelector('[fs-cmsfilter-element="tag-number"]');
1087
+
1088
+ if (checkedBoxes.length > 0) {
1089
+ // Check if firstCheckedText is still checked
1090
+ if (![...checkedBoxes].some(cb => cb.nextElementSibling.textContent.split('(')[0].trim() === firstCheckedText)) {
1091
+ // If not, set it to the current checkbox text without the count
1092
+ firstCheckedText = checkedBoxes[0].nextElementSibling.textContent.split('(')[0].trim();
1093
+ }
1094
+ titleField.textContent = firstCheckedText;
1095
+ dropdownHolder.classList.add('active-dropdown');
1096
+ } else {
1097
+ titleField.textContent = originalText;
1098
+ dropdownHolder.classList.remove('active-dropdown');
1099
+ firstCheckedText = null;
1100
+ }
1101
+
1102
+ if (checkedBoxes.length > 1) {
1103
+ const numberText = `+${checkedBoxes.length - 1}`;
1104
+ tagNumber.textContent = numberText;
1105
+ } else {
1106
+ tagNumber.textContent = '';
1107
+ }
1108
+ });
1109
+ });
1110
+ });
1111
+ }
1112
+
1113
+ // Filtering logic on Client's page
1114
+ window.formatCounter = function() {
1115
+ function format_number(x) {
1116
+ let parts = x.toFixed(1).split(".");
1117
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
1118
+ let formattedNumber = parts.join(".");
1119
+ let digits = formattedNumber.split('').map(char => {
1120
+ if (char === '.') {
1121
+ return char;
1122
+ } else {
1123
+ return `<span class="single-number">${char}</span>`;
1124
+ }
1125
+ }).join('');
1126
+ return digits;
1127
+ }
1128
+
1129
+ function easeOutQuad(t) {
1130
+ return t * (2 - t);
1131
+ }
1132
+
1133
+ function animateValue(start, end, duration) {
1134
+ const counter = document.getElementById('counter');
1135
+ let startTimestamp = null;
1136
+ const step = (timestamp) => {
1137
+ if (!startTimestamp) startTimestamp = timestamp;
1138
+ const progress = Math.min((timestamp - startTimestamp) / duration, 1);
1139
+ const easedProgress = easeOutQuad(progress);
1140
+ const currentValue = start + (end - start) * easedProgress;
1141
+ counter.innerHTML = format_number(currentValue);
1142
+ if (progress < 1) {
1143
+ window.requestAnimationFrame(step);
1144
+ }
1145
+ };
1146
+ window.requestAnimationFrame(step);
1147
+ }
1148
+
1149
+ animateValue(52.0, 56.2, 3500);
1150
+ }
1151
+
1152
+ // GSAP Counter Up Animation onc Client's Page
971
1153
  window.counterUpAnimation = function() {
1154
+
1155
+
1156
+ function format_number(x) {
1157
+ let parts = x.toFixed(1).split(".");
1158
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ".");
1159
+ let formattedNumber = parts.join(".");
1160
+ let digits = formattedNumber.split('').map(char => {
1161
+ if (char === '.') {
1162
+ return char;
1163
+ } else {
1164
+ return `<span class="single-number">${char}</span>`;
1165
+ }
1166
+ }).join('');
1167
+ return digits;
1168
+ }
1169
+
1170
+ function easeOutQuad(t) {
1171
+ return t * (2 - t);
1172
+ }
1173
+
1174
+ function animateValue(start, end, duration) {
1175
+ const counter = document.getElementById('counter');
1176
+ let startTimestamp = null;
1177
+ const step = (timestamp) => {
1178
+ if (!startTimestamp) startTimestamp = timestamp;
1179
+ const progress = Math.min((timestamp - startTimestamp) / duration, 1);
1180
+ const easedProgress = easeOutQuad(progress);
1181
+ const currentValue = start + (end - start) * easedProgress;
1182
+ counter.innerHTML = format_number(currentValue);
1183
+ if (progress < 1) {
1184
+ window.requestAnimationFrame(step);
1185
+ }
1186
+ };
1187
+ window.requestAnimationFrame(step);
1188
+ }
1189
+
1190
+ animateValue(52.0, 56.2, 3500);
1191
+
1192
+
972
1193
  const counters = document.querySelectorAll('#counter');
973
1194
 
974
1195
  counters.forEach(counter => {
975
- // Get the final value from the element's text content and parse it as a float
976
1196
  const finalValue = parseFloat(counter.textContent.replace(/,/g, '')); // Handle comma-separated numbers
977
1197
 
978
- // Create a GSAP animation for the counter
979
1198
  gsap.fromTo(counter,
980
1199
  { innerHTML: 0 },
981
1200
  {
982
1201
  innerHTML: finalValue,
983
- duration: 2, // Animation duration in seconds
1202
+ duration: 2,
984
1203
  ease: 'power1.inOut',
985
- snap: { innerHTML: 1 }, // Ensure whole numbers
1204
+ snap: { innerHTML: 1 },
986
1205
  onUpdate: function() {
987
- // Update the element's text content with the current value
988
- counter.textContent = this.targets()[0].innerHTML.toLocaleString(); // Format with commas if needed
1206
+
1207
+ counter.textContent = this.targets()[0].innerHTML.toLocaleString();
989
1208
  }
990
1209
  }
991
1210
  );
992
1211
  });
993
1212
  }
994
1213
 
995
-
996
-
997
-
998
-
1214
+ // Slider on Client's page
999
1215
  window.heroSliders = function(e) {
1000
1216
  console.log("Initializing Splide on element:", e);
1001
1217
 
@@ -1021,7 +1237,6 @@ window.heroSliders = function(e) {
1021
1237
 
1022
1238
  const descriptions = e.querySelectorAll('.slider-description');
1023
1239
 
1024
- // Set the initial state: Hide descriptions except the one in the active slide
1025
1240
  descriptions.forEach(desc => {
1026
1241
  if (!desc.closest('.splide__slide').classList.contains('is-active')) {
1027
1242
  gsap.set(desc, { opacity: 0 });
@@ -1034,12 +1249,10 @@ window.heroSliders = function(e) {
1034
1249
  });
1035
1250
  }
1036
1251
 
1037
- // Hide descriptions instantly on slide change
1038
1252
  slider.on('move', function() {
1039
1253
  gsap.set(descriptions, { opacity: 0 });
1040
1254
  });
1041
1255
 
1042
- // Show description on new active slide
1043
1256
  slider.on('active', function (slide) {
1044
1257
  gsap.to(slide.slide.querySelectorAll('.slider-description'), { opacity: 1, duration: 0.15, ease: 'linear' });
1045
1258
  });
@@ -1060,7 +1273,44 @@ window.heroSliders = function(e) {
1060
1273
 
1061
1274
 
1062
1275
 
1063
-
1276
+ // Sliders on Services page
1277
+ window.servicesSliders = function(e) {
1278
+ const config = {
1279
+ type: 'loop',
1280
+ perPage: 1,
1281
+ gap: 0,
1282
+ arrows: false,
1283
+ drag: false,
1284
+ duration: 0.15,
1285
+ easing: 'cubic-bezier(0.83, 0, 0.17, 1)',
1286
+ classes: {
1287
+ pagination: 'splide__pagination services-pagination',
1288
+ page: 'splide__pagination__page services-page',
1289
+ },
1290
+ breakpoints: {
1291
+ 992: { drag: true, fixedWidth: '90%' },
1292
+ 480: {},
1293
+ },
1294
+ };
1295
+ const slider = new Splide(e, config).mount();
1296
+ if (window.innerWidth > 992) {
1297
+ slider.on('click', function () {
1298
+ slider.go('+1');
1299
+ });
1300
+ }
1301
+ gsap.from(e, {
1302
+ scrollTrigger: {
1303
+ trigger: e,
1304
+ start: 'top bottom',
1305
+ end: 'bottom bottom+=15%',
1306
+ scrub: 1,
1307
+ once: true,
1308
+ },
1309
+ x: '10%',
1310
+ opacity: 0,
1311
+ ease: 'linear',
1312
+ });
1313
+ }
1064
1314
 
1065
1315
 
1066
1316