@oicl/openbridge-webcomponents 2.0.0-next.83 → 2.0.0-next.85

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 (26) hide show
  1. package/bundle/openbridge-webcomponents.bundle.js +1223 -493
  2. package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
  3. package/custom-elements.json +642 -196
  4. package/dist/components/tab-item/tab-item.css.js +8 -1
  5. package/dist/components/tab-item/tab-item.css.js.map +1 -1
  6. package/dist/components/tab-item/tab-item.d.ts +44 -0
  7. package/dist/components/tab-item/tab-item.d.ts.map +1 -1
  8. package/dist/components/tab-item/tab-item.js +44 -25
  9. package/dist/components/tab-item/tab-item.js.map +1 -1
  10. package/dist/components/tab-row/tab-row.d.ts +23 -9
  11. package/dist/components/tab-row/tab-row.d.ts.map +1 -1
  12. package/dist/components/tab-row/tab-row.js +24 -7
  13. package/dist/components/tab-row/tab-row.js.map +1 -1
  14. package/dist/components/textbox/textbox.css.js +29 -5
  15. package/dist/components/textbox/textbox.css.js.map +1 -1
  16. package/dist/components/textbox/textbox.d.ts +5 -0
  17. package/dist/components/textbox/textbox.d.ts.map +1 -1
  18. package/dist/components/textbox/textbox.js +6 -1
  19. package/dist/components/textbox/textbox.js.map +1 -1
  20. package/dist/navigation-instruments/readout-list-item/readout-list-item.css.js +611 -230
  21. package/dist/navigation-instruments/readout-list-item/readout-list-item.css.js.map +1 -1
  22. package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts +280 -61
  23. package/dist/navigation-instruments/readout-list-item/readout-list-item.d.ts.map +1 -1
  24. package/dist/navigation-instruments/readout-list-item/readout-list-item.js +529 -247
  25. package/dist/navigation-instruments/readout-list-item/readout-list-item.js.map +1 -1
  26. package/package.json +1 -1
@@ -119,11 +119,18 @@ const compentStyle = css`* {
119
119
  color: var(--on-flat-disabled-color);
120
120
  }
121
121
 
122
+ .wrapper .badges {
123
+ display: flex;
124
+ align-items: center;
125
+ gap: 4px;
126
+ position: relative;
127
+ }
128
+
122
129
  .wrapper .badge {
123
130
  position: relative;
124
131
  }
125
132
 
126
- .wrapper:not(.hug) .badge {
133
+ .wrapper:not(.hug) .badges {
127
134
  right: 0;
128
135
  }
129
136
 
@@ -1 +1 @@
1
- {"version":3,"file":"tab-item.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"tab-item.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,7 +1,26 @@
1
1
  import { LitElement } from 'lit';
2
+ import { BadgeSize, BadgeType } from '../badge/badge.js';
2
3
  import '../icon-button/icon-button.js';
3
4
  import '../../icons/icon-close-google.js';
4
5
  import '../badge/badge.js';
6
+ /**
7
+ * Configuration for a single badge rendered by `<obc-tab-item>` via the `badges` property.
8
+ */
9
+ export interface TabItemBadge {
10
+ /** Visual style/type of the badge. See `BadgeType` for available options. */
11
+ type: BadgeType;
12
+ /** Size of the badge. See `BadgeSize` for available options. */
13
+ size: BadgeSize;
14
+ /** The numeric value to display in the badge. */
15
+ count?: number;
16
+ /** Whether to show an icon inside the badge. Default: false. */
17
+ showIcon?: boolean;
18
+ /**
19
+ * When set, a `<slot>` with this name is rendered inside the badge so a custom
20
+ * icon can be projected (used for badge types without a built-in icon).
21
+ */
22
+ iconSlotName?: string;
23
+ }
5
24
  /**
6
25
  * `<obc-tab-item>` – A selectable tab component for navigation menus and tabbed interfaces.
7
26
  *
@@ -135,6 +154,19 @@ export declare class ObcTabItem extends LitElement {
135
154
  */
136
155
  hasDivider: boolean;
137
156
  /**
157
+ * One or more badges (count/status) to display on the tab.
158
+ *
159
+ * When this array is non-empty it takes precedence over the deprecated
160
+ * single-badge props (`hasBadge`, `badgeType`, `badgeSize`, `badgeCount`,
161
+ * `badgeShowNumber`, `showLeadingBadgeIcon`). When empty, the deprecated
162
+ * props are used instead (gated by `hasBadge`).
163
+ *
164
+ * Default: []
165
+ */
166
+ badges: TabItemBadge[];
167
+ /**
168
+ * @deprecated Use the `badges` array instead.
169
+ *
138
170
  * Displays a badge (count/status) on the tab.
139
171
  * Configure badge appearance via `badgeCount`, `badgeType`, `badgeSize`, etc.
140
172
  *
@@ -174,6 +206,8 @@ export declare class ObcTabItem extends LitElement {
174
206
  */
175
207
  disabled: boolean;
176
208
  /**
209
+ * @deprecated Use the `badges` array instead.
210
+ *
177
211
  * Type of badge to display (e.g., 'regular', 'alarm', 'warning', etc.).
178
212
  * See `BadgeType` enum for available options.
179
213
  *
@@ -182,6 +216,8 @@ export declare class ObcTabItem extends LitElement {
182
216
  */
183
217
  badgeType: string;
184
218
  /**
219
+ * @deprecated Use the `badges` array instead.
220
+ *
185
221
  * Size of the badge ('regular' or 'large').
186
222
  * See `BadgeSize` enum for available options.
187
223
  *
@@ -190,6 +226,8 @@ export declare class ObcTabItem extends LitElement {
190
226
  */
191
227
  badgeSize: string;
192
228
  /**
229
+ * @deprecated Use the `badges` array instead.
230
+ *
193
231
  * Shows the badge's numeric value. When false, only the badge background is rendered (for status-only badges).
194
232
  *
195
233
  * Default: true
@@ -197,6 +235,8 @@ export declare class ObcTabItem extends LitElement {
197
235
  */
198
236
  badgeShowNumber: boolean;
199
237
  /**
238
+ * @deprecated Use the `badges` array instead.
239
+ *
200
240
  * The numeric value to display in the badge (e.g., count of notifications).
201
241
  *
202
242
  * Default: 0
@@ -204,6 +244,8 @@ export declare class ObcTabItem extends LitElement {
204
244
  */
205
245
  badgeCount: number;
206
246
  /**
247
+ * @deprecated Use the `badges` array instead.
248
+ *
207
249
  * Shows an icon inside the badge.
208
250
  * Supply icon content via the `badge-icon` slot.
209
251
  *
@@ -214,6 +256,8 @@ export declare class ObcTabItem extends LitElement {
214
256
  private handleClick;
215
257
  private handleClose;
216
258
  private handleKeyDown;
259
+ private get effectiveBadges();
260
+ private renderBadge;
217
261
  render(): import('lit-html').TemplateResult<1>;
218
262
  static styles: import('lit').CSSResult;
219
263
  }
@@ -1 +1 @@
1
- {"version":3,"file":"tab-item.d.ts","sourceRoot":"","sources":["../../../src/components/tab-item/tab-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA2B,MAAM,KAAK,CAAC;AAIzD,OAAO,+BAA+B,CAAC;AAEvC,OAAO,kCAAkC,CAAC;AAC1C,OAAO,mBAAmB,CAAC;AAG3B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,qBACa,UAAW,SAAQ,UAAU;IACxC;;;;;OAKG;IACuC,GAAG,UAAS;IAEtD;;;;;OAKG;IACwB,aAAa,UAAS;IAEjD;;;;;OAKG;IACuC,OAAO,UAAS;IAE1D;;;;;OAKG;IACgD,QAAQ,UAAS;IAEpE;;;;;OAKG;IACuD,cAAc,UAChE;IAER;;;;;OAKG;IACgD,QAAQ,UAAS;IAEpE;;;;;;OAMG;IACkD,UAAU,UAAS;IAExE;;;;;OAKG;IACgD,QAAQ,UAAS;IAEpE;;;;;OAKG;IACuB,IAAI,SAAiB;IAE/C;;;;;OAKG;IACgC,KAAK,SAAe;IAEvD;;;;OAIG;IACoD,YAAY,UAAS;IAE5E;;;;OAIG;IACuB,QAAQ,SAAM;IAExC;;;;OAIG;IACwB,QAAQ,UAAS;IAE5C;;;;;;OAMG;IACuB,SAAS,EAAE,MAAM,CAAqB;IAEhE;;;;;;OAMG;IACuB,SAAS,EAAE,MAAM,CAAqB;IAEhE;;;;;OAKG;IAC0C,eAAe,EAAE,OAAO,CAAQ;IAE7E;;;;;OAKG;IACuB,UAAU,SAAK;IAEzC;;;;;;OAMG;IACwB,oBAAoB,UAAS;IAExD,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,aAAa;IAOZ,MAAM;IA2Ff,OAAgB,MAAM,0BAA2B;CAClD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,cAAc,EAAE,UAAU,CAAC;KAC5B;CACF"}
1
+ {"version":3,"file":"tab-item.d.ts","sourceRoot":"","sources":["../../../src/components/tab-item/tab-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAA2B,MAAM,KAAK,CAAC;AAIzD,OAAO,+BAA+B,CAAC;AAEvC,OAAO,kCAAkC,CAAC;AAC1C,OAAO,mBAAmB,CAAC;AAC3B,OAAO,EAAC,SAAS,EAAE,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAEvD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,6EAA6E;IAC7E,IAAI,EAAE,SAAS,CAAC;IAChB,gEAAgE;IAChE,IAAI,EAAE,SAAS,CAAC;IAChB,iDAAiD;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,qBACa,UAAW,SAAQ,UAAU;IACxC;;;;;OAKG;IACuC,GAAG,UAAS;IAEtD;;;;;OAKG;IACwB,aAAa,UAAS;IAEjD;;;;;OAKG;IACuC,OAAO,UAAS;IAE1D;;;;;OAKG;IACgD,QAAQ,UAAS;IAEpE;;;;;OAKG;IACuD,cAAc,UAChE;IAER;;;;;OAKG;IACgD,QAAQ,UAAS;IAEpE;;;;;;OAMG;IACkD,UAAU,UAAS;IAExE;;;;;;;;;OASG;IACwC,MAAM,EAAE,YAAY,EAAE,CAAM;IAEvE;;;;;;;OAOG;IACgD,QAAQ,UAAS;IAEpE;;;;;OAKG;IACuB,IAAI,SAAiB;IAE/C;;;;;OAKG;IACgC,KAAK,SAAe;IAEvD;;;;OAIG;IACoD,YAAY,UAAS;IAE5E;;;;OAIG;IACuB,QAAQ,SAAM;IAExC;;;;OAIG;IACwB,QAAQ,UAAS;IAE5C;;;;;;;;OAQG;IACuB,SAAS,EAAE,MAAM,CAAqB;IAEhE;;;;;;;;OAQG;IACuB,SAAS,EAAE,MAAM,CAAqB;IAEhE;;;;;;;OAOG;IAC0C,eAAe,EAAE,OAAO,CAAQ;IAE7E;;;;;;;OAOG;IACuB,UAAU,SAAK;IAEzC;;;;;;;;OAQG;IACwB,oBAAoB,UAAS;IAExD,OAAO,CAAC,WAAW;IAanB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,aAAa;IAOrB,OAAO,KAAK,eAAe,GAgB1B;IAED,OAAO,CAAC,WAAW;IAiBV,MAAM;IAuEf,OAAgB,MAAM,0BAA2B;CAClD;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,cAAc,EAAE,UAAU,CAAC;KAC5B;CACF"}
@@ -26,6 +26,7 @@ let ObcTabItem = class extends LitElement {
26
26
  this.hasLeadingIcon = false;
27
27
  this.hasTitle = false;
28
28
  this.hasDivider = false;
29
+ this.badges = [];
29
30
  this.hasBadge = false;
30
31
  this.icon = "placeholder";
31
32
  this.title = "Tab title";
@@ -65,7 +66,40 @@ let ObcTabItem = class extends LitElement {
65
66
  this.handleClick(event);
66
67
  }
67
68
  }
69
+ get effectiveBadges() {
70
+ if (this.badges.length > 0) {
71
+ return this.badges;
72
+ }
73
+ if (!this.hasBadge) {
74
+ return [];
75
+ }
76
+ return [
77
+ {
78
+ type: this.badgeType || BadgeType.regular,
79
+ size: this.badgeSize || BadgeSize.regular,
80
+ count: this.badgeShowNumber ? this.badgeCount : void 0,
81
+ showIcon: this.showLeadingBadgeIcon,
82
+ iconSlotName: this.showLeadingBadgeIcon ? "badge-icon" : void 0
83
+ }
84
+ ];
85
+ }
86
+ renderBadge(badge) {
87
+ return html`
88
+ <obc-badge
89
+ class="badge"
90
+ .number=${badge.count ?? 0}
91
+ .type=${badge.type || BadgeType.regular}
92
+ .size=${badge.size || BadgeSize.regular}
93
+ .showNumber=${badge.count !== void 0}
94
+ .showIcon=${badge.showIcon ?? false}
95
+ >
96
+ ${badge.iconSlotName ? html`<slot name=${badge.iconSlotName} slot="badge-icon"></slot>` : nothing}
97
+ </obc-badge>
98
+ `;
99
+ }
68
100
  render() {
101
+ const badges = this.effectiveBadges;
102
+ const hasBadge = badges.length > 0;
69
103
  const wrapperClasses = {
70
104
  wrapper: true,
71
105
  hug: this.hug,
@@ -73,7 +107,7 @@ let ObcTabItem = class extends LitElement {
73
107
  "has-leading-icon": this.hasLeadingIcon,
74
108
  "has-title": this.hasTitle,
75
109
  "has-divider": this.hasDivider && !this.checked,
76
- "has-badge": this.hasBadge,
110
+ "has-badge": hasBadge,
77
111
  "has-subtitle": this.showSubtitle,
78
112
  disabled: this.disabled,
79
113
  "center-content": this.centerContent
@@ -100,31 +134,13 @@ let ObcTabItem = class extends LitElement {
100
134
  ${this.showSubtitle && this.subtitle ? html`<div class="subtitle">${this.subtitle}</div>` : nothing}
101
135
  </div>
102
136
  ` : nothing}
