@magicfeedback/popup-sdk 1.1.8 → 1.3.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/dist/index.js CHANGED
@@ -181,6 +181,14 @@ var init_font = __esm({
181
181
  }
182
182
  });
183
183
 
184
+ // src/assets/style.css
185
+ var style_default;
186
+ var init_style = __esm({
187
+ "src/assets/style.css"() {
188
+ style_default = '.magicfeedback-container {\n width: 100%;\n}\n\n\n.magicfeedback-success-message,\n.magicfeedback-info-message,\n.magicfeedback-start-message,\n.magicfeedback-container{\n animation-duration: 0.5s;\n animation-name: animate-fade;\n animation-delay: 0.25s;\n animation-fill-mode: backwards;\n\n font-style: normal;\n text-align: justify;\n font-weight: 400;\n font-size: 1.2rem;\n color: #475569;\n line-height: 1.5;\n}\n\n@keyframes animate-fade {\n 0% { opacity: 0; }\n 100% { opacity: 1; }\n}\n\n.magicfeedback-form {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: center;\n width: 100%;\n}\n.magicfeedback-questions {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: flex-start;\n width: 100%;\n}\n\n.magicfeedback-div {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n align-items: flex-start;\n margin-bottom: 10px;\n width: 100%;\n}\n\n.magicfeedback-label {\n margin-bottom: 25px;\n margin-top: 20px;\n font-weight: 400;\n font-family: inherit;\n font-size: 1.2rem;\n color: #212529;\n text-align: start;\n word-wrap: break-word;\n white-space: normal;\n\n}\n\n.magicfeedback-checkbox {\n display: flex;\n flex-direction: column;\n flex-wrap: wrap;\n width: 100%;\n}\n\n.magicfeedback-checkbox-container {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin-bottom: 5px;\n margin-top: 5px;\n}\n\n/* Cualificado con `div`: @magicfeedback/native reutiliza la clase "magicfeedback-radio"\n tambi\xE9n en el <input> de cada opci\xF3n (rating), y sin el tag este selector lo capturaba\n tambi\xE9n, rompiendo su tama\xF1o (el input pasaba a display:flex; width:100%). */\ndiv.magicfeedback-radio {\n display: flex;\n flex-direction: column;\n justify-content: flex-start;\n flex-wrap: wrap;\n width: 100%;\n margin-right: 5px;\n padding: 5px;\n box-sizing: border-box;\n}\n\n.magicfeedback-checkbox-container,\n.magicfeedback-radio-container {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin: 5px;\n padding: 5px 0;\n background-color: #fff;\n border-radius: 5px;\n box-shadow: 0 0 3px #ccc;\n}\n\n.deepdots-popup input::-webkit-outer-spin-button,\n.deepdots-popup input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n -moz-appearance: textfield;\n}\n\n.magicfeedback-checkbox input[type="checkbox"] {\n margin-right: 5px;\n margin-left: 5px;\n width: 20px;\n height: 20px;\n cursor: pointer;\n}\n\n\n.magicfeedback-checkbox label,\n.magicfeedback-radio-container label {\n margin-left: 5px;\n font-weight: 400;\n font-family: inherit;\n font-size: 16px;\n color: #212529;\n text-align: start;\n width: 100%;\n}\n\n.deepdots-popup p {\n margin-bottom: 0px;\n font-size: 12px;\n}\n\n.deepdots-popup h2 {\n line-height: 1.66;\n margin: 0;\n padding: 0;\n font-weight: 900;\n color: #222;\n font-family: var(--deepdots-font, \'Montserrat\');\n font-size: 18px;\n text-transform: uppercase;\n text-align: center;\n margin-bottom: 40px;\n}\n\n/* Los controles de formulario no heredan font-family por defecto: cuando hay\n fuente custom (clase deepdots-has-font), los forzamos a usar la del contenedor. */\n.deepdots-popup.deepdots-has-font button,\n.deepdots-popup.deepdots-has-font input,\n.deepdots-popup.deepdots-has-font textarea,\n.deepdots-popup.deepdots-has-font select {\n font-family: var(--deepdots-font, inherit);\n}\n\n.deepdots-popup h6 {\n margin-bottom: 1rem;\n}\n\n.deepdots-popup input[type="date"],\n.deepdots-popup input[type="text"],\n.deepdots-popup input[type="number"],\n.deepdots-popup input[type="email"],\n.deepdots-popup input[type="password"],\n.deepdots-popup textarea,\n.deepdots-popup select {\n box-sizing: border-box;\n padding: 10px;\n margin: 10px 0;\n width: 100%;\n border: 2px solid #ccc; /* Default border color - you can customize this */\n border-radius: 5px;\n font-size: 18px;\n outline: none;\n transition: border-color 0.3s ease;\n min-height: 50px;\n font-family: inherit;\n -webkit-appearance: none;\n}\n\n.deepdots-popup select {\n background-image: linear-gradient(45deg, transparent 50%, gray 50%),\n linear-gradient(135deg, gray 50%, transparent 50%),\n linear-gradient(to right, #ccc, #ccc);\n background-position: calc(100% - 20px) calc(1em + 2px),\n calc(100% - 15px) calc(1em + 2px),\n calc(100% - 2.5em) 0.5em;\n background-size: 5px 5px,\n 5px 5px,\n 1px 1.5em;\n background-repeat: no-repeat;\n}\n\n.magicfeedback-boolean-container {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin: 10px 0;\n width: 100%;\n}\n\n.magicfeedback-boolean-container label {\n margin-left: 10px;\n font-weight: 400;\n font-size: 16px;\n width: 100%;\n padding-top: 5px;\n}\n\n.magicfeedback-boolean-option {\n margin-right: 10px;\n margin-left: 10px;\n width: 100%;\n height: 38px;\n border-radius: 8px;\n font-size: 16px;\n cursor: pointer;\n border: 1px solid #ced4da !important;\n}\n\n.magicfeedback-boolean-option label {\n font-weight: 400;\n font-size: 16px;\n color: #475569;\n cursor: pointer;\n width: 100%;\n height: 100%;\n display: flex;\n justify-content: center;\n align-items: center;\n border-radius: inherit;\n}\n\n.magicfeedback-boolean-option input[type=radio] + label:hover {\n color: #007bff;\n}\n\n.magicfeedback-boolean-option input[type=radio]:checked + label {\n color: #007bff;\n background-color: #cadff8;\n}\n\n.deepdots-popup input[type="radio"] {\n padding: 20px;\n margin: 10px 0 10px 15px;\n width: 40px;\n background-color: #fff;\n box-shadow: none;\n}\n\n/* Style for focused input/select */\n.deepdots-popup input:focus, .deepdots-popup select:focus {\n border-color: #4CAF50; /* Highlight color when focused - you can customize this */\n}\n\n/* Style for invalid input (example: validation error) */\n.deepdots-popup input.error, .deepdots-popup select.error {\n border-color: #ff3333; /* Red color for error state - you can customize this */\n}\n\n.magicfeedback-action-container {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n margin-top: 10px;\n width: 100%;\n}\n\n.magicfeedback-action-container .magicfeedback-submit {\n cursor: pointer;\n padding: 10px;\n margin: 10px 0;\n width: 100px;\n border-radius: 8px;\n font-size: 16px;\n outline: none;\n transition: border-color 0.3s ease;\n background-color: #1E293B;\n color: white;\n}\n\n.magicfeedback-action-container .magicfeedback-back {\n cursor: pointer;\n padding: 10px;\n margin: 10px 0;\n width: 100px;\n border: 0;\n border-radius: 8px;\n font-size: 16px;\n outline: none;\n transition: border-color 0.3s ease;\n background-color: transparent;\n color: #212529;\n}\n\n\n\n/* Rating styles */\n.magicfeedback-rating {\n width: 100%;\n}\n\n.magicfeedback-rating-container {\n display: flex;\n flex-direction: row;\n justify-content: space-around;\n flex-wrap: wrap;\n align-items: center;\n\n margin: 15px 5px;\n padding: 0;\n\n list-style: none;\n font-size: 1.5rem;\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n}\n\n.magicfeedback-rating-placeholder-value,\n.magicfeedback-rating-placeholder{\n text-align: center;\n align-content: center;\n justify-content: center;\n text-wrap: wrap;\n}\n\n.magicfeedback-rating-option {\n margin: 0 0.5rem;\n padding: 0;\n}\n\n@media (max-width: 1024px) {\n .magicfeedback-rating-option {\n margin: 10px 0;\n padding: 0;\n width: 20%;\n display: flex;\n justify-content: center;\n }\n\n .magicfeedback-rating-placeholder-value {\n font-size: 0.75rem;\n margin-bottom: 1px;\n }\n .magicfeedback-rating-placeholder{\n justify-content: center;\n }\n\n .magicfeedback-rating-container {\n flex-wrap: wrap;\n justify-content: flex-start;\n }\n}\n\n\n.magicfeedback-rating-option-label-container {\n display: flex;\n flex-direction: column;\n}\n\n\n.magicfeedback-rating-option-label-container label {\n display: inline-block;\n text-align: center;\n margin-bottom: 0;\n font-weight: 600;\n font-size: 18px;\n color: #475569;\n}\n\n.magicfeedback-rating-option-label-container input[type=radio] {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n}\n\n/* IMAGE STYLES */\n.magicfeedback-rating-option-label-container input[type=radio] + img {\n cursor: pointer;\n height: 48px;\n width: 48px;\n}\n\n/* LABEL STYLES */\n.magicfeedback-rating-option-label-container input[type=radio] + label {\n cursor: pointer;\n}\n\n/* CHECKED STYLES */\n.magicfeedback-rating-option-label-container input[type=radio]:checked + img {\n box-shadow: #007bff 0px 1px 4px, #007BFFA0 0px 0px 0px 2px;\n border-radius: 50%;\n}\n\n.magicfeedback-rating-number {\n width: 100%;\n}\n.magicfeedback-rating-container,\n.magicfeedback-rating-number-container {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n\n margin: 15px 0;\n padding: 0;\n\n list-style: none;\n font-size: 1.5rem;\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n}\n\n/* Cuando hay placeholders (Very bad / Very good), el placeholder ocupa\n el 100% de la primera l\xEDnea y los boxes bajan a la siguiente */\n.magicfeedback-rating-number-container--with-placeholder {\n flex-wrap: wrap;\n align-items: flex-start;\n}\n\n.magicfeedback-rating-number-container--with-placeholder .magicfeedback-rating-placeholder {\n width: 100%;\n margin-bottom: 8px;\n}\n\n.magicfeedback-rating-number-container--with-placeholder .magicfeedback-rating-number-option {\n width: auto;\n flex: 1;\n}\n\n.magicfeedback-rating-number-option {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin: 5px;\n padding: 0;\n list-style: none;\n font-size: 1.5rem;\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n width: 100%;\n}\n\n.magicfeedback-rating-number-option-row{\n max-width: 100% !important;\n}\n\n.magicfeedback-rating-number-top-placeholder,\n.magicfeedback-rating-number-bottom-placeholder{\n text-align: center !important;\n align-content: center;\n justify-content: center;\n text-wrap: wrap;\n\n font-size: 15px;\n color: #475569;\n\n width: 100%;\n margin: auto;\n}\n\n@media (min-width: 650px) {\n .magicfeedback-rating-number-option-row +.magicfeedback-rating-number-container-ltr:first-child,\n .magicfeedback-rating-number-option-row + +.magicfeedback-rating-number-container-rtl:last-child {\n margin-left: 0;\n width: calc(100% - 10px);\n }\n\n .magicfeedback-rating-number-option-row +.magicfeedback-rating-number-container-rtl:first-child,\n .magicfeedback-rating-number-option-row + +.magicfeedback-rating-number-container-ltr:last-child {\n margin-right: 0;\n width: calc(100% - 10px);\n }\n}\n\n\n.magicfeedback-rating-number-option-label-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n width: 100%;\n height: 100%;\n}\n\n.magicfeedback-rating-number-option-label-container label {\n display: flex;\n align-items: center;\n justify-content: center;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n margin: 0 10px;\n font-weight: 600;\n font-size: 14px;\n color: #475569;\n cursor: pointer;\n width: 100%;\n height: 100%;\n min-height: 50px;\n text-align: center;\n padding: 0;\n border-radius: 4px;\n border: 1px solid #ced4da;\n background-color: rgba(246, 246, 246, 0.3);\n transition: background-color 0.15s ease-in-out;\n}\n\n.magicfeedback-rating-number-option-label-container input[type=radio] {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n}\n\n.magicfeedback-rating-number-option-label-container input[type=radio] + label {\n cursor: pointer;\n}\n\n.magicfeedback-rating-number-option-label-container input[type=radio] + label:hover,\n.magicfeedback-rating-number-option-label-container input[type=radio]:checked + label {\n color: #007bff;\n border: 1px solid #007bff;\n background-color: rgba(86, 168, 253, 0.29);\n}\n\n.magicfeedback-rating-number-container-column{\n align-items: flex-start !important;\n}\n\n@media (max-width: 650px) {\n .magicfeedback-rating-number-container-ltr {\n justify-content: center;\n flex-wrap: wrap;\n }\n\n .magicfeedback-rating-number-container-rtl {\n justify-content: center;\n flex-wrap: wrap-reverse;\n }\n\n .magicfeedback-rating-number-option {\n max-width: 100%;\n height: 55px;\n margin: 5px 0;\n }\n}\n\n.magicfeedback-rating-star {\n width: 100%;\n}\n\n.magicfeedback-rating-star-container {\n display: flex !important;\n flex-direction: row !important;\n justify-content: center !important;\n align-items: center !important;\n flex-wrap: wrap;\n margin: 15px 5px;\n padding: 0;\n list-style: none;\n font-size: 1.5rem;\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n}\n\n.magicfeedback-rating-star-option:not(:checked) > .rating__star {\n float: right;\n width: 1em;\n overflow: hidden;\n white-space: nowrap;\n cursor: pointer;\n font-size: 30px;\n color: #ccc;\n margin: 0 10px;\n}\n\n.magicfeedback-rating-star-option:not(:checked) > .rating__star:hover,\n.magicfeedback-rating-star-option:not(:checked) > .rating__star:hover ~ span {\n color: #deb217 !important;\n}\n\n.magicfeedback-rating-star-selected {\n color: #ffc700 !important;\n}\n\n\n/* Style for multiple choice image */\n.magicfeedback-image-option-label-container:hover {\n cursor: pointer;\n border: 0 !important;\n}\n\n.magicfeedback-image-option-label-container input[type=radio]:checked + img,\n.magicfeedback-image-option-label-container input[type=checkbox]:checked + img {\n border: 1px solid #007bff !important;\n box-shadow: 0 0 3px #007bff !important;\n}\n\n.magicfeedback-image-option-label-container input[type=radio] + img,\n.magicfeedback-image-option-label-container input[type=checkbox] + img {\n border: 1px solid transparent !important;\n}\n\n.magicfeedback-image-option-label-container{\n margin: 10px !important;\n height: calc(100% - 20px) !important;\n width: calc(100% - 20px) !important;\n}\n\n.magicfeedback-multiple-choice-image-option {\n display: flex;\n height: auto !important;\n box-shadow: 0 0 3px #ccc;\n}\n\n.magicfeedback-multiple-choice-image-label {\n font-size: 1rem;\n}\n\n.magicfeedback-consent-container {\n display: flex;\n flex-direction: row;\n justify-content: flex-start;\n align-items: center;\n margin: 10px 0;\n width: 100%;\n}\n\n.magicfeedback-consent-container label {\n margin-left: 10px;\n}\n\n.magicfeedback-start-message-container {\n /* ... add your start message container styles here ... */\n}\n\n.magicfeedback-success-message,\n.magicfeedback-info-message,\n.magicfeedback-start-message {\n margin: 35px 5px;\n}\n\n.magicfeedback-success-message p,\n.magicfeedback-info-message p,\n.magicfeedback-start-message p {\n font-style: normal;\n text-align: start;\n font-weight: 400;\n font-size: 16px;\n color: #475569;\n line-height: 1.5;\n}\n\n.magicfeedback-success-message img,\n.magicfeedback-info-message img,\n.magicfeedback-start-message img {\n width: 400px;\n max-width: 80%;\n height: auto;\n margin: 10px auto;\n}\n\n.magicfeedback-counter,\n.magicfeedback-point-system-total {\n margin: 10px 0 0 0 !important;\n display: flex !important;\n justify-content: right !important;\n align-items: center !important;\n width: 100%;\n}\n\n.magicfeedback-skip-container {\n background-color: transparent !important;\n border: 0 !important;\n color: #999999FF !important;\n padding: 0 !important;\n margin: 0 !important;\n cursor: pointer !important;\n font-size: 0.5em !important;\n font-weight: 400 !important;\n box-shadow: 0 0 0 !important;\n\n &:hover {\n color: #0066ff;\n }\n}\n\n.magicfeedback-skip-container input[type=checkbox] {\n border-color: #999999FF !important;\n border: 0 !important;\n cursor: pointer !important;\n\n}\n\n.magicfeedback-multi-question-matrix,\n.magicfeedback-point-system,\n.magicfeedback-priority-list {\n width: 100% !important;\n}\n\n.magicfeedback-multi-question-matrix-container,\n.magicfeedback-point-system-container,\n.magicfeedback-priority-list-container {\n width: 100% !important;\n overflow-x: auto;\n}\n\n.magicfeedback-point-system-list,\n.magicfeedback-priority-list-list,\n.magicfeedback-multi-question-matrix-table {\n width: 100% !important;\n padding: 0 !important;\n overflow-x: auto;\n}\n\n.magicfeedback-multi-question-matrix {\n position: relative !important;\n}\n\n.magicfeedback-multi-question-matrix-container {\n overflow: auto !important;\n padding-bottom: 10px;\n}\n\n.magicfeedback-multi-question-matrix-label{\n text-align: left !important;\n}\n.magicfeedback-priority-list-item {\n display: flex;\n flex-direction: row;\n justify-content: space-between;\n align-items: center;\n padding: 10px 0 10px 10px;\n\n border: 1px solid #ced4da;\n border-radius: 5px;\n margin: 10px 0 !important;\n}\n\n.magicfeedback-point-system-item {\n height: 45px;\n margin: 5px 0 !important;\n}\n\n.magicfeedback-point-system-item label,\n.magicfeedback-priority-list-item-label {\n font-family: inherit;\n font-size: 18px !important;\n color: #212529;\n text-align: start;\n word-wrap: break-word;\n white-space: normal;\n padding: 0 10px 0 0;\n}\n\n.magicfeedback-point-system-input-container {\n padding: 0 10px 0 0;\n border-radius: 5px;\n font-size: 14px;\n border: 1px solid #ced4da;\n height: 42px;\n margin: auto 0;\n}\n\n.magicfeedback-multi-question-matrix-table thead {\n margin-bottom: 20px;\n}\n\n.magicfeedback-multi-question-matrix-table th{\n text-align: center;\n font-weight: 400 !important;\n font-size: 1rem !important;\n padding: 0 10px !important;\n}\n\n.magicfeedback-multi-question-matrix-table th,\n.magicfeedback-multi-question-matrix-table td label,\n.magicfeedback-priority-list-arrow-up,\n.magicfeedback-priority-list-arrow-down {\n font-style: normal !important;\n font-weight: 400 !important;\n font-size: 1rem !important;\n color: #475569 !important;\n cursor: pointer !important;\n margin: 0 !important;\n line-height: inherit;\n}\n\n.magicfeedback-multi-question-matrix-table tr {\n align-items: center;\n margin: 5px 0;\n}\n\n.magicfeedback-multi-question-matrix-row-tr{\n border-radius: 5px;\n margin: 10px 0 !important;\n}\n\n.magicfeedback-multi-question-matrix-row-tr:nth-child(odd) {\n background-color: #f1f6f6; /* Light gray background for odd rows */\n}\n\n.magicfeedback-multi-question-matrix-row-tr:nth-child(even) {\n background-color: #ffffff; /* White background for even rows */\n}\n\n.magicfeedback-multi-question-matrix-row-label {\n text-align: left !important;\n}\n\n.magicfeedback-point-system-item span {\n color: #475569 !important;\n}\n\n.magicfeedback-point-system-item input {\n padding: 0;\n margin: 0 !important;\n width: auto !important;\n min-width: 100px !important;\n height: auto !important;\n min-height: 42px;\n cursor: pointer;\n font-size: 14px;\n text-align: center !important;\n}\n\n.magicfeedback-multi-question-matrix-table input {\n margin: auto !important;\n padding: 20px !important;\n width: 100% !important;\n height: 15px;\n border: 1px solid #ced4da;\n cursor: pointer;\n}\n\n.magicfeedback-image{\n max-height: 400px !important;\n height: auto !important;\n max-width: 100% !important;\n margin: 10px auto !important;\n}\n\n.magicfeedback-error{\n margin-top: 5px;\n}';
189
+ }
190
+ });
191
+
184
192
  // src/util/logger.ts
