@kodaris/krubble-components 1.0.3 → 1.0.5
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/custom-elements.json +174 -66
- package/dist/button/button.d.ts +34 -3
- package/dist/button/button.d.ts.map +1 -1
- package/dist/button/button.js +193 -38
- package/dist/button/button.js.map +1 -1
- package/dist/krubble.bundled.js +244 -49
- package/dist/krubble.bundled.js.map +1 -1
- package/dist/krubble.bundled.min.js +165 -78
- package/dist/krubble.bundled.min.js.map +1 -1
- package/dist/krubble.umd.js +244 -49
- package/dist/krubble.umd.js.map +1 -1
- package/dist/krubble.umd.min.js +166 -79
- package/dist/krubble.umd.min.js.map +1 -1
- package/dist/snackbar/snackbar.d.ts +16 -6
- package/dist/snackbar/snackbar.d.ts.map +1 -1
- package/dist/snackbar/snackbar.js +52 -12
- package/dist/snackbar/snackbar.js.map +1 -1
- package/package.json +1 -1
package/dist/krubble.bundled.js
CHANGED
|
@@ -396,16 +396,19 @@ var __decorate$5 = (undefined && undefined.__decorate) || function (decorators,
|
|
|
396
396
|
* A customizable button component.
|
|
397
397
|
*
|
|
398
398
|
* @slot - The button content
|
|
399
|
-
* @csspart button - The button element
|
|
400
399
|
* @fires click - Fired when the button is clicked
|
|
401
400
|
*/
|
|
402
401
|
let KRButton = class KRButton extends i$1 {
|
|
403
402
|
constructor() {
|
|
404
403
|
super(...arguments);
|
|
405
404
|
/**
|
|
406
|
-
* The button variant
|
|
405
|
+
* The button variant (shape)
|
|
407
406
|
*/
|
|
408
|
-
this.variant = '
|
|
407
|
+
this.variant = 'flat';
|
|
408
|
+
/**
|
|
409
|
+
* The button color
|
|
410
|
+
*/
|
|
411
|
+
this.color = 'primary';
|
|
409
412
|
/**
|
|
410
413
|
* The button size
|
|
411
414
|
*/
|
|
@@ -414,104 +417,256 @@ let KRButton = class KRButton extends i$1 {
|
|
|
414
417
|
* Whether the button is disabled
|
|
415
418
|
*/
|
|
416
419
|
this.disabled = false;
|
|
420
|
+
this._state = 'idle';
|
|
421
|
+
this._stateText = '';
|
|
422
|
+
this._handleKeydown = (e) => {
|
|
423
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
424
|
+
e.preventDefault();
|
|
425
|
+
this.click();
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
}
|
|
429
|
+
connectedCallback() {
|
|
430
|
+
super.connectedCallback();
|
|
431
|
+
this.setAttribute('role', 'button');
|
|
432
|
+
this.setAttribute('tabindex', '0');
|
|
433
|
+
this.addEventListener('keydown', this._handleKeydown);
|
|
434
|
+
}
|
|
435
|
+
disconnectedCallback() {
|
|
436
|
+
super.disconnectedCallback();
|
|
437
|
+
this.removeEventListener('keydown', this._handleKeydown);
|
|
438
|
+
}
|
|
439
|
+
/**
|
|
440
|
+
* Shows a loading spinner and disables the button.
|
|
441
|
+
*/
|
|
442
|
+
showLoading() {
|
|
443
|
+
this._clearStateTimeout();
|
|
444
|
+
this._state = 'loading';
|
|
445
|
+
this._stateText = '';
|
|
446
|
+
}
|
|
447
|
+
/**
|
|
448
|
+
* Shows a success state with optional custom text.
|
|
449
|
+
* @param text - Text to display (default: "Saved")
|
|
450
|
+
* @param duration - Duration in ms before auto-reset (default: 2000)
|
|
451
|
+
*/
|
|
452
|
+
showSuccess(text = 'Success', duration = 2000) {
|
|
453
|
+
this._clearStateTimeout();
|
|
454
|
+
this._state = 'success';
|
|
455
|
+
this._stateText = text;
|
|
456
|
+
this._stateTimeout = window.setTimeout(() => this.reset(), duration);
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Shows an error state with optional custom text.
|
|
460
|
+
* @param text - Text to display (default: "Error")
|
|
461
|
+
* @param duration - Duration in ms before auto-reset (default: 2000)
|
|
462
|
+
*/
|
|
463
|
+
showError(text = 'Error', duration = 2000) {
|
|
464
|
+
this._clearStateTimeout();
|
|
465
|
+
this._state = 'error';
|
|
466
|
+
this._stateText = text;
|
|
467
|
+
this._stateTimeout = window.setTimeout(() => this.reset(), duration);
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Resets the button to its idle state.
|
|
471
|
+
*/
|
|
472
|
+
reset() {
|
|
473
|
+
this._clearStateTimeout();
|
|
474
|
+
this._state = 'idle';
|
|
475
|
+
this._stateText = '';
|
|
476
|
+
}
|
|
477
|
+
_clearStateTimeout() {
|
|
478
|
+
if (this._stateTimeout) {
|
|
479
|
+
clearTimeout(this._stateTimeout);
|
|
480
|
+
this._stateTimeout = undefined;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
updated(changedProperties) {
|
|
484
|
+
// Reflect state classes to host
|
|
485
|
+
this.classList.toggle('kr-button--loading', this._state === 'loading');
|
|
486
|
+
this.classList.toggle('kr-button--success', this._state === 'success');
|
|
487
|
+
this.classList.toggle('kr-button--error', this._state === 'error');
|
|
488
|
+
this.classList.toggle(`kr-button--${this.variant}`, true);
|
|
489
|
+
this.classList.toggle(`kr-button--${this.color}`, true);
|
|
490
|
+
this.classList.toggle('kr-button--small', this.size === 'small');
|
|
491
|
+
this.classList.toggle('kr-button--large', this.size === 'large');
|
|
417
492
|
}
|
|
418
493
|
render() {
|
|
419
|
-
const sizeClass = this.size !== 'medium' ? this.size : '';
|
|
420
494
|
return b `
|
|
421
|
-
<
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
495
|
+
<slot></slot>
|
|
496
|
+
${this._state !== 'idle'
|
|
497
|
+
? b `<span class="state-overlay">
|
|
498
|
+
${this._state === 'loading'
|
|
499
|
+
? b `<span class="spinner"></span>`
|
|
500
|
+
: this._stateText}
|
|
501
|
+
</span>`
|
|
502
|
+
: ''}
|
|
428
503
|
`;
|
|
429
504
|
}
|
|
430
505
|
};
|
|
431
506
|
KRButton.styles = i$4 `
|
|
432
507
|
:host {
|
|
433
|
-
display: inline-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
508
|
+
display: inline-flex;
|
|
509
|
+
position: relative;
|
|
510
|
+
align-items: center;
|
|
511
|
+
justify-content: center;
|
|
437
512
|
font-family: inherit;
|
|
438
513
|
font-size: 14px;
|
|
439
514
|
font-weight: 400;
|
|
440
515
|
letter-spacing: 0.01em;
|
|
441
516
|
padding: 0 22px;
|
|
442
517
|
height: 36px;
|
|
443
|
-
line-height: 36px;
|
|
444
518
|
border: none;
|
|
445
519
|
border-radius: 20px;
|
|
446
520
|
cursor: pointer;
|
|
447
521
|
transition: background 0.15s ease;
|
|
522
|
+
user-select: none;
|
|
523
|
+
box-sizing: border-box;
|
|
448
524
|
}
|
|
449
525
|
|
|
450
|
-
|
|
451
|
-
|
|
526
|
+
:host([disabled]),
|
|
527
|
+
:host(.kr-button--loading),
|
|
528
|
+
:host(.kr-button--success),
|
|
529
|
+
:host(.kr-button--error) {
|
|
530
|
+
cursor: not-allowed;
|
|
531
|
+
pointer-events: none;
|
|
452
532
|
}
|
|
453
533
|
|
|
454
|
-
button:
|
|
534
|
+
:host([disabled]:not(.kr-button--loading):not(.kr-button--success):not(.kr-button--error)) {
|
|
455
535
|
opacity: 0.5;
|
|
456
|
-
cursor: not-allowed;
|
|
457
536
|
}
|
|
458
537
|
|
|
459
|
-
/*
|
|
460
|
-
|
|
538
|
+
/* Flat + Primary (default) */
|
|
539
|
+
:host,
|
|
540
|
+
:host(.kr-button--flat.kr-button--primary) {
|
|
461
541
|
background: #163052;
|
|
462
542
|
color: white;
|
|
463
543
|
}
|
|
464
544
|
|
|
465
|
-
|
|
545
|
+
:host(:hover:not([disabled])),
|
|
546
|
+
:host(.kr-button--flat.kr-button--primary:hover:not([disabled])) {
|
|
466
547
|
background: #0e1f35;
|
|
467
548
|
}
|
|
468
549
|
|
|
469
|
-
|
|
550
|
+
/* Flat + Secondary */
|
|
551
|
+
:host(.kr-button--flat.kr-button--secondary) {
|
|
470
552
|
background: #f3f4f6;
|
|
471
553
|
color: #374151;
|
|
472
554
|
}
|
|
473
555
|
|
|
474
|
-
button.secondary:hover:not(
|
|
556
|
+
:host(.kr-button--flat.kr-button--secondary:hover:not([disabled])) {
|
|
475
557
|
background: #e5e7eb;
|
|
476
558
|
}
|
|
477
559
|
|
|
478
|
-
|
|
560
|
+
/* Outline + Primary */
|
|
561
|
+
:host(.kr-button--outline.kr-button--primary) {
|
|
562
|
+
background: transparent;
|
|
563
|
+
border: 1px solid #163052;
|
|
564
|
+
color: #163052;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
:host(.kr-button--outline.kr-button--primary:hover:not([disabled])) {
|
|
568
|
+
background: rgba(22, 48, 82, 0.05);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/* Outline + Secondary */
|
|
572
|
+
:host(.kr-button--outline.kr-button--secondary) {
|
|
479
573
|
background: transparent;
|
|
480
574
|
border: 1px solid #d1d5db;
|
|
481
575
|
color: #374151;
|
|
482
|
-
box-shadow: none;
|
|
483
576
|
}
|
|
484
577
|
|
|
485
|
-
button.
|
|
578
|
+
:host(.kr-button--outline.kr-button--secondary:hover:not([disabled])) {
|
|
486
579
|
background: #f9fafb;
|
|
487
580
|
border-color: #9ca3af;
|
|
488
|
-
box-shadow: none;
|
|
489
581
|
}
|
|
490
582
|
|
|
491
583
|
/* Sizes */
|
|
492
|
-
button
|
|
584
|
+
:host(.kr-button--small) {
|
|
493
585
|
font-size: 13px;
|
|
494
586
|
height: 28px;
|
|
495
|
-
line-height: 28px;
|
|
496
587
|
padding: 0 16px;
|
|
497
588
|
}
|
|
498
589
|
|
|
499
|
-
button
|
|
500
|
-
font-size:
|
|
590
|
+
:host(.kr-button--large) {
|
|
591
|
+
font-size: 16px;
|
|
501
592
|
height: 44px;
|
|
502
|
-
line-height: 44px;
|
|
503
593
|
padding: 0 24px;
|
|
594
|
+
border-radius: 30px;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
/* State colors */
|
|
598
|
+
:host(.kr-button--success) {
|
|
599
|
+
background: #198754 !important;
|
|
600
|
+
color: white !important;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
:host(.kr-button--error) {
|
|
604
|
+
background: rgb(220, 53, 69) !important;
|
|
605
|
+
color: white !important;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/* Content */
|
|
609
|
+
:host(.kr-button--loading) slot,
|
|
610
|
+
:host(.kr-button--success) slot,
|
|
611
|
+
:host(.kr-button--error) slot {
|
|
612
|
+
visibility: hidden;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/* State overlay */
|
|
616
|
+
.state-overlay {
|
|
617
|
+
position: absolute;
|
|
618
|
+
inset: 0;
|
|
619
|
+
display: flex;
|
|
620
|
+
align-items: center;
|
|
621
|
+
justify-content: center;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
/* Spinner */
|
|
625
|
+
@keyframes kr-spin {
|
|
626
|
+
to {
|
|
627
|
+
transform: rotate(360deg);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.spinner {
|
|
632
|
+
width: 12px;
|
|
633
|
+
height: 12px;
|
|
634
|
+
border: 2.5px solid currentColor;
|
|
635
|
+
border-top-color: transparent;
|
|
636
|
+
border-radius: 50%;
|
|
637
|
+
animation: kr-spin 0.6s linear infinite;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
:host(.kr-button--small) .spinner {
|
|
641
|
+
width: 10px;
|
|
642
|
+
height: 10px;
|
|
643
|
+
border-width: 2px;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
:host(.kr-button--large) .spinner {
|
|
647
|
+
width: 16px;
|
|
648
|
+
height: 16px;
|
|
649
|
+
border-width: 3px;
|
|
504
650
|
}
|
|
505
651
|
`;
|
|
506
652
|
__decorate$5([
|
|
507
|
-
n({ type: String })
|
|
653
|
+
n({ type: String, reflect: true })
|
|
508
654
|
], KRButton.prototype, "variant", void 0);
|
|
509
655
|
__decorate$5([
|
|
510
|
-
n({ type: String })
|
|
656
|
+
n({ type: String, reflect: true })
|
|
657
|
+
], KRButton.prototype, "color", void 0);
|
|
658
|
+
__decorate$5([
|
|
659
|
+
n({ type: String, reflect: true })
|
|
511
660
|
], KRButton.prototype, "size", void 0);
|
|
512
661
|
__decorate$5([
|
|
513
|
-
n({ type: Boolean })
|
|
662
|
+
n({ type: Boolean, reflect: true })
|
|
514
663
|
], KRButton.prototype, "disabled", void 0);
|
|
664
|
+
__decorate$5([
|
|
665
|
+
r$1()
|
|
666
|
+
], KRButton.prototype, "_state", void 0);
|
|
667
|
+
__decorate$5([
|
|
668
|
+
r$1()
|
|
669
|
+
], KRButton.prototype, "_stateText", void 0);
|
|
515
670
|
KRButton = __decorate$5([
|
|
516
671
|
t$1('kr-button')
|
|
517
672
|
], KRButton);
|
|
@@ -1127,10 +1282,13 @@ var KRSnackbar_1;
|
|
|
1127
1282
|
* @example
|
|
1128
1283
|
* ```ts
|
|
1129
1284
|
* // Show a success message
|
|
1130
|
-
* KRSnackbar.show('Item saved successfully',
|
|
1285
|
+
* KRSnackbar.show({ message: 'Item saved successfully', type: 'success' });
|
|
1286
|
+
*
|
|
1287
|
+
* // Show a message with title
|
|
1288
|
+
* KRSnackbar.show({ title: 'Upload Complete', message: 'Your file has been uploaded.', type: 'success' });
|
|
1131
1289
|
*
|
|
1132
1290
|
* // Show an error that stays until manually dismissed
|
|
1133
|
-
* KRSnackbar.show('Failed to save',
|
|
1291
|
+
* KRSnackbar.show({ message: 'Failed to save', type: 'error', duration: 0 });
|
|
1134
1292
|
* ```
|
|
1135
1293
|
*/
|
|
1136
1294
|
let KRSnackbar = KRSnackbar_1 = class KRSnackbar extends i$1 {
|
|
@@ -1141,6 +1299,10 @@ let KRSnackbar = KRSnackbar_1 = class KRSnackbar extends i$1 {
|
|
|
1141
1299
|
* The snackbar type/severity. Controls the color scheme and icon.
|
|
1142
1300
|
*/
|
|
1143
1301
|
this.type = 'info';
|
|
1302
|
+
/**
|
|
1303
|
+
* Optional title to display above the message.
|
|
1304
|
+
*/
|
|
1305
|
+
this.title = '';
|
|
1144
1306
|
/**
|
|
1145
1307
|
* The message to display in the snackbar.
|
|
1146
1308
|
*/
|
|
@@ -1152,16 +1314,24 @@ let KRSnackbar = KRSnackbar_1 = class KRSnackbar extends i$1 {
|
|
|
1152
1314
|
this.duration = 5000;
|
|
1153
1315
|
}
|
|
1154
1316
|
/**
|
|
1155
|
-
* Show a snackbar with the given
|
|
1156
|
-
* @param
|
|
1157
|
-
* @param options - Optional configuration for type and duration
|
|
1317
|
+
* Show a snackbar with the given options.
|
|
1318
|
+
* @param options - Configuration including message, optional title, type, and duration
|
|
1158
1319
|
* @returns The created snackbar element
|
|
1159
1320
|
*/
|
|
1160
|
-
static show(
|
|
1321
|
+
static show(options) {
|
|
1161
1322
|
const snackbar = document.createElement('kr-snackbar');
|
|
1162
|
-
snackbar.message = message;
|
|
1163
|
-
snackbar.
|
|
1164
|
-
snackbar.
|
|
1323
|
+
snackbar.message = options.message;
|
|
1324
|
+
snackbar.title = options.title ?? '';
|
|
1325
|
+
snackbar.type = options.type ?? 'info';
|
|
1326
|
+
if (options.duration !== undefined) {
|
|
1327
|
+
snackbar.duration = options.duration;
|
|
1328
|
+
}
|
|
1329
|
+
else if (snackbar.type === 'error') {
|
|
1330
|
+
snackbar.duration = 0;
|
|
1331
|
+
}
|
|
1332
|
+
else {
|
|
1333
|
+
snackbar.duration = 5000;
|
|
1334
|
+
}
|
|
1165
1335
|
document.body.appendChild(snackbar);
|
|
1166
1336
|
return snackbar;
|
|
1167
1337
|
}
|
|
@@ -1170,6 +1340,9 @@ let KRSnackbar = KRSnackbar_1 = class KRSnackbar extends i$1 {
|
|
|
1170
1340
|
// Set role and type class on host
|
|
1171
1341
|
this.setAttribute('role', 'alert');
|
|
1172
1342
|
this.classList.add(`kr-snackbar--${this.type}`);
|
|
1343
|
+
if (this.title) {
|
|
1344
|
+
this.classList.add('kr-snackbar--has-title');
|
|
1345
|
+
}
|
|
1173
1346
|
// Add to active snackbars and update positions
|
|
1174
1347
|
KRSnackbar_1.activeSnackbars.push(this);
|
|
1175
1348
|
this.updatePositions();
|
|
@@ -1195,7 +1368,7 @@ let KRSnackbar = KRSnackbar_1 = class KRSnackbar extends i$1 {
|
|
|
1195
1368
|
}
|
|
1196
1369
|
}
|
|
1197
1370
|
updatePositions() {
|
|
1198
|
-
let bottomOffset =
|
|
1371
|
+
let bottomOffset = 24;
|
|
1199
1372
|
for (const snackbar of KRSnackbar_1.activeSnackbars) {
|
|
1200
1373
|
snackbar.style.bottom = `${bottomOffset}px`;
|
|
1201
1374
|
bottomOffset += snackbar.offsetHeight + 8;
|
|
@@ -1221,7 +1394,10 @@ let KRSnackbar = KRSnackbar_1 = class KRSnackbar extends i$1 {
|
|
|
1221
1394
|
};
|
|
1222
1395
|
return b `
|
|
1223
1396
|
${icons[this.type]}
|
|
1224
|
-
<div class="
|
|
1397
|
+
<div class="content">
|
|
1398
|
+
${this.title ? b `<div class="title">${this.title}</div>` : ''}
|
|
1399
|
+
<div class="message">${this.message}</div>
|
|
1400
|
+
</div>
|
|
1225
1401
|
<button
|
|
1226
1402
|
class="dismiss"
|
|
1227
1403
|
type="button"
|
|
@@ -1261,6 +1437,10 @@ KRSnackbar.styles = i$4 `
|
|
|
1261
1437
|
animation: slideIn 0.2s ease-out;
|
|
1262
1438
|
}
|
|
1263
1439
|
|
|
1440
|
+
:host(.kr-snackbar--has-title) {
|
|
1441
|
+
align-items: flex-start;
|
|
1442
|
+
}
|
|
1443
|
+
|
|
1264
1444
|
@keyframes slideIn {
|
|
1265
1445
|
from {
|
|
1266
1446
|
opacity: 0;
|
|
@@ -1332,10 +1512,22 @@ KRSnackbar.styles = i$4 `
|
|
|
1332
1512
|
flex-shrink: 0;
|
|
1333
1513
|
width: 20px;
|
|
1334
1514
|
height: 20px;
|
|
1515
|
+
margin-top: 1px;
|
|
1335
1516
|
}
|
|
1336
1517
|
|
|
1337
|
-
.
|
|
1518
|
+
.content {
|
|
1338
1519
|
flex: 1;
|
|
1520
|
+
min-width: 0;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
.title {
|
|
1524
|
+
font-size: 14px;
|
|
1525
|
+
font-weight: 600;
|
|
1526
|
+
color: #000000;
|
|
1527
|
+
margin: 0 0 2px 0;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
.message {
|
|
1339
1531
|
font-size: 14px;
|
|
1340
1532
|
color: #000000;
|
|
1341
1533
|
margin: 0;
|
|
@@ -1372,6 +1564,9 @@ KRSnackbar.activeSnackbars = [];
|
|
|
1372
1564
|
__decorate$1([
|
|
1373
1565
|
n({ type: String })
|
|
1374
1566
|
], KRSnackbar.prototype, "type", void 0);
|
|
1567
|
+
__decorate$1([
|
|
1568
|
+
n({ type: String })
|
|
1569
|
+
], KRSnackbar.prototype, "title", void 0);
|
|
1375
1570
|
__decorate$1([
|
|
1376
1571
|
n({ type: String })
|
|
1377
1572
|
], KRSnackbar.prototype, "message", void 0);
|