@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 +81 -37
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +81 -37
- package/dist/index.js.map +1 -1
- package/dist/initialization.js +80 -36
- package/package.json +1 -1
package/dist/initialization.js
CHANGED
|
@@ -127,6 +127,11 @@ export async function updateSubdivisionSelect(select, apiKey, backendUrl, state,
|
|
|
127
127
|
const dataDefaultValue = !isMultiple
|
|
128
128
|
? select.dataset.defaultValue
|
|
129
129
|
: undefined;
|
|
130
|
+
// Preserve user's current selection before clearing innerHTML
|
|
131
|
+
// This prevents preselected values from overwriting user selections
|
|
132
|
+
const currentValue = select.value;
|
|
133
|
+
const defaultValue = select.dataset.defaultValue || '';
|
|
134
|
+
const hasUserSelection = currentValue && currentValue !== defaultValue && currentValue.trim() !== '';
|
|
130
135
|
select.innerHTML = buildSubdivisionOptionsHTML(subdivisions, select, subdivisionsLanguage, config.showSubdivisionType, config.allowParentSelection, config.subdivisionNameFilter);
|
|
131
136
|
// Restore data attributes after setting innerHTML
|
|
132
137
|
if (!isMultiple) {
|
|
@@ -137,41 +142,53 @@ export async function updateSubdivisionSelect(select, apiKey, backendUrl, state,
|
|
|
137
142
|
select.dataset.defaultValue = dataDefaultValue;
|
|
138
143
|
}
|
|
139
144
|
}
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
valueSetByWidget = true;
|
|
150
|
-
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));
|
|
145
|
+
// Restore user's selection if it exists in the new options (user selection takes priority)
|
|
146
|
+
let userSelectionRestored = false;
|
|
147
|
+
if (hasUserSelection && !isMultiple) {
|
|
148
|
+
const optionExists = Array.from(select.options).some(opt => opt.value === currentValue);
|
|
149
|
+
if (optionExists) {
|
|
150
|
+
select.value = currentValue;
|
|
151
|
+
userSelectionRestored = true;
|
|
152
|
+
// Don't dispatch event here - user already selected it, no need to notify again
|
|
153
|
+
}
|
|
151
154
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if (
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
155
|
+
// Manual preselection only if user hasn't selected anything
|
|
156
|
+
if (!userSelectionRestored) {
|
|
157
|
+
// Check if preselected value exists (applyPreselectedValue will read it from select element)
|
|
158
|
+
const hasPreselectedValue = (select.getAttribute('data-preselected') || select.dataset.preselected || select.dataset._widgetTempPreselect) !== undefined;
|
|
159
|
+
if (hasPreselectedValue) {
|
|
160
|
+
applyPreselectedValue(select, apiKey);
|
|
161
|
+
dispatchUpdateEvent(select, {
|
|
162
|
+
type: 'subdivision',
|
|
163
|
+
reason: 'preselected',
|
|
164
|
+
});
|
|
165
|
+
valueSetByWidget = true;
|
|
166
|
+
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));
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
// Try GeoIP preselect (only if user hasn't selected anything)
|
|
170
|
+
if (shouldUseGeoIP) {
|
|
171
|
+
const preselectedSubdivision = subdivisions.find((subdivision) => subdivision.preselected);
|
|
172
|
+
if (preselectedSubdivision) {
|
|
173
|
+
const isMultiple = select.hasAttribute('multiple');
|
|
174
|
+
if (isMultiple) {
|
|
175
|
+
// For multi-select, find and select the option
|
|
176
|
+
const option = Array.from(select.options).find((opt) => opt.value === preselectedSubdivision.code);
|
|
177
|
+
if (option) {
|
|
178
|
+
option.selected = true;
|
|
179
|
+
}
|
|
163
180
|
}
|
|
181
|
+
else {
|
|
182
|
+
// Single select: set value directly
|
|
183
|
+
select.value = preselectedSubdivision.code;
|
|
184
|
+
}
|
|
185
|
+
dispatchUpdateEvent(select, {
|
|
186
|
+
type: 'subdivision',
|
|
187
|
+
reason: 'geoip',
|
|
188
|
+
});
|
|
189
|
+
valueSetByWidget = true;
|
|
190
|
+
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));
|
|
164
191
|
}
|
|
165
|
-
else {
|
|
166
|
-
// Single select: set value directly
|
|
167
|
-
select.value = preselectedSubdivision.code;
|
|
168
|
-
}
|
|
169
|
-
dispatchUpdateEvent(select, {
|
|
170
|
-
type: 'subdivision',
|
|
171
|
-
reason: 'geoip',
|
|
172
|
-
});
|
|
173
|
-
valueSetByWidget = true;
|
|
174
|
-
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));
|
|
175
192
|
}
|
|
176
193
|
}
|
|
177
194
|
}
|
|
@@ -206,6 +223,27 @@ export async function updateSubdivisionSelect(select, apiKey, backendUrl, state,
|
|
|
206
223
|
select.innerHTML += `<option value="${defaultValue}" disabled>Error: No country select present</option>`;
|
|
207
224
|
}
|
|
208
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Get current subdivision config from window.CountriesDBConfig
|
|
228
|
+
* This ensures we always use the latest config values, even after widget reload
|
|
229
|
+
*/
|
|
230
|
+
function getCurrentSubdivisionConfig(apiKey, backendUrl) {
|
|
231
|
+
const globalConfig = typeof window !== 'undefined' && window.CountriesDBConfig
|
|
232
|
+
? window.CountriesDBConfig
|
|
233
|
+
: null;
|
|
234
|
+
return {
|
|
235
|
+
followRelated: globalConfig?.followRelated || false,
|
|
236
|
+
followUpward: globalConfig?.followUpward || false,
|
|
237
|
+
showSubdivisionType: globalConfig?.showSubdivisionType !== false,
|
|
238
|
+
allowParentSelection: globalConfig?.allowParentSelection || false,
|
|
239
|
+
preferOfficialSubdivisions: globalConfig?.preferOfficialSubdivisions || false,
|
|
240
|
+
subdivisionRomanizationPreference: globalConfig?.subdivisionRomanizationPreference,
|
|
241
|
+
preferLocalVariant: globalConfig?.preferLocalVariant || false,
|
|
242
|
+
forcedLanguage: globalConfig?.forcedLanguage,
|
|
243
|
+
defaultLanguage: globalConfig?.defaultLanguage,
|
|
244
|
+
subdivisionNameFilter: globalConfig?.subdivisionNameFilter,
|
|
245
|
+
};
|
|
246
|
+
}
|
|
209
247
|
/**
|
|
210
248
|
* Update subdivisions for all linked subdivision selects when country changes
|
|
211
249
|
*/
|
|
@@ -306,8 +344,13 @@ export async function setupCountrySelection(apiKey, backendUrl, state, config, s
|
|
|
306
344
|
}
|
|
307
345
|
// Dispatch update event for user-initiated country change
|
|
308
346
|
dispatchUpdateEvent(select, { type: 'country', reason: 'regular' });
|
|
309
|
-
//
|
|
310
|
-
|
|
347
|
+
// Get current config dynamically to ensure we use the latest values
|
|
348
|
+
const currentSubdivisionConfig = getCurrentSubdivisionConfig(apiKey, backendUrl);
|
|
349
|
+
const currentConfig = typeof window !== 'undefined' && window.CountriesDBConfig
|
|
350
|
+
? window.CountriesDBConfig
|
|
351
|
+
: config;
|
|
352
|
+
// Update subdivisions with current config
|
|
353
|
+
await updateSubdivisions(select, apiKey, backendUrl, state, currentSubdivisionConfig);
|
|
311
354
|
const chosen = select.value;
|
|
312
355
|
if (!chosen) {
|
|
313
356
|
return;
|
|
@@ -319,8 +362,9 @@ export async function setupCountrySelection(apiKey, backendUrl, state, config, s
|
|
|
319
362
|
}
|
|
320
363
|
// followUpward from country perspective
|
|
321
364
|
// Only works when country is single-select (never for multi-select)
|
|
322
|
-
|
|
323
|
-
|
|
365
|
+
const currentFollowUpward = currentConfig?.followUpward || false;
|
|
366
|
+
if (currentFollowUpward && !select.multiple && picked.is_subdivision_of) {
|
|
367
|
+
await handleFollowUpwardFromCountry(select, apiKey, backendUrl, state, currentFollowUpward, (s, key, code) => updateSubdivisionSelect(s, key, backendUrl, state, currentSubdivisionConfig, code));
|
|
324
368
|
}
|
|
325
369
|
};
|
|
326
370
|
// Store and attach the handler
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@countriesdb/widget",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.28",
|
|
4
4
|
"description": "Country and state/province select widget with ISO 3166-1 and ISO 3166-2 codes. Auto-populates dropdowns with up-to-date country and subdivision data in multiple languages. Easy integration for forms, location selection, and address validation.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|