185
193
  function setLogger(logger) {
186
194
  active = logger ?? console;
@@ -2127,876 +2135,6 @@ var require_magicfeedback_sdk_browser = __commonJS({
2127
2135
  }
2128
2136
  });
2129
2137
 
2130
- // src/assets/style.css
2131
- var style_default;
2132
- var init_style = __esm({
2133
- "src/assets/style.css"() {
2134
- style_default = `.magicfeedback-container {
2135
- width: 100%;
2136
- }
2137
-
2138
-
2139
- .magicfeedback-success-message,
2140
- .magicfeedback-info-message,
2141
- .magicfeedback-start-message,
2142
- .magicfeedback-container{
2143
- animation-duration: 0.5s;
2144
- animation-name: animate-fade;
2145
- animation-delay: 0.25s;
2146
- animation-fill-mode: backwards;
2147
-
2148
- font-style: normal;
2149
- text-align: justify;
2150
- font-weight: 400;
2151
- font-size: 1.2rem;
2152
- color: #475569;
2153
- line-height: 1.5;
2154
- }
2155
-
2156
- @keyframes animate-fade {
2157
- 0% { opacity: 0; }
2158
- 100% { opacity: 1; }
2159
- }
2160
-
2161
- .magicfeedback-form {
2162
- display: flex;
2163
- flex-direction: column;
2164
- justify-content: flex-start;
2165
- align-items: center;
2166
- width: 100%;
2167
- }
2168
- .magicfeedback-questions {
2169
- display: flex;
2170
- flex-direction: column;
2171
- justify-content: flex-start;
2172
- align-items: flex-start;
2173
- width: 100%;
2174
- }
2175
-
2176
- .magicfeedback-div {
2177
- display: flex;
2178
- flex-direction: column;
2179
- justify-content: flex-start;
2180
- align-items: flex-start;
2181
- margin-bottom: 10px;
2182
- width: 100%;
2183
- }
2184
-
2185
- .magicfeedback-label {
2186
- margin-bottom: 25px;
2187
- margin-top: 20px;
2188
- font-weight: 400;
2189
- font-family: inherit;
2190
- font-size: 1.2rem;
2191
- color: #212529;
2192
- text-align: start;
2193
- word-wrap: break-word;
2194
- white-space: normal;
2195
-
2196
- }
2197
-
2198
- .magicfeedback-checkbox {
2199
- display: flex;
2200
- flex-direction: column;
2201
- flex-wrap: wrap;
2202
- width: 100%;
2203
- }
2204
-
2205
- .magicfeedback-checkbox-container {
2206
- display: flex;
2207
- flex-direction: row;
2208
- justify-content: flex-start;
2209
- align-items: center;
2210
- margin-bottom: 5px;
2211
- margin-top: 5px;
2212
- }
2213
-
2214
- .magicfeedback-radio {
2215
- display: flex;
2216
- flex-direction: column;
2217
- justify-content: flex-start;
2218
- flex-wrap: wrap;
2219
- width: 100%;
2220
- margin-right: 5px;
2221
- padding: 5px;
2222
- }
2223
-
2224
- .magicfeedback-checkbox-container,
2225
- .magicfeedback-radio-container {
2226
- display: flex;
2227
- flex-direction: row;
2228
- justify-content: flex-start;
2229
- align-items: center;
2230
- margin: 5px;
2231
- padding: 5px 0;
2232
- background-color: #fff;
2233
- border-radius: 5px;
2234
- box-shadow: 0 0 3px #ccc;
2235
- }
2236
-
2237
- .deepdots-popup input::-webkit-outer-spin-button,
2238
- .deepdots-popup input::-webkit-inner-spin-button {
2239
- -webkit-appearance: none;
2240
- -moz-appearance: textfield;
2241
- }
2242
-
2243
- .magicfeedback-checkbox input[type="checkbox"] {
2244
- margin-right: 5px;
2245
- margin-left: 5px;
2246
- width: 20px;
2247
- height: 20px;
2248
- cursor: pointer;
2249
- }
2250
-
2251
-
2252
- .magicfeedback-checkbox label,
2253
- .magicfeedback-radio-container label {
2254
- margin-left: 5px;
2255
- font-weight: 400;
2256
- font-family: inherit;
2257
- font-size: 16px;
2258
- color: #212529;
2259
- text-align: start;
2260
- width: 100%;
2261
- }
2262
-
2263
- .deepdots-popup p {
2264
- margin-bottom: 0px;
2265
- font-size: 12px;
2266
- }
2267
-
2268
- .deepdots-popup h2 {
2269
- line-height: 1.66;
2270
- margin: 0;
2271
- padding: 0;
2272
- font-weight: 900;
2273
- color: #222;
2274
- font-family: var(--deepdots-font, 'Montserrat');
2275
- font-size: 18px;
2276
- text-transform: uppercase;
2277
- text-align: center;
2278
- margin-bottom: 40px;
2279
- }
2280
-
2281
- /* Los controles de formulario no heredan font-family por defecto: cuando hay
2282
- fuente custom (clase deepdots-has-font), los forzamos a usar la del contenedor. */
2283
- .deepdots-popup.deepdots-has-font button,
2284
- .deepdots-popup.deepdots-has-font input,
2285
- .deepdots-popup.deepdots-has-font textarea,
2286
- .deepdots-popup.deepdots-has-font select {
2287
- font-family: var(--deepdots-font, inherit);
2288
- }
2289
-
2290
- .deepdots-popup h6 {
2291
- margin-bottom: 1rem;
2292
- }
2293
-
2294
- .deepdots-popup input[type="date"],
2295
- .deepdots-popup input[type="text"],
2296
- .deepdots-popup input[type="number"],
2297
- .deepdots-popup input[type="email"],
2298
- .deepdots-popup input[type="password"],
2299
- .deepdots-popup textarea,
2300
- .deepdots-popup select {
2301
- box-sizing: border-box;
2302
- padding: 10px;
2303
- margin: 10px 0;
2304
- width: 100%;
2305
- border: 2px solid #ccc; /* Default border color - you can customize this */
2306
- border-radius: 5px;
2307
- font-size: 18px;
2308
- outline: none;
2309
- transition: border-color 0.3s ease;
2310
- min-height: 50px;
2311
- font-family: inherit;
2312
- -webkit-appearance: none;
2313
- }
2314
-
2315
- .deepdots-popup select {
2316
- background-image: linear-gradient(45deg, transparent 50%, gray 50%),
2317
- linear-gradient(135deg, gray 50%, transparent 50%),
2318
- linear-gradient(to right, #ccc, #ccc);
2319
- background-position: calc(100% - 20px) calc(1em + 2px),
2320
- calc(100% - 15px) calc(1em + 2px),
2321
- calc(100% - 2.5em) 0.5em;
2322
- background-size: 5px 5px,
2323
- 5px 5px,
2324
- 1px 1.5em;
2325
- background-repeat: no-repeat;
2326
- }
2327
-
2328
- .magicfeedback-boolean-container {
2329
- display: flex;
2330
- flex-direction: row;
2331
- justify-content: flex-start;
2332
- align-items: center;
2333
- margin: 10px 0;
2334
- width: 100%;
2335
- }
2336
-
2337
- .magicfeedback-boolean-container label {
2338
- margin-left: 10px;
2339
- font-weight: 400;
2340
- font-size: 16px;
2341
- width: 100%;
2342
- padding-top: 5px;
2343
- }
2344
-
2345
- .magicfeedback-boolean-option {
2346
- margin-right: 10px;
2347
- margin-left: 10px;
2348
- width: 100%;
2349
- height: 38px;
2350
- border-radius: 8px;
2351
- font-size: 16px;
2352
- cursor: pointer;
2353
- border: 1px solid #ced4da !important;
2354
- }
2355
-
2356
- .magicfeedback-boolean-option label {
2357
- font-weight: 400;
2358
- font-size: 16px;
2359
- color: #475569;
2360
- cursor: pointer;
2361
- width: 100%;
2362
- height: 100%;
2363
- display: flex;
2364
- justify-content: center;
2365
- align-items: center;
2366
- border-radius: inherit;
2367
- }
2368
-
2369
- .magicfeedback-boolean-option input[type=radio] + label:hover {
2370
- color: #007bff;
2371
- }
2372
-
2373
- .magicfeedback-boolean-option input[type=radio]:checked + label {
2374
- color: #007bff;
2375
- background-color: #cadff8;
2376
- }
2377
-
2378
- .deepdots-popup input[type="radio"] {
2379
- padding: 20px;
2380
- margin: 10px 0 10px 15px;
2381
- width: 40px;
2382
- background-color: #fff;
2383
- box-shadow: none;
2384
- }
2385
-
2386
- /* Style for focused input/select */
2387
- .deepdots-popup input:focus, .deepdots-popup select:focus {
2388
- border-color: #4CAF50; /* Highlight color when focused - you can customize this */
2389
- }
2390
-
2391
- /* Style for invalid input (example: validation error) */
2392
- .deepdots-popup input.error, .deepdots-popup select.error {
2393
- border-color: #ff3333; /* Red color for error state - you can customize this */
2394
- }
2395
-
2396
- .magicfeedback-action-container {
2397
- display: flex;
2398
- flex-direction: row;
2399
- justify-content: space-between;
2400
- align-items: center;
2401
- margin-top: 10px;
2402
- width: 100%;
2403
- }
2404
-
2405
- .magicfeedback-action-container .magicfeedback-submit {
2406
- cursor: pointer;
2407
- padding: 10px;
2408
- margin: 10px 0;
2409
- width: 100px;
2410
- border-radius: 8px;
2411
- font-size: 16px;
2412
- outline: none;
2413
- transition: border-color 0.3s ease;
2414
- background-color: #1E293B;
2415
- color: white;
2416
- }
2417
-
2418
- .magicfeedback-action-container .magicfeedback-back {
2419
- cursor: pointer;
2420
- padding: 10px;
2421
- margin: 10px 0;
2422
- width: 100px;
2423
- border: 0;
2424
- border-radius: 8px;
2425
- font-size: 16px;
2426
- outline: none;
2427
- transition: border-color 0.3s ease;
2428
- background-color: transparent;
2429
- color: #212529;
2430
- }
2431
-
2432
-
2433
-
2434
- /* Rating styles */
2435
- .magicfeedback-rating {
2436
- width: 100%;
2437
- }
2438
-
2439
- .magicfeedback-rating-container {
2440
- display: flex;
2441
- flex-direction: row;
2442
- justify-content: space-around;
2443
- flex-wrap: wrap;
2444
- align-items: center;
2445
-
2446
- margin: 15px 5px;
2447
- padding: 0;
2448
-
2449
- list-style: none;
2450
- font-size: 1.5rem;
2451
- cursor: pointer;
2452
- user-select: none;
2453
- -webkit-user-select: none;
2454
- -moz-user-select: none;
2455
- -ms-user-select: none;
2456
- }
2457
-
2458
- .magicfeedback-rating-placeholder-value,
2459
- .magicfeedback-rating-placeholder{
2460
- text-align: center;
2461
- align-content: center;
2462
- justify-content: center;
2463
- text-wrap: wrap;
2464
- }
2465
-
2466
- .magicfeedback-rating-option {
2467
- margin: 0 0.5rem;
2468
- padding: 0;
2469
- }
2470
-
2471
- @media (max-width: 1024px) {
2472
- .magicfeedback-rating-option {
2473
- margin: 10px 0;
2474
- padding: 0;
2475
- width: 20%;
2476
- display: flex;
2477
- justify-content: center;
2478
- }
2479
-
2480
- .magicfeedback-rating-placeholder-value {
2481
- font-size: 0.75rem;
2482
- margin-bottom: 1px;
2483
- }
2484
- .magicfeedback-rating-placeholder{
2485
- justify-content: center;
2486
- }
2487
-
2488
- .magicfeedback-rating-container {
2489
- flex-wrap: wrap;
2490
- justify-content: flex-start;
2491
- }
2492
- }
2493
-
2494
-
2495
- .magicfeedback-rating-option-label-container {
2496
- display: flex;
2497
- flex-direction: column;
2498
- }
2499
-
2500
-
2501
- .magicfeedback-rating-option-label-container label {
2502
- display: inline-block;
2503
- text-align: center;
2504
- margin-bottom: 0;
2505
- font-weight: 600;
2506
- font-size: 18px;
2507
- color: #475569;
2508
- }
2509
-
2510
- .magicfeedback-rating-option-label-container input[type=radio] {
2511
- position: absolute;
2512
- opacity: 0;
2513
- width: 0;
2514
- height: 0;
2515
- }
2516
-
2517
- /* IMAGE STYLES */
2518
- .magicfeedback-rating-option-label-container input[type=radio] + img {
2519
- cursor: pointer;
2520
- height: 48px;
2521
- width: 48px;
2522
- }
2523
-
2524
- /* LABEL STYLES */
2525
- .magicfeedback-rating-option-label-container input[type=radio] + label {
2526
- cursor: pointer;
2527
- }
2528
-
2529
- /* CHECKED STYLES */
2530
- .magicfeedback-rating-option-label-container input[type=radio]:checked + img {
2531
- box-shadow: #007bff 0px 1px 4px, #007BFFA0 0px 0px 0px 2px;
2532
- border-radius: 50%;
2533
- }
2534
-
2535
- .magicfeedback-rating-number {
2536
- width: 100%;
2537
- }
2538
- .magicfeedback-rating-container,
2539
- .magicfeedback-rating-number-container {
2540
- display: flex;
2541
- flex-direction: row;
2542
- justify-content: space-between;
2543
- align-items: center;
2544
-
2545
- margin: 15px 0;
2546
- padding: 0;
2547
-
2548
- list-style: none;
2549
- font-size: 1.5rem;
2550
- cursor: pointer;
2551
- user-select: none;
2552
- -webkit-user-select: none;
2553
- -moz-user-select: none;
2554
- -ms-user-select: none;
2555
- }
2556
-
2557
- /* Cuando hay placeholders (Very bad / Very good), el placeholder ocupa
2558
- el 100% de la primera l\xEDnea y los boxes bajan a la siguiente */
2559
- .magicfeedback-rating-number-container--with-placeholder {
2560
- flex-wrap: wrap;
2561
- align-items: flex-start;
2562
- }
2563
-
2564
- .magicfeedback-rating-number-container--with-placeholder .magicfeedback-rating-placeholder {
2565
- width: 100%;
2566
- margin-bottom: 8px;
2567
- }
2568
-
2569
- .magicfeedback-rating-number-container--with-placeholder .magicfeedback-rating-number-option {
2570
- width: auto;
2571
- flex: 1;
2572
- }
2573
-
2574
- .magicfeedback-rating-number-option {
2575
- display: flex;
2576
- flex-direction: row;
2577
- justify-content: flex-start;
2578
- align-items: center;
2579
- margin: 5px;
2580
- padding: 0;
2581
- list-style: none;
2582
- font-size: 1.5rem;
2583
- cursor: pointer;
2584
- user-select: none;
2585
- -webkit-user-select: none;
2586
- -moz-user-select: none;
2587
- -ms-user-select: none;
2588
- width: 100%;
2589
- }
2590
-
2591
- .magicfeedback-rating-number-option-row{
2592
- max-width: 100% !important;
2593
- }
2594
-
2595
- .magicfeedback-rating-number-top-placeholder,
2596
- .magicfeedback-rating-number-bottom-placeholder{
2597
- text-align: center !important;
2598
- align-content: center;
2599
- justify-content: center;
2600
- text-wrap: wrap;
2601
-
2602
- font-size: 15px;
2603
- color: #475569;
2604
-
2605
- width: 100%;
2606
- margin: auto;
2607
- }
2608
-
2609
- @media (min-width: 650px) {
2610
- .magicfeedback-rating-number-option-row +.magicfeedback-rating-number-container-ltr:first-child,
2611
- .magicfeedback-rating-number-option-row + +.magicfeedback-rating-number-container-rtl:last-child {
2612
- margin-left: 0;
2613
- width: calc(100% - 10px);
2614
- }
2615
-
2616
- .magicfeedback-rating-number-option-row +.magicfeedback-rating-number-container-rtl:first-child,
2617
- .magicfeedback-rating-number-option-row + +.magicfeedback-rating-number-container-ltr:last-child {
2618
- margin-right: 0;
2619
- width: calc(100% - 10px);
2620
- }
2621
- }
2622
-
2623
-
2624
- .magicfeedback-rating-number-option-label-container {
2625
- display: flex;
2626
- flex-direction: column;
2627
- align-items: center;
2628
- justify-content: center;
2629
- width: 100%;
2630
- height: 100%;
2631
- }
2632
-
2633
- .magicfeedback-rating-number-option-label-container label {
2634
- display: flex;
2635
- align-items: center;
2636
- justify-content: center;
2637
- white-space: nowrap;
2638
- overflow: hidden;
2639
- text-overflow: ellipsis;
2640
- margin: 0 10px;
2641
- font-weight: 600;
2642
- font-size: 14px;
2643
- color: #475569;
2644
- cursor: pointer;
2645
- width: 100%;
2646
- height: 100%;
2647
- min-height: 50px;
2648
- text-align: center;
2649
- padding: 0;
2650
- border-radius: 4px;
2651
- border: 1px solid #ced4da;
2652
- background-color: rgba(246, 246, 246, 0.3);
2653
- transition: background-color 0.15s ease-in-out;
2654
- }
2655
-
2656
- .magicfeedback-rating-number-option-label-container input[type=radio] {
2657
- position: absolute;
2658
- opacity: 0;
2659
- width: 0;
2660
- height: 0;
2661
- }
2662
-
2663
- .magicfeedback-rating-number-option-label-container input[type=radio] + label {
2664
- cursor: pointer;
2665
- }
2666
-
2667
- .magicfeedback-rating-number-option-label-container input[type=radio] + label:hover,
2668
- .magicfeedback-rating-number-option-label-container input[type=radio]:checked + label {
2669
- color: #007bff;
2670
- border: 1px solid #007bff;
2671
- background-color: rgba(86, 168, 253, 0.29);
2672
- }
2673
-
2674
- .magicfeedback-rating-number-container-column{
2675
- align-items: flex-start !important;
2676
- }
2677
-
2678
- @media (max-width: 650px) {
2679
- .magicfeedback-rating-number-container-ltr {
2680
- justify-content: center;
2681
- flex-wrap: wrap;
2682
- }
2683
-
2684
- .magicfeedback-rating-number-container-rtl {
2685
- justify-content: center;
2686
- flex-wrap: wrap-reverse;
2687
- }
2688
-
2689
- .magicfeedback-rating-number-option {
2690
- max-width: 100%;
2691
- height: 55px;
2692
- margin: 5px 0;
2693
- }
2694
- }
2695
-
2696
- .magicfeedback-rating-star {
2697
- width: 100%;
2698
- }
2699
-
2700
- .magicfeedback-rating-star-container {
2701
- display: flex !important;
2702
- flex-direction: row !important;
2703
- justify-content: center !important;
2704
- align-items: center !important;
2705
- flex-wrap: wrap;
2706
- margin: 15px 5px;
2707
- padding: 0;
2708
- list-style: none;
2709
- font-size: 1.5rem;
2710
- cursor: pointer;
2711
- user-select: none;
2712
- -webkit-user-select: none;
2713
- -moz-user-select: none;
2714
- -ms-user-select: none;
2715
- }
2716
-
2717
- .magicfeedback-rating-star-option:not(:checked) > .rating__star {
2718
- float: right;
2719
- width: 1em;
2720
- overflow: hidden;
2721
- white-space: nowrap;
2722
- cursor: pointer;
2723
- font-size: 30px;
2724
- color: #ccc;
2725
- margin: 0 10px;
2726
- }
2727
-
2728
- .magicfeedback-rating-star-option:not(:checked) > .rating__star:hover,
2729
- .magicfeedback-rating-star-option:not(:checked) > .rating__star:hover ~ span {
2730
- color: #deb217 !important;
2731
- }
2732
-
2733
- .magicfeedback-rating-star-selected {
2734
- color: #ffc700 !important;
2735
- }
2736
-
2737
-
2738
- /* Style for multiple choice image */
2739
- .magicfeedback-image-option-label-container:hover {
2740
- cursor: pointer;
2741
- border: 0 !important;
2742
- }
2743
-
2744
- .magicfeedback-image-option-label-container input[type=radio]:checked + img,
2745
- .magicfeedback-image-option-label-container input[type=checkbox]:checked + img {
2746
- border: 1px solid #007bff !important;
2747
- box-shadow: 0 0 3px #007bff !important;
2748
- }
2749
-
2750
- .magicfeedback-image-option-label-container input[type=radio] + img,
2751
- .magicfeedback-image-option-label-container input[type=checkbox] + img {
2752
- border: 1px solid transparent !important;
2753
- }
2754
-
2755
- .magicfeedback-image-option-label-container{
2756
- margin: 10px !important;
2757
- height: calc(100% - 20px) !important;
2758
- width: calc(100% - 20px) !important;
2759
- }
2760
-
2761
- .magicfeedback-multiple-choice-image-option {
2762
- display: flex;
2763
- height: auto !important;
2764
- box-shadow: 0 0 3px #ccc;
2765
- }
2766
-
2767
- .magicfeedback-multiple-choice-image-label {
2768
- font-size: 1rem;
2769
- }
2770
-
2771
- .magicfeedback-consent-container {
2772
- display: flex;
2773
- flex-direction: row;
2774
- justify-content: flex-start;
2775
- align-items: center;
2776
- margin: 10px 0;
2777
- width: 100%;
2778
- }
2779
-
2780
- .magicfeedback-consent-container label {
2781
- margin-left: 10px;
2782
- }
2783
-
2784
- .magicfeedback-start-message-container {
2785
- /* ... add your start message container styles here ... */
2786
- }
2787
-
2788
- .magicfeedback-success-message,
2789
- .magicfeedback-info-message,
2790
- .magicfeedback-start-message {
2791
- margin: 35px 5px;
2792
- }
2793
-
2794
- .magicfeedback-success-message p,
2795
- .magicfeedback-info-message p,
2796
- .magicfeedback-start-message p {
2797
- font-style: normal;
2798
- text-align: start;
2799
- font-weight: 400;
2800
- font-size: 16px;
2801
- color: #475569;
2802
- line-height: 1.5;
2803
- }
2804
-
2805
- .magicfeedback-success-message img,
2806
- .magicfeedback-info-message img,
2807
- .magicfeedback-start-message img {
2808
- width: 400px;
2809
- max-width: 80%;
2810
- height: auto;
2811
- margin: 10px auto;
2812
- }
2813
-
2814
- .magicfeedback-counter,
2815
- .magicfeedback-point-system-total {
2816
- margin: 10px 0 0 0 !important;
2817
- display: flex !important;
2818
- justify-content: right !important;
2819
- align-items: center !important;
2820
- width: 100%;
2821
- }
2822
-
2823
- .magicfeedback-skip-container {
2824
- background-color: transparent !important;
2825
- border: 0 !important;
2826
- color: #999999FF !important;
2827
- padding: 0 !important;
2828
- margin: 0 !important;
2829
- cursor: pointer !important;
2830
- font-size: 0.5em !important;
2831
- font-weight: 400 !important;
2832
- box-shadow: 0 0 0 !important;
2833
-
2834
- &:hover {
2835
- color: #0066ff;
2836
- }
2837
- }
2838
-
2839
- .magicfeedback-skip-container input[type=checkbox] {
2840
- border-color: #999999FF !important;
2841
- border: 0 !important;
2842
- cursor: pointer !important;
2843
-
2844
- }
2845
-
2846
- .magicfeedback-multi-question-matrix,
2847
- .magicfeedback-point-system,
2848
- .magicfeedback-priority-list {
2849
- width: 100% !important;
2850
- }
2851
-
2852
- .magicfeedback-multi-question-matrix-container,
2853
- .magicfeedback-point-system-container,
2854
- .magicfeedback-priority-list-container {
2855
- width: 100% !important;
2856
- overflow-x: auto;
2857
- }
2858
-
2859
- .magicfeedback-point-system-list,
2860
- .magicfeedback-priority-list-list,
2861
- .magicfeedback-multi-question-matrix-table {
2862
- width: 100% !important;
2863
- padding: 0 !important;
2864
- overflow-x: auto;
2865
- }
2866
-
2867
- .magicfeedback-multi-question-matrix {
2868
- position: relative !important;
2869
- }
2870
-
2871
- .magicfeedback-multi-question-matrix-container {
2872
- overflow: auto !important;
2873
- padding-bottom: 10px;
2874
- }
2875
-
2876
- .magicfeedback-multi-question-matrix-label{
2877
- text-align: left !important;
2878
- }
2879
- .magicfeedback-priority-list-item {
2880
- display: flex;
2881
- flex-direction: row;
2882
- justify-content: space-between;
2883
- align-items: center;
2884
- padding: 10px 0 10px 10px;
2885
-
2886
- border: 1px solid #ced4da;
2887
- border-radius: 5px;
2888
- margin: 10px 0 !important;
2889
- }
2890
-
2891
- .magicfeedback-point-system-item {
2892
- height: 45px;
2893
- margin: 5px 0 !important;
2894
- }
2895
-
2896
- .magicfeedback-point-system-item label,
2897
- .magicfeedback-priority-list-item-label {
2898
- font-family: inherit;
2899
- font-size: 18px !important;
2900
- color: #212529;
2901
- text-align: start;
2902
- word-wrap: break-word;
2903
- white-space: normal;
2904
- padding: 0 10px 0 0;
2905
- }
2906
-
2907
- .magicfeedback-point-system-input-container {
2908
- padding: 0 10px 0 0;
2909
- border-radius: 5px;
2910
- font-size: 14px;
2911
- border: 1px solid #ced4da;
2912
- height: 42px;
2913
- margin: auto 0;
2914
- }
2915
-
2916
- .magicfeedback-multi-question-matrix-table thead {
2917
- margin-bottom: 20px;
2918
- }
2919
-
2920
- .magicfeedback-multi-question-matrix-table th{
2921
- text-align: center;
2922
- font-weight: 400 !important;
2923
- font-size: 1rem !important;
2924
- padding: 0 10px !important;
2925
- }
2926
-
2927
- .magicfeedback-multi-question-matrix-table th,
2928
- .magicfeedback-multi-question-matrix-table td label,
2929
- .magicfeedback-priority-list-arrow-up,
2930
- .magicfeedback-priority-list-arrow-down {
2931
- font-style: normal !important;
2932
- font-weight: 400 !important;
2933
- font-size: 1rem !important;
2934
- color: #475569 !important;
2935
- cursor: pointer !important;
2936
- margin: 0 !important;
2937
- line-height: inherit;
2938
- }
2939
-
2940
- .magicfeedback-multi-question-matrix-table tr {
2941
- align-items: center;
2942
- margin: 5px 0;
2943
- }
2944
-
2945
- .magicfeedback-multi-question-matrix-row-tr{
2946
- border-radius: 5px;
2947
- margin: 10px 0 !important;
2948
- }
2949
-
2950
- .magicfeedback-multi-question-matrix-row-tr:nth-child(odd) {
2951
- background-color: #f1f6f6; /* Light gray background for odd rows */
2952
- }
2953
-
2954
- .magicfeedback-multi-question-matrix-row-tr:nth-child(even) {
2955
- background-color: #ffffff; /* White background for even rows */
2956
- }
2957
-
2958
- .magicfeedback-multi-question-matrix-row-label {
2959
- text-align: left !important;
2960
- }
2961
-
2962
- .magicfeedback-point-system-item span {
2963
- color: #475569 !important;
2964
- }
2965
-
2966
- .magicfeedback-point-system-item input {
2967
- padding: 0;
2968
- margin: 0 !important;
2969
- width: auto !important;
2970
- min-width: 100px !important;
2971
- height: auto !important;
2972
- min-height: 42px;
2973
- cursor: pointer;
2974
- font-size: 14px;
2975
- text-align: center !important;
2976
- }
2977
-
2978
- .magicfeedback-multi-question-matrix-table input {
2979
- margin: auto !important;
2980
- padding: 20px !important;
2981
- width: 100% !important;
2982
- height: 15px;
2983
- border: 1px solid #ced4da;
2984
- cursor: pointer;
2985
- }
2986
-
2987
- .magicfeedback-image{
2988
- max-height: 400px !important;
2989
- height: auto !important;
2990
- max-width: 100% !important;
2991
- margin: 10px auto !important;
2992
- }
2993
-
2994
- .magicfeedback-error{
2995
- margin-top: 5px;
2996
- }`;
2997
- }
2998
- });
2999
-
3000
2138
  // src/ui/renderPopup.ts
