kempo-ui 0.4.2 → 0.4.3

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 (79) hide show
  1. package/dist/components/Calendar.js +170 -0
  2. package/dist/components/Time.js +37 -0
  3. package/docs/components/accordion.html +8 -0
  4. package/docs/components/aside.html +8 -0
  5. package/docs/components/calendar.html +712 -0
  6. package/docs/components/card.html +8 -0
  7. package/docs/components/code-editor.html +8 -0
  8. package/docs/components/color-picker.html +8 -0
  9. package/docs/components/combobox.html +8 -0
  10. package/docs/components/content-slider.html +8 -0
  11. package/docs/components/context.html +8 -0
  12. package/docs/components/dialog.html +8 -0
  13. package/docs/components/dropdown.html +8 -0
  14. package/docs/components/filter-list.html +8 -0
  15. package/docs/components/focus-capture.html +8 -0
  16. package/docs/components/html-editor.html +8 -0
  17. package/docs/components/hybrid-component.html +8 -0
  18. package/docs/components/icon.html +8 -0
  19. package/docs/components/import.html +8 -0
  20. package/docs/components/light-component.html +8 -0
  21. package/docs/components/nav-spacer.html +8 -0
  22. package/docs/components/nav.html +8 -0
  23. package/docs/components/photo-viewer.html +8 -0
  24. package/docs/components/progress.html +8 -0
  25. package/docs/components/resize.html +8 -0
  26. package/docs/components/shadow-component.html +8 -0
  27. package/docs/components/show-more.html +8 -0
  28. package/docs/components/slider.html +8 -0
  29. package/docs/components/sortable.html +8 -0
  30. package/docs/components/spinner.html +8 -0
  31. package/docs/components/split.html +8 -0
  32. package/docs/components/table.html +8 -0
  33. package/docs/components/tableControls.html +8 -0
  34. package/docs/components/tableCustomFields.html +8 -0
  35. package/docs/components/tableFetchRecords.html +8 -0
  36. package/docs/components/tableFieldSortHide.html +8 -0
  37. package/docs/components/tablePagination.html +8 -0
  38. package/docs/components/tablePlaceholder.html +8 -0
  39. package/docs/components/tableRecordEditing.html +8 -0
  40. package/docs/components/tableRecordFiltering.html +8 -0
  41. package/docs/components/tableRecordHiding.html +8 -0
  42. package/docs/components/tableRecordSearching.html +8 -0
  43. package/docs/components/tableRecordSelection.html +8 -0
  44. package/docs/components/tableRowControls.html +8 -0
  45. package/docs/components/tableServerSync.html +8 -0
  46. package/docs/components/tableSorting.html +8 -0
  47. package/docs/components/tabs.html +8 -0
  48. package/docs/components/tags.html +8 -0
  49. package/docs/components/theme-select.html +8 -0
  50. package/docs/components/theme-switcher.html +8 -0
  51. package/docs/components/time.html +662 -0
  52. package/docs/components/timestamp.html +8 -0
  53. package/docs/components/toast.html +8 -0
  54. package/docs/components/toggle.html +8 -0
  55. package/docs/components/tree.html +8 -0
  56. package/docs/index.html +20 -0
  57. package/docs/src/components/Calendar.js +170 -0
  58. package/docs/src/components/Time.js +37 -0
  59. package/docs/utils/context.html +8 -0
  60. package/docs/utils/cookie.html +8 -0
  61. package/docs/utils/debounce.html +8 -0
  62. package/docs/utils/drag.html +8 -0
  63. package/docs/utils/elevation.html +8 -0
  64. package/docs/utils/formatTimestamp.html +8 -0
  65. package/docs/utils/object.html +8 -0
  66. package/docs/utils/propConverters.html +8 -0
  67. package/docs/utils/string.html +8 -0
  68. package/docs/utils/theme.html +8 -0
  69. package/docs/utils/toTitleCase.html +8 -0
  70. package/docs/utils/type.html +8 -0
  71. package/docs/utils/wait.html +8 -0
  72. package/docs-src/components/calendar.page.html +254 -0
  73. package/docs-src/components/time.page.html +204 -0
  74. package/docs-src/index.page.html +12 -0
  75. package/docs-src/nav.fragment.html +8 -0
  76. package/llms.txt +2 -0
  77. package/package.json +1 -1
  78. package/src/components/Calendar.js +473 -0
  79. package/src/components/Time.js +137 -0
