@kodaris/krubble-components 1.0.69 → 1.0.70

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.
@@ -475,18 +475,34 @@ let KRButton = class KRButton extends i$2 {
475
475
  * @attr icon-position
476
476
  */
477
477
  this.iconPosition = 'left';
478
+ /**
479
+ * When true and options are provided, renders as a split button with
480
+ * separate primary action and dropdown trigger zones.
481
+ */
482
+ this.split = false;
478
483
  this._state = 'idle';
479
484
  this._stateText = '';
480
485
  this._dropdownOpened = false;
481
486
  this._handleHostClick = (e) => {
487
+ if (this.split && this.options.length) {
488
+ return;
489
+ }
482
490
  if (this.options.length) {
483
491
  e.stopPropagation();
484
492
  this._toggleDropdown();
485
493
  }
486
494
  };
487
495
  this._handleKeydown = (e) => {
496
+ if (e.key === 'Escape' && this._dropdownOpened) {
497
+ this._dropdownOpened = false;
498
+ return;
499
+ }
488
500
  if (e.key === 'Enter' || e.key === ' ') {
489
501
  e.preventDefault();
502
+ if (this.split && this.options.length) {
503
+ this.dispatchEvent(new MouseEvent('click', { bubbles: true, composed: true }));
504
+ return;
505
+ }
490
506
  if (this.options.length) {
491
507
  this._toggleDropdown();
492
508
  }
@@ -494,8 +510,11 @@ let KRButton = class KRButton extends i$2 {
494
510
  this.click();
495
511
  }
496
512
  }
497
- if (e.key === 'Escape' && this._dropdownOpened) {
498
- this._dropdownOpened = false;
513
+ if (this.split && this.options.length && e.key === 'ArrowDown') {
514
+ e.preventDefault();
515
+ if (!this._dropdownOpened) {
516
+ this._toggleDropdown();
517
+ }
499
518
  }
500
519
  };
501
520
  this._handleClickOutside = (e) => {
@@ -518,6 +537,20 @@ let KRButton = class KRButton extends i$2 {
518
537
  this.removeEventListener('click', this._handleHostClick);
519
538
  document.removeEventListener('click', this._handleClickOutside);
520
539
  }
540
+ _handleSplitPrimaryClick(e) {
541
+ e.stopPropagation();
542
+ if (this._dropdownOpened) {
543
+ this._dropdownOpened = false;
544
+ }
545
+ this.dispatchEvent(new MouseEvent('click', {
546
+ bubbles: true,
547
+ composed: true,
548
+ }));
549
+ }
550
+ _handleSplitTriggerClick(e) {
551
+ e.stopPropagation();
552
+ this._toggleDropdown();
553
+ }
521
554
  _toggleDropdown() {
522
555
  this._dropdownOpened = !this._dropdownOpened;
523
556
  if (this._dropdownOpened) {
@@ -630,8 +663,38 @@ let KRButton = class KRButton extends i$2 {
630
663
  this.classList.toggle(`kr-button--${this.color}`, true);
631
664
  this.classList.toggle('kr-button--small', this.size === 'small');
632
665
  this.classList.toggle('kr-button--large', this.size === 'large');
666
+ this.classList.toggle('kr-button--split', this.split && !!this.options.length);
633
667
  }
634
668
  render() {
669
+ if (this.split && this.options.length) {
670
+ return b `
671
+ <div class="split-primary" @click=${(e) => this._handleSplitPrimaryClick(e)}>
672
+ <span class="content">
673
+ <slot name="icon"></slot>
674
+ <slot></slot>
675
+ </span>
676
+ ${this._state !== 'idle'
677
+ ? b `<span class="state-overlay">
678
+ ${this._state === 'loading'
679
+ ? b `<span class="spinner"></span>`
680
+ : this._stateText}
681
+ </span>`
682
+ : A}
683
+ </div>
684
+ <div class="split-divider"></div>
685
+ <div class="split-trigger" @click=${(e) => this._handleSplitTriggerClick(e)}>
686
+ <svg class="caret" xmlns="http://www.w3.org/2000/svg" height="20" width="20" viewBox="0 0 24 24" fill="currentColor"><path d="M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z"/></svg>
687
+ </div>
688
+ <div class="dropdown ${this._dropdownOpened ? 'dropdown--opened' : ''}">
689
+ ${this.options.map(option => b `
690
+ <button
691
+ class="dropdown-item"
692
+ @click=${(e) => this._handleOptionClick(option, e)}
693
+ >${option.label}</button>
694
+ `)}
695
+ </div>
696
+ `;
697
+ }
635
698
  const content = b `
636
699
  <span class="content">
637
700
  <slot name="icon"></slot>
@@ -931,6 +994,154 @@ KRButton.styles = i$5 `
931
994
  width: 22px;
932
995
  height: 22px;
933
996
  }
997
+
998
+ /* ========================
999
+ Split Button
1000
+ ======================== */
1001
+
1002
+ :host(.kr-button--split) {
1003
+ padding: 0;
1004
+ pointer-events: none;
1005
+ }
1006
+
1007
+ .split-primary,
1008
+ .split-trigger {
1009
+ display: inline-flex;
1010
+ align-items: center;
1011
+ justify-content: center;
1012
+ height: 100%;
1013
+ cursor: pointer;
1014
+ pointer-events: auto;
1015
+ }
1016
+
1017
+ .split-primary {
1018
+ padding: 0 16px 0 22px;
1019
+ border-radius: 20px 0 0 20px;
1020
+ position: relative;
1021
+ flex: 1;
1022
+ }
1023
+
1024
+ .split-trigger {
1025
+ padding: 0 14px 0 8px;
1026
+ border-radius: 0 20px 20px 0;
1027
+ }
1028
+
1029
+ .split-trigger .caret {
1030
+ margin: 0;
1031
+ }
1032
+
1033
+ .split-divider {
1034
+ width: 1px;
1035
+ height: 100%;
1036
+ flex-shrink: 0;
1037
+ }
1038
+
1039
+ .dropdown {
1040
+ pointer-events: auto;
1041
+ }
1042
+
1043
+ /* Split: zone hover — flat primary */
1044
+ :host(.kr-button--flat.kr-button--primary) .split-primary:hover,
1045
+ :host(.kr-button--flat.kr-button--primary) .split-trigger:hover {
1046
+ background: #0e1f35;
1047
+ }
1048
+
1049
+ /* Split: zone hover — flat secondary */
1050
+ :host(.kr-button--flat.kr-button--secondary) .split-primary:hover,
1051
+ :host(.kr-button--flat.kr-button--secondary) .split-trigger:hover {
1052
+ background: #e5e7eb;
1053
+ }
1054
+
1055
+ /* Split: zone hover — flat danger */
1056
+ :host(.kr-button--flat.kr-button--danger) .split-primary:hover,
1057
+ :host(.kr-button--flat.kr-button--danger) .split-trigger:hover {
1058
+ background: #b91c1c;
1059
+ }
1060
+
1061
+ /* Split: zone hover — outline primary */
1062
+ :host(.kr-button--outline.kr-button--primary) .split-primary:hover,
1063
+ :host(.kr-button--outline.kr-button--primary) .split-trigger:hover {
1064
+ background: rgba(22, 48, 82, 0.05);
1065
+ }
1066
+
1067
+ /* Split: zone hover — outline secondary */
1068
+ :host(.kr-button--outline.kr-button--secondary) .split-primary:hover,
1069
+ :host(.kr-button--outline.kr-button--secondary) .split-trigger:hover {
1070
+ background: #f9fafb;
1071
+ }
1072
+
1073
+ /* Split: zone hover — outline danger */
1074
+ :host(.kr-button--outline.kr-button--danger) .split-primary:hover,
1075
+ :host(.kr-button--outline.kr-button--danger) .split-trigger:hover {
1076
+ background: rgba(219, 38, 39, 0.05);
1077
+ }
1078
+
1079
+ /* Split: divider colors — flat variants */
1080
+ :host(.kr-button--flat.kr-button--primary) .split-divider {
1081
+ background: rgba(255, 255, 255, 0.3);
1082
+ }
1083
+
1084
+ :host(.kr-button--flat.kr-button--secondary) .split-divider {
1085
+ background: rgba(0, 0, 0, 0.15);
1086
+ }
1087
+
1088
+ :host(.kr-button--flat.kr-button--danger) .split-divider {
1089
+ background: rgba(255, 255, 255, 0.3);
1090
+ }
1091
+
1092
+ /* Split: divider colors — outline variants */
1093
+ :host(.kr-button--outline.kr-button--primary) .split-divider {
1094
+ background: #163052;
1095
+ }
1096
+
1097
+ :host(.kr-button--outline.kr-button--secondary) .split-divider {
1098
+ background: #d1d5db;
1099
+ }
1100
+
1101
+ :host(.kr-button--outline.kr-button--danger) .split-divider {
1102
+ background: rgb(219, 38, 39);
1103
+ }
1104
+
1105
+ /* Split: size small */
1106
+ :host(.kr-button--split.kr-button--small) .split-primary {
1107
+ padding: 0 12px 0 16px;
1108
+ }
1109
+
1110
+ :host(.kr-button--split.kr-button--small) .split-trigger {
1111
+ padding: 0 10px;
1112
+ }
1113
+
1114
+ /* Split: size large */
1115
+ :host(.kr-button--split.kr-button--large) .split-primary {
1116
+ padding: 0 18px 0 24px;
1117
+ border-radius: 30px 0 0 30px;
1118
+ }
1119
+
1120
+ :host(.kr-button--split.kr-button--large) .split-trigger {
1121
+ padding: 0 16px;
1122
+ border-radius: 0 30px 30px 0;
1123
+ }
1124
+
1125
+ /* Split: disabled */
1126
+ :host([disabled]) .split-primary,
1127
+ :host([disabled]) .split-trigger {
1128
+ cursor: not-allowed;
1129
+ pointer-events: none;
1130
+ }
1131
+
1132
+ /* Split: loading/success/error — overlay in primary zone only */
1133
+ :host(.kr-button--split.kr-button--loading) .split-primary .content,
1134
+ :host(.kr-button--split.kr-button--success) .split-primary .content,
1135
+ :host(.kr-button--split.kr-button--error) .split-primary .content {
1136
+ visibility: hidden;
1137
+ }
1138
+
1139
+ :host(.kr-button--split.kr-button--loading) .split-trigger,
1140
+ :host(.kr-button--split.kr-button--success) .split-trigger,
1141
+ :host(.kr-button--split.kr-button--error) .split-trigger {
1142
+ pointer-events: none;
1143
+ opacity: 0.6;
1144
+ }
934
1145
  `;
935
1146
  __decorate$l([
936
1147
  n$1({ type: String, reflect: true })
@@ -956,6 +1167,9 @@ __decorate$l([
956
1167
  __decorate$l([
957
1168
  n$1({ type: String, reflect: true, attribute: 'icon-position' })
958
1169
  ], KRButton.prototype, "iconPosition", void 0);
1170
+ __decorate$l([
1171
+ n$1({ type: Boolean, reflect: true })
1172
+ ], KRButton.prototype, "split", void 0);
959
1173
  __decorate$l([
960
1174
  r$1()
961
1175
  ], KRButton.prototype, "_state", void 0);