3001
2139
  var renderPopup_exports = {};
3002
2140
  __export(renderPopup_exports, {
@@ -3077,6 +2215,11 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3077
2215
  const isDark = style?.theme === "dark";
3078
2216
  const theme = {
3079
2217
  popupBg: isDark ? "#1e1e1e" : "#fff",
2218
+ // El popup fija su propio fondo, así que debe fijar también el esquema de color.
2219
+ // Sin esto los controles de formulario (input/textarea/select) caen al estilo por
2220
+ // defecto del navegador: en un host con `prefers-color-scheme: dark` se pintan
2221
+ // oscuros con texto blanco sobre el fondo claro del popup.
2222
+ colorScheme: isDark ? "dark" : "light",
3080
2223
  textPrimary: isDark ? "#f0f0f0" : "#111",
3081
2224
  closeBtnHoverBg: isDark ? "rgba(255,255,255,0.10)" : "rgba(0,0,0,0.06)",
3082
2225
  closeBtnHoverColor: isDark ? "#fff" : "#000000"
@@ -3099,6 +2242,7 @@ async function renderPopup(container, surveyId, productId, actions, emit, onClos
3099
2242
  flex-direction: column;
3100
2243
  justify-content: flex-start;
3101
2244
  background: ${theme.popupBg};
2245
+ color-scheme: ${theme.colorScheme};
3102
2246
  border-radius: 8px;
3103
2247
  padding: 24px;
3104
2248
  box-shadow: 0 4px 6px rgba(0,0,0,0.1);
@@ -3550,6 +2694,9 @@ __export(index_exports, {
3550
2694
  CrashReporter: () => CrashReporter,
3551
2695
  DeepdotsPopups: () => DeepdotsPopups,
3552
2696
  InMemoryStorage: () => InMemoryStorage,
2697
+ MAX_TRACKED_MESSAGES: () => MAX_TRACKED_MESSAGES,
2698
+ MESSAGE_CHANNELS: () => MESSAGE_CHANNELS,
2699
+ MessageGuard: () => MessageGuard,
3553
2700
  NoopPopupRenderer: () => NoopPopupRenderer,
3554
2701
  POPUP_TRIGGER_CONDITION_STATUSES: () => POPUP_TRIGGER_CONDITION_STATUSES,
3555
2702
  ReactNativePopupRenderer: () => ReactNativePopupRenderer,
@@ -3754,6 +2901,16 @@ init_tracking_manager();
3754
2901
 
3755
2902
  // src/ui/surveyHtml.ts
3756
2903
  init_font();
2904
+ init_style();
2905
+ var POSITION_MAP = {
2906
+ center: { justifyContent: "center", alignItems: "center", padding: "0", background: "rgba(0,0,0,0.5)" },
2907
+ bottom: { justifyContent: "center", alignItems: "flex-end", padding: "16px", background: "transparent" },
2908
+ "bottom-right": { justifyContent: "flex-end", alignItems: "flex-end", padding: "16px", background: "transparent" },
2909
+ "bottom-left": { justifyContent: "flex-start", alignItems: "flex-end", padding: "16px", background: "transparent" },
2910
+ top: { justifyContent: "center", alignItems: "flex-start", padding: "16px", background: "transparent" },
2911
+ "top-right": { justifyContent: "flex-end", alignItems: "flex-start", padding: "16px", background: "transparent" },
2912
+ "top-left": { justifyContent: "flex-start", alignItems: "flex-start", padding: "16px", background: "transparent" }
2913
+ };
3757
2914
  function buildSurveyHtml(opts) {
3758
2915
  const env = opts.env === "development" ? "dev" : "prod";
3759
2916
  const version = opts.version ?? "2.2.4";
@@ -3764,17 +2921,141 @@ function buildSurveyHtml(opts) {
3764
2921
  const metaJson = JSON.stringify(opts.metadata ?? []);
3765
2922
  const fontFaceCss = opts.font ? buildFontFaceCss(opts.font.family, opts.font.url) : "";
3766
2923
  const fontFamilyValue = opts.font ? buildFontFamilyValue(opts.font.family) : "-apple-system,system-ui,sans-serif";
2924
+ const popupClass = opts.font?.family ? "deepdots-popup deepdots-has-font" : "deepdots-popup";
2925
+ const isDark = opts.theme === "dark";
2926
+ const popupBg = isDark ? "#1e1e1e" : "#fff";
2927
+ const colorScheme = isDark ? "dark" : "light";
2928
+ const textPrimary = isDark ? "#f0f0f0" : "#111";
2929
+ const pos = POSITION_MAP[opts.position ?? "center"] ?? POSITION_MAP.center;
2930
+ const backLabel = JSON.stringify(opts.actions?.back?.label ?? "Back");
2931
+ const startLabel = JSON.stringify(opts.actions?.start?.label ?? "Start survey");
2932
+ const completeLabel = JSON.stringify(opts.actions?.complete?.label ?? "Complete survey");
2933
+ const submitLabel = JSON.stringify(opts.actions?.accept?.label ?? "Send");
3767
2934
  return `<!DOCTYPE html><html><head>
3768
2935
  <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
3769
- <meta name="color-scheme" content="light"/>
3770
- <style>${fontFaceCss}html,body{margin:0;padding:0;background:transparent;font-family:${fontFamilyValue}}#mf{width:100%;box-sizing:border-box}#mf *{max-width:100%;box-sizing:border-box}</style>
2936
+ <meta name="color-scheme" content="${colorScheme}"/>
2937
+ <style>
2938
+ ${style_default}
2939
+ ${fontFaceCss}
2940
+ html,body{margin:0;padding:0;height:100%;font-family:${fontFamilyValue}}
2941
+ body{display:flex;justify-content:${pos.justifyContent};align-items:${pos.alignItems};background:${pos.background};padding:${pos.padding};box-sizing:border-box}
2942
+ .deepdots-popup{position:relative;display:flex;flex-direction:column;justify-content:flex-start;background:${popupBg};color-scheme:${colorScheme};border-radius:8px;padding:24px;box-shadow:0 4px 6px rgba(0,0,0,0.1);max-width:600px;width:90%;min-height:200px;box-sizing:border-box}
2943
+ .deepdots-popup-header{display:flex;justify-content:flex-end;align-items:center;width:100%}
2944
+ #dd-close{background:transparent;border:none;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border-radius:8px;cursor:pointer;color:${textPrimary};padding:4px}
2945
+ .deepdots-popup-container-content{display:flex;flex-direction:column;padding:0 20px 12px 20px;max-height:80vh;overflow:hidden;box-sizing:border-box}
2946
+ .deepdots-popup-main{display:flex;flex-direction:column;width:100%;max-height:80vh;overflow-y:auto;overflow-x:hidden;position:relative}
2947
+ #dd-form-wrapper{width:100%;flex:1 1 auto}
2948
+ #mf{width:100%;box-sizing:border-box;visibility:hidden}
2949
+ .deepdots-popup-main *{max-width:100%;box-sizing:border-box}
2950
+ #dd-logo{max-height:40px;max-width:100%;object-fit:contain}
2951
+ .deepdots-error-hint{display:none;margin:12px 0 0 0;padding:10px 12px;border-radius:6px;background:#FEF3C7;color:#92400E;border:1px solid #FCD34D;font-size:13px}
2952
+ .deepdots-popup-footer{display:flex;flex-direction:row-reverse;justify-content:space-between;align-items:center;gap:8px;margin-top:auto;width:100%;padding-top:16px}
2953
+ .dd-nav-btn{display:none;border:none;padding:12px 24px;border-radius:4px;cursor:pointer;font-size:14px;box-shadow:0 2px 4px rgba(0,0,0,0.1);align-items:center;justify-content:center;text-align:center}
2954
+ #dd-back{background:transparent;color:#333;border:1px solid #999}
2955
+ #dd-start,#dd-complete,#dd-submit{background:#1E293B;color:#fff;border:none}
2956
+ #dd-submit:disabled,#dd-start:disabled,#dd-back:disabled,#dd-complete:disabled{opacity:0.6;cursor:not-allowed}
2957
+ .mf-spinner{display:none;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}
2958
+ .mf-spinner-circle{width:28px;height:28px;border:3px solid #e0e6ed;border-top-color:#1E293B;border-radius:50%;animation:ddspin 0.9s linear infinite}
2959
+ @keyframes ddspin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}
2960
+ @media (max-width:640px){
2961
+ .deepdots-popup{width:calc(100% - 24px);max-width:calc(100% - 24px);border-radius:12px}
2962
+ .deepdots-popup-footer{flex-direction:column-reverse;gap:12px}
2963
+ .dd-nav-btn{width:100%}
2964
+ .magicfeedback-checkbox-container,.magicfeedback-radio-container{margin:4px 0;padding:4px 8px}
2965
+ .magicfeedback-checkbox label,.magicfeedback-radio-container label{font-size:15px}
2966
+ .deepdots-popup input[type="radio"]{margin:6px 0 6px 8px}
2967
+ .deepdots-popup input[type="checkbox"]{width:16px;height:16px}
2968
+ }
2969
+ </style>
3771
2970
  </head><body>
3772
- <div id="mf"></div>
2971
+ <div class="${popupClass}" id="dd-popup">
2972
+ <div class="deepdots-popup-header">
2973
+ <button type="button" id="dd-close" aria-label="Close popup">
2974
+ <svg width="28" height="28" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2975
+ <path d="M6 6L18 18M6 18L18 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
2976
+ </svg>
2977
+ </button>
2978
+ </div>
2979
+ <div class="deepdots-popup-container-content">
2980
+ <div class="deepdots-popup-main" id="dd-main">
2981
+ <div id="dd-form-wrapper">
2982
+ <div class="mf-spinner" id="dd-spinner" role="status" aria-label="Loading survey"><div class="mf-spinner-circle"></div></div>
2983
+ <div id="mf"></div>
2984
+ </div>
2985
+ <div class="deepdots-error-hint" id="dd-error" role="alert" aria-live="polite"></div>
2986
+ <div class="deepdots-popup-footer" id="dd-footer">
2987
+ <button type="button" class="dd-nav-btn" id="dd-submit">Send</button>
2988
+ <button type="button" class="dd-nav-btn" id="dd-back">Back</button>
2989
+ <button type="button" class="dd-nav-btn" id="dd-complete">Complete survey</button>
2990
+ <button type="button" class="dd-nav-btn" id="dd-start">Start survey</button>
2991
+ </div>
2992
+ </div>
2993
+ </div>
2994
+ </div>
3773
2995
  <script>
3774
2996
  (function(){
3775
2997
  function emit(s){ try{ if(window.ReactNativeWebView){ window.ReactNativeWebView.postMessage(s); } }catch(e){} }
3776
2998
  function emitJSON(n,p){ try{ emit(JSON.stringify({name:n,payload:p||{}})); }catch(e){} }
3777
2999
  window.DeepdotsClose = function(){ emitJSON('popup_close'); };
3000
+
3001
+ var popup=document.getElementById('dd-popup');
3002
+ var main=document.getElementById('dd-main');
3003
+ var footer=document.getElementById('dd-footer');
3004
+ var spinner=document.getElementById('dd-spinner');
3005
+ var formHost=document.getElementById('mf');
3006
+ var errorHint=document.getElementById('dd-error');
3007
+ var backBtn=document.getElementById('dd-back');
3008
+ var startBtn=document.getElementById('dd-start');
3009
+ var completeBtn=document.getElementById('dd-complete');
3010
+ var submitBtn=document.getElementById('dd-submit');
3011
+
3012
+ backBtn.textContent=${backLabel};
3013
+ startBtn.textContent=${startLabel};
3014
+ completeBtn.textContent=${completeLabel};
3015
+ submitBtn.textContent=${submitLabel};
3016
+
3017
+ document.getElementById('dd-close').onclick=function(){ emitJSON('popup_close'); };
3018
+ backBtn.onclick=function(){ if(window.DeepdotsForm && window.DeepdotsForm.back){ window.DeepdotsForm.back(); } };
3019
+ startBtn.onclick=function(){ if(window.DeepdotsForm && window.DeepdotsForm.startForm){ window.DeepdotsForm.startForm(); } };
3020
+ completeBtn.onclick=function(){ emitJSON('popup_close'); };
3021
+ var surveyCompletedEmitted=false;
3022
+ submitBtn.onclick=function(){
3023
+ if(surveyCompletedEmitted) return;
3024
+ if(window.DeepdotsForm && window.DeepdotsForm.send){ window.DeepdotsForm.send(); }
3025
+ };
3026
+
3027
+ function updateButtons(state){
3028
+ backBtn.style.display='none';
3029
+ startBtn.style.display='none';
3030
+ submitBtn.style.display='none';
3031
+ completeBtn.style.display='none';
3032
+ backBtn.style.width='';
3033
+ startBtn.style.width='';
3034
+ submitBtn.style.width='';
3035
+ completeBtn.style.width='';
3036
+ if(state==='start'){
3037
+ startBtn.style.display='inline-flex';
3038
+ startBtn.style.width='100%';
3039
+ } else if(state==='in_progress_first'){
3040
+ submitBtn.style.display='inline-flex';
3041
+ } else if(state==='in_progress_next'){
3042
+ backBtn.style.display='inline-flex';
3043
+ submitBtn.style.display='inline-flex';
3044
+ } else if(state==='completed'){
3045
+ completeBtn.style.display='inline-flex';
3046
+ completeBtn.style.width='100%';
3047
+ }
3048
+ }
3049
+
3050
+ function setLoading(isLoading){
3051
+ spinner.style.display=isLoading?'flex':'none';
3052
+ if(!isLoading){ formHost.style.visibility='visible'; }
3053
+ footer.style.display=isLoading?'none':'flex';
3054
+ backBtn.disabled=isLoading; startBtn.disabled=isLoading; completeBtn.disabled=isLoading; submitBtn.disabled=isLoading;
3055
+ if(isLoading){ updateButtons(null); }
3056
+ }
3057
+ setLoading(true);
3058
+
3778
3059
  var initialized=false;
3779
3060
  function initMF(){
3780
3061
  if(initialized || !window.magicfeedback) return initialized;
@@ -3783,23 +3064,85 @@ function buildSurveyHtml(opts) {
3783
3064
  window.magicfeedback.init({ debug:false, env:'${env}' });
3784
3065
  var form = window.magicfeedback.form(${sid}, ${pid}, ${profileJson}, ${metaJson});
3785
3066
  window.DeepdotsForm = form;
3067
+ var stylesInjected=false;
3786
3068
  form.generate('mf', {
3787
3069
  addButton:false,
3788
3070
  getMetaData:true,
3789
- onLoadedEvent:function(){ emitJSON('loaded'); },
3790
- beforeSubmitEvent:function(){ emitJSON('before_submit'); },
3071
+ onLoadedEvent:function(args){
3072
+ var s=args && args.formData ? args.formData.style : null;
3073
+ if(s && !stylesInjected){
3074
+ stylesInjected=true;
3075
+ if(s.boxBackgroundColor){ popup.style.background=s.boxBackgroundColor; }
3076
+ if(s.contentAlign){ main.style.justifyContent = s.contentAlign==='center' ? 'center' : 'flex-start'; }
3077
+ if(s.buttonPrimaryColor){
3078
+ submitBtn.style.background=s.buttonPrimaryColor; submitBtn.style.border='none'; submitBtn.style.color='#fff';
3079
+ startBtn.style.background=s.buttonPrimaryColor; startBtn.style.border='none'; startBtn.style.color='#fff';
3080
+ completeBtn.style.background=s.buttonPrimaryColor; completeBtn.style.border='none'; completeBtn.style.color='#fff';
3081
+ }
3082
+ if(s.buttonSecondaryColor){
3083
+ backBtn.style.background='#fff'; backBtn.style.color=s.buttonSecondaryColor; backBtn.style.border='1px solid '+s.buttonSecondaryColor;
3084
+ }
3085
+ if(s.logo && !document.getElementById('dd-logo')){
3086
+ var logoImg=document.createElement('img');
3087
+ logoImg.id='dd-logo'; logoImg.src=s.logo; logoImg.alt='Logo';
3088
+ if(s.logoSize==='small'){ logoImg.style.maxHeight='30px'; }
3089
+ else if(s.logoSize==='medium'){ logoImg.style.maxHeight='50px'; }
3090
+ else if(s.logoSize==='large'){ logoImg.style.maxHeight='70px'; }
3091
+ if(s.logoPosition==='left'){ logoImg.style.margin='0 16px 20px 0'; logoImg.style.display='block'; logoImg.style.marginLeft='0'; }
3092
+ else if(s.logoPosition==='right'){ logoImg.style.margin='0 0 20px 16px'; logoImg.style.display='block'; logoImg.style.marginLeft='auto'; }
3093
+ else if(s.logoPosition==='center'){ logoImg.style.margin='0 auto 20px auto'; logoImg.style.display='block'; }
3094
+ main.insertBefore(logoImg, document.getElementById('dd-form-wrapper'));
3095
+ }
3096
+ if(s.startMessage && s.startMessage!==''){ updateButtons('start'); }
3097
+ else { updateButtons('in_progress_first'); }
3098
+ } else {
3099
+ updateButtons('in_progress_first');
3100
+ }
3101
+ emitJSON('loaded');
3102
+ setLoading(false);
3103
+ },
3104
+ beforeSubmitEvent:function(){
3105
+ setLoading(true);
3106
+ emitJSON('before_submit');
3107
+ },
3791
3108
  afterSubmitEvent:function(p){
3792
- try{ if(p && p.completed){ emitJSON('survey_completed', p); } else { emitJSON('after_submit', p); } }
3793
- catch(e){ emitJSON('after_submit'); }
3109
+ var error=p && p.error ? (typeof p.error==='string' ? p.error : String(p.error)) : '';
3110
+ if(error){
3111
+ setLoading(false);
3112
+ if(error.toLowerCase().indexOf('no response')!==-1){
3113
+ errorHint.textContent='Please answer the required question to continue.';
3114
+ errorHint.style.display='block';
3115
+ updateButtons('in_progress_next');
3116
+ return;
3117
+ }
3118
+ errorHint.textContent='An error occurred while submitting. Please try again or close the popup.';
3119
+ errorHint.style.display='block';
3120
+ return;
3121
+ }
3122
+ errorHint.style.display='none';
3123
+ setLoading(false);
3124
+ if(p && p.completed){
3125
+ surveyCompletedEmitted=true;
3126
+ updateButtons('completed');
3127
+ emitJSON('survey_completed', p);
3128
+ return;
3129
+ }
3130
+ if(p && p.total>1 && p.progress>0 && p.progress<p.total){ updateButtons('in_progress_next'); }
3131
+ else { updateButtons('in_progress_first'); }
3132
+ emitJSON('after_submit', p);
3794
3133
  },
3795
- onBackEvent:function(p){ emitJSON('back', p); }
3796
- }).catch(function(e){ emit('error:init'); });
3797
- }catch(e){ emit('error:exception'); }
3134
+ onBackEvent:function(p){
3135
+ if(p && p.progress===0){ updateButtons('in_progress_first'); }
3136
+ else { updateButtons('in_progress_next'); }
3137
+ emitJSON('back', p);
3138
+ }
3139
+ }).catch(function(e){ setLoading(false); emit('error:init'); });
3140
+ }catch(e){ setLoading(false); emit('error:exception'); }
3798
3141
  return true;
3799
3142
  }
3800
3143
  var s=document.createElement('script'); s.src=${JSON.stringify(cdn)}; s.async=true;
3801
3144
  s.onload=function(){ initMF(); };
3802
- s.onerror=function(){ emit('error:load'); };
3145
+ s.onerror=function(){ setLoading(false); emit('error:load'); };
3803
3146
  document.head.appendChild(s);
3804
3147
  var tries=0, t=setInterval(function(){ if(initMF()||++tries>40){ clearInterval(t); } },150);
3805
3148
  })();
@@ -3819,18 +3162,28 @@ var ReactNativePopupRenderer = class {
3819
3162
  }
3820
3163
  init() {
3821
3164
  }
3822
- show(surveyId, productId, _actions, emit, onClose, env = "production", userId, style, sessionId, miniService, analyticsFeedbackSessionId) {
3165
+ show(surveyId, productId, actions, emit, onClose, env = "production", userId, style, sessionId, miniService, analyticsFeedbackSessionId) {
3823
3166
  this.emitFn = emit;
3824
3167
  this.onCloseFn = onClose;
3825
3168
  this.currentSurveyId = surveyId;
3826
3169
  this.partialEmitted = false;
3827
3170
  const { profile, metadata } = buildSurveyIdentity(userId ?? null, sessionId ?? null, miniService ?? null, analyticsFeedbackSessionId ?? null);
3828
- const html = buildSurveyHtml({ surveyId, productId, env, profile, metadata, font: style?.font });
3171
+ const html = buildSurveyHtml({
3172
+ surveyId,
3173
+ productId,
3174
+ env,
3175
+ profile,
3176
+ metadata,
3177
+ font: style?.font,
3178
+ theme: style?.theme,
3179
+ position: style?.position,
3180
+ actions
3181
+ });
3829
3182
  if (this.options.onShow) {
3830
3183
  this.options.onShow({ surveyId, productId, html });
3831
3184
  } else {
3832
3185
  sdkWarn(
3833
- "[Deepdots] ReactNativePopupRenderer sin onShow: pasa { onShow } a new ReactNativePopupRenderer({...}) para montar el WebView del survey."
3186
+ "[Deepdots] ReactNativePopupRenderer has no onShow: pass { onShow } to new ReactNativePopupRenderer({...}) to mount the survey WebView."
3834
3187
  );
3835
3188
  }
3836
3189
  }
@@ -3948,7 +3301,7 @@ init_tracking_manager();
3948
3301
  // src/analytics/analytics-manager.ts
3949
3302
  function createDryRunSink(log = console.log) {
3950
3303
  return (payload) => log(
3951
- "[DeepdotsAnalytics] (dry-run \xB7 NO enviado \xB7 sin init.analytics) POST /sdk/feedback \u2192",
3304
+ "[DeepdotsAnalytics] (dry-run \xB7 NOT sent \xB7 no init.analytics) POST /sdk/feedback \u2192",
3952
3305
  JSON.stringify(payload, null, 2)
3953
3306
  );
3954
3307
  }
@@ -4017,6 +3370,15 @@ var AnalyticsManager = class {
4017
3370
  this.exitMiniService(name);
4018
3371
  }
4019
3372
  }
3373
+ /**
3374
+ * Olvida lo que pertenecía al usuario anterior (user attributes + métricas) al cambiar de
3375
+ * usuario. NO toca el buffer de eventos: el cierre de sesión ya lo vació con la identidad
3376
+ * vieja, y lo que llegue después es del usuario nuevo.
3377
+ */
3378
+ resetUserScope() {
3379
+ this.attributes = {};
3380
+ this.metrics = {};
3381
+ }
4020
3382
  /** Registra un evento de analítica (modelo GA: nombre + params). */
4021
3383
  track(name, params) {
4022
3384
  const current = this.getMiniService();
@@ -4104,7 +3466,7 @@ function pushKV(list, key, value) {
4104
3466
  if (value === void 0 || value === null || value === "") return;
4105
3467
  list.push({ key, value: [String(value)] });
4106
3468
  }
4107
- function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
3469
+ function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId, options) {
4108
3470
  const { context } = envelope;
4109
3471
  const profile = [];
4110
3472
  pushKV(profile, "external-user-id", envelope.userId);
@@ -4155,7 +3517,8 @@ function buildAnalyticsFeedbackBody(envelope, keys, feedbackSessionId) {
4155
3517
  },
4156
3518
  publicKey: keys.publicKey,
4157
3519
  integration: keys.integration,
4158
- completed: false,
3520
+ // Único marcador de cierre acordado con backend: el último lote de la sesión.
3521
+ completed: options?.sessionEnd === true,
4159
3522
  ...feedbackSessionId ? { sessionId: feedbackSessionId } : {}
4160
3523
  };
4161
3524
  }
@@ -4174,20 +3537,20 @@ function createFeedbackSink(options) {
4174
3537
  let feedbackSessionId;
4175
3538
  let firstPostInFlight = null;
4176
3539
  const url = `${options.baseUrl}/sdk/feedback`;
4177
- const post = async (body, final) => {
3540
+ const post = async (body, final, sessionEnd = false) => {
4178
3541
  const json = JSON.stringify(body);
4179
3542
  const small = json.length <= KEEPALIVE_MAX_BYTES;
4180
3543
  if (final && options.sendBeaconImpl && small) {
4181
3544
  const payload = typeof Blob !== "undefined" ? new Blob([json], { type: "application/json" }) : json;
4182
3545
  if (options.sendBeaconImpl(url, payload)) {
4183
- options.log?.("[DeepdotsAnalytics] flush final v\xEDa sendBeacon");
3546
+ options.log?.("[DeepdotsAnalytics] final flush via sendBeacon");
4184
3547
  return;
4185
3548
  }
4186
- options.log?.("[DeepdotsAnalytics] sendBeacon rechaz\xF3 el lote; fallback a fetch");
3549
+ options.log?.("[DeepdotsAnalytics] sendBeacon rejected the batch; falling back to fetch");
4187
3550
  }
4188
3551
  const f = options.fetchImpl ?? (typeof fetch !== "undefined" ? fetch : void 0);
4189
3552
  if (!f) {
4190
- options.log?.("[DeepdotsAnalytics] no fetch disponible; payload no enviado", body);
3553
+ options.log?.("[DeepdotsAnalytics] no fetch available; payload not sent", body);
4191
3554
  return;
4192
3555
  }
4193
3556
  const res = await f(url, {
@@ -4200,19 +3563,20 @@ function createFeedbackSink(options) {
4200
3563
  if (!res.ok) {
4201
3564
  const detail = await safeBodyText(res);
4202
3565
  if (isRetryableStatus(res.status)) {
4203
- throw new Error(`POST /sdk/feedback ${res.status} (reintentable): ${detail}`);
3566
+ throw new Error(`POST /sdk/feedback ${res.status} (retryable): ${detail}`);
4204
3567
  }
4205
3568
  options.log?.(
4206
- `[DeepdotsAnalytics] POST /sdk/feedback rechazado con ${res.status}; lote DESCARTADO:`,
3569
+ `[DeepdotsAnalytics] POST /sdk/feedback rejected with ${res.status}; batch DISCARDED:`,
4207
3570
  detail
4208
3571
  );
4209
3572
  return;
4210
3573
  }
3574
+ if (sessionEnd) return;
4211
3575
  try {
4212
3576
  const data = await res.json();
4213
3577
  if (data?.sessionId && data.sessionId !== feedbackSessionId) {
4214
3578
  feedbackSessionId = data.sessionId;
4215
- options.log?.("[DeepdotsAnalytics] feedbackSessionId cacheado:", feedbackSessionId);
3579
+ options.log?.("[DeepdotsAnalytics] feedbackSessionId cached:", feedbackSessionId);
4216
3580
  options.onSessionId?.(feedbackSessionId);
4217
3581
  }
4218
3582
  } catch {
@@ -4220,13 +3584,18 @@ function createFeedbackSink(options) {
4220
3584
  };
4221
3585
  return async (envelope, meta) => {
4222
3586
  const final = meta?.final === true;
3587
+ const sessionEnd = meta?.sessionEnd === true;
4223
3588
  if (!feedbackSessionId && firstPostInFlight && !final) {
4224
3589
  await firstPostInFlight;
4225
3590
  }
4226
- const body = buildAnalyticsFeedbackBody(envelope, options.keys, feedbackSessionId);
3591
+ const body = buildAnalyticsFeedbackBody(envelope, options.keys, feedbackSessionId, { sessionEnd });
4227
3592
  options.log?.("[DeepdotsAnalytics] POST /sdk/feedback \u2192", body);
4228
- const sent = post(body, final);
4229
- if (!feedbackSessionId) {
3593
+ const sent = post(body, final, sessionEnd);
3594
+ if (sessionEnd) {
3595
+ feedbackSessionId = void 0;
3596
+ firstPostInFlight = null;
3597
+ options.onSessionReset?.();
3598
+ } else if (!feedbackSessionId) {
4230
3599
  firstPostInFlight = sent.then(
4231
3600
  () => void 0,
4232
3601
  () => void 0
@@ -4665,6 +4034,7 @@ var CrashReporter = class {
4665
4034
  init_logger();
4666
4035
 
4667
4036
  // src/analytics/messaging.ts
4037
+ var MESSAGE_CHANNELS = ["push", "in_app"];
4668
4038
  function buildMessageParams(stage, o) {
4669
4039
  const p = {
4670
4040
  stage,
@@ -4677,6 +4047,57 @@ function buildMessageParams(stage, o) {
4677
4047
  if (o.currency) p.currency = o.currency;
4678
4048
  return { ...p, ...o.params ?? {} };
4679
4049
  }
4050
+ var MAX_TRACKED_MESSAGES = 500;
4051
+ var MessageGuard = class {
4052
+ constructor(maxTrackedMessages = MAX_TRACKED_MESSAGES) {
4053
+ this.maxTrackedMessages = maxTrackedMessages;
4054
+ /** message_id → canal fijado + stages ya emitidos. El orden de inserción marca la eviction. */
4055
+ this.seen = /* @__PURE__ */ new Map();
4056
+ }
4057
+ evaluate(stage, options) {
4058
+ const channel = options.channel;
4059
+ if (!MESSAGE_CHANNELS.includes(channel)) {
4060
+ return {
4061
+ emit: false,
4062
+ reason: "invalid_channel",
4063
+ detail: `invalid channel "${channel}" (expected ${MESSAGE_CHANNELS.join(" | ")})`
4064
+ };
4065
+ }
4066
+ const entry = this.seen.get(options.id);
4067
+ if (!entry) {
4068
+ this.remember(options.id, channel, stage);
4069
+ return { emit: true };
4070
+ }
4071
+ if (entry.channel !== channel) {
4072
+ return {
4073
+ emit: false,
4074
+ reason: "channel_conflict",
4075
+ detail: `message_id "${options.id}" was already reported on channel "${entry.channel}"; discarding "${channel}"`
4076
+ };
4077
+ }
4078
+ if (entry.stages.has(stage)) {
4079
+ return {
4080
+ emit: false,
4081
+ reason: "duplicate_stage",
4082
+ detail: `stage "${stage}" was already sent for message_id "${options.id}"`
4083
+ };
4084
+ }
4085
+ entry.stages.add(stage);
4086
+ return { emit: true };
4087
+ }
4088
+ /** Olvida todo lo vigilado (nueva sesión). */
4089
+ reset() {
4090
+ this.seen.clear();
4091
+ }
4092
+ remember(id, channel, stage) {
4093
+ this.seen.set(id, { channel, stages: /* @__PURE__ */ new Set([stage]) });
4094
+ while (this.seen.size > this.maxTrackedMessages) {
4095
+ const oldest = this.seen.keys().next();
4096
+ if (oldest.done) break;
4097
+ this.seen.delete(oldest.value);
4098
+ }
4099
+ }
4100
+ };
4680
4101
 
4681
4102
  // src/core/deepdots-popups.ts
4682
4103
  var EXIT_QUEUE_STORAGE_KEY = "__deepdots_exit_popup_queue__";
@@ -4718,14 +4139,24 @@ var DeepdotsPopups = class {
4718
4139
  this.analyticsFlushTimer = void 0;
4719
4140
  /** Crash & error reporting (#14–17). Null hasta init(). */
4720
4141
  this.crashReporter = null;
4142
+ /** Protecciones del funnel de Messaging (#18–22). Vigencia de sesión: se reinicia en init(). */
4143
+ this.messageGuard = new MessageGuard();
4721
4144
  /** Observador de navegación (Fase 2): emite page_view por el canal de analytics. */
4722
4145
  this.navObserver = null;
4723
4146
  /** Tiempo activo (engagement time, #8). */
4724
4147
  this.engagement = null;
4725
4148
  /** Atributos internos del usuario identificado → POST /sdk/popups/contact. Null si no hay userId. */
4726
4149
  this.contact = null;
4150
+ /** Storage resuelto en init() (inyectado por el host o localStorage). Reusado al cambiar de usuario. */
4151
+ this.storage = null;
4727
4152
  /** Marca si ya se inició la navegación manual (setScreen) — para RN sin History API. */
4728
4153
  this.navStarted = false;
4154
+ /**
4155
+ * `true` entre `session_start` y `session_end`. Hace idempotente tanto la apertura como
4156
+ * el cierre (p. ej. `visibilitychange` + `pagehide` seguidos) y permite abrir una sesión
4157
+ * nueva al volver a foreground o al conceder el consentimiento más tarde.
4158
+ */
4159
+ this.sessionOpen = false;
4729
4160
  /**
4730
4161
  * Idioma resuelto en init() (explícito > navigator.language > Intl). Única fuente de
4731
4162
  * verdad para el context de analytics Y para la segmentación por idioma de los popups.
@@ -4737,6 +4168,11 @@ var DeepdotsPopups = class {
4737
4168
  this.logger = config.logger ?? console;
4738
4169
  setLogger(this.logger);
4739
4170
  if (this.initialized) {
4171
+ const nextUserId = config.userId || void 0;
4172
+ if (nextUserId !== this.config?.userId) {
4173
+ this.setUserId(nextUserId);
4174
+ return;
4175
+ }
4740
4176
  this.log("SDK already initialized");
4741
4177
  return;
4742
4178
  }
@@ -4749,6 +4185,7 @@ var DeepdotsPopups = class {
4749
4185
  userId: config.userId || void 0
4750
4186
  };
4751
4187
  const storage = config.storage ?? createDefaultStorage();
4188
+ this.storage = storage;
4752
4189
  this.tracking = new TrackingManager({
4753
4190
  storage,
4754
4191
  clientUserId: this.config.userId,
@@ -4776,6 +4213,9 @@ var DeepdotsPopups = class {
4776
4213
  sendBeaconImpl: typeof navigator !== "undefined" && typeof navigator.sendBeacon === "function" ? (url, body) => navigator.sendBeacon(url, body) : void 0,
4777
4214
  onSessionId: (id) => {
4778
4215
  this.analyticsFeedbackSessionId = id;
4216
+ },
4217
+ onSessionReset: () => {
4218
+ this.analyticsFeedbackSessionId = void 0;
4779
4219
  }
4780
4220
  }) : createDryRunSink((...a) => this.logger.log(...a));
4781
4221
  const device = config.device ?? collectDeviceInfo(config.appVersion);
@@ -4784,6 +4224,7 @@ var DeepdotsPopups = class {
4784
4224
  navigator: typeof navigator !== "undefined" ? navigator : void 0,
4785
4225
  intl: typeof Intl !== "undefined" ? Intl : void 0
4786
4226
  });
4227
+ this.messageGuard.reset();
4787
4228
  this.analytics = new AnalyticsManager({
4788
4229
  sink: analyticsSink,
4789
4230
  publicKey: config.analytics?.publicKey ?? this.config.apiKey,
@@ -4819,7 +4260,7 @@ var DeepdotsPopups = class {
4819
4260
  this.engagement = new EngagementTracker();
4820
4261
  this.engagement.resume();
4821
4262
  this.setupAnalyticsFlush();
4822
- this.track("deepdots_session_start", {});
4263
+ this.openSession();
4823
4264
  const pendingCrashes = this.crashReporter.drainPendingCrashes();
4824
4265
  if (this.tracking?.isTrackingEnabled()) {
4825
4266
  for (const rec of pendingCrashes) {
@@ -4851,7 +4292,9 @@ var DeepdotsPopups = class {
4851
4292
  }
4852
4293
  /** Activa/desactiva el tracking (identidad + sesión + analytics). Kill-switch del contrato §7bis. */
4853
4294
  setTrackingEnabled(enabled) {
4295
+ if (!enabled) this.closeSession("tracking_disabled");
4854
4296
  this.tracking?.setTrackingEnabled(enabled);
4297
+ if (enabled) this.openSession();
4855
4298
  this.log("tracking \xB7 setTrackingEnabled:", enabled, "\xB7 session_id:", this.tracking?.getSessionId() ?? null);
4856
4299
  }
4857
4300
  // ───────── Analytics (canal separado del feedback, vinculado por user_id) ─────────
@@ -4921,8 +4364,18 @@ var DeepdotsPopups = class {
4921
4364
  trackFunnelStep(funnel, step, taskId, params) {
4922
4365
  this.track("deepdots_funnel_step", { funnel, step, task_id: taskId, ...params ?? {} });
4923
4366
  }
4924
- /** Messaging (#18–22): registra una etapa del funnel de una notificación (push/in-app). No-op si tracking off. */
4367
+ /**
4368
+ * Messaging (#18–22): registra una etapa del funnel de una notificación (push/in-app).
4369
+ * No-op si tracking off. El evento se descarta (con warning) si el `channel` no es válido,
4370
+ * si ese `(message_id, stage)` ya se emitió en la sesión, o si el `message_id` ya se reportó
4371
+ * en otro canal — ver `MessageGuard`.
4372
+ */
4925
4373
  trackMessage(stage, options) {
4374
+ const verdict = this.messageGuard.evaluate(stage, options);
4375
+ if (!verdict.emit) {
4376
+ console.warn(`[DeepdotsPopups] trackMessage discarded (${verdict.reason}): ${verdict.detail}`);
4377
+ return;
4378
+ }
4926
4379
  this.track("deepdots_message", buildMessageParams(stage, options));
4927
4380
  }
4928
4381
  /**
@@ -4938,21 +4391,86 @@ var DeepdotsPopups = class {
4938
4391
  this.navObserver.visit(name);
4939
4392
  }
4940
4393
  }
4941
- /** App a foreground (RN: AppState 'active'): reanuda el engagement time. */
4394
+ /** App a foreground (RN: AppState 'active'): reanuda el engagement time y abre sesión nueva. */
4942
4395
  onForeground() {
4943
4396
  this.engagement?.resume();
4397
+ this.openSession();
4944
4398
  }
4945
4399
  /**
4946
- * App a background (RN: AppState 'background'): cierra pantalla actual (page_view),
4947
- * mini-service (mini_service_exit), emite engagement y hace flush del lote.
4400
+ * App a background (RN: AppState 'background'): FIN DE SESIÓN. Cierra pantalla actual
4401
+ * (page_view), mini-services (mini_service_exit), emite engagement + `session_end` y
4402
+ * envía el último lote con `completed:true`.
4403
+ *
4404
+ * Es la única señal disponible en móvil: el kill de la app (swipe) NO da callback.
4948
4405
  */
4949
4406
  onBackground() {
4407
+ this.closeSession("background");
4408
+ this.engagement?.pause();
4409
+ }
4410
+ /**
4411
+ * Cierre EXPLÍCITO de la sesión por parte del host (logout, fin de flujo…): emite
4412
+ * `session_end` y envía el último lote con `completed:true`.
4413
+ */
4414
+ endSession() {
4415
+ this.closeSession("manual");
4416
+ }
4417
+ /**
4418
+ * Cambio de usuario (login / logout / cambio de cuenta). Cierra la sesión del usuario
4419
+ * anterior (`session_end` con `reason: 'user_change'` + `completed:true`), cambia la
4420
+ * identidad y abre una sesión nueva. Sin `userId` vuelve al id anónimo del SDK.
4421
+ *
4422
+ * Equivale a llamar a `init()` otra vez con otro `userId`.
4423
+ */
4424
+ setUserId(userId) {
4425
+ const next = userId || void 0;
4426
+ if (!this.initialized || !this.config || next === this.config.userId) return;
4427
+ this.closeSession("user_change");
4428
+ const enabled = this.tracking?.isTrackingEnabled() ?? true;
4429
+ const storage = this.storage ?? createDefaultStorage();
4430
+ this.config.userId = next;
4431
+ this.tracking = new TrackingManager({ storage, clientUserId: next, enabled });
4432
+ this.contact = next ? new ContactManager({
4433
+ storage,
4434
+ publicKey: this.config.apiKey ?? "",
4435
+ userId: next,
4436
+ post: (body) => this.postContact(body)
4437
+ }) : null;
4438
+ this.analytics?.resetUserScope();
4439
+ this.messageGuard.reset();
4440
+ this.log("tracking \xB7 user_change \xB7 user_id:", this.tracking.getUserId());
4441
+ this.openSession();
4442
+ }
4443
+ /**
4444
+ * Cierra la sesión actual: vuelca todo lo que quedaba abierto y envía el último lote
4445
+ * marcado con `completed:true`, para que el backend cierre el registro. El `sessionId`
4446
+ * cacheado se olvida → el lote siguiente abre un registro nuevo.
4447
+ *
4448
+ * Idempotente: dos cierres seguidos (p. ej. `visibilitychange` + `pagehide`) no duplican
4449
+ * el `session_end`.
4450
+ */
4451
+ closeSession(reason) {
4452
+ if (!this.sessionOpen) return;
4453
+ if (!this.tracking?.isTrackingEnabled()) return;
4454
+ this.sessionOpen = false;
4950
4455
  this.navObserver?.stop();
4951
4456
  this.navStarted = false;
4952
- if (this.tracking?.isTrackingEnabled()) this.analytics?.exitAllMiniServices();
4457
+ this.analytics?.exitAllMiniServices();
4953
4458
  this.flushEngagement();
4954
- this.engagement?.pause();
4955
- this.flushAnalytics();
4459
+ this.track("deepdots_session_end", { reason });
4460
+ this.flushAnalytics({ final: reason === "page_hide", sessionEnd: true });
4461
+ this.analyticsFeedbackSessionId = void 0;
4462
+ this.tracking?.setSessionId(null);
4463
+ this.log("tracking \xB7 session_end:", reason);
4464
+ }
4465
+ /**
4466
+ * Abre sesión (`session_start`) si no hay una abierta y el tracking está activo. Idempotente:
4467
+ * se llama en init(), al volver a foreground y al conceder el consentimiento.
4468
+ */
4469
+ openSession() {
4470
+ if (this.sessionOpen) return;
4471
+ if (!this.tracking?.isTrackingEnabled()) return;
4472
+ this.sessionOpen = true;
4473
+ this.track("deepdots_session_start", {});
4956
4474
  }
4957
4475
  /** Payload que se ENVIARÍA al endpoint de analytics (no envía ni vacía el buffer). */
4958
4476
  previewAnalytics() {
@@ -4990,10 +4508,7 @@ var DeepdotsPopups = class {
4990
4508
  this.analyticsFlushTimer = setInterval(() => this.flushAnalytics(), ANALYTICS_FLUSH_INTERVAL_MS);
4991
4509
  window.addEventListener("pagehide", () => {
4992
4510
  clearInterval(this.analyticsFlushTimer);
4993
- this.navObserver?.stop();
4994
- if (this.tracking?.isTrackingEnabled()) this.analytics?.exitAllMiniServices();
4995
- this.flushEngagement();
4996
- this.flushAnalytics({ final: true });
4511
+ this.closeSession("page_hide");
4997
4512
  });
4998
4513
  document.addEventListener("visibilitychange", () => {
4999
4514
  if (document.visibilityState === "hidden") {
@@ -5671,7 +5186,8 @@ function setupReactNative(sdk, config, deps = {}) {
5671
5186
  if (deps.appState?.addEventListener) {
5672
5187
  subscription = deps.appState.addEventListener("change", (state) => {
5673
5188
  if (state === "active") sdk.onForeground();
5674
- else sdk.onBackground();
5189
+ else if (state === "background") sdk.onBackground();
5190
+ else sdk.flushAnalytics();
5675
5191
  });
5676
5192
  }
5677
5193
  return () => {