@@ -0,0 +1,473 @@
1
+ import { html, css } from '../lit-all.min.js';
2
+ import ShadowComponent from './ShadowComponent.js';
3
+
4
+ const MONTH_NAMES = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
5
+ const DAY_LABELS = ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'];
6
+
7
+ export default class Calendar extends ShadowComponent {
8
+ static formAssociated = true;
9
+
10
+ static properties = {
11
+ value: { type: String, reflect: true },
12
+ name: { type: String, reflect: true },
13
+ mode: { type: String, reflect: true },
14
+ min: { type: String, reflect: true },
15
+ max: { type: String, reflect: true },
16
+ disabled: { type: Boolean, reflect: true },
17
+ required: { type: Boolean, reflect: true },
18
+ view: { state: true },
19
+ hoverDate: { state: true }
20
+ };
21
+
22
+ /*
23
+ Lifecycle Callbacks
24
+ */
25
+ constructor() {
26
+ super();
27
+ this.internals = this.attachInternals();
28
+ this.value = '';
29
+ this.name = '';
30
+ this.mode = 'single';
31
+ this.min = '';
32
+ this.max = '';
33
+ this.disabled = false;
34
+ this.required = false;
35
+ const today = new Date();
36
+ this.view = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}`;
37
+ this.hoverDate = null;
38
+ }
39
+
40
+ #skipViewSync = false;
41
+
42
+ updated(changedProperties) {
43
+ super.updated(changedProperties);
44
+ this.internals.setFormValue(this.value);
45
+ if(this.required && !this.value){
46
+ this.internals.setValidity(
47
+ { valueMissing: true },
48
+ 'Please select a date.',
49
+ this.shadowRoot?.querySelector('.day')
50
+ );
51
+ } else {
52
+ this.internals.setValidity({});
53
+ }
54
+ if(changedProperties.has('value') && changedProperties.get('value') !== undefined){
55
+ this.dispatchEvent(new CustomEvent('change', {
56
+ detail: { value: this.value },
57
+ bubbles: true
58
+ }));
59
+ }
60
+ if(changedProperties.has('value') && this.value && !this.#skipViewSync){
61
+ const first = this.fromIso(this.value.split(',')[0]);
62
+ if(first){
63
+ const newView = `${first.getFullYear()}-${String(first.getMonth() + 1).padStart(2, '0')}`;
64
+ if(newView !== this.view){
65
+ this.view = newView;
66
+ }
67
+ }
68
+ }
69
+ this.#skipViewSync = false;
70
+ }
71
+
72
+ /*
73
+ Utility
74
+ */
75
+ get isRange() {
76
+ return this.mode === 'range';
77
+ }
78
+
79
+ get viewYear() {
80
+ return Number(this.view.split('-')[0]);
81
+ }
82
+
83
+ get viewMonth() {
84
+ return Number(this.view.split('-')[1]) - 1;
85
+ }
86
+
87
+ get parsed() {
88
+ if(!this.value){
89
+ return this.isRange ? { start: null, end: null } : { date: null };
90
+ }
91
+ if(this.isRange){
92
+ const [s, e] = this.value.split(',');
93
+ return {
94
+ start: s ? this.fromIso(s) : null,
95
+ end: e ? this.fromIso(e) : null
96
+ };
97
+ }
98
+ return { date: this.fromIso(this.value) };
99
+ }
100
+
101
+ toIso = (date) => {
102
+ if(!date) return '';
103
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
104
+ };
105
+
106
+ fromIso = (str) => {
107
+ if(!str) return null;
108
+ const [y, m, d] = str.split('-').map(Number);
109
+ if(isNaN(y) || isNaN(m) || isNaN(d)) return null;
110
+ return new Date(y, m - 1, d);
111
+ };
112
+
113
+ isSameDay = (a, b) => {
114
+ if(!a || !b) return false;
115
+ return a.getFullYear() === b.getFullYear()
116
+ && a.getMonth() === b.getMonth()
117
+ && a.getDate() === b.getDate();
118
+ };
119
+
120
+ isWithinRange = (date, start, end) => {
121
+ if(!start || !end || !date) return false;
122
+ const t = date.getTime();
123
+ return t > start.getTime() && t < end.getTime();
124
+ };
125
+
126
+ resolveDate = (input) => {
127
+ if(!input) return null;
128
+ const key = String(input).toLowerCase();
129
+ if(key === 'today' || key === 'tomorrow' || key === 'yesterday'){
130
+ const d = new Date();
131
+ d.setHours(0, 0, 0, 0);
132
+ if(key === 'tomorrow') d.setDate(d.getDate() + 1);
133
+ if(key === 'yesterday') d.setDate(d.getDate() - 1);
134
+ return d;
135
+ }
136
+ return this.fromIso(input);
137
+ };
138
+
139
+ get minDate() {
140
+ return this.resolveDate(this.min) || this.fromIso('1900-01-01');
141
+ }
142
+
143
+ get maxDate() {
144
+ if(this.max) return this.resolveDate(this.max);
145
+ const now = new Date();
146
+ return new Date(now.getFullYear() + 10, 11, 31);
147
+ }
148
+
149
+ isDisabledDate = (date) => {
150
+ if(!date) return false;
151
+ const minDate = this.minDate;
152
+ if(minDate && date < minDate) return true;
153
+ const maxDate = this.maxDate;
154
+ if(maxDate && date > maxDate) return true;
155
+ return false;
156
+ };
157
+
158
+ get availableYears() {
159
+ const minY = this.minDate?.getFullYear() ?? 1900;
160
+ const maxY = this.maxDate?.getFullYear() ?? (new Date().getFullYear() + 10);
161
+ const years = [];
162
+ for(let y = minY; y <= maxY; y++) years.push(y);
163
+ return years;
164
+ }
165
+
166
+ isMonthDisabled = (year, month) => {
167
+ const lastDay = new Date(year, month + 1, 0);
168
+ const firstDay = new Date(year, month, 1);
169
+ const min = this.minDate;
170
+ const max = this.maxDate;
171
+ if(min && lastDay < min) return true;
172
+ if(max && firstDay > max) return true;
173
+ return false;
174
+ };
175
+
176
+ get weekGrid() {
177
+ const year = this.viewYear;
178
+ const month = this.viewMonth;
179
+ const first = new Date(year, month, 1);
180
+ const startOffset = first.getDay();
181
+ const gridStart = new Date(year, month, 1 - startOffset);
182
+ const weeks = [];
183
+ for(let w = 0; w < 6; w++){
184
+ const days = [];
185
+ for(let d = 0; d < 7; d++){
186
+ const date = new Date(gridStart);
187
+ date.setDate(gridStart.getDate() + w * 7 + d);
188
+ days.push(date);
189
+ }
190
+ weeks.push(days);
191
+ }
192
+ return weeks;
193
+ }
194
+
195
+ get monthLabel() {
196
+ return `${MONTH_NAMES[this.viewMonth]} ${this.viewYear}`;
197
+ }
198
+
199
+ /*
200
+ Navigation
201
+ */
202
+ prevMonth = () => {
203
+ const d = new Date(this.viewYear, this.viewMonth - 1, 1);
204
+ this.view = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;
205
+ };
206
+
207
+ nextMonth = () => {
208
+ const d = new Date(this.viewYear, this.viewMonth + 1, 1);
209
+ this.view = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}`;
210
+ };
211
+
212
+ goToMonth = (year, month) => {
213
+ this.view = `${year}-${String(month + 1).padStart(2, '0')}`;
214
+ };
215
+
216
+ goToToday = () => {
217
+ const today = new Date();
218
+ this.view = `${today.getFullYear()}-${String(today.getMonth() + 1).padStart(2, '0')}`;
219
+ };
220
+
221
+ /*
222
+ Event Handlers
223
+ */
224
+ handleDayClick = (date) => {
225
+ if(this.disabled || this.isDisabledDate(date)) return;
226
+ this.#skipViewSync = true;
227
+ if(this.isRange){
228
+ const { start, end } = this.parsed;
229
+ if(!start || end){
230
+ this.value = this.toIso(date);
231
+ } else if(date < start){
232
+ this.value = `${this.toIso(date)},${this.toIso(start)}`;
233
+ } else {
234
+ this.value = `${this.toIso(start)},${this.toIso(date)}`;
235
+ }
236
+ } else {
237
+ this.value = this.toIso(date);
238
+ }
239
+ };
240
+
241
+ handleDayHover = (date) => {
242
+ if(this.isRange){
243
+ this.hoverDate = date;
244
+ }
245
+ };
246
+
247
+ handleMouseLeave = () => {
248
+ if(this.isRange){
249
+ this.hoverDate = null;
250
+ }
251
+ };
252
+
253
+ handleMonthChange = (e) => {
254
+ this.goToMonth(this.viewYear, Number(e.target.value));
255
+ };
256
+
257
+ handleYearChange = (e) => {
258
+ this.goToMonth(Number(e.target.value), this.viewMonth);
259
+ };
260
+
261
+ /*
262
+ Rendering
263
+ */
264
+ render() {
265
+ const today = new Date();
266
+ const parsed = this.parsed;
267
+ const single = parsed.date;
268
+ const rawStart = parsed.start;
269
+ const rawEnd = parsed.end;
270
+ const previewEnd = this.isRange && rawStart && !rawEnd && this.hoverDate ? this.hoverDate : rawEnd;
271
+ const rangeStart = this.isRange && rawStart && previewEnd && rawStart > previewEnd ? previewEnd : rawStart;
272
+ const rangeEnd = this.isRange && rawStart && previewEnd && rawStart > previewEnd ? rawStart : previewEnd;
273
+
274
+ return html`
275
+ <div class="header">
276
+ <select
277
+ class="month-select"
278
+ aria-label="Month"
279
+ ?disabled=${this.disabled}
280
+ @change=${this.handleMonthChange}
281
+ >
282
+ ${MONTH_NAMES.map((name, i) => html`
283
+ <option
284
+ value=${i}
285
+ ?selected=${i === this.viewMonth}
286
+ ?disabled=${this.isMonthDisabled(this.viewYear, i)}
287
+ >${name}</option>
288
+ `)}
289
+ </select>
290
+ <select
291
+ class="year-select"
292
+ aria-label="Year"
293
+ ?disabled=${this.disabled}
294
+ @change=${this.handleYearChange}
295
+ >
296
+ ${this.availableYears.map(y => html`
297
+ <option value=${y} ?selected=${y === this.viewYear}>${y}</option>
298
+ `)}
299
+ </select>
300
+ </div>
301
+ <div class="grid" @mouseleave=${this.handleMouseLeave}>
302
+ <div class="row head">
303
+ ${DAY_LABELS.map(d => html`<div class="dow">${d}</div>`)}
304
+ </div>
305
+ ${this.weekGrid.map(week => html`
306
+ <div class="row">
307
+ ${week.map(date => {
308
+ const outside = date.getMonth() !== this.viewMonth;
309
+ const isToday = this.isSameDay(date, today);
310
+ const isSelected = !this.isRange && this.isSameDay(date, single);
311
+ const isStart = this.isRange && this.isSameDay(date, rangeStart);
312
+ const isEnd = this.isRange && this.isSameDay(date, rangeEnd);
313
+ const inRange = this.isRange && this.isWithinRange(date, rangeStart, rangeEnd);
314
+ const disabled = this.isDisabledDate(date);
315
+ const isPreview = this.isRange && !rawEnd && (isStart || isEnd || inRange) && !isSelected;
316
+ const classes = [
317
+ 'day',
318
+ outside ? 'outside' : '',
319
+ isToday ? 'today' : '',
320
+ isSelected ? 'selected' : '',
321
+ isStart ? 'range-start' : '',
322
+ isEnd && !isStart ? 'range-end' : '',
323
+ inRange ? 'in-range' : '',
324
+ isPreview ? 'preview' : '',
325
+ disabled ? 'disabled' : ''
326
+ ].filter(Boolean).join(' ');
327
+ return html`
328
+ <button
329
+ type="button"
330
+ class="no-btn ${classes}"
331
+ ?disabled=${disabled || this.disabled}
332
+ aria-selected=${isSelected || isStart || isEnd ? 'true' : 'false'}
333
+ @click=${() => this.handleDayClick(date)}
334
+ @mouseenter=${() => this.handleDayHover(date)}
335
+ >${date.getDate()}</button>
336
+ `;
337
+ })}
338
+ </div>
339
+ `)}
340
+ </div>
341
+ `;
342
+ }
343
+
344
+ /*
345
+ Styles
346
+ */
347
+ static styles = css`
348
+ :host {
349
+ --day_size: 2rem;
350
+ --day_radius: var(--radius);
351
+ --day_bg__selected: var(--c_primary);
352
+ --day_tc__selected: white;
353
+ --day_bg__range: var(--c_bg__alt);
354
+ --day_bg__hover: var(--c_bg__alt);
355
+
356
+ display: inline-block;
357
+ border: 1px solid var(--c_border);
358
+ border-radius: var(--radius);
359
+ padding: 0.5rem;
360
+ background: var(--c_bg);
361
+ user-select: none;
362
+ }
363
+ :host([disabled]) {
364
+ opacity: 0.5;
365
+ pointer-events: none;
366
+ }
367
+ .header {
368
+ display: flex;
369
+ align-items: center;
370
+ gap: 0.25rem;
371
+ padding: 0.25rem;
372
+ margin-bottom: 0.25rem;
373
+ }
374
+ .month-select,
375
+ .year-select {
376
+ font-weight: 600;
377
+ width: auto;
378
+ }
379
+ .month-select {
380
+ flex: 1;
381
+ }
382
+ .grid {
383
+ display: flex;
384
+ flex-direction: column;
385
+ }
386
+ .row {
387
+ display: grid;
388
+ grid-template-columns: repeat(7, var(--day_size));
389
+ }
390
+ .row.head {
391
+ margin-bottom: 0.25rem;
392
+ }
393
+ .dow {
394
+ display: flex;
395
+ align-items: center;
396
+ justify-content: center;
397
+ font-size: 0.75rem;
398
+ color: var(--tc_muted);
399
+ font-weight: 500;
400
+ height: var(--day_size);
401
+ }
402
+ .day {
403
+ appearance: none;
404
+ background: transparent;
405
+ border: 1px solid transparent;
406
+ border-radius: var(--day_radius);
407
+ width: var(--day_size);
408
+ height: var(--day_size);
409
+ cursor: pointer;
410
+ color: var(--tc);
411
+ font: inherit;
412
+ font-size: 0.875rem;
413
+ padding: 0;
414
+ position: relative;
415
+ display: inline-flex;
416
+ align-items: center;
417
+ justify-content: center;
418
+ transition: background var(--animation_ms), color var(--animation_ms);
419
+ }
420
+ .day:hover:not(:disabled):not(.selected):not(.range-start):not(.range-end) {
421
+ background: var(--day_bg__hover);
422
+ }
423
+ .day:focus-visible {
424
+ outline: none;
425
+ border-color: var(--c_primary);
426
+ box-shadow: var(--focus_shadow);
427
+ z-index: 1;
428
+ }
429
+ .day.outside {
430
+ color: var(--tc_muted);
431
+ opacity: 0.5;
432
+ }
433
+ .day.today {
434
+ font-weight: 700;
435
+ border-color: var(--c_primary);
436
+ }
437
+ .day.selected,
438
+ .day.in-range,
439
+ .day.range-start,
440
+ .day.range-end {
441
+ background: var(--day_bg__selected);
442
+ color: var(--day_tc__selected);
443
+ border-color: transparent;
444
+ }
445
+ .day.in-range {
446
+ border-radius: 0;
447
+ }
448
+ .day.range-start:not(.range-end) {
449
+ border-top-right-radius: 0;
450
+ border-bottom-right-radius: 0;
451
+ }
452
+ .day.range-end:not(.range-start) {
453
+ border-top-left-radius: 0;
454
+ border-bottom-left-radius: 0;
455
+ }
456
+ .day.outside.in-range,
457
+ .day.outside.range-start,
458
+ .day.outside.range-end {
459
+ opacity: 0.6;
460
+ }
461
+ .day.preview.in-range,
462
+ .day.preview.range-start,
463
+ .day.preview.range-end {
464
+ opacity: 0.75;
465
+ }
466
+ .day:disabled {
467
+ opacity: 0.3;
468
+ cursor: not-allowed;
469
+ }
470
+ `;
471
+ }
472
+
473
+ customElements.define('k-calendar', Calendar);
@@ -0,0 +1,137 @@
1
+ import { html, css } from '../lit-all.min.js';
2
+ import ShadowComponent from './ShadowComponent.js';
3
+
4
+ export default class Time extends ShadowComponent {
5
+ static formAssociated = true;
6
+
7
+ static properties = {
8
+ value: { type: String, reflect: true },
9
+ name: { type: String, reflect: true },
10
+ increment: { type: Number, reflect: true },
11
+ military: { type: Boolean, reflect: true },
12
+ disabled: { type: Boolean, reflect: true },
13
+ required: { type: Boolean, reflect: true }
14
+ };
15
+
16
+ /*
17
+ Lifecycle Callbacks
18
+ */
19
+ constructor() {
20
+ super();
21
+ this.internals = this.attachInternals();
22
+ this.value = '';
23
+ this.name = '';
24
+ this.increment = 1;
25
+ this.military = false;
26
+ this.disabled = false;
27
+ this.required = false;
28
+ }
29
+
30
+ updated(changedProperties) {
31
+ super.updated(changedProperties);
32
+ this.internals.setFormValue(this.value);
33
+ if(this.required && !this.value){
34
+ this.internals.setValidity(
35
+ { valueMissing: true },
36
+ 'Please enter a time.',
37
+ this.shadowRoot?.querySelector('input')
38
+ );
39
+ } else {
40
+ this.internals.setValidity({});
41
+ }
42
+ if(changedProperties.has('value') && changedProperties.get('value') !== undefined){
43
+ this.dispatchEvent(new CustomEvent('change', {
44
+ detail: { value: this.value },
45
+ bubbles: true
46
+ }));
47
+ }
48
+ }
49
+
50
+ /*
51
+ Utility
52
+ */
53
+ get stepSeconds() {
54
+ return Math.max(1, Math.floor(this.increment || 1)) * 60;
55
+ }
56
+
57
+ roundToIncrement = (raw) => {
58
+ if(!raw) return '';
59
+ const [hStr, mStr] = raw.split(':');
60
+ let hour = Number(hStr);
61
+ let minute = Number(mStr);
62
+ if(isNaN(hour) || isNaN(minute)) return raw;
63
+ const inc = Math.max(1, Math.floor(this.increment || 1));
64
+ minute = Math.round(minute / inc) * inc;
65
+ if(minute >= 60){
66
+ minute -= 60;
67
+ hour = (hour + 1) % 24;
68
+ }
69
+ return `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
70
+ };
71
+
72
+ /*
73
+ Event Handlers
74
+ */
75
+ handleNativeChange = (e) => {
76
+ if(this.disabled) return;
77
+ this.value = e.target.value || '';
78
+ };
79
+
80
+ handleBlur = (e) => {
81
+ if(this.disabled) return;
82
+ const rounded = this.roundToIncrement(e.target.value);
83
+ if(rounded !== this.value){
84
+ this.value = rounded;
85
+ }
86
+ };
87
+
88
+ /*
89
+ Rendering
90
+ */
91
+ render() {
92
+ return html`
93
+ <input
94
+ type="time"
95
+ .value=${this.value || ''}
96
+ step=${this.stepSeconds}
97
+ lang=${this.military ? 'en-GB' : 'en-US'}
98
+ ?disabled=${this.disabled}
99
+ ?required=${this.required}
100
+ @change=${this.handleNativeChange}
101
+ @blur=${this.handleBlur}
102
+ />
103
+ `;
104
+ }
105
+
106
+ /*
107
+ Styles
108
+ */
109
+ static styles = css`
110
+ :host {
111
+ display: inline-block;
112
+ }
113
+ :host([disabled]) {
114
+ opacity: 0.5;
115
+ pointer-events: none;
116
+ }
117
+ input {
118
+ padding: var(--spacer_h) var(--spacer);
119
+ border: 1px solid var(--c_border);
120
+ border-radius: var(--radius);
121
+ background: var(--c_bg);
122
+ color: var(--tc);
123
+ font: inherit;
124
+ outline: none;
125
+ box-sizing: border-box;
126
+ transition: border-color var(--animation_ms);
127
+ }
128
+ input:focus {
129
+ border-color: var(--c_primary);
130
+ }
131
+ input::-webkit-calendar-picker-indicator {
132
+ display: none;
133
+ }
134
+ `;
135
+ }
136
+
137
+ customElements.define('k-time', Time);