@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.esm.js CHANGED
@@ -598,6 +598,11 @@ async function updateSubdivisionSelect(select, apiKey, backendUrl, state, config
598
598
  const dataDefaultValue = !isMultiple
599
599
  ? select.dataset.defaultValue
600
600
  : undefined;
601
+ // Preserve user's current selection before clearing innerHTML
602
+ // This prevents preselected values from overwriting user selections
603
+ const currentValue = select.value;
604
+ const defaultValue = select.dataset.defaultValue || '';
605
+ const hasUserSelection = currentValue && currentValue !== defaultValue && currentValue.trim() !== '';
601
606
  select.innerHTML = buildSubdivisionOptionsHTML(subdivisions, select, subdivisionsLanguage, config.showSubdivisionType, config.allowParentSelection, config.subdivisionNameFilter);
602
607
  // Restore data attributes after setting innerHTML
603
608
  if (!isMultiple) {
@@ -608,41 +613,53 @@ async function updateSubdivisionSelect(select, apiKey, backendUrl, state, config
608
613
  select.dataset.defaultValue = dataDefaultValue;
609
614
  }
610
615
  }
611
- // Manual preselection wins
612
- // Check if preselected value exists (applyPreselectedValue will read it from select element)
613
- const hasPreselectedValue = (select.getAttribute('data-preselected') || select.dataset.preselected || select.dataset._widgetTempPreselect) !== undefined;
614
- if (hasPreselectedValue) {
615
- applyPreselectedValue(select, apiKey);
616
- dispatchUpdateEvent(select, {
617
- type: 'subdivision',
618
- reason: 'preselected',
619
- });
620
- valueSetByWidget = true;
621
- 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));
616
+ // Restore user's selection if it exists in the new options (user selection takes priority)
617
+ let userSelectionRestored = false;
618
+ if (hasUserSelection && !isMultiple) {
619
+ const optionExists = Array.from(select.options).some(opt => opt.value === currentValue);
620
+ if (optionExists) {
621
+ select.value = currentValue;
622
+ userSelectionRestored = true;
623
+ // Don't dispatch event here - user already selected it, no need to notify again
624
+ }
622
625
  }
623
- else {
624
- // Try GeoIP preselect
625
- if (shouldUseGeoIP) {
626
- const preselectedSubdivision = subdivisions.find((subdivision) => subdivision.preselected);
627
- if (preselectedSubdivision) {
628
- const isMultiple = select.hasAttribute('multiple');
629
- if (isMultiple) {
630
- // For multi-select, find and select the option
631
- const option = Array.from(select.options).find((opt) => opt.value === preselectedSubdivision.code);
632
- if (option) {
633
- option.selected = true;
626
+ // Manual preselection only if user hasn't selected anything
627
+ if (!userSelectionRestored) {
628
+ // Check if preselected value exists (applyPreselectedValue will read it from select element)
629
+ const hasPreselectedValue = (select.getAttribute('data-preselected') || select.dataset.preselected || select.dataset._widgetTempPreselect) !== undefined;
630
+ if (hasPreselectedValue) {
631
+ applyPreselectedValue(select, apiKey);
632
+ dispatchUpdateEvent(select, {
633
+ type: 'subdivision',
634
+ reason: 'preselected',
635
+ });
636
+ valueSetByWidget = true;
637
+ 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));
638
+ }
639
+ else {
640
+ // Try GeoIP preselect (only if user hasn't selected anything)
641
+ if (shouldUseGeoIP) {
642
+ const preselectedSubdivision = subdivisions.find((subdivision) => subdivision.preselected);
643
+ if (preselectedSubdivision) {
644
+ const isMultiple = select.hasAttribute('multiple');
645
+ if (isMultiple) {
646
+ // For multi-select, find and select the option
647
+ const option = Array.from(select.options).find((opt) => opt.value === preselectedSubdivision.code);
648
+ if (option) {
649
+ option.selected = true;
650
+ }
634
651
  }
652
+ else {
653
+ // Single select: set value directly
654
+ select.value = preselectedSubdivision.code;
655
+ }
656
+ dispatchUpdateEvent(select, {
657
+ type: 'subdivision',
658
+ reason: 'geoip',
659
+ });
660
+ valueSetByWidget = true;
661
+ 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));
635
662
  }
636
- else {
637
- // Single select: set value directly
638
- select.value = preselectedSubdivision.code;
639
- }
640
- dispatchUpdateEvent(select, {
641
- type: 'subdivision',
642
- reason: 'geoip',
643
- });
644
- valueSetByWidget = true;
645
- 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));
646
663
  }
647
664
  }
