cookiecraft 1.0.0 → 1.0.3

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.
@@ -518,6 +518,35 @@
518
518
  return '';
519
519
  }
520
520
 
521
+ /**
522
+ * Adjust a hex color brightness by a percentage
523
+ * Negative = darker, positive = lighter
524
+ */
525
+ function adjustColorBrightness(color, percent) {
526
+ const hex = color.replace('#', '');
527
+ const r = parseInt(hex.substring(0, 2), 16);
528
+ const g = parseInt(hex.substring(2, 4), 16);
529
+ const b = parseInt(hex.substring(4, 6), 16);
530
+ const adjust = (value) => {
531
+ const adjusted = value + (value * percent / 100);
532
+ return Math.max(0, Math.min(255, Math.round(adjusted)));
533
+ };
534
+ const toHex = (value) => {
535
+ const h = value.toString(16);
536
+ return h.length === 1 ? '0' + h : h;
537
+ };
538
+ return `#${toHex(adjust(r))}${toHex(adjust(g))}${toHex(adjust(b))}`;
539
+ }
540
+ /**
541
+ * Build inline CSS custom properties for a primary color
542
+ */
543
+ function buildColorStyle(safeColor) {
544
+ if (!safeColor)
545
+ return '';
546
+ const hover = adjustColorBrightness(safeColor, -15);
547
+ return `--cc-primary: ${safeColor}; --cc-primary-hover: ${hover};`;
548
+ }
549
+
521
550
  /**
522
551
  * Banner - Cookie consent banner component
523
552
  */
@@ -531,24 +560,28 @@
531
560
  * Show the banner
532
561
  */
