@keenthemes/ktui 1.0.26 → 1.0.27

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.
Files changed (60) hide show
  1. package/dist/ktui.js +136 -17
  2. package/dist/ktui.min.js +1 -1
  3. package/dist/ktui.min.js.map +1 -1
  4. package/dist/styles.css +6 -13
  5. package/examples/modal/remote-select-dropdown.html +166 -0
  6. package/examples/modal/select-dropdown-container.html +129 -0
  7. package/examples/select/modal-positioning-test.html +10 -8
  8. package/lib/cjs/components/modal/modal.js +13 -1
  9. package/lib/cjs/components/modal/modal.js.map +1 -1
  10. package/lib/cjs/components/select/dropdown.js +34 -6
  11. package/lib/cjs/components/select/dropdown.js.map +1 -1
  12. package/lib/cjs/components/select/select.js +89 -10
  13. package/lib/cjs/components/select/select.js.map +1 -1
  14. package/lib/esm/components/modal/modal.js +13 -1
  15. package/lib/esm/components/modal/modal.js.map +1 -1
  16. package/lib/esm/components/select/dropdown.js +34 -6
  17. package/lib/esm/components/select/dropdown.js.map +1 -1
  18. package/lib/esm/components/select/select.js +89 -10
  19. package/lib/esm/components/select/select.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/modal/modal.ts +15 -1
  22. package/src/components/select/dropdown.ts +42 -6
  23. package/src/components/select/select.ts +123 -10
  24. package/lib/cjs/components/config.js +0 -26
  25. package/lib/cjs/components/config.js.map +0 -1
  26. package/lib/cjs/components/config.umd.js +0 -23
  27. package/lib/cjs/components/config.umd.js.map +0 -1
  28. package/lib/cjs/components/menu/index.js +0 -6
  29. package/lib/cjs/components/menu/index.js.map +0 -1
  30. package/lib/cjs/components/menu/menu.js +0 -1021
  31. package/lib/cjs/components/menu/menu.js.map +0 -1
  32. package/lib/cjs/components/menu/types.js +0 -3
  33. package/lib/cjs/components/menu/types.js.map +0 -1
  34. package/lib/cjs/components/theme/index.js +0 -6
  35. package/lib/cjs/components/theme/index.js.map +0 -1
  36. package/lib/cjs/components/theme/theme.js +0 -147
  37. package/lib/cjs/components/theme/theme.js.map +0 -1
  38. package/lib/cjs/components/theme/types.js +0 -3
  39. package/lib/cjs/components/theme/types.js.map +0 -1
  40. package/lib/esm/components/config.js +0 -24
  41. package/lib/esm/components/config.js.map +0 -1
  42. package/lib/esm/components/config.umd.js +0 -23
  43. package/lib/esm/components/config.umd.js.map +0 -1
  44. package/lib/esm/components/menu/index.js +0 -2
  45. package/lib/esm/components/menu/index.js.map +0 -1
  46. package/lib/esm/components/menu/menu.js +0 -1018
  47. package/lib/esm/components/menu/menu.js.map +0 -1
  48. package/lib/esm/components/menu/types.js +0 -2
  49. package/lib/esm/components/menu/types.js.map +0 -1
  50. package/lib/esm/components/theme/index.js +0 -2
  51. package/lib/esm/components/theme/index.js.map +0 -1
  52. package/lib/esm/components/theme/theme.js +0 -144
  53. package/lib/esm/components/theme/theme.js.map +0 -1
  54. package/lib/esm/components/theme/types.js +0 -2
  55. package/lib/esm/components/theme/types.js.map +0 -1
  56. /package/examples/modal/{persistent-test.html → persistent.html} +0 -0
  57. /package/examples/select/{dark-mode-test.html → dark-mode.html} +0 -0
  58. /package/examples/select/{dropdowncontainer-test.html → dropdowncontainer.html} +0 -0
  59. /package/examples/select/{formdata-remote-test.html → formdata-remote.html} +0 -0
  60. /package/examples/select/{global-config-test.html → global-config.html} +0 -0
