uni-select-field 1.0.0

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.
@@ -0,0 +1,496 @@
1
+ import { _wcl } from './common-lib.js';
2
+ import { _wccss } from './common-css.js';
3
+ import {
4
+ colorPalette as _uniColorPalette
5
+ } from 'https://unpkg.com/uni-input-field/mjs/uni-css.js';
6
+
7
+ const defaults = {
8
+ subject: '',
9
+ message: '',
10
+ stat: '', // valid, invalid
11
+ appearance: 'filled', // filled, outlined
12
+ size: 'medium' // large, medium, small
13
+ };
14
+
15
+ const booleanAttrs = [];
16
+ const objectAttrs = [];
17
+ const custumEvents = {};
18
+
19
+ const template = document.createElement('template');
20
+ template.innerHTML = `
21
+ <style>
22
+ ${_wccss}
23
+ ${_uniColorPalette}
24
+
25
+ :host{position:relative;display:block;}
26
+
27
+ :host([hidden]) {
28
+ display: none;
29
+ }
30
+
31
+ /* state */
32
+ :host([stat=valid]) {
33
+ .main {
34
+ --border-color: var(--border-color-valid);
35
+ --message-color: var(--message-color-valid);
36
+ }
37
+ }
38
+
39
+ :host([stat=invalid]) {
40
+ .main {
41
+ --text-color: var(--text-color-invalid);
42
+ --border-color: var(--border-color-invalid);
43
+ --message-color: var(--message-color-invalid);
44
+ }
45
+ }
46
+
47
+ /* appearance */
48
+ :host([appearance=outlined]) {
49
+ .main {
50
+ --border-color: var(--border-color-outline);
51
+ --background-color: transparent;
52
+ }
53
+ }
54
+
55
+ /* size */
56
+ :host([size=large]) {
57
+ .main {
58
+ --border-radius: var(--large-border-radius);
59
+ --padding-inline: var(--large-padding-inline);
60
+ --block-size: var(--large-block-size);
61
+ }
62
+ }
63
+
64
+ :host([size=medium]) {
65
+ .main {
66
+ --border-radius: var(--medium-border-radius);
67
+ --padding-inline: var(--medium-padding-inline);
68
+ --block-size: var(--medium-block-size);
69
+ }
70
+ }
71
+
72
+ :host([size=small]) {
73
+ .main {
74
+ --border-radius: var(--small-border-radius);
75
+ --padding-inline: var(--small-padding-inline);
76
+ --block-size: var(--small-block-size);
77
+ }
78
+ }
79
+
80
+ :host {
81
+ &:has([slot="select"][required]) {
82
+ .main__subject__span::after {
83
+ content: '*';
84
+ color: var(--ct_icon_moderate_strong);
85
+ margin-inline-start: 4px;
86
+ }
87
+ }
88
+
89
+ &:has([slot="select"][disabled],[slot="select"][inert]) {
90
+ .main {
91
+ --text-color: var(--text-color-disabled);
92
+ --caret-color: var(--caret-color-disabled);
93
+ }
94
+
95
+ slot[name="select"] {
96
+ interactivity: inert;
97
+ }
98
+ }
99
+
100
+ @container style(--interactivity: inert) {
101
+ .main {
102
+ --text-color: var(--text-color-disabled);
103
+ }
104
+
105
+ slot[name="select"] {
106
+ interactivity: inert;
107
+ }
108
+ }
109
+ }
110
+
111
+ .main {
112
+ --border-color-normal: var(--uni-select-field-border-color-normal, transparent);
113
+ --border-color-disabled: var(--uni-select-field-border-color-disabled, var(--ct_input-general_dim_container_default));
114
+ --border-color-valid: var(--uni-select-field-border-color-valid, var(--ct_text_success_general));
115
+ --border-color-invalid: var(--uni-select-field-border-color-invalid, var(--ct_text_danger_general));
116
+ --border-color-outline: var(--uni-select-field-border-color-outline, var(--ct_input-general_main_stroke_default));
117
+ --border-color: var(--border-color-normal);
118
+
119
+ --background-color-normal: var(--uni-select-field-background-color-normal, var(--ct_input-general_dim_container_default));
120
+ --background-color-readonly: var(--uni-select-field-background-color-readonly, var(--ct_input-general_dim_container_default));
121
+ --background-color-disabled: var(--uni-select-field-background-color-disabled, var(--ct_input-general_dim_container_default));
122
+ --background-color: var(--background-color-normal);
123
+
124
+ --text-color-normal: var(--uni-select-field-text-color-normal, var(--ct_text_main_general));
125
+ --text-color-readonly: var(--uni-select-field-text-color-readonly, var(--ct_text_main_general));
126
+ --text-color-disabled: var(--uni-select-field-text-color-disabled, var(--ct_text_main_pale));
127
+ --text-color-invalid: var(--uni-select-field-text-color-invalid, var(--ct_text_danger_general));
128
+ --text-color: var(--text-color-normal);
129
+
130
+ --message-color-normal: var(--uni-select-field-message-color-normal, var(--ct_text_main_subtle));
131
+ --message-color-valid: var(--uni-select-field-message-color-valid, var(--ct_text_success_general));
132
+ --message-color-invalid: var(--uni-select-field-message-color-invalid, var(--ct_text_danger_general));
133
+ --message-color: var(--message-color-normal);
134
+
135
+ --caret-color-normal: var(--uni-select-field-caret-color-normal, var(--ct_icon_main_subtle));
136
+ --caret-color-disabled: var(--uni-select-field-caret-color-disabled, var(--ct_icon_main_pale));
137
+ --caret-color: var(--caret-color-normal);
138
+
139
+ --subject-color: var(--uni-select-field-subject-color, var(--ct_text_main_subtle));
140
+ --caret-size: 20px;
141
+
142
+ /* size */
143
+ --basis-padding: 12px;
144
+ --large-border-radius: 24px;
145
+ --large-padding-inline: var(--basis-padding) calc(var(--basis-padding) * 2 + var(--basis-padding));
146
+ --large-block-size: 56px;
147
+ --medium-border-radius: 44px;
148
+ --medium-padding-inline: var(--basis-padding) calc(var(--basis-padding) * 2 + var(--basis-padding));
149
+ --medium-block-size: 44px;
150
+ --small-border-radius: 32px;
151
+ --small-padding-inline: var(--basis-padding) calc(var(--basis-padding) * 2 + var(--basis-padding));
152
+ --small-block-size: 32px;
153
+
154
+ --border-radius: var(--medium-border-radius);
155
+ --padding-inline: var(--medium-padding-inline);
156
+ --block-size: var(--medium-block-size);
157
+
158
+ inline-size: 100%;
159
+
160
+ .main__subject {
161
+ padding-block-end: 4px;
162
+ display: flex;
163
+ align-items: center;
164
+ gap: 4px;
165
+
166
+ &:has(.main__subject__span:empty) {
167
+ display: none;
168
+ }
169
+
170
+ .main__subject__span {
171
+ font-size: 12px;
172
+ color: var(--subject-color);
173
+ line-height: 1.667;
174
+ }
175
+
176
+ em {
177
+ inline-size: 15px;
178
+ block-size: 15px;
179
+ clip-path: path('M7.1,0C3.2,0,0,3.2,0,7.1s3.2,7.1,7.1,7.1,7.1-3.2,7.1-7.1S11.1,0,7.1,0ZM7.1,12.7c-3.1,0-5.6-2.5-5.6-5.5S4.1,1.6,7.1,1.6s5.5,2.5,5.5,5.6-2.5,5.5-5.5,5.5h0ZM7.9,6.3h-1.6v4.7h1.6v-4.7ZM7.9,3.6h-1.6v1.5h1.6v-1.5Z');
180
+ background-color: var(--subject-color);
181
+ display: block;
182
+ }
183
+ }
184
+
185
+ .main__info {
186
+ --justify-content: space-between;
187
+
188
+ padding: 4px 8px;
189
+ box-sizing: border-box;
190
+ display: flex;
191
+ gap: 16px;
192
+ justify-content: var(--justify-content);
193
+ align-items: center;
194
+
195
+ &:has(.main__info__message:empty) {
196
+ --justify-content: flex-end;
197
+ }
198
+
199
+ .main__info__message {
200
+ font-size: 11px;
201
+ color: var(--message-color);
202
+ line-height: 1.3;
203
+
204
+ &:empty {
205
+ display: none;
206
+ }
207
+ }
208
+
209
+ .main__info__counter {
210
+ flex-shrink: 0;
211
+ font-size: 12px;
212
+ color: var(--counter-color);
213
+ display: var(--counter-display);
214
+
215
+ &::after {
216
+ content: ' / ' attr(data-maxlength);
217
+ }
218
+ }
219
+ }
220
+
221
+ slot[name=select] {
222
+ position: relative;
223
+ inline-size: 100%;
224
+ inline-size: fit-content;
225
+ display: block;
226
+
227
+ &::after {
228
+ content: '';
229
+ position: absolute;
230
+ inset: 0;
231
+ margin-block: auto;
232
+ margin-inline: auto var(--basis-padding);
233
+ inline-size: var(--caret-size);
234
+ aspect-ratio: 1/1;
235
+ background-color: var(--caret-color);
236
+ clip-path: path(evenodd, 'M10.7854 13.4895C10.3514 13.9235 9.64792 13.9235 9.21401 13.4895L3.75879 8.03433L5.173 6.62012L9.99968 11.4468L14.8264 6.62012L16.2406 8.03433L10.7854 13.4895Z');
237
+ pointer-events: none;
238
+ }
239
+ }
240
+
241
+ /* select */
242
+ ::slotted(select) {
243
+ outline: 0 none;
244
+ resize: none;
245
+ appearance: none;
246
+ box-shadow: none;
247
+
248
+ display: inline-flex;
249
+ align-items: center;
250
+
251
+ font-size: 16px;
252
+ line-height: 1.4;
253
+ color: var(--text-color);
254
+ max-inline-size: 100%;
255
+ field-sizing: content;
256
+ block-size: var(--block-size);
257
+ box-sizing: border-box;
258
+ padding-inline: var(--padding-inline) !important;
259
+ text-overflow: ellipsis;
260
+ border: 1px solid var(--border-color);
261
+ background-color: var(--background-color);
262
+ border-radius: var(--border-radius);
263
+ }
264
+ }
265
+ </style>
266
+
267
+ <div class="main" ontouchstart="" tabindex="0">
268
+ <p class="main__subject">
269
+ <em part="icon-subject"></em>
270
+ <span class="main__subject__span"></span>
271
+ </p>
272
+ <slot name="select"></slot>
273
+ <div class="main__info">
274
+ <p class="main__info__message"></p>
275
+ </div>
276
+ </div>
277
+ `;
278
+
279
+ export class UniSelectField extends HTMLElement {
280
+ #data;
281
+ #nodes;
282
+ #config;
283
+
284
+ constructor(config) {
285
+ super();
286
+
287
+ // template
288
+ this.attachShadow({ mode: 'open', delegatesFocus: true });
289
+ this.shadowRoot.appendChild(template.content.cloneNode(true));
290
+
291
+ // data
292
+ this.#data = {
293
+ controller: ''
294
+ };
295
+
296
+ // nodes
297
+ this.#nodes = {
298
+ styleSheet: this.shadowRoot.querySelector('style'),
299
+ select: this.querySelector('[slot=select]'),
300
+ subject: this.shadowRoot.querySelector('.main__subject__span'),
301
+ message: this.shadowRoot.querySelector('.main__info__message'),
302
+ counter: this.shadowRoot.querySelector('.main__info__counter'),
303
+ };
304
+
305
+ // config
306
+ this.#config = {
307
+ ...defaults,
308
+ ...config // new UniSelectField(config)
309
+ };
310
+ }
311
+
312
+ async connectedCallback() {
313
+ const { config, error } = await _wcl.getWCConfig(this);
314
+
315
+ if (error) {
316
+ console.warn(`${_wcl.classToTagName(this.constructor.name)}: ${error}`);
317
+ this.remove();
318
+ return;
319
+ } else {
320
+ this.#config = {
321
+ ...this.#config,
322
+ ...config
323
+ };
324
+ }
325
+
326
+ // upgradeProperty
327
+ Object.keys(defaults).forEach((key) => this.#upgradeProperty(key));
328
+ }
329
+
330
+ disconnectedCallback() {
331
+ if (this.#data?.controller) {
332
+ this.#data.controller.abort();
333
+ }
334
+ }
335
+
336
+ #format(attrName, oldValue, newValue) {
337
+ const hasValue = newValue !== null;
338
+
339
+ if (!hasValue) {
340
+ if (booleanAttrs.includes(attrName)) {
341
+ this.#config[attrName] = false;
342
+ } else {
343
+ this.#config[attrName] = defaults[attrName];
344
+ }
345
+ } else {
346
+ switch (attrName) {
347
+ case 'subject':
348
+ case 'message': {
349
+ this.#config[attrName] = newValue;
350
+ break;
351
+ }
352
+
353
+ case 'stat': {
354
+ this.#config[attrName] = ['', 'valid', 'invalid'].includes(newValue) ? newValue : defaults.state;
355
+ break;
356
+ }
357
+
358
+ case 'appearance': {
359
+ this.#config[attrName] = ['filled', 'outlined'].includes(newValue) ? newValue : defaults.appearance;
360
+ break;
361
+ }
362
+
363
+ case 'size': {
364
+ this.#config[attrName] = ['large', 'medium', 'small'].includes(newValue) ? newValue : defaults.size;
365
+ break;
366
+ }
367
+ }
368
+ }
369
+ }
370
+
371
+ attributeChangedCallback(attrName, oldValue, newValue) {
372
+ if (!UniSelectField.observedAttributes.includes(attrName)) {
373
+ return;
374
+ }
375
+
376
+ this.#format(attrName, oldValue, newValue);
377
+
378
+ switch (attrName) {
379
+ case 'subject': {
380
+ this.#nodes.subject.textContent = this.subject;
381
+ break;
382
+ }
383
+
384
+ case 'message': {
385
+ this.#nodes.message.textContent = this.message;
386
+ break;
387
+ }
388
+ }
389
+ }
390
+
391
+ static get observedAttributes() {
392
+ return Object.keys(defaults); // UniSelectField.observedAttributes
393
+ }
394
+
395
+ static get supportedEvents() {
396
+ return Object.keys(custumEvents).map(
397
+ (key) => {
398
+ return custumEvents[key];
399
+ }
400
+ );
401
+ }
402
+
403
+ #upgradeProperty(prop) {
404
+ let value;
405
+
406
+ if (UniSelectField.observedAttributes.includes(prop)) {
407
+ if (Object.prototype.hasOwnProperty.call(this, prop)) {
408
+ value = this[prop];
409
+ delete this[prop];
410
+ } else {
411
+ if (booleanAttrs.includes(prop)) {
412
+ value = (this.hasAttribute(prop) || this.#config[prop]) ? true : false;
413
+ } else if (objectAttrs.includes(prop)) {
414
+ value = this.hasAttribute(prop) ? this.getAttribute(prop) : JSON.stringify(this.#config[prop]);
415
+ } else {
416
+ value = this.hasAttribute(prop) ? this.getAttribute(prop) : this.#config[prop];
417
+ }
418
+ }
419
+
420
+ this[prop] = value;
421
+ }
422
+ }
423
+
424
+ set subject(value) {
425
+ if (value) {
426
+ this.setAttribute('subject', value);
427
+ } else {
428
+ this.removeAttribute('subject');
429
+ }
430
+ }
431
+
432
+ get subject() {
433
+ return this.#config.subject;
434
+ }
435
+
436
+ set message(value) {
437
+ if (value) {
438
+ this.setAttribute('message', value);
439
+ } else {
440
+ this.removeAttribute('message');
441
+ }
442
+ }
443
+
444
+ get message() {
445
+ return this.#config.message;
446
+ }
447
+
448
+ set stat(value) {
449
+ if (value) {
450
+ this.setAttribute('stat', value);
451
+ } else {
452
+ this.removeAttribute('stat');
453
+ }
454
+ }
455
+
456
+ get stat() {
457
+ return this.#config.stat;
458
+ }
459
+
460
+ set appearance(value) {
461
+ if (value) {
462
+ this.setAttribute('appearance', value);
463
+ } else {
464
+ this.removeAttribute('appearance');
465
+ }
466
+ }
467
+
468
+ get appearance() {
469
+ return this.#config.appearance;
470
+ }
471
+
472
+ set size(value) {
473
+ if (value) {
474
+ this.setAttribute('size', value);
475
+ } else {
476
+ this.removeAttribute('size');
477
+ }
478
+ }
479
+
480
+ get size() {
481
+ return this.#config.size;
482
+ }
483
+
484
+ refresh() {
485
+ this.hidden = true;
486
+ this.offsetHeight;
487
+ this.hidden = false;
488
+ }
489
+ }
490
+
491
+ // define web component
492
+ const S = _wcl.supports();
493
+ const T = _wcl.classToTagName('UniSelectField');
494
+ if (S.customElements && S.shadowDOM && S.template && !window.customElements.get(T)) {
495
+ window.customElements.define(_wcl.classToTagName('UniSelectField'), UniSelectField);
496
+ }