533
562
  show() {
534
- var _a;
535
- if (!this.element) {
536
- this.element = this.createDOM();
537
- document.body.appendChild(this.element);
538
- this.attachListeners();
539
- }
540
- // Trigger animation
541
- requestAnimationFrame(() => {
542
- var _a;
543
- (_a = this.element) === null || _a === void 0 ? void 0 : _a.classList.add('is-visible');
544
- });
545
- // Focus first button for accessibility
546
- const firstButton = (_a = this.element) === null || _a === void 0 ? void 0 : _a.querySelector('button');
547
- firstButton === null || firstButton === void 0 ? void 0 : firstButton.focus();
548
- // Disable page interaction if configured
549
- if (this.config.disablePageInteraction) {
550
- document.body.style.overflow = 'hidden';
563
+ const append = () => {
564
+ if (!this.element) {
565
+ this.element = this.createDOM();
566
+ document.body.appendChild(this.element);
567
+ this.attachListeners();
568
+ }
569
+ // Trigger animation
570
+ requestAnimationFrame(() => {
571
+ var _a;
572
+ (_a = this.element) === null || _a === void 0 ? void 0 : _a.classList.add('is-visible');
573
+ });
574
+ // Disable page interaction if configured
575
+ if (this.config.disablePageInteraction) {
576
+ document.body.style.overflow = 'hidden';
577
+ }
578
+ };
579
+ // Wait for body if not yet available
580
+ if (!document.body) {
581
+ document.addEventListener('DOMContentLoaded', append);
582
+ return;
551
583
  }
584
+ append();
552
585
  }
553
586
  /**
554
587
  * Hide the banner
@@ -583,7 +616,7 @@
583
616
  const layout = this.config.layout || 'bar';
584
617
  const backdropBlur = this.config.backdropBlur !== false;
585
618
  const safeColor = this.config.primaryColor ? sanitizeColor(this.config.primaryColor) : '';
586
- const colorStyle = safeColor ? `--cc-primary: ${safeColor};` : '';
619
+ const colorStyle = buildColorStyle(safeColor);
587
620
  const template = `
588
621
  <div
589
622
  class="cc-banner cc-banner--${escapeHtml(position)} cc-banner--${escapeHtml(layout)} ${backdropBlur ? 'cc-backdrop-blur' : ''}"
@@ -603,6 +636,13 @@
603
636
  </p>
604
637
  </div>
605
638
  <div class="cc-banner__actions">
639
+ <button
640
+ class="cc-btn cc-btn--ghost"
641
+ data-action="reject"
642
+ aria-label="${escapeHtml(translations.rejectAll || 'Uniquement essentiels')}"
643
+ >
644
+ ${escapeHtml(translations.rejectAll || 'Uniquement essentiels')}
645
+ </button>
606
646
  <button
607
647
  class="cc-btn cc-btn--tertiary"
608
648
  data-action="customize"
@@ -610,13 +650,6 @@
610
650
  >
611
651
  ${escapeHtml(translations.customize || 'Personnaliser')}
612
652
  </button>
613
- <button
614
- class="cc-btn cc-btn--reject"
615
- data-action="reject"
616
- aria-label="${escapeHtml(translations.rejectAll || 'Tout refuser')}"
617
- >
618
- ${escapeHtml(translations.rejectAll || 'Tout refuser')}
619
- </button>
620
653
  <button
621
654
  class="cc-btn cc-btn--accept"
622
655
  data-action="accept"
@@ -737,15 +770,22 @@
737
770
  * Show the preference center
738
771
  */
739
772
  show() {
740
- if (!this.element) {
741
- this.element = this.createDOM();
742
- document.body.appendChild(this.element);
743
- this.attachListeners();
773
+ const append = () => {
774
+ if (!this.element) {
775
+ this.element = this.createDOM();
776
+ document.body.appendChild(this.element);
777
+ this.attachListeners();
778
+ }
779
+ this.element.classList.add('is-visible');
780
+ this.trapFocus();
781
+ // Prevent body scroll
782
+ document.body.style.overflow = 'hidden';
783
+ };
784
+ if (!document.body) {
785
+ document.addEventListener('DOMContentLoaded', append);
786
+ return;
744
787
  }
745
- this.element.classList.add('is-visible');
746
- this.trapFocus();
747
- // Prevent body scroll
748
- document.body.style.overflow = 'hidden';
788
+ append();
749
789
  }
750
790
  /**
751
791
  * Hide the preference center
@@ -775,9 +815,7 @@
775
815
  const theme = this.config.theme || 'light';
776
816
  const position = this.config.preferencesPosition || 'center';
777
817
  const safeColor = this.config.primaryColor ? sanitizeColor(this.config.primaryColor) : '';
778
- const colorStyle = safeColor
779
- ? `--cc-primary: ${safeColor}; --cc-primary-hover: ${this.adjustColorBrightness(safeColor, -15)};`
780
- : '';
818
+ const colorStyle = buildColorStyle(safeColor);
781
819
  const privacyLinkHtml = translations.privacyPolicyUrl
782
820
  ? (() => {
783
821
  const safeUrl = sanitizeUrl(translations.privacyPolicyUrl);
@@ -975,28 +1013,6 @@
975
1013
  }
976
1014
  });
977
1015
  }
978
- /**
979
- * Adjust color brightness for hover effect
980
- */
981
- adjustColorBrightness(color, percent) {
982
- // Remove # if present
983
- const hex = color.replace('#', '');
984
- // Convert to RGB
985
- const r = parseInt(hex.substring(0, 2), 16);
986
- const g = parseInt(hex.substring(2, 4), 16);
987
- const b = parseInt(hex.substring(4, 6), 16);
988
- // Adjust brightness
989
- const adjust = (value) => {
990
- const adjusted = value + (value * percent / 100);
991
- return Math.max(0, Math.min(255, Math.round(adjusted)));
992
- };
993
- // Convert back to hex
994
- const toHex = (value) => {
995
- const hex = value.toString(16);
996
- return hex.length === 1 ? '0' + hex : hex;
997
- };
998
- return `#${toHex(adjust(r))}${toHex(adjust(g))}${toHex(adjust(b))}`;
999
- }
1000
1016
  }
1001
1017
 
1002
1018
  /**
@@ -1014,17 +1030,24 @@
1014
1030
  * Show the floating widget
1015
1031
  */
1016
1032
  show() {
1017
- if (!this.element) {
1018
- this.element = this.createDOM();
1019
- document.body.appendChild(this.element);
1020
- this.attachListeners();
1033
+ const append = () => {
1034
+ if (!this.element) {
1035
+ this.element = this.createDOM();
1036
+ document.body.appendChild(this.element);
1037
+ this.attachListeners();
1038
+ }
1039
+ // Delay to allow for transition
1040
+ requestAnimationFrame(() => {
1041
+ var _a;
1042
+ (_a = this.element) === null || _a === void 0 ? void 0 : _a.classList.add('is-visible');
1043
+ this.isVisible = true;
1044
+ });
1045
+ };
1046
+ if (!document.body) {
1047
+ document.addEventListener('DOMContentLoaded', append);
1048
+ return;
1021
1049
  }
1022
- // Delay to allow for transition
1023
- requestAnimationFrame(() => {
1024
- var _a;
1025
- (_a = this.element) === null || _a === void 0 ? void 0 : _a.classList.add('is-visible');
1026
- this.isVisible = true;
1027
- });
1050
+ append();
1028
1051
  }
1029
1052
  /**
1030
1053
  * Hide the floating widget
@@ -1059,7 +1082,7 @@
1059
1082
  const widgetPosition = this.config.widgetPosition || 'bottom-right';
1060
1083
  const widgetStyle = this.config.widgetStyle || 'full';
1061
1084
  const safeColor = this.config.primaryColor ? sanitizeColor(this.config.primaryColor) : '';
1062
- const colorStyle = safeColor ? `--cc-primary: ${safeColor};` : '';
1085
+ const colorStyle = buildColorStyle(safeColor);
1063
1086
  const template = `
1064
1087
  <div
1065
1088
  class="cc-widget cc-widget--${escapeHtml(widgetPosition)} cc-widget--${escapeHtml(widgetStyle)}"
@@ -1069,13 +1092,17 @@
1069
1092
  data-theme="${escapeHtml(theme)}"
1070
1093
  style="${colorStyle}"
1071
1094
  >
1072
- <svg class="cc-widget__icon" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor">
1073
- <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8z"/>
1074
- <circle cx="12" cy="12" r="2"/>
1075
- <circle cx="7" cy="7" r="1.5"/>
1076
- <circle cx="17" cy="7" r="1.5"/>
1077
- <circle cx="7" cy="17" r="1.5"/>
1078
- <circle cx="17" cy="17" r="1.5"/>
1095
+ <svg class="cc-widget__icon" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
1096
+ <defs>
1097
+ <path id="cc-ck-a" d="M6,9 C5.448,9 5,8.552 5,8 C5,7.448 5.448,7 6,7 C6.552,7 7,7.448 7,8 C7,8.552 6.552,9 6,9 Z M0.5,5 C0.776,5 1,5.224 1,5.5 C1,5.776 0.776,6 0.5,6 C0.224,6 0,5.776 0,5.5 C0,5.224 0.224,5 0.5,5 Z M1.5,0 C1.776,0 2,0.224 2,0.5 C2,0.776 1.776,1 1.5,1 C1.224,1 1,0.776 1,0.5 C1,0.224 1.224,0 1.5,0 Z"/>
1098
+ <path id="cc-ck-c" d="M16.899,14.984 C14.727,14.802 12.991,13.088 12.773,10.927 C10.117,10.808 8,8.617 8,5.932 C8,4.837 8.352,3.824 8.949,3 C5.027,3.515 2,6.87 2,10.932 C2,15.35 5.582,18.932 10,18.932 C12.939,18.932 15.509,17.346 16.899,14.984 Z M18.623,15.998 C16.839,19.029 13.583,20.932 10,20.932 C4.477,20.932 0,16.454 0,10.932 C0,5.897 3.74,1.666 8.689,1.017 C10.429,0.789 11.599,2.753 10.568,4.174 C10.2,4.682 10,5.289 10,5.932 C10,7.537 11.265,8.857 12.862,8.929 C13.854,8.973 14.663,9.738 14.763,10.726 C14.884,11.932 15.857,12.889 17.067,12.991 C18.535,13.114 19.37,14.729 18.623,15.998 Z M10,18 C8.343,18 7,16.657 7,15 C7,13.343 8.343,12 10,12 C11.657,12 13,13.343 13,15 C13,16.657 11.657,18 10,18 Z M10,16 C10.552,16 11,15.552 11,15 C11,14.448 10.552,14 10,14 C9.448,14 9,14.448 9,15 C9,15.552 9.448,16 10,16 Z M4.5,14 C3.672,14 3,13.328 3,12.5 C3,11.672 3.672,11 4.5,11 C5.328,11 6,11.672 6,12.5 C6,13.328 5.328,14 4.5,14 Z M4.5,12 C4.224,12 4,12.224 4,12.5 C4,12.776 4.224,13 4.5,13 C4.776,13 5,12.776 5,12.5 C5,12.224 4.776,12 4.5,12 Z M5.5,9 C4.672,9 4,8.328 4,7.5 C4,6.672 4.672,6 5.5,6 C6.328,6 7,6.672 7,7.5 C7,8.328 6.328,9 5.5,9 Z M5.5,7 C5.224,7 5,7.224 5,7.5 C5,7.776 5.224,8 5.5,8 C5.776,8 6,7.776 6,7.5 C6,7.224 5.776,7 5.5,7 Z"/>
1099
+ </defs>
1100
+ <g fill="currentColor" fill-rule="evenodd" transform="translate(3 1)">
1101
+ <g transform="translate(4 7)">
1102
+ <use href="#cc-ck-a"/>
1103
+ </g>
1104
+ <use href="#cc-ck-c"/>
1105
+ </g>
1079
1106
  </svg>
1080
1107
  <span class="cc-widget__text">
1081
1108
  ${escapeHtml(translations.cookies || 'Cookies')}
@@ -1378,6 +1405,9 @@
1378
1405
  this.showBanner();
1379
1406
  }
1380
1407
  }
1408
+ // Store instance globally so it won't be garbage collected
1409
+ // when used without a variable (e.g. new CookieConsent({}).init())
1410
+ window.cookieConsent = this;
1381
1411
  this.eventEmitter.emit('consent:init');
1382
1412
  }
1383
1413
  /**
@@ -1506,7 +1536,7 @@
1506
1536
  * Validate and set default config values
1507
1537
  */
1508
1538
  validateConfig(config) {
1509
- return Object.assign(Object.assign({}, config), { mode: config.mode || 'opt-in', autoShow: config.autoShow !== undefined ? config.autoShow : true, revision: config.revision || 1, gtmConsentMode: config.gtmConsentMode || false, disablePageInteraction: config.disablePageInteraction || false, theme: config.theme || 'light', position: config.position || 'bottom', layout: config.layout || 'bar', backdropBlur: config.backdropBlur !== false, animationStyle: config.animationStyle || 'smooth', preferencesPosition: config.preferencesPosition || 'center', showWidget: config.showWidget !== undefined ? config.showWidget : true, widgetPosition: config.widgetPosition || 'bottom-right', widgetStyle: config.widgetStyle || 'full' });
1539
+ return Object.assign(Object.assign({}, config), { mode: config.mode || 'opt-in', autoShow: config.autoShow !== undefined ? config.autoShow : true, revision: config.revision || 1, gtmConsentMode: config.gtmConsentMode !== undefined ? config.gtmConsentMode : true, disablePageInteraction: config.disablePageInteraction || false, theme: config.theme || 'light', position: config.position || 'bottom-left', layout: config.layout || 'box', backdropBlur: config.backdropBlur !== false, animationStyle: config.animationStyle || 'smooth', preferencesPosition: config.preferencesPosition || 'center', showWidget: config.showWidget !== undefined ? config.showWidget : true, widgetPosition: config.widgetPosition || 'bottom-left', widgetStyle: config.widgetStyle || 'compact' });
1510
1540
  }
1511
1541
  }
1512
1542