@keenthemes/ktui 1.0.26 → 1.0.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/CONTRIBUTING.md +13 -0
- package/dist/ktui.js +149 -18
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/dist/styles.css +11 -13
- package/examples/modal/remote-select-dropdown.html +166 -0
- package/examples/modal/select-dropdown-container.html +129 -0
- package/examples/select/modal-positioning-test.html +10 -8
- package/lib/cjs/components/datatable/datatable.js +13 -1
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/modal/modal.js +13 -1
- package/lib/cjs/components/modal/modal.js.map +1 -1
- package/lib/cjs/components/select/dropdown.js +34 -6
- package/lib/cjs/components/select/dropdown.js.map +1 -1
- package/lib/cjs/components/select/select.js +89 -10
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/esm/components/datatable/datatable.js +13 -1
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/modal/modal.js +13 -1
- package/lib/esm/components/modal/modal.js.map +1 -1
- package/lib/esm/components/select/dropdown.js +34 -6
- package/lib/esm/components/select/dropdown.js.map +1 -1
- package/lib/esm/components/select/select.js +89 -10
- package/lib/esm/components/select/select.js.map +1 -1
- package/package.json +13 -5
- package/src/components/datatable/datatable.ts +13 -3
- package/src/components/modal/modal.ts +15 -1
- package/src/components/select/dropdown.ts +42 -6
- package/src/components/select/select.ts +123 -10
- package/src/components/table/table.css +7 -0
- package/webpack.config.js +1 -1
- package/lib/cjs/components/config.js +0 -26
- package/lib/cjs/components/config.js.map +0 -1
- package/lib/cjs/components/config.umd.js +0 -23
- package/lib/cjs/components/config.umd.js.map +0 -1
- package/lib/cjs/components/menu/index.js +0 -6
- package/lib/cjs/components/menu/index.js.map +0 -1
- package/lib/cjs/components/menu/menu.js +0 -1021
- package/lib/cjs/components/menu/menu.js.map +0 -1
- package/lib/cjs/components/menu/types.js +0 -3
- package/lib/cjs/components/menu/types.js.map +0 -1
- package/lib/cjs/components/theme/index.js +0 -6
- package/lib/cjs/components/theme/index.js.map +0 -1
- package/lib/cjs/components/theme/theme.js +0 -147
- package/lib/cjs/components/theme/theme.js.map +0 -1
- package/lib/cjs/components/theme/types.js +0 -3
- package/lib/cjs/components/theme/types.js.map +0 -1
- package/lib/esm/components/config.js +0 -24
- package/lib/esm/components/config.js.map +0 -1
- package/lib/esm/components/config.umd.js +0 -23
- package/lib/esm/components/config.umd.js.map +0 -1
- package/lib/esm/components/menu/index.js +0 -2
- package/lib/esm/components/menu/index.js.map +0 -1
- package/lib/esm/components/menu/menu.js +0 -1018
- package/lib/esm/components/menu/menu.js.map +0 -1
- package/lib/esm/components/menu/types.js +0 -2
- package/lib/esm/components/menu/types.js.map +0 -1
- package/lib/esm/components/theme/index.js +0 -2
- package/lib/esm/components/theme/index.js.map +0 -1
- package/lib/esm/components/theme/theme.js +0 -144
- package/lib/esm/components/theme/theme.js.map +0 -1
- package/lib/esm/components/theme/types.js +0 -2
- package/lib/esm/components/theme/types.js.map +0 -1
- /package/examples/modal/{persistent-test.html → persistent.html} +0 -0
- /package/examples/select/{dark-mode-test.html → dark-mode.html} +0 -0
- /package/examples/select/{dropdowncontainer-test.html → dropdowncontainer.html} +0 -0
- /package/examples/select/{formdata-remote-test.html → formdata-remote.html} +0 -0
- /package/examples/select/{global-config-test.html → global-config.html} +0 -0
package/CONTRIBUTING.md
CHANGED
|
@@ -31,6 +31,19 @@ If you need any help, feel free to reach out us via [@keenthemes](https://x.com/
|
|
|
31
31
|
```sh
|
|
32
32
|
npm run lint
|
|
33
33
|
```
|
|
34
|
+
4. Build the project:
|
|
35
|
+
```sh
|
|
36
|
+
npm run build
|
|
37
|
+
```
|
|
38
|
+
5. Start development mode (watch for changes):
|
|
39
|
+
```sh
|
|
40
|
+
npm run dev
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Build Commands
|
|
44
|
+
|
|
45
|
+
- **`npm run build`**: Performs a one-off build and exits. Use this for production builds and CI/CD pipelines.
|
|
46
|
+
- **`npm run dev`**: Starts development mode with file watching. Use this during development for live reloading when files change.
|
|
34
47
|
|
|
35
48
|
## Format and lint your code
|
|
36
49
|
|
package/dist/ktui.js
CHANGED
|
@@ -8343,7 +8343,19 @@ var KTDataTable = /** @class */ (function (_super) {
|
|
|
8343
8343
|
return [3 /*break*/, 5];
|
|
8344
8344
|
case 4:
|
|
8345
8345
|
error_1 = _a.sent();
|
|
8346
|
-
|
|
8346
|
+
// Fire event with complete error context for application handling
|
|
8347
|
+
this._fireEvent('parseError', {
|
|
8348
|
+
response: response,
|
|
8349
|
+
error: String(error_1),
|
|
8350
|
+
status: response.status,
|
|
8351
|
+
statusText: response.statusText
|
|
8352
|
+
});
|
|
8353
|
+
this._dispatchEvent('parseError', {
|
|
8354
|
+
response: response,
|
|
8355
|
+
error: String(error_1),
|
|
8356
|
+
status: response.status,
|
|
8357
|
+
statusText: response.statusText
|
|
8358
|
+
});
|
|
8347
8359
|
return [2 /*return*/];
|
|
8348
8360
|
case 5:
|
|
8349
8361
|
this._fireEvent('fetched', { response: responseData });
|
|
@@ -9252,8 +9264,20 @@ var KTModal = /** @class */ (function (_super) {
|
|
|
9252
9264
|
KTModal.prototype._handlers = function () {
|
|
9253
9265
|
var _this = this;
|
|
9254
9266
|
this._element.addEventListener('click', function (event) {
|
|
9255
|
-
|
|
9267
|
+
var target = event.target;
|
|
9268
|
+
var currentTarget = event.currentTarget;
|
|
9269
|
+
// Only proceed if clicking directly on the backdrop (modal element itself)
|
|
9270
|
+
// This prevents closing when clicking inside modal content or any child elements
|
|
9271
|
+
// (including dropdowns rendered via dropdownContainer pointing to modal)
|
|
9272
|
+
if (target !== currentTarget) {
|
|
9273
|
+
// Stop propagation for clicks inside dropdowns to prevent dropdown from closing
|
|
9274
|
+
// Check if click is inside a dropdown element (KT Select dropdown)
|
|
9275
|
+
var dropdownElement = target.closest('[data-kt-select-dropdown]');
|
|
9276
|
+
if (dropdownElement) {
|
|
9277
|
+
event.stopPropagation();
|
|
9278
|
+
}
|
|
9256
9279
|
return;
|
|
9280
|
+
}
|
|
9257
9281
|
// Only hide if both backdropStatic is false AND persistent is false
|
|
9258
9282
|
if (_this._getOption('backdropStatic') === false &&
|
|
9259
9283
|
utils_1.default.stringToBoolean(_this._getOption('persistent')) === false) {
|
|
@@ -9576,8 +9600,14 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9576
9600
|
_this._dropdownElement = dropdownElement;
|
|
9577
9601
|
_this._config = config;
|
|
9578
9602
|
_this._ktSelectInstance = ktSelectInstance; // Assign instance
|
|
9603
|
+
// For centered modals, don't move dropdown to container to preserve positioning context
|
|
9604
|
+
// For other cases, move to container if specified
|
|
9605
|
+
var modalParent = _this._getModalContainer();
|
|
9606
|
+
var isCenteredModal = modalParent && modalParent.classList.contains('kt-modal-center');
|
|
9607
|
+
// Only move dropdown if not in centered modal (regardless of strategy override)
|
|
9608
|
+
// This prevents the positioning bug even if user sets dropdownStrategy: 'fixed'
|
|
9579
9609
|
var container = _this._resolveDropdownContainer();
|
|
9580
|
-
if (container) {
|
|
9610
|
+
if (container && !isCenteredModal) {
|
|
9581
9611
|
if (container !== _this._dropdownElement.parentElement) {
|
|
9582
9612
|
container.appendChild(_this._dropdownElement);
|
|
9583
9613
|
}
|
|
@@ -9652,17 +9682,40 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9652
9682
|
KTSelectDropdown.prototype._getModalContainer = function () {
|
|
9653
9683
|
return this._element.closest('[data-kt-modal], .kt-modal, .kt-modal-center');
|
|
9654
9684
|
};
|
|
9685
|
+
/**
|
|
9686
|
+
* Get the appropriate boundary element for Popper positioning
|
|
9687
|
+
* For centered modals, use .kt-modal-content to avoid transform calculation issues
|
|
9688
|
+
* @returns The boundary element, or null if no modal found
|
|
9689
|
+
*/
|
|
9690
|
+
KTSelectDropdown.prototype._getModalBoundary = function () {
|
|
9691
|
+
var modalParent = this._getModalContainer();
|
|
9692
|
+
if (!modalParent) {
|
|
9693
|
+
return null;
|
|
9694
|
+
}
|
|
9695
|
+
// For centered modals, use .kt-modal-content as boundary to avoid transform issues
|
|
9696
|
+
if (modalParent.classList.contains('kt-modal-center')) {
|
|
9697
|
+
var modalContent = modalParent.querySelector('.kt-modal-content');
|
|
9698
|
+
return modalContent || modalParent;
|
|
9699
|
+
}
|
|
9700
|
+
// For non-centered modals, use the modal element itself
|
|
9701
|
+
return modalParent;
|
|
9702
|
+
};
|
|
9655
9703
|
/**
|
|
9656
9704
|
* Get the appropriate positioning strategy based on context
|
|
9657
|
-
* @returns 'fixed' if inside modal, 'absolute'
|
|
9705
|
+
* @returns 'fixed' if inside non-centered modal, 'absolute' for centered modals or no modal
|
|
9658
9706
|
*/
|
|
9659
9707
|
KTSelectDropdown.prototype._getPositioningStrategy = function () {
|
|
9660
9708
|
// Check if config explicitly sets strategy
|
|
9661
9709
|
if (this._config.dropdownStrategy) {
|
|
9662
9710
|
return this._config.dropdownStrategy;
|
|
9663
9711
|
}
|
|
9664
|
-
//
|
|
9712
|
+
// For centered modals, use absolute positioning to avoid transform calculation issues
|
|
9713
|
+
// For non-centered modals, use fixed positioning
|
|
9665
9714
|
var modalParent = this._getModalContainer();
|
|
9715
|
+
if (modalParent && modalParent.classList.contains('kt-modal-center')) {
|
|
9716
|
+
return 'absolute';
|
|
9717
|
+
}
|
|
9718
|
+
// Use fixed positioning for non-centered modals
|
|
9666
9719
|
return modalParent ? 'fixed' : 'absolute';
|
|
9667
9720
|
};
|
|
9668
9721
|
/**
|
|
@@ -9678,9 +9731,8 @@ var KTSelectDropdown = /** @class */ (function (_super) {
|
|
|
9678
9731
|
var strategy = this._getPositioningStrategy();
|
|
9679
9732
|
var preventOverflow = this._config.dropdownPreventOverflow !== false;
|
|
9680
9733
|
var flip = this._config.dropdownFlip !== false;
|
|
9681
|
-
//
|
|
9682
|
-
var
|
|
9683
|
-
var boundary = modalParent || 'clippingParents';
|
|
9734
|
+
// Get appropriate boundary element for modal context
|
|
9735
|
+
var boundary = this._getModalBoundary() || 'clippingParents';
|
|
9684
9736
|
// Create new popper instance
|
|
9685
9737
|
this._popperInstance = (0, core_1.createPopper)(this._toggleElement, this._dropdownElement, {
|
|
9686
9738
|
placement: placement,
|
|
@@ -11894,6 +11946,12 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
11894
11946
|
KTSelect.prototype._completeRemoteSetup = function () {
|
|
11895
11947
|
// Initialize options
|
|
11896
11948
|
this._preSelectOptions(this._element);
|
|
11949
|
+
// Prevent browser auto-selection when placeholder is configured
|
|
11950
|
+
if (this._config.placeholder &&
|
|
11951
|
+
this._state.getSelectedOptions().length === 0 &&
|
|
11952
|
+
this._preSelectedValues.length === 0) {
|
|
11953
|
+
this._element.value = '';
|
|
11954
|
+
}
|
|
11897
11955
|
// Apply pre-selected values captured before remote data was loaded
|
|
11898
11956
|
if (this._preSelectedValues.length > 0) {
|
|
11899
11957
|
if (this._config.debug) {
|
|
@@ -12136,6 +12194,11 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
12136
12194
|
this._setupElementReferences();
|
|
12137
12195
|
// Initialize options
|
|
12138
12196
|
this._preSelectOptions(this._element);
|
|
12197
|
+
// Prevent browser auto-selection when placeholder is configured
|
|
12198
|
+
if (this._config.placeholder &&
|
|
12199
|
+
this._state.getSelectedOptions().length === 0) {
|
|
12200
|
+
this._element.value = '';
|
|
12201
|
+
}
|
|
12139
12202
|
// Apply disabled state if needed
|
|
12140
12203
|
this._applyInitialDisabledState();
|
|
12141
12204
|
// Initialize search if enabled
|
|
@@ -13065,10 +13128,18 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
13065
13128
|
};
|
|
13066
13129
|
/**
|
|
13067
13130
|
* Update the dropdown to sync with native select element changes
|
|
13068
|
-
* For remote selects, refetches data from the server
|
|
13131
|
+
* For remote selects, refetches data from the server and preserves selections
|
|
13069
13132
|
* Optionally accepts new options to replace existing ones (static selects only)
|
|
13070
|
-
*
|
|
13133
|
+
*
|
|
13134
|
+
* @param newOptions Optional array of new options [{value, text}, ...] (static selects only)
|
|
13071
13135
|
* @public
|
|
13136
|
+
* @remarks
|
|
13137
|
+
* - For static selects: rebuilds dropdown from native select or new options
|
|
13138
|
+
* - For remote selects: fetches fresh data, preserves matching selections
|
|
13139
|
+
* - Selections are preserved if their values exist in new remote data
|
|
13140
|
+
* - Selections are cleared if their values don't exist in new data
|
|
13141
|
+
* @fires updated - After update completes successfully
|
|
13142
|
+
* @fires updateError - If remote data fetch fails
|
|
13072
13143
|
*/
|
|
13073
13144
|
KTSelect.prototype.update = function (newOptions) {
|
|
13074
13145
|
var _this = this;
|
|
@@ -13077,19 +13148,36 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
13077
13148
|
this._remoteModule
|
|
13078
13149
|
.fetchData()
|
|
13079
13150
|
.then(function (items) {
|
|
13080
|
-
//
|
|
13151
|
+
// Capture currently selected values before clearing
|
|
13152
|
+
var currentlySelected = _this._state.getSelectedOptions();
|
|
13153
|
+
// Clear existing options (also captures to _preSelectedValues)
|
|
13081
13154
|
_this._clearExistingOptions();
|
|
13082
|
-
//
|
|
13155
|
+
// Get all available values from new remote data
|
|
13156
|
+
var availableValues = items.map(function (item) { return item.id; });
|
|
13157
|
+
// Filter to only values that exist in new data
|
|
13158
|
+
var validSelections = currentlySelected.filter(function (value) {
|
|
13159
|
+
return availableValues.includes(value);
|
|
13160
|
+
});
|
|
13161
|
+
if (_this._config.debug && currentlySelected.length > 0) {
|
|
13162
|
+
console.log('update(): Preserving selections that exist in new data:', validSelections);
|
|
13163
|
+
}
|
|
13164
|
+
// Add new options from remote data and restore selection state
|
|
13083
13165
|
items.forEach(function (item) {
|
|
13084
13166
|
var option = document.createElement('option');
|
|
13085
13167
|
option.value = item.id;
|
|
13086
13168
|
option.textContent = item.title;
|
|
13087
13169
|
if (item.disabled)
|
|
13088
13170
|
option.disabled = true;
|
|
13171
|
+
// Restore selected attribute for preserved selections
|
|
13172
|
+
if (validSelections.includes(item.id)) {
|
|
13173
|
+
option.selected = true;
|
|
13174
|
+
}
|
|
13089
13175
|
_this._element.appendChild(option);
|
|
13090
13176
|
});
|
|
13091
13177
|
// Rebuild dropdown
|
|
13092
13178
|
_this._rebuildOptionsFromNative();
|
|
13179
|
+
// Sync selection state from native select (now has selected attributes)
|
|
13180
|
+
_this._syncSelectionFromNative();
|
|
13093
13181
|
// Dispatch updated event
|
|
13094
13182
|
_this._dispatchEvent('updated');
|
|
13095
13183
|
_this._fireEvent('updated');
|
|
@@ -13136,19 +13224,38 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
13136
13224
|
// Dispatch reload start event
|
|
13137
13225
|
this._dispatchEvent('reloadStart');
|
|
13138
13226
|
this._fireEvent('reloadStart');
|
|
13227
|
+
// Capture currently selected values before clearing
|
|
13228
|
+
var currentlySelected = this._state.getSelectedOptions();
|
|
13139
13229
|
// Fetch fresh remote data
|
|
13140
13230
|
return this._remoteModule
|
|
13141
13231
|
.fetchData()
|
|
13142
13232
|
.then(function (items) {
|
|
13143
|
-
// Clear existing options
|
|
13233
|
+
// Clear existing options (captures to _preSelectedValues)
|
|
13144
13234
|
_this._clearExistingOptions();
|
|
13145
13235
|
// Update state with new items
|
|
13146
13236
|
return _this._state.setItems(items).then(function () {
|
|
13147
13237
|
// Generate new options HTML
|
|
13148
13238
|
_this._generateOptionsHtml(_this._element);
|
|
13239
|
+
// Preserve selections by marking matching options as selected
|
|
13240
|
+
var availableValues = items.map(function (item) {
|
|
13241
|
+
return item.id !== undefined ? String(item.id) : '';
|
|
13242
|
+
});
|
|
13243
|
+
var validSelections = currentlySelected.filter(function (value) {
|
|
13244
|
+
return availableValues.includes(value);
|
|
13245
|
+
});
|
|
13246
|
+
if (_this._config.debug && currentlySelected.length > 0) {
|
|
13247
|
+
console.log('reload(): Preserving selections that exist in new data:', validSelections);
|
|
13248
|
+
}
|
|
13249
|
+
// Mark preserved selections on new options
|
|
13250
|
+
validSelections.forEach(function (value) {
|
|
13251
|
+
var option = Array.from(_this._element.querySelectorAll('option')).find(function (opt) { return opt.value === value; });
|
|
13252
|
+
if (option) {
|
|
13253
|
+
option.selected = true;
|
|
13254
|
+
}
|
|
13255
|
+
});
|
|
13149
13256
|
// Update the dropdown
|
|
13150
13257
|
_this._updateDropdownWithNewOptions();
|
|
13151
|
-
// Sync selection state from native select
|
|
13258
|
+
// Sync selection state from native select (now has selected attributes)
|
|
13152
13259
|
_this._syncSelectionFromNative();
|
|
13153
13260
|
// Update visual display
|
|
13154
13261
|
_this.updateSelectedOptionDisplay();
|
|
@@ -13173,8 +13280,17 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
13173
13280
|
};
|
|
13174
13281
|
/**
|
|
13175
13282
|
* Refresh the visual display and state without rebuilding options
|
|
13176
|
-
* For remote selects, refetches data from the server
|
|
13283
|
+
* For remote selects, refetches data from the server and preserves selections
|
|
13284
|
+
* that exist in the newly fetched data
|
|
13285
|
+
*
|
|
13177
13286
|
* @public
|
|
13287
|
+
* @remarks
|
|
13288
|
+
* - For static selects: syncs visual state with native select
|
|
13289
|
+
* - For remote selects: fetches fresh data, preserves matching selections
|
|
13290
|
+
* - Selections are preserved if their values exist in new remote data
|
|
13291
|
+
* - Selections are cleared if their values don't exist in new data
|
|
13292
|
+
* @fires refreshed - After refresh completes successfully
|
|
13293
|
+
* @fires refreshError - If remote data fetch fails
|
|
13178
13294
|
*/
|
|
13179
13295
|
KTSelect.prototype.refresh = function () {
|
|
13180
13296
|
var _this = this;
|
|
@@ -13183,20 +13299,35 @@ var KTSelect = /** @class */ (function (_super) {
|
|
|
13183
13299
|
this._remoteModule
|
|
13184
13300
|
.fetchData()
|
|
13185
13301
|
.then(function (items) {
|
|
13186
|
-
//
|
|
13302
|
+
// Capture currently selected values before clearing
|
|
13303
|
+
var currentlySelected = _this._state.getSelectedOptions();
|
|
13304
|
+
// Clear existing options (also captures to _preSelectedValues)
|
|
13187
13305
|
_this._clearExistingOptions();
|
|
13188
|
-
//
|
|
13306
|
+
// Get all available values from new remote data
|
|
13307
|
+
var availableValues = items.map(function (item) { return item.id; });
|
|
13308
|
+
// Filter to only values that exist in new data
|
|
13309
|
+
var validSelections = currentlySelected.filter(function (value) {
|
|
13310
|
+
return availableValues.includes(value);
|
|
13311
|
+
});
|
|
13312
|
+
if (_this._config.debug && currentlySelected.length > 0) {
|
|
13313
|
+
console.log('refresh(): Preserving selections that exist in new data:', validSelections);
|
|
13314
|
+
}
|
|
13315
|
+
// Add new options and restore selection state
|
|
13189
13316
|
items.forEach(function (item) {
|
|
13190
13317
|
var option = document.createElement('option');
|
|
13191
13318
|
option.value = item.id;
|
|
13192
13319
|
option.textContent = item.title;
|
|
13193
13320
|
if (item.disabled)
|
|
13194
13321
|
option.disabled = true;
|
|
13322
|
+
// Restore selected attribute for preserved selections
|
|
13323
|
+
if (validSelections.includes(item.id)) {
|
|
13324
|
+
option.selected = true;
|
|
13325
|
+
}
|
|
13195
13326
|
_this._element.appendChild(option);
|
|
13196
13327
|
});
|
|
13197
13328
|
// Rebuild dropdown
|
|
13198
13329
|
_this._rebuildOptionsFromNative();
|
|
13199
|
-
// Sync selection state
|
|
13330
|
+
// Sync selection state from native select (now has selected attributes)
|
|
13200
13331
|
_this._syncSelectionFromNative();
|
|
13201
13332
|
// Reapply ARIA attributes
|
|
13202
13333
|
_this._setAriaAttributes();
|