@krollins/blueprint 0.1.12 → 0.1.14

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 (109) hide show
  1. package/README.md +9 -3
  2. package/README.npm.md +9 -3
  3. package/dist/components/accordion.js +393 -0
  4. package/dist/components/accordion.js.map +1 -0
  5. package/dist/components/alert.js +213 -0
  6. package/dist/components/alert.js.map +1 -0
  7. package/dist/components/avatar.js +237 -0
  8. package/dist/components/avatar.js.map +1 -0
  9. package/dist/components/badge/badge.d.ts.map +1 -1
  10. package/dist/components/badge.js +144 -0
  11. package/dist/components/badge.js.map +1 -0
  12. package/dist/components/breadcrumb.js +481 -0
  13. package/dist/components/breadcrumb.js.map +1 -0
  14. package/dist/components/button.js +192 -0
  15. package/dist/components/button.js.map +1 -0
  16. package/dist/components/card.js +223 -0
  17. package/dist/components/card.js.map +1 -0
  18. package/dist/components/checkbox.js +336 -0
  19. package/dist/components/checkbox.js.map +1 -0
  20. package/dist/components/code-block/code-block.d.ts +143 -0
  21. package/dist/components/code-block/code-block.d.ts.map +1 -0
  22. package/dist/components/code-block/code-block.style.d.ts +2 -0
  23. package/dist/components/code-block/code-block.style.d.ts.map +1 -0
  24. package/dist/components/code-block.js +587 -0
  25. package/dist/components/code-block.js.map +1 -0
  26. package/dist/components/color-picker/color-picker.d.ts.map +1 -1
  27. package/dist/components/color-picker.js +1660 -0
  28. package/dist/components/color-picker.js.map +1 -0
  29. package/dist/components/combobox.js +595 -0
  30. package/dist/components/combobox.js.map +1 -0
  31. package/dist/components/date-picker.js +726 -0
  32. package/dist/components/date-picker.js.map +1 -0
  33. package/dist/components/divider.js +214 -0
  34. package/dist/components/divider.js.map +1 -0
  35. package/dist/components/drawer.js +568 -0
  36. package/dist/components/drawer.js.map +1 -0
  37. package/dist/components/dropdown.js +377 -0
  38. package/dist/components/dropdown.js.map +1 -0
  39. package/dist/components/file-upload.js +669 -0
  40. package/dist/components/file-upload.js.map +1 -0
  41. package/dist/components/heading.js +161 -0
  42. package/dist/components/heading.js.map +1 -0
  43. package/dist/components/icon.js +599 -0
  44. package/dist/components/icon.js.map +1 -0
  45. package/dist/components/index.d.ts +3 -0
  46. package/dist/components/index.d.ts.map +1 -1
  47. package/dist/components/input.js +363 -0
  48. package/dist/components/input.js.map +1 -0
  49. package/dist/components/link.js +178 -0
  50. package/dist/components/link.js.map +1 -0
  51. package/dist/components/menu.js +331 -0
  52. package/dist/components/menu.js.map +1 -0
  53. package/dist/components/modal.js +317 -0
  54. package/dist/components/modal.js.map +1 -0
  55. package/dist/components/multi-select.js +642 -0
  56. package/dist/components/multi-select.js.map +1 -0
  57. package/dist/components/notification.js +429 -0
  58. package/dist/components/notification.js.map +1 -0
  59. package/dist/components/number-input.js +556 -0
  60. package/dist/components/number-input.js.map +1 -0
  61. package/dist/components/pagination.js +320 -0
  62. package/dist/components/pagination.js.map +1 -0
  63. package/dist/components/popover.js +597 -0
  64. package/dist/components/popover.js.map +1 -0
  65. package/dist/components/progress.js +219 -0
  66. package/dist/components/progress.js.map +1 -0
  67. package/dist/components/radio.js +321 -0
  68. package/dist/components/radio.js.map +1 -0
  69. package/dist/components/select.js +498 -0
  70. package/dist/components/select.js.map +1 -0
  71. package/dist/components/skeleton.js +240 -0
  72. package/dist/components/skeleton.js.map +1 -0
  73. package/dist/components/slider.js +9 -0
  74. package/dist/components/slider.js.map +1 -0
  75. package/dist/components/spinner.js +133 -0
  76. package/dist/components/spinner.js.map +1 -0
  77. package/dist/components/stepper.js +812 -0
  78. package/dist/components/stepper.js.map +1 -0
  79. package/dist/components/switch.js +379 -0
  80. package/dist/components/switch.js.map +1 -0
  81. package/dist/components/table.js +642 -0
  82. package/dist/components/table.js.map +1 -0
  83. package/dist/components/tabs.js +547 -0
  84. package/dist/components/tabs.js.map +1 -0
  85. package/dist/components/tag/tag.d.ts.map +1 -1
  86. package/dist/components/tag.js +291 -0
  87. package/dist/components/tag.js.map +1 -0
  88. package/dist/components/text.js +278 -0
  89. package/dist/components/text.js.map +1 -0
  90. package/dist/components/textarea.js +380 -0
  91. package/dist/components/textarea.js.map +1 -0
  92. package/dist/components/time-picker.js +457 -0
  93. package/dist/components/time-picker.js.map +1 -0
  94. package/dist/components/tooltip.js +239 -0
  95. package/dist/components/tooltip.js.map +1 -0
  96. package/dist/components/tree.js +582 -0
  97. package/dist/components/tree.js.map +1 -0
  98. package/dist/index.js +96 -17799
  99. package/dist/index.js.map +1 -1
  100. package/dist/shared/boolean-converter-XDGfS9LC.js +12 -0
  101. package/dist/shared/boolean-converter-XDGfS9LC.js.map +1 -0
  102. package/dist/shared/debounce-BckY30Sf.js +23 -0
  103. package/dist/shared/debounce-BckY30Sf.js.map +1 -0
  104. package/dist/shared/memoize-DlOFy-92.js +16 -0
  105. package/dist/shared/memoize-DlOFy-92.js.map +1 -0
  106. package/dist/shared/slider-BNt5TITl.js +484 -0
  107. package/dist/shared/slider-BNt5TITl.js.map +1 -0
  108. package/dist/utilities/memoize.d.ts.map +1 -1
  109. package/package.json +44 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table.js","sources":["../../source/components/table/table.style.ts","../../source/components/table/table.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const tableStyles = css`\n /* Base styles */\n :host {\n display: block;\n }\n\n .table-wrapper {\n overflow-x: auto;\n border-radius: var(--bp-border-radius);\n }\n\n .table {\n width: 100%;\n border-collapse: collapse;\n font-family: var(--bp-font-family);\n font-size: var(--bp-font-size-sm);\n color: var(--bp-color-text);\n background: var(--bp-color-surface);\n }\n\n /* Header styles */\n .header-row {\n background: var(--bp-color-surface-subdued);\n border-bottom: var(--bp-border-width) solid var(--bp-color-border);\n }\n\n .header-cell {\n font-weight: var(--bp-font-weight-semibold);\n text-align: left;\n color: var(--bp-color-text);\n }\n\n .header-cell--sortable {\n cursor: pointer;\n user-select: none;\n transition: background-color var(--bp-transition-fast);\n position: relative;\n }\n\n .header-cell--sortable::after {\n content: '';\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n height: 2px;\n background: transparent;\n transition: background var(--bp-transition-fast);\n }\n\n .header-cell--sortable:hover::after {\n background: var(--bp-color-primary);\n opacity: 0.3;\n }\n\n .header-cell--sortable:hover {\n background: var(--bp-color-surface);\n }\n\n .header-cell--sortable:active {\n background: var(--bp-color-surface-subdued);\n transform: translateY(1px);\n }\n\n .header-cell__content {\n display: flex;\n align-items: center;\n gap: var(--bp-spacing-1);\n }\n\n .header-cell__label {\n flex: 1;\n }\n\n /* Sort icon */\n .sort-icon {\n display: flex;\n align-items: center;\n color: var(--bp-color-text-muted);\n transition: color var(--bp-transition-fast);\n }\n\n .sort-icon--active {\n color: var(--bp-color-primary);\n }\n\n /* Cell styles */\n .cell {\n padding: var(--bp-spacing-3) var(--bp-spacing-4);\n border-bottom: var(--bp-border-width) solid var(--bp-color-border);\n vertical-align: middle;\n }\n\n .cell--checkbox {\n width: var(--bp-spacing-10);\n text-align: center;\n padding-left: var(--bp-spacing-3);\n padding-right: 0;\n }\n\n .cell--checkbox input[type='checkbox'] {\n width: var(--bp-spacing-6);\n height: var(--bp-spacing-6);\n cursor: pointer;\n }\n\n /* Row styles */\n .row {\n transition: background-color var(--bp-transition-fast);\n content-visibility: auto;\n contain-intrinsic-size: auto 48px;\n }\n\n .row--hoverable:hover {\n background: var(--bp-color-surface-subdued);\n }\n\n .row--selected {\n background: oklch(from var(--bp-color-primary) l c h / 0.15);\n }\n\n .row--selected:hover {\n background: oklch(from var(--bp-color-primary) l c h / 0.2);\n }\n\n /* Remove border from last row */\n tbody tr:last-child .cell {\n border-bottom: none;\n }\n\n /* Variants */\n .table--striped tbody tr:nth-child(even) {\n background: var(--bp-color-surface-subdued);\n }\n\n .table--striped tbody tr:nth-child(even):hover {\n background: var(--bp-color-surface);\n }\n\n .table--striped .row--selected {\n background: oklch(from var(--bp-color-primary) l c h / 0.15) !important;\n }\n\n .table--striped .row--selected:hover {\n background: oklch(from var(--bp-color-primary) l c h / 0.2) !important;\n }\n\n .table--bordered {\n border: var(--bp-border-width) solid var(--bp-color-border);\n }\n\n .table--bordered .cell {\n border: var(--bp-border-width) solid var(--bp-color-border);\n }\n\n /* Sizes */\n .table--sm .cell {\n padding: var(--bp-spacing-1) var(--bp-spacing-3);\n font-size: var(--bp-font-size-xs);\n }\n\n .table--sm .row {\n contain-intrinsic-size: auto 36px;\n }\n\n .table--md .cell {\n padding: var(--bp-spacing-3) var(--bp-spacing-4);\n font-size: var(--bp-font-size-sm);\n }\n\n .table--md .row {\n contain-intrinsic-size: auto 48px;\n }\n\n .table--lg .cell {\n padding: var(--bp-spacing-4) var(--bp-spacing-5);\n font-size: var(--bp-font-size-base);\n }\n\n .table--lg .row {\n contain-intrinsic-size: auto 56px;\n }\n\n /* Sticky header */\n .table--sticky-header thead {\n position: sticky;\n top: 0;\n z-index: 1;\n }\n\n .table--sticky-header .header-row {\n box-shadow: var(--bp-shadow-sm);\n }\n\n /* Selectable - add pointer cursor */\n .table--selectable .row {\n cursor: pointer;\n }\n\n /* Loading state */\n .table--loading {\n opacity: var(--bp-opacity-disabled);\n pointer-events: none;\n }\n\n /* Empty state */\n .empty-state {\n text-align: center;\n padding: var(--bp-spacing-10);\n color: var(--bp-color-text-muted);\n background: var(--bp-color-surface-subdued);\n }\n\n .state-content {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: var(--bp-spacing-3);\n padding: var(--bp-spacing-5);\n }\n\n .sort-icon--inactive {\n opacity: 0.4;\n }\n\n /* Focus styles for keyboard navigation */\n .header-cell--sortable:focus-visible {\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\n outline-offset: var(--bp-focus-offset);\n }\n\n .row:focus-visible {\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\n outline-offset: calc(-1 * var(--bp-focus-offset));\n }\n\n .cell--checkbox input[type='checkbox']:focus-visible {\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\n outline-offset: var(--bp-focus-offset);\n }\n\n /* Reduced motion */\n @media (prefers-reduced-motion: reduce) {\n .row,\n .header-cell--sortable,\n .sort-icon {\n transition: none;\n }\n\n .header-cell--sortable:active {\n transform: none;\n }\n\n .header-cell--sortable::after {\n transition: none;\n }\n }\n`;\n","import { LitElement, html, nothing, TemplateResult, PropertyValues } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { tableStyles } from './table.style.js';\nimport { memoizeOne } from '../../utilities/memoize.js';\nimport { booleanConverter } from '../../utilities/boolean-converter.js';\nimport '../icon/icon.js';\n\nexport type TableVariant = 'default' | 'striped' | 'bordered';\nexport type TableSize = 'sm' | 'md' | 'lg';\nexport type TableSortDirection = 'asc' | 'desc' | 'none';\n\n/**\n * Column definition for the table\n */\nexport interface TableColumn {\n /** Unique key for the column (matches data property) */\n key: string;\n /** Header label for the column */\n label: string;\n /** Whether this column is sortable */\n sortable?: boolean;\n /** Text alignment */\n align?: 'left' | 'center' | 'right';\n /** Fixed width for the column */\n width?: string;\n /** Custom render function for cell content */\n render?: (value: unknown, row: TableRow) => TemplateResult | string;\n}\n\n/**\n * Row data for the table\n */\nexport interface TableRow {\n /** Unique identifier for the row */\n id: string | number;\n /** Row data keyed by column key */\n [key: string]: unknown;\n}\n\n/**\n * Sort state for the table\n */\nexport interface TableSortState {\n /** Column key being sorted */\n column: string;\n /** Sort direction */\n direction: TableSortDirection;\n}\n\n/**\n * A data table component for displaying tabular data with sorting and selection.\n *\n * @element bp-table\n *\n * @property {TableColumn[]} columns - Array of column definitions\n * @property {TableRow[]} rows - Array of row data objects\n * @property {TableVariant} variant - Visual style variant\n * @property {TableSize} size - Size of the table cells\n * @property {boolean} selectable - Whether rows can be selected\n * @property {boolean} multiSelect - Whether multiple rows can be selected\n * @property {(string|number)[]} selectedRows - Array of selected row IDs\n * @property {TableSortState} sortState - Current sort state\n * @property {boolean} stickyHeader - Whether the header sticks on scroll\n * @property {boolean} hoverable - Whether rows highlight on hover\n * @property {boolean} loading - Whether the table is in loading state\n *\n * @fires bp-sort - Fired when a sortable column header is clicked\n * @fires bp-select - Fired when row selection changes\n * @fires bp-row-click - Fired when a row is clicked\n *\n * @slot empty - Content to show when table has no data\n * @slot loading - Content to show when table is loading\n *\n * @csspart table - The table element\n * @csspart thead - The table header section\n * @csspart tbody - The table body section\n * @csspart header-row - A header row\n * @csspart header-cell - A header cell\n * @csspart row - A data row\n * @csspart cell - A data cell\n * @csspart checkbox - Selection checkbox\n * @csspart sort-icon - Sort direction icon\n * @csspart empty-state - Empty state container\n */\n@customElement('bp-table')\nexport class BpTable extends LitElement {\n /** Array of column definitions */\n @property({ type: Array }) declare columns: TableColumn[];\n\n /** Array of row data objects */\n @property({ type: Array }) declare rows: TableRow[];\n\n /** Visual style variant */\n @property({\n type: String,\n reflect: true,\n converter: {\n fromAttribute: (value: string | null) => {\n const valid: TableVariant[] = ['default', 'striped', 'bordered'];\n return value && valid.includes(value as TableVariant)\n ? (value as TableVariant)\n : 'default';\n },\n },\n })\n declare variant: TableVariant;\n\n /** Size of the table cells */\n @property({\n type: String,\n reflect: true,\n converter: {\n fromAttribute: (value: string | null) => {\n const valid: TableSize[] = ['sm', 'md', 'lg'];\n return value && valid.includes(value as TableSize)\n ? (value as TableSize)\n : 'md';\n },\n },\n })\n declare size: TableSize;\n\n /** Whether rows can be selected */\n @property({ type: Boolean, reflect: true }) declare selectable: boolean;\n\n /** Whether multiple rows can be selected */\n @property({ type: Boolean, reflect: true }) declare multiSelect: boolean;\n\n /** Array of selected row IDs */\n @property({ type: Array }) declare selectedRows: (string | number)[];\n\n /** Current sort state */\n @property({ type: Object }) declare sortState: TableSortState | null;\n\n /** Whether the header sticks on scroll */\n @property({ type: Boolean, reflect: true, attribute: 'sticky-header' })\n declare stickyHeader: boolean;\n\n /** Whether rows highlight on hover */\n @property({ converter: booleanConverter, reflect: true })\n declare hoverable: boolean;\n\n /** Whether the table is in loading state */\n @property({ type: Boolean, reflect: true }) declare loading: boolean;\n\n @state() private allSelected = false;\n\n /**\n * Properties that only affect visual styling, not rendered structure.\n * Changes to only these properties can skip a full re-render.\n */\n private static readonly VISUAL_ONLY_PROPS = new Set([\n 'hoverable',\n 'stickyHeader',\n ]);\n\n static styles = [tableStyles];\n\n constructor() {\n super();\n this.columns = [];\n this.rows = [];\n this.variant = 'default';\n this.size = 'md';\n this.selectable = false;\n this.multiSelect = false;\n this.selectedRows = [];\n this.sortState = null;\n this.stickyHeader = false;\n this.hoverable = true;\n this.loading = false;\n }\n\n protected shouldUpdate(changedProperties: PropertyValues): boolean {\n // If all changed properties are visual-only, skip the update.\n // Be conservative: return true if any non-visual property changed.\n for (const key of changedProperties.keys()) {\n if (!BpTable.VISUAL_ONLY_PROPS.has(key as string)) {\n return true;\n }\n }\n // All changes are visual-only — still need to update for CSS class changes\n return true;\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n if (\n changedProperties.has('selectedRows') ||\n changedProperties.has('rows')\n ) {\n this.allSelected =\n this.rows.length > 0 && this.selectedRows.length === this.rows.length;\n }\n }\n\n /**\n * Memoized sorted rows computation.\n * Only recomputes when rows or sortState references change.\n */\n private computeSortedRows = memoizeOne(\n (rows: TableRow[], sortState: TableSortState | null): TableRow[] => {\n if (!sortState || sortState.direction === 'none') {\n return rows;\n }\n\n const { column, direction } = sortState;\n return [...rows].sort((a, b) => {\n const aVal = a[column];\n const bVal = b[column];\n\n if (aVal === bVal) return 0;\n if (aVal === null || aVal === undefined) return 1;\n if (bVal === null || bVal === undefined) return -1;\n\n let comparison = 0;\n if (typeof aVal === 'string' && typeof bVal === 'string') {\n comparison = aVal.localeCompare(bVal);\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal;\n } else {\n comparison = String(aVal).localeCompare(String(bVal));\n }\n\n return direction === 'desc' ? -comparison : comparison;\n });\n }\n );\n\n /**\n * Get sorted rows based on current sort state (memoized).\n */\n private get sortedRows(): TableRow[] {\n return this.computeSortedRows(this.rows, this.sortState);\n }\n\n /**\n * Handles click on sortable column header.\n * Cycles through sort directions: asc → desc → none.\n * Manages focus on header after sort completes.\n */\n private handleHeaderClick(column: TableColumn, event: Event) {\n if (!column.sortable) return;\n\n let direction: TableSortDirection = 'asc';\n if (this.sortState?.column === column.key) {\n if (this.sortState.direction === 'asc') {\n direction = 'desc';\n } else if (this.sortState.direction === 'desc') {\n direction = 'none';\n }\n }\n\n this.sortState = { column: column.key, direction };\n this.dispatchEvent(\n new CustomEvent('bp-sort', {\n detail: { column: column.key, direction },\n bubbles: true,\n composed: true,\n })\n );\n\n // Focus management: focus header after sort completes\n this.updateComplete.then(() => {\n (event.target as HTMLElement)?.focus();\n });\n }\n\n /**\n * Handles click events on table rows.\n * Dispatches bp-row-click event and toggles selection if selectable.\n */\n private handleRowClick(row: TableRow, event: Event) {\n this.dispatchEvent(\n new CustomEvent('bp-row-click', {\n detail: { row, originalEvent: event },\n bubbles: true,\n composed: true,\n })\n );\n\n if (this.selectable) {\n this.toggleRowSelection(row);\n }\n }\n\n /**\n * Handles keyboard events on table rows.\n * Triggers selection on Enter or Space key press when selectable.\n */\n private handleRowKeyDown(row: TableRow, event: KeyboardEvent) {\n if (!this.selectable) return;\n\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.toggleRowSelection(row);\n }\n }\n\n /**\n * Toggles selection state for a row.\n * Respects multiSelect setting for single vs multiple selection.\n */\n private toggleRowSelection(row: TableRow) {\n const rowId = row.id;\n const isSelected = this.selectedRows.includes(rowId);\n\n let newSelection: (string | number)[];\n if (this.multiSelect) {\n newSelection = isSelected\n ? this.selectedRows.filter((id) => id !== rowId)\n : [...this.selectedRows, rowId];\n } else {\n newSelection = isSelected ? [] : [rowId];\n }\n\n this.selectedRows = newSelection;\n this.dispatchEvent(\n new CustomEvent('bp-select', {\n detail: { selectedRows: newSelection, row, selected: !isSelected },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n /**\n * Handles select all checkbox toggle.\n * Selects or deselects all rows based on current state.\n */\n private handleSelectAll() {\n if (this.allSelected) {\n this.selectedRows = [];\n } else {\n this.selectedRows = this.rows.map((row) => row.id);\n }\n this.dispatchEvent(\n new CustomEvent('bp-select', {\n detail: {\n selectedRows: this.selectedRows,\n selectAll: !this.allSelected,\n },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n /**\n * Handles checkbox click events.\n * Stops propagation only on the checkbox itself to prevent row click.\n */\n private handleCheckboxClick(event: Event, row?: TableRow) {\n // Only stop propagation on the checkbox to prevent triggering row click\n if (event.target instanceof HTMLInputElement) {\n event.stopPropagation();\n }\n if (row) {\n this.toggleRowSelection(row);\n } else {\n this.handleSelectAll();\n }\n }\n\n /** Select all rows */\n selectAll() {\n this.selectedRows = this.rows.map((row) => row.id);\n this.dispatchEvent(\n new CustomEvent('bp-select', {\n detail: { selectedRows: this.selectedRows, selectAll: true },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n /** Deselect all rows */\n deselectAll() {\n this.selectedRows = [];\n this.dispatchEvent(\n new CustomEvent('bp-select', {\n detail: { selectedRows: [], selectAll: false },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n /** Clear sort state */\n clearSort() {\n this.sortState = null;\n }\n\n /**\n * Renders the sort icon for sortable columns.\n * Shows chevron-up for ascending, chevron-down for descending, unsorted icon otherwise.\n */\n private renderSortIcon(column: TableColumn) {\n if (!column.sortable) return nothing;\n\n const isActive = this.sortState?.column === column.key;\n const direction = isActive ? this.sortState?.direction : 'none';\n\n const iconName =\n direction === 'asc'\n ? 'chevron-up'\n : direction === 'desc'\n ? 'chevron-down'\n : 'chevron-up';\n\n const iconClasses = {\n 'sort-icon': true,\n 'sort-icon--active': isActive && direction !== 'none',\n 'sort-icon--inactive': direction === 'none',\n };\n\n return html`\n <span class=${classMap(iconClasses)} part=\"sort-icon\" aria-hidden=\"true\">\n <bp-icon name=${iconName} size=\"sm\"></bp-icon>\n </span>\n `;\n }\n\n /**\n * Renders the table header with column labels and sort icons.\n */\n private renderHeader() {\n return html`\n <thead part=\"thead\">\n <tr class=\"header-row\" part=\"header-row\">\n ${this.selectable && this.multiSelect\n ? html`\n <th class=\"cell cell--checkbox\" part=\"header-cell\">\n <input\n type=\"checkbox\"\n part=\"checkbox\"\n .checked=${this.allSelected}\n .indeterminate=${this.selectedRows.length > 0 &&\n !this.allSelected}\n @click=${(e: Event) => this.handleCheckboxClick(e)}\n aria-label=\"Select all rows\"\n />\n </th>\n `\n : this.selectable\n ? html`<th class=\"cell cell--checkbox\" part=\"header-cell\"></th>`\n : nothing}\n ${repeat(\n this.columns,\n (column) => column.key,\n (column) => html`\n <th\n class=\"cell header-cell ${column.sortable\n ? 'header-cell--sortable'\n : ''}\"\n part=\"header-cell\"\n style=${column.width ? `width: ${column.width}` : ''}\n @click=${(e: Event) => this.handleHeaderClick(column, e)}\n tabindex=${column.sortable ? 0 : -1}\n @keydown=${(e: KeyboardEvent) => {\n if (column.sortable && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n this.handleHeaderClick(column, e);\n }\n }}\n aria-sort=${this.sortState?.column === column.key\n ? this.sortState.direction === 'asc'\n ? 'ascending'\n : this.sortState.direction === 'desc'\n ? 'descending'\n : 'none'\n : 'none'}\n >\n <span\n class=\"header-cell__content\"\n style=\"justify-content: ${column.align === 'center'\n ? 'center'\n : column.align === 'right'\n ? 'flex-end'\n : 'flex-start'}\"\n >\n <span class=\"header-cell__label\">${column.label}</span>\n ${this.renderSortIcon(column)}\n </span>\n </th>\n `\n )}\n </tr>\n </thead>\n `;\n }\n\n /**\n * Renders the table body with rows and cells.\n * Handles loading and empty states.\n */\n private renderBody() {\n const sortedRows = this.sortedRows;\n\n if (this.loading) {\n return html`\n <tbody part=\"tbody\">\n <tr>\n <td\n colspan=${this.columns.length + (this.selectable ? 1 : 0)}\n class=\"empty-state\"\n part=\"empty-state\"\n >\n <slot name=\"loading\">\n <div class=\"state-content\">Loading...</div>\n </slot>\n </td>\n </tr>\n </tbody>\n `;\n }\n\n if (sortedRows.length === 0) {\n return html`\n <tbody part=\"tbody\">\n <tr>\n <td\n colspan=${this.columns.length + (this.selectable ? 1 : 0)}\n class=\"empty-state\"\n part=\"empty-state\"\n >\n <slot name=\"empty\">\n <div class=\"state-content\">No data available</div>\n </slot>\n </td>\n </tr>\n </tbody>\n `;\n }\n\n return html`\n <tbody part=\"tbody\">\n ${repeat(\n sortedRows,\n (row) => row.id,\n (row) => {\n const isSelected = this.selectedRows.includes(row.id);\n const rowClasses = {\n row: true,\n 'row--selected': isSelected,\n 'row--hoverable': this.hoverable,\n };\n\n return html`\n <tr\n class=${classMap(rowClasses)}\n part=\"row\"\n @click=${(e: Event) => this.handleRowClick(row, e)}\n @keydown=${(e: KeyboardEvent) => this.handleRowKeyDown(row, e)}\n tabindex=${this.selectable ? 0 : -1}\n aria-selected=${ifDefined(\n this.selectable ? (isSelected ? 'true' : 'false') : undefined\n )}\n >\n ${this.selectable\n ? html`\n <td class=\"cell cell--checkbox\" part=\"cell\">\n <input\n type=\"checkbox\"\n part=\"checkbox\"\n .checked=${isSelected}\n @click=${(e: Event) =>\n this.handleCheckboxClick(e, row)}\n aria-label=\"Select row\"\n />\n </td>\n `\n : nothing}\n ${repeat(\n this.columns,\n (column) => column.key,\n (column) => {\n const value = row[column.key];\n const content = column.render\n ? column.render(value, row)\n : value;\n\n return html`\n <td\n class=\"cell\"\n part=\"cell\"\n style=\"text-align: ${column.align || 'left'}\"\n >\n ${content}\n </td>\n `;\n }\n )}\n </tr>\n `;\n }\n )}\n </tbody>\n `;\n }\n\n render() {\n const tableClasses = {\n table: true,\n [`table--${this.variant}`]: true,\n [`table--${this.size}`]: true,\n 'table--sticky-header': this.stickyHeader,\n 'table--selectable': this.selectable,\n 'table--loading': this.loading,\n };\n\n return html`\n <div class=\"table-wrapper\">\n <table\n class=${classMap(tableClasses)}\n part=\"table\"\n role=\"grid\"\n aria-busy=${this.loading}\n >\n ${this.renderHeader()} ${this.renderBody()}\n </table>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'bp-table': BpTable;\n }\n}\n"],"names":["tableStyles","css","BpTable","LitElement","memoizeOne","rows","sortState","column","direction","a","b","aVal","bVal","comparison","changedProperties","key","event","row","rowId","isSelected","newSelection","id","nothing","isActive","iconName","html","classMap","repeat","e","sortedRows","rowClasses","ifDefined","value","content","tableClasses","__decorateClass","property","booleanConverter","state","customElement"],"mappings":";;;;;;;AAEO,MAAMA,IAAcC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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"}
@@ -0,0 +1,547 @@
1
+ import { css as f, LitElement as h, nothing as c, html as d } from "lit";
2
+ import { property as l, state as m, queryAssignedElements as y, customElement as v } from "lit/decorators.js";
3
+ import { classMap as u } from "lit/directives/class-map.js";
4
+ import { repeat as x } from "lit/directives/repeat.js";
5
+ const w = f`
6
+ /* Base styles */
7
+ :host {
8
+ display: block;
9
+ }
10
+
11
+ .tabs {
12
+ font-family: var(--bp-font-family);
13
+ display: flex;
14
+ flex-direction: column;
15
+ }
16
+
17
+ /* Tablist - horizontal by default */
18
+ .tablist {
19
+ display: flex;
20
+ flex-wrap: nowrap;
21
+ gap: var(--bp-spacing-xs);
22
+ border-bottom: var(--bp-border-width) solid var(--bp-color-border);
23
+ padding-bottom: var(--bp-spacing-xs);
24
+ }
25
+
26
+ /* Tab button base */
27
+ .tab {
28
+ /* Reset */
29
+ appearance: none;
30
+ border: none;
31
+ background: transparent;
32
+ margin: 0;
33
+
34
+ /* Layout */
35
+ display: inline-flex;
36
+ align-items: center;
37
+ justify-content: center;
38
+ gap: var(--bp-spacing-xs);
39
+ cursor: pointer;
40
+ flex-shrink: 0;
41
+
42
+ /* Typography */
43
+ font-family: var(--bp-font-family);
44
+ font-weight: var(--bp-font-weight-medium);
45
+ white-space: nowrap;
46
+
47
+ /* Visual */
48
+ color: var(--bp-color-text-muted);
49
+ border-radius: var(--bp-border-radius);
50
+ transition: all var(--bp-transition-fast);
51
+
52
+ /* Focus */
53
+ outline: none;
54
+ }
55
+
56
+ .tab__icon {
57
+ flex-shrink: 0;
58
+ }
59
+
60
+ .tab__label {
61
+ display: inline-block;
62
+ }
63
+
64
+ .tab__close {
65
+ /* Reset */
66
+ appearance: none;
67
+ border: none;
68
+ background: transparent;
69
+ padding: var(--bp-spacing-xs);
70
+ margin: calc(-1 * var(--bp-spacing-xs));
71
+ margin-left: var(--bp-spacing-xs);
72
+ cursor: pointer;
73
+ border-radius: var(--bp-border-radius);
74
+
75
+ /* Layout */
76
+ display: inline-flex;
77
+ align-items: center;
78
+ justify-content: center;
79
+ width: var(--bp-spacing-lg);
80
+ height: var(--bp-spacing-lg);
81
+
82
+ /* Visual */
83
+ color: var(--bp-color-text-muted);
84
+ transition: all var(--bp-transition-fast);
85
+ }
86
+
87
+ .tab__close svg {
88
+ width: var(--bp-spacing-md);
89
+ height: var(--bp-spacing-md);
90
+ }
91
+
92
+ .tab__close:hover {
93
+ background: var(--bp-color-surface);
94
+ color: var(--bp-color-text);
95
+ }
96
+
97
+ .tab__close:active {
98
+ transform: scale(0.95);
99
+ }
100
+
101
+ /* Panels container */
102
+ .panels {
103
+ flex: 1;
104
+ padding: var(--bp-spacing-md);
105
+ }
106
+
107
+ /* Sizes */
108
+ .tabs--sm .tab {
109
+ padding: var(--bp-spacing-xs) var(--bp-spacing-sm);
110
+ font-size: var(--bp-font-size-sm);
111
+ line-height: var(--bp-line-height-tight);
112
+ }
113
+
114
+ .tabs--md .tab {
115
+ padding: var(--bp-spacing-sm) var(--bp-spacing-md);
116
+ font-size: var(--bp-font-size-base);
117
+ line-height: var(--bp-line-height-normal);
118
+ }
119
+
120
+ .tabs--lg .tab {
121
+ padding: var(--bp-spacing-md) var(--bp-spacing-lg);
122
+ font-size: var(--bp-font-size-lg);
123
+ line-height: var(--bp-line-height-normal);
124
+ }
125
+
126
+ /* Default variant */
127
+ .tabs--default .tab--active {
128
+ color: var(--bp-color-primary);
129
+ background: var(--bp-color-surface);
130
+ }
131
+
132
+ .tabs--default .tab:hover:not(.tab--disabled):not(.tab--active) {
133
+ color: var(--bp-color-text);
134
+ background: var(--bp-color-surface-subdued);
135
+ }
136
+
137
+ .tab:active:not(.tab--disabled) {
138
+ opacity: 0.8;
139
+ }
140
+
141
+ /* Underline variant */
142
+ .tabs--underline .tablist {
143
+ gap: var(--bp-spacing-md);
144
+ }
145
+
146
+ .tabs--underline .tab {
147
+ border-radius: 0;
148
+ position: relative;
149
+ padding-bottom: var(--bp-spacing-sm);
150
+ margin-bottom: calc(-1 * var(--bp-spacing-xs) - var(--bp-border-width));
151
+ }
152
+
153
+ .tabs--underline .tab::after {
154
+ content: '';
155
+ position: absolute;
156
+ bottom: 0;
157
+ left: 0;
158
+ right: 0;
159
+ height: var(--bp-spacing-0-5);
160
+ background: transparent;
161
+ transition: background var(--bp-transition-fast);
162
+ }
163
+
164
+ .tabs--underline .tab--active::after {
165
+ background: var(--bp-color-primary);
166
+ }
167
+
168
+ .tabs--underline .tab--active {
169
+ color: var(--bp-color-primary);
170
+ }
171
+
172
+ .tabs--underline .tab:hover:not(.tab--disabled):not(.tab--active) {
173
+ color: var(--bp-color-text);
174
+ }
175
+
176
+ .tabs--underline .tab:hover:not(.tab--disabled):not(.tab--active)::after {
177
+ background: var(--bp-color-border);
178
+ }
179
+
180
+ /* Pills variant */
181
+ .tabs--pills .tablist {
182
+ border-bottom: none;
183
+ gap: var(--bp-spacing-xs);
184
+ padding-bottom: 0;
185
+ background: var(--bp-color-surface);
186
+ padding: var(--bp-spacing-xs);
187
+ border-radius: var(--bp-border-radius-large);
188
+ }
189
+
190
+ .tabs--pills .tab {
191
+ border-radius: var(--bp-border-radius);
192
+ }
193
+
194
+ .tabs--pills .tab--active {
195
+ background: var(--bp-color-background);
196
+ color: var(--bp-color-text);
197
+ box-shadow: var(--bp-shadow-sm);
198
+ }
199
+
200
+ .tabs--pills .tab:hover:not(.tab--disabled):not(.tab--active) {
201
+ color: var(--bp-color-text);
202
+ }
203
+
204
+ /* Placement: bottom */
205
+ .tabs--bottom {
206
+ flex-direction: column-reverse;
207
+ }
208
+
209
+ .tabs--bottom .tablist {
210
+ border-bottom: none;
211
+ border-top: var(--bp-border-width) solid var(--bp-color-border);
212
+ padding-bottom: 0;
213
+ padding-top: var(--bp-spacing-xs);
214
+ }
215
+
216
+ .tabs--bottom.tabs--underline .tab {
217
+ margin-bottom: 0;
218
+ margin-top: calc(-1 * var(--bp-spacing-xs) - var(--bp-border-width));
219
+ padding-bottom: var(--bp-spacing-sm);
220
+ padding-top: var(--bp-spacing-sm);
221
+ }
222
+
223
+ .tabs--bottom.tabs--underline .tab::after {
224
+ top: 0;
225
+ bottom: auto;
226
+ }
227
+
228
+ /* Placement: start (vertical left) */
229
+ .tabs--start {
230
+ flex-direction: row;
231
+ }
232
+
233
+ .tabs--start .tablist {
234
+ flex-direction: column;
235
+ border-bottom: none;
236
+ border-right: var(--bp-border-width) solid var(--bp-color-border);
237
+ padding-bottom: 0;
238
+ padding-right: var(--bp-spacing-xs);
239
+ }
240
+
241
+ .tabs--start .tab {
242
+ justify-content: flex-start;
243
+ }
244
+
245
+ .tabs--start.tabs--underline .tab {
246
+ margin-bottom: 0;
247
+ margin-right: calc(-1 * var(--bp-spacing-xs) - var(--bp-border-width));
248
+ padding-right: var(--bp-spacing-sm);
249
+ }
250
+
251
+ .tabs--start.tabs--underline .tab::after {
252
+ left: auto;
253
+ right: 0;
254
+ top: 0;
255
+ bottom: 0;
256
+ width: var(--bp-spacing-0-5);
257
+ height: auto;
258
+ }
259
+
260
+ /* Placement: end (vertical right) */
261
+ .tabs--end {
262
+ flex-direction: row-reverse;
263
+ }
264
+
265
+ .tabs--end .tablist {
266
+ flex-direction: column;
267
+ border-bottom: none;
268
+ border-left: var(--bp-border-width) solid var(--bp-color-border);
269
+ padding-bottom: 0;
270
+ padding-left: var(--bp-spacing-xs);
271
+ }
272
+
273
+ .tabs--end .tab {
274
+ justify-content: flex-start;
275
+ }
276
+
277
+ .tabs--end.tabs--underline .tab {
278
+ margin-bottom: 0;
279
+ margin-left: calc(-1 * var(--bp-spacing-xs) - var(--bp-border-width));
280
+ padding-left: var(--bp-spacing-sm);
281
+ }
282
+
283
+ .tabs--end.tabs--underline .tab::after {
284
+ right: auto;
285
+ left: 0;
286
+ top: 0;
287
+ bottom: 0;
288
+ width: var(--bp-spacing-0-5);
289
+ height: auto;
290
+ }
291
+
292
+ /* States */
293
+ .tab--disabled {
294
+ cursor: not-allowed;
295
+ opacity: var(--bp-opacity-disabled);
296
+ pointer-events: none;
297
+ }
298
+
299
+ .tabs--disabled .tab {
300
+ cursor: not-allowed;
301
+ opacity: var(--bp-opacity-disabled);
302
+ pointer-events: none;
303
+ }
304
+
305
+ .tab:focus-visible {
306
+ outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
307
+ outline-offset: var(--bp-focus-offset);
308
+ }
309
+ `;
310
+ var T = Object.defineProperty, k = Object.getOwnPropertyDescriptor, o = (t, a, e, s) => {
311
+ for (var i = s > 1 ? void 0 : s ? k(a, e) : a, n = t.length - 1, b; n >= 0; n--)
312
+ (b = t[n]) && (i = (s ? b(a, e, i) : b(i)) || i);
313
+ return s && i && T(a, e, i), i;
314
+ };
315
+ let r = class extends h {
316
+ constructor() {
317
+ super(), this.focusedTabId = null, this.handleSlotChange = () => {
318
+ if (!this.value && this.tabs.length > 0) {
319
+ const t = this.tabs.find((a) => !a.disabled);
320
+ t && (this.value = t.id);
321
+ } else if (!this.value) {
322
+ const t = this.getPanels();
323
+ t.length > 0 && (this.value = t[0].getAttribute("data-tab-id") || "");
324
+ }
325
+ this.updatePanelVisibility();
326
+ }, this.handleTabClick = (t, a) => {
327
+ a || this.disabled || this.selectTab(t);
328
+ }, this.handleTabKeyDown = (t, a) => {
329
+ if (this.disabled) return;
330
+ const e = this.getEnabledTabs(), s = e.findIndex((b) => b.id === a);
331
+ let i = s, n = !1;
332
+ switch (t.key) {
333
+ case "ArrowLeft":
334
+ case "ArrowUp":
335
+ t.preventDefault(), n = !0, i = s > 0 ? s - 1 : e.length - 1;
336
+ break;
337
+ case "ArrowRight":
338
+ case "ArrowDown":
339
+ t.preventDefault(), n = !0, i = s < e.length - 1 ? s + 1 : 0;
340
+ break;
341
+ case "Home":
342
+ t.preventDefault(), n = !0, i = 0;
343
+ break;
344
+ case "End":
345
+ t.preventDefault(), n = !0, i = e.length - 1;
346
+ break;
347
+ case "Enter":
348
+ case " ":
349
+ this.manual && this.focusedTabId && (t.preventDefault(), n = !0, this.selectTab(this.focusedTabId));
350
+ break;
351
+ case "Delete":
352
+ case "Backspace": {
353
+ this.tabs.find((g) => g.id === a)?.closable && (t.preventDefault(), n = !0, this.handleTabClose(t, a));
354
+ break;
355
+ }
356
+ }
357
+ if (n && i !== s) {
358
+ const b = e[i];
359
+ b && (this.focusedTabId = b.id, this.focusTab(b.id), this.manual || this.selectTab(b.id));
360
+ }
361
+ }, this.handleTabClose = (t, a) => {
362
+ t.stopPropagation(), this.dispatchEvent(
363
+ new CustomEvent("bp-tab-close", {
364
+ detail: { tabId: a },
365
+ bubbles: !0,
366
+ composed: !0
367
+ })
368
+ );
369
+ const e = this.tabs.findIndex((s) => s.id === a);
370
+ if (this.tabs = this.tabs.filter((s) => s.id !== a), this.value === a && this.tabs.length > 0) {
371
+ const s = Math.min(e, this.tabs.length - 1);
372
+ this.value = this.tabs[s].id;
373
+ }
374
+ }, this.handleTabFocus = (t) => {
375
+ this.focusedTabId = t;
376
+ }, this.handleTabBlur = () => {
377
+ this.focusedTabId = null;
378
+ }, this.value = "", this.tabs = [], this.size = "md", this.variant = "default", this.placement = "top", this.disabled = !1, this.manual = !1;
379
+ }
380
+ connectedCallback() {
381
+ super.connectedCallback(), this.setAttribute("role", "tablist");
382
+ }
383
+ updated(t) {
384
+ super.updated(t), t.has("value") && this.updatePanelVisibility();
385
+ }
386
+ getPanels() {
387
+ return this.panelElements.filter(
388
+ (t) => t.hasAttribute("data-tab-id") || t.tagName === "BP-TAB-PANEL"
389
+ );
390
+ }
391
+ getEnabledTabs() {
392
+ return this.tabs.filter((t) => !t.disabled);
393
+ }
394
+ updatePanelVisibility() {
395
+ this.getPanels().forEach((a) => {
396
+ const s = (a.getAttribute("data-tab-id") || "") === this.value;
397
+ a.hidden = !s, a.setAttribute("aria-hidden", String(!s)), s ? a.setAttribute("tabindex", "0") : a.removeAttribute("tabindex");
398
+ });
399
+ }
400
+ focusTab(t) {
401
+ this.shadowRoot?.querySelector(
402
+ `[data-tab-id="${t}"]`
403
+ )?.focus();
404
+ }
405
+ selectTab(t) {
406
+ const a = this.value;
407
+ a !== t && (this.value = t, this.updatePanelVisibility(), this.dispatchEvent(
408
+ new CustomEvent("bp-tab-change", {
409
+ detail: {
410
+ value: t,
411
+ previousValue: a
412
+ },
413
+ bubbles: !0,
414
+ composed: !0
415
+ })
416
+ ));
417
+ }
418
+ renderTab(t) {
419
+ const a = this.value === t.id, e = t.disabled || this.disabled;
420
+ return d`
421
+ <button
422
+ class=${u({
423
+ tab: !0,
424
+ "tab--active": a,
425
+ "tab--disabled": e
426
+ })}
427
+ part="tab ${a ? "tab-active" : ""} ${e ? "tab-disabled" : ""}"
428
+ role="tab"
429
+ data-tab-id=${t.id}
430
+ id="tab-${t.id}"
431
+ aria-selected=${a}
432
+ aria-controls="panel-${t.id}"
433
+ aria-disabled=${e}
434
+ tabindex=${a ? 0 : -1}
435
+ ?disabled=${e}
436
+ @click=${() => this.handleTabClick(t.id, e)}
437
+ @keydown=${(i) => this.handleTabKeyDown(i, t.id)}
438
+ @focus=${() => this.handleTabFocus(t.id)}
439
+ @blur=${this.handleTabBlur}
440
+ >
441
+ ${t.icon ? d`<bp-icon name=${t.icon} class="tab__icon"></bp-icon>` : c}
442
+ <span class="tab__label">${t.label}</span>
443
+ ${t.closable ? d`
444
+ <button
445
+ class="tab__close"
446
+ part="tab-close"
447
+ aria-label="Close ${t.label}"
448
+ @click=${(i) => this.handleTabClose(i, t.id)}
449
+ @keydown=${(i) => i.stopPropagation()}
450
+ >
451
+ <svg
452
+ viewBox="0 0 24 24"
453
+ fill="none"
454
+ stroke="currentColor"
455
+ stroke-width="2"
456
+ >
457
+ <path d="M18 6L6 18M6 6l12 12" />
458
+ </svg>
459
+ </button>
460
+ ` : c}
461
+ </button>
462
+ `;
463
+ }
464
+ render() {
465
+ const t = {
466
+ tabs: !0,
467
+ [`tabs--${this.size}`]: !0,
468
+ [`tabs--${this.variant}`]: !0,
469
+ [`tabs--${this.placement}`]: !0,
470
+ "tabs--disabled": this.disabled
471
+ }, a = this.placement === "start" || this.placement === "end";
472
+ return d`
473
+ <div
474
+ class=${u(t)}
475
+ part="tabs"
476
+ aria-orientation=${a ? "vertical" : "horizontal"}
477
+ >
478
+ <div class="tablist" part="tablist" role="tablist">
479
+ ${x(
480
+ this.tabs,
481
+ (e) => e.id,
482
+ (e) => this.renderTab(e)
483
+ )}
484
+ </div>
485
+ <div class="panels" part="panels">
486
+ <slot @slotchange=${this.handleSlotChange}></slot>
487
+ </div>
488
+ </div>
489
+ `;
490
+ }
491
+ };
492
+ r.styles = [w];
493
+ o([
494
+ l({ type: String, reflect: !0 })
495
+ ], r.prototype, "value", 2);
496
+ o([
497
+ l({ type: Array })
498
+ ], r.prototype, "tabs", 2);
499
+ o([
500
+ l({ type: String, reflect: !0 })
501
+ ], r.prototype, "size", 2);
502
+ o([
503
+ l({ type: String, reflect: !0 })
504
+ ], r.prototype, "variant", 2);
505
+ o([
506
+ l({ type: String, reflect: !0 })
507
+ ], r.prototype, "placement", 2);
508
+ o([
509
+ l({ type: Boolean, reflect: !0 })
510
+ ], r.prototype, "disabled", 2);
511
+ o([
512
+ l({ type: Boolean, reflect: !0 })
513
+ ], r.prototype, "manual", 2);
514
+ o([
515
+ m()
516
+ ], r.prototype, "focusedTabId", 2);
517
+ o([
518
+ y({ slot: "", flatten: !0 })
519
+ ], r.prototype, "panelElements", 2);
520
+ r = o([
521
+ v("bp-tabs")
522
+ ], r);
523
+ let p = class extends h {
524
+ constructor() {
525
+ super(), this.tabId = "";
526
+ }
527
+ connectedCallback() {
528
+ super.connectedCallback(), this.setAttribute("role", "tabpanel"), this.setAttribute("data-tab-id", this.tabId);
529
+ }
530
+ updated(t) {
531
+ super.updated(t), t.has("tabId") && (this.setAttribute("data-tab-id", this.tabId), this.id = `panel-${this.tabId}`, this.setAttribute("aria-labelledby", `tab-${this.tabId}`));
532
+ }
533
+ render() {
534
+ return d`<slot></slot>`;
535
+ }
536
+ };
537
+ o([
538
+ l({ type: String, attribute: "tab-id", reflect: !0 })
539
+ ], p.prototype, "tabId", 2);
540
+ p = o([
541
+ v("bp-tab-panel")
542
+ ], p);
543
+ export {
544
+ p as BpTabPanel,
545
+ r as BpTabs
546
+ };
547
+ //# sourceMappingURL=tabs.js.map