103
- ${this.centerContent && this.hasBadge ? html`
104
- <obc-badge
105
- class="badge"
106
- .number=${this.badgeCount}
107
- .type=${this.badgeType || BadgeType.regular}
108
- .size=${this.badgeSize || BadgeSize.regular}
109
- .showNumber=${this.badgeShowNumber}
110
- .showIcon=${this.showLeadingBadgeIcon}
111
- >
112
- ${this.showLeadingBadgeIcon ? html`<slot name="badge-icon" slot="badge-icon"></slot>` : nothing}
113
- </obc-badge>
114
- ` : nothing}
137
+ ${this.centerContent && hasBadge ? html`<div class="badges">
138
+ ${badges.map((badge) => this.renderBadge(badge))}
139
+ </div>` : nothing}
115
140
  </div>
116
- ${!this.centerContent && this.hasBadge ? html`
117
- <obc-badge
118
- class="badge"
119
- .number=${this.badgeCount}
120
- .type=${this.badgeType || BadgeType.regular}
121
- .size=${this.badgeSize || BadgeSize.regular}
122
- .showNumber=${this.badgeShowNumber}
123
- .showIcon=${this.showLeadingBadgeIcon}
124
- >
125
- ${this.showLeadingBadgeIcon ? html`<slot name="badge-icon" slot="badge-icon"></slot>` : nothing}
126
- </obc-badge>
127
- ` : nothing}
141
+ ${!this.centerContent && hasBadge ? html`<div class="badges">
142
+ ${badges.map((badge) => this.renderBadge(badge))}
143
+ </div>` : nothing}
128
144
  ${this.hasClose ? html`
129
145
  <obc-icon-button
130
146
  class="close-button"
@@ -161,6 +177,9 @@ __decorateClass([
161
177
  __decorateClass([
162
178
  property({ type: Boolean, attribute: "has-divider" })
163
179
  ], ObcTabItem.prototype, "hasDivider", 2);
180
+ __decorateClass([
181
+ property({ type: Array, attribute: false })
182
+ ], ObcTabItem.prototype, "badges", 2);
164
183
  __decorateClass([
165
184
  property({ type: Boolean, attribute: "has-badge" })
166
185
  ], ObcTabItem.prototype, "hasBadge", 2);
@@ -1 +1 @@
1
- {"version":3,"file":"tab-item.js","sources":["../../../src/components/tab-item/tab-item.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport compentStyle from './tab-item.css?inline';\nimport '../icon-button/icon-button.js';\nimport {property} from 'lit/decorators.js';\nimport '../../icons/icon-close-google.js';\nimport '../badge/badge.js';\nimport {BadgeSize, BadgeType} from '../badge/badge.js';\n\n/**\n * `<obc-tab-item>` – A selectable tab component for navigation menus and tabbed interfaces.\n *\n * Represents a single tab within a tab bar or navigation group, supporting optional icons, subtitles, badges, close actions, and various layout modes. Designed for use in horizontal or vertical tab sets, allowing users to switch between different views or content panels.\n *\n * Appears as a button-like element that can display a leading icon, a title, an optional subtitle, a badge (for counts or status), and an optional close button. Supports both fixed-width and \"hug\" (fit-content) layouts, and can be styled as checked (active/selected) or disabled.\n *\n * ### Features\n * - **Selectable State:** Indicates active/selected tab via the `checked` property.\n * - **Leading Icon:** Optionally displays a leading icon via the `leading-icon` slot.\n * - **Title:** Supports a title label, either via property or slot.\n * - **Subtitle:** Optionally displays secondary contextual text below the title.\n * - **Badge Support:** Can show a badge (count/status) with configurable type, size, and icon.\n * - **Close Button:** Optional close action via a trailing icon button.\n * - **Layout Modes:**\n * - **Hug:** Shrinks to fit content width (`hug` property).\n * - **Center Content:** Centers content within the tab (`centerContent` property).\n * - **Divider:** Optional divider line for visual separation.\n * - **Disabled State:** Prevents interaction and visually indicates non-interactive state.\n * - **Keyboard Accessible:** Supports activation via Enter/Space keys.\n *\n * ### Variants and Configuration\n * - **Badge Types:** Supports all badge types from `obc-badge` (e.g., `alarm`, `warning`, `notification`, etc.).\n * - **Badge Sizes:** Regular and large badge sizes.\n * - **Badge Number Toggle:** Optionally hide the badge number via `badgeShowNumber` for status-only badges.\n * - **Show Leading Badge Icon:** Optionally display an icon within the badge.\n * - **Subtitle Toggle:** Optionally display a subtitle line using `showSubtitle`.\n *\n * ### Usage Guidelines\n * Use `obc-tab-item` within a tab bar or navigation group to represent a single selectable view or section. Ideal for switching between content panels, dashboards, or grouped settings. Use the `checked` property to indicate the active tab, and `disabled` to prevent selection. Use `subtitle` for short contextual information that helps distinguish similarly named tabs. The close button is suitable for user-removable tabs (e.g., in dynamic tab sets).\n *\n * - Use the badge for counts (e.g., notifications, alarms) or status indicators.\n * - Use the leading icon for visual context or to reinforce the tab's purpose.\n * - Avoid using the close button on non-removable tabs.\n * - For best accessibility, ensure each tab has a unique label/title.\n *\n * **TODO(designer):** Confirm if there are recommended maximum title lengths or truncation guidelines for tab labels.\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * | -------------- | ---------------------- | -------------------------------------------------------- |\n * | leading-icon | `hasLeadingIcon` true | Leading icon representing the tab's category or purpose. |\n * | title | `hasTitle` true | Tab label or heading text. |\n * | badge-icon | `hasBadge` & `showLeadingBadgeIcon` true | Icon inside the badge (e.g., status symbol). |\n *\n * ### Events\n * - `tab-click` – Fired when the tab is clicked or activated via keyboard.\n * - `tab-close` – Fired when the close button is clicked.\n *\n * ### Best Practices\n * - Only one tab in a group should have `checked` set to true.\n * - Use the badge for concise status/counts; avoid long text in badges.\n * - The close button should only be used for tabs that users can remove.\n * - For accessibility, ensure tabs are focusable and have clear labels.\n *\n * **Example:**\n * ```\n * <obc-tab-item\n * checked\n * has-leading-icon\n * has-title\n * show-subtitle\n * subtitle=\"Context\"\n * has-badge\n * badgeCount=\"3\"\n * badgeType=\"alarm\"\n * has-close\n * title=\"Alarms\"\n * >\n * <obi-placeholder slot=\"leading-icon\"></obi-placeholder>\n * <obi-placeholder slot=\"badge-icon\"></obi-placeholder>\n * </obc-tab-item>\n * ```\n *\n * @slot leading-icon - Slot for the leading icon (shown when `hasLeadingIcon` is true)\n * @slot title - Slot for the tab's label/title (shown when `hasTitle` is true)\n * @slot badge-icon - Slot for an icon inside the badge (shown when `hasBadge` and `showLeadingBadgeIcon` are true)\n * @fires tab-click {CustomEvent<{title: string}>} When the tab is clicked or activated via keyboard\n * @fires tab-close {CustomEvent<{title: string}>} When the close button is clicked\n */\n@customElement('obc-tab-item')\nexport class ObcTabItem extends LitElement {\n /**\n * Shrinks the tab width to fit its content instead of using the default fixed width.\n * When enabled, the tab will use `width: fit-content` and a minimum width.\n *\n * Default: false\n */\n @property({type: Boolean, reflect: true}) hug = false;\n\n /**\n * Centers the content (icon, title, badge) horizontally within the tab.\n * When enabled, content is centered rather than left-aligned.\n *\n * Default: false\n */\n @property({type: Boolean}) centerContent = false;\n\n /**\n * Marks the tab as selected/active.\n * Only one tab in a group should have `checked` set to true.\n *\n * Default: false\n */\n @property({type: Boolean, reflect: true}) checked = false;\n\n /**\n * Displays a close button at the end of the tab.\n * Use for tabs that can be removed by the user.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'has-close'}) hasClose = false;\n\n /**\n * Shows a leading icon at the start of the tab.\n * Supply icon content via the `leading-icon` slot.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'has-leading-icon'}) hasLeadingIcon =\n false;\n\n /**\n * Displays the tab's title/label.\n * Content can be provided via the `title` slot or the `title` property.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'has-title'}) hasTitle = false;\n\n /**\n * Shows a vertical divider on the left edge of the tab (except when checked).\n * Useful for visually separating tabs.\n *\n * Default: false\n * @availableWhen checked==false\n */\n @property({type: Boolean, attribute: 'has-divider'}) hasDivider = false;\n\n /**\n * Displays a badge (count/status) on the tab.\n * Configure badge appearance via `badgeCount`, `badgeType`, `badgeSize`, etc.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'has-badge'}) hasBadge = false;\n\n /**\n * (Deprecated/Unused) Icon name for the tab.\n * Icon content should be provided via the `leading-icon` slot.\n *\n * Default: 'placeholder'\n */\n @property({type: String}) icon = 'placeholder';\n\n /**\n * The tab's title/label text.\n * Can be overridden by slotting content into the `title` slot.\n *\n * Default: 'Tab title'\n */\n @property({type: String}) override title = 'Tab title';\n\n /**\n * Shows contextual text below the tab title.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'show-subtitle'}) showSubtitle = false;\n\n /**\n * Contextual text shown below the tab title when `showSubtitle` is true.\n *\n * Default: ''\n */\n @property({type: String}) subtitle = '';\n\n /**\n * Disables the tab, preventing user interaction and applying disabled styles.\n *\n * Default: false\n */\n @property({type: Boolean}) disabled = false;\n\n /**\n * Type of badge to display (e.g., 'regular', 'alarm', 'warning', etc.).\n * See `BadgeType` enum for available options.\n *\n * Default: 'regular'\n * @availableWhen hasBadge==true\n */\n @property({type: String}) badgeType: string = BadgeType.regular;\n\n /**\n * Size of the badge ('regular' or 'large').\n * See `BadgeSize` enum for available options.\n *\n * Default: 'regular'\n * @availableWhen hasBadge==true\n */\n @property({type: String}) badgeSize: string = BadgeSize.regular;\n\n /**\n * Shows the badge's numeric value. When false, only the badge background is rendered (for status-only badges).\n *\n * Default: true\n * @availableWhen hasBadge==true\n */\n @property({type: Boolean, attribute: false}) badgeShowNumber: boolean = true;\n\n /**\n * The numeric value to display in the badge (e.g., count of notifications).\n *\n * Default: 0\n * @availableWhen hasBadge==true\n */\n @property({type: Number}) badgeCount = 0;\n\n /**\n * Shows an icon inside the badge.\n * Supply icon content via the `badge-icon` slot.\n *\n * Default: false\n * @availableWhen hasBadge==true\n */\n @property({type: Boolean}) showLeadingBadgeIcon = false;\n\n private handleClick(event: Event) {\n if (this.disabled) {\n event.preventDefault();\n return;\n }\n const clickEvent = new CustomEvent('tab-click', {\n detail: {title: this.title},\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(clickEvent);\n }\n\n private handleClose(event: Event) {\n event.stopPropagation();\n const closeEvent = new CustomEvent('tab-close', {\n detail: {title: this.title},\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(closeEvent);\n }\n\n private handleKeyDown(event: KeyboardEvent) {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.handleClick(event);\n }\n }\n\n override render() {\n const wrapperClasses = {\n wrapper: true,\n hug: this.hug,\n 'has-close': this.hasClose,\n 'has-leading-icon': this.hasLeadingIcon,\n 'has-title': this.hasTitle,\n 'has-divider': this.hasDivider && !this.checked,\n 'has-badge': this.hasBadge,\n 'has-subtitle': this.showSubtitle,\n disabled: this.disabled,\n 'center-content': this.centerContent,\n };\n\n return html`\n <div\n class=${classMap(wrapperClasses)}\n role=\"tab\"\n tabindex=${this.disabled ? '-1' : '0'}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <div class=\"content\">\n ${this.hasLeadingIcon\n ? html`\n <div class=\"leading-icon\">\n <slot name=\"leading-icon\"></slot>\n </div>\n `\n : nothing}\n ${this.hasTitle\n ? html`\n <div class=\"text-content\">\n <div class=\"title\">\n <slot name=\"title\">${this.title}</slot>\n </div>\n ${this.showSubtitle && this.subtitle\n ? html`<div class=\"subtitle\">${this.subtitle}</div>`\n : nothing}\n </div>\n `\n : nothing}\n ${this.centerContent && this.hasBadge\n ? html`\n <obc-badge\n class=\"badge\"\n .number=${this.badgeCount}\n .type=${this.badgeType || BadgeType.regular}\n .size=${this.badgeSize || BadgeSize.regular}\n .showNumber=${this.badgeShowNumber}\n .showIcon=${this.showLeadingBadgeIcon}\n >\n ${this.showLeadingBadgeIcon\n ? html`<slot name=\"badge-icon\" slot=\"badge-icon\"></slot>`\n : nothing}\n </obc-badge>\n `\n : nothing}\n </div>\n ${!this.centerContent && this.hasBadge\n ? html`\n <obc-badge\n class=\"badge\"\n .number=${this.badgeCount}\n .type=${this.badgeType || BadgeType.regular}\n .size=${this.badgeSize || BadgeSize.regular}\n .showNumber=${this.badgeShowNumber}\n .showIcon=${this.showLeadingBadgeIcon}\n >\n ${this.showLeadingBadgeIcon\n ? html`<slot name=\"badge-icon\" slot=\"badge-icon\"></slot>`\n : nothing}\n </obc-badge>\n `\n : nothing}\n ${this.hasClose\n ? html`\n <obc-icon-button\n class=\"close-button\"\n variant=\"flat\"\n @click=${this.handleClose}\n aria-label=\"Close tab\"\n .disabled=${this.disabled}\n ><obi-close-google></obi-close-google\n ></obc-icon-button>\n `\n : nothing}\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-tab-item': ObcTabItem;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tab-item.js","sources":["../../../src/components/tab-item/tab-item.ts"],"sourcesContent":["import {LitElement, html, nothing, unsafeCSS} from 'lit';\nimport {customElement} from '../../decorator.js';\nimport {classMap} from 'lit/directives/class-map.js';\nimport compentStyle from './tab-item.css?inline';\nimport '../icon-button/icon-button.js';\nimport {property} from 'lit/decorators.js';\nimport '../../icons/icon-close-google.js';\nimport '../badge/badge.js';\nimport {BadgeSize, BadgeType} from '../badge/badge.js';\n\n/**\n * Configuration for a single badge rendered by `<obc-tab-item>` via the `badges` property.\n */\nexport interface TabItemBadge {\n /** Visual style/type of the badge. See `BadgeType` for available options. */\n type: BadgeType;\n /** Size of the badge. See `BadgeSize` for available options. */\n size: BadgeSize;\n /** The numeric value to display in the badge. */\n count?: number;\n /** Whether to show an icon inside the badge. Default: false. */\n showIcon?: boolean;\n /**\n * When set, a `<slot>` with this name is rendered inside the badge so a custom\n * icon can be projected (used for badge types without a built-in icon).\n */\n iconSlotName?: string;\n}\n\n/**\n * `<obc-tab-item>` – A selectable tab component for navigation menus and tabbed interfaces.\n *\n * Represents a single tab within a tab bar or navigation group, supporting optional icons, subtitles, badges, close actions, and various layout modes. Designed for use in horizontal or vertical tab sets, allowing users to switch between different views or content panels.\n *\n * Appears as a button-like element that can display a leading icon, a title, an optional subtitle, a badge (for counts or status), and an optional close button. Supports both fixed-width and \"hug\" (fit-content) layouts, and can be styled as checked (active/selected) or disabled.\n *\n * ### Features\n * - **Selectable State:** Indicates active/selected tab via the `checked` property.\n * - **Leading Icon:** Optionally displays a leading icon via the `leading-icon` slot.\n * - **Title:** Supports a title label, either via property or slot.\n * - **Subtitle:** Optionally displays secondary contextual text below the title.\n * - **Badge Support:** Can show a badge (count/status) with configurable type, size, and icon.\n * - **Close Button:** Optional close action via a trailing icon button.\n * - **Layout Modes:**\n * - **Hug:** Shrinks to fit content width (`hug` property).\n * - **Center Content:** Centers content within the tab (`centerContent` property).\n * - **Divider:** Optional divider line for visual separation.\n * - **Disabled State:** Prevents interaction and visually indicates non-interactive state.\n * - **Keyboard Accessible:** Supports activation via Enter/Space keys.\n *\n * ### Variants and Configuration\n * - **Badge Types:** Supports all badge types from `obc-badge` (e.g., `alarm`, `warning`, `notification`, etc.).\n * - **Badge Sizes:** Regular and large badge sizes.\n * - **Badge Number Toggle:** Optionally hide the badge number via `badgeShowNumber` for status-only badges.\n * - **Show Leading Badge Icon:** Optionally display an icon within the badge.\n * - **Subtitle Toggle:** Optionally display a subtitle line using `showSubtitle`.\n *\n * ### Usage Guidelines\n * Use `obc-tab-item` within a tab bar or navigation group to represent a single selectable view or section. Ideal for switching between content panels, dashboards, or grouped settings. Use the `checked` property to indicate the active tab, and `disabled` to prevent selection. Use `subtitle` for short contextual information that helps distinguish similarly named tabs. The close button is suitable for user-removable tabs (e.g., in dynamic tab sets).\n *\n * - Use the badge for counts (e.g., notifications, alarms) or status indicators.\n * - Use the leading icon for visual context or to reinforce the tab's purpose.\n * - Avoid using the close button on non-removable tabs.\n * - For best accessibility, ensure each tab has a unique label/title.\n *\n * **TODO(designer):** Confirm if there are recommended maximum title lengths or truncation guidelines for tab labels.\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * | -------------- | ---------------------- | -------------------------------------------------------- |\n * | leading-icon | `hasLeadingIcon` true | Leading icon representing the tab's category or purpose. |\n * | title | `hasTitle` true | Tab label or heading text. |\n * | badge-icon | `hasBadge` & `showLeadingBadgeIcon` true | Icon inside the badge (e.g., status symbol). |\n *\n * ### Events\n * - `tab-click` – Fired when the tab is clicked or activated via keyboard.\n * - `tab-close` – Fired when the close button is clicked.\n *\n * ### Best Practices\n * - Only one tab in a group should have `checked` set to true.\n * - Use the badge for concise status/counts; avoid long text in badges.\n * - The close button should only be used for tabs that users can remove.\n * - For accessibility, ensure tabs are focusable and have clear labels.\n *\n * **Example:**\n * ```\n * <obc-tab-item\n * checked\n * has-leading-icon\n * has-title\n * show-subtitle\n * subtitle=\"Context\"\n * has-badge\n * badgeCount=\"3\"\n * badgeType=\"alarm\"\n * has-close\n * title=\"Alarms\"\n * >\n * <obi-placeholder slot=\"leading-icon\"></obi-placeholder>\n * <obi-placeholder slot=\"badge-icon\"></obi-placeholder>\n * </obc-tab-item>\n * ```\n *\n * @slot leading-icon - Slot for the leading icon (shown when `hasLeadingIcon` is true)\n * @slot title - Slot for the tab's label/title (shown when `hasTitle` is true)\n * @slot badge-icon - Slot for an icon inside the badge (shown when `hasBadge` and `showLeadingBadgeIcon` are true)\n * @fires tab-click {CustomEvent<{title: string}>} When the tab is clicked or activated via keyboard\n * @fires tab-close {CustomEvent<{title: string}>} When the close button is clicked\n */\n@customElement('obc-tab-item')\nexport class ObcTabItem extends LitElement {\n /**\n * Shrinks the tab width to fit its content instead of using the default fixed width.\n * When enabled, the tab will use `width: fit-content` and a minimum width.\n *\n * Default: false\n */\n @property({type: Boolean, reflect: true}) hug = false;\n\n /**\n * Centers the content (icon, title, badge) horizontally within the tab.\n * When enabled, content is centered rather than left-aligned.\n *\n * Default: false\n */\n @property({type: Boolean}) centerContent = false;\n\n /**\n * Marks the tab as selected/active.\n * Only one tab in a group should have `checked` set to true.\n *\n * Default: false\n */\n @property({type: Boolean, reflect: true}) checked = false;\n\n /**\n * Displays a close button at the end of the tab.\n * Use for tabs that can be removed by the user.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'has-close'}) hasClose = false;\n\n /**\n * Shows a leading icon at the start of the tab.\n * Supply icon content via the `leading-icon` slot.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'has-leading-icon'}) hasLeadingIcon =\n false;\n\n /**\n * Displays the tab's title/label.\n * Content can be provided via the `title` slot or the `title` property.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'has-title'}) hasTitle = false;\n\n /**\n * Shows a vertical divider on the left edge of the tab (except when checked).\n * Useful for visually separating tabs.\n *\n * Default: false\n * @availableWhen checked==false\n */\n @property({type: Boolean, attribute: 'has-divider'}) hasDivider = false;\n\n /**\n * One or more badges (count/status) to display on the tab.\n *\n * When this array is non-empty it takes precedence over the deprecated\n * single-badge props (`hasBadge`, `badgeType`, `badgeSize`, `badgeCount`,\n * `badgeShowNumber`, `showLeadingBadgeIcon`). When empty, the deprecated\n * props are used instead (gated by `hasBadge`).\n *\n * Default: []\n */\n @property({type: Array, attribute: false}) badges: TabItemBadge[] = [];\n\n /**\n * @deprecated Use the `badges` array instead.\n *\n * Displays a badge (count/status) on the tab.\n * Configure badge appearance via `badgeCount`, `badgeType`, `badgeSize`, etc.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'has-badge'}) hasBadge = false;\n\n /**\n * (Deprecated/Unused) Icon name for the tab.\n * Icon content should be provided via the `leading-icon` slot.\n *\n * Default: 'placeholder'\n */\n @property({type: String}) icon = 'placeholder';\n\n /**\n * The tab's title/label text.\n * Can be overridden by slotting content into the `title` slot.\n *\n * Default: 'Tab title'\n */\n @property({type: String}) override title = 'Tab title';\n\n /**\n * Shows contextual text below the tab title.\n *\n * Default: false\n */\n @property({type: Boolean, attribute: 'show-subtitle'}) showSubtitle = false;\n\n /**\n * Contextual text shown below the tab title when `showSubtitle` is true.\n *\n * Default: ''\n */\n @property({type: String}) subtitle = '';\n\n /**\n * Disables the tab, preventing user interaction and applying disabled styles.\n *\n * Default: false\n */\n @property({type: Boolean}) disabled = false;\n\n /**\n * @deprecated Use the `badges` array instead.\n *\n * Type of badge to display (e.g., 'regular', 'alarm', 'warning', etc.).\n * See `BadgeType` enum for available options.\n *\n * Default: 'regular'\n * @availableWhen hasBadge==true\n */\n @property({type: String}) badgeType: string = BadgeType.regular;\n\n /**\n * @deprecated Use the `badges` array instead.\n *\n * Size of the badge ('regular' or 'large').\n * See `BadgeSize` enum for available options.\n *\n * Default: 'regular'\n * @availableWhen hasBadge==true\n */\n @property({type: String}) badgeSize: string = BadgeSize.regular;\n\n /**\n * @deprecated Use the `badges` array instead.\n *\n * Shows the badge's numeric value. When false, only the badge background is rendered (for status-only badges).\n *\n * Default: true\n * @availableWhen hasBadge==true\n */\n @property({type: Boolean, attribute: false}) badgeShowNumber: boolean = true;\n\n /**\n * @deprecated Use the `badges` array instead.\n *\n * The numeric value to display in the badge (e.g., count of notifications).\n *\n * Default: 0\n * @availableWhen hasBadge==true\n */\n @property({type: Number}) badgeCount = 0;\n\n /**\n * @deprecated Use the `badges` array instead.\n *\n * Shows an icon inside the badge.\n * Supply icon content via the `badge-icon` slot.\n *\n * Default: false\n * @availableWhen hasBadge==true\n */\n @property({type: Boolean}) showLeadingBadgeIcon = false;\n\n private handleClick(event: Event) {\n if (this.disabled) {\n event.preventDefault();\n return;\n }\n const clickEvent = new CustomEvent('tab-click', {\n detail: {title: this.title},\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(clickEvent);\n }\n\n private handleClose(event: Event) {\n event.stopPropagation();\n const closeEvent = new CustomEvent('tab-close', {\n detail: {title: this.title},\n bubbles: true,\n composed: true,\n });\n this.dispatchEvent(closeEvent);\n }\n\n private handleKeyDown(event: KeyboardEvent) {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.handleClick(event);\n }\n }\n\n private get effectiveBadges(): TabItemBadge[] {\n if (this.badges.length > 0) {\n return this.badges;\n }\n if (!this.hasBadge) {\n return [];\n }\n return [\n {\n type: (this.badgeType as BadgeType) || BadgeType.regular,\n size: (this.badgeSize as BadgeSize) || BadgeSize.regular,\n count: this.badgeShowNumber ? this.badgeCount : undefined,\n showIcon: this.showLeadingBadgeIcon,\n iconSlotName: this.showLeadingBadgeIcon ? 'badge-icon' : undefined,\n },\n ];\n }\n\n private renderBadge(badge: TabItemBadge) {\n return html`\n <obc-badge\n class=\"badge\"\n .number=${badge.count ?? 0}\n .type=${badge.type || BadgeType.regular}\n .size=${badge.size || BadgeSize.regular}\n .showNumber=${badge.count !== undefined}\n .showIcon=${badge.showIcon ?? false}\n >\n ${badge.iconSlotName\n ? html`<slot name=${badge.iconSlotName} slot=\"badge-icon\"></slot>`\n : nothing}\n </obc-badge>\n `;\n }\n\n override render() {\n const badges = this.effectiveBadges;\n const hasBadge = badges.length > 0;\n const wrapperClasses = {\n wrapper: true,\n hug: this.hug,\n 'has-close': this.hasClose,\n 'has-leading-icon': this.hasLeadingIcon,\n 'has-title': this.hasTitle,\n 'has-divider': this.hasDivider && !this.checked,\n 'has-badge': hasBadge,\n 'has-subtitle': this.showSubtitle,\n disabled: this.disabled,\n 'center-content': this.centerContent,\n };\n\n return html`\n <div\n class=${classMap(wrapperClasses)}\n role=\"tab\"\n tabindex=${this.disabled ? '-1' : '0'}\n @click=${this.handleClick}\n @keydown=${this.handleKeyDown}\n >\n <div class=\"content\">\n ${this.hasLeadingIcon\n ? html`\n <div class=\"leading-icon\">\n <slot name=\"leading-icon\"></slot>\n </div>\n `\n : nothing}\n ${this.hasTitle\n ? html`\n <div class=\"text-content\">\n <div class=\"title\">\n <slot name=\"title\">${this.title}</slot>\n </div>\n ${this.showSubtitle && this.subtitle\n ? html`<div class=\"subtitle\">${this.subtitle}</div>`\n : nothing}\n </div>\n `\n : nothing}\n ${this.centerContent && hasBadge\n ? html`<div class=\"badges\">\n ${badges.map((badge) => this.renderBadge(badge))}\n </div>`\n : nothing}\n </div>\n ${!this.centerContent && hasBadge\n ? html`<div class=\"badges\">\n ${badges.map((badge) => this.renderBadge(badge))}\n </div>`\n : nothing}\n ${this.hasClose\n ? html`\n <obc-icon-button\n class=\"close-button\"\n variant=\"flat\"\n @click=${this.handleClose}\n aria-label=\"Close tab\"\n .disabled=${this.disabled}\n ><obi-close-google></obi-close-google\n ></obc-icon-button>\n `\n : nothing}\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-tab-item': ObcTabItem;\n }\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AA+GO,IAAM,aAAN,cAAyB,WAAW;AAAA,EAApC,cAAA;AAAA,UAAA,GAAA,SAAA;AAOqC,SAAA,MAAM;AAQrB,SAAA,gBAAgB;AAQD,SAAA,UAAU;AAQD,SAAA,WAAW;AAQJ,SAAA,iBACxD;AAQiD,SAAA,WAAW;AAST,SAAA,aAAa;AAYvB,SAAA,SAAyB,CAAA;AAUjB,SAAA,WAAW;AAQpC,SAAA,OAAO;AAQP,SAAS,QAAQ;AAOY,SAAA,eAAe;AAO5C,SAAA,WAAW;AAOV,SAAA,WAAW;AAWZ,SAAA,YAAoB,UAAU;AAW9B,SAAA,YAAoB,UAAU;AAUX,SAAA,kBAA2B;AAU9C,SAAA,aAAa;AAWZ,SAAA,uBAAuB;AAAA,EAAA;AAAA,EAE1C,YAAY,OAAc;AAChC,QAAI,KAAK,UAAU;AACjB,YAAM,eAAA;AACN;AAAA,IACF;AACA,UAAM,aAAa,IAAI,YAAY,aAAa;AAAA,MAC9C,QAAQ,EAAC,OAAO,KAAK,MAAA;AAAA,MACrB,SAAS;AAAA,MACT,UAAU;AAAA,IAAA,CACX;AACD,SAAK,cAAc,UAAU;AAAA,EAC/B;AAAA,EAEQ,YAAY,OAAc;AAChC,UAAM,gBAAA;AACN,UAAM,aAAa,IAAI,YAAY,aAAa;AAAA,MAC9C,QAAQ,EAAC,OAAO,KAAK,MAAA;AAAA,MACrB,SAAS;AAAA,MACT,UAAU;AAAA,IAAA,CACX;AACD,SAAK,cAAc,UAAU;AAAA,EAC/B;AAAA,EAEQ,cAAc,OAAsB;AAC1C,QAAI,MAAM,QAAQ,WAAW,MAAM,QAAQ,KAAK;AAC9C,YAAM,eAAA;AACN,WAAK,YAAY,KAAK;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,IAAY,kBAAkC;AAC5C,QAAI,KAAK,OAAO,SAAS,GAAG;AAC1B,aAAO,KAAK;AAAA,IACd;AACA,QAAI,CAAC,KAAK,UAAU;AAClB,aAAO,CAAA;AAAA,IACT;AACA,WAAO;AAAA,MACL;AAAA,QACE,MAAO,KAAK,aAA2B,UAAU;AAAA,QACjD,MAAO,KAAK,aAA2B,UAAU;AAAA,QACjD,OAAO,KAAK,kBAAkB,KAAK,aAAa;AAAA,QAChD,UAAU,KAAK;AAAA,QACf,cAAc,KAAK,uBAAuB,eAAe;AAAA,MAAA;AAAA,IAC3D;AAAA,EAEJ;AAAA,EAEQ,YAAY,OAAqB;AACvC,WAAO;AAAA;AAAA;AAAA,kBAGO,MAAM,SAAS,CAAC;AAAA,gBAClB,MAAM,QAAQ,UAAU,OAAO;AAAA,gBAC/B,MAAM,QAAQ,UAAU,OAAO;AAAA,sBACzB,MAAM,UAAU,MAAS;AAAA,oBAC3B,MAAM,YAAY,KAAK;AAAA;AAAA,UAEjC,MAAM,eACJ,kBAAkB,MAAM,YAAY,+BACpC,OAAO;AAAA;AAAA;AAAA,EAGjB;AAAA,EAES,SAAS;AAChB,UAAM,SAAS,KAAK;AACpB,UAAM,WAAW,OAAO,SAAS;AACjC,UAAM,iBAAiB;AAAA,MACrB,SAAS;AAAA,MACT,KAAK,KAAK;AAAA,MACV,aAAa,KAAK;AAAA,MAClB,oBAAoB,KAAK;AAAA,MACzB,aAAa,KAAK;AAAA,MAClB,eAAe,KAAK,cAAc,CAAC,KAAK;AAAA,MACxC,aAAa;AAAA,MACb,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,MACf,kBAAkB,KAAK;AAAA,IAAA;AAGzB,WAAO;AAAA;AAAA,gBAEK,SAAS,cAAc,CAAC;AAAA;AAAA,mBAErB,KAAK,WAAW,OAAO,GAAG;AAAA,iBAC5B,KAAK,WAAW;AAAA,mBACd,KAAK,aAAa;AAAA;AAAA;AAAA,YAGzB,KAAK,iBACH;AAAA;AAAA;AAAA;AAAA,kBAKA,OAAO;AAAA,YACT,KAAK,WACH;AAAA;AAAA;AAAA,yCAG2B,KAAK,KAAK;AAAA;AAAA,oBAE/B,KAAK,gBAAgB,KAAK,WACxB,6BAA6B,KAAK,QAAQ,WAC1C,OAAO;AAAA;AAAA,kBAGf,OAAO;AAAA,YACT,KAAK,iBAAiB,WACpB;AAAA,kBACI,OAAO,IAAI,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC;AAAA,wBAElD,OAAO;AAAA;AAAA,UAEX,CAAC,KAAK,iBAAiB,WACrB;AAAA,gBACI,OAAO,IAAI,CAAC,UAAU,KAAK,YAAY,KAAK,CAAC,CAAC;AAAA,sBAElD,OAAO;AAAA,UACT,KAAK,WACH;AAAA;AAAA;AAAA;AAAA,yBAIa,KAAK,WAAW;AAAA;AAAA,4BAEb,KAAK,QAAQ;AAAA;AAAA;AAAA,gBAI7B,OAAO;AAAA;AAAA;AAAA,EAGjB;AAGF;AApTa,WAmTK,SAAS,UAAU,YAAY;AA5SL,gBAAA;AAAA,EAAzC,SAAS,EAAC,MAAM,SAAS,SAAS,MAAK;AAAA,GAP7B,WAO+B,WAAA,OAAA,CAAA;AAQf,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAfd,WAegB,WAAA,iBAAA,CAAA;AAQe,gBAAA;AAAA,EAAzC,SAAS,EAAC,MAAM,SAAS,SAAS,MAAK;AAAA,GAvB7B,WAuB+B,WAAA,WAAA,CAAA;AAQS,gBAAA;AAAA,EAAlD,SAAS,EAAC,MAAM,SAAS,WAAW,aAAY;AAAA,GA/BtC,WA+BwC,WAAA,YAAA,CAAA;AAQO,gBAAA;AAAA,EAAzD,SAAS,EAAC,MAAM,SAAS,WAAW,oBAAmB;AAAA,GAvC7C,WAuC+C,WAAA,kBAAA,CAAA;AASP,gBAAA;AAAA,EAAlD,SAAS,EAAC,MAAM,SAAS,WAAW,aAAY;AAAA,GAhDtC,WAgDwC,WAAA,YAAA,CAAA;AASE,gBAAA;AAAA,EAApD,SAAS,EAAC,MAAM,SAAS,WAAW,eAAc;AAAA,GAzDxC,WAyD0C,WAAA,cAAA,CAAA;AAYV,gBAAA;AAAA,EAA1C,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GArE9B,WAqEgC,WAAA,UAAA,CAAA;AAUQ,gBAAA;AAAA,EAAlD,SAAS,EAAC,MAAM,SAAS,WAAW,aAAY;AAAA,GA/EtC,WA+EwC,WAAA,YAAA,CAAA;AAQzB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAvFb,WAuFe,WAAA,QAAA,CAAA;AAQS,gBAAA;AAAA,EAAlC,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA/Fb,WA+FwB,WAAA,SAAA,CAAA;AAOoB,gBAAA;AAAA,EAAtD,SAAS,EAAC,MAAM,SAAS,WAAW,iBAAgB;AAAA,GAtG1C,WAsG4C,WAAA,gBAAA,CAAA;AAO7B,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA7Gb,WA6Ge,WAAA,YAAA,CAAA;AAOC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GApHd,WAoHgB,WAAA,YAAA,CAAA;AAWD,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA/Hb,WA+He,WAAA,aAAA,CAAA;AAWA,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA1Ib,WA0Ie,WAAA,aAAA,CAAA;AAUmB,gBAAA;AAAA,EAA5C,SAAS,EAAC,MAAM,SAAS,WAAW,OAAM;AAAA,GApJhC,WAoJkC,WAAA,mBAAA,CAAA;AAUnB,gBAAA;AAAA,EAAzB,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA9Jb,WA8Je,WAAA,cAAA,CAAA;AAWC,gBAAA;AAAA,EAA1B,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAzKd,WAyKgB,WAAA,wBAAA,CAAA;AAzKhB,aAAN,gBAAA;AAAA,EADN,cAAc,cAAc;AAAA,GAChB,UAAA;"}
@@ -1,4 +1,5 @@
1
1
  import { LitElement } from 'lit';
2
+ import { TabItemBadge } from '../tab-item/tab-item.js';
2
3
  import { BadgeType, BadgeSize } from '../badge/badge.js';
3
4
  import '../tab-item/tab-item.js';
4
5
  import '../icon-button/icon-button.js';
@@ -10,11 +11,22 @@ export interface TabData {
10
11
  subtitle?: string;
11
12
  showSubtitle?: boolean;
12
13
  hasLeadingIcon?: boolean;
14
+ /**
15
+ * One or more badges to display on the tab. When non-empty this takes
16
+ * precedence over the deprecated single-badge fields below.
17
+ */
18
+ badges?: TabItemBadge[];
19
+ /** @deprecated Use `badges` instead. */
13
20
  hasBadge?: boolean;
21
+ /** @deprecated Use `badges` instead. */
14
22
  badgeCount?: number;
23
+ /** @deprecated Use `badges` instead. */
15
24
  badgeType?: BadgeType;
25
+ /** @deprecated Use `badges` instead. */
16
26
  badgeSize?: BadgeSize;
27
+ /** @deprecated Use `badges` instead. */
17
28
  badgeShowNumber?: boolean;
29
+ /** @deprecated Use `badges` instead. */
18
30
  showLeadingBadgeIcon?: boolean;
19
31
  disabled?: boolean;
20
32
  }
@@ -74,8 +86,8 @@ export interface TabData {
74
86
  *
75
87
  * | Slot Name | Renders When... | Purpose |
76
88
  * |--------------------------|------------------------------------|------------------------------------------------------|
77
- * | `tab-<id>-icon` | If `hasLeadingIcon` is true | Leading icon for a specific tab (replaceable) |
78
- * | `tab-<id>-badge-icon` | If `showLeadingBadgeIcon` is true | Badge icon for a specific tab (replaceable) |
89
+ * | `tab-<id>-icon` | If `hasLeadingIcon` is true | Leading icon for a specific tab (replaceable) |
90
+ * | `tab-<id>-<iconSlotName>` | For each badge that declares an `iconSlotName` | Custom icon for a specific tab's badge (replaceable). The deprecated single-badge path uses `tab-<id>-badge-icon`. |
79
91
  *
80
92
  * ---
81
93
  *
@@ -94,7 +106,7 @@ export interface TabData {
94
106
  * - If using custom icons, provide them via the appropriate named slot for each tab.
95
107
  *
96
108
  * @slot tab-<id>-icon - Leading icon slot for each tab (shown when `hasLeadingIcon` is true for that tab)
97
- * @slot tab-<id>-badge-icon - Badge icon slot for each tab (shown when `showLeadingBadgeIcon` is true for that tab)
109
+ * @slot tab-<id>-<iconSlotName> - Custom badge icon slot for each tab, one per badge that declares an `iconSlotName`. The deprecated single-badge path uses `tab-<id>-badge-icon`.
98
110
  * @fires tab-selected {CustomEvent<{tab: TabData, id: string, index: number}>} Fired when a tab is selected.
99
111
  * @fires tab-closed {CustomEvent<{tab: TabData, id: string, index: number}>} Fired when a tab's close button is clicked.
100
112
  * @fires add-new-tab {CustomEvent<void>} Fired when the "add new tab" button is clicked.
@@ -108,12 +120,13 @@ export declare class ObcTabRow extends LitElement {
108
120
  * - `subtitle` (string): Contextual text shown below the title when subtitle display is enabled.
109
121
  * - `showSubtitle` (boolean): Optional per-tab override for displaying the subtitle.
110
122
  * - `hasLeadingIcon` (boolean): Whether to show a leading icon (default: true).
111
- * - `hasBadge` (boolean): Whether to show a badge on the tab.
112
- * - `badgeCount` (number): Number to display in the badge.
113
- * - `badgeType` (BadgeType): Visual style of the badge (e.g., notification, alarm, enhance).
114
- * - `badgeSize` (BadgeSize): Size of the badge (e.g., regular, large).
115
- * - `badgeShowNumber` (boolean): If true, shows the badge number.
116
- * - `showLeadingBadgeIcon` (boolean): If true, shows a badge icon.
123
+ * - `badges` (TabItemBadge[]): One or more badges to display on the tab. Takes precedence over the deprecated single-badge fields below.
124
+ * - `hasBadge` (boolean, deprecated): Whether to show a badge on the tab.
125
+ * - `badgeCount` (number, deprecated): Number to display in the badge.
126
+ * - `badgeType` (BadgeType, deprecated): Visual style of the badge (e.g., notification, alarm, enhance).
127
+ * - `badgeSize` (BadgeSize, deprecated): Size of the badge (e.g., regular, large).
128
+ * - `badgeShowNumber` (boolean, deprecated): If true, shows the badge number.
129
+ * - `showLeadingBadgeIcon` (boolean, deprecated): If true, shows a badge icon.
117
130
  * - `disabled` (boolean): If true, disables the tab.
118
131
  */
119
132
  tabs: TabData[];
@@ -129,6 +142,7 @@ export declare class ObcTabRow extends LitElement {
129
142
  * Default: `false`.
130
143
  */
131
144
  hasClose: boolean;
145
+ centerContent: boolean;
132
146
  /**
133
147
  * Enables "hug" mode for a more compact tab layout with reduced padding.
134
148
  *
@@ -1 +1 @@
1
- {"version":3,"file":"tab-row.d.ts","sourceRoot":"","sources":["../../../src/components/tab-row/tab-row.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkB,MAAM,KAAK,CAAC;AAIhD,OAAO,yBAAyB,CAAC;AACjC,OAAO,+BAA+B,CAAC;AACvC,OAAO,iCAAiC,CAAC;AAEzC,OAAO,4BAA4B,CAAC;AACpC,OAAO,EAAC,SAAS,EAAE,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,qBACa,SAAU,SAAQ,UAAU;IACvC;;;;;;;;;;;;;;;OAeG;IACsB,IAAI,EAAE,OAAO,EAAE,CAAM;IAE9C;;;;OAIG;IACqD,aAAa,SAAM;IAE3E;;;;OAIG;IACgD,QAAQ,UAAS;IAEpE;;;;OAIG;IACwB,GAAG,UAAS;IAEvC;;;;OAIG;IACoD,YAAY,UAAS;IAE5E;;;;OAIG;IACsD,YAAY,UAAS;IAE9E,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,SAAS;IA6CR,MAAM;IAwBf,OAAgB,MAAM,0BAA2B;CAClD"}
1
+ {"version":3,"file":"tab-row.d.ts","sourceRoot":"","sources":["../../../src/components/tab-row/tab-row.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAkB,MAAM,KAAK,CAAC;AAIhD,OAAO,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,yBAAyB,CAAC;AAC1D,OAAO,+BAA+B,CAAC;AACvC,OAAO,iCAAiC,CAAC;AAEzC,OAAO,4BAA4B,CAAC;AACpC,OAAO,EAAC,SAAS,EAAE,SAAS,EAAC,MAAM,mBAAmB,CAAC;AAEvD,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,MAAM,CAAC,EAAE,YAAY,EAAE,CAAC;IACxB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wCAAwC;IACxC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,wCAAwC;IACxC,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,wCAAwC;IACxC,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,wCAAwC;IACxC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgFG;AACH,qBACa,SAAU,SAAQ,UAAU;IACvC;;;;;;;;;;;;;;;;OAgBG;IACsB,IAAI,EAAE,OAAO,EAAE,CAAM;IAE9C;;;;OAIG;IACqD,aAAa,SAAM;IAE3E;;;;OAIG;IACgD,QAAQ,UAAS;IAEzC,aAAa,UAAS;IAEjD;;;;OAIG;IACwB,GAAG,UAAS;IAEvC;;;;OAIG;IACoD,YAAY,UAAS;IAE5E;;;;OAIG;IACsD,YAAY,UAAS;IAE9E,OAAO,CAAC,cAAc;IAatB,OAAO,CAAC,cAAc;IAsBtB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,SAAS;IAiER,MAAM;IAwBf,OAAgB,MAAM,0BAA2B;CAClD"}
@@ -24,6 +24,7 @@ let ObcTabRow = class extends LitElement {
24
24
  this.tabs = [];
25
25
  this.selectedTabId = "";
26
26
  this.hasClose = false;
27
+ this.centerContent = false;
27
28
  this.hug = false;
28
29
  this.showSubtitle = false;
29
30
  this.hasAddNewTab = false;
@@ -68,8 +69,17 @@ let ObcTabRow = class extends LitElement {
68
69
  }
69
70
  renderTab(tab, index) {
70
71
  const isFirst = index === 0;
72
+ const previousTabSelected = this.selectedTabId === this.tabs[index - 1]?.id;
71
73
  const isChecked = tab.id === this.selectedTabId;
72
74
  const showSubtitle = tab.showSubtitle ?? this.showSubtitle;
75
+ const badgeIconSlots = [
76
+ ...new Set(
77
+ (tab.badges ?? []).map((badge) => badge.iconSlotName).filter((slotName) => slotName !== void 0)
78
+ )
79
+ ];
80
+ if ((tab.showLeadingBadgeIcon ?? false) && !badgeIconSlots.includes("badge-icon")) {
81
+ badgeIconSlots.push("badge-icon");
82
+ }
73
83
  return html`
74
84
  <obc-tab-item
75
85
  .title=${tab.title}
@@ -79,10 +89,12 @@ let ObcTabRow = class extends LitElement {
79
89
  .hasClose=${this.hasClose}
80
90
  .hasLeadingIcon=${tab.hasLeadingIcon ?? true}
81
91
  .hasTitle=${true}
82
- .hasDivider=${!isFirst}
92
+ .hasDivider=${!isFirst && !previousTabSelected}
83
93
  .hug=${this.hug}
94
+ .centerContent=${this.centerContent}
84
95
  .disabled=${tab.disabled || false}
85
- .hasBadge=${tab.hasBadge || tab.badgeCount !== void 0 && tab.badgeCount > 0}
96
+ .badges=${tab.badges ?? []}
97
+ .hasBadge=${tab.hasBadge || false}
86
98
  .badgeCount=${tab.badgeCount || 0}
87
99
  .badgeType=${tab.badgeType ?? BadgeType.regular}
88
100
  .badgeSize=${tab.badgeSize ?? BadgeSize.regular}
@@ -97,11 +109,13 @@ let ObcTabRow = class extends LitElement {
97
109
  </slot>
98
110
  ` : ""}
99
111
  <span slot="title">${tab.title}</span>
100
- ${tab.showLeadingBadgeIcon ? html`
101
- <slot name="tab-${tab.id}-badge-icon" slot="badge-icon">
102
- <obi-placeholder></obi-placeholder>
103
- </slot>
104
- ` : ""}
112
+ ${badgeIconSlots.map(
113
+ (slotName) => html`
114
+ <slot name="tab-${tab.id}-${slotName}" slot=${slotName}>
115
+ <obi-placeholder></obi-placeholder>
116
+ </slot>
117
+ `
118
+ )}
105
119
  </obc-tab-item>
106
120
  `;
107
121
  }
@@ -137,6 +151,9 @@ __decorateClass([
137
151
  __decorateClass([
138
152
  property({ type: Boolean, attribute: "has-close" })
139
153
  ], ObcTabRow.prototype, "hasClose", 2);
154
+ __decorateClass([
155
+ property({ type: Boolean })
156
+ ], ObcTabRow.prototype, "centerContent", 2);
140
157
  __decorateClass([
141
158
  property({ type: Boolean })
142
159
  ], ObcTabRow.prototype, "hug", 2);
@@ -1 +1 @@
1
- {"version":3,"file":"tab-row.js","sources":["../../../src/components/tab-row/tab-row.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {repeat} from 'lit/directives/repeat.js';\nimport compentStyle from './tab-row.css?inline';\nimport '../tab-item/tab-item.js';\nimport '../icon-button/icon-button.js';\nimport '../../icons/icon-placeholder.js';\nimport {customElement} from '../../decorator.js';\nimport '../../icons/icon-up-iec.js';\nimport {BadgeType, BadgeSize} from '../badge/badge.js';\n\nexport interface TabData {\n id: string;\n title: string;\n subtitle?: string;\n showSubtitle?: boolean;\n hasLeadingIcon?: boolean;\n hasBadge?: boolean;\n badgeCount?: number;\n badgeType?: BadgeType;\n badgeSize?: BadgeSize;\n badgeShowNumber?: boolean;\n showLeadingBadgeIcon?: boolean;\n disabled?: boolean;\n}\n\n/**\n * `<obc-tab-row>` – A horizontal tab navigation bar for switching between multiple content sections.\n *\n * Displays a row of interactive tabs, each representing a distinct view or section. Supports subtitles, badges, icons, close buttons, and an optional \"add new tab\" action. Designed for use cases where users need to quickly switch between related content areas, such as dashboards, settings, or document editors.\n *\n * ---\n *\n * ### Features\n * - **Tab Selection:** Only one tab can be selected at a time; selection is managed via the `selectedTabId` property.\n * - **Closeable Tabs:** Optionally display a close button on each tab (`hasClose`), allowing users to remove tabs dynamically.\n * - **Add New Tab:** Optionally show an \"add new tab\" button at the end of the row (`hasAddNewTab`), emitting an event when clicked.\n * - **Subtitles:** Optionally show secondary contextual text below each tab title (`showSubtitle` and `subtitle`).\n * - **Badges:** Tabs can display badges with counts and types (e.g., notification, alarm, enhance), supporting different badge sizes and optional hiding of the number.\n * - **Icons:** Each tab can show a leading icon (customizable via slot), and optionally a badge icon.\n * - **Disabled Tabs:** Individual tabs can be disabled to prevent user interaction.\n * - **Hug Mode:** When `hug` is enabled, tabs use a compact layout with reduced padding.\n * - **Responsive Layout:** Tabs are arranged horizontally and adapt to the available width.\n *\n * ---\n *\n * ### Usage Guidelines\n * Use `<obc-tab-row>` to organize content into logical sections that users can switch between without leaving the current page. Ideal for navigation in multi-view interfaces, such as settings panels, dashboards, or editors. Each tab should represent a distinct, high-level section. Avoid using tabs for navigation between unrelated pages or for single-action toggles.\n *\n * - Use badges to highlight new activity or counts (e.g., unread messages).\n * - Use the close button for tabs that represent removable or temporary content (e.g., documents, chat sessions).\n * - The \"add new tab\" action is suitable for interfaces where users can create new sections dynamically.\n * - For best accessibility, ensure each tab has a unique `id` and descriptive `title`.\n *\n * **TODO(designer):** Confirm if there are recommended limits on the number of tabs, or guidance for handling overflow (e.g., scrolling, collapsing).\n *\n * ---\n *\n * ### Example\n * ```html\n * <obc-tab-row\n * .tabs=${[\n * {id: 'tab1', title: 'Inbox', subtitle: 'Monitoring', hasBadge: true, badgeCount: 5, badgeType: 'notification'},\n * {id: 'tab2', title: 'Updates'},\n * {id: 'tab3', title: 'Settings', hasLeadingIcon: true}\n * ]}\n * selectedTabId=\"tab1\"\n * show-subtitle\n * hasClose\n * hasAddNewTab\n * >\n * <obi-placeholder slot=\"tab-tab1-icon\"></obi-placeholder>\n * <obi-placeholder slot=\"tab-tab3-icon\"></obi-placeholder>\n * </obc-tab-row>\n * ```\n *\n * ---\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |--------------------------|------------------------------------|------------------------------------------------------|\n * | `tab-<id>-icon` | If `hasLeadingIcon` is true | Leading icon for a specific tab (replaceable) |\n * | `tab-<id>-badge-icon` | If `showLeadingBadgeIcon` is true | Badge icon for a specific tab (replaceable) |\n *\n * ---\n *\n * ### Events\n * - `tab-selected` – Fired when a tab is selected. Detail: `{tab, id, index}`.\n * - `tab-closed` – Fired when a tab's close button is clicked. Detail: `{tab, id, index}`.\n * - `add-new-tab` – Fired when the \"add new tab\" button is clicked. No detail.\n *\n * ---\n *\n * ### Best Practices\n * - Only one tab should be selected at a time.\n * - Use badges sparingly to avoid overwhelming the user.\n * - Avoid using the close button for tabs that should always be present.\n * - For accessibility, ensure tab titles are clear and concise.\n * - If using custom icons, provide them via the appropriate named slot for each tab.\n *\n * @slot tab-<id>-icon - Leading icon slot for each tab (shown when `hasLeadingIcon` is true for that tab)\n * @slot tab-<id>-badge-icon - Badge icon slot for each tab (shown when `showLeadingBadgeIcon` is true for that tab)\n * @fires tab-selected {CustomEvent<{tab: TabData, id: string, index: number}>} Fired when a tab is selected.\n * @fires tab-closed {CustomEvent<{tab: TabData, id: string, index: number}>} Fired when a tab's close button is clicked.\n * @fires add-new-tab {CustomEvent<void>} Fired when the \"add new tab\" button is clicked.\n */\n@customElement('obc-tab-row')\nexport class ObcTabRow extends LitElement {\n /**\n * The list of tabs to display. Each tab is defined by an object with properties such as `id`, `title`, `subtitle`, `showSubtitle`, `hasLeadingIcon`, `hasBadge`, `badgeCount`, `badgeType`, `badgeSize`, `badgeShowNumber`, `showLeadingBadgeIcon`, and `disabled`.\n *\n * - `id` (string): Unique identifier for the tab.\n * - `title` (string): Display label for the tab.\n * - `subtitle` (string): Contextual text shown below the title when subtitle display is enabled.\n * - `showSubtitle` (boolean): Optional per-tab override for displaying the subtitle.\n * - `hasLeadingIcon` (boolean): Whether to show a leading icon (default: true).\n * - `hasBadge` (boolean): Whether to show a badge on the tab.\n * - `badgeCount` (number): Number to display in the badge.\n * - `badgeType` (BadgeType): Visual style of the badge (e.g., notification, alarm, enhance).\n * - `badgeSize` (BadgeSize): Size of the badge (e.g., regular, large).\n * - `badgeShowNumber` (boolean): If true, shows the badge number.\n * - `showLeadingBadgeIcon` (boolean): If true, shows a badge icon.\n * - `disabled` (boolean): If true, disables the tab.\n */\n @property({type: Array}) tabs: TabData[] = [];\n\n /**\n * The `id` of the currently selected tab. Only one tab can be selected at a time.\n *\n * Changing this property updates the selected tab visually and emits the `tab-selected` event when changed by user interaction.\n */\n @property({type: String, attribute: 'selected-tab-id'}) selectedTabId = '';\n\n /**\n * Whether to display a close button on each tab. When enabled, users can remove tabs individually.\n *\n * Default: `false`.\n */\n @property({type: Boolean, attribute: 'has-close'}) hasClose = false;\n\n /**\n * Enables \"hug\" mode for a more compact tab layout with reduced padding.\n *\n * Default: `false`.\n */\n @property({type: Boolean}) hug = false;\n\n /**\n * Whether to display subtitle text for each tab. Individual tabs can override this with `tab.showSubtitle`.\n *\n * Default: `false`.\n */\n @property({type: Boolean, attribute: 'show-subtitle'}) showSubtitle = false;\n\n /**\n * Whether to display an \"add new tab\" button at the end of the tab row. When clicked, emits the `add-new-tab` event.\n *\n * Default: `false`.\n */\n @property({type: Boolean, attribute: 'has-add-new-tab'}) hasAddNewTab = false;\n\n private handleTabClick(_: Event, tabId: string) {\n const tabIndex = this.tabs.findIndex((t) => t.id === tabId);\n if (tabIndex === -1) return;\n this.selectedTabId = this.tabs[tabIndex].id;\n this.dispatchEvent(\n new CustomEvent('tab-selected', {\n detail: {tab: this.tabs[tabIndex], id: tabId, index: tabIndex},\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private handleTabClose(event: Event, tabId: string) {\n event.stopPropagation();\n const tabIndex = this.tabs.findIndex((t) => t.id === tabId);\n if (tabIndex === -1) return;\n const removedTab = this.tabs[tabIndex];\n this.tabs = [\n ...this.tabs.slice(0, tabIndex),\n ...this.tabs.slice(tabIndex + 1),\n ];\n if (removedTab.id === this.selectedTabId && this.tabs.length) {\n const newIdx = Math.min(tabIndex, this.tabs.length - 1);\n this.selectedTabId = this.tabs[newIdx].id;\n }\n this.dispatchEvent(\n new CustomEvent('tab-closed', {\n detail: {tab: removedTab, id: removedTab.id, index: tabIndex},\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private handleAddNewTab() {\n this.dispatchEvent(\n new CustomEvent('add-new-tab', {bubbles: true, composed: true})\n );\n }\n\n private renderTab(tab: TabData, index: number) {\n const isFirst = index === 0;\n const isChecked = tab.id === this.selectedTabId;\n const showSubtitle = tab.showSubtitle ?? this.showSubtitle;\n return html`\n <obc-tab-item\n .title=${tab.title}\n .subtitle=${tab.subtitle ?? ''}\n .showSubtitle=${showSubtitle}\n .checked=${isChecked}\n .hasClose=${this.hasClose}\n .hasLeadingIcon=${tab.hasLeadingIcon ?? true}\n .hasTitle=${true}\n .hasDivider=${!isFirst}\n .hug=${this.hug}\n .disabled=${tab.disabled || false}\n .hasBadge=${tab.hasBadge ||\n (tab.badgeCount !== undefined && tab.badgeCount > 0)}\n .badgeCount=${tab.badgeCount || 0}\n .badgeType=${tab.badgeType ?? BadgeType.regular}\n .badgeSize=${tab.badgeSize ?? BadgeSize.regular}\n .badgeShowNumber=${tab.badgeShowNumber ?? true}\n .showLeadingBadgeIcon=${tab.showLeadingBadgeIcon || false}\n @tab-click=${(e: Event) => this.handleTabClick(e, tab.id)}\n @tab-close=${(e: Event) => this.handleTabClose(e, tab.id)}\n >\n ${tab.hasLeadingIcon !== false\n ? html`\n <slot name=\"tab-${tab.id}-icon\" slot=\"leading-icon\">\n <obi-placeholder></obi-placeholder>\n </slot>\n `\n : ''}\n <span slot=\"title\">${tab.title}</span>\n ${tab.showLeadingBadgeIcon\n ? html`\n <slot name=\"tab-${tab.id}-badge-icon\" slot=\"badge-icon\">\n <obi-placeholder></obi-placeholder>\n </slot>\n `\n : ''}\n </obc-tab-item>\n `;\n }\n\n override render() {\n return html`\n <div class=\"wrapper\" role=\"tablist\">\n ${repeat(\n this.tabs,\n (t) => t.id,\n (t, i) => this.renderTab(t, i)\n )}\n ${this.hasAddNewTab\n ? html`\n <obc-icon-button\n class=\"add-new-tab\"\n variant=\"flat\"\n @click=${this.handleAddNewTab}\n aria-label=\"Add new tab\"\n >\n <obi-up-iec></obi-up-iec>\n </obc-icon-button>\n `\n : ''}\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tab-row.js","sources":["../../../src/components/tab-row/tab-row.ts"],"sourcesContent":["import {LitElement, html, unsafeCSS} from 'lit';\nimport {property} from 'lit/decorators.js';\nimport {repeat} from 'lit/directives/repeat.js';\nimport compentStyle from './tab-row.css?inline';\nimport '../tab-item/tab-item.js';\nimport type {TabItemBadge} from '../tab-item/tab-item.js';\nimport '../icon-button/icon-button.js';\nimport '../../icons/icon-placeholder.js';\nimport {customElement} from '../../decorator.js';\nimport '../../icons/icon-up-iec.js';\nimport {BadgeType, BadgeSize} from '../badge/badge.js';\n\nexport interface TabData {\n id: string;\n title: string;\n subtitle?: string;\n showSubtitle?: boolean;\n hasLeadingIcon?: boolean;\n /**\n * One or more badges to display on the tab. When non-empty this takes\n * precedence over the deprecated single-badge fields below.\n */\n badges?: TabItemBadge[];\n /** @deprecated Use `badges` instead. */\n hasBadge?: boolean;\n /** @deprecated Use `badges` instead. */\n badgeCount?: number;\n /** @deprecated Use `badges` instead. */\n badgeType?: BadgeType;\n /** @deprecated Use `badges` instead. */\n badgeSize?: BadgeSize;\n /** @deprecated Use `badges` instead. */\n badgeShowNumber?: boolean;\n /** @deprecated Use `badges` instead. */\n showLeadingBadgeIcon?: boolean;\n disabled?: boolean;\n}\n\n/**\n * `<obc-tab-row>` – A horizontal tab navigation bar for switching between multiple content sections.\n *\n * Displays a row of interactive tabs, each representing a distinct view or section. Supports subtitles, badges, icons, close buttons, and an optional \"add new tab\" action. Designed for use cases where users need to quickly switch between related content areas, such as dashboards, settings, or document editors.\n *\n * ---\n *\n * ### Features\n * - **Tab Selection:** Only one tab can be selected at a time; selection is managed via the `selectedTabId` property.\n * - **Closeable Tabs:** Optionally display a close button on each tab (`hasClose`), allowing users to remove tabs dynamically.\n * - **Add New Tab:** Optionally show an \"add new tab\" button at the end of the row (`hasAddNewTab`), emitting an event when clicked.\n * - **Subtitles:** Optionally show secondary contextual text below each tab title (`showSubtitle` and `subtitle`).\n * - **Badges:** Tabs can display badges with counts and types (e.g., notification, alarm, enhance), supporting different badge sizes and optional hiding of the number.\n * - **Icons:** Each tab can show a leading icon (customizable via slot), and optionally a badge icon.\n * - **Disabled Tabs:** Individual tabs can be disabled to prevent user interaction.\n * - **Hug Mode:** When `hug` is enabled, tabs use a compact layout with reduced padding.\n * - **Responsive Layout:** Tabs are arranged horizontally and adapt to the available width.\n *\n * ---\n *\n * ### Usage Guidelines\n * Use `<obc-tab-row>` to organize content into logical sections that users can switch between without leaving the current page. Ideal for navigation in multi-view interfaces, such as settings panels, dashboards, or editors. Each tab should represent a distinct, high-level section. Avoid using tabs for navigation between unrelated pages or for single-action toggles.\n *\n * - Use badges to highlight new activity or counts (e.g., unread messages).\n * - Use the close button for tabs that represent removable or temporary content (e.g., documents, chat sessions).\n * - The \"add new tab\" action is suitable for interfaces where users can create new sections dynamically.\n * - For best accessibility, ensure each tab has a unique `id` and descriptive `title`.\n *\n * **TODO(designer):** Confirm if there are recommended limits on the number of tabs, or guidance for handling overflow (e.g., scrolling, collapsing).\n *\n * ---\n *\n * ### Example\n * ```html\n * <obc-tab-row\n * .tabs=${[\n * {id: 'tab1', title: 'Inbox', subtitle: 'Monitoring', hasBadge: true, badgeCount: 5, badgeType: 'notification'},\n * {id: 'tab2', title: 'Updates'},\n * {id: 'tab3', title: 'Settings', hasLeadingIcon: true}\n * ]}\n * selectedTabId=\"tab1\"\n * show-subtitle\n * hasClose\n * hasAddNewTab\n * >\n * <obi-placeholder slot=\"tab-tab1-icon\"></obi-placeholder>\n * <obi-placeholder slot=\"tab-tab3-icon\"></obi-placeholder>\n * </obc-tab-row>\n * ```\n *\n * ---\n *\n * ### Slots\n *\n * | Slot Name | Renders When... | Purpose |\n * |--------------------------|------------------------------------|------------------------------------------------------|\n * | `tab-<id>-icon` | If `hasLeadingIcon` is true | Leading icon for a specific tab (replaceable) |\n * | `tab-<id>-<iconSlotName>` | For each badge that declares an `iconSlotName` | Custom icon for a specific tab's badge (replaceable). The deprecated single-badge path uses `tab-<id>-badge-icon`. |\n *\n * ---\n *\n * ### Events\n * - `tab-selected` – Fired when a tab is selected. Detail: `{tab, id, index}`.\n * - `tab-closed` – Fired when a tab's close button is clicked. Detail: `{tab, id, index}`.\n * - `add-new-tab` – Fired when the \"add new tab\" button is clicked. No detail.\n *\n * ---\n *\n * ### Best Practices\n * - Only one tab should be selected at a time.\n * - Use badges sparingly to avoid overwhelming the user.\n * - Avoid using the close button for tabs that should always be present.\n * - For accessibility, ensure tab titles are clear and concise.\n * - If using custom icons, provide them via the appropriate named slot for each tab.\n *\n * @slot tab-<id>-icon - Leading icon slot for each tab (shown when `hasLeadingIcon` is true for that tab)\n * @slot tab-<id>-<iconSlotName> - Custom badge icon slot for each tab, one per badge that declares an `iconSlotName`. The deprecated single-badge path uses `tab-<id>-badge-icon`.\n * @fires tab-selected {CustomEvent<{tab: TabData, id: string, index: number}>} Fired when a tab is selected.\n * @fires tab-closed {CustomEvent<{tab: TabData, id: string, index: number}>} Fired when a tab's close button is clicked.\n * @fires add-new-tab {CustomEvent<void>} Fired when the \"add new tab\" button is clicked.\n */\n@customElement('obc-tab-row')\nexport class ObcTabRow extends LitElement {\n /**\n * The list of tabs to display. Each tab is defined by an object with properties such as `id`, `title`, `subtitle`, `showSubtitle`, `hasLeadingIcon`, `hasBadge`, `badgeCount`, `badgeType`, `badgeSize`, `badgeShowNumber`, `showLeadingBadgeIcon`, and `disabled`.\n *\n * - `id` (string): Unique identifier for the tab.\n * - `title` (string): Display label for the tab.\n * - `subtitle` (string): Contextual text shown below the title when subtitle display is enabled.\n * - `showSubtitle` (boolean): Optional per-tab override for displaying the subtitle.\n * - `hasLeadingIcon` (boolean): Whether to show a leading icon (default: true).\n * - `badges` (TabItemBadge[]): One or more badges to display on the tab. Takes precedence over the deprecated single-badge fields below.\n * - `hasBadge` (boolean, deprecated): Whether to show a badge on the tab.\n * - `badgeCount` (number, deprecated): Number to display in the badge.\n * - `badgeType` (BadgeType, deprecated): Visual style of the badge (e.g., notification, alarm, enhance).\n * - `badgeSize` (BadgeSize, deprecated): Size of the badge (e.g., regular, large).\n * - `badgeShowNumber` (boolean, deprecated): If true, shows the badge number.\n * - `showLeadingBadgeIcon` (boolean, deprecated): If true, shows a badge icon.\n * - `disabled` (boolean): If true, disables the tab.\n */\n @property({type: Array}) tabs: TabData[] = [];\n\n /**\n * The `id` of the currently selected tab. Only one tab can be selected at a time.\n *\n * Changing this property updates the selected tab visually and emits the `tab-selected` event when changed by user interaction.\n */\n @property({type: String, attribute: 'selected-tab-id'}) selectedTabId = '';\n\n /**\n * Whether to display a close button on each tab. When enabled, users can remove tabs individually.\n *\n * Default: `false`.\n */\n @property({type: Boolean, attribute: 'has-close'}) hasClose = false;\n\n @property({type: Boolean}) centerContent = false;\n\n /**\n * Enables \"hug\" mode for a more compact tab layout with reduced padding.\n *\n * Default: `false`.\n */\n @property({type: Boolean}) hug = false;\n\n /**\n * Whether to display subtitle text for each tab. Individual tabs can override this with `tab.showSubtitle`.\n *\n * Default: `false`.\n */\n @property({type: Boolean, attribute: 'show-subtitle'}) showSubtitle = false;\n\n /**\n * Whether to display an \"add new tab\" button at the end of the tab row. When clicked, emits the `add-new-tab` event.\n *\n * Default: `false`.\n */\n @property({type: Boolean, attribute: 'has-add-new-tab'}) hasAddNewTab = false;\n\n private handleTabClick(_: Event, tabId: string) {\n const tabIndex = this.tabs.findIndex((t) => t.id === tabId);\n if (tabIndex === -1) return;\n this.selectedTabId = this.tabs[tabIndex].id;\n this.dispatchEvent(\n new CustomEvent('tab-selected', {\n detail: {tab: this.tabs[tabIndex], id: tabId, index: tabIndex},\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private handleTabClose(event: Event, tabId: string) {\n event.stopPropagation();\n const tabIndex = this.tabs.findIndex((t) => t.id === tabId);\n if (tabIndex === -1) return;\n const removedTab = this.tabs[tabIndex];\n this.tabs = [\n ...this.tabs.slice(0, tabIndex),\n ...this.tabs.slice(tabIndex + 1),\n ];\n if (removedTab.id === this.selectedTabId && this.tabs.length) {\n const newIdx = Math.min(tabIndex, this.tabs.length - 1);\n this.selectedTabId = this.tabs[newIdx].id;\n }\n this.dispatchEvent(\n new CustomEvent('tab-closed', {\n detail: {tab: removedTab, id: removedTab.id, index: tabIndex},\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private handleAddNewTab() {\n this.dispatchEvent(\n new CustomEvent('add-new-tab', {bubbles: true, composed: true})\n );\n }\n\n private renderTab(tab: TabData, index: number) {\n const isFirst = index === 0;\n const previousTabSelected = this.selectedTabId === this.tabs[index - 1]?.id;\n const isChecked = tab.id === this.selectedTabId;\n const showSubtitle = tab.showSubtitle ?? this.showSubtitle;\n // Forward a light-DOM slot for every distinct `iconSlotName` declared by the\n // tab's badges (new `badges` array), plus the deprecated single badge-icon\n // slot. obc-tab-item renders `<slot name=${iconSlotName} slot=\"badge-icon\">`\n // inside each badge, so obc-tab-row must project matching content into that\n // slot. Slots are namespaced by tab id to stay unique across the row.\n const badgeIconSlots = [\n ...new Set(\n (tab.badges ?? [])\n .map((badge) => badge.iconSlotName)\n .filter((slotName): slotName is string => slotName !== undefined)\n ),\n ];\n if (\n (tab.showLeadingBadgeIcon ?? false) &&\n !badgeIconSlots.includes('badge-icon')\n ) {\n badgeIconSlots.push('badge-icon');\n }\n return html`\n <obc-tab-item\n .title=${tab.title}\n .subtitle=${tab.subtitle ?? ''}\n .showSubtitle=${showSubtitle}\n .checked=${isChecked}\n .hasClose=${this.hasClose}\n .hasLeadingIcon=${tab.hasLeadingIcon ?? true}\n .hasTitle=${true}\n .hasDivider=${!isFirst && !previousTabSelected}\n .hug=${this.hug}\n .centerContent=${this.centerContent}\n .disabled=${tab.disabled || false}\n .badges=${tab.badges ?? []}\n .hasBadge=${tab.hasBadge || false}\n .badgeCount=${tab.badgeCount || 0}\n .badgeType=${tab.badgeType ?? BadgeType.regular}\n .badgeSize=${tab.badgeSize ?? BadgeSize.regular}\n .badgeShowNumber=${tab.badgeShowNumber ?? true}\n .showLeadingBadgeIcon=${tab.showLeadingBadgeIcon || false}\n @tab-click=${(e: Event) => this.handleTabClick(e, tab.id)}\n @tab-close=${(e: Event) => this.handleTabClose(e, tab.id)}\n >\n ${tab.hasLeadingIcon !== false\n ? html`\n <slot name=\"tab-${tab.id}-icon\" slot=\"leading-icon\">\n <obi-placeholder></obi-placeholder>\n </slot>\n `\n : ''}\n <span slot=\"title\">${tab.title}</span>\n ${badgeIconSlots.map(\n (slotName) => html`\n <slot name=\"tab-${tab.id}-${slotName}\" slot=${slotName}>\n <obi-placeholder></obi-placeholder>\n </slot>\n `\n )}\n </obc-tab-item>\n `;\n }\n\n override render() {\n return html`\n <div class=\"wrapper\" role=\"tablist\">\n ${repeat(\n this.tabs,\n (t) => t.id,\n (t, i) => this.renderTab(t, i)\n )}\n ${this.hasAddNewTab\n ? html`\n <obc-icon-button\n class=\"add-new-tab\"\n variant=\"flat\"\n @click=${this.handleAddNewTab}\n aria-label=\"Add new tab\"\n >\n <obi-up-iec></obi-up-iec>\n </obc-icon-button>\n `\n : ''}\n </div>\n `;\n }\n\n static override styles = unsafeCSS(compentStyle);\n}\n"],"names":[],"mappings":"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"}
@@ -34,6 +34,11 @@ const componentStyle = css`* {
34
34
  justify-content: var(--alignment-justify, flex-end);
35
35
  height: var(--height);
36
36
  overflow: hidden;
37
+ /* Opt-in: animate a \`size\` change (height + font-size below). Defaults to 0s
38
+ (instant, current behavior) so existing usages and snapshots are unchanged;
39
+ a consumer sets \`--obc-textbox-size-transition\` (e.g. 300ms) to animate the
40
+ swap — used by readout-list-item's setpoint flip-flop. */
41
+ transition: height var(--obc-textbox-size-transition, 0s) ease;
37
42
  }
38
43
 
39
44
  /* The spacer must share the content's exact font metrics so the width it
@@ -45,6 +50,8 @@ const componentStyle = css`* {
45
50
  font-size: calc(var(--height) - 2 * var(--padding));
46
51
  font-size-adjust: cap-height 1;
47
52
  white-space: nowrap;
53
+ /* Opt-in size animation — see \`.inner-wrapper\`. */
54
+ transition: font-size var(--obc-textbox-size-transition, 0s) ease;
48
55
  }
49
56
 
50
57
  .content {
@@ -52,23 +59,40 @@ const componentStyle = css`* {
52
59
  text-box-edge: cap alphabetic;
53
60
  }
54
61
 
55
- .wrapper.size-xs .inner-wrapper {
62
+ /* Opt-in numeric mode: fixed-width lining numerals so values stay
63
+ column-aligned and width-stable. Applied to the spacer too so the reserved
64
+ width matches the rendered digits exactly. */
65
+
66
+ .wrapper.tabular-nums .content,
67
+ .wrapper.tabular-nums .length-spacer {
68
+ font-variant-numeric: tabular-nums lining-nums;
69
+ font-feature-settings:
70
+ "ss04" on,
71
+ "tnum" on,
72
+ "lnum" on;
73
+ }
74
+
75
+ /* Size override is set on \`.wrapper\` (not \`.inner-wrapper\`) so it reaches BOTH
76
+ the visible \`.content\` AND the sibling \`.length-spacer\`; otherwise the spacer
77
+ keeps the default (m) \`--height\` and reserves width at the wrong font size. */
78
+
79
+ .wrapper.size-xs {
56
80
  --height: 16px;
57
81
  }
58
82
 
59
- .wrapper.size-s .inner-wrapper {
83
+ .wrapper.size-s {
60
84
  --height: 20px;
61
85
  }
62
86
 
63
- .wrapper.size-m .inner-wrapper {
87
+ .wrapper.size-m {
64
88
  --height: 24px;
65
89
  }
66
90
 
67
- .wrapper.size-l .inner-wrapper {
91
+ .wrapper.size-l {
68
92
  --height: 32px;
69
93
  }
70
94
 
71
- .wrapper.size-xl .inner-wrapper {
95
+ .wrapper.size-xl {
72
96
  --height: 40px;
73
97
  }
74
98
 
@@ -1 +1 @@
1
- {"version":3,"file":"textbox.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"textbox.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}