package/dist/ktui.js CHANGED
@@ -9252,8 +9252,20 @@ var KTModal = /** @class */ (function (_super) {
9252
9252
  KTModal.prototype._handlers = function () {
9253
9253
  var _this = this;
9254
9254
  this._element.addEventListener('click', function (event) {
9255
- if (_this._element !== event.target)
9255
+ var target = event.target;
9256
+ var currentTarget = event.currentTarget;
9257
+ // Only proceed if clicking directly on the backdrop (modal element itself)
9258
+ // This prevents closing when clicking inside modal content or any child elements
9259
+ // (including dropdowns rendered via dropdownContainer pointing to modal)
9260
+ if (target !== currentTarget) {
9261
+ // Stop propagation for clicks inside dropdowns to prevent dropdown from closing
9262
+ // Check if click is inside a dropdown element (KT Select dropdown)
9263
+ var dropdownElement = target.closest('[data-kt-select-dropdown]');
9264
+ if (dropdownElement) {
9265
+ event.stopPropagation();
9266
+ }
9256
9267
  return;
9268
+ }
9257
9269
  // Only hide if both backdropStatic is false AND persistent is false
9258
9270
  if (_this._getOption('backdropStatic') === false &&
9259
9271
  utils_1.default.stringToBoolean(_this._getOption('persistent')) === false) {
@@ -9576,8 +9588,14 @@ var KTSelectDropdown = /** @class */ (function (_super) {
9576
9588
  _this._dropdownElement = dropdownElement;
9577
9589
  _this._config = config;
9578
9590
  _this._ktSelectInstance = ktSelectInstance; // Assign instance
9591
+ // For centered modals, don't move dropdown to container to preserve positioning context
9592
+ // For other cases, move to container if specified
9593
+ var modalParent = _this._getModalContainer();
9594
+ var isCenteredModal = modalParent && modalParent.classList.contains('kt-modal-center');
9595
+ // Only move dropdown if not in centered modal (regardless of strategy override)
9596
+ // This prevents the positioning bug even if user sets dropdownStrategy: 'fixed'
9579
9597
  var container = _this._resolveDropdownContainer();
9580
- if (container) {
9598
+ if (container && !isCenteredModal) {
9581
9599
  if (container !== _this._dropdownElement.parentElement) {
9582
9600
  container.appendChild(_this._dropdownElement);
9583
9601
  }
@@ -9652,17 +9670,40 @@ var KTSelectDropdown = /** @class */ (function (_super) {
9652
9670
  KTSelectDropdown.prototype._getModalContainer = function () {
9653
9671
  return this._element.closest('[data-kt-modal], .kt-modal, .kt-modal-center');
9654
9672
  };
9673
+ /**
9674
+ * Get the appropriate boundary element for Popper positioning
9675
+ * For centered modals, use .kt-modal-content to avoid transform calculation issues
9676
+ * @returns The boundary element, or null if no modal found
9677
+ */
9678
+ KTSelectDropdown.prototype._getModalBoundary = function () {
9679
+ var modalParent = this._getModalContainer();
9680
+ if (!modalParent) {
9681
+ return null;
9682
+ }
9683
+ // For centered modals, use .kt-modal-content as boundary to avoid transform issues
9684
+ if (modalParent.classList.contains('kt-modal-center')) {
9685
+ var modalContent = modalParent.querySelector('.kt-modal-content');
9686
+ return modalContent || modalParent;
9687
+ }
9688
+ // For non-centered modals, use the modal element itself
9689
+ return modalParent;
9690
+ };
9655
9691
  /**
9656
9692
  * Get the appropriate positioning strategy based on context
9657
- * @returns 'fixed' if inside modal, 'absolute' otherwise
9693
+ * @returns 'fixed' if inside non-centered modal, 'absolute' for centered modals or no modal
9658
9694
  */
9659
9695
  KTSelectDropdown.prototype._getPositioningStrategy = function () {
9660
9696
  // Check if config explicitly sets strategy
9661
9697
  if (this._config.dropdownStrategy) {
9662
9698
  return this._config.dropdownStrategy;
9663
9699
  }
9664
- // Use fixed positioning if inside a modal (to handle transform-based centering)
9700
+ // For centered modals, use absolute positioning to avoid transform calculation issues
9701
+ // For non-centered modals, use fixed positioning
9665
9702
  var modalParent = this._getModalContainer();
9703
+ if (modalParent && modalParent.classList.contains('kt-modal-center')) {
9704
+ return 'absolute';
9705
+ }
9706
+ // Use fixed positioning for non-centered modals
9666
9707
  return modalParent ? 'fixed' : 'absolute';
9667
9708
  };
9668
9709
  /**
@@ -9678,9 +9719,8 @@ var KTSelectDropdown = /** @class */ (function (_super) {
9678
9719
  var strategy = this._getPositioningStrategy();
9679
9720
  var preventOverflow = this._config.dropdownPreventOverflow !== false;
9680
9721
  var flip = this._config.dropdownFlip !== false;
9681
- // Detect modal container for boundary
9682
- var modalParent = this._getModalContainer();
9683
- var boundary = modalParent || 'clippingParents';
9722
+ // Get appropriate boundary element for modal context
9723
+ var boundary = this._getModalBoundary() || 'clippingParents';
9684
9724
  // Create new popper instance
9685
9725
  this._popperInstance = (0, core_1.createPopper)(this._toggleElement, this._dropdownElement, {
9686
9726
  placement: placement,
@@ -11894,6 +11934,12 @@ var KTSelect = /** @class */ (function (_super) {
11894
11934
  KTSelect.prototype._completeRemoteSetup = function () {
11895
11935
  // Initialize options
11896
11936
  this._preSelectOptions(this._element);
11937
+ // Prevent browser auto-selection when placeholder is configured
11938
+ if (this._config.placeholder &&
11939
+ this._state.getSelectedOptions().length === 0 &&
11940
+ this._preSelectedValues.length === 0) {
11941
+ this._element.value = '';
11942
+ }
11897
11943
  // Apply pre-selected values captured before remote data was loaded
11898
11944
  if (this._preSelectedValues.length > 0) {
11899
11945
  if (this._config.debug) {
@@ -12136,6 +12182,11 @@ var KTSelect = /** @class */ (function (_super) {
12136
12182
  this._setupElementReferences();
12137
12183
  // Initialize options
12138
12184
  this._preSelectOptions(this._element);
12185
+ // Prevent browser auto-selection when placeholder is configured
12186
+ if (this._config.placeholder &&
12187
+ this._state.getSelectedOptions().length === 0) {
12188
+ this._element.value = '';
12189
+ }
12139
12190
  // Apply disabled state if needed
12140
12191
  this._applyInitialDisabledState();
12141
12192
  // Initialize search if enabled
@@ -13065,10 +13116,18 @@ var KTSelect = /** @class */ (function (_super) {
13065
13116
  };
13066
13117
  /**
13067
13118
  * Update the dropdown to sync with native select element changes
13068
- * For remote selects, refetches data from the server
13119
+ * For remote selects, refetches data from the server and preserves selections
13069
13120
  * Optionally accepts new options to replace existing ones (static selects only)
13070
- * @param newOptions Optional array of new options [{value, text}, ...]
13121
+ *
13122
+ * @param newOptions Optional array of new options [{value, text}, ...] (static selects only)
13071
13123
  * @public
13124
+ * @remarks
13125
+ * - For static selects: rebuilds dropdown from native select or new options
13126
+ * - For remote selects: fetches fresh data, preserves matching selections
13127
+ * - Selections are preserved if their values exist in new remote data
13128
+ * - Selections are cleared if their values don't exist in new data
13129
+ * @fires updated - After update completes successfully
13130
+ * @fires updateError - If remote data fetch fails
13072
13131
  */
13073
13132
  KTSelect.prototype.update = function (newOptions) {
13074
13133
  var _this = this;
@@ -13077,19 +13136,36 @@ var KTSelect = /** @class */ (function (_super) {
13077
13136
  this._remoteModule
13078
13137
  .fetchData()
13079
13138
  .then(function (items) {
13080
- // Clear existing options
13139
+ // Capture currently selected values before clearing
13140
+ var currentlySelected = _this._state.getSelectedOptions();
13141
+ // Clear existing options (also captures to _preSelectedValues)
13081
13142
  _this._clearExistingOptions();
13082
- // Add new options from remote data
13143
+ // Get all available values from new remote data
13144
+ var availableValues = items.map(function (item) { return item.id; });
13145
+ // Filter to only values that exist in new data
13146
+ var validSelections = currentlySelected.filter(function (value) {
13147
+ return availableValues.includes(value);
13148
+ });
13149
+ if (_this._config.debug && currentlySelected.length > 0) {
13150
+ console.log('update(): Preserving selections that exist in new data:', validSelections);
13151
+ }
13152
+ // Add new options from remote data and restore selection state
13083
13153
  items.forEach(function (item) {
13084
13154
  var option = document.createElement('option');
13085
13155
  option.value = item.id;
13086
13156
  option.textContent = item.title;
13087
13157
  if (item.disabled)
13088
13158
  option.disabled = true;
13159
+ // Restore selected attribute for preserved selections
13160
+ if (validSelections.includes(item.id)) {
13161
+ option.selected = true;
13162
+ }
13089
13163
  _this._element.appendChild(option);
13090
13164
  });
13091
13165
  // Rebuild dropdown
13092
13166
  _this._rebuildOptionsFromNative();
13167
+ // Sync selection state from native select (now has selected attributes)
13168
+ _this._syncSelectionFromNative();
13093
13169
  // Dispatch updated event
13094
13170
  _this._dispatchEvent('updated');
13095
13171
  _this._fireEvent('updated');
@@ -13136,19 +13212,38 @@ var KTSelect = /** @class */ (function (_super) {
13136
13212
  // Dispatch reload start event
13137
13213
  this._dispatchEvent('reloadStart');
13138
13214
  this._fireEvent('reloadStart');
13215
+ // Capture currently selected values before clearing
13216
+ var currentlySelected = this._state.getSelectedOptions();
13139
13217
  // Fetch fresh remote data
13140
13218
  return this._remoteModule
13141
13219
  .fetchData()
13142
13220
  .then(function (items) {
13143
- // Clear existing options
13221
+ // Clear existing options (captures to _preSelectedValues)
13144
13222
  _this._clearExistingOptions();
13145
13223
  // Update state with new items
13146
13224
  return _this._state.setItems(items).then(function () {
13147
13225
  // Generate new options HTML
13148
13226
  _this._generateOptionsHtml(_this._element);
13227
+ // Preserve selections by marking matching options as selected
13228
+ var availableValues = items.map(function (item) {
13229
+ return item.id !== undefined ? String(item.id) : '';
13230
+ });
13231
+ var validSelections = currentlySelected.filter(function (value) {
13232
+ return availableValues.includes(value);
13233
+ });
13234
+ if (_this._config.debug && currentlySelected.length > 0) {
13235
+ console.log('reload(): Preserving selections that exist in new data:', validSelections);
13236
+ }
13237
+ // Mark preserved selections on new options
13238
+ validSelections.forEach(function (value) {
13239
+ var option = Array.from(_this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
13240
+ if (option) {
13241
+ option.selected = true;
13242
+ }
13243
+ });
13149
13244
  // Update the dropdown
13150
13245
  _this._updateDropdownWithNewOptions();
13151
- // Sync selection state from native select
13246
+ // Sync selection state from native select (now has selected attributes)
13152
13247
  _this._syncSelectionFromNative();
13153
13248
  // Update visual display
13154
13249
  _this.updateSelectedOptionDisplay();
@@ -13173,8 +13268,17 @@ var KTSelect = /** @class */ (function (_super) {
13173
13268
  };
13174
13269
  /**
13175
13270
  * Refresh the visual display and state without rebuilding options
13176
- * For remote selects, refetches data from the server
13271
+ * For remote selects, refetches data from the server and preserves selections
13272
+ * that exist in the newly fetched data
13273
+ *
13177
13274
  * @public
13275
+ * @remarks
13276
+ * - For static selects: syncs visual state with native select
13277
+ * - For remote selects: fetches fresh data, preserves matching selections
13278
+ * - Selections are preserved if their values exist in new remote data
13279
+ * - Selections are cleared if their values don't exist in new data
13280
+ * @fires refreshed - After refresh completes successfully
13281
+ * @fires refreshError - If remote data fetch fails
13178
13282
  */
13179
13283
  KTSelect.prototype.refresh = function () {
13180
13284
  var _this = this;
@@ -13183,20 +13287,35 @@ var KTSelect = /** @class */ (function (_super) {
13183
13287
  this._remoteModule
13184
13288
  .fetchData()
13185
13289
  .then(function (items) {
13186
- // Clear existing options
13290
+ // Capture currently selected values before clearing
13291
+ var currentlySelected = _this._state.getSelectedOptions();
13292
+ // Clear existing options (also captures to _preSelectedValues)
13187
13293
  _this._clearExistingOptions();
13188
- // Add new options
13294
+ // Get all available values from new remote data
13295
+ var availableValues = items.map(function (item) { return item.id; });
13296
+ // Filter to only values that exist in new data
13297
+ var validSelections = currentlySelected.filter(function (value) {
13298
+ return availableValues.includes(value);
13299
+ });
13300
+ if (_this._config.debug && currentlySelected.length > 0) {
13301
+ console.log('refresh(): Preserving selections that exist in new data:', validSelections);
13302
+ }
13303
+ // Add new options and restore selection state
13189
13304
  items.forEach(function (item) {
13190
13305
  var option = document.createElement('option');
13191
13306
  option.value = item.id;
13192
13307
  option.textContent = item.title;
13193
13308
  if (item.disabled)
13194
13309
  option.disabled = true;
13310
+ // Restore selected attribute for preserved selections
13311
+ if (validSelections.includes(item.id)) {
13312
+ option.selected = true;
13313
+ }
13195
13314
  _this._element.appendChild(option);
13196
13315
  });
13197
13316
  // Rebuild dropdown
13198
13317
  _this._rebuildOptionsFromNative();
13199
- // Sync selection state
13318
+ // Sync selection state from native select (now has selected attributes)
13200
13319
  _this._syncSelectionFromNative();
13201
13320
  // Reapply ARIA attributes
13202
13321
  _this._setAriaAttributes();