@countriesdb/widget 0.1.33 → 0.1.35

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.
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Widget initialization logic
3
3
  */
4
- import { CountriesDBClient } from '@countriesdb/widget-core';
4
+ import { CountriesDBClient, buildSubdivisionTree } from '@countriesdb/widget-core';
5
5
  import { initializeSelect, populateCountrySelect, buildSubdivisionOptionsHTML, applyPreselectedValue, handleApiError, } from './dom-manipulation';
6
6
  import { dispatchReadyEvent, dispatchUpdateEvent, isWidgetInitiatedEvent, } from './event-system';
7
7
  import { triggerFollowLogic, handleFollowRelatedFromSubdivision, handleFollowUpwardFromSubdivision, handleFollowUpwardFromCountry, } from './follow-logic';
@@ -156,7 +156,13 @@ export async function updateSubdivisionSelect(select, apiKey, backendUrl, state,
156
156
  if (!userSelectionRestored) {
157
157
  // Check if preselected value exists (applyPreselectedValue will read it from select element)
158
158
  const hasPreselectedValue = (select.getAttribute('data-preselected') || select.dataset.preselected || select.dataset._widgetTempPreselect) !== undefined;
159
- if (hasPreselectedValue) {
159
+ const preselectedConsumed = select.dataset._widgetPreselectedConsumed === '1';
160
+ // Only apply preselected if:
161
+ // 1. It exists AND
162
+ // 2. Either it hasn't been consumed yet, OR this is the initial load (not a reload)
163
+ // This prevents reapplying preselected values on user-initiated country changes
164
+ // But allows them on initial load and on reload: true (which clears the consumed flag)
165
+ if (hasPreselectedValue && (!preselectedConsumed || !isReload)) {
160
166
  applyPreselectedValue(select, apiKey);
161
167
  dispatchUpdateEvent(select, {
162
168
  type: 'subdivision',
@@ -171,16 +177,64 @@ export async function updateSubdivisionSelect(select, apiKey, backendUrl, state,
171
177
  const preselectedSubdivision = subdivisions.find((subdivision) => subdivision.preselected);
172
178
  if (preselectedSubdivision) {
173
179
  const isMultiple = select.hasAttribute('multiple');
180
+ let subdivisionToSelect = preselectedSubdivision;
181
+ // Check if the preselected subdivision is disabled (parent with children when allowParentSelection is false)
182
+ if (!config.allowParentSelection && !isMultiple) {
183
+ const option = Array.from(select.options).find((opt) => opt.value === preselectedSubdivision.code);
184
+ // If option is disabled, find the first child subdivision
185
+ if (option && option.disabled) {
186
+ const tree = buildSubdivisionTree(subdivisions);
187
+ // Find the node in the tree
188
+ function findNodeInTree(nodes, code) {
189
+ for (const node of nodes) {
190
+ if (node.code === code) {
191
+ return node;
192
+ }
193
+ if (node.children && node.children.length > 0) {
194
+ const found = findNodeInTree(node.children, code);
195
+ if (found)
196
+ return found;
197
+ }
198
+ }
199
+ return null;
200
+ }
201
+ const preselectedNode = findNodeInTree(tree, preselectedSubdivision.code);
202
+ // Get the first child (recursively if needed)
203
+ function getFirstChild(node) {
204
+ if (!node || !node.children || node.children.length === 0) {
205
+ return null;
206
+ }
207
+ // Sort children to get consistent first child
208
+ const sortedChildren = [...node.children].sort((a, b) => {
209
+ const nameA = a.name || '';
210
+ const nameB = b.name || '';
211
+ return nameA.localeCompare(nameB);
212
+ });
213
+ const firstChild = sortedChildren[0];
214
+ // If first child also has children and would be disabled, recurse
215
+ if (firstChild.children && firstChild.children.length > 0) {
216
+ const deeperChild = getFirstChild(firstChild);
217
+ return deeperChild || firstChild;
218
+ }
219
+ return firstChild;
220
+ }
221
+ const firstChild = preselectedNode ? getFirstChild(preselectedNode) : null;
222
+ if (firstChild) {
223
+ // Find the subdivision object by code
224
+ subdivisionToSelect = subdivisions.find((sub) => sub.code === firstChild.code) || preselectedSubdivision;
225
+ }
226
+ }
227
+ }
174
228
  if (isMultiple) {
175
229
  // For multi-select, find and select the option
176
- const option = Array.from(select.options).find((opt) => opt.value === preselectedSubdivision.code);
230
+ const option = Array.from(select.options).find((opt) => opt.value === subdivisionToSelect.code);
177
231
  if (option) {
178
232
  option.selected = true;
179
233
  }
180
234
  }
181
235
  else {
182
236
  // Single select: set value directly
183
- select.value = preselectedSubdivision.code;
237
+ select.value = subdivisionToSelect.code;
184
238
  }
185
239
  dispatchUpdateEvent(select, {
186
240
  type: 'subdivision',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@countriesdb/widget",
3
- "version": "0.1.33",
3
+ "version": "0.1.35",
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",