648
665
  }
@@ -677,6 +694,27 @@ async function updateSubdivisionSelect(select, apiKey, backendUrl, state, config
677
694
  select.innerHTML += `<option value="${defaultValue}" disabled>Error: No country select present</option>`;
678
695
  }
679
696
  }
697
+ /**
698
+ * Get current subdivision config from window.CountriesDBConfig
699
+ * This ensures we always use the latest config values, even after widget reload
700
+ */
701
+ function getCurrentSubdivisionConfig(apiKey, backendUrl) {
702
+ const globalConfig = typeof window !== 'undefined' && window.CountriesDBConfig
703
+ ? window.CountriesDBConfig
704
+ : null;
705
+ return {
706
+ followRelated: globalConfig?.followRelated || false,
707
+ followUpward: globalConfig?.followUpward || false,
708
+ showSubdivisionType: globalConfig?.showSubdivisionType !== false,
709
+ allowParentSelection: globalConfig?.allowParentSelection || false,
710
+ preferOfficialSubdivisions: globalConfig?.preferOfficialSubdivisions || false,
711
+ subdivisionRomanizationPreference: globalConfig?.subdivisionRomanizationPreference,
712
+ preferLocalVariant: globalConfig?.preferLocalVariant || false,
713
+ forcedLanguage: globalConfig?.forcedLanguage,
714
+ defaultLanguage: globalConfig?.defaultLanguage,
715
+ subdivisionNameFilter: globalConfig?.subdivisionNameFilter,
716
+ };
717
+ }
680
718
  /**
681
719
  * Update subdivisions for all linked subdivision selects when country changes
682
720
  */
@@ -777,8 +815,13 @@ async function setupCountrySelection(apiKey, backendUrl, state, config, subdivis
777
815
  }
778
816
  // Dispatch update event for user-initiated country change
779
817
  dispatchUpdateEvent(select, { type: 'country', reason: 'regular' });
780
- // Update subdivisions
781
- await updateSubdivisions(select, apiKey, backendUrl, state, subdivisionConfig);
818
+ // Get current config dynamically to ensure we use the latest values
819
+ const currentSubdivisionConfig = getCurrentSubdivisionConfig(apiKey, backendUrl);
820
+ const currentConfig = typeof window !== 'undefined' && window.CountriesDBConfig
821
+ ? window.CountriesDBConfig
822
+ : config;
823
+ // Update subdivisions with current config
824
+ await updateSubdivisions(select, apiKey, backendUrl, state, currentSubdivisionConfig);
782
825
  const chosen = select.value;
783
826
  if (!chosen) {
784
827
  return;
@@ -790,8 +833,9 @@ async function setupCountrySelection(apiKey, backendUrl, state, config, subdivis
790
833
  }
791
834
  // followUpward from country perspective
792
835
  // Only works when country is single-select (never for multi-select)
793
- if (config.followUpward && !select.multiple && picked.is_subdivision_of) {
794
- await handleFollowUpwardFromCountry(select, apiKey, backendUrl, state, config.followUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, subdivisionConfig, code));
836
+ const currentFollowUpward = currentConfig?.followUpward || false;
837
+ if (currentFollowUpward && !select.multiple && picked.is_subdivision_of) {
838
+ await handleFollowUpwardFromCountry(select, apiKey, backendUrl, state, currentFollowUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, currentSubdivisionConfig, code));
795
839
  }
796
840
  };
797
841
  // Store and attach the handler
@@ -908,7 +952,7 @@ async function CountriesWidgetLoad(options = {}) {
908
952
  followRelated: config.followRelated || false,
909
953
  followUpward: config.followUpward || false,
910
954
  countryNameFilter: config.countryNameFilter,
911
- }, subdivisionConfig);
955
+ });
912
956
  // After countries are set up, update subdivisions for any preselected countries
913
957
  const countrySelects = Array.from(document.querySelectorAll('.country-selection'));
914
958
  for (const select of countrySelects) {