@keenthemes/ktui 1.0.10 → 1.0.12
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/README.md +2 -2
- package/dist/ktui.js +1283 -1100
- package/dist/ktui.min.js +1 -1
- package/dist/ktui.min.js.map +1 -1
- package/examples/select/basic-usage.html +43 -0
- package/examples/select/combobox-icons.html +58 -0
- package/examples/select/combobox.html +46 -0
- package/examples/select/description.html +69 -0
- package/examples/select/disable-option.html +43 -0
- package/examples/select/disable-select.html +34 -0
- package/examples/select/icon-description.html +56 -0
- package/examples/select/icon-multiple.html +58 -0
- package/examples/select/icon.html +58 -0
- package/examples/select/max-selection.html +39 -0
- package/examples/select/modal.html +70 -0
- package/examples/select/multiple.html +42 -0
- package/examples/select/placeholder.html +43 -0
- package/examples/select/remote-data.html +32 -0
- package/examples/select/search.html +49 -0
- package/examples/select/tags-icons.html +58 -0
- package/examples/select/tags-selected.html +59 -0
- package/examples/select/tags.html +58 -0
- package/examples/select/template-customization.html +65 -0
- package/examples/select/test.html +94 -0
- package/examples/toast/example.html +427 -0
- package/lib/cjs/components/component.js +1 -1
- package/lib/cjs/components/component.js.map +1 -1
- package/lib/cjs/components/datatable/datatable.js +22 -6
- package/lib/cjs/components/datatable/datatable.js.map +1 -1
- package/lib/cjs/components/modal/modal.js +0 -4
- package/lib/cjs/components/modal/modal.js.map +1 -1
- package/lib/cjs/components/select/combobox.js +38 -120
- package/lib/cjs/components/select/combobox.js.map +1 -1
- package/lib/cjs/components/select/config.js +4 -16
- package/lib/cjs/components/select/config.js.map +1 -1
- package/lib/cjs/components/select/dropdown.js +10 -49
- package/lib/cjs/components/select/dropdown.js.map +1 -1
- package/lib/cjs/components/select/index.js +2 -1
- package/lib/cjs/components/select/index.js.map +1 -1
- package/lib/cjs/components/select/option.js +21 -4
- package/lib/cjs/components/select/option.js.map +1 -1
- package/lib/cjs/components/select/remote.js +1 -37
- package/lib/cjs/components/select/remote.js.map +1 -1
- package/lib/cjs/components/select/search.js +11 -41
- package/lib/cjs/components/select/search.js.map +1 -1
- package/lib/cjs/components/select/select.js +213 -326
- package/lib/cjs/components/select/select.js.map +1 -1
- package/lib/cjs/components/select/tags.js +39 -31
- package/lib/cjs/components/select/tags.js.map +1 -1
- package/lib/cjs/components/select/templates.js +120 -179
- package/lib/cjs/components/select/templates.js.map +1 -1
- package/lib/cjs/components/select/types.js +0 -12
- package/lib/cjs/components/select/types.js.map +1 -1
- package/lib/cjs/components/select/utils.js +204 -257
- package/lib/cjs/components/select/utils.js.map +1 -1
- package/lib/cjs/components/toast/index.js +10 -0
- package/lib/cjs/components/toast/index.js.map +1 -0
- package/lib/cjs/components/toast/toast.js +543 -0
- package/lib/cjs/components/toast/toast.js.map +1 -0
- package/lib/cjs/components/toast/types.js +7 -0
- package/lib/cjs/components/toast/types.js.map +1 -0
- package/lib/cjs/helpers/dom.js +24 -0
- package/lib/cjs/helpers/dom.js.map +1 -1
- package/lib/cjs/index.js +5 -1
- package/lib/cjs/index.js.map +1 -1
- package/lib/esm/components/component.js +1 -1
- package/lib/esm/components/component.js.map +1 -1
- package/lib/esm/components/datatable/datatable.js +22 -6
- package/lib/esm/components/datatable/datatable.js.map +1 -1
- package/lib/esm/components/modal/modal.js +0 -4
- package/lib/esm/components/modal/modal.js.map +1 -1
- package/lib/esm/components/select/combobox.js +39 -121
- package/lib/esm/components/select/combobox.js.map +1 -1
- package/lib/esm/components/select/config.js +3 -15
- package/lib/esm/components/select/config.js.map +1 -1
- package/lib/esm/components/select/dropdown.js +10 -49
- package/lib/esm/components/select/dropdown.js.map +1 -1
- package/lib/esm/components/select/index.js +1 -1
- package/lib/esm/components/select/index.js.map +1 -1
- package/lib/esm/components/select/option.js +21 -4
- package/lib/esm/components/select/option.js.map +1 -1
- package/lib/esm/components/select/remote.js +1 -37
- package/lib/esm/components/select/remote.js.map +1 -1
- package/lib/esm/components/select/search.js +12 -42
- package/lib/esm/components/select/search.js.map +1 -1
- package/lib/esm/components/select/select.js +214 -327
- package/lib/esm/components/select/select.js.map +1 -1
- package/lib/esm/components/select/tags.js +39 -31
- package/lib/esm/components/select/tags.js.map +1 -1
- package/lib/esm/components/select/templates.js +119 -178
- package/lib/esm/components/select/templates.js.map +1 -1
- package/lib/esm/components/select/types.js +1 -11
- package/lib/esm/components/select/types.js.map +1 -1
- package/lib/esm/components/select/utils.js +201 -255
- package/lib/esm/components/select/utils.js.map +1 -1
- package/lib/esm/components/toast/index.js +6 -0
- package/lib/esm/components/toast/index.js.map +1 -0
- package/lib/esm/components/toast/toast.js +540 -0
- package/lib/esm/components/toast/toast.js.map +1 -0
- package/lib/esm/components/toast/types.js +6 -0
- package/lib/esm/components/toast/types.js.map +1 -0
- package/lib/esm/helpers/dom.js +24 -0
- package/lib/esm/helpers/dom.js.map +1 -1
- package/lib/esm/index.js +3 -0
- package/lib/esm/index.js.map +1 -1
- package/package.json +8 -6
- package/src/components/alert/alert.css +20 -2
- package/src/components/badge/badge.css +5 -0
- package/src/components/component.ts +4 -0
- package/src/components/datatable/datatable.ts +24 -16
- package/src/components/drawer/drawer.css +1 -1
- package/src/components/input/input.css +3 -1
- package/src/components/link/link.css +2 -2
- package/src/components/modal/modal.css +18 -2
- package/src/components/modal/modal.ts +0 -5
- package/src/components/select/combobox.ts +42 -149
- package/src/components/select/config.ts +38 -33
- package/src/components/select/dropdown.ts +8 -55
- package/src/components/select/index.ts +1 -1
- package/src/components/select/option.ts +28 -7
- package/src/components/select/remote.ts +2 -42
- package/src/components/select/search.ts +14 -54
- package/src/components/select/select.css +49 -0
- package/src/components/select/select.ts +231 -437
- package/src/components/select/tags.ts +40 -37
- package/src/components/select/templates.ts +166 -303
- package/src/components/select/types.ts +0 -10
- package/src/components/select/utils.ts +214 -304
- package/src/components/table/table.css +1 -1
- package/src/components/textarea/textarea.css +2 -1
- package/src/components/toast/index.ts +7 -0
- package/src/components/toast/toast.css +60 -0
- package/src/components/toast/toast.ts +605 -0
- package/src/components/toast/types.ts +169 -0
- package/src/helpers/dom.ts +30 -0
- package/src/index.ts +4 -0
- package/styles/main.css +3 -0
- package/styles/vars.css +138 -0
- package/styles.css +1 -0
|
@@ -4,57 +4,44 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { KTSelectConfigInterface, KTSelectOption } from './config';
|
|
7
|
-
import {
|
|
7
|
+
import { renderTemplateString } from './utils';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Default HTML string templates for KTSelect. All UI structure is defined here.
|
|
11
11
|
* Users can override any template by providing a matching key in the config.templates object.
|
|
12
12
|
*/
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
</
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<span data-kt-select-arrow class="ml-2">
|
|
46
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
47
|
-
<polyline points="6 9 12 15 18 9"></polyline>
|
|
48
|
-
</svg>
|
|
49
|
-
</span>
|
|
50
|
-
</div>`,
|
|
51
|
-
option: `<li data-kt-select-option data-value="{{value}}" class="px-3 py-2 cursor-pointer hover:bg-gray-100 flex items-center{{selectedClass}}{{disabledClass}}" role="option" {{selected}} {{disabled}}>{{icon}}<div class="option-content"><div class="option-title" data-kt-option-title>{{text}}</div>{{description}}</div></li>`,
|
|
52
|
-
|
|
53
|
-
optionGroup: `<li role="group" aria-label="{{label}}" class="py-1"><div class="px-3 py-1 text-xs font-semibold text-gray-500 uppercase">{{label}}</div><ul>{{optionsHtml}}</ul></li>`,
|
|
54
|
-
search: `<div class="px-3 py-2 border-b border-gray-200"><input type="text" data-kt-select-search placeholder="{{searchPlaceholder}}" class="w-full border-none focus:outline-none text-sm" role="searchbox" aria-label="{{searchPlaceholder}}"/></div>`,
|
|
55
|
-
noResults: `<li class="px-3 py-2 text-gray-500" role="status">{{searchNotFoundText}}</li>`,
|
|
56
|
-
loading: `<li class="px-3 py-2 text-gray-500 italic" role="status" aria-live="polite">{{loadingMessage}}</li>`,
|
|
57
|
-
tag: `<div data-kt-select-tag class="inline-flex items-center bg-blue-50 border border-blue-100 rounded px-2 py-1 text-sm mr-1 mb-1"><span>{{title}}</span><span data-kt-select-remove-button data-value="{{id}}" class="ml-1 text-blue-400 hover:text-blue-600 cursor-pointer" role="button" aria-label="Remove {{safeTitle}}" tabindex="0"><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg></span></div>`,
|
|
13
|
+
export const coreTemplateStrings = {
|
|
14
|
+
dropdown: `<div data-kt-select-dropdown class="kt-select-dropdown hidden {{class}}" style="z-index: {{zindex}};">{{content}}</div>`,
|
|
15
|
+
options: `<ul role="listbox" aria-label="{{label}}" class="kt-select-options {{class}}" data-kt-select-options="true">{{content}}</ul>`,
|
|
16
|
+
error: `<li class="kt-select-error" role="alert">{{content}}</li>`,
|
|
17
|
+
highlight: `<span data-kt-select-highlight class="kt-select-highlight highlighted {{class}}">{{text}}</span>`,
|
|
18
|
+
wrapper: `<div data-kt-select-wrapper class="kt-select-wrapper {{class}}"></div>`,
|
|
19
|
+
combobox: `
|
|
20
|
+
<div data-kt-select-combobox data-kt-select-display class="kt-select-combobox {{class}}">
|
|
21
|
+
<input class="kt-input kt-select-combobox-input" data-kt-select-search="true" data-kt-select-value="true" type="text" placeholder="{{placeholder}}" role="searchbox" aria-label="{{label}}" {{disabled}} />
|
|
22
|
+
<button type="button" data-kt-select-clear-button="true" class="kt-select-combobox-clear-btn" aria-label="Clear selection">
|
|
23
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
24
|
+
<line x1="18" y1="6" x2="6" y2="18"></line>
|
|
25
|
+
<line x1="6" y1="6" x2="18" y2="18"></line>
|
|
26
|
+
</svg>
|
|
27
|
+
</button>
|
|
28
|
+
</div>
|
|
29
|
+
`,
|
|
30
|
+
display: `
|
|
31
|
+
<div data-kt-select-display class="kt-select-display {{class}}" tabindex="{{tabindex}}" role="button" data-selected="0" aria-haspopup="listbox" aria-expanded="false" aria-label="{{label}}" {{disabled}}>
|
|
32
|
+
<div data-kt-select-value="true" class="kt-select-label">{{content}}</div>
|
|
33
|
+
</div>
|
|
34
|
+
`,
|
|
35
|
+
placeholder: `<div data-kt-select-placeholder class="kt-select-placeholder {{class}}">{{content}}</div>`,
|
|
36
|
+
option: `<li data-kt-select-option data-value="{{value}}" data-text="{{text}}" class="kt-select-option {{class}}" role="option" {{selected}} {{disabled}}>{{content}}</li>`,
|
|
37
|
+
search: `<div data-kt-select-search class="kt-select-search {{class}}"><input type="text" data-kt-select-search="true" placeholder="{{searchPlaceholder}}" class="kt-input kt-select-search-input" role="searchbox" aria-label="{{searchPlaceholder}}"/></div>`,
|
|
38
|
+
empty: `<li data-kt-select-empty class="kt-select-no-result {{class}}" role="status">{{content}}</li>`,
|
|
39
|
+
loading: `<li class="kt-select-loading {{class}}" role="status" aria-live="polite">{{content}}</li>`,
|
|
40
|
+
tag: `<div data-kt-select-tag="true" class="kt-select-tag {{class}}">
|
|
41
|
+
{{content}}
|
|
42
|
+
</div>`,
|
|
43
|
+
loadMore: `<li class="kt-select-load-more {{class}}" data-kt-select-load-more="true">{{content}}</li>`,
|
|
44
|
+
tagRemoveButton: `<button type="button" data-kt-select-remove-button class="kt-select-tag-remove" aria-label="Remove tag" tabindex="0"><svg width="12" height="12" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="2"><line x1="3" y1="3" x2="9" y2="9"/><line x1="9" y1="3" x2="3" y2="9"/></svg></button>`,
|
|
58
45
|
};
|
|
59
46
|
|
|
60
47
|
/**
|
|
@@ -65,27 +52,15 @@ export interface KTSelectTemplateInterface {
|
|
|
65
52
|
/**
|
|
66
53
|
* Renders the dropdown content container
|
|
67
54
|
*/
|
|
68
|
-
|
|
55
|
+
dropdown: (
|
|
69
56
|
config: KTSelectConfigInterface & { zindex?: number; content?: string },
|
|
70
57
|
) => HTMLElement;
|
|
71
58
|
/**
|
|
72
59
|
* Renders the options container
|
|
73
60
|
*/
|
|
74
|
-
|
|
61
|
+
options: (
|
|
75
62
|
config: KTSelectConfigInterface & { options?: string },
|
|
76
63
|
) => HTMLElement;
|
|
77
|
-
/**
|
|
78
|
-
* Renders an empty <option> for native select
|
|
79
|
-
*/
|
|
80
|
-
emptyOption: (
|
|
81
|
-
config: KTSelectConfigInterface & { placeholder?: string },
|
|
82
|
-
) => HTMLOptionElement;
|
|
83
|
-
/**
|
|
84
|
-
* Renders an error <option> for the native select
|
|
85
|
-
*/
|
|
86
|
-
errorOption: (
|
|
87
|
-
config: KTSelectConfigInterface & { errorMessage: string },
|
|
88
|
-
) => HTMLElement;
|
|
89
64
|
/**
|
|
90
65
|
* Renders the load more button for pagination
|
|
91
66
|
*/
|
|
@@ -98,45 +73,27 @@ export interface KTSelectTemplateInterface {
|
|
|
98
73
|
highlight: (config: KTSelectConfigInterface, text: string) => HTMLElement;
|
|
99
74
|
|
|
100
75
|
// Main components
|
|
101
|
-
|
|
76
|
+
wrapper: (config: KTSelectConfigInterface) => HTMLElement;
|
|
102
77
|
display: (config: KTSelectConfigInterface) => HTMLElement;
|
|
103
|
-
dropdown: (
|
|
104
|
-
config: KTSelectConfigInterface,
|
|
105
|
-
optionsHtml: string,
|
|
106
|
-
) => HTMLElement;
|
|
107
|
-
|
|
108
|
-
// Icon rendering
|
|
109
|
-
icon: (icon: string, config: KTSelectConfigInterface) => HTMLElement;
|
|
110
|
-
description: (
|
|
111
|
-
description: string,
|
|
112
|
-
config: KTSelectConfigInterface,
|
|
113
|
-
) => HTMLElement;
|
|
114
78
|
|
|
115
79
|
// Option rendering
|
|
116
80
|
option: (
|
|
117
81
|
option: KTSelectOption | HTMLOptionElement,
|
|
118
82
|
config: KTSelectConfigInterface,
|
|
119
83
|
) => HTMLElement;
|
|
120
|
-
optionGroup: (
|
|
121
|
-
label: string,
|
|
122
|
-
optionsHtml: string,
|
|
123
|
-
config: KTSelectConfigInterface,
|
|
124
|
-
) => HTMLElement;
|
|
125
84
|
|
|
126
85
|
// Search and empty states
|
|
127
86
|
search: (config: KTSelectConfigInterface) => HTMLElement;
|
|
128
|
-
|
|
87
|
+
empty: (config: KTSelectConfigInterface) => HTMLElement;
|
|
129
88
|
loading: (
|
|
130
89
|
config: KTSelectConfigInterface,
|
|
131
90
|
loadingMessage: string,
|
|
132
91
|
) => HTMLElement;
|
|
133
92
|
|
|
134
93
|
// Multi-select
|
|
135
|
-
tag: (option:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
config: KTSelectConfigInterface,
|
|
139
|
-
) => string;
|
|
94
|
+
tag: (option: HTMLOptionElement, config: KTSelectConfigInterface) => HTMLElement;
|
|
95
|
+
|
|
96
|
+
placeholder: (config: KTSelectConfigInterface) => HTMLElement;
|
|
140
97
|
}
|
|
141
98
|
|
|
142
99
|
/**
|
|
@@ -151,14 +108,14 @@ function stringToElement(html: string): HTMLElement {
|
|
|
151
108
|
/**
|
|
152
109
|
* User-supplied template overrides. Use setTemplateStrings() to add or update.
|
|
153
110
|
*/
|
|
154
|
-
let userTemplateStrings: Partial<typeof
|
|
111
|
+
let userTemplateStrings: Partial<typeof coreTemplateStrings> = {};
|
|
155
112
|
|
|
156
113
|
/**
|
|
157
114
|
* Register or update user template overrides.
|
|
158
115
|
* @param templates Partial template object to merge with defaults.
|
|
159
116
|
*/
|
|
160
117
|
export function setTemplateStrings(
|
|
161
|
-
templates: Partial<typeof
|
|
118
|
+
templates: Partial<typeof coreTemplateStrings>,
|
|
162
119
|
): void {
|
|
163
120
|
userTemplateStrings = { ...userTemplateStrings, ...templates };
|
|
164
121
|
}
|
|
@@ -169,15 +126,17 @@ export function setTemplateStrings(
|
|
|
169
126
|
*/
|
|
170
127
|
export function getTemplateStrings(
|
|
171
128
|
config?: KTSelectConfigInterface,
|
|
172
|
-
): typeof
|
|
129
|
+
): typeof coreTemplateStrings {
|
|
173
130
|
const templates =
|
|
174
131
|
config && typeof config === 'object' && 'templates' in config
|
|
175
132
|
? (config as any).templates
|
|
176
133
|
: undefined;
|
|
134
|
+
|
|
177
135
|
if (templates) {
|
|
178
|
-
return { ...
|
|
136
|
+
return { ...coreTemplateStrings, ...userTemplateStrings, ...templates };
|
|
179
137
|
}
|
|
180
|
-
|
|
138
|
+
|
|
139
|
+
return { ...coreTemplateStrings, ...userTemplateStrings };
|
|
181
140
|
}
|
|
182
141
|
|
|
183
142
|
/**
|
|
@@ -189,58 +148,42 @@ export const defaultTemplates: KTSelectTemplateInterface = {
|
|
|
189
148
|
*/
|
|
190
149
|
highlight: (config: KTSelectConfigInterface, text: string) => {
|
|
191
150
|
const template = getTemplateStrings(config).highlight;
|
|
192
|
-
const html = template.replace('{{text}}', text);
|
|
151
|
+
const html = template.replace('{{text}}', text).replace('{{class}}', config.highlightClass || '');
|
|
193
152
|
return stringToElement(html);
|
|
194
153
|
},
|
|
195
154
|
|
|
196
155
|
/**
|
|
197
156
|
* Renders the dropdown content
|
|
198
157
|
*/
|
|
199
|
-
|
|
158
|
+
dropdown: (
|
|
200
159
|
config: KTSelectConfigInterface & { zindex?: number; content?: string },
|
|
201
160
|
) => {
|
|
202
|
-
|
|
161
|
+
let template = getTemplateStrings(config).dropdown;
|
|
162
|
+
let content = config.content || '';
|
|
163
|
+
if (config.dropdownTemplate) {
|
|
164
|
+
content = renderTemplateString(config.dropdownTemplate, {
|
|
165
|
+
zindex: config.zindex ? String(config.zindex) : '',
|
|
166
|
+
content: config.content || '',
|
|
167
|
+
class: config.dropdownClass || '',
|
|
168
|
+
});
|
|
169
|
+
}
|
|
203
170
|
const html = template
|
|
204
171
|
.replace('{{zindex}}', config.zindex ? String(config.zindex) : '')
|
|
205
|
-
.replace('{{content}}',
|
|
172
|
+
.replace('{{content}}', content)
|
|
173
|
+
.replace('{{class}}', config.dropdownClass || '');
|
|
206
174
|
return stringToElement(html);
|
|
207
175
|
},
|
|
208
176
|
|
|
209
177
|
/**
|
|
210
178
|
* Renders the options container for the dropdown
|
|
211
179
|
*/
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
) => {
|
|
215
|
-
const template = getTemplateStrings(config).optionsContainer;
|
|
180
|
+
options: (config: KTSelectConfigInterface & { options?: string }) => {
|
|
181
|
+
const template = getTemplateStrings(config).options;
|
|
216
182
|
const html = template
|
|
217
183
|
.replace('{{label}}', config.label || 'Options')
|
|
218
184
|
.replace('{{height}}', config.height ? String(config.height) : '250')
|
|
219
|
-
.replace('{{options}}', config.options || '')
|
|
220
|
-
|
|
221
|
-
},
|
|
222
|
-
|
|
223
|
-
/**
|
|
224
|
-
* Renders an empty option in the dropdown
|
|
225
|
-
*/
|
|
226
|
-
emptyOption: (config: KTSelectConfigInterface & { placeholder?: string }) => {
|
|
227
|
-
const template = getTemplateStrings(config).emptyOption;
|
|
228
|
-
const html = template.replace(
|
|
229
|
-
'{{placeholder}}',
|
|
230
|
-
config.placeholder || 'Select...',
|
|
231
|
-
);
|
|
232
|
-
return stringToElement(html) as HTMLOptionElement;
|
|
233
|
-
},
|
|
234
|
-
|
|
235
|
-
/**
|
|
236
|
-
* Renders an error option in the dropdown
|
|
237
|
-
*/
|
|
238
|
-
errorOption: (config: KTSelectConfigInterface & { errorMessage: string }) => {
|
|
239
|
-
const template = getTemplateStrings(config).errorOption;
|
|
240
|
-
const html = template.replace(
|
|
241
|
-
'{{errorMessage}}',
|
|
242
|
-
config.errorMessage || 'An error occurred',
|
|
243
|
-
);
|
|
185
|
+
.replace('{{options}}', config.options || '')
|
|
186
|
+
.replace('{{class}}', config.optionsClass || '');
|
|
244
187
|
return stringToElement(html);
|
|
245
188
|
},
|
|
246
189
|
|
|
@@ -261,68 +204,47 @@ export const defaultTemplates: KTSelectTemplateInterface = {
|
|
|
261
204
|
config: KTSelectConfigInterface & { errorMessage: string },
|
|
262
205
|
): string => {
|
|
263
206
|
const template = getTemplateStrings(config).error;
|
|
264
|
-
return template
|
|
265
|
-
'{{errorMessage}}',
|
|
266
|
-
config.
|
|
267
|
-
);
|
|
207
|
+
return template
|
|
208
|
+
.replace('{{errorMessage}}', config.errorMessage || 'An error occurred')
|
|
209
|
+
.replace('{{class}}', config.errorClass || '');
|
|
268
210
|
},
|
|
269
211
|
/**
|
|
270
212
|
* Renders the main container for the select component
|
|
271
213
|
*/
|
|
272
|
-
|
|
273
|
-
const html = getTemplateStrings(config).
|
|
274
|
-
'{{
|
|
275
|
-
|
|
276
|
-
);
|
|
277
|
-
|
|
214
|
+
wrapper: (config: KTSelectConfigInterface): HTMLElement => {
|
|
215
|
+
const html = getTemplateStrings(config).wrapper
|
|
216
|
+
.replace('{{class}}', config.wrapperClass || '');
|
|
217
|
+
const element = stringToElement(html);
|
|
218
|
+
element.setAttribute('data-kt-select-combobox', config.combobox ? 'true' : 'false');
|
|
219
|
+
element.setAttribute('data-kt-select-tags', config.tags ? 'true' : 'false');
|
|
220
|
+
return element;
|
|
278
221
|
},
|
|
279
222
|
|
|
280
223
|
/**
|
|
281
224
|
* Renders the display element (trigger) for the select
|
|
282
225
|
*/
|
|
283
226
|
display: (config: KTSelectConfigInterface): HTMLElement => {
|
|
284
|
-
|
|
285
|
-
if (isCombobox) {
|
|
227
|
+
if (config.combobox) {
|
|
286
228
|
let html = getTemplateStrings(config)
|
|
287
|
-
.
|
|
288
|
-
/{{placeholder}}/g,
|
|
289
|
-
config.placeholder || 'Select...',
|
|
290
|
-
)
|
|
229
|
+
.combobox.replace(/{{placeholder}}/g, config.placeholder || 'Select...')
|
|
291
230
|
.replace(
|
|
292
231
|
/{{label}}/g,
|
|
293
232
|
config.label || config.placeholder || 'Select...',
|
|
294
233
|
)
|
|
295
|
-
.replace('{{disabled}}', config.disabled ? 'disabled' : '')
|
|
234
|
+
.replace('{{disabled}}', config.disabled ? 'disabled' : '')
|
|
235
|
+
.replace('{{class}}', config.displayClass || '');
|
|
296
236
|
return stringToElement(html);
|
|
297
237
|
}
|
|
298
|
-
|
|
299
|
-
|
|
238
|
+
|
|
239
|
+
let content = config.label || config.placeholder || 'Select...';
|
|
240
|
+
|
|
241
|
+
let html = getTemplateStrings(config).display
|
|
242
|
+
.replace('{{tabindex}}', config.disabled ? '-1' : '0')
|
|
300
243
|
.replace('{{label}}', config.label || config.placeholder || 'Select...')
|
|
301
244
|
.replace('{{disabled}}', config.disabled ? 'aria-disabled="true"' : '')
|
|
302
|
-
.replace('{{placeholder}}', config.placeholder || 'Select...')
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
/**
|
|
307
|
-
* Renders the dropdown content container
|
|
308
|
-
*/
|
|
309
|
-
dropdown: (
|
|
310
|
-
config: KTSelectConfigInterface,
|
|
311
|
-
optionsHtml: string,
|
|
312
|
-
): HTMLElement => {
|
|
313
|
-
const isCombobox = config.mode === SelectMode.COMBOBOX;
|
|
314
|
-
const hasSearch = config.enableSearch && !isCombobox;
|
|
315
|
-
const template = getTemplateStrings(config).dropdown;
|
|
316
|
-
let searchHtml = '';
|
|
317
|
-
if (hasSearch) {
|
|
318
|
-
const searchElement = defaultTemplates.search(config);
|
|
319
|
-
searchHtml = searchElement.outerHTML;
|
|
320
|
-
}
|
|
321
|
-
const html = template
|
|
322
|
-
.replace('{{search}}', searchHtml)
|
|
323
|
-
.replace('{{options}}', optionsHtml)
|
|
324
|
-
.replace('{{label}}', config.label || 'Options')
|
|
325
|
-
.replace('{{height}}', config.height ? String(config.height) : '250');
|
|
245
|
+
.replace('{{placeholder}}', config.placeholder || 'Select...')
|
|
246
|
+
.replace('{{class}}', config.displayClass || '')
|
|
247
|
+
.replace('{{content}}', content);
|
|
326
248
|
return stringToElement(html);
|
|
327
249
|
},
|
|
328
250
|
|
|
@@ -331,7 +253,7 @@ export const defaultTemplates: KTSelectTemplateInterface = {
|
|
|
331
253
|
*/
|
|
332
254
|
option: (
|
|
333
255
|
option: KTSelectOption | HTMLOptionElement,
|
|
334
|
-
config: KTSelectConfigInterface
|
|
256
|
+
config: KTSelectConfigInterface,
|
|
335
257
|
): HTMLElement => {
|
|
336
258
|
const isHtmlOption = option instanceof HTMLOptionElement;
|
|
337
259
|
|
|
@@ -344,92 +266,26 @@ export const defaultTemplates: KTSelectTemplateInterface = {
|
|
|
344
266
|
? option.selected
|
|
345
267
|
: !!(option as KTSelectOption).selected;
|
|
346
268
|
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
// fallback to legacy attributes if JSON is invalid
|
|
359
|
-
description =
|
|
360
|
-
option.getAttribute('data-kt-select-option-description') ||
|
|
361
|
-
undefined;
|
|
362
|
-
icon = option.getAttribute('data-kt-select-option-icon') || undefined;
|
|
363
|
-
}
|
|
364
|
-
} else {
|
|
365
|
-
description =
|
|
366
|
-
option.getAttribute('data-kt-select-option-description') || undefined;
|
|
367
|
-
icon = option.getAttribute('data-kt-select-option-icon') || undefined;
|
|
368
|
-
}
|
|
369
|
-
} else {
|
|
370
|
-
description = (option as KTSelectOption).description;
|
|
371
|
-
icon = (option as KTSelectOption).icon;
|
|
269
|
+
let content = text;
|
|
270
|
+
if (config.optionTemplate) {
|
|
271
|
+
// Use the user template to render the content, but only for {{content}}
|
|
272
|
+
content = renderTemplateString(config.optionTemplate, {
|
|
273
|
+
value,
|
|
274
|
+
text,
|
|
275
|
+
class: config.optionClass || '',
|
|
276
|
+
selected: selected ? 'aria-selected="true"' : 'aria-selected="false"',
|
|
277
|
+
disabled: disabled ? 'aria-disabled="true"' : '',
|
|
278
|
+
content: text,
|
|
279
|
+
});
|
|
372
280
|
}
|
|
373
281
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
const disabledClass = disabled ? ' disabled' : '';
|
|
377
|
-
let html = getTemplateStrings(config)
|
|
378
|
-
.option.replace('{{value}}', value)
|
|
379
|
-
.replace('{{selectedClass}}', selectedClass)
|
|
380
|
-
.replace('{{disabledClass}}', disabledClass)
|
|
381
|
-
.replace(
|
|
382
|
-
'{{selected}}',
|
|
383
|
-
selected ? 'aria-selected="true"' : 'aria-selected="false"',
|
|
384
|
-
)
|
|
385
|
-
.replace('{{disabled}}', disabled ? 'aria-disabled="true"' : '')
|
|
386
|
-
.replace(
|
|
387
|
-
/{{icon}}/g,
|
|
388
|
-
icon ? defaultTemplates.icon(icon, config).outerHTML : '',
|
|
389
|
-
)
|
|
282
|
+
const html = getTemplateStrings(config).option
|
|
283
|
+
.replace('{{value}}', value)
|
|
390
284
|
.replace('{{text}}', text)
|
|
391
|
-
.replace(
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
: '',
|
|
396
|
-
);
|
|
397
|
-
return stringToElement(html);
|
|
398
|
-
},
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Renders an icon
|
|
402
|
-
*/
|
|
403
|
-
icon: (icon: string, config: KTSelectConfigInterface): HTMLElement => {
|
|
404
|
-
const html = getTemplateStrings(config).icon.replace('{{icon}}', icon);
|
|
405
|
-
return stringToElement(html);
|
|
406
|
-
},
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Renders a description
|
|
410
|
-
*/
|
|
411
|
-
description: (
|
|
412
|
-
description: string,
|
|
413
|
-
config: KTSelectConfigInterface,
|
|
414
|
-
): HTMLElement => {
|
|
415
|
-
const html = getTemplateStrings(config).description.replace(
|
|
416
|
-
'{{description}}',
|
|
417
|
-
description,
|
|
418
|
-
);
|
|
419
|
-
return stringToElement(html);
|
|
420
|
-
},
|
|
421
|
-
|
|
422
|
-
/**
|
|
423
|
-
* Renders an option group with header
|
|
424
|
-
*/
|
|
425
|
-
optionGroup: (
|
|
426
|
-
label: string,
|
|
427
|
-
optionsHtml: string,
|
|
428
|
-
config: KTSelectConfigInterface,
|
|
429
|
-
): HTMLElement => {
|
|
430
|
-
let html = getTemplateStrings(config)
|
|
431
|
-
.optionGroup.replace(/{{label}}/g, label)
|
|
432
|
-
.replace('{{optionsHtml}}', optionsHtml);
|
|
285
|
+
.replace('{{selected}}', selected ? 'aria-selected="true"' : 'aria-selected="false"')
|
|
286
|
+
.replace('{{disabled}}', disabled ? 'aria-disabled="true"' : '')
|
|
287
|
+
.replace('{{content}}', content)
|
|
288
|
+
.replace('{{class}}', config.optionClass || '');
|
|
433
289
|
return stringToElement(html);
|
|
434
290
|
},
|
|
435
291
|
|
|
@@ -437,21 +293,25 @@ export const defaultTemplates: KTSelectTemplateInterface = {
|
|
|
437
293
|
* Renders the search input
|
|
438
294
|
*/
|
|
439
295
|
search: (config: KTSelectConfigInterface): HTMLElement => {
|
|
440
|
-
let html = getTemplateStrings(config)
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
296
|
+
let html = getTemplateStrings(config)
|
|
297
|
+
.search.replace(
|
|
298
|
+
'{{searchPlaceholder}}',
|
|
299
|
+
config.searchPlaceholder || 'Search...',
|
|
300
|
+
)
|
|
301
|
+
.replace('{{class}}', config.searchClass || '');
|
|
444
302
|
return stringToElement(html);
|
|
445
303
|
},
|
|
446
304
|
|
|
447
305
|
/**
|
|
448
306
|
* Renders the no results message
|
|
449
307
|
*/
|
|
450
|
-
|
|
451
|
-
let html = getTemplateStrings(config)
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
308
|
+
empty: (config: KTSelectConfigInterface): HTMLElement => {
|
|
309
|
+
let html = getTemplateStrings(config)
|
|
310
|
+
.empty.replace(
|
|
311
|
+
'{{searchNotFoundText}}',
|
|
312
|
+
config.searchNotFoundText || 'No results found',
|
|
313
|
+
)
|
|
314
|
+
.replace('{{class}}', config.emptyClass || '');
|
|
455
315
|
return stringToElement(html);
|
|
456
316
|
},
|
|
457
317
|
|
|
@@ -462,10 +322,12 @@ export const defaultTemplates: KTSelectTemplateInterface = {
|
|
|
462
322
|
config: KTSelectConfigInterface,
|
|
463
323
|
loadingMessage: string,
|
|
464
324
|
): HTMLElement => {
|
|
465
|
-
let html = getTemplateStrings(config)
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
325
|
+
let html = getTemplateStrings(config)
|
|
326
|
+
.loading.replace(
|
|
327
|
+
'{{loadingMessage}}',
|
|
328
|
+
loadingMessage || 'Loading options...',
|
|
329
|
+
)
|
|
330
|
+
.replace('{{class}}', config.loadingClass || '');
|
|
469
331
|
return stringToElement(html);
|
|
470
332
|
},
|
|
471
333
|
|
|
@@ -473,59 +335,60 @@ export const defaultTemplates: KTSelectTemplateInterface = {
|
|
|
473
335
|
* Renders a tag for multi-select
|
|
474
336
|
*/
|
|
475
337
|
tag: (
|
|
476
|
-
option:
|
|
338
|
+
option: HTMLOptionElement,
|
|
477
339
|
config: KTSelectConfigInterface,
|
|
478
340
|
): HTMLElement => {
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
341
|
+
let template = getTemplateStrings(config).tag;
|
|
342
|
+
let content = option.title;
|
|
343
|
+
if (config.tagTemplate) {
|
|
344
|
+
let tagTemplate = config.tagTemplate;
|
|
345
|
+
|
|
346
|
+
const text = option.getAttribute('data-text');
|
|
347
|
+
const value = option.getAttribute('data-value');
|
|
348
|
+
|
|
349
|
+
// Replace all {{varname}} in option.innerHTML with values from _config
|
|
350
|
+
Object.entries((config.optionsConfig as any)[value] || {}).forEach(([key, value]) => {
|
|
351
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
352
|
+
tagTemplate = tagTemplate.replace(new RegExp(`{{${key}}}`, 'g'), String(value));
|
|
353
|
+
}
|
|
490
354
|
});
|
|
491
|
-
};
|
|
492
355
|
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
356
|
+
content = renderTemplateString(tagTemplate, {
|
|
357
|
+
title: option.title,
|
|
358
|
+
id: option.id,
|
|
359
|
+
class: config.tagClass || '',
|
|
360
|
+
content: option.innerHTML,
|
|
361
|
+
text: option.innerText,
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
content += getTemplateStrings(config).tagRemoveButton;
|
|
366
|
+
|
|
367
|
+
const html = template
|
|
368
|
+
.replace('{{title}}', option.title)
|
|
497
369
|
.replace('{{id}}', option.id)
|
|
498
|
-
.replace('{{
|
|
370
|
+
.replace('{{content}}', content)
|
|
371
|
+
.replace('{{class}}', config.tagClass || '');
|
|
499
372
|
return stringToElement(html);
|
|
500
373
|
},
|
|
501
374
|
|
|
502
375
|
/**
|
|
503
|
-
*
|
|
376
|
+
* Renders the placeholder for the select
|
|
504
377
|
*/
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
return config.placeholder || 'Select...';
|
|
511
|
-
}
|
|
378
|
+
placeholder: (config: KTSelectConfigInterface): HTMLElement => {
|
|
379
|
+
let html = getTemplateStrings(config)
|
|
380
|
+
.placeholder.replace('{{class}}', config.placeholderClass || '');
|
|
381
|
+
|
|
382
|
+
let content = config.placeholder || 'Select...';
|
|
512
383
|
|
|
513
|
-
if (config.
|
|
514
|
-
|
|
515
|
-
config.
|
|
516
|
-
|
|
517
|
-
)
|
|
518
|
-
return config.renderSelected(selectedOptions);
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
if (config.showSelectedCount) {
|
|
522
|
-
const count = selectedOptions.length;
|
|
523
|
-
return `${count} ${count === 1 ? 'item' : 'items'} selected`;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
return selectedOptions.map((option) => option.title).join(', ');
|
|
527
|
-
} else {
|
|
528
|
-
return selectedOptions[0].title;
|
|
384
|
+
if (config.placeholderTemplate) {
|
|
385
|
+
content = renderTemplateString(config.placeholderTemplate, {
|
|
386
|
+
placeholder: config.placeholder || 'Select...',
|
|
387
|
+
class: config.placeholderClass || '',
|
|
388
|
+
});
|
|
529
389
|
}
|
|
390
|
+
|
|
391
|
+
html = html.replace('{{content}}', content);
|
|
392
|
+
return stringToElement(html);
|
|
530
393
|
},
|
|
531
394
|
};
|