@countriesdb/widget 0.1.26 → 0.1.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -844,6 +844,11 @@
844
844
  const dataDefaultValue = !isMultiple
845
845
  ? select.dataset.defaultValue
846
846
  : undefined;
847
+ // Preserve user's current selection before clearing innerHTML
848
+ // This prevents preselected values from overwriting user selections
849
+ const currentValue = select.value;
850
+ const defaultValue = select.dataset.defaultValue || '';
851
+ const hasUserSelection = currentValue && currentValue !== defaultValue && currentValue.trim() !== '';
847
852
  select.innerHTML = buildSubdivisionOptionsHTML(subdivisions, select, subdivisionsLanguage, config.showSubdivisionType, config.allowParentSelection, config.subdivisionNameFilter);
848
853
  // Restore data attributes after setting innerHTML
849
854
  if (!isMultiple) {
@@ -854,41 +859,53 @@
854
859
  select.dataset.defaultValue = dataDefaultValue;
855
860
  }
856
861
  }
857
- // Manual preselection wins
858
- // Check if preselected value exists (applyPreselectedValue will read it from select element)
859
- const hasPreselectedValue = (select.getAttribute('data-preselected') || select.dataset.preselected || select.dataset._widgetTempPreselect) !== undefined;
860
- if (hasPreselectedValue) {
861
- applyPreselectedValue(select, apiKey);
862
- dispatchUpdateEvent(select, {
863
- type: 'subdivision',
864
- reason: 'preselected',
865
- });
866
- valueSetByWidget = true;
867
- await triggerFollowLogic(select, apiKey, backendUrl, state, config.followRelated, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code), (countrySelect, key) => updateSubdivisions(countrySelect, key, backendUrl, state, config));
862
+ // Restore user's selection if it exists in the new options (user selection takes priority)
863
+ let userSelectionRestored = false;
864
+ if (hasUserSelection && !isMultiple) {
865
+ const optionExists = Array.from(select.options).some(opt => opt.value === currentValue);
866
+ if (optionExists) {
867
+ select.value = currentValue;
868
+ userSelectionRestored = true;
869
+ // Don't dispatch event here - user already selected it, no need to notify again
870
+ }
868
871
  }
869
- else {
870
- // Try GeoIP preselect
871
- if (shouldUseGeoIP) {
872
- const preselectedSubdivision = subdivisions.find((subdivision) => subdivision.preselected);
873
- if (preselectedSubdivision) {
874
- const isMultiple = select.hasAttribute('multiple');
875
- if (isMultiple) {
876
- // For multi-select, find and select the option
877
- const option = Array.from(select.options).find((opt) => opt.value === preselectedSubdivision.code);
878
- if (option) {
879
- option.selected = true;
872
+ // Manual preselection only if user hasn't selected anything
873
+ if (!userSelectionRestored) {
874
+ // Check if preselected value exists (applyPreselectedValue will read it from select element)
875
+ const hasPreselectedValue = (select.getAttribute('data-preselected') || select.dataset.preselected || select.dataset._widgetTempPreselect) !== undefined;
876
+ if (hasPreselectedValue) {
877
+ applyPreselectedValue(select, apiKey);
878
+ dispatchUpdateEvent(select, {
879
+ type: 'subdivision',
880
+ reason: 'preselected',
881
+ });
882
+ valueSetByWidget = true;
883
+ await triggerFollowLogic(select, apiKey, backendUrl, state, config.followRelated, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code), (countrySelect, key) => updateSubdivisions(countrySelect, key, backendUrl, state, config));
884
+ }
885
+ else {
886
+ // Try GeoIP preselect (only if user hasn't selected anything)
887
+ if (shouldUseGeoIP) {
888
+ const preselectedSubdivision = subdivisions.find((subdivision) => subdivision.preselected);
889
+ if (preselectedSubdivision) {
890
+ const isMultiple = select.hasAttribute('multiple');
891
+ if (isMultiple) {
892
+ // For multi-select, find and select the option
893
+ const option = Array.from(select.options).find((opt) => opt.value === preselectedSubdivision.code);
894
+ if (option) {
895
+ option.selected = true;
896
+ }
880
897
  }
898
+ else {
899
+ // Single select: set value directly
900
+ select.value = preselectedSubdivision.code;
901
+ }
902
+ dispatchUpdateEvent(select, {
903
+ type: 'subdivision',
904
+ reason: 'geoip',
905
+ });
906
+ valueSetByWidget = true;
907
+ await triggerFollowLogic(select, apiKey, backendUrl, state, config.followRelated, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code), (countrySelect, key) => updateSubdivisions(countrySelect, key, backendUrl, state, config));
881
908
  }
882
- else {
883
- // Single select: set value directly
884
- select.value = preselectedSubdivision.code;
885
- }
886
- dispatchUpdateEvent(select, {
887
- type: 'subdivision',
888
- reason: 'geoip',
889
- });
890
- valueSetByWidget = true;
891
- await triggerFollowLogic(select, apiKey, backendUrl, state, config.followRelated, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, config, code), (countrySelect, key) => updateSubdivisions(countrySelect, key, backendUrl, state, config));
892
909
  }
893
910
  }
894
911
  }
@@ -923,6 +940,27 @@
923
940
  select.innerHTML += `<option value="${defaultValue}" disabled>Error: No country select present</option>`;
924
941
  }
925
942
  }
