q2-tecton-elements 1.10.2 → 1.10.6

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 (130) hide show
  1. package/dist/cjs/click-elsewhere.cjs.entry.js +1 -1
  2. package/dist/cjs/{icons-fa5f4367.js → icons-4595ee47.js} +311 -2
  3. package/dist/cjs/{index-6b2c271e.js → index-c2e53804.js} +19 -0
  4. package/dist/cjs/{index-14348270.js → index-f4153f5a.js} +18 -4
  5. package/dist/cjs/loader.cjs.js +2 -2
  6. package/dist/cjs/q2-avatar.cjs.entry.js +3 -3
  7. package/dist/cjs/q2-btn_2.cjs.entry.js +3 -3
  8. package/dist/cjs/q2-calendar.cjs.entry.js +7 -3
  9. package/dist/cjs/q2-carousel-pane.cjs.entry.js +2 -2
  10. package/dist/cjs/q2-carousel.cjs.entry.js +2 -2
  11. package/dist/cjs/q2-checkbox-group.cjs.entry.js +2 -2
  12. package/dist/cjs/q2-checkbox.cjs.entry.js +2 -2
  13. package/dist/cjs/q2-dropdown-item.cjs.entry.js +2 -2
  14. package/dist/cjs/q2-dropdown.cjs.entry.js +2 -2
  15. package/dist/cjs/q2-editable-field.cjs.entry.js +2 -2
  16. package/dist/cjs/q2-icon.cjs.entry.js +3 -3
  17. package/dist/cjs/q2-input.cjs.entry.js +3 -3
  18. package/dist/cjs/q2-loading-element.cjs.entry.js +2 -2
  19. package/dist/cjs/q2-loc.cjs.entry.js +2 -2
  20. package/dist/cjs/q2-message.cjs.entry.js +21 -3
  21. package/dist/cjs/q2-optgroup.cjs.entry.js +2 -2
  22. package/dist/cjs/q2-option.cjs.entry.js +1 -1
  23. package/dist/cjs/q2-radio-group.cjs.entry.js +8 -4
  24. package/dist/cjs/q2-radio.cjs.entry.js +2 -2
  25. package/dist/cjs/q2-section.cjs.entry.js +3 -9
  26. package/dist/cjs/q2-select.cjs.entry.js +2 -2
  27. package/dist/cjs/q2-stepper-pane.cjs.entry.js +2 -2
  28. package/dist/cjs/q2-stepper.cjs.entry.js +2 -2
  29. package/dist/cjs/q2-tab-container.cjs.entry.js +85 -115
  30. package/dist/cjs/q2-tab-pane.cjs.entry.js +1 -1
  31. package/dist/cjs/q2-tecton-elements.cjs.js +2 -2
  32. package/dist/cjs/q2-textarea.cjs.entry.js +2 -2
  33. package/dist/cjs/{shapes-a7595d72.js → shapes-086c0365.js} +1 -1
  34. package/dist/cjs/tecton-tab-pane.cjs.entry.js +12 -1
  35. package/dist/collection/components/q2-avatar/index.js +2 -2
  36. package/dist/collection/components/q2-calendar/index.js +5 -1
  37. package/dist/collection/components/q2-icon/icons.js +310 -1
  38. package/dist/collection/components/q2-input/styles.css +5 -4
  39. package/dist/collection/components/q2-message/index.js +48 -8
  40. package/dist/collection/components/q2-message/styles.css +68 -75
  41. package/dist/collection/components/q2-radio-group/index.js +7 -3
  42. package/dist/collection/components/q2-radio-group/styles.css +3 -0
  43. package/dist/collection/components/q2-section/index.js +1 -7
  44. package/dist/collection/components/q2-tab-container/index.js +97 -125
  45. package/dist/collection/components/q2-tab-container/styles.css +118 -98
  46. package/dist/collection/components/tecton-tab-pane/index.js +11 -0
  47. package/dist/collection/utils/index.js +9 -3
  48. package/dist/esm/click-elsewhere.entry.js +1 -1
  49. package/dist/esm/{icons-17612675.js → icons-3ee662ea.js} +311 -2
  50. package/dist/esm/{index-da24669a.js → index-476b86cc.js} +17 -5
  51. package/dist/esm/{index-5fa3e016.js → index-be8376c0.js} +19 -0
  52. package/dist/esm/loader.js +2 -2
  53. package/dist/esm/q2-avatar.entry.js +3 -3
  54. package/dist/esm/q2-btn_2.entry.js +3 -3
  55. package/dist/esm/q2-calendar.entry.js +7 -3
  56. package/dist/esm/q2-carousel-pane.entry.js +2 -2
  57. package/dist/esm/q2-carousel.entry.js +2 -2
  58. package/dist/esm/q2-checkbox-group.entry.js +2 -2
  59. package/dist/esm/q2-checkbox.entry.js +2 -2
  60. package/dist/esm/q2-dropdown-item.entry.js +2 -2
  61. package/dist/esm/q2-dropdown.entry.js +2 -2
  62. package/dist/esm/q2-editable-field.entry.js +2 -2
  63. package/dist/esm/q2-icon.entry.js +3 -3
  64. package/dist/esm/q2-input.entry.js +3 -3
  65. package/dist/esm/q2-loading-element.entry.js +2 -2
  66. package/dist/esm/q2-loc.entry.js +2 -2
  67. package/dist/esm/q2-message.entry.js +21 -3
  68. package/dist/esm/q2-optgroup.entry.js +2 -2
  69. package/dist/esm/q2-option.entry.js +1 -1
  70. package/dist/esm/q2-radio-group.entry.js +8 -4
  71. package/dist/esm/q2-radio.entry.js +2 -2
  72. package/dist/esm/q2-section.entry.js +3 -9
  73. package/dist/esm/q2-select.entry.js +2 -2
  74. package/dist/esm/q2-stepper-pane.entry.js +2 -2
  75. package/dist/esm/q2-stepper.entry.js +2 -2
  76. package/dist/esm/q2-tab-container.entry.js +85 -115
  77. package/dist/esm/q2-tab-pane.entry.js +1 -1
  78. package/dist/esm/q2-tecton-elements.js +2 -2
  79. package/dist/esm/q2-textarea.entry.js +2 -2
  80. package/dist/esm/{shapes-073c5aad.js → shapes-81c11dfe.js} +1 -1
  81. package/dist/esm/tecton-tab-pane.entry.js +12 -1
  82. package/dist/q2-tecton-elements/{p-c92e3bc2.entry.js → p-01e00610.entry.js} +1 -1
  83. package/dist/q2-tecton-elements/p-080839ed.js +1 -0
  84. package/dist/q2-tecton-elements/{p-576509e6.entry.js → p-1fc4e6f6.entry.js} +1 -1
  85. package/dist/q2-tecton-elements/{p-6f570344.js → p-25a5f691.js} +1 -1
  86. package/dist/q2-tecton-elements/p-27353237.entry.js +1 -0
  87. package/dist/q2-tecton-elements/{p-2c2a5d58.entry.js → p-3e100450.entry.js} +1 -1
  88. package/dist/q2-tecton-elements/{p-7520656d.entry.js → p-428d15fd.entry.js} +1 -1
  89. package/dist/q2-tecton-elements/{p-3f2590c0.entry.js → p-4830affe.entry.js} +1 -1
  90. package/dist/q2-tecton-elements/{p-64eef8d1.entry.js → p-48fc317d.entry.js} +1 -1
  91. package/dist/q2-tecton-elements/{p-aaa55918.js → p-4cd00f1a.js} +1 -1
  92. package/dist/q2-tecton-elements/{p-3b80823a.entry.js → p-5222b792.entry.js} +1 -1
  93. package/dist/q2-tecton-elements/p-5469c1e9.entry.js +1 -0
  94. package/dist/q2-tecton-elements/{p-82b24667.entry.js → p-61c0e5fd.entry.js} +1 -1
  95. package/dist/q2-tecton-elements/{p-37d281b7.entry.js → p-74c1a311.entry.js} +1 -1
  96. package/dist/q2-tecton-elements/{p-65894494.entry.js → p-784af485.entry.js} +1 -1
  97. package/dist/q2-tecton-elements/{p-e3a27b97.entry.js → p-7c99a58b.entry.js} +1 -1
  98. package/dist/q2-tecton-elements/p-7f74b629.entry.js +1 -0
  99. package/dist/q2-tecton-elements/{p-ebee91e2.entry.js → p-831a461f.entry.js} +1 -1
  100. package/dist/q2-tecton-elements/{p-905a22d5.entry.js → p-84c05db6.entry.js} +1 -1
  101. package/dist/q2-tecton-elements/{p-2f2bbed9.entry.js → p-84c52d3b.entry.js} +2 -2
  102. package/dist/q2-tecton-elements/{p-dd33b297.entry.js → p-9024859f.entry.js} +1 -1
  103. package/dist/q2-tecton-elements/{p-c14e0622.entry.js → p-997e4c7e.entry.js} +1 -1
  104. package/dist/q2-tecton-elements/{p-7c06467f.entry.js → p-a166b9a6.entry.js} +1 -1
  105. package/dist/q2-tecton-elements/p-a224bc9c.entry.js +1 -0
  106. package/dist/q2-tecton-elements/{p-891ca6f8.entry.js → p-a9bdd814.entry.js} +1 -1
  107. package/dist/q2-tecton-elements/{p-fa6e46e2.js → p-c90a6016.js} +1 -1
  108. package/dist/q2-tecton-elements/{p-86116f5c.entry.js → p-d1d040ef.entry.js} +1 -1
  109. package/dist/q2-tecton-elements/{p-8b4f6d3f.entry.js → p-d893fcf2.entry.js} +1 -1
  110. package/dist/q2-tecton-elements/{p-4d283b84.entry.js → p-da7cca07.entry.js} +1 -1
  111. package/dist/q2-tecton-elements/p-df182f61.entry.js +1 -0
  112. package/dist/q2-tecton-elements/p-f17761da.entry.js +1 -0
  113. package/dist/q2-tecton-elements/{p-5289f040.entry.js → p-f5e074f8.entry.js} +1 -1
  114. package/dist/q2-tecton-elements/q2-tecton-elements.esm.js +1 -1
  115. package/dist/types/components/q2-calendar/index.d.ts +1 -1
  116. package/dist/types/components/q2-message/index.d.ts +6 -2
  117. package/dist/types/components/q2-radio-group/index.d.ts +1 -1
  118. package/dist/types/components/q2-section/index.d.ts +0 -1
  119. package/dist/types/components/q2-tab-container/index.d.ts +11 -16
  120. package/dist/types/components/tecton-tab-pane/index.d.ts +1 -0
  121. package/dist/types/components.d.ts +7 -6
  122. package/dist/types/utils/index.d.ts +2 -0
  123. package/package.json +2 -2
  124. package/dist/q2-tecton-elements/p-076b95fd.entry.js +0 -1
  125. package/dist/q2-tecton-elements/p-2a28baa9.entry.js +0 -1
  126. package/dist/q2-tecton-elements/p-6ed006a7.entry.js +0 -1
  127. package/dist/q2-tecton-elements/p-8e863fbc.js +0 -1
  128. package/dist/q2-tecton-elements/p-98bb1355.entry.js +0 -1
  129. package/dist/q2-tecton-elements/p-9b420e22.entry.js +0 -1
  130. package/dist/q2-tecton-elements/p-d0d605dc.entry.js +0 -1
@@ -64,113 +64,106 @@ button {
64
64
  visibility: hidden;
65
65
  }
66
66
 
67
-
68
67
  :host {
69
- display: block;
68
+ display: block;
70
69
  }
71
70
 
72
71
  :host([hidden]) {
73
- display: none;
72
+ display: none;
74
73
  }
75
74
 
76
75
  .message {
77
- border-left-width: var(--tct-message-bar-width, var(--app-scale-1, 5px));
78
- border-left-style: solid;
79
- display: flex;
80
- align-items: flex-start;
81
- background: var(--tct-message-bg, var(--tct-gray-14, var(--t-gray-14, var(--tct-gray-l3, var(--app-gray-l3, #f2f2f2)))));
82
- color: var(--tct-message-font-color, inherit);
83
- box-shadow: var(--tct-message-box-shadow, inherit);
84
- border-radius: var(--tct-message-border-radius, inherit);
76
+ border-left-width: var(--tct-message-bar-width, var(--t-message-bar-width, var(--app-scale-1, 5px)));
77
+ border-left-style: solid;
78
+ display: grid;
79
+ gap: var(--tct-scale-1, var(--app-scale-1, 5px));
80
+ align-items: flex-start;
81
+ background: var(--tct-message-bg, var(--t-message-bg, var(--tct-gray-14, var(--t-gray-14, var(--tct-gray-l3, var(--app-gray-l3, #f2f2f2))))));
82
+ color: var(--tct-message-font-color, var(--t-message-font-color, inherit));
83
+ box-shadow: var(--tct-message-box-shadow, var(--t-message-box-shadow, inherit));
84
+ border-radius: var(--tct-message-border-radius, var(--t-message-border-radius, inherit));
85
+ }
86
+
87
+ .message-icon {
88
+ width: 24px;
89
+ }
90
+
91
+ .message-content {
92
+ flex: 1;
85
93
  }
86
94
 
87
95
  ::slotted(ul) {
88
- padding-left: var(--tct-scale-l3, var(--app-scale-3, 15px));
96
+ padding-left: var(--tct-scale-l3, var(--app-scale-3, 15px));
89
97
  }
90
98
 
91
99
  :host(:not([appearance])),
92
- :host([appearance='standard']) {
93
- margin: var(--tct-scale-l3, var(--app-scale-3, 15px)) 0;
100
+ :host([appearance=standard]) {
101
+ margin: var(--tct-scale-l3, var(--app-scale-3, 15px)) 0;
94
102
  }
95
-
96
103
  :host(:not([appearance])) .message,
97
- :host([appearance='standard']) .message {
98
- padding: var(--tct-message-padding, var(--app-scale-3, 15px));
104
+ :host([appearance=standard]) .message {
105
+ grid-template-columns: 24px 1fr;
106
+ --comp-padding: var(--tct-message-padding, var(--t-message-padding, var(--app-scale-3, 15px)));
107
+ padding: var(--comp-padding);
108
+ padding-top: calc(var(--comp-padding) - var(--tct-scale-1, var(--app-scale-1, 5px)));
109
+ padding-left: calc(var(--comp-padding) - var(--tct-scale-2, var(--app-scale-2, 10px)));
110
+ }
111
+ :host(:not([appearance])) .message-content,
112
+ :host([appearance=standard]) .message-content {
113
+ padding-top: var(--tct-scale-1, var(--app-scale-1, 5px));
99
114
  }
100
-
101
115
  :host(:not([appearance])) ::slotted(ul),
102
- :host([appearance='standard']) ::slotted(ul) {
103
- margin: var(--tct-scale-l3, var(--app-scale-3, 15px)) 0;
116
+ :host([appearance=standard]) ::slotted(ul) {
117
+ margin: var(--tct-scale-l3, var(--app-scale-3, 15px)) 0;
104
118
  }
105
119
 
106
- :host([appearance='minimal']) {
107
- margin: 0;
120
+ :host([appearance=minimal]) {
121
+ margin: 0;
108
122
  }
109
- :host([appearance='minimal']) .message {
110
- padding: var(--tct-message-minimal-padding, var(--app-scale-2, 10px));
123
+ :host([appearance=minimal]) .message {
124
+ padding: var(--tct-message-minimal-padding, var(--t-message-minimal-padding, var(--app-scale-2, 10px)));
125
+ grid-template-columns: 1fr;
111
126
  }
112
- :host([appearance='minimal']) ::slotted(ul) {
113
- margin: var(--tct-scale-1, var(--app-scale-1, 5px)) 0;
127
+ :host([appearance=minimal]) ::slotted(ul) {
128
+ margin: var(--tct-scale-1, var(--app-scale-1, 5px)) 0;
114
129
  }
115
130
 
116
131
  :host(:not([type])) .message,
117
- :host([type='info']) .message {
118
- border-left-color: var(--tct-stoplight-info, var(--const-stoplight-info, #0079c1));
132
+ :host([type=info]) .message {
133
+ border-left-color: var(--tct-stoplight-info, var(--const-stoplight-info, #0079c1));
119
134
  }
120
-
121
135
  :host(:not([type])) .message-icon,
122
- :host([type='info']) .message-icon {
123
- --tct-icon-stroke-primary: var(--tct-stoplight-info, var(--const-stoplight-info, #0079c1));
124
- --tct-icon-stroke-secondary: var(--tct-stoplight-info, var(--const-stoplight-info, #0079c1));
125
- }
126
-
127
- :host([type='success']) .message {
128
- border-left-color: var(--tct-stoplight-success, var(--const-stoplight-success, #0e8a00));
129
- }
130
- :host([type='success']) .message-icon {
131
- --tct-icon-stroke-primary: var(
132
- --tct-stoplight-success,
133
- var(--const-stoplight-success, #0e8a00)
134
- );
135
- --tct-icon-stroke-secondary: var(
136
- --tct-stoplight-success,
137
- var(--const-stoplight-success, #0e8a00)
138
- );
139
- }
140
-
141
- :host([type='warning']) .message {
142
- border-left-color: var(--tct-stoplight-warning, var(--const-stoplight-warning, #f0b400));
136
+ :host(:not([type])) .message-icon,
137
+ :host([type=info]) .message-icon,
138
+ :host([type=info]) .message-icon {
139
+ --tct-icon-stroke-primary: var(--tct-stoplight-info, var(--const-stoplight-info, #0079c1));
140
+ --tct-icon-stroke-secondary: var(--tct-stoplight-info, var(--const-stoplight-info, #0079c1));
143
141
  }
144
142
 
145
- :host([type='warning']) .message-icon {
146
- --tct-icon-stroke-primary: var(
147
- --tct-stoplight-warning,
148
- var(--const-stoplight-warning, #f0b400)
149
- );
150
- --tct-icon-stroke-secondary: var(
151
- --tct-stoplight-warning,
152
- var(--const-stoplight-warning, #f0b400)
153
- );
143
+ :host([type=success]) .message {
144
+ border-left-color: var(--tct-stoplight-success, var(--const-stoplight-success, #0e8a00));
154
145
  }
155
-
156
- :host([type='error']) .message,
157
- :host([type='danger']) .message {
158
- border-left-color: var(--tct-stoplight-error, var(--const-stoplight-alert, #c30000));
146
+ :host([type=success]) .message-icon {
147
+ --tct-icon-stroke-primary: var(--tct-stoplight-success, var(--const-stoplight-success, #0e8a00));
148
+ --tct-icon-stroke-secondary: var(--tct-stoplight-success, var(--const-stoplight-success, #0e8a00));
159
149
  }
160
150
 
161
- :host([type='error']) .message-icon,
162
- :host([type='danger']) .message-icon {
163
- --tct-icon-stroke-primary: var(--tct-stoplight-error, var(--const-stoplight-alert, #c30000));
164
- --tct-icon-stroke-secondary: var(--tct-stoplight-error, var(--const-stoplight-alert, #c30000));
151
+ :host([type=warning]) .message {
152
+ border-left-color: var(--tct-stoplight-warning, var(--const-stoplight-warning, #f0b400));
165
153
  }
166
-
167
- .message-icon {
168
- width: 24px;
169
- margin-top: calc(var(--tct-scale-1, var(--app-scale-1, 5px)) * -1);
170
- margin-right: var(--tct-scale-1, var(--app-scale-1, 5px));
171
- margin-left: calc(var(--tct-scale-2, var(--app-scale-2, 10px)) * -1);
154
+ :host([type=warning]) .message-icon {
155
+ --tct-icon-stroke-primary: var(--tct-stoplight-warning, var(--const-stoplight-warning, #f0b400));
156
+ --tct-icon-stroke-secondary: var(--tct-stoplight-warning, var(--const-stoplight-warning, #f0b400));
172
157
  }
173
158
 
174
- .message-content {
175
- flex: 1;
159
+ :host([type=error]) .message,
160
+ :host([type=danger]) .message {
161
+ border-left-color: var(--tct-stoplight-error, var(--const-stoplight-alert, #c30000));
176
162
  }
163
+ :host([type=error]) .message-icon,
164
+ :host([type=error]) .message-icon,
165
+ :host([type=danger]) .message-icon,
166
+ :host([type=danger]) .message-icon {
167
+ --tct-icon-stroke-primary: var(--tct-stoplight-error, var(--const-stoplight-alert, #c30000));
168
+ --tct-icon-stroke-secondary: var(--tct-stoplight-error, var(--const-stoplight-alert, #c30000));
169
+ }
@@ -70,7 +70,11 @@ export class Q2RadioGroup {
70
70
  }
71
71
  inputDom() {
72
72
  if (this.tilelayout) {
73
- return (h("div", { class: this.tileAlignment === 'left' ? 'flexed left' : 'flexed' },
73
+ const { tileAlignment } = this;
74
+ const alignment = ['left', 'center', 'right'].includes(tileAlignment)
75
+ ? tileAlignment
76
+ : 'center';
77
+ return (h("div", { class: `flexed ${alignment}` },
74
78
  h("slot", null)));
75
79
  }
76
80
  else {
@@ -193,8 +197,8 @@ export class Q2RadioGroup {
193
197
  "type": "string",
194
198
  "mutable": false,
195
199
  "complexType": {
196
- "original": "string",
197
- "resolved": "string",
200
+ "original": "'left' | 'center' | 'right'",
201
+ "resolved": "\"center\" | \"left\" | \"right\"",
198
202
  "references": {}
199
203
  },
200
204
  "required": false,
@@ -133,3 +133,6 @@ legend.sr-only {
133
133
  .flexed.left {
134
134
  justify-content: left;
135
135
  }
136
+ .flexed.right {
137
+ justify-content: right;
138
+ }
@@ -102,12 +102,6 @@ export class Q2Section {
102
102
  const animateClass = this.animating ? ' animate' : '';
103
103
  return `q2-section-wrapper${collapsibleClass}${stateClass}${headerClass}${animateClass}`;
104
104
  }
105
- get btnLabel() {
106
- const label = loc(this.label);
107
- return this.expanded
108
- ? `${loc('tecton.element.section.collapse')} ${label}`
109
- : `${loc('tecton.element.section.expand')} ${label}`;
110
- }
111
105
  get slottedContentHeight() {
112
106
  const content = this.contentContainer;
113
107
  return `${content.offsetHeight || 0}px`;
@@ -158,7 +152,7 @@ export class Q2Section {
158
152
  !this.hasYieldedHeader && !!this.label ? (h("h2", { class: "title" }, loc(this.label))) : (''),
159
153
  h("div", { class: "q2-section-header-slot-wrapper" },
160
154
  h("slot", { name: "q2-section-header" }))),
161
- this.collapsible && !this.noCollapseIcon ? (h("q2-btn", { class: `q2-section-content-toggle ${this.expanded ? 'expanded' : 'collapsed'}`, label: this.btnLabel, ariaExpanded: !!this.expanded, ariaControls: this.contentId, ariaHasPopup: true, "test-id": "toggleButton", "hide-label": true, onClick: this.onHeaderClick },
155
+ this.collapsible && !this.noCollapseIcon ? (h("q2-btn", { class: `q2-section-content-toggle ${this.expanded ? 'expanded' : 'collapsed'}`, label: this.label, ariaExpanded: !!this.expanded, ariaControls: this.contentId, "test-id": "toggleButton", "hide-label": true, onClick: this.onHeaderClick },
162
156
  h("q2-icon", { type: "chevron-up", class: "toggle-icon" }))) : ('')),
163
157
  h("div", { class: "q2-section-content-wrapper", id: this.contentId, "aria-labelledby": this.titleId, role: "region", onAnimationStart: this.onAnimationStart, onAnimationEnd: this.onAnimationEnd },
164
158
  h("div", { class: "q2-section-content" },
@@ -1,4 +1,4 @@
1
- import { Component, Prop, Element, Event, State, Listen, Watch, h } from '@stencil/core';
1
+ import { Component, Prop, Element, Event, State, Listen, Watch, h, Fragment } from '@stencil/core';
2
2
  import { createGuid, loc, addSmoothScrollPolyfill } from 'src/utils';
3
3
  addSmoothScrollPolyfill();
4
4
  const userAgent = navigator.userAgent.toLowerCase();
@@ -11,6 +11,9 @@ export class Q2TabContainer {
11
11
  this.lastScrolled = new Date(null).getTime();
12
12
  this.hasLeft = false;
13
13
  this.hasRight = false;
14
+ this.scrollEnabled = false;
15
+ this.showScrollLeft = false;
16
+ this.showScrollRight = false;
14
17
  ///////// Actions /////////
15
18
  this.updateTabData = () => {
16
19
  this.updateTabPaneProps();
@@ -24,131 +27,97 @@ export class Q2TabContainer {
24
27
  });
25
28
  };
26
29
  this.setTabs = () => {
27
- this.tabs = this.tabPanes.map(({ label, value }) => {
28
- return {
29
- label: (label && loc(label)) || '',
30
- value
31
- };
32
- });
30
+ this.tabs = this.tabPanes.map(({ label, value }) => ({
31
+ label: (label && loc(label)) || '',
32
+ value
33
+ }));
33
34
  };
34
35
  this.onTabClick = (event) => {
36
+ const isAlreadySelected = this.value === event.target.dataset.value;
37
+ if (isAlreadySelected)
38
+ return;
35
39
  this.change.emit({
36
40
  value: event.target.dataset.value
37
41
  });
38
42
  };
39
43
  this.onTabKeyDown = (event) => {
40
44
  const value = event.target.dataset.value;
41
- if (event.key === 'ArrowRight' || event.key === 'Right') {
42
- this.moveToAdjacentTab(value, 'next');
43
- return;
44
- }
45
- if (event.key === 'ArrowLeft' || event.key === 'Left') {
46
- this.moveToAdjacentTab(value, 'prev');
47
- return;
48
- }
49
- if (event.code === 'Space' || event.code === 'Enter') {
50
- // to prevent triggering scroll when press the space key
51
- event.preventDefault();
52
- this.change.emit({ value });
53
- return;
45
+ switch (event.key) {
46
+ case 'ArrowRight':
47
+ event.preventDefault();
48
+ this.moveToAdjacentTab(value, 'next');
49
+ break;
50
+ case 'ArrowLeft':
51
+ event.preventDefault();
52
+ this.moveToAdjacentTab(value, 'prev');
53
+ break;
54
+ case 'Home':
55
+ event.preventDefault();
56
+ this.moveToAdjacentTab(value, 'first');
57
+ break;
58
+ case 'End':
59
+ event.preventDefault();
60
+ this.moveToAdjacentTab(value, 'last');
61
+ break;
62
+ case 'Space':
63
+ case 'Enter':
64
+ event.preventDefault();
65
+ this.change.emit({ value });
66
+ break;
54
67
  }
55
68
  };
56
69
  this.moveToAdjacentTab = (value, direction) => {
57
70
  let index = this.tabs.map(({ value }) => value).indexOf(value);
58
- let newIndex = direction === 'next'
59
- ? Math.min(index + 1, this.tabs.length - 1)
60
- : Math.max(index - 1, 0);
61
- if (index !== newIndex) {
62
- const focusedTab = this.moveFocus(newIndex);
63
- // Scroll only if it overflows
64
- if (this.tabList.scrollWidth > this.tabList.clientWidth) {
65
- // Scroll only if it's first or last tab
66
- if (newIndex !== 0 && newIndex !== this.tabs.length - 1) {
67
- this.scrollByKeyboard(direction, focusedTab);
68
- }
69
- else {
70
- // first or last element: just show or hide nav arrow
71
- this.onTabScroll(direction);
72
- }
73
- }
71
+ let newIndex;
72
+ switch (direction) {
73
+ case 'next':
74
+ newIndex = Math.min(index + 1, this.tabs.length - 1);
75
+ break;
76
+ case 'prev':
77
+ newIndex = Math.max(index - 1, 0);
78
+ break;
79
+ case 'first':
80
+ newIndex = 0;
81
+ break;
82
+ case 'last':
83
+ newIndex = this.tabs.length - 1;
84
+ break;
74
85
  }
86
+ if (index === newIndex)
87
+ return;
88
+ this.moveFocus(newIndex, false);
75
89
  };
76
90
  this.moveFocus = (index, preventScroll = true) => {
77
91
  const focusedValue = this.tabs[index].value;
78
- const focusedTab = this.hostElement.shadowRoot.querySelector(`.tab-list a[data-value="${focusedValue}"]`);
92
+ const focusedTab = this.listElement.querySelector(`[data-value="${focusedValue}"]`);
79
93
  focusedTab.focus({ preventScroll });
94
+ const left = focusedTab.offsetLeft - this.listElement.clientWidth / 2;
95
+ this.listElement.scrollTo({
96
+ left,
97
+ behavior: 'smooth'
98
+ });
80
99
  return focusedTab;
81
100
  };
82
- this.calculateKeyboardScroll = (direction, focusedTab) => {
83
- const { left: tabListLeft } = this.tabList.getBoundingClientRect();
84
- const { left: focusedTabLeft } = focusedTab.getBoundingClientRect();
85
- const arrowWidth = 46;
86
- let scrollAmount = 0;
87
- // check how much focused tab overflows
88
- if (direction === 'next' &&
89
- focusedTabLeft + focusedTab.clientWidth >
90
- tabListLeft + this.tabList.clientWidth + arrowWidth) {
91
- scrollAmount =
92
- this.tabList.scrollLeft +
93
- arrowWidth +
94
- (focusedTabLeft + focusedTab.clientWidth) -
95
- (tabListLeft + this.tabList.clientWidth);
96
- }
97
- else if (direction === 'prev' && focusedTabLeft + arrowWidth < tabListLeft) {
98
- scrollAmount = this.tabList.scrollLeft - arrowWidth + (focusedTabLeft - tabListLeft);
99
- }
100
- return scrollAmount;
101
+ this.checkScrollState = () => {
102
+ const { scrollLeft, scrollWidth, clientWidth } = this.listElement;
103
+ this.scrollEnabled = scrollWidth > clientWidth;
104
+ this.showScrollLeft = !!scrollLeft;
105
+ this.showScrollRight = scrollWidth !== scrollLeft + clientWidth;
101
106
  };
102
- this.scrollByKeyboard = (direction, focusedTab) => {
103
- const scrollAmount = this.calculateKeyboardScroll(direction, focusedTab);
104
- if (scrollAmount !== 0) {
105
- this.tabList.scroll({ left: scrollAmount, behavior: 'smooth' });
106
- // wait to finish scroll then show or hide nav arrow
107
- setTimeout(() => this.onTabScroll(), 100);
108
- }
109
- };
110
- this.calculateTabScroll = ({ direction, scrollWidth, clientWidth, scrollLeft }) => {
111
- const directions = { prev: -1, next: 1 };
112
- // step 0 means no scroll needed, re-render or resize can trigger this
113
- const step = directions[direction] || 0;
114
- const scrollRate = 0.5; // half of visual width
115
- const delta = Math.round(clientWidth * scrollRate);
116
- const newScrollLeft = scrollLeft + step * delta;
117
- const scrolled = clientWidth + newScrollLeft;
118
- const hasLeft = newScrollLeft > 0;
119
- const hasRight = scrollWidth > scrolled;
120
- return {
121
- newScrollLeft,
122
- hasLeft,
123
- hasRight
124
- };
125
- };
126
- this.onTabScroll = (direction) => {
127
- // throttle under 50ms due to re-rendering & resizing
128
- const now = new Date().getTime();
129
- if (now - this.lastScrolled < 50)
130
- return;
131
- this.lastScrolled = now;
132
- if (!this.tabList)
133
- return;
134
- let { scrollWidth, clientWidth, scrollLeft } = this.tabList;
135
- const { newScrollLeft, hasLeft, hasRight } = this.calculateTabScroll({
136
- direction,
137
- scrollWidth,
138
- clientWidth,
139
- scrollLeft
107
+ this.onScrollBtnClick = (direction) => {
108
+ const scrollAmount = Math.floor(this.listElement.clientWidth / 2);
109
+ this.listElement.scrollBy({
110
+ left: direction === 'left' ? -scrollAmount : scrollAmount,
111
+ behavior: 'smooth'
140
112
  });
141
- this.hasLeft = hasLeft;
142
- this.hasRight = hasRight;
143
- if (direction) {
144
- this.tabList.scroll({ left: newScrollLeft, behavior: 'smooth' });
145
- }
113
+ };
114
+ this.onSlotChange = () => {
115
+ this.checkScrollState();
146
116
  };
147
117
  }
148
118
  resizeIframe() {
149
- return (window.TectonElements &&
150
- window.TectonElements.resizeIframe &&
151
- window.TectonElements.resizeIframe());
119
+ var _a, _b;
120
+ return (_b = (_a = window.TectonElements) === null || _a === void 0 ? void 0 : _a.resizeIframe) === null || _b === void 0 ? void 0 : _b.call(_a);
152
121
  }
153
122
  get tabPanes() {
154
123
  const tabPanes = this.hostElement.querySelectorAll('q2-tab-pane, tecton-tab-pane');
@@ -170,7 +139,7 @@ export class Q2TabContainer {
170
139
  }
171
140
  }
172
141
  onResize() {
173
- this.onTabScroll();
142
+ this.checkScrollState();
174
143
  }
175
144
  onFocus() {
176
145
  // firefox receives focus on overflowed element even if it's not interactive element
@@ -184,25 +153,26 @@ export class Q2TabContainer {
184
153
  const observer = new MutationObserver(this.updateTabData);
185
154
  observer.observe(this.hostElement, { childList: true, attributes: true });
186
155
  this.mutationObserver = observer;
156
+ this.resizeObserver = new ResizeObserver(() => this.checkScrollState());
187
157
  this.updateTabData();
188
158
  }
189
159
  componentDidRender() {
190
160
  this.scheduledAfterRender.forEach(fn => fn());
191
161
  this.scheduledAfterRender = [];
192
162
  this.settled.emit();
193
- this.onTabScroll();
194
163
  }
195
164
  componentDidLoad() {
165
+ this.resizeObserver.observe(this.listElement);
166
+ this.checkScrollState();
196
167
  const index = this.tabs.findIndex(el => el.value === this.value);
197
- // move focus if the value is valid and not the first tab's value
198
- if (index > 0) {
199
- this.scheduledAfterRender.push(() => {
200
- const tab = this.moveFocus(index, false);
201
- tab.blur();
202
- });
203
- }
168
+ this.scheduledAfterRender.push(() => {
169
+ const tab = this.moveFocus(Math.max(index, 0), false);
170
+ this.value = tab.dataset.value;
171
+ tab.blur();
172
+ });
204
173
  }
205
174
  disconnectedCallback() {
175
+ this.resizeObserver.disconnect();
206
176
  this.mutationObserver.disconnect();
207
177
  this.mutationObserver = null;
208
178
  }
@@ -220,30 +190,29 @@ export class Q2TabContainer {
220
190
  }
221
191
  ///////// View Methods /////////
222
192
  render() {
223
- return (h("div", { class: "tab-container" },
224
- h("ul", { class: `tab-list ${this.noPrint ? 'no-print' : ''}`, role: "tablist" },
225
- this.hasLeft && (h("li", { role: "presentation", class: "nav nav-left", onClick: () => this.onTabScroll('prev') },
226
- h("div", { class: "arrow-container" },
227
- h("a", null,
228
- h("q2-icon", { type: "chevron-left" }))))),
229
- this.tabs.map((tab, index) => this.generateTab(tab, index)),
230
- this.hasRight && (h("li", { role: "presentation", class: "nav nav-right", onClick: () => this.onTabScroll('next') },
231
- h("div", { class: "arrow-container" },
232
- h("a", null,
233
- h("q2-icon", { type: "chevron-right" })))))),
193
+ return (h(Fragment, null,
194
+ h("div", { class: "tab-container" },
195
+ this.scrollEnabled && (h(Fragment, null,
196
+ h("div", { class: "gradient-left", hidden: !this.showScrollLeft }),
197
+ h("div", { class: "gradient-right", hidden: !this.showScrollRight }),
198
+ h("q2-btn", { class: "btn-left", hidden: !this.showScrollLeft, onClick: () => this.onScrollBtnClick('left') },
199
+ h("q2-icon", { type: "chevron-left" })),
200
+ h("q2-btn", { class: "btn-right", hidden: !this.showScrollRight, onClick: () => this.onScrollBtnClick('right') },
201
+ h("q2-icon", { type: "chevron-right" })))),
202
+ h("ul", { onScroll: this.checkScrollState, ref: el => (this.listElement = el), class: this.noPrint ? 'no-print' : null, role: "tablist" }, this.tabs.map((tab, index) => this.generateTab(tab, index)))),
234
203
  h("div", { class: "tab-content" },
235
- h("slot", null))));
204
+ h("slot", { onSlotchange: () => this.onSlotChange() }))));
236
205
  }
237
206
  generateTab(tab, index) {
238
207
  const { label, value } = tab;
239
208
  const isSelected = this.selectedTabValue === value;
240
209
  return (h("li", { role: "presentation" },
241
- h("a", { id: `tab-${this.guid}-${index}`, href: "javascript://", "data-value": value, "test-id": "tabLink", tabIndex: isSelected ? 0 : -1, role: "tab", "aria-selected": `${isSelected}`, "aria-controls": `tab-pane-${this.guid}-${index}`, onClick: this.onTabClick, onKeyDown: this.onTabKeyDown }, label)));
210
+ h("button", { id: `tab-${this.guid}-${index}`, "data-value": value, "test-id": "tabLink", tabIndex: isSelected ? 0 : -1, role: "tab", "aria-selected": isSelected ? 'true' : undefined, "aria-controls": `tab-pane-${this.guid}-${index}`, onClick: this.onTabClick, onKeyDown: this.onTabKeyDown }, label)));
242
211
  }
243
212
  static get is() { return "q2-tab-container"; }
244
213
  static get encapsulation() { return "shadow"; }
245
214
  static get originalStyleUrls() { return {
246
- "$": ["styles.css"]
215
+ "$": ["styles.scss"]
247
216
  }; }
248
217
  static get styleUrls() { return {
249
218
  "$": ["styles.css"]
@@ -339,6 +308,9 @@ export class Q2TabContainer {
339
308
  static get states() { return {
340
309
  "hasLeft": {},
341
310
  "hasRight": {},
311
+ "scrollEnabled": {},
312
+ "showScrollLeft": {},
313
+ "showScrollRight": {},
342
314
  "tabs": {}
343
315
  }; }
344
316
  static get events() { return [{