kmaterialize 2.3.3-1.0.2 → 2.3.3-1.0.21
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 +4 -4
- package/components/air-datepicker/_air-datepicker.scss +137 -0
- package/components/air-datepicker/air-datepicker.ts +192 -0
- package/components/alert/_alerts.scss +130 -0
- package/components/alert/alert.ts +73 -0
- package/components/appbar/appbar.css +301 -4
- package/components/button/_buttons.scss +39 -1
- package/components/card/_cards.scss +9 -1
- package/components/checkbox/_checkboxes.scss +120 -229
- package/components/collapsible/_collapsible.scss +50 -0
- package/components/color-input/_color-input.scss +124 -0
- package/components/color-input/color-input.ts +203 -0
- package/components/dropdown/dropdown.ts +1 -1
- package/components/file-input/_file-input-enhanced.scss +61 -0
- package/components/file-input/file-input.ts +203 -0
- package/components/kanban/_kanban.scss +148 -0
- package/components/kanban/kanban.ts +133 -0
- package/components/list/_collection.scss +10 -2
- package/components/number-input/number-input.ts +103 -0
- package/components/password-input/password-input.ts +72 -0
- package/components/slider/_range.scss +5 -1
- package/components/switch/_switches.scss +5 -0
- package/components/textfield/_input-fields.scss +4 -4
- package/components/textfield/_select.scss +54 -0
- package/components/tom-select/_tom-select-field.scss +256 -0
- package/components/tom-select/tom-select-field.ts +175 -0
- package/components/toolbar/_toolbar.scss +324 -0
- package/components/toolbar/toolbar.ts +152 -0
- package/dist/css/materialize.colors.min.css +2 -2
- package/dist/css/materialize.css +10575 -711
- package/dist/css/materialize.min.css +2 -2
- package/dist/css/materialize.min.css.map +1 -1
- package/dist/js/materialize.cjs.js +1136 -45
- package/dist/js/materialize.d.ts +227 -2
- package/dist/js/materialize.js +1136 -45
- package/dist/js/materialize.min.js +2 -2
- package/dist/js/materialize.mjs +1128 -46
- package/package.json +45 -1
- package/sass/_colors.scss +191 -5
- package/sass/_global.scss +240 -1
- package/sass/materialize.scss +14 -1
- package/sass/mixins.module.scss +6 -6
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
// Materialize styling for the wrapper generated after select.tomselected.
|
|
2
|
+
.input-field:has(> select.tomselected) {
|
|
3
|
+
margin-top: 16px;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.input-field > .ts-wrapper {
|
|
7
|
+
margin-top: 5px;
|
|
8
|
+
|
|
9
|
+
&.single > .ts-control,
|
|
10
|
+
&.multi > .ts-control {
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
width: 100%;
|
|
15
|
+
height: 56px;
|
|
16
|
+
min-height: 56px;
|
|
17
|
+
padding: 0 0 0 15px !important;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
background: var(--md-sys-color-background) !important;
|
|
20
|
+
background-image: none !important;
|
|
21
|
+
border: 0 !important;
|
|
22
|
+
border-bottom: 1px solid var(--md-sys-color-on-surface-variant) !important;
|
|
23
|
+
border-radius: 4px 4px 0 0;
|
|
24
|
+
box-shadow: none !important;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&.focus > .ts-control {
|
|
28
|
+
border-bottom: 2px solid var(--input-color) !important;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Join the control visually to its open dropdown. Closed controls retain
|
|
32
|
+
// their normal corner radius.
|
|
33
|
+
&.dropdown-active > .ts-control {
|
|
34
|
+
border-bottom-right-radius: 0 !important;
|
|
35
|
+
border-bottom-left-radius: 0 !important;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.ts-control {
|
|
39
|
+
font-size: 16px;
|
|
40
|
+
color: var(--md-sys-color-on-surface);
|
|
41
|
+
|
|
42
|
+
> input,
|
|
43
|
+
input[role="combobox"] {
|
|
44
|
+
box-sizing: border-box;
|
|
45
|
+
width: auto !important;
|
|
46
|
+
height: auto !important;
|
|
47
|
+
min-height: 0 !important;
|
|
48
|
+
margin: 0 !important;
|
|
49
|
+
padding: 0 !important;
|
|
50
|
+
color: var(--md-sys-color-on-surface) !important;
|
|
51
|
+
font-size: 16px;
|
|
52
|
+
line-height: 24px;
|
|
53
|
+
background: transparent !important;
|
|
54
|
+
border: 0 !important;
|
|
55
|
+
border-radius: 0 !important;
|
|
56
|
+
box-shadow: none !important;
|
|
57
|
+
|
|
58
|
+
&::placeholder {
|
|
59
|
+
color: color-mix(in srgb, var(--md-sys-color-on-surface) 55%, transparent);
|
|
60
|
+
opacity: 1;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Only multi-select values are rendered as chips. A single value remains
|
|
66
|
+
// normal input text, matching Materialize's select and text fields.
|
|
67
|
+
&.multi > .ts-control {
|
|
68
|
+
gap: 6px;
|
|
69
|
+
padding: 0 0 0 15px !important;
|
|
70
|
+
flex-wrap: nowrap;
|
|
71
|
+
|
|
72
|
+
.item {
|
|
73
|
+
flex: 0 0 auto;
|
|
74
|
+
margin: 0 !important;
|
|
75
|
+
padding: 4px 10px !important;
|
|
76
|
+
color: var(--md-sys-color-on-primary-container);
|
|
77
|
+
line-height: 20px;
|
|
78
|
+
background: var(--md-sys-color-primary-container);
|
|
79
|
+
border: 1px solid var(--md-sys-color-outline-variant);
|
|
80
|
+
border-radius: 999px;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
&.single > .ts-control .item {
|
|
85
|
+
margin: 0 !important;
|
|
86
|
+
padding: 0 !important;
|
|
87
|
+
color: var(--md-sys-color-on-surface);
|
|
88
|
+
line-height: 24px;
|
|
89
|
+
background: transparent;
|
|
90
|
+
border: 0;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
&.disabled > .ts-control {
|
|
94
|
+
opacity: 1;
|
|
95
|
+
color: color-mix(in srgb, transparent, var(--md-sys-color-on-surface) 38%);
|
|
96
|
+
background: color-mix(in srgb, transparent, var(--md-sys-color-on-surface) 4%) !important;
|
|
97
|
+
border-color: color-mix(in srgb, transparent, var(--md-sys-color-on-surface) 12%) !important;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Tom Select hides the native caret, so draw one centered in the field.
|
|
101
|
+
&.single > .ts-control::after {
|
|
102
|
+
content: "";
|
|
103
|
+
position: absolute;
|
|
104
|
+
top: 50%;
|
|
105
|
+
right: 24px;
|
|
106
|
+
width: 9px;
|
|
107
|
+
height: 9px;
|
|
108
|
+
margin-top: -6px;
|
|
109
|
+
border: solid var(--md-sys-color-on-surface) !important;
|
|
110
|
+
border-width: 0 3px 3px 0 !important;
|
|
111
|
+
transform: rotate(45deg);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
&.single.dropdown-active > .ts-control::after {
|
|
115
|
+
margin-top: -3px;
|
|
116
|
+
transform: rotate(-135deg);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.ts-dropdown {
|
|
120
|
+
z-index: 9999;
|
|
121
|
+
margin-top: 0;
|
|
122
|
+
color: var(--md-sys-color-on-surface);
|
|
123
|
+
background: var(--md-sys-color-background) !important;
|
|
124
|
+
border: 1px solid var(--md-sys-color-outline-variant);
|
|
125
|
+
border-radius: 0 0 4px 4px;
|
|
126
|
+
overflow: hidden;
|
|
127
|
+
box-shadow: 0 2px 2px #00000024, 0 3px 1px -2px #0000001f, 0 1px 5px #0003;
|
|
128
|
+
|
|
129
|
+
.ts-dropdown-content {
|
|
130
|
+
background: inherit;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.create,
|
|
134
|
+
.no-results,
|
|
135
|
+
.option {
|
|
136
|
+
display: block;
|
|
137
|
+
padding: 14px 16px;
|
|
138
|
+
color: var(--md-sys-color-on-surface);
|
|
139
|
+
font-size: 16px;
|
|
140
|
+
line-height: 22px;
|
|
141
|
+
background: transparent;
|
|
142
|
+
|
|
143
|
+
&.active {
|
|
144
|
+
background: var(--md-sys-color-primary-container);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.ts-option-content {
|
|
150
|
+
display: flex;
|
|
151
|
+
align-items: center;
|
|
152
|
+
gap: 10px;
|
|
153
|
+
width: 100%;
|
|
154
|
+
|
|
155
|
+
img {
|
|
156
|
+
width: 32px;
|
|
157
|
+
height: 32px;
|
|
158
|
+
object-fit: cover;
|
|
159
|
+
border-radius: 50%;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Large multi-value sets can either grow onto additional rows or retain the
|
|
165
|
+
// standard field height and expose a horizontal scrollbar.
|
|
166
|
+
.input-field > select.tomselected[data-select-overflow="wrap"] + .ts-wrapper.multi > .ts-control {
|
|
167
|
+
height: auto;
|
|
168
|
+
min-height: 56px;
|
|
169
|
+
padding: 8px 0 8px 15px !important;
|
|
170
|
+
overflow: visible;
|
|
171
|
+
flex-wrap: wrap;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.input-field > select.tomselected[data-select-overflow="scroll"] + .ts-wrapper.multi > .ts-control {
|
|
175
|
+
overflow-x: auto;
|
|
176
|
+
overflow-y: hidden;
|
|
177
|
+
flex-wrap: nowrap;
|
|
178
|
+
scrollbar-color: var(--md-sys-color-outline) transparent;
|
|
179
|
+
scrollbar-width: thin;
|
|
180
|
+
|
|
181
|
+
&::-webkit-scrollbar {
|
|
182
|
+
height: 5px;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
&::-webkit-scrollbar-thumb {
|
|
186
|
+
background: var(--md-sys-color-outline);
|
|
187
|
+
border-radius: 999px;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Tom Select labels have the same two states as Materialize text fields.
|
|
192
|
+
// State 1: no value and no placeholder — label acts as the in-field prompt.
|
|
193
|
+
.input-field > select.tomselected + .ts-wrapper + label {
|
|
194
|
+
position: absolute !important;
|
|
195
|
+
top: 16px !important;
|
|
196
|
+
left: 16px !important;
|
|
197
|
+
z-index: 2;
|
|
198
|
+
margin: 0 !important;
|
|
199
|
+
padding: 0 !important;
|
|
200
|
+
color: var(--md-sys-color-on-surface-variant);
|
|
201
|
+
font-size: 16px !important;
|
|
202
|
+
line-height: 24px !important;
|
|
203
|
+
text-align: left !important;
|
|
204
|
+
background: transparent;
|
|
205
|
+
transform: none !important;
|
|
206
|
+
transform-origin: top left !important;
|
|
207
|
+
transition: top 0.2s ease-out, transform 0.2s ease-out, color 0.2s ease-out;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// State 2: a placeholder, a selected value, or focus — float from the same
|
|
211
|
+
// 16px base font/position used by Materialize text-input labels.
|
|
212
|
+
.input-field > select.tomselected[placeholder]:not([placeholder=""]) + .ts-wrapper + label,
|
|
213
|
+
.input-field > select.tomselected:has(> option[value=""]:checked:not(:empty)) + .ts-wrapper + label,
|
|
214
|
+
.input-field > select.tomselected + .ts-wrapper.has-items + label,
|
|
215
|
+
.input-field > select.tomselected + .ts-wrapper.focus + label {
|
|
216
|
+
position: absolute !important;
|
|
217
|
+
top: -12px !important;
|
|
218
|
+
left: 16px !important;
|
|
219
|
+
font-size: 16px !important;
|
|
220
|
+
transform: scale(0.75) !important;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.input-field > select.tomselected + .ts-wrapper.focus + label {
|
|
224
|
+
color: var(--input-color);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Outlined fields use the same two states; only the floating position changes
|
|
228
|
+
// so the small label cuts a notch through the outline like a text input.
|
|
229
|
+
.input-field.outlined > .ts-wrapper.single > .ts-control,
|
|
230
|
+
.input-field.outlined > .ts-wrapper.multi > .ts-control {
|
|
231
|
+
padding: 0 0 0 15px !important;
|
|
232
|
+
background: transparent !important;
|
|
233
|
+
border: 1px solid var(--md-sys-color-on-surface-variant) !important;
|
|
234
|
+
border-radius: 4px;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.input-field.outlined > .ts-wrapper.focus > .ts-control {
|
|
238
|
+
border: 2px solid var(--input-color) !important;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
.input-field.outlined > select.tomselected[placeholder]:not([placeholder=""]) + .ts-wrapper + label,
|
|
242
|
+
.input-field.outlined > select.tomselected:has(> option[value=""]:checked:not(:empty)) + .ts-wrapper + label,
|
|
243
|
+
.input-field.outlined > select.tomselected + .ts-wrapper.has-items + label,
|
|
244
|
+
.input-field.outlined > select.tomselected + .ts-wrapper.focus + label {
|
|
245
|
+
top: -8px !important;
|
|
246
|
+
left: 12px !important;
|
|
247
|
+
padding: 0 4px !important;
|
|
248
|
+
line-height: 16px !important;
|
|
249
|
+
background: var(--md-sys-color-surface);
|
|
250
|
+
transform: scale(0.75) !important;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
div.suffix.suffix-tomselect {
|
|
254
|
+
z-index: 2;
|
|
255
|
+
top: 30px;
|
|
256
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import type TomSelectCtor from 'tom-select';
|
|
2
|
+
import type { TomSettings } from 'tom-select/dist/esm/types/settings.js';
|
|
3
|
+
import type { RecursivePartial } from 'tom-select/dist/esm/types/core.js';
|
|
4
|
+
import { Component, BaseOptions, InitElements, MElement } from '../../src/component';
|
|
5
|
+
import { loadPeer } from '../../src/peer-loader';
|
|
6
|
+
import { FormSelect } from '../textfield/select';
|
|
7
|
+
|
|
8
|
+
export interface RemoteDataSpec {
|
|
9
|
+
url: string;
|
|
10
|
+
value: string;
|
|
11
|
+
label: string;
|
|
12
|
+
search?: string;
|
|
13
|
+
dataKey?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface TomSelectFieldOptions extends BaseOptions {
|
|
17
|
+
remote?: RemoteDataSpec;
|
|
18
|
+
settings?: RecursivePartial<TomSettings>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const _defaults: TomSelectFieldOptions = {};
|
|
22
|
+
|
|
23
|
+
function readRemoteSpec(el: HTMLSelectElement): RemoteDataSpec | undefined {
|
|
24
|
+
const raw = el.dataset.selectRemote;
|
|
25
|
+
if (!raw) return undefined;
|
|
26
|
+
try {
|
|
27
|
+
return JSON.parse(raw);
|
|
28
|
+
} catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// @implement /Users/kzarshenas/Sites/CrazyProject/CrazyPHP/src/Front/Library/Utility/Form/Select.ts
|
|
34
|
+
// Enhances an EXISTING native `<select class="tomselected">` with Tom
|
|
35
|
+
// Select - searchable, taggable, remote-loading, dependent-field wiring,
|
|
36
|
+
// clear button, drag-drop reorder. Ported in a somewhat scoped form: the
|
|
37
|
+
// CrazyPHP source's remote-loading path goes through its own app-specific
|
|
38
|
+
// Crazyrequest/Crazyurl HTTP-client and query-param helpers, which have no
|
|
39
|
+
// equivalent in a standalone UI library - this version uses a plain
|
|
40
|
+
// `fetch()` instead, keeping the same `data-select-remote` JSON shape
|
|
41
|
+
// (url/value/label/search/dataKey) and the same `{{field}}` render-template
|
|
42
|
+
// convention.
|
|
43
|
+
//
|
|
44
|
+
// Coexistence with FormSelect: `.tomselected` is a recognized exclusion
|
|
45
|
+
// marker in FormSelect's own AutoInit selector (see src/index.ts), so a
|
|
46
|
+
// `.tomselected` select is never picked up by FormSelect regardless of
|
|
47
|
+
// init ordering. This constructor still defensively tears down any
|
|
48
|
+
// FormSelect instance found on the same element, belt-and-suspenders, in
|
|
49
|
+
// case that selector rule is ever violated by hand.
|
|
50
|
+
//
|
|
51
|
+
// Tom Select is an optional peerDependency, loaded on demand via
|
|
52
|
+
// peer-loader.
|
|
53
|
+
export class TomSelectField extends Component<TomSelectFieldOptions> {
|
|
54
|
+
declare el: HTMLSelectElement;
|
|
55
|
+
tomSelect: TomSelectCtor | undefined;
|
|
56
|
+
ready: Promise<void>;
|
|
57
|
+
private _dependsOnEl: HTMLElement | null = null;
|
|
58
|
+
|
|
59
|
+
constructor(el: HTMLSelectElement, options: Partial<TomSelectFieldOptions>) {
|
|
60
|
+
super(el, options, TomSelectField);
|
|
61
|
+
(this.el as any).M_TomSelectField = this;
|
|
62
|
+
|
|
63
|
+
FormSelect.getInstance(this.el)?.destroy();
|
|
64
|
+
|
|
65
|
+
this.options = {
|
|
66
|
+
remote: readRemoteSpec(this.el),
|
|
67
|
+
...TomSelectField.defaults,
|
|
68
|
+
...options
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
this.ready = this._setup();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
static get defaults(): TomSelectFieldOptions {
|
|
75
|
+
return _defaults;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static init(el: HTMLSelectElement, options?: Partial<TomSelectFieldOptions>): TomSelectField;
|
|
79
|
+
static init(
|
|
80
|
+
els: InitElements<HTMLSelectElement | MElement>,
|
|
81
|
+
options?: Partial<TomSelectFieldOptions>
|
|
82
|
+
): TomSelectField[];
|
|
83
|
+
static init(
|
|
84
|
+
els: HTMLSelectElement | InitElements<HTMLSelectElement | MElement>,
|
|
85
|
+
options: Partial<TomSelectFieldOptions> = {}
|
|
86
|
+
): TomSelectField | TomSelectField[] {
|
|
87
|
+
return super.init(els, options, TomSelectField);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static getInstance(el: HTMLSelectElement): TomSelectField {
|
|
91
|
+
return (el as any).M_TomSelectField;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
destroy() {
|
|
95
|
+
if (this._dependsOnEl) this._dependsOnEl.removeEventListener('change', this._handleDependencyChange);
|
|
96
|
+
this.tomSelect?.destroy();
|
|
97
|
+
(this.el as any).M_TomSelectField = undefined;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
_handleDependencyChange = () => {
|
|
101
|
+
this.tomSelect?.clear();
|
|
102
|
+
this.tomSelect?.clearOptions();
|
|
103
|
+
this.tomSelect?.load?.('');
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
async _setup(): Promise<void> {
|
|
107
|
+
const TomSelect = await loadPeer<typeof TomSelectCtor>(
|
|
108
|
+
{
|
|
109
|
+
specifier: 'tom-select',
|
|
110
|
+
globalName: 'TomSelect',
|
|
111
|
+
feature: 'Select (Tom Select) enhancement',
|
|
112
|
+
cdnHint: '<script src="path/to/tom-select.complete.min.js"></script> (self-hosted - copy from node_modules/tom-select/dist/js/, or a CDN of your choice)'
|
|
113
|
+
},
|
|
114
|
+
() => import('tom-select')
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const dataset = this.el.dataset;
|
|
118
|
+
const settings: RecursivePartial<TomSettings> = {
|
|
119
|
+
persist: false,
|
|
120
|
+
createOnBlur: true,
|
|
121
|
+
create: 'selectTag' in dataset,
|
|
122
|
+
plugins: {},
|
|
123
|
+
...this.options.settings
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
if ('selectClear' in dataset) {
|
|
127
|
+
(settings.plugins as any).clear_button = { title: dataset.selectClear || 'Clear' };
|
|
128
|
+
}
|
|
129
|
+
if ('selectTag' in dataset || this.el.multiple) {
|
|
130
|
+
(settings.plugins as any).caret_position = {};
|
|
131
|
+
(settings.plugins as any).drag_drop = {};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (this.el.classList.contains('icons')) {
|
|
135
|
+
const renderWithIcon = (data: Record<string, any>, escape: (value: string) => string) => {
|
|
136
|
+
const icon = data.icon ? `<img src="${escape(String(data.icon))}" alt="" />` : '';
|
|
137
|
+
return `<div class="ts-option-content">${icon}<span>${escape(String(data.text ?? ''))}</span></div>`;
|
|
138
|
+
};
|
|
139
|
+
settings.render = { ...settings.render, option: renderWithIcon, item: renderWithIcon };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const remote = this.options.remote;
|
|
143
|
+
if (remote) {
|
|
144
|
+
settings.valueField = remote.value;
|
|
145
|
+
if (remote.search) settings.searchField = [remote.search];
|
|
146
|
+
|
|
147
|
+
if (remote.label && remote.label.includes('{{') && remote.label.includes('}}')) {
|
|
148
|
+
const renderTemplate = (data: Record<string, any>, escape: (input: string) => string) =>
|
|
149
|
+
`<div>${remote.label.replace(/\{\{(.*?)\}\}/g, (_m, key) => escape(String(data[key] ?? '')))}</div>`;
|
|
150
|
+
settings.render = { option: renderTemplate, item: renderTemplate };
|
|
151
|
+
} else {
|
|
152
|
+
settings.labelField = remote.label;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
settings.load = (query, callback) => {
|
|
156
|
+
fetch(remote.url)
|
|
157
|
+
.then((r) => r.json())
|
|
158
|
+
.then((value) => {
|
|
159
|
+
const results = remote.dataKey
|
|
160
|
+
? remote.dataKey.split('.').reduce((acc: any, key: string) => acc && acc[key], value)
|
|
161
|
+
: value?.results ?? value;
|
|
162
|
+
callback(Array.isArray(results) ? results : []);
|
|
163
|
+
})
|
|
164
|
+
.catch(() => callback([]));
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
this.tomSelect = new TomSelect(this.el, settings);
|
|
169
|
+
|
|
170
|
+
if (dataset.depends) {
|
|
171
|
+
this._dependsOnEl = document.querySelector<HTMLElement>(dataset.depends);
|
|
172
|
+
this._dependsOnEl?.addEventListener('change', this._handleDependencyChange);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|