943
+ /**
944
+ * Get current subdivision config from window.CountriesDBConfig
945
+ * This ensures we always use the latest config values, even after widget reload
946
+ */
947
+ function getCurrentSubdivisionConfig(apiKey, backendUrl) {
948
+ const globalConfig = typeof window !== 'undefined' && window.CountriesDBConfig
949
+ ? window.CountriesDBConfig
950
+ : null;
951
+ return {
952
+ followRelated: globalConfig?.followRelated || false,
953
+ followUpward: globalConfig?.followUpward || false,
954
+ showSubdivisionType: globalConfig?.showSubdivisionType !== false,
955
+ allowParentSelection: globalConfig?.allowParentSelection || false,
956
+ preferOfficialSubdivisions: globalConfig?.preferOfficialSubdivisions || false,
957
+ subdivisionRomanizationPreference: globalConfig?.subdivisionRomanizationPreference,
958
+ preferLocalVariant: globalConfig?.preferLocalVariant || false,
959
+ forcedLanguage: globalConfig?.forcedLanguage,
960
+ defaultLanguage: globalConfig?.defaultLanguage,
961
+ subdivisionNameFilter: globalConfig?.subdivisionNameFilter,
962
+ };
963
+ }
926
964
  /**
927
965
  * Update subdivisions for all linked subdivision selects when country changes
928
966
  */
@@ -1023,8 +1061,13 @@
1023
1061
  }
1024
1062
  // Dispatch update event for user-initiated country change
1025
1063
  dispatchUpdateEvent(select, { type: 'country', reason: 'regular' });
1026
- // Update subdivisions
1027
- await updateSubdivisions(select, apiKey, backendUrl, state, subdivisionConfig);
1064
+ // Get current config dynamically to ensure we use the latest values
1065
+ const currentSubdivisionConfig = getCurrentSubdivisionConfig(apiKey, backendUrl);
1066
+ const currentConfig = typeof window !== 'undefined' && window.CountriesDBConfig
1067
+ ? window.CountriesDBConfig
1068
+ : config;
1069
+ // Update subdivisions with current config
1070
+ await updateSubdivisions(select, apiKey, backendUrl, state, currentSubdivisionConfig);
1028
1071
  const chosen = select.value;
1029
1072
  if (!chosen) {
1030
1073
  return;
@@ -1036,8 +1079,9 @@
1036
1079
  }
1037
1080
  // followUpward from country perspective
1038
1081
  // Only works when country is single-select (never for multi-select)
1039
- if (config.followUpward && !select.multiple && picked.is_subdivision_of) {
1040
- await handleFollowUpwardFromCountry(select, apiKey, backendUrl, state, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, subdivisionConfig, code));
1082
+ const currentFollowUpward = currentConfig?.followUpward || false;
1083
+ if (currentFollowUpward && !select.multiple && picked.is_subdivision_of) {
1084
+ await handleFollowUpwardFromCountry(select, apiKey, backendUrl, state, currentFollowUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, currentSubdivisionConfig, code));
1041
1085
  }
1042
1086
  };
1043
1087
  // Store and attach the handler
@@ -1154,7 +1198,7 @@
1154
1198
  followRelated: config.followRelated || false,
1155
1199
  followUpward: config.followUpward || false,
1156
1200
  countryNameFilter: config.countryNameFilter,
1157
- }, subdivisionConfig);
1201
+ });
1158
1202
  // After countries are set up, update subdivisions for any preselected countries
1159
1203
  const countrySelects = Array.from(document.querySelectorAll('.country-selection'));
1160
1204
  for (const select of countrySelects) {