@krollins/blueprint 0.1.13 → 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 (50) hide show
  1. package/README.md +9 -3
  2. package/README.npm.md +9 -3
  3. package/dist/components/accordion.js.map +1 -1
  4. package/dist/components/badge/badge.d.ts.map +1 -1
  5. package/dist/components/badge.js.map +1 -1
  6. package/dist/components/breadcrumb.js.map +1 -1
  7. package/dist/components/card.js.map +1 -1
  8. package/dist/components/checkbox.js +0 -1
  9. package/dist/components/checkbox.js.map +1 -1
  10. package/dist/components/code-block/code-block.d.ts +143 -0
  11. package/dist/components/code-block/code-block.d.ts.map +1 -0
  12. package/dist/components/code-block/code-block.style.d.ts +2 -0
  13. package/dist/components/code-block/code-block.style.d.ts.map +1 -0
  14. package/dist/components/code-block.js +587 -0
  15. package/dist/components/code-block.js.map +1 -0
  16. package/dist/components/color-picker/color-picker.d.ts.map +1 -1
  17. package/dist/components/color-picker.js.map +1 -1
  18. package/dist/components/date-picker.js.map +1 -1
  19. package/dist/components/divider.js.map +1 -1
  20. package/dist/components/drawer.js.map +1 -1
  21. package/dist/components/dropdown.js.map +1 -1
  22. package/dist/components/file-upload.js.map +1 -1
  23. package/dist/components/index.d.ts +3 -0
  24. package/dist/components/index.d.ts.map +1 -1
  25. package/dist/components/menu.js.map +1 -1
  26. package/dist/components/multi-select.js.map +1 -1
  27. package/dist/components/notification.js.map +1 -1
  28. package/dist/components/pagination.js.map +1 -1
  29. package/dist/components/popover.js.map +1 -1
  30. package/dist/components/radio.js.map +1 -1
  31. package/dist/components/select.js.map +1 -1
  32. package/dist/components/skeleton.js.map +1 -1
  33. package/dist/components/stepper.js.map +1 -1
  34. package/dist/components/switch.js +0 -1
  35. package/dist/components/switch.js.map +1 -1
  36. package/dist/components/table.js.map +1 -1
  37. package/dist/components/tabs.js.map +1 -1
  38. package/dist/components/tag/tag.d.ts.map +1 -1
  39. package/dist/components/tag.js.map +1 -1
  40. package/dist/components/textarea.js.map +1 -1
  41. package/dist/components/time-picker.js.map +1 -1
  42. package/dist/components/tree.js.map +1 -1
  43. package/dist/index.js +31 -28
  44. package/dist/index.js.map +1 -1
  45. package/dist/shared/boolean-converter-XDGfS9LC.js.map +1 -1
  46. package/dist/shared/debounce-BckY30Sf.js.map +1 -1
  47. package/dist/shared/memoize-DlOFy-92.js.map +1 -1
  48. package/dist/shared/slider-BNt5TITl.js.map +1 -1
  49. package/dist/utilities/memoize.d.ts.map +1 -1
  50. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","sources":["../../source/components/pagination/pagination.style.ts","../../source/components/pagination/pagination.ts"],"sourcesContent":["import { css } from 'lit';\r\n\r\nexport const paginationStyles = css`\r\n /* Base styles */\r\n :host {\r\n display: inline-block;\r\n }\r\n\r\n .pagination {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--bp-spacing-sm);\r\n font-family: var(--bp-font-sans);\r\n }\r\n\r\n .pagination__button {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n min-width: var(--bp-spacing-10);\r\n height: var(--bp-spacing-10);\r\n padding: var(--bp-spacing-xs) var(--bp-spacing-sm);\r\n border: var(--bp-border-width) solid var(--bp-color-border);\r\n border-radius: var(--bp-border-radius-md);\r\n background-color: var(--bp-color-background);\r\n color: var(--bp-color-text);\r\n font-family: var(--bp-font-sans);\r\n font-size: var(--bp-font-size-base);\r\n font-weight: var(--bp-font-weight-medium);\r\n line-height: var(--bp-line-height-tight);\r\n cursor: pointer;\r\n transition:\r\n background-color var(--bp-transition-fast),\r\n border-color var(--bp-transition-fast),\r\n color var(--bp-transition-fast),\r\n transform var(--bp-transition-fast);\r\n user-select: none;\r\n }\r\n\r\n .pagination__button:hover:not(:disabled) {\r\n background-color: var(--bp-color-surface);\r\n border-color: var(--bp-color-border-strong);\r\n color: var(--bp-color-text);\r\n }\r\n\r\n .pagination__button:active:not(:disabled) {\r\n background-color: var(--bp-color-surface);\r\n border-color: var(--bp-color-border-strong);\r\n transform: translateY(1px) scale(0.98);\r\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\r\n }\r\n\r\n .pagination__button:focus-visible {\r\n outline: var(--bp-border-width) solid var(--bp-color-primary);\r\n outline-offset: var(--bp-spacing-0-5);\r\n }\r\n\r\n .pagination__button:disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n .pagination__button--active {\r\n background-color: var(--bp-color-primary);\r\n border-color: var(--bp-color-primary);\r\n color: var(--bp-color-text-inverse);\r\n font-weight: var(--bp-font-weight-semibold);\r\n }\r\n\r\n .pagination__button--active:hover:not(:disabled) {\r\n background-color: var(--bp-color-primary-hover);\r\n border-color: var(--bp-color-primary-hover);\r\n }\r\n\r\n .pagination__button--active:focus-visible {\r\n outline: 2px solid var(--bp-color-text-inverse);\r\n outline-offset: 2px;\r\n }\r\n\r\n /* Navigation buttons (first, last, prev, next) - ghost style for visual hierarchy */\r\n .pagination__button--first,\r\n .pagination__button--last,\r\n .pagination__button--prev,\r\n .pagination__button--next {\r\n color: var(--bp-color-text-muted);\r\n background-color: transparent;\r\n }\r\n\r\n .pagination__button--first:hover:not(:disabled),\r\n .pagination__button--last:hover:not(:disabled),\r\n .pagination__button--prev:hover:not(:disabled),\r\n .pagination__button--next:hover:not(:disabled) {\r\n color: var(--bp-color-text);\r\n background-color: var(--bp-color-surface);\r\n }\r\n\r\n .pagination__ellipsis {\r\n display: inline-flex;\r\n align-items: end;\r\n justify-content: center;\r\n min-width: var(--bp-spacing-2xl);\r\n height: var(--bp-spacing-2xl);\r\n color: var(--bp-color-text-muted);\r\n font-size: var(--bp-font-size-base);\r\n user-select: none;\r\n }\r\n\r\n .pagination__info {\r\n margin-left: var(--bp-spacing-lg);\r\n color: var(--bp-color-text-muted);\r\n font-size: var(--bp-font-size-sm);\r\n white-space: nowrap;\r\n }\r\n\r\n /* Sizes */\r\n .pagination--sm .pagination__button {\r\n min-width: var(--bp-spacing-xl);\r\n height: var(--bp-spacing-xl);\r\n padding: var(--bp-spacing-2xs) var(--bp-spacing-xs);\r\n font-size: var(--bp-font-size-sm);\r\n }\r\n\r\n .pagination--sm .pagination__ellipsis {\r\n min-width: var(--bp-spacing-xl);\r\n height: var(--bp-spacing-xl);\r\n font-size: var(--bp-font-size-sm);\r\n }\r\n\r\n .pagination--sm .pagination__info {\r\n font-size: var(--bp-font-size-xs);\r\n }\r\n\r\n .pagination--lg .pagination__button {\r\n min-width: var(--bp-spacing-2xl);\r\n height: var(--bp-spacing-2xl);\r\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\r\n font-size: var(--bp-font-size-lg);\r\n }\r\n\r\n .pagination--lg .pagination__ellipsis {\r\n min-width: var(--bp-spacing-2xl);\r\n height: var(--bp-spacing-2xl);\r\n font-size: var(--bp-font-size-lg);\r\n }\r\n\r\n .pagination--lg .pagination__info {\r\n font-size: var(--bp-font-size-base);\r\n }\r\n\r\n .pagination--lg {\r\n gap: var(--bp-spacing-md);\r\n }\r\n\r\n /* Touch target size: ensure 44x44px minimum on touch devices */\r\n @media (pointer: coarse) {\r\n .pagination__button {\r\n min-width: 44px;\r\n min-height: 44px;\r\n }\r\n }\r\n`;\r\n","import { LitElement, html } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport { repeat } from 'lit/directives/repeat.js';\r\nimport { paginationStyles } from './pagination.style.js';\r\nimport { booleanConverter } from '../../utilities/boolean-converter.js';\r\n\r\n/**\r\n * A pagination component for navigating through multiple pages of content.\r\n *\r\n * @fires bp-page-change - Dispatched when the page changes\r\n *\r\n * @slot - Default slot for custom content (not typically used)\r\n *\r\n * @csspart container - The main pagination container\r\n * @csspart button - All pagination buttons\r\n * @csspart button-first - The first page button\r\n * @csspart button-prev - The previous page button\r\n * @csspart button-next - The next page button\r\n * @csspart button-last - The last page button\r\n * @csspart button-page - Individual page number buttons\r\n * @csspart button-ellipsis - Ellipsis indicators\r\n * @csspart info - The page info text\r\n */\r\n@customElement('bp-pagination')\r\nexport class BpPagination extends LitElement {\r\n /** Current page number (1-indexed) */\r\n @property({ type: Number, attribute: 'current-page' })\r\n declare currentPage: number;\r\n\r\n /** Total number of pages */\r\n @property({ type: Number, attribute: 'total-pages' })\r\n declare totalPages: number;\r\n\r\n /** Number of page buttons to show around the current page */\r\n @property({ type: Number, attribute: 'sibling-count' })\r\n declare siblingCount: number;\r\n\r\n /** Number of page buttons to show at the start and end */\r\n @property({ type: Number, attribute: 'boundary-count' })\r\n declare boundaryCount: number;\r\n\r\n /** Show first/last page buttons */\r\n @property({\r\n converter: booleanConverter,\r\n reflect: true,\r\n attribute: 'show-first-last',\r\n })\r\n declare showFirstLast: boolean;\r\n\r\n /** Show previous/next page buttons */\r\n @property({\r\n converter: booleanConverter,\r\n reflect: true,\r\n attribute: 'show-prev-next',\r\n })\r\n declare showPrevNext: boolean;\r\n\r\n /** Show page info text (e.g., \"Page 1 of 10\") */\r\n @property({ type: Boolean, attribute: 'show-info' })\r\n declare showInfo: boolean;\r\n\r\n /** Disable all pagination controls */\r\n @property({ type: Boolean }) declare disabled: boolean;\r\n\r\n /** Size variant */\r\n @property({ type: String }) declare size: 'sm' | 'md' | 'lg';\r\n\r\n static styles = [paginationStyles];\r\n\r\n constructor() {\r\n super();\r\n this.currentPage = 1;\r\n this.totalPages = 1;\r\n this.siblingCount = 1;\r\n this.boundaryCount = 1;\r\n this.showFirstLast = true;\r\n this.showPrevNext = true;\r\n this.showInfo = false;\r\n this.disabled = false;\r\n this.size = 'md';\r\n }\r\n\r\n private handlePageChange(newPage: number) {\r\n if (\r\n this.disabled ||\r\n newPage < 1 ||\r\n newPage > this.totalPages ||\r\n newPage === this.currentPage\r\n ) {\r\n return;\r\n }\r\n\r\n this.currentPage = newPage;\r\n this.dispatchEvent(\r\n new CustomEvent('bp-page-change', {\r\n detail: { page: newPage },\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n }\r\n\r\n private getPageNumbers(): (number | 'ellipsis')[] {\r\n const pages: (number | 'ellipsis')[] = [];\r\n const totalCount = this.totalPages;\r\n const currentPageNum = this.currentPage;\r\n const siblingCountNum = this.siblingCount;\r\n const boundaryCountNum = this.boundaryCount;\r\n\r\n // Calculate range around current page\r\n const startPage = Math.max(1, currentPageNum - siblingCountNum);\r\n const endPage = Math.min(totalCount, currentPageNum + siblingCountNum);\r\n\r\n // Add boundary pages at start\r\n for (let i = 1; i <= Math.min(boundaryCountNum, totalCount); i++) {\r\n pages.push(i);\r\n }\r\n\r\n // Add ellipsis after boundary if needed\r\n if (startPage > boundaryCountNum + 1) {\r\n pages.push('ellipsis');\r\n }\r\n\r\n // Add pages around current page\r\n for (let i = startPage; i <= endPage; i++) {\r\n if (i > boundaryCountNum && i <= totalCount - boundaryCountNum) {\r\n pages.push(i);\r\n }\r\n }\r\n\r\n // Add ellipsis before end boundary if needed\r\n if (endPage < totalCount - boundaryCountNum) {\r\n pages.push('ellipsis');\r\n }\r\n\r\n // Add boundary pages at end\r\n for (\r\n let i = Math.max(totalCount - boundaryCountNum + 1, boundaryCountNum + 1);\r\n i <= totalCount;\r\n i++\r\n ) {\r\n if (!pages.includes(i)) {\r\n pages.push(i);\r\n }\r\n }\r\n\r\n // Remove duplicates while preserving order\r\n return pages.filter((page, index, self) => self.indexOf(page) === index);\r\n }\r\n\r\n render() {\r\n const pageNumbers = this.getPageNumbers();\r\n const isFirstPage = this.currentPage === 1;\r\n const isLastPage = this.currentPage === this.totalPages;\r\n\r\n return html`\r\n <nav\r\n class=\"pagination pagination--${this.size}\"\r\n part=\"container\"\r\n aria-label=\"Pagination\"\r\n >\r\n ${this.showFirstLast\r\n ? html`\r\n <button\r\n class=\"pagination__button pagination__button--first\"\r\n part=\"button button-first\"\r\n ?disabled=${this.disabled || isFirstPage}\r\n @click=${() => this.handlePageChange(1)}\r\n aria-label=\"First page\"\r\n >\r\n «\r\n </button>\r\n `\r\n : ''}\r\n ${this.showPrevNext\r\n ? html`\r\n <button\r\n class=\"pagination__button pagination__button--prev\"\r\n part=\"button button-prev\"\r\n ?disabled=${this.disabled || isFirstPage}\r\n @click=${() => this.handlePageChange(this.currentPage - 1)}\r\n aria-label=\"Previous page\"\r\n >\r\n ‹\r\n </button>\r\n `\r\n : ''}\r\n ${repeat(\r\n pageNumbers,\r\n (page, index) => (page === 'ellipsis' ? `ellipsis-${index}` : page),\r\n (page) =>\r\n page === 'ellipsis'\r\n ? html`\r\n <span\r\n class=\"pagination__ellipsis\"\r\n part=\"button-ellipsis\"\r\n aria-hidden=\"true\"\r\n >…</span\r\n >\r\n `\r\n : html`\r\n <button\r\n class=\"pagination__button pagination__button--page ${page ===\r\n this.currentPage\r\n ? 'pagination__button--active'\r\n : ''}\"\r\n part=\"button button-page\"\r\n ?disabled=${this.disabled}\r\n @click=${() => this.handlePageChange(page)}\r\n aria-label=\"Page ${page}\"\r\n aria-current=${page === this.currentPage ? 'page' : 'false'}\r\n >\r\n ${page}\r\n </button>\r\n `\r\n )}\r\n ${this.showPrevNext\r\n ? html`\r\n <button\r\n class=\"pagination__button pagination__button--next\"\r\n part=\"button button-next\"\r\n ?disabled=${this.disabled || isLastPage}\r\n @click=${() => this.handlePageChange(this.currentPage + 1)}\r\n aria-label=\"Next page\"\r\n >\r\n ›\r\n </button>\r\n `\r\n : ''}\r\n ${this.showFirstLast\r\n ? html`\r\n <button\r\n class=\"pagination__button pagination__button--last\"\r\n part=\"button button-last\"\r\n ?disabled=${this.disabled || isLastPage}\r\n @click=${() => this.handlePageChange(this.totalPages)}\r\n aria-label=\"Last page\"\r\n >\r\n »\r\n </button>\r\n `\r\n : ''}\r\n ${this.showInfo\r\n ? html`\r\n <span class=\"pagination__info\" part=\"info\" aria-live=\"polite\">\r\n Page ${this.currentPage} of ${this.totalPages}\r\n </span>\r\n `\r\n : ''}\r\n </nav>\r\n `;\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'bp-pagination': BpPagination;\r\n }\r\n}\r\n"],"names":["paginationStyles","css","BpPagination","LitElement","newPage","pages","totalCount","currentPageNum","siblingCountNum","boundaryCountNum","startPage","endPage","i","page","index","self","pageNumbers","isFirstPage","isLastPage","html","repeat","__decorateClass","property","booleanConverter","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"pagination.js","sources":["../../source/components/pagination/pagination.style.ts","../../source/components/pagination/pagination.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const paginationStyles = css`\n /* Base styles */\n :host {\n display: inline-block;\n }\n\n .pagination {\n display: flex;\n align-items: center;\n gap: var(--bp-spacing-sm);\n font-family: var(--bp-font-sans);\n }\n\n .pagination__button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: var(--bp-spacing-10);\n height: var(--bp-spacing-10);\n padding: var(--bp-spacing-xs) var(--bp-spacing-sm);\n border: var(--bp-border-width) solid var(--bp-color-border);\n border-radius: var(--bp-border-radius-md);\n background-color: var(--bp-color-background);\n color: var(--bp-color-text);\n font-family: var(--bp-font-sans);\n font-size: var(--bp-font-size-base);\n font-weight: var(--bp-font-weight-medium);\n line-height: var(--bp-line-height-tight);\n cursor: pointer;\n transition:\n background-color var(--bp-transition-fast),\n border-color var(--bp-transition-fast),\n color var(--bp-transition-fast),\n transform var(--bp-transition-fast);\n user-select: none;\n }\n\n .pagination__button:hover:not(:disabled) {\n background-color: var(--bp-color-surface);\n border-color: var(--bp-color-border-strong);\n color: var(--bp-color-text);\n }\n\n .pagination__button:active:not(:disabled) {\n background-color: var(--bp-color-surface);\n border-color: var(--bp-color-border-strong);\n transform: translateY(1px) scale(0.98);\n box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n }\n\n .pagination__button:focus-visible {\n outline: var(--bp-border-width) solid var(--bp-color-primary);\n outline-offset: var(--bp-spacing-0-5);\n }\n\n .pagination__button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n .pagination__button--active {\n background-color: var(--bp-color-primary);\n border-color: var(--bp-color-primary);\n color: var(--bp-color-text-inverse);\n font-weight: var(--bp-font-weight-semibold);\n }\n\n .pagination__button--active:hover:not(:disabled) {\n background-color: var(--bp-color-primary-hover);\n border-color: var(--bp-color-primary-hover);\n }\n\n .pagination__button--active:focus-visible {\n outline: 2px solid var(--bp-color-text-inverse);\n outline-offset: 2px;\n }\n\n /* Navigation buttons (first, last, prev, next) - ghost style for visual hierarchy */\n .pagination__button--first,\n .pagination__button--last,\n .pagination__button--prev,\n .pagination__button--next {\n color: var(--bp-color-text-muted);\n background-color: transparent;\n }\n\n .pagination__button--first:hover:not(:disabled),\n .pagination__button--last:hover:not(:disabled),\n .pagination__button--prev:hover:not(:disabled),\n .pagination__button--next:hover:not(:disabled) {\n color: var(--bp-color-text);\n background-color: var(--bp-color-surface);\n }\n\n .pagination__ellipsis {\n display: inline-flex;\n align-items: end;\n justify-content: center;\n min-width: var(--bp-spacing-2xl);\n height: var(--bp-spacing-2xl);\n color: var(--bp-color-text-muted);\n font-size: var(--bp-font-size-base);\n user-select: none;\n }\n\n .pagination__info {\n margin-left: var(--bp-spacing-lg);\n color: var(--bp-color-text-muted);\n font-size: var(--bp-font-size-sm);\n white-space: nowrap;\n }\n\n /* Sizes */\n .pagination--sm .pagination__button {\n min-width: var(--bp-spacing-xl);\n height: var(--bp-spacing-xl);\n padding: var(--bp-spacing-2xs) var(--bp-spacing-xs);\n font-size: var(--bp-font-size-sm);\n }\n\n .pagination--sm .pagination__ellipsis {\n min-width: var(--bp-spacing-xl);\n height: var(--bp-spacing-xl);\n font-size: var(--bp-font-size-sm);\n }\n\n .pagination--sm .pagination__info {\n font-size: var(--bp-font-size-xs);\n }\n\n .pagination--lg .pagination__button {\n min-width: var(--bp-spacing-2xl);\n height: var(--bp-spacing-2xl);\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\n font-size: var(--bp-font-size-lg);\n }\n\n .pagination--lg .pagination__ellipsis {\n min-width: var(--bp-spacing-2xl);\n height: var(--bp-spacing-2xl);\n font-size: var(--bp-font-size-lg);\n }\n\n .pagination--lg .pagination__info {\n font-size: var(--bp-font-size-base);\n }\n\n .pagination--lg {\n gap: var(--bp-spacing-md);\n }\n\n /* Touch target size: ensure 44x44px minimum on touch devices */\n @media (pointer: coarse) {\n .pagination__button {\n min-width: 44px;\n min-height: 44px;\n }\n }\n`;\n","import { LitElement, html } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { paginationStyles } from './pagination.style.js';\nimport { booleanConverter } from '../../utilities/boolean-converter.js';\n\n/**\n * A pagination component for navigating through multiple pages of content.\n *\n * @fires bp-page-change - Dispatched when the page changes\n *\n * @slot - Default slot for custom content (not typically used)\n *\n * @csspart container - The main pagination container\n * @csspart button - All pagination buttons\n * @csspart button-first - The first page button\n * @csspart button-prev - The previous page button\n * @csspart button-next - The next page button\n * @csspart button-last - The last page button\n * @csspart button-page - Individual page number buttons\n * @csspart button-ellipsis - Ellipsis indicators\n * @csspart info - The page info text\n */\n@customElement('bp-pagination')\nexport class BpPagination extends LitElement {\n /** Current page number (1-indexed) */\n @property({ type: Number, attribute: 'current-page' })\n declare currentPage: number;\n\n /** Total number of pages */\n @property({ type: Number, attribute: 'total-pages' })\n declare totalPages: number;\n\n /** Number of page buttons to show around the current page */\n @property({ type: Number, attribute: 'sibling-count' })\n declare siblingCount: number;\n\n /** Number of page buttons to show at the start and end */\n @property({ type: Number, attribute: 'boundary-count' })\n declare boundaryCount: number;\n\n /** Show first/last page buttons */\n @property({\n converter: booleanConverter,\n reflect: true,\n attribute: 'show-first-last',\n })\n declare showFirstLast: boolean;\n\n /** Show previous/next page buttons */\n @property({\n converter: booleanConverter,\n reflect: true,\n attribute: 'show-prev-next',\n })\n declare showPrevNext: boolean;\n\n /** Show page info text (e.g., \"Page 1 of 10\") */\n @property({ type: Boolean, attribute: 'show-info' })\n declare showInfo: boolean;\n\n /** Disable all pagination controls */\n @property({ type: Boolean }) declare disabled: boolean;\n\n /** Size variant */\n @property({ type: String }) declare size: 'sm' | 'md' | 'lg';\n\n static styles = [paginationStyles];\n\n constructor() {\n super();\n this.currentPage = 1;\n this.totalPages = 1;\n this.siblingCount = 1;\n this.boundaryCount = 1;\n this.showFirstLast = true;\n this.showPrevNext = true;\n this.showInfo = false;\n this.disabled = false;\n this.size = 'md';\n }\n\n private handlePageChange(newPage: number) {\n if (\n this.disabled ||\n newPage < 1 ||\n newPage > this.totalPages ||\n newPage === this.currentPage\n ) {\n return;\n }\n\n this.currentPage = newPage;\n this.dispatchEvent(\n new CustomEvent('bp-page-change', {\n detail: { page: newPage },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private getPageNumbers(): (number | 'ellipsis')[] {\n const pages: (number | 'ellipsis')[] = [];\n const totalCount = this.totalPages;\n const currentPageNum = this.currentPage;\n const siblingCountNum = this.siblingCount;\n const boundaryCountNum = this.boundaryCount;\n\n // Calculate range around current page\n const startPage = Math.max(1, currentPageNum - siblingCountNum);\n const endPage = Math.min(totalCount, currentPageNum + siblingCountNum);\n\n // Add boundary pages at start\n for (let i = 1; i <= Math.min(boundaryCountNum, totalCount); i++) {\n pages.push(i);\n }\n\n // Add ellipsis after boundary if needed\n if (startPage > boundaryCountNum + 1) {\n pages.push('ellipsis');\n }\n\n // Add pages around current page\n for (let i = startPage; i <= endPage; i++) {\n if (i > boundaryCountNum && i <= totalCount - boundaryCountNum) {\n pages.push(i);\n }\n }\n\n // Add ellipsis before end boundary if needed\n if (endPage < totalCount - boundaryCountNum) {\n pages.push('ellipsis');\n }\n\n // Add boundary pages at end\n for (\n let i = Math.max(totalCount - boundaryCountNum + 1, boundaryCountNum + 1);\n i <= totalCount;\n i++\n ) {\n if (!pages.includes(i)) {\n pages.push(i);\n }\n }\n\n // Remove duplicates while preserving order\n return pages.filter((page, index, self) => self.indexOf(page) === index);\n }\n\n render() {\n const pageNumbers = this.getPageNumbers();\n const isFirstPage = this.currentPage === 1;\n const isLastPage = this.currentPage === this.totalPages;\n\n return html`\n <nav\n class=\"pagination pagination--${this.size}\"\n part=\"container\"\n aria-label=\"Pagination\"\n >\n ${this.showFirstLast\n ? html`\n <button\n class=\"pagination__button pagination__button--first\"\n part=\"button button-first\"\n ?disabled=${this.disabled || isFirstPage}\n @click=${() => this.handlePageChange(1)}\n aria-label=\"First page\"\n >\n «\n </button>\n `\n : ''}\n ${this.showPrevNext\n ? html`\n <button\n class=\"pagination__button pagination__button--prev\"\n part=\"button button-prev\"\n ?disabled=${this.disabled || isFirstPage}\n @click=${() => this.handlePageChange(this.currentPage - 1)}\n aria-label=\"Previous page\"\n >\n ‹\n </button>\n `\n : ''}\n ${repeat(\n pageNumbers,\n (page, index) => (page === 'ellipsis' ? `ellipsis-${index}` : page),\n (page) =>\n page === 'ellipsis'\n ? html`\n <span\n class=\"pagination__ellipsis\"\n part=\"button-ellipsis\"\n aria-hidden=\"true\"\n >…</span\n >\n `\n : html`\n <button\n class=\"pagination__button pagination__button--page ${page ===\n this.currentPage\n ? 'pagination__button--active'\n : ''}\"\n part=\"button button-page\"\n ?disabled=${this.disabled}\n @click=${() => this.handlePageChange(page)}\n aria-label=\"Page ${page}\"\n aria-current=${page === this.currentPage ? 'page' : 'false'}\n >\n ${page}\n </button>\n `\n )}\n ${this.showPrevNext\n ? html`\n <button\n class=\"pagination__button pagination__button--next\"\n part=\"button button-next\"\n ?disabled=${this.disabled || isLastPage}\n @click=${() => this.handlePageChange(this.currentPage + 1)}\n aria-label=\"Next page\"\n >\n ›\n </button>\n `\n : ''}\n ${this.showFirstLast\n ? html`\n <button\n class=\"pagination__button pagination__button--last\"\n part=\"button button-last\"\n ?disabled=${this.disabled || isLastPage}\n @click=${() => this.handlePageChange(this.totalPages)}\n aria-label=\"Last page\"\n >\n »\n </button>\n `\n : ''}\n ${this.showInfo\n ? html`\n <span class=\"pagination__info\" part=\"info\" aria-live=\"polite\">\n Page ${this.currentPage} of ${this.totalPages}\n </span>\n `\n : ''}\n </nav>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'bp-pagination': BpPagination;\n }\n}\n"],"names":["paginationStyles","css","BpPagination","LitElement","newPage","pages","totalCount","currentPageNum","siblingCountNum","boundaryCountNum","startPage","endPage","i","page","index","self","pageNumbers","isFirstPage","isLastPage","html","repeat","__decorateClass","property","booleanConverter","customElement"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"popover.js","sources":["../../source/components/popover/popover.style.ts","../../source/components/popover/popover.ts"],"sourcesContent":["import { css } from 'lit';\r\n\r\nexport const popoverStyles = css`\r\n /* Base styles */\r\n :host {\r\n display: inline-block;\r\n position: relative;\r\n }\r\n\r\n .popover {\r\n position: relative;\r\n display: inline-block;\r\n font-family: var(--bp-font-family);\r\n font-size: var(--bp-font-size-base);\r\n color: var(--bp-color-text);\r\n }\r\n\r\n /* Trigger */\r\n .popover__trigger {\r\n display: inline-flex;\r\n align-items: center;\r\n cursor: pointer;\r\n outline: none;\r\n user-select: none;\r\n }\r\n\r\n .popover__trigger:hover {\r\n opacity: 0.8;\r\n }\r\n\r\n .popover__trigger:focus-visible {\r\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\r\n outline-offset: var(--bp-focus-offset);\r\n border-radius: var(--bp-border-radius-sm);\r\n }\r\n\r\n .popover--disabled .popover__trigger {\r\n cursor: not-allowed;\r\n opacity: var(--bp-opacity-disabled);\r\n }\r\n\r\n /* Panel base */\r\n .popover__panel {\r\n position: absolute;\r\n z-index: var(--bp-z-popover);\r\n min-width: 160px;\r\n max-width: 320px;\r\n max-height: calc(100vh - 80px);\r\n background-color: var(--bp-color-surface-elevated);\r\n border: var(--bp-border-width) solid var(--bp-color-border);\r\n border-radius: var(--bp-border-radius-lg);\r\n box-shadow: var(--bp-shadow-lg);\r\n opacity: 1;\r\n animation: popover-fade-in var(--bp-transition-fast) ease-out;\r\n }\r\n\r\n @keyframes popover-fade-in {\r\n from {\r\n opacity: 0;\r\n transform: scale(0.95);\r\n }\r\n to {\r\n opacity: 1;\r\n transform: scale(1);\r\n }\r\n }\r\n\r\n /* Panel placements - Bottom */\r\n .popover__panel--bottom,\r\n .popover__panel--bottom-start,\r\n .popover__panel--bottom-end {\r\n top: 100%;\r\n margin-top: var(--popover-distance);\r\n }\r\n\r\n .popover__panel--bottom {\r\n left: 50%;\r\n transform: translateX(-50%);\r\n }\r\n\r\n .popover__panel--bottom-start {\r\n left: 0;\r\n }\r\n\r\n .popover__panel--bottom-end {\r\n right: 0;\r\n }\r\n\r\n /* Panel placements - Top */\r\n .popover__panel--top,\r\n .popover__panel--top-start,\r\n .popover__panel--top-end {\r\n bottom: 100%;\r\n margin-bottom: var(--popover-distance);\r\n }\r\n\r\n .popover__panel--top {\r\n left: 50%;\r\n transform: translateX(-50%);\r\n }\r\n\r\n .popover__panel--top-start {\r\n left: 0;\r\n }\r\n\r\n .popover__panel--top-end {\r\n right: 0;\r\n }\r\n\r\n /* Panel placements - Left */\r\n .popover__panel--left,\r\n .popover__panel--left-start,\r\n .popover__panel--left-end {\r\n right: 100%;\r\n margin-right: var(--popover-distance);\r\n }\r\n\r\n .popover__panel--left {\r\n top: 50%;\r\n transform: translateY(-50%);\r\n }\r\n\r\n .popover__panel--left-start {\r\n top: 0;\r\n }\r\n\r\n .popover__panel--left-end {\r\n bottom: 0;\r\n }\r\n\r\n /* Panel placements - Right */\r\n .popover__panel--right,\r\n .popover__panel--right-start,\r\n .popover__panel--right-end {\r\n left: 100%;\r\n margin-left: var(--popover-distance);\r\n }\r\n\r\n .popover__panel--right {\r\n top: 50%;\r\n transform: translateY(-50%);\r\n }\r\n\r\n .popover__panel--right-start {\r\n top: 0;\r\n }\r\n\r\n .popover__panel--right-end {\r\n bottom: 0;\r\n }\r\n\r\n /* Arrow */\r\n .popover__arrow {\r\n position: absolute;\r\n width: var(--bp-spacing-5);\r\n height: var(--bp-spacing-5);\r\n background-color: var(--bp-color-surface-elevated);\r\n border: var(--bp-border-width) solid var(--bp-color-border);\r\n transform: rotate(45deg);\r\n z-index: -1;\r\n }\r\n\r\n /* Arrow positions - bottom placements */\r\n .popover__panel--bottom .popover__arrow,\r\n .popover__panel--bottom-start .popover__arrow,\r\n .popover__panel--bottom-end .popover__arrow {\r\n top: calc(var(--bp-spacing-2) * -1);\r\n border-bottom: none;\r\n border-right: none;\r\n }\r\n\r\n .popover__panel--bottom .popover__arrow {\r\n left: 50%;\r\n transform: translateX(-50%) rotate(45deg);\r\n }\r\n\r\n .popover__panel--bottom-start .popover__arrow {\r\n left: var(--bp-spacing-5);\r\n }\r\n\r\n .popover__panel--bottom-end .popover__arrow {\r\n right: var(--bp-spacing-5);\r\n }\r\n\r\n /* Arrow positions - top placements */\r\n .popover__panel--top .popover__arrow,\r\n .popover__panel--top-start .popover__arrow,\r\n .popover__panel--top-end .popover__arrow {\r\n bottom: calc(var(--bp-spacing-2) * -1);\r\n border-top: none;\r\n border-left: none;\r\n }\r\n\r\n .popover__panel--top .popover__arrow {\r\n left: 50%;\r\n transform: translateX(-50%) rotate(45deg);\r\n }\r\n\r\n .popover__panel--top-start .popover__arrow {\r\n left: var(--bp-spacing-5);\r\n }\r\n\r\n .popover__panel--top-end .popover__arrow {\r\n right: var(--bp-spacing-5);\r\n }\r\n\r\n /* Arrow positions - left placements */\r\n .popover__panel--left .popover__arrow,\r\n .popover__panel--left-start .popover__arrow,\r\n .popover__panel--left-end .popover__arrow {\r\n right: calc(var(--bp-spacing-2) * -1);\r\n border-left: none;\r\n border-bottom: none;\r\n }\r\n\r\n .popover__panel--left .popover__arrow {\r\n top: 50%;\r\n transform: translateY(-50%) rotate(45deg);\r\n }\r\n\r\n .popover__panel--left-start .popover__arrow {\r\n top: var(--bp-spacing-5);\r\n }\r\n\r\n .popover__panel--left-end .popover__arrow {\r\n bottom: var(--bp-spacing-5);\r\n }\r\n\r\n /* Arrow positions - right placements */\r\n .popover__panel--right .popover__arrow,\r\n .popover__panel--right-start .popover__arrow,\r\n .popover__panel--right-end .popover__arrow {\r\n left: calc(var(--bp-spacing-2) * -1);\r\n border-right: none;\r\n border-top: none;\r\n }\r\n\r\n .popover__panel--right .popover__arrow {\r\n top: 50%;\r\n transform: translateY(-50%) rotate(45deg);\r\n }\r\n\r\n .popover__panel--right-start .popover__arrow {\r\n top: var(--bp-spacing-5);\r\n }\r\n\r\n .popover__panel--right-end .popover__arrow {\r\n bottom: var(--bp-spacing-5);\r\n }\r\n\r\n /* Header */\r\n .popover__header {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: var(--bp-spacing-4);\r\n padding: var(--bp-spacing-4) var(--bp-spacing-5);\r\n border-bottom: var(--bp-border-width) solid var(--bp-color-border);\r\n }\r\n\r\n .popover__header ::slotted(*) {\r\n margin: 0;\r\n font-size: var(--bp-font-size-base);\r\n font-weight: var(--bp-font-weight-semibold);\r\n color: var(--bp-color-text-strong);\r\n }\r\n\r\n /* Body */\r\n .popover__body {\r\n padding: var(--bp-spacing-4) var(--bp-spacing-5);\r\n overflow-y: auto;\r\n max-height: calc(100vh - 160px);\r\n }\r\n\r\n /* Footer */\r\n .popover__footer {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--bp-spacing-4);\r\n padding: var(--bp-spacing-4) var(--bp-spacing-5);\r\n border-top: var(--bp-border-width) solid var(--bp-color-border);\r\n }\r\n\r\n /* Close button */\r\n .popover__close {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 44px;\r\n height: 44px;\r\n padding: 0;\r\n margin-left: auto;\r\n background: transparent;\r\n border: none;\r\n border-radius: var(--bp-border-radius-sm);\r\n color: var(--bp-color-text-muted);\r\n cursor: pointer;\r\n transition:\r\n background-color var(--bp-transition-fast),\r\n color var(--bp-transition-fast),\r\n transform var(--bp-transition-fast);\r\n }\r\n\r\n .popover__close:hover {\r\n background-color: var(--bp-color-surface-subdued);\r\n color: var(--bp-color-text);\r\n }\r\n\r\n .popover__close:active {\r\n background-color: var(--bp-color-surface-pressed);\r\n transform: translateY(1px);\r\n }\r\n\r\n .popover__close:focus {\r\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\r\n outline-offset: var(--bp-focus-offset);\r\n }\r\n\r\n .popover__close:focus:not(:focus-visible) {\r\n outline: none;\r\n }\r\n\r\n .popover__close:focus-visible {\r\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\r\n outline-offset: var(--bp-focus-offset);\r\n }\r\n\r\n .popover__close bp-icon {\r\n width: var(--bp-spacing-4);\r\n height: var(--bp-spacing-4);\r\n }\r\n\r\n /* Reduced motion */\r\n @media (prefers-reduced-motion: reduce) {\r\n .popover__panel {\r\n animation: none;\r\n }\r\n\r\n .popover__close {\r\n transition: none;\r\n }\r\n }\r\n`;\r\n","import { LitElement, html, nothing } from 'lit';\r\nimport { customElement, property, state, query } from 'lit/decorators.js';\r\nimport { popoverStyles } from './popover.style.js';\r\nimport { booleanConverter } from '../../utilities/boolean-converter.js';\r\nimport '../icon/icon.js';\r\n\r\nexport type PopoverPlacement =\r\n | 'top'\r\n | 'top-start'\r\n | 'top-end'\r\n | 'bottom'\r\n | 'bottom-start'\r\n | 'bottom-end'\r\n | 'left'\r\n | 'left-start'\r\n | 'left-end'\r\n | 'right'\r\n | 'right-start'\r\n | 'right-end';\r\n\r\nexport type PopoverTrigger = 'click' | 'hover' | 'focus' | 'manual';\r\n\r\n/**\r\n * A popover component that displays rich content in a floating panel.\r\n * Supports multiple trigger modes: click, hover, focus, or manual control.\r\n *\r\n * @fires bp-show - Fired when the popover opens\r\n * @fires bp-hide - Fired when the popover closes\r\n * @fires bp-after-show - Fired after the popover open animation completes\r\n * @fires bp-after-hide - Fired after the popover close animation completes\r\n *\r\n * @slot - The trigger element that controls the popover\r\n * @slot content - The rich content to display in the popover panel\r\n * @slot header - Optional header content for the popover\r\n * @slot footer - Optional footer content for the popover\r\n *\r\n * @csspart trigger - The trigger wrapper element\r\n * @csspart panel - The popover panel container\r\n * @csspart header - The header section\r\n * @csspart body - The body/content section\r\n * @csspart footer - The footer section\r\n * @csspart arrow - The arrow pointing to the trigger\r\n * @csspart close-button - The close button (when showClose is true)\r\n */\r\n@customElement('bp-popover')\r\nexport class BpPopover extends LitElement {\r\n /** Whether the popover is currently open */\r\n @property({ type: Boolean, reflect: true }) declare open: boolean;\r\n\r\n /** Placement of the popover relative to the trigger */\r\n @property({\r\n type: String,\r\n reflect: true,\r\n converter: {\r\n fromAttribute: (value: string | null): PopoverPlacement => {\r\n const validPlacements: PopoverPlacement[] = [\r\n 'top',\r\n 'top-start',\r\n 'top-end',\r\n 'bottom',\r\n 'bottom-start',\r\n 'bottom-end',\r\n 'left',\r\n 'left-start',\r\n 'left-end',\r\n 'right',\r\n 'right-start',\r\n 'right-end',\r\n ];\r\n return validPlacements.includes(value as PopoverPlacement)\r\n ? (value as PopoverPlacement)\r\n : 'bottom';\r\n },\r\n },\r\n })\r\n declare placement: PopoverPlacement;\r\n\r\n /** How the popover is triggered */\r\n @property({\r\n type: String,\r\n converter: {\r\n fromAttribute: (value: string | null): PopoverTrigger => {\r\n const validTriggers: PopoverTrigger[] = [\r\n 'click',\r\n 'hover',\r\n 'focus',\r\n 'manual',\r\n ];\r\n return validTriggers.includes(value as PopoverTrigger)\r\n ? (value as PopoverTrigger)\r\n : 'click';\r\n },\r\n },\r\n })\r\n declare trigger: PopoverTrigger;\r\n\r\n /** Whether to show an arrow pointing to the trigger */\r\n @property({ type: Boolean }) declare arrow: boolean;\r\n\r\n /** Whether to show a close button in the popover */\r\n @property({ type: Boolean, attribute: 'show-close' })\r\n declare showClose: boolean;\r\n\r\n /** Whether clicking outside closes the popover */\r\n @property({\r\n converter: booleanConverter,\r\n attribute: 'close-on-outside-click',\r\n reflect: true,\r\n })\r\n declare closeOnOutsideClick: boolean;\r\n\r\n /** Whether pressing Escape closes the popover */\r\n @property({\r\n converter: booleanConverter,\r\n attribute: 'close-on-escape',\r\n reflect: true,\r\n })\r\n declare closeOnEscape: boolean;\r\n\r\n /** Distance in pixels between the trigger and the panel */\r\n @property({ type: Number }) declare distance: number;\r\n\r\n /** Delay in milliseconds before showing (for hover trigger) */\r\n @property({ type: Number, attribute: 'show-delay' })\r\n declare showDelay: number;\r\n\r\n /** Delay in milliseconds before hiding (for hover trigger) */\r\n @property({ type: Number, attribute: 'hide-delay' })\r\n declare hideDelay: number;\r\n\r\n /** Whether the popover is disabled */\r\n @property({ type: Boolean }) declare disabled: boolean;\r\n\r\n /** Accessible label for the popover panel */\r\n @property({ type: String }) declare label: string;\r\n\r\n /** Whether the popover has header slot content */\r\n @state() private hasHeader = false;\r\n\r\n /** Whether the popover has footer slot content */\r\n @state() private hasFooter = false;\r\n\r\n @query('.popover__trigger') private triggerElement!: HTMLElement;\r\n\r\n private showTimeout: number | null = null;\r\n private hideTimeout: number | null = null;\r\n private popoverId = `popover-${Math.random().toString(36).substring(2, 11)}`;\r\n\r\n static styles = [popoverStyles];\r\n\r\n constructor() {\r\n super();\r\n this.open = false;\r\n this.placement = 'bottom';\r\n this.trigger = 'click';\r\n this.arrow = false;\r\n this.showClose = false;\r\n this.closeOnOutsideClick = true;\r\n this.closeOnEscape = true;\r\n this.distance = 8;\r\n this.showDelay = 200;\r\n this.hideDelay = 200;\r\n this.disabled = false;\r\n this.label = '';\r\n }\r\n\r\n connectedCallback(): void {\r\n super.connectedCallback();\r\n document.addEventListener('click', this.handleDocumentClick, {\r\n passive: true,\r\n });\r\n document.addEventListener('keydown', this.handleDocumentKeydown);\r\n }\r\n\r\n disconnectedCallback(): void {\r\n super.disconnectedCallback();\r\n document.removeEventListener('click', this.handleDocumentClick, {\r\n passive: true,\r\n } as EventListenerOptions);\r\n document.removeEventListener('keydown', this.handleDocumentKeydown);\r\n this.clearTimeouts();\r\n }\r\n\r\n /** Show the popover */\r\n show(): void {\r\n if (this.disabled || this.open) return;\r\n\r\n this.clearTimeouts();\r\n this.open = true;\r\n\r\n this.dispatchEvent(\r\n new CustomEvent('bp-show', { bubbles: true, composed: true })\r\n );\r\n\r\n this.updateComplete.then(() => {\r\n this.dispatchEvent(\r\n new CustomEvent('bp-after-show', { bubbles: true, composed: true })\r\n );\r\n });\r\n }\r\n\r\n /** Hide the popover */\r\n hide(): void {\r\n if (!this.open) return;\r\n\r\n this.clearTimeouts();\r\n this.open = false;\r\n\r\n this.dispatchEvent(\r\n new CustomEvent('bp-hide', { bubbles: true, composed: true })\r\n );\r\n\r\n this.updateComplete.then(() => {\r\n this.dispatchEvent(\r\n new CustomEvent('bp-after-hide', { bubbles: true, composed: true })\r\n );\r\n });\r\n }\r\n\r\n /** Toggle the popover open/closed */\r\n toggle(): void {\r\n if (this.open) {\r\n this.hide();\r\n } else {\r\n this.show();\r\n }\r\n }\r\n\r\n /**\r\n * Clears any pending show/hide timeout operations.\r\n * Prevents race conditions with rapid trigger interactions.\r\n */\r\n private clearTimeouts(): void {\r\n if (this.showTimeout !== null) {\r\n window.clearTimeout(this.showTimeout);\r\n this.showTimeout = null;\r\n }\r\n if (this.hideTimeout !== null) {\r\n window.clearTimeout(this.hideTimeout);\r\n this.hideTimeout = null;\r\n }\r\n }\r\n\r\n /**\r\n * Handles click events on the trigger element.\r\n * Toggles popover state for click trigger mode.\r\n * @param event - The mouse click event\r\n */\r\n private handleTriggerClick = (event: MouseEvent): void => {\r\n if (this.disabled || this.trigger !== 'click') return;\r\n event.stopPropagation();\r\n this.toggle();\r\n };\r\n\r\n /**\r\n * Handles keyboard events on the trigger element.\r\n * Toggles popover on Enter or Space key for click trigger mode.\r\n * @param event - The keyboard event\r\n */\r\n private handleTriggerKeydown = (event: KeyboardEvent): void => {\r\n if (this.disabled) return;\r\n\r\n if (\r\n this.trigger === 'click' &&\r\n (event.key === 'Enter' || event.key === ' ')\r\n ) {\r\n event.preventDefault();\r\n this.toggle();\r\n }\r\n };\r\n\r\n /**\r\n * Handles mouse enter events on the trigger element.\r\n * Starts the show delay timer for hover trigger mode.\r\n */\r\n private handleTriggerMouseEnter = (): void => {\r\n if (this.disabled || this.trigger !== 'hover') return;\r\n\r\n this.clearTimeouts();\r\n this.showTimeout = window.setTimeout(() => {\r\n this.show();\r\n }, this.showDelay);\r\n };\r\n\r\n /**\r\n * Handles mouse leave events on the trigger element.\r\n * Starts the hide delay timer for hover trigger mode.\r\n */\r\n private handleTriggerMouseLeave = (): void => {\r\n if (this.trigger !== 'hover') return;\r\n\r\n this.clearTimeouts();\r\n this.hideTimeout = window.setTimeout(() => {\r\n this.hide();\r\n }, this.hideDelay);\r\n };\r\n\r\n /**\r\n * Handles mouse enter events on the popover panel.\r\n * Prevents the popover from hiding when hovering over panel content in hover trigger mode.\r\n */\r\n private handlePanelMouseEnter = (): void => {\r\n if (this.trigger !== 'hover') return;\r\n this.clearTimeouts();\r\n };\r\n\r\n /**\r\n * Handles mouse leave events on the popover panel.\r\n * Starts the hide delay timer when leaving panel in hover trigger mode.\r\n */\r\n private handlePanelMouseLeave = (): void => {\r\n if (this.trigger !== 'hover') return;\r\n\r\n this.clearTimeouts();\r\n this.hideTimeout = window.setTimeout(() => {\r\n this.hide();\r\n }, this.hideDelay);\r\n };\r\n\r\n /**\r\n * Handles focus events on the trigger element.\r\n * Shows popover immediately for focus trigger mode.\r\n */\r\n private handleTriggerFocus = (): void => {\r\n if (this.disabled || this.trigger !== 'focus') return;\r\n this.show();\r\n };\r\n\r\n /**\r\n * Handles blur events on the trigger element.\r\n * Hides popover immediately for focus trigger mode.\r\n */\r\n private handleTriggerBlur = (): void => {\r\n if (this.trigger !== 'focus') return;\r\n this.hide();\r\n };\r\n\r\n /**\r\n * Handles click events on the document.\r\n * Closes popover when clicking outside if closeOnOutsideClick is true.\r\n * @param event - The mouse click event\r\n */\r\n private handleDocumentClick = (event: MouseEvent): void => {\r\n if (!this.closeOnOutsideClick || !this.open) return;\r\n if (this.trigger === 'manual') return;\r\n\r\n const path = event.composedPath();\r\n if (!path.includes(this)) {\r\n this.hide();\r\n }\r\n };\r\n\r\n /**\r\n * Handles keyboard events on the document.\r\n * Closes popover on Escape key if closeOnEscape is true and returns focus to trigger.\r\n * @param event - The keyboard event\r\n */\r\n private handleDocumentKeydown = (event: KeyboardEvent): void => {\r\n if (!this.closeOnEscape || !this.open) return;\r\n\r\n if (event.key === 'Escape') {\r\n event.preventDefault();\r\n this.hide();\r\n this.triggerElement?.focus();\r\n }\r\n };\r\n\r\n /**\r\n * Handles click events on the close button.\r\n * Closes the popover immediately.\r\n */\r\n private handleCloseClick = (): void => {\r\n this.hide();\r\n };\r\n\r\n /**\r\n * Handles changes to the header slot.\r\n * Updates internal state to conditionally render header wrapper.\r\n * @param event - The slotchange event\r\n */\r\n private handleHeaderSlotChange = (event: Event): void => {\r\n const slot = event.target as HTMLElement & {\r\n assignedNodes: (options?: { flatten?: boolean }) => Node[];\r\n };\r\n this.hasHeader = slot.assignedNodes({ flatten: true }).length > 0;\r\n };\r\n\r\n /**\r\n * Handles changes to the footer slot.\r\n * Updates internal state to conditionally render footer wrapper.\r\n * @param event - The slotchange event\r\n */\r\n private handleFooterSlotChange = (event: Event): void => {\r\n const slot = event.target as HTMLElement & {\r\n assignedNodes: (options?: { flatten?: boolean }) => Node[];\r\n };\r\n this.hasFooter = slot.assignedNodes({ flatten: true }).length > 0;\r\n };\r\n\r\n render() {\r\n return html`\r\n <div\r\n class=\"popover ${this.open ? 'popover--open' : ''} ${this.disabled\r\n ? 'popover--disabled'\r\n : ''}\"\r\n >\r\n <div\r\n class=\"popover__trigger\"\r\n part=\"trigger\"\r\n tabindex=${this.disabled ? -1 : 0}\r\n role=\"button\"\r\n aria-haspopup=\"dialog\"\r\n aria-expanded=${this.open}\r\n aria-controls=${this.open ? this.popoverId : nothing}\r\n aria-disabled=${this.disabled}\r\n @click=${this.handleTriggerClick}\r\n @keydown=${this.handleTriggerKeydown}\r\n @mouseenter=${this.handleTriggerMouseEnter}\r\n @mouseleave=${this.handleTriggerMouseLeave}\r\n @focus=${this.handleTriggerFocus}\r\n @blur=${this.handleTriggerBlur}\r\n >\r\n <slot></slot>\r\n </div>\r\n ${this.open\r\n ? html`\r\n <div\r\n id=${this.popoverId}\r\n class=\"popover__panel popover__panel--${this.placement}\"\r\n part=\"panel\"\r\n role=\"dialog\"\r\n aria-label=${this.label || nothing}\r\n aria-modal=\"false\"\r\n style=\"--popover-distance: ${this.distance}px;\"\r\n @mouseenter=${this.handlePanelMouseEnter}\r\n @mouseleave=${this.handlePanelMouseLeave}\r\n >\r\n ${this.arrow\r\n ? html`<div class=\"popover__arrow\" part=\"arrow\"></div>`\r\n : nothing}\r\n ${this.hasHeader || this.showClose\r\n ? html`\r\n <div class=\"popover__header\" part=\"header\">\r\n <slot\r\n name=\"header\"\r\n @slotchange=${this.handleHeaderSlotChange}\r\n ></slot>\r\n ${this.showClose\r\n ? html`\r\n <button\r\n class=\"popover__close\"\r\n part=\"close-button\"\r\n type=\"button\"\r\n aria-label=\"Close popover\"\r\n @click=${this.handleCloseClick}\r\n >\r\n <bp-icon name=\"close\" size=\"sm\"></bp-icon>\r\n </button>\r\n `\r\n : nothing}\r\n </div>\r\n `\r\n : html`<slot\r\n name=\"header\"\r\n @slotchange=${this.handleHeaderSlotChange}\r\n ></slot>`}\r\n <div class=\"popover__body\" part=\"body\">\r\n <slot name=\"content\"></slot>\r\n </div>\r\n ${this.hasFooter\r\n ? html`\r\n <div class=\"popover__footer\" part=\"footer\">\r\n <slot\r\n name=\"footer\"\r\n @slotchange=${this.handleFooterSlotChange}\r\n ></slot>\r\n </div>\r\n `\r\n : html`<slot\r\n name=\"footer\"\r\n @slotchange=${this.handleFooterSlotChange}\r\n ></slot>`}\r\n </div>\r\n `\r\n : nothing}\r\n </div>\r\n `;\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'bp-popover': BpPopover;\r\n }\r\n}\r\n"],"names":["popoverStyles","css","BpPopover","LitElement","event","slot","html","nothing","__decorateClass","property","value","booleanConverter","state","query","customElement"],"mappings":";;;AAEO,MAAMA,IAAgBC;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;AAAA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"}
1
+ {"version":3,"file":"popover.js","sources":["../../source/components/popover/popover.style.ts","../../source/components/popover/popover.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const popoverStyles = css`\n /* Base styles */\n :host {\n display: inline-block;\n position: relative;\n }\n\n .popover {\n position: relative;\n display: inline-block;\n font-family: var(--bp-font-family);\n font-size: var(--bp-font-size-base);\n color: var(--bp-color-text);\n }\n\n /* Trigger */\n .popover__trigger {\n display: inline-flex;\n align-items: center;\n cursor: pointer;\n outline: none;\n user-select: none;\n }\n\n .popover__trigger:hover {\n opacity: 0.8;\n }\n\n .popover__trigger:focus-visible {\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\n outline-offset: var(--bp-focus-offset);\n border-radius: var(--bp-border-radius-sm);\n }\n\n .popover--disabled .popover__trigger {\n cursor: not-allowed;\n opacity: var(--bp-opacity-disabled);\n }\n\n /* Panel base */\n .popover__panel {\n position: absolute;\n z-index: var(--bp-z-popover);\n min-width: 160px;\n max-width: 320px;\n max-height: calc(100vh - 80px);\n background-color: var(--bp-color-surface-elevated);\n border: var(--bp-border-width) solid var(--bp-color-border);\n border-radius: var(--bp-border-radius-lg);\n box-shadow: var(--bp-shadow-lg);\n opacity: 1;\n animation: popover-fade-in var(--bp-transition-fast) ease-out;\n }\n\n @keyframes popover-fade-in {\n from {\n opacity: 0;\n transform: scale(0.95);\n }\n to {\n opacity: 1;\n transform: scale(1);\n }\n }\n\n /* Panel placements - Bottom */\n .popover__panel--bottom,\n .popover__panel--bottom-start,\n .popover__panel--bottom-end {\n top: 100%;\n margin-top: var(--popover-distance);\n }\n\n .popover__panel--bottom {\n left: 50%;\n transform: translateX(-50%);\n }\n\n .popover__panel--bottom-start {\n left: 0;\n }\n\n .popover__panel--bottom-end {\n right: 0;\n }\n\n /* Panel placements - Top */\n .popover__panel--top,\n .popover__panel--top-start,\n .popover__panel--top-end {\n bottom: 100%;\n margin-bottom: var(--popover-distance);\n }\n\n .popover__panel--top {\n left: 50%;\n transform: translateX(-50%);\n }\n\n .popover__panel--top-start {\n left: 0;\n }\n\n .popover__panel--top-end {\n right: 0;\n }\n\n /* Panel placements - Left */\n .popover__panel--left,\n .popover__panel--left-start,\n .popover__panel--left-end {\n right: 100%;\n margin-right: var(--popover-distance);\n }\n\n .popover__panel--left {\n top: 50%;\n transform: translateY(-50%);\n }\n\n .popover__panel--left-start {\n top: 0;\n }\n\n .popover__panel--left-end {\n bottom: 0;\n }\n\n /* Panel placements - Right */\n .popover__panel--right,\n .popover__panel--right-start,\n .popover__panel--right-end {\n left: 100%;\n margin-left: var(--popover-distance);\n }\n\n .popover__panel--right {\n top: 50%;\n transform: translateY(-50%);\n }\n\n .popover__panel--right-start {\n top: 0;\n }\n\n .popover__panel--right-end {\n bottom: 0;\n }\n\n /* Arrow */\n .popover__arrow {\n position: absolute;\n width: var(--bp-spacing-5);\n height: var(--bp-spacing-5);\n background-color: var(--bp-color-surface-elevated);\n border: var(--bp-border-width) solid var(--bp-color-border);\n transform: rotate(45deg);\n z-index: -1;\n }\n\n /* Arrow positions - bottom placements */\n .popover__panel--bottom .popover__arrow,\n .popover__panel--bottom-start .popover__arrow,\n .popover__panel--bottom-end .popover__arrow {\n top: calc(var(--bp-spacing-2) * -1);\n border-bottom: none;\n border-right: none;\n }\n\n .popover__panel--bottom .popover__arrow {\n left: 50%;\n transform: translateX(-50%) rotate(45deg);\n }\n\n .popover__panel--bottom-start .popover__arrow {\n left: var(--bp-spacing-5);\n }\n\n .popover__panel--bottom-end .popover__arrow {\n right: var(--bp-spacing-5);\n }\n\n /* Arrow positions - top placements */\n .popover__panel--top .popover__arrow,\n .popover__panel--top-start .popover__arrow,\n .popover__panel--top-end .popover__arrow {\n bottom: calc(var(--bp-spacing-2) * -1);\n border-top: none;\n border-left: none;\n }\n\n .popover__panel--top .popover__arrow {\n left: 50%;\n transform: translateX(-50%) rotate(45deg);\n }\n\n .popover__panel--top-start .popover__arrow {\n left: var(--bp-spacing-5);\n }\n\n .popover__panel--top-end .popover__arrow {\n right: var(--bp-spacing-5);\n }\n\n /* Arrow positions - left placements */\n .popover__panel--left .popover__arrow,\n .popover__panel--left-start .popover__arrow,\n .popover__panel--left-end .popover__arrow {\n right: calc(var(--bp-spacing-2) * -1);\n border-left: none;\n border-bottom: none;\n }\n\n .popover__panel--left .popover__arrow {\n top: 50%;\n transform: translateY(-50%) rotate(45deg);\n }\n\n .popover__panel--left-start .popover__arrow {\n top: var(--bp-spacing-5);\n }\n\n .popover__panel--left-end .popover__arrow {\n bottom: var(--bp-spacing-5);\n }\n\n /* Arrow positions - right placements */\n .popover__panel--right .popover__arrow,\n .popover__panel--right-start .popover__arrow,\n .popover__panel--right-end .popover__arrow {\n left: calc(var(--bp-spacing-2) * -1);\n border-right: none;\n border-top: none;\n }\n\n .popover__panel--right .popover__arrow {\n top: 50%;\n transform: translateY(-50%) rotate(45deg);\n }\n\n .popover__panel--right-start .popover__arrow {\n top: var(--bp-spacing-5);\n }\n\n .popover__panel--right-end .popover__arrow {\n bottom: var(--bp-spacing-5);\n }\n\n /* Header */\n .popover__header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--bp-spacing-4);\n padding: var(--bp-spacing-4) var(--bp-spacing-5);\n border-bottom: var(--bp-border-width) solid var(--bp-color-border);\n }\n\n .popover__header ::slotted(*) {\n margin: 0;\n font-size: var(--bp-font-size-base);\n font-weight: var(--bp-font-weight-semibold);\n color: var(--bp-color-text-strong);\n }\n\n /* Body */\n .popover__body {\n padding: var(--bp-spacing-4) var(--bp-spacing-5);\n overflow-y: auto;\n max-height: calc(100vh - 160px);\n }\n\n /* Footer */\n .popover__footer {\n display: flex;\n align-items: center;\n gap: var(--bp-spacing-4);\n padding: var(--bp-spacing-4) var(--bp-spacing-5);\n border-top: var(--bp-border-width) solid var(--bp-color-border);\n }\n\n /* Close button */\n .popover__close {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n padding: 0;\n margin-left: auto;\n background: transparent;\n border: none;\n border-radius: var(--bp-border-radius-sm);\n color: var(--bp-color-text-muted);\n cursor: pointer;\n transition:\n background-color var(--bp-transition-fast),\n color var(--bp-transition-fast),\n transform var(--bp-transition-fast);\n }\n\n .popover__close:hover {\n background-color: var(--bp-color-surface-subdued);\n color: var(--bp-color-text);\n }\n\n .popover__close:active {\n background-color: var(--bp-color-surface-pressed);\n transform: translateY(1px);\n }\n\n .popover__close:focus {\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\n outline-offset: var(--bp-focus-offset);\n }\n\n .popover__close:focus:not(:focus-visible) {\n outline: none;\n }\n\n .popover__close: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 .popover__close bp-icon {\n width: var(--bp-spacing-4);\n height: var(--bp-spacing-4);\n }\n\n /* Reduced motion */\n @media (prefers-reduced-motion: reduce) {\n .popover__panel {\n animation: none;\n }\n\n .popover__close {\n transition: none;\n }\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state, query } from 'lit/decorators.js';\nimport { popoverStyles } from './popover.style.js';\nimport { booleanConverter } from '../../utilities/boolean-converter.js';\nimport '../icon/icon.js';\n\nexport type PopoverPlacement =\n | 'top'\n | 'top-start'\n | 'top-end'\n | 'bottom'\n | 'bottom-start'\n | 'bottom-end'\n | 'left'\n | 'left-start'\n | 'left-end'\n | 'right'\n | 'right-start'\n | 'right-end';\n\nexport type PopoverTrigger = 'click' | 'hover' | 'focus' | 'manual';\n\n/**\n * A popover component that displays rich content in a floating panel.\n * Supports multiple trigger modes: click, hover, focus, or manual control.\n *\n * @fires bp-show - Fired when the popover opens\n * @fires bp-hide - Fired when the popover closes\n * @fires bp-after-show - Fired after the popover open animation completes\n * @fires bp-after-hide - Fired after the popover close animation completes\n *\n * @slot - The trigger element that controls the popover\n * @slot content - The rich content to display in the popover panel\n * @slot header - Optional header content for the popover\n * @slot footer - Optional footer content for the popover\n *\n * @csspart trigger - The trigger wrapper element\n * @csspart panel - The popover panel container\n * @csspart header - The header section\n * @csspart body - The body/content section\n * @csspart footer - The footer section\n * @csspart arrow - The arrow pointing to the trigger\n * @csspart close-button - The close button (when showClose is true)\n */\n@customElement('bp-popover')\nexport class BpPopover extends LitElement {\n /** Whether the popover is currently open */\n @property({ type: Boolean, reflect: true }) declare open: boolean;\n\n /** Placement of the popover relative to the trigger */\n @property({\n type: String,\n reflect: true,\n converter: {\n fromAttribute: (value: string | null): PopoverPlacement => {\n const validPlacements: PopoverPlacement[] = [\n 'top',\n 'top-start',\n 'top-end',\n 'bottom',\n 'bottom-start',\n 'bottom-end',\n 'left',\n 'left-start',\n 'left-end',\n 'right',\n 'right-start',\n 'right-end',\n ];\n return validPlacements.includes(value as PopoverPlacement)\n ? (value as PopoverPlacement)\n : 'bottom';\n },\n },\n })\n declare placement: PopoverPlacement;\n\n /** How the popover is triggered */\n @property({\n type: String,\n converter: {\n fromAttribute: (value: string | null): PopoverTrigger => {\n const validTriggers: PopoverTrigger[] = [\n 'click',\n 'hover',\n 'focus',\n 'manual',\n ];\n return validTriggers.includes(value as PopoverTrigger)\n ? (value as PopoverTrigger)\n : 'click';\n },\n },\n })\n declare trigger: PopoverTrigger;\n\n /** Whether to show an arrow pointing to the trigger */\n @property({ type: Boolean }) declare arrow: boolean;\n\n /** Whether to show a close button in the popover */\n @property({ type: Boolean, attribute: 'show-close' })\n declare showClose: boolean;\n\n /** Whether clicking outside closes the popover */\n @property({\n converter: booleanConverter,\n attribute: 'close-on-outside-click',\n reflect: true,\n })\n declare closeOnOutsideClick: boolean;\n\n /** Whether pressing Escape closes the popover */\n @property({\n converter: booleanConverter,\n attribute: 'close-on-escape',\n reflect: true,\n })\n declare closeOnEscape: boolean;\n\n /** Distance in pixels between the trigger and the panel */\n @property({ type: Number }) declare distance: number;\n\n /** Delay in milliseconds before showing (for hover trigger) */\n @property({ type: Number, attribute: 'show-delay' })\n declare showDelay: number;\n\n /** Delay in milliseconds before hiding (for hover trigger) */\n @property({ type: Number, attribute: 'hide-delay' })\n declare hideDelay: number;\n\n /** Whether the popover is disabled */\n @property({ type: Boolean }) declare disabled: boolean;\n\n /** Accessible label for the popover panel */\n @property({ type: String }) declare label: string;\n\n /** Whether the popover has header slot content */\n @state() private hasHeader = false;\n\n /** Whether the popover has footer slot content */\n @state() private hasFooter = false;\n\n @query('.popover__trigger') private triggerElement!: HTMLElement;\n\n private showTimeout: number | null = null;\n private hideTimeout: number | null = null;\n private popoverId = `popover-${Math.random().toString(36).substring(2, 11)}`;\n\n static styles = [popoverStyles];\n\n constructor() {\n super();\n this.open = false;\n this.placement = 'bottom';\n this.trigger = 'click';\n this.arrow = false;\n this.showClose = false;\n this.closeOnOutsideClick = true;\n this.closeOnEscape = true;\n this.distance = 8;\n this.showDelay = 200;\n this.hideDelay = 200;\n this.disabled = false;\n this.label = '';\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n document.addEventListener('click', this.handleDocumentClick, {\n passive: true,\n });\n document.addEventListener('keydown', this.handleDocumentKeydown);\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('click', this.handleDocumentClick, {\n passive: true,\n } as EventListenerOptions);\n document.removeEventListener('keydown', this.handleDocumentKeydown);\n this.clearTimeouts();\n }\n\n /** Show the popover */\n show(): void {\n if (this.disabled || this.open) return;\n\n this.clearTimeouts();\n this.open = true;\n\n this.dispatchEvent(\n new CustomEvent('bp-show', { bubbles: true, composed: true })\n );\n\n this.updateComplete.then(() => {\n this.dispatchEvent(\n new CustomEvent('bp-after-show', { bubbles: true, composed: true })\n );\n });\n }\n\n /** Hide the popover */\n hide(): void {\n if (!this.open) return;\n\n this.clearTimeouts();\n this.open = false;\n\n this.dispatchEvent(\n new CustomEvent('bp-hide', { bubbles: true, composed: true })\n );\n\n this.updateComplete.then(() => {\n this.dispatchEvent(\n new CustomEvent('bp-after-hide', { bubbles: true, composed: true })\n );\n });\n }\n\n /** Toggle the popover open/closed */\n toggle(): void {\n if (this.open) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * Clears any pending show/hide timeout operations.\n * Prevents race conditions with rapid trigger interactions.\n */\n private clearTimeouts(): void {\n if (this.showTimeout !== null) {\n window.clearTimeout(this.showTimeout);\n this.showTimeout = null;\n }\n if (this.hideTimeout !== null) {\n window.clearTimeout(this.hideTimeout);\n this.hideTimeout = null;\n }\n }\n\n /**\n * Handles click events on the trigger element.\n * Toggles popover state for click trigger mode.\n * @param event - The mouse click event\n */\n private handleTriggerClick = (event: MouseEvent): void => {\n if (this.disabled || this.trigger !== 'click') return;\n event.stopPropagation();\n this.toggle();\n };\n\n /**\n * Handles keyboard events on the trigger element.\n * Toggles popover on Enter or Space key for click trigger mode.\n * @param event - The keyboard event\n */\n private handleTriggerKeydown = (event: KeyboardEvent): void => {\n if (this.disabled) return;\n\n if (\n this.trigger === 'click' &&\n (event.key === 'Enter' || event.key === ' ')\n ) {\n event.preventDefault();\n this.toggle();\n }\n };\n\n /**\n * Handles mouse enter events on the trigger element.\n * Starts the show delay timer for hover trigger mode.\n */\n private handleTriggerMouseEnter = (): void => {\n if (this.disabled || this.trigger !== 'hover') return;\n\n this.clearTimeouts();\n this.showTimeout = window.setTimeout(() => {\n this.show();\n }, this.showDelay);\n };\n\n /**\n * Handles mouse leave events on the trigger element.\n * Starts the hide delay timer for hover trigger mode.\n */\n private handleTriggerMouseLeave = (): void => {\n if (this.trigger !== 'hover') return;\n\n this.clearTimeouts();\n this.hideTimeout = window.setTimeout(() => {\n this.hide();\n }, this.hideDelay);\n };\n\n /**\n * Handles mouse enter events on the popover panel.\n * Prevents the popover from hiding when hovering over panel content in hover trigger mode.\n */\n private handlePanelMouseEnter = (): void => {\n if (this.trigger !== 'hover') return;\n this.clearTimeouts();\n };\n\n /**\n * Handles mouse leave events on the popover panel.\n * Starts the hide delay timer when leaving panel in hover trigger mode.\n */\n private handlePanelMouseLeave = (): void => {\n if (this.trigger !== 'hover') return;\n\n this.clearTimeouts();\n this.hideTimeout = window.setTimeout(() => {\n this.hide();\n }, this.hideDelay);\n };\n\n /**\n * Handles focus events on the trigger element.\n * Shows popover immediately for focus trigger mode.\n */\n private handleTriggerFocus = (): void => {\n if (this.disabled || this.trigger !== 'focus') return;\n this.show();\n };\n\n /**\n * Handles blur events on the trigger element.\n * Hides popover immediately for focus trigger mode.\n */\n private handleTriggerBlur = (): void => {\n if (this.trigger !== 'focus') return;\n this.hide();\n };\n\n /**\n * Handles click events on the document.\n * Closes popover when clicking outside if closeOnOutsideClick is true.\n * @param event - The mouse click event\n */\n private handleDocumentClick = (event: MouseEvent): void => {\n if (!this.closeOnOutsideClick || !this.open) return;\n if (this.trigger === 'manual') return;\n\n const path = event.composedPath();\n if (!path.includes(this)) {\n this.hide();\n }\n };\n\n /**\n * Handles keyboard events on the document.\n * Closes popover on Escape key if closeOnEscape is true and returns focus to trigger.\n * @param event - The keyboard event\n */\n private handleDocumentKeydown = (event: KeyboardEvent): void => {\n if (!this.closeOnEscape || !this.open) return;\n\n if (event.key === 'Escape') {\n event.preventDefault();\n this.hide();\n this.triggerElement?.focus();\n }\n };\n\n /**\n * Handles click events on the close button.\n * Closes the popover immediately.\n */\n private handleCloseClick = (): void => {\n this.hide();\n };\n\n /**\n * Handles changes to the header slot.\n * Updates internal state to conditionally render header wrapper.\n * @param event - The slotchange event\n */\n private handleHeaderSlotChange = (event: Event): void => {\n const slot = event.target as HTMLElement & {\n assignedNodes: (options?: { flatten?: boolean }) => Node[];\n };\n this.hasHeader = slot.assignedNodes({ flatten: true }).length > 0;\n };\n\n /**\n * Handles changes to the footer slot.\n * Updates internal state to conditionally render footer wrapper.\n * @param event - The slotchange event\n */\n private handleFooterSlotChange = (event: Event): void => {\n const slot = event.target as HTMLElement & {\n assignedNodes: (options?: { flatten?: boolean }) => Node[];\n };\n this.hasFooter = slot.assignedNodes({ flatten: true }).length > 0;\n };\n\n render() {\n return html`\n <div\n class=\"popover ${this.open ? 'popover--open' : ''} ${this.disabled\n ? 'popover--disabled'\n : ''}\"\n >\n <div\n class=\"popover__trigger\"\n part=\"trigger\"\n tabindex=${this.disabled ? -1 : 0}\n role=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded=${this.open}\n aria-controls=${this.open ? this.popoverId : nothing}\n aria-disabled=${this.disabled}\n @click=${this.handleTriggerClick}\n @keydown=${this.handleTriggerKeydown}\n @mouseenter=${this.handleTriggerMouseEnter}\n @mouseleave=${this.handleTriggerMouseLeave}\n @focus=${this.handleTriggerFocus}\n @blur=${this.handleTriggerBlur}\n >\n <slot></slot>\n </div>\n ${this.open\n ? html`\n <div\n id=${this.popoverId}\n class=\"popover__panel popover__panel--${this.placement}\"\n part=\"panel\"\n role=\"dialog\"\n aria-label=${this.label || nothing}\n aria-modal=\"false\"\n style=\"--popover-distance: ${this.distance}px;\"\n @mouseenter=${this.handlePanelMouseEnter}\n @mouseleave=${this.handlePanelMouseLeave}\n >\n ${this.arrow\n ? html`<div class=\"popover__arrow\" part=\"arrow\"></div>`\n : nothing}\n ${this.hasHeader || this.showClose\n ? html`\n <div class=\"popover__header\" part=\"header\">\n <slot\n name=\"header\"\n @slotchange=${this.handleHeaderSlotChange}\n ></slot>\n ${this.showClose\n ? html`\n <button\n class=\"popover__close\"\n part=\"close-button\"\n type=\"button\"\n aria-label=\"Close popover\"\n @click=${this.handleCloseClick}\n >\n <bp-icon name=\"close\" size=\"sm\"></bp-icon>\n </button>\n `\n : nothing}\n </div>\n `\n : html`<slot\n name=\"header\"\n @slotchange=${this.handleHeaderSlotChange}\n ></slot>`}\n <div class=\"popover__body\" part=\"body\">\n <slot name=\"content\"></slot>\n </div>\n ${this.hasFooter\n ? html`\n <div class=\"popover__footer\" part=\"footer\">\n <slot\n name=\"footer\"\n @slotchange=${this.handleFooterSlotChange}\n ></slot>\n </div>\n `\n : html`<slot\n name=\"footer\"\n @slotchange=${this.handleFooterSlotChange}\n ></slot>`}\n </div>\n `\n : nothing}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'bp-popover': BpPopover;\n }\n}\n"],"names":["popoverStyles","css","BpPopover","LitElement","event","slot","html","nothing","__decorateClass","property","value","booleanConverter","state","query","customElement"],"mappings":";;;AAEO,MAAMA,IAAgBC;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;AAAA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"}
@@ -1 +1 @@
1
- {"version":3,"file":"radio.js","sources":["../../source/components/radio/radio.style.ts","../../source/components/radio/radio.ts"],"sourcesContent":["import { css } from 'lit';\r\n\r\nexport const radioStyles = css`\r\n /* Base styles */\r\n :host {\r\n display: inline-block;\r\n }\r\n\r\n .radio {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: var(--bp-spacing-sm);\r\n cursor: pointer;\r\n font-family: var(--bp-font-family);\r\n font-size: var(--bp-font-size-base);\r\n color: var(--bp-color-text);\r\n user-select: none;\r\n }\r\n\r\n .radio__input {\r\n position: absolute;\r\n opacity: 0;\r\n width: 0;\r\n height: 0;\r\n margin: 0;\r\n padding: 0;\r\n }\r\n\r\n .radio__circle {\r\n position: relative;\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n border: var(--bp-border-width) solid var(--bp-color-border-strong);\r\n border-radius: 50%;\r\n background-color: var(--bp-color-surface);\r\n transition: all var(--bp-transition-fast);\r\n }\r\n\r\n .radio__circle-inner {\r\n width: 50%;\r\n height: 50%;\r\n border-radius: 50%;\r\n background-color: var(--bp-color-text-inverse);\r\n opacity: 0;\r\n transform: scale(0);\r\n transition:\r\n opacity var(--bp-duration-fast) var(--bp-ease-out),\r\n transform var(--bp-duration-fast) var(--bp-ease-bounce);\r\n }\r\n\r\n .radio__label {\r\n line-height: var(--bp-line-height-normal);\r\n }\r\n\r\n /* Sizes */\r\n .radio--sm .radio__circle {\r\n width: var(--bp-spacing-4);\r\n height: var(--bp-spacing-4);\r\n }\r\n\r\n .radio--sm .radio__label {\r\n font-size: var(--bp-font-size-sm);\r\n }\r\n\r\n .radio--md .radio__circle {\r\n width: var(--bp-spacing-5);\r\n height: var(--bp-spacing-5);\r\n }\r\n\r\n .radio--md .radio__label {\r\n font-size: var(--bp-font-size-base);\r\n }\r\n\r\n .radio--lg .radio__circle {\r\n width: var(--bp-spacing-6);\r\n height: var(--bp-spacing-6);\r\n }\r\n\r\n .radio--lg .radio__label {\r\n font-size: var(--bp-font-size-lg);\r\n }\r\n\r\n /* States - Checked */\r\n .radio__input:checked ~ .radio__circle {\r\n background-color: var(--bp-color-primary);\r\n border-color: var(--bp-color-primary);\r\n }\r\n\r\n .radio__input:checked ~ .radio__circle .radio__circle-inner {\r\n opacity: 1;\r\n transform: scale(1);\r\n }\r\n\r\n /* States - Focus */\r\n .radio--focused .radio__circle {\r\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\r\n outline-offset: var(--bp-focus-offset);\r\n z-index: 1;\r\n }\r\n\r\n /* States - Hover */\r\n .radio:hover:not(.radio--disabled) .radio__circle {\r\n border-color: var(--bp-color-primary);\r\n background-color: color-mix(\r\n in srgb,\r\n var(--bp-color-primary) 8%,\r\n transparent\r\n );\r\n }\r\n\r\n .radio:hover:not(.radio--disabled) .radio__input:checked ~ .radio__circle {\r\n background-color: var(--bp-color-primary-hover);\r\n border-color: var(--bp-color-primary-hover);\r\n }\r\n\r\n /* States - Active */\r\n .radio:active:not(.radio--disabled) .radio__circle {\r\n transform: scale(0.95);\r\n }\r\n\r\n /* States - Error */\r\n .radio--error .radio__circle {\r\n border-color: var(--bp-color-error);\r\n }\r\n\r\n .radio--error.radio--focused .radio__circle {\r\n outline-color: var(--bp-color-error);\r\n }\r\n\r\n .radio--error .radio__input:checked ~ .radio__circle {\r\n background-color: var(--bp-color-error);\r\n border-color: var(--bp-color-error);\r\n }\r\n\r\n /* States - Disabled */\r\n .radio--disabled {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n }\r\n\r\n /* Touch target size: ensure 44x44px minimum on touch devices */\r\n @media (pointer: coarse) {\r\n .radio {\r\n min-height: 44px;\r\n padding: var(--bp-spacing-xs) 0;\r\n }\r\n\r\n .radio__circle {\r\n position: relative;\r\n }\r\n\r\n /* Expand touch target with pseudo-element */\r\n .radio__circle::before {\r\n content: '';\r\n position: absolute;\r\n top: 50%;\r\n left: 50%;\r\n transform: translate(-50%, -50%);\r\n width: 44px;\r\n height: 44px;\r\n }\r\n }\r\n`;\r\n","import { LitElement, html } from 'lit';\r\nimport { customElement, property, query, state } from 'lit/decorators.js';\r\nimport { ifDefined } from 'lit/directives/if-defined.js';\r\nimport { live } from 'lit/directives/live.js';\r\nimport { radioStyles } from './radio.style.js';\r\n\r\nexport type RadioSize = 'sm' | 'md' | 'lg';\r\n\r\n/**\r\n * A form radio input with label support and group functionality.\r\n *\r\n * @element bp-radio\r\n *\r\n * @property {boolean} checked - Whether the radio is checked\r\n * @property {boolean} disabled - Whether the radio is disabled\r\n * @property {boolean} required - Whether the radio is required\r\n * @property {string} name - The name of the radio for form submission and grouping\r\n * @property {string} value - The value of the radio for form submission\r\n * @property {RadioSize} size - The size of the radio\r\n * @property {boolean} error - Whether the radio has an error state\r\n *\r\n * @slot - The radio label text\r\n *\r\n * @fires bp-change - Fired when the checked state changes\r\n * @fires bp-focus - Fired when the radio receives focus\r\n * @fires bp-blur - Fired when the radio loses focus\r\n *\r\n * @csspart radio - The radio container\r\n * @csspart input - The native radio input element\r\n * @csspart circle - The visual circle indicator\r\n * @csspart label - The label text container\r\n */\r\n@customElement('bp-radio')\r\nexport class BpRadio extends LitElement {\r\n @query('input[type=\"radio\"]') declare input: HTMLInputElement;\r\n\r\n /**\r\n * Whether the radio is checked.\r\n */\r\n @property({ type: Boolean, reflect: true }) declare checked: boolean;\r\n\r\n /**\r\n * Whether the radio is disabled.\r\n */\r\n @property({ type: Boolean, reflect: true }) declare disabled: boolean;\r\n\r\n /**\r\n * Whether the radio is required.\r\n */\r\n @property({ type: Boolean, reflect: true }) declare required: boolean;\r\n\r\n /**\r\n * The name of the radio for form submission and grouping.\r\n * Radios with the same name form a group where only one can be selected.\r\n */\r\n @property({ type: String, reflect: true }) declare name: string;\r\n\r\n /**\r\n * The value of the radio for form submission.\r\n */\r\n @property({ type: String }) declare value: string;\r\n\r\n /**\r\n * The size of the radio.\r\n */\r\n @property({ type: String, reflect: true }) declare size: RadioSize;\r\n\r\n /**\r\n * Whether the radio has an error state.\r\n */\r\n @property({ type: Boolean, reflect: true }) declare error: boolean;\r\n\r\n @state() private hasFocus = false;\r\n\r\n static styles = [radioStyles];\r\n\r\n static formAssociated = true;\r\n private internals: globalThis.ElementInternals | null = null;\r\n\r\n constructor() {\r\n super();\r\n this.checked = false;\r\n this.disabled = false;\r\n this.required = false;\r\n this.name = '';\r\n this.value = '';\r\n this.size = 'md';\r\n this.error = false;\r\n\r\n if ('attachInternals' in this) {\r\n this.internals = (this as HTMLElement).attachInternals();\r\n }\r\n }\r\n\r\n connectedCallback(): void {\r\n super.connectedCallback();\r\n this.setAttribute('role', 'radio');\r\n this.updateAriaAttributes();\r\n }\r\n\r\n updated(changedProperties: Map<string, unknown>): void {\r\n super.updated(changedProperties);\r\n\r\n if (\r\n changedProperties.has('checked') ||\r\n changedProperties.has('disabled') ||\r\n changedProperties.has('required') ||\r\n changedProperties.has('error')\r\n ) {\r\n this.updateAriaAttributes();\r\n this.updateFormValue();\r\n }\r\n }\r\n\r\n private updateAriaAttributes(): void {\r\n this.setAttribute('aria-checked', this.checked.toString());\r\n this.setAttribute('aria-disabled', this.disabled.toString());\r\n\r\n if (this.required) {\r\n this.setAttribute('aria-required', 'true');\r\n } else {\r\n this.removeAttribute('aria-required');\r\n }\r\n\r\n if (this.error) {\r\n this.setAttribute('aria-invalid', 'true');\r\n } else {\r\n this.removeAttribute('aria-invalid');\r\n }\r\n }\r\n\r\n private updateFormValue(): void {\r\n if (!this.internals) return;\r\n\r\n if (this.checked) {\r\n this.internals.setFormValue(this.value || 'on');\r\n } else {\r\n this.internals.setFormValue(null);\r\n }\r\n }\r\n\r\n private handleChange(event: Event): void {\r\n const inputElement = event.target as HTMLInputElement;\r\n this.checked = inputElement.checked;\r\n\r\n // Uncheck other radios in the same group\r\n if (this.checked && this.name) {\r\n this.uncheckOtherRadios();\r\n }\r\n\r\n this.dispatchEvent(\r\n new CustomEvent('bp-change', {\r\n detail: { checked: this.checked, value: this.value },\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n }\r\n\r\n private handleFocus(): void {\r\n this.hasFocus = true;\r\n this.dispatchEvent(\r\n new CustomEvent('bp-focus', {\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n }\r\n\r\n private handleBlur(): void {\r\n this.hasFocus = false;\r\n this.dispatchEvent(\r\n new CustomEvent('bp-blur', {\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n }\r\n\r\n private handleClick(): void {\r\n if (!this.disabled) {\r\n this.input?.focus();\r\n }\r\n }\r\n\r\n private uncheckOtherRadios(): void {\r\n if (!this.name) return;\r\n\r\n // Find all radios with the same name in the document\r\n const root = this.getRootNode() as\r\n | globalThis.Document\r\n | globalThis.ShadowRoot;\r\n const radios = Array.from(\r\n root.querySelectorAll(`bp-radio[name=\"${this.name}\"]`)\r\n ) as BpRadio[];\r\n\r\n radios.forEach((radio) => {\r\n if (radio !== this && radio.checked && !radio.disabled) {\r\n radio.checked = false;\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Sets focus on the radio.\r\n */\r\n focus(options?: globalThis.FocusOptions): void {\r\n this.input?.focus(options);\r\n }\r\n\r\n /**\r\n * Removes focus from the radio.\r\n */\r\n blur(): void {\r\n this.input?.blur();\r\n }\r\n\r\n /**\r\n * Checks if the radio satisfies its required constraint.\r\n */\r\n checkValidity(): boolean {\r\n return this.input?.checkValidity() ?? true;\r\n }\r\n\r\n /**\r\n * Checks validity and shows validation message if invalid.\r\n */\r\n reportValidity(): boolean {\r\n return this.input?.reportValidity() ?? true;\r\n }\r\n\r\n render() {\r\n const classes = [\r\n 'radio',\r\n `radio--${this.size}`,\r\n this.disabled ? 'radio--disabled' : '',\r\n this.error ? 'radio--error' : '',\r\n this.hasFocus ? 'radio--focused' : '',\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n\r\n return html`\r\n <label class=${classes} part=\"radio\" @click=${this.handleClick}>\r\n <input\r\n class=\"radio__input\"\r\n part=\"input\"\r\n type=\"radio\"\r\n name=${ifDefined(this.name || undefined)}\r\n value=${ifDefined(this.value || undefined)}\r\n .checked=${live(this.checked)}\r\n ?disabled=${this.disabled}\r\n ?required=${this.required}\r\n @change=${this.handleChange}\r\n @focus=${this.handleFocus}\r\n @blur=${this.handleBlur}\r\n aria-hidden=\"true\"\r\n tabindex=\"-1\"\r\n />\r\n <span class=\"radio__circle\" part=\"circle\">\r\n <span class=\"radio__circle-inner\"></span>\r\n </span>\r\n <span class=\"radio__label\" part=\"label\">\r\n <slot></slot>\r\n </span>\r\n </label>\r\n `;\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'bp-radio': BpRadio;\r\n }\r\n}\r\n"],"names":["radioStyles","css","BpRadio","LitElement","changedProperties","event","inputElement","root","radio","options","classes","html","ifDefined","live","__decorateClass","query","property","state","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"radio.js","sources":["../../source/components/radio/radio.style.ts","../../source/components/radio/radio.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const radioStyles = css`\n /* Base styles */\n :host {\n display: inline-block;\n }\n\n .radio {\n display: inline-flex;\n align-items: center;\n gap: var(--bp-spacing-sm);\n cursor: pointer;\n font-family: var(--bp-font-family);\n font-size: var(--bp-font-size-base);\n color: var(--bp-color-text);\n user-select: none;\n }\n\n .radio__input {\n position: absolute;\n opacity: 0;\n width: 0;\n height: 0;\n margin: 0;\n padding: 0;\n }\n\n .radio__circle {\n position: relative;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n border: var(--bp-border-width) solid var(--bp-color-border-strong);\n border-radius: 50%;\n background-color: var(--bp-color-surface);\n transition: all var(--bp-transition-fast);\n }\n\n .radio__circle-inner {\n width: 50%;\n height: 50%;\n border-radius: 50%;\n background-color: var(--bp-color-text-inverse);\n opacity: 0;\n transform: scale(0);\n transition:\n opacity var(--bp-duration-fast) var(--bp-ease-out),\n transform var(--bp-duration-fast) var(--bp-ease-bounce);\n }\n\n .radio__label {\n line-height: var(--bp-line-height-normal);\n }\n\n /* Sizes */\n .radio--sm .radio__circle {\n width: var(--bp-spacing-4);\n height: var(--bp-spacing-4);\n }\n\n .radio--sm .radio__label {\n font-size: var(--bp-font-size-sm);\n }\n\n .radio--md .radio__circle {\n width: var(--bp-spacing-5);\n height: var(--bp-spacing-5);\n }\n\n .radio--md .radio__label {\n font-size: var(--bp-font-size-base);\n }\n\n .radio--lg .radio__circle {\n width: var(--bp-spacing-6);\n height: var(--bp-spacing-6);\n }\n\n .radio--lg .radio__label {\n font-size: var(--bp-font-size-lg);\n }\n\n /* States - Checked */\n .radio__input:checked ~ .radio__circle {\n background-color: var(--bp-color-primary);\n border-color: var(--bp-color-primary);\n }\n\n .radio__input:checked ~ .radio__circle .radio__circle-inner {\n opacity: 1;\n transform: scale(1);\n }\n\n /* States - Focus */\n .radio--focused .radio__circle {\n outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);\n outline-offset: var(--bp-focus-offset);\n z-index: 1;\n }\n\n /* States - Hover */\n .radio:hover:not(.radio--disabled) .radio__circle {\n border-color: var(--bp-color-primary);\n background-color: color-mix(\n in srgb,\n var(--bp-color-primary) 8%,\n transparent\n );\n }\n\n .radio:hover:not(.radio--disabled) .radio__input:checked ~ .radio__circle {\n background-color: var(--bp-color-primary-hover);\n border-color: var(--bp-color-primary-hover);\n }\n\n /* States - Active */\n .radio:active:not(.radio--disabled) .radio__circle {\n transform: scale(0.95);\n }\n\n /* States - Error */\n .radio--error .radio__circle {\n border-color: var(--bp-color-error);\n }\n\n .radio--error.radio--focused .radio__circle {\n outline-color: var(--bp-color-error);\n }\n\n .radio--error .radio__input:checked ~ .radio__circle {\n background-color: var(--bp-color-error);\n border-color: var(--bp-color-error);\n }\n\n /* States - Disabled */\n .radio--disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n /* Touch target size: ensure 44x44px minimum on touch devices */\n @media (pointer: coarse) {\n .radio {\n min-height: 44px;\n padding: var(--bp-spacing-xs) 0;\n }\n\n .radio__circle {\n position: relative;\n }\n\n /* Expand touch target with pseudo-element */\n .radio__circle::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 44px;\n height: 44px;\n }\n }\n`;\n","import { LitElement, html } from 'lit';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { live } from 'lit/directives/live.js';\nimport { radioStyles } from './radio.style.js';\n\nexport type RadioSize = 'sm' | 'md' | 'lg';\n\n/**\n * A form radio input with label support and group functionality.\n *\n * @element bp-radio\n *\n * @property {boolean} checked - Whether the radio is checked\n * @property {boolean} disabled - Whether the radio is disabled\n * @property {boolean} required - Whether the radio is required\n * @property {string} name - The name of the radio for form submission and grouping\n * @property {string} value - The value of the radio for form submission\n * @property {RadioSize} size - The size of the radio\n * @property {boolean} error - Whether the radio has an error state\n *\n * @slot - The radio label text\n *\n * @fires bp-change - Fired when the checked state changes\n * @fires bp-focus - Fired when the radio receives focus\n * @fires bp-blur - Fired when the radio loses focus\n *\n * @csspart radio - The radio container\n * @csspart input - The native radio input element\n * @csspart circle - The visual circle indicator\n * @csspart label - The label text container\n */\n@customElement('bp-radio')\nexport class BpRadio extends LitElement {\n @query('input[type=\"radio\"]') declare input: HTMLInputElement;\n\n /**\n * Whether the radio is checked.\n */\n @property({ type: Boolean, reflect: true }) declare checked: boolean;\n\n /**\n * Whether the radio is disabled.\n */\n @property({ type: Boolean, reflect: true }) declare disabled: boolean;\n\n /**\n * Whether the radio is required.\n */\n @property({ type: Boolean, reflect: true }) declare required: boolean;\n\n /**\n * The name of the radio for form submission and grouping.\n * Radios with the same name form a group where only one can be selected.\n */\n @property({ type: String, reflect: true }) declare name: string;\n\n /**\n * The value of the radio for form submission.\n */\n @property({ type: String }) declare value: string;\n\n /**\n * The size of the radio.\n */\n @property({ type: String, reflect: true }) declare size: RadioSize;\n\n /**\n * Whether the radio has an error state.\n */\n @property({ type: Boolean, reflect: true }) declare error: boolean;\n\n @state() private hasFocus = false;\n\n static styles = [radioStyles];\n\n static formAssociated = true;\n private internals: globalThis.ElementInternals | null = null;\n\n constructor() {\n super();\n this.checked = false;\n this.disabled = false;\n this.required = false;\n this.name = '';\n this.value = '';\n this.size = 'md';\n this.error = false;\n\n if ('attachInternals' in this) {\n this.internals = (this as HTMLElement).attachInternals();\n }\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n this.setAttribute('role', 'radio');\n this.updateAriaAttributes();\n }\n\n updated(changedProperties: Map<string, unknown>): void {\n super.updated(changedProperties);\n\n if (\n changedProperties.has('checked') ||\n changedProperties.has('disabled') ||\n changedProperties.has('required') ||\n changedProperties.has('error')\n ) {\n this.updateAriaAttributes();\n this.updateFormValue();\n }\n }\n\n private updateAriaAttributes(): void {\n this.setAttribute('aria-checked', this.checked.toString());\n this.setAttribute('aria-disabled', this.disabled.toString());\n\n if (this.required) {\n this.setAttribute('aria-required', 'true');\n } else {\n this.removeAttribute('aria-required');\n }\n\n if (this.error) {\n this.setAttribute('aria-invalid', 'true');\n } else {\n this.removeAttribute('aria-invalid');\n }\n }\n\n private updateFormValue(): void {\n if (!this.internals) return;\n\n if (this.checked) {\n this.internals.setFormValue(this.value || 'on');\n } else {\n this.internals.setFormValue(null);\n }\n }\n\n private handleChange(event: Event): void {\n const inputElement = event.target as HTMLInputElement;\n this.checked = inputElement.checked;\n\n // Uncheck other radios in the same group\n if (this.checked && this.name) {\n this.uncheckOtherRadios();\n }\n\n this.dispatchEvent(\n new CustomEvent('bp-change', {\n detail: { checked: this.checked, value: this.value },\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private handleFocus(): void {\n this.hasFocus = true;\n this.dispatchEvent(\n new CustomEvent('bp-focus', {\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private handleBlur(): void {\n this.hasFocus = false;\n this.dispatchEvent(\n new CustomEvent('bp-blur', {\n bubbles: true,\n composed: true,\n })\n );\n }\n\n private handleClick(): void {\n if (!this.disabled) {\n this.input?.focus();\n }\n }\n\n private uncheckOtherRadios(): void {\n if (!this.name) return;\n\n // Find all radios with the same name in the document\n const root = this.getRootNode() as\n | globalThis.Document\n | globalThis.ShadowRoot;\n const radios = Array.from(\n root.querySelectorAll(`bp-radio[name=\"${this.name}\"]`)\n ) as BpRadio[];\n\n radios.forEach((radio) => {\n if (radio !== this && radio.checked && !radio.disabled) {\n radio.checked = false;\n }\n });\n }\n\n /**\n * Sets focus on the radio.\n */\n focus(options?: globalThis.FocusOptions): void {\n this.input?.focus(options);\n }\n\n /**\n * Removes focus from the radio.\n */\n blur(): void {\n this.input?.blur();\n }\n\n /**\n * Checks if the radio satisfies its required constraint.\n */\n checkValidity(): boolean {\n return this.input?.checkValidity() ?? true;\n }\n\n /**\n * Checks validity and shows validation message if invalid.\n */\n reportValidity(): boolean {\n return this.input?.reportValidity() ?? true;\n }\n\n render() {\n const classes = [\n 'radio',\n `radio--${this.size}`,\n this.disabled ? 'radio--disabled' : '',\n this.error ? 'radio--error' : '',\n this.hasFocus ? 'radio--focused' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return html`\n <label class=${classes} part=\"radio\" @click=${this.handleClick}>\n <input\n class=\"radio__input\"\n part=\"input\"\n type=\"radio\"\n name=${ifDefined(this.name || undefined)}\n value=${ifDefined(this.value || undefined)}\n .checked=${live(this.checked)}\n ?disabled=${this.disabled}\n ?required=${this.required}\n @change=${this.handleChange}\n @focus=${this.handleFocus}\n @blur=${this.handleBlur}\n aria-hidden=\"true\"\n tabindex=\"-1\"\n />\n <span class=\"radio__circle\" part=\"circle\">\n <span class=\"radio__circle-inner\"></span>\n </span>\n <span class=\"radio__label\" part=\"label\">\n <slot></slot>\n </span>\n </label>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'bp-radio': BpRadio;\n }\n}\n"],"names":["radioStyles","css","BpRadio","LitElement","changedProperties","event","inputElement","root","radio","options","classes","html","ifDefined","live","__decorateClass","query","property","state","customElement"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"select.js","sources":["../../source/components/select/select.style.ts","../../source/components/select/select.ts"],"sourcesContent":["import { css } from 'lit';\r\n\r\nexport const selectStyles = css`\r\n /* Base styles */\r\n :host {\r\n display: inline-block;\r\n width: 100%;\r\n box-sizing: border-box;\r\n }\r\n\r\n *,\r\n *::before,\r\n *::after {\r\n box-sizing: border-box;\r\n }\r\n\r\n .select {\r\n position: relative;\r\n font-family: var(--bp-font-family);\r\n }\r\n\r\n .select-label {\r\n display: block;\r\n font-family: var(--bp-font-family);\r\n font-size: var(--bp-font-size-sm);\r\n font-weight: var(--bp-font-weight-medium);\r\n color: var(--bp-color-text);\r\n line-height: var(--bp-line-height-normal);\r\n margin-bottom: var(--bp-spacing-xs);\r\n }\r\n\r\n .select-required {\r\n color: var(--bp-color-error);\r\n margin-left: var(--bp-spacing-xs);\r\n }\r\n\r\n .select-trigger {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n width: 100%;\r\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\r\n background-color: var(--bp-color-background);\r\n border: var(--bp-border-width) solid var(--bp-color-border);\r\n border-radius: var(--bp-border-radius-md);\r\n font-size: var(--bp-font-size-base);\r\n line-height: var(--bp-line-height-normal);\r\n color: var(--bp-color-text);\r\n cursor: pointer;\r\n box-shadow: inset 0 1px 2px oklch(0 0 0 / 0.05);\r\n transition:\r\n border-color var(--bp-transition-fast),\r\n box-shadow var(--bp-transition-fast);\r\n }\r\n\r\n .select-value {\r\n flex: 1;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n position: relative;\r\n }\r\n\r\n /* Hidden sizer keeps the trigger width stable across placeholder/option changes */\r\n .select-value__sizer {\r\n display: block;\r\n height: 0;\r\n overflow: hidden;\r\n visibility: hidden;\r\n white-space: nowrap;\r\n }\r\n\r\n .select-value__display {\r\n display: block;\r\n overflow: hidden;\r\n text-overflow: ellipsis;\r\n white-space: nowrap;\r\n }\r\n\r\n /* Placeholder state - when no value is selected */\r\n .select-trigger:not([aria-label]) .select-value:empty {\r\n opacity: 0.6;\r\n }\r\n\r\n .select-icon {\r\n width: var(--bp-spacing-4);\r\n height: var(--bp-spacing-4);\r\n flex-shrink: 0;\r\n margin-left: var(--bp-spacing-xs);\r\n transition:\r\n transform var(--bp-transition-base),\r\n color var(--bp-transition-fast);\r\n }\r\n\r\n .select-dropdown {\r\n position: absolute;\r\n top: calc(100% + var(--bp-spacing-2xs));\r\n left: 0;\r\n right: 0;\r\n overflow-y: auto;\r\n background-color: var(--bp-color-background);\r\n border: var(--bp-border-width) solid var(--bp-color-border);\r\n border-radius: var(--bp-border-radius-md);\r\n box-shadow: var(--bp-shadow-lg);\r\n z-index: var(--bp-z-dropdown);\r\n animation: slideDown 150ms ease-out;\r\n transform-origin: top;\r\n contain: layout style paint;\r\n }\r\n\r\n @keyframes slideDown {\r\n from {\r\n opacity: 0;\r\n transform: translateY(calc(-1 * var(--bp-spacing-2)));\r\n }\r\n to {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n }\r\n\r\n .select-option {\r\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\r\n cursor: pointer;\r\n transition: background-color var(--bp-transition-fast);\r\n }\r\n\r\n .select-option:hover:not(.select-option--focused) {\r\n background-color: var(--bp-color-surface-elevated);\r\n }\r\n\r\n .select-option--focused {\r\n background-color: var(--bp-color-surface-subdued);\r\n outline: var(--bp-focus-width) solid var(--bp-color-primary);\r\n outline-offset: calc(-1 * var(--bp-focus-width));\r\n }\r\n\r\n .select-option--selected {\r\n background-color: color-mix(\r\n in srgb,\r\n var(--bp-color-primary) 8%,\r\n transparent\r\n );\r\n color: var(--bp-color-primary);\r\n font-weight: var(--bp-font-weight-semibold);\r\n position: relative;\r\n padding-right: var(--bp-spacing-2xl);\r\n }\r\n\r\n /* Checkmark for selected option */\r\n .select-option--selected::after {\r\n content: '✓';\r\n position: absolute;\r\n right: var(--bp-spacing-md);\r\n color: var(--bp-color-primary);\r\n font-weight: var(--bp-font-weight-bold);\r\n font-size: var(--bp-font-size-lg);\r\n }\r\n\r\n /* Sizes */\r\n .select--sm .select-trigger {\r\n padding: var(--bp-spacing-xs) var(--bp-spacing-sm);\r\n font-size: var(--bp-font-size-sm);\r\n }\r\n\r\n .select--sm .select-option {\r\n padding: var(--bp-spacing-xs) var(--bp-spacing-sm);\r\n font-size: var(--bp-font-size-sm);\r\n }\r\n\r\n .select--md .select-trigger {\r\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\r\n font-size: var(--bp-font-size-base);\r\n }\r\n\r\n .select--md .select-option {\r\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\r\n font-size: var(--bp-font-size-base);\r\n }\r\n\r\n .select--lg .select-trigger {\r\n padding: var(--bp-spacing-md) var(--bp-spacing-lg);\r\n font-size: var(--bp-font-size-lg);\r\n }\r\n\r\n .select--lg .select-option {\r\n padding: var(--bp-spacing-md) var(--bp-spacing-lg);\r\n font-size: var(--bp-font-size-lg);\r\n }\r\n\r\n /* States */\r\n .select-trigger:hover:not(.select--disabled .select-trigger) {\r\n border-color: var(--bp-color-primary);\r\n }\r\n\r\n .select-trigger:focus {\r\n outline: none;\r\n }\r\n\r\n .select-trigger:focus-visible {\r\n outline: var(--bp-focus-width) solid var(--bp-color-primary);\r\n outline-offset: var(--bp-focus-offset);\r\n border-color: var(--bp-color-primary);\r\n }\r\n\r\n .select--open .select-trigger {\r\n border-color: var(--bp-color-primary);\r\n }\r\n\r\n .select--open .select-icon {\r\n transform: rotate(180deg);\r\n color: var(--bp-color-primary);\r\n }\r\n\r\n .select--disabled .select-trigger {\r\n opacity: 0.5;\r\n cursor: not-allowed;\r\n background-color: var(--bp-color-surface-subdued);\r\n }\r\n\r\n /* iOS zoom prevention: ensure 16px minimum on touch devices */\r\n @media (max-width: 768px) {\r\n .select--sm .select-trigger {\r\n font-size: 16px;\r\n }\r\n\r\n .select--sm .select-option {\r\n font-size: 16px;\r\n }\r\n }\r\n`;\r\n","import { LitElement, html } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\nimport { classMap } from 'lit/directives/class-map.js';\r\nimport { ifDefined } from 'lit/directives/if-defined.js';\r\nimport { repeat } from 'lit/directives/repeat.js';\r\nimport { selectStyles } from './select.style.js';\r\n\r\nexport type SelectSize = 'sm' | 'md' | 'lg';\r\n\r\n@customElement('bp-select')\r\nexport class BpSelect extends LitElement {\r\n /** The current value of the select */\r\n @property({ type: String, reflect: true }) declare value: string;\r\n\r\n /** Name attribute for form submission */\r\n @property({ type: String }) declare name: string;\r\n\r\n /** Visible label text displayed above the select */\r\n @property({ type: String, reflect: true }) declare label: string;\r\n\r\n /** Placeholder text when no value is selected */\r\n @property({ type: String }) declare placeholder: string;\r\n\r\n /** Whether the select is disabled */\r\n @property({ type: Boolean, reflect: true }) declare disabled: boolean;\r\n\r\n /** Whether the select is required */\r\n @property({ type: Boolean, reflect: true }) declare required: boolean;\r\n\r\n /** Size variant of the select */\r\n @property({ type: String, reflect: true }) declare size: SelectSize;\r\n\r\n /** Whether the dropdown is currently open */\r\n @state() private isOpen = false;\r\n\r\n /** Label for the selected option */\r\n @state() private selectedLabel = '';\r\n\r\n /** Index of the focused option for keyboard navigation */\r\n @state() private focusedIndex = -1;\r\n\r\n static styles = [selectStyles];\r\n\r\n constructor() {\r\n super();\r\n this.value = '';\r\n this.name = '';\r\n this.label = '';\r\n this.placeholder = 'Select an option';\r\n this.disabled = false;\r\n this.required = false;\r\n this.size = 'md';\r\n }\r\n\r\n connectedCallback() {\r\n super.connectedCallback();\r\n document.addEventListener('click', this.handleDocumentClick, {\r\n passive: true,\r\n });\r\n // Update selected label on initial load\r\n this.updateComplete.then(() => this.updateSelectedLabel());\r\n }\r\n\r\n disconnectedCallback() {\r\n super.disconnectedCallback();\r\n document.removeEventListener('click', this.handleDocumentClick, {\r\n passive: true,\r\n } as EventListenerOptions);\r\n }\r\n\r\n private handleSlotChange = () => {\r\n this.updateSelectedLabel();\r\n };\r\n\r\n private updateSelectedLabel() {\r\n if (!this.value) return;\r\n\r\n const slot = this.shadowRoot?.querySelector('slot');\r\n const assignedElements = slot?.assignedElements() || [];\r\n const options = assignedElements.filter(\r\n (el): el is globalThis.HTMLOptionElement => el.tagName === 'OPTION'\r\n );\r\n\r\n options.forEach((option) => {\r\n if ((option.value || option.textContent) === this.value) {\r\n this.selectedLabel = option.textContent || '';\r\n }\r\n });\r\n }\r\n\r\n private handleDocumentClick = (event: MouseEvent) => {\r\n if (!this.contains(event.target as unknown as globalThis.Node)) {\r\n this.isOpen = false;\r\n }\r\n };\r\n\r\n private handleToggle = (event?: Event) => {\r\n event?.stopPropagation();\r\n if (this.disabled) return;\r\n this.isOpen = !this.isOpen;\r\n };\r\n\r\n private handleOptionClick = (event: Event) => {\r\n if (this.disabled) return;\r\n\r\n const target = event.currentTarget as HTMLElement;\r\n const optionValue = target.dataset.value || '';\r\n const optionLabel = target.dataset.label || '';\r\n\r\n const previousValue = this.value;\r\n this.value = optionValue;\r\n this.selectedLabel = optionLabel;\r\n this.isOpen = false;\r\n this.focusedIndex = -1;\r\n\r\n // Dispatch change event\r\n this.dispatchEvent(\r\n new CustomEvent('bp-change', {\r\n detail: {\r\n value: this.value,\r\n label: this.selectedLabel,\r\n previousValue,\r\n },\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n\r\n // Update the underlying hidden input for form integration\r\n const hiddenInput = this.shadowRoot?.querySelector('input[type=\"hidden\"]');\r\n if (hiddenInput) {\r\n (hiddenInput as HTMLInputElement).value = this.value;\r\n hiddenInput.dispatchEvent(new Event('change', { bubbles: true }));\r\n }\r\n };\r\n\r\n private handleKeyDown = (event: globalThis.KeyboardEvent) => {\r\n if (this.disabled) return;\r\n\r\n const options = this.getOptions();\r\n\r\n switch (event.key) {\r\n case 'Enter':\r\n case ' ':\r\n event.preventDefault();\r\n if (this.isOpen && this.focusedIndex >= 0) {\r\n // Select the focused option\r\n const option = options[this.focusedIndex];\r\n if (option) {\r\n const optionValue = option.value || option.textContent || '';\r\n const optionLabel = option.textContent || '';\r\n const previousValue = this.value;\r\n this.value = optionValue;\r\n this.selectedLabel = optionLabel;\r\n this.isOpen = false;\r\n this.focusedIndex = -1;\r\n\r\n this.dispatchEvent(\r\n new CustomEvent('bp-change', {\r\n detail: {\r\n value: this.value,\r\n label: this.selectedLabel,\r\n previousValue,\r\n },\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n\r\n const hiddenInput = this.shadowRoot?.querySelector(\r\n 'input[type=\"hidden\"]'\r\n );\r\n if (hiddenInput) {\r\n (hiddenInput as HTMLInputElement).value = this.value;\r\n hiddenInput.dispatchEvent(new Event('change', { bubbles: true }));\r\n }\r\n }\r\n } else {\r\n this.handleToggle();\r\n }\r\n break;\r\n case 'Escape':\r\n this.isOpen = false;\r\n this.focusedIndex = -1;\r\n break;\r\n case 'ArrowDown':\r\n event.preventDefault();\r\n if (!this.isOpen) {\r\n this.isOpen = true;\r\n this.focusedIndex = 0;\r\n } else {\r\n this.focusedIndex = Math.min(\r\n this.focusedIndex + 1,\r\n options.length - 1\r\n );\r\n }\r\n this.scrollFocusedOptionIntoView();\r\n break;\r\n case 'ArrowUp':\r\n event.preventDefault();\r\n if (!this.isOpen) {\r\n this.isOpen = true;\r\n this.focusedIndex = options.length - 1;\r\n } else {\r\n this.focusedIndex = Math.max(this.focusedIndex - 1, 0);\r\n }\r\n this.scrollFocusedOptionIntoView();\r\n break;\r\n case 'Home':\r\n if (this.isOpen) {\r\n event.preventDefault();\r\n this.focusedIndex = 0;\r\n this.scrollFocusedOptionIntoView();\r\n }\r\n break;\r\n case 'End':\r\n if (this.isOpen) {\r\n event.preventDefault();\r\n this.focusedIndex = options.length - 1;\r\n this.scrollFocusedOptionIntoView();\r\n }\r\n break;\r\n }\r\n };\r\n\r\n private getOptions(): Array<{ value: string; textContent: string }> {\r\n const slot = this.shadowRoot?.querySelector('slot');\r\n const assignedElements = slot?.assignedElements() || [];\r\n const options = assignedElements.filter(\r\n (el): el is globalThis.HTMLOptionElement => el.tagName === 'OPTION'\r\n );\r\n return options.map((option) => ({\r\n value: option.value || option.textContent || '',\r\n textContent: option.textContent || '',\r\n }));\r\n }\r\n\r\n private scrollFocusedOptionIntoView() {\r\n this.updateComplete.then(() => {\r\n const focusedOption = this.shadowRoot?.querySelector(\r\n '.select-option--focused'\r\n ) as HTMLElement;\r\n if (focusedOption) {\r\n focusedOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Returns the longest text among all options and the placeholder.\r\n * Used by a hidden sizer element to keep the trigger width stable.\r\n */\r\n private getSizerText(): string {\r\n const options = this.getOptions();\r\n let longestText = this.placeholder || '';\r\n\r\n for (const option of options) {\r\n const text = option.textContent || '';\r\n if (text.length > longestText.length) {\r\n longestText = text;\r\n }\r\n }\r\n\r\n return longestText;\r\n }\r\n\r\n private getOptionElements = () => {\r\n const slot = this.shadowRoot?.querySelector('slot');\r\n const assignedElements = slot?.assignedElements() || [];\r\n const options = assignedElements.filter(\r\n (el): el is globalThis.HTMLOptionElement => el.tagName === 'OPTION'\r\n );\r\n\r\n return repeat(\r\n options,\r\n (option) => option.value || option.textContent || '',\r\n (option, index) => {\r\n const optionValue = option.value || option.textContent || '';\r\n const optionLabel = option.textContent || '';\r\n const isSelected = this.value === optionValue;\r\n const isFocused = this.focusedIndex === index;\r\n\r\n if (isSelected && !this.selectedLabel) {\r\n this.selectedLabel = optionLabel;\r\n }\r\n\r\n return html`\r\n <div\r\n class=\"select-option ${isSelected\r\n ? 'select-option--selected'\r\n : ''} ${isFocused ? 'select-option--focused' : ''}\"\r\n part=\"option\"\r\n role=\"option\"\r\n aria-selected=\"${isSelected ? 'true' : 'false'}\"\r\n data-value=\"${optionValue}\"\r\n data-label=\"${optionLabel}\"\r\n tabindex=\"-1\"\r\n @click=${this.handleOptionClick}\r\n >\r\n ${optionLabel}\r\n </div>\r\n `;\r\n }\r\n );\r\n };\r\n\r\n render() {\r\n const selectClasses = {\r\n select: true,\r\n [`select--${this.size}`]: true,\r\n 'select--disabled': this.disabled,\r\n 'select--open': this.isOpen,\r\n };\r\n\r\n const displayLabel = this.selectedLabel || this.placeholder;\r\n\r\n const labelId = this.label ? 'select-label' : undefined;\r\n\r\n return html`\r\n <div class=${classMap(selectClasses)} part=\"container\">\r\n ${this.label\r\n ? html`\r\n <label class=\"select-label\" id=\"select-label\" part=\"label\">\r\n ${this.label}\r\n ${this.required\r\n ? html`<span class=\"select-required\">*</span>`\r\n : ''}\r\n </label>\r\n `\r\n : ''}\r\n <!-- Hidden input for form integration (using input instead of select to avoid Firefox conflict) -->\r\n <input\r\n type=\"hidden\"\r\n name=${ifDefined(this.name || undefined)}\r\n .value=${this.value}\r\n />\r\n\r\n <!-- Slot for option elements (not rendered, just for content projection) -->\r\n <slot\r\n @slotchange=${this.handleSlotChange}\r\n style=\"display: none;\"\r\n ></slot>\r\n\r\n <!-- Custom select trigger -->\r\n <div\r\n class=\"select-trigger\"\r\n part=\"trigger\"\r\n role=\"combobox\"\r\n aria-expanded=\"${this.isOpen ? 'true' : 'false'}\"\r\n aria-haspopup=\"listbox\"\r\n aria-labelledby=\"${ifDefined(labelId)}\"\r\n aria-disabled=\"${this.disabled ? 'true' : 'false'}\"\r\n aria-required=\"${this.required ? 'true' : 'false'}\"\r\n tabindex=\"${this.disabled ? '-1' : '0'}\"\r\n @click=${this.handleToggle}\r\n @keydown=${this.handleKeyDown}\r\n >\r\n <span class=\"select-value\" part=\"display\">\r\n <span class=\"select-value__sizer\" aria-hidden=\"true\"\r\n >${this.getSizerText()}</span\r\n >\r\n <span class=\"select-value__display\">${displayLabel}</span>\r\n </span>\r\n <svg\r\n class=\"select-icon\"\r\n part=\"icon\"\r\n viewBox=\"0 0 16 16\"\r\n fill=\"none\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n >\r\n <path\r\n d=\"M4 6L8 10L12 6\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n\r\n <!-- Dropdown menu -->\r\n ${this.isOpen\r\n ? html`\r\n <div class=\"select-dropdown\" part=\"dropdown\" role=\"listbox\">\r\n ${this.getOptionElements()}\r\n </div>\r\n `\r\n : null}\r\n </div>\r\n `;\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'bp-select': BpSelect;\r\n }\r\n}\r\n"],"names":["selectStyles","css","BpSelect","LitElement","event","target","optionValue","optionLabel","previousValue","hiddenInput","options","option","el","repeat","index","isSelected","isFocused","html","focusedOption","longestText","text","selectClasses","displayLabel","labelId","classMap","ifDefined","__decorateClass","property","state","customElement"],"mappings":";;;;;AAEO,MAAMA,IAAeC;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;;;;;;ACQrB,IAAMC,IAAN,cAAuBC,EAAW;AAAA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"}
1
+ {"version":3,"file":"select.js","sources":["../../source/components/select/select.style.ts","../../source/components/select/select.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const selectStyles = css`\n /* Base styles */\n :host {\n display: inline-block;\n width: 100%;\n box-sizing: border-box;\n }\n\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n }\n\n .select {\n position: relative;\n font-family: var(--bp-font-family);\n }\n\n .select-label {\n display: block;\n font-family: var(--bp-font-family);\n font-size: var(--bp-font-size-sm);\n font-weight: var(--bp-font-weight-medium);\n color: var(--bp-color-text);\n line-height: var(--bp-line-height-normal);\n margin-bottom: var(--bp-spacing-xs);\n }\n\n .select-required {\n color: var(--bp-color-error);\n margin-left: var(--bp-spacing-xs);\n }\n\n .select-trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n width: 100%;\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\n background-color: var(--bp-color-background);\n border: var(--bp-border-width) solid var(--bp-color-border);\n border-radius: var(--bp-border-radius-md);\n font-size: var(--bp-font-size-base);\n line-height: var(--bp-line-height-normal);\n color: var(--bp-color-text);\n cursor: pointer;\n box-shadow: inset 0 1px 2px oklch(0 0 0 / 0.05);\n transition:\n border-color var(--bp-transition-fast),\n box-shadow var(--bp-transition-fast);\n }\n\n .select-value {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n position: relative;\n }\n\n /* Hidden sizer keeps the trigger width stable across placeholder/option changes */\n .select-value__sizer {\n display: block;\n height: 0;\n overflow: hidden;\n visibility: hidden;\n white-space: nowrap;\n }\n\n .select-value__display {\n display: block;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* Placeholder state - when no value is selected */\n .select-trigger:not([aria-label]) .select-value:empty {\n opacity: 0.6;\n }\n\n .select-icon {\n width: var(--bp-spacing-4);\n height: var(--bp-spacing-4);\n flex-shrink: 0;\n margin-left: var(--bp-spacing-xs);\n transition:\n transform var(--bp-transition-base),\n color var(--bp-transition-fast);\n }\n\n .select-dropdown {\n position: absolute;\n top: calc(100% + var(--bp-spacing-2xs));\n left: 0;\n right: 0;\n overflow-y: auto;\n background-color: var(--bp-color-background);\n border: var(--bp-border-width) solid var(--bp-color-border);\n border-radius: var(--bp-border-radius-md);\n box-shadow: var(--bp-shadow-lg);\n z-index: var(--bp-z-dropdown);\n animation: slideDown 150ms ease-out;\n transform-origin: top;\n contain: layout style paint;\n }\n\n @keyframes slideDown {\n from {\n opacity: 0;\n transform: translateY(calc(-1 * var(--bp-spacing-2)));\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .select-option {\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\n cursor: pointer;\n transition: background-color var(--bp-transition-fast);\n }\n\n .select-option:hover:not(.select-option--focused) {\n background-color: var(--bp-color-surface-elevated);\n }\n\n .select-option--focused {\n background-color: var(--bp-color-surface-subdued);\n outline: var(--bp-focus-width) solid var(--bp-color-primary);\n outline-offset: calc(-1 * var(--bp-focus-width));\n }\n\n .select-option--selected {\n background-color: color-mix(\n in srgb,\n var(--bp-color-primary) 8%,\n transparent\n );\n color: var(--bp-color-primary);\n font-weight: var(--bp-font-weight-semibold);\n position: relative;\n padding-right: var(--bp-spacing-2xl);\n }\n\n /* Checkmark for selected option */\n .select-option--selected::after {\n content: '✓';\n position: absolute;\n right: var(--bp-spacing-md);\n color: var(--bp-color-primary);\n font-weight: var(--bp-font-weight-bold);\n font-size: var(--bp-font-size-lg);\n }\n\n /* Sizes */\n .select--sm .select-trigger {\n padding: var(--bp-spacing-xs) var(--bp-spacing-sm);\n font-size: var(--bp-font-size-sm);\n }\n\n .select--sm .select-option {\n padding: var(--bp-spacing-xs) var(--bp-spacing-sm);\n font-size: var(--bp-font-size-sm);\n }\n\n .select--md .select-trigger {\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\n font-size: var(--bp-font-size-base);\n }\n\n .select--md .select-option {\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\n font-size: var(--bp-font-size-base);\n }\n\n .select--lg .select-trigger {\n padding: var(--bp-spacing-md) var(--bp-spacing-lg);\n font-size: var(--bp-font-size-lg);\n }\n\n .select--lg .select-option {\n padding: var(--bp-spacing-md) var(--bp-spacing-lg);\n font-size: var(--bp-font-size-lg);\n }\n\n /* States */\n .select-trigger:hover:not(.select--disabled .select-trigger) {\n border-color: var(--bp-color-primary);\n }\n\n .select-trigger:focus {\n outline: none;\n }\n\n .select-trigger:focus-visible {\n outline: var(--bp-focus-width) solid var(--bp-color-primary);\n outline-offset: var(--bp-focus-offset);\n border-color: var(--bp-color-primary);\n }\n\n .select--open .select-trigger {\n border-color: var(--bp-color-primary);\n }\n\n .select--open .select-icon {\n transform: rotate(180deg);\n color: var(--bp-color-primary);\n }\n\n .select--disabled .select-trigger {\n opacity: 0.5;\n cursor: not-allowed;\n background-color: var(--bp-color-surface-subdued);\n }\n\n /* iOS zoom prevention: ensure 16px minimum on touch devices */\n @media (max-width: 768px) {\n .select--sm .select-trigger {\n font-size: 16px;\n }\n\n .select--sm .select-option {\n font-size: 16px;\n }\n }\n`;\n","import { LitElement, html } 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 { selectStyles } from './select.style.js';\n\nexport type SelectSize = 'sm' | 'md' | 'lg';\n\n@customElement('bp-select')\nexport class BpSelect extends LitElement {\n /** The current value of the select */\n @property({ type: String, reflect: true }) declare value: string;\n\n /** Name attribute for form submission */\n @property({ type: String }) declare name: string;\n\n /** Visible label text displayed above the select */\n @property({ type: String, reflect: true }) declare label: string;\n\n /** Placeholder text when no value is selected */\n @property({ type: String }) declare placeholder: string;\n\n /** Whether the select is disabled */\n @property({ type: Boolean, reflect: true }) declare disabled: boolean;\n\n /** Whether the select is required */\n @property({ type: Boolean, reflect: true }) declare required: boolean;\n\n /** Size variant of the select */\n @property({ type: String, reflect: true }) declare size: SelectSize;\n\n /** Whether the dropdown is currently open */\n @state() private isOpen = false;\n\n /** Label for the selected option */\n @state() private selectedLabel = '';\n\n /** Index of the focused option for keyboard navigation */\n @state() private focusedIndex = -1;\n\n static styles = [selectStyles];\n\n constructor() {\n super();\n this.value = '';\n this.name = '';\n this.label = '';\n this.placeholder = 'Select an option';\n this.disabled = false;\n this.required = false;\n this.size = 'md';\n }\n\n connectedCallback() {\n super.connectedCallback();\n document.addEventListener('click', this.handleDocumentClick, {\n passive: true,\n });\n // Update selected label on initial load\n this.updateComplete.then(() => this.updateSelectedLabel());\n }\n\n disconnectedCallback() {\n super.disconnectedCallback();\n document.removeEventListener('click', this.handleDocumentClick, {\n passive: true,\n } as EventListenerOptions);\n }\n\n private handleSlotChange = () => {\n this.updateSelectedLabel();\n };\n\n private updateSelectedLabel() {\n if (!this.value) return;\n\n const slot = this.shadowRoot?.querySelector('slot');\n const assignedElements = slot?.assignedElements() || [];\n const options = assignedElements.filter(\n (el): el is globalThis.HTMLOptionElement => el.tagName === 'OPTION'\n );\n\n options.forEach((option) => {\n if ((option.value || option.textContent) === this.value) {\n this.selectedLabel = option.textContent || '';\n }\n });\n }\n\n private handleDocumentClick = (event: MouseEvent) => {\n if (!this.contains(event.target as unknown as globalThis.Node)) {\n this.isOpen = false;\n }\n };\n\n private handleToggle = (event?: Event) => {\n event?.stopPropagation();\n if (this.disabled) return;\n this.isOpen = !this.isOpen;\n };\n\n private handleOptionClick = (event: Event) => {\n if (this.disabled) return;\n\n const target = event.currentTarget as HTMLElement;\n const optionValue = target.dataset.value || '';\n const optionLabel = target.dataset.label || '';\n\n const previousValue = this.value;\n this.value = optionValue;\n this.selectedLabel = optionLabel;\n this.isOpen = false;\n this.focusedIndex = -1;\n\n // Dispatch change event\n this.dispatchEvent(\n new CustomEvent('bp-change', {\n detail: {\n value: this.value,\n label: this.selectedLabel,\n previousValue,\n },\n bubbles: true,\n composed: true,\n })\n );\n\n // Update the underlying hidden input for form integration\n const hiddenInput = this.shadowRoot?.querySelector('input[type=\"hidden\"]');\n if (hiddenInput) {\n (hiddenInput as HTMLInputElement).value = this.value;\n hiddenInput.dispatchEvent(new Event('change', { bubbles: true }));\n }\n };\n\n private handleKeyDown = (event: globalThis.KeyboardEvent) => {\n if (this.disabled) return;\n\n const options = this.getOptions();\n\n switch (event.key) {\n case 'Enter':\n case ' ':\n event.preventDefault();\n if (this.isOpen && this.focusedIndex >= 0) {\n // Select the focused option\n const option = options[this.focusedIndex];\n if (option) {\n const optionValue = option.value || option.textContent || '';\n const optionLabel = option.textContent || '';\n const previousValue = this.value;\n this.value = optionValue;\n this.selectedLabel = optionLabel;\n this.isOpen = false;\n this.focusedIndex = -1;\n\n this.dispatchEvent(\n new CustomEvent('bp-change', {\n detail: {\n value: this.value,\n label: this.selectedLabel,\n previousValue,\n },\n bubbles: true,\n composed: true,\n })\n );\n\n const hiddenInput = this.shadowRoot?.querySelector(\n 'input[type=\"hidden\"]'\n );\n if (hiddenInput) {\n (hiddenInput as HTMLInputElement).value = this.value;\n hiddenInput.dispatchEvent(new Event('change', { bubbles: true }));\n }\n }\n } else {\n this.handleToggle();\n }\n break;\n case 'Escape':\n this.isOpen = false;\n this.focusedIndex = -1;\n break;\n case 'ArrowDown':\n event.preventDefault();\n if (!this.isOpen) {\n this.isOpen = true;\n this.focusedIndex = 0;\n } else {\n this.focusedIndex = Math.min(\n this.focusedIndex + 1,\n options.length - 1\n );\n }\n this.scrollFocusedOptionIntoView();\n break;\n case 'ArrowUp':\n event.preventDefault();\n if (!this.isOpen) {\n this.isOpen = true;\n this.focusedIndex = options.length - 1;\n } else {\n this.focusedIndex = Math.max(this.focusedIndex - 1, 0);\n }\n this.scrollFocusedOptionIntoView();\n break;\n case 'Home':\n if (this.isOpen) {\n event.preventDefault();\n this.focusedIndex = 0;\n this.scrollFocusedOptionIntoView();\n }\n break;\n case 'End':\n if (this.isOpen) {\n event.preventDefault();\n this.focusedIndex = options.length - 1;\n this.scrollFocusedOptionIntoView();\n }\n break;\n }\n };\n\n private getOptions(): Array<{ value: string; textContent: string }> {\n const slot = this.shadowRoot?.querySelector('slot');\n const assignedElements = slot?.assignedElements() || [];\n const options = assignedElements.filter(\n (el): el is globalThis.HTMLOptionElement => el.tagName === 'OPTION'\n );\n return options.map((option) => ({\n value: option.value || option.textContent || '',\n textContent: option.textContent || '',\n }));\n }\n\n private scrollFocusedOptionIntoView() {\n this.updateComplete.then(() => {\n const focusedOption = this.shadowRoot?.querySelector(\n '.select-option--focused'\n ) as HTMLElement;\n if (focusedOption) {\n focusedOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n }\n });\n }\n\n /**\n * Returns the longest text among all options and the placeholder.\n * Used by a hidden sizer element to keep the trigger width stable.\n */\n private getSizerText(): string {\n const options = this.getOptions();\n let longestText = this.placeholder || '';\n\n for (const option of options) {\n const text = option.textContent || '';\n if (text.length > longestText.length) {\n longestText = text;\n }\n }\n\n return longestText;\n }\n\n private getOptionElements = () => {\n const slot = this.shadowRoot?.querySelector('slot');\n const assignedElements = slot?.assignedElements() || [];\n const options = assignedElements.filter(\n (el): el is globalThis.HTMLOptionElement => el.tagName === 'OPTION'\n );\n\n return repeat(\n options,\n (option) => option.value || option.textContent || '',\n (option, index) => {\n const optionValue = option.value || option.textContent || '';\n const optionLabel = option.textContent || '';\n const isSelected = this.value === optionValue;\n const isFocused = this.focusedIndex === index;\n\n if (isSelected && !this.selectedLabel) {\n this.selectedLabel = optionLabel;\n }\n\n return html`\n <div\n class=\"select-option ${isSelected\n ? 'select-option--selected'\n : ''} ${isFocused ? 'select-option--focused' : ''}\"\n part=\"option\"\n role=\"option\"\n aria-selected=\"${isSelected ? 'true' : 'false'}\"\n data-value=\"${optionValue}\"\n data-label=\"${optionLabel}\"\n tabindex=\"-1\"\n @click=${this.handleOptionClick}\n >\n ${optionLabel}\n </div>\n `;\n }\n );\n };\n\n render() {\n const selectClasses = {\n select: true,\n [`select--${this.size}`]: true,\n 'select--disabled': this.disabled,\n 'select--open': this.isOpen,\n };\n\n const displayLabel = this.selectedLabel || this.placeholder;\n\n const labelId = this.label ? 'select-label' : undefined;\n\n return html`\n <div class=${classMap(selectClasses)} part=\"container\">\n ${this.label\n ? html`\n <label class=\"select-label\" id=\"select-label\" part=\"label\">\n ${this.label}\n ${this.required\n ? html`<span class=\"select-required\">*</span>`\n : ''}\n </label>\n `\n : ''}\n <!-- Hidden input for form integration (using input instead of select to avoid Firefox conflict) -->\n <input\n type=\"hidden\"\n name=${ifDefined(this.name || undefined)}\n .value=${this.value}\n />\n\n <!-- Slot for option elements (not rendered, just for content projection) -->\n <slot\n @slotchange=${this.handleSlotChange}\n style=\"display: none;\"\n ></slot>\n\n <!-- Custom select trigger -->\n <div\n class=\"select-trigger\"\n part=\"trigger\"\n role=\"combobox\"\n aria-expanded=\"${this.isOpen ? 'true' : 'false'}\"\n aria-haspopup=\"listbox\"\n aria-labelledby=\"${ifDefined(labelId)}\"\n aria-disabled=\"${this.disabled ? 'true' : 'false'}\"\n aria-required=\"${this.required ? 'true' : 'false'}\"\n tabindex=\"${this.disabled ? '-1' : '0'}\"\n @click=${this.handleToggle}\n @keydown=${this.handleKeyDown}\n >\n <span class=\"select-value\" part=\"display\">\n <span class=\"select-value__sizer\" aria-hidden=\"true\"\n >${this.getSizerText()}</span\n >\n <span class=\"select-value__display\">${displayLabel}</span>\n </span>\n <svg\n class=\"select-icon\"\n part=\"icon\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M4 6L8 10L12 6\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </div>\n\n <!-- Dropdown menu -->\n ${this.isOpen\n ? html`\n <div class=\"select-dropdown\" part=\"dropdown\" role=\"listbox\">\n ${this.getOptionElements()}\n </div>\n `\n : null}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'bp-select': BpSelect;\n }\n}\n"],"names":["selectStyles","css","BpSelect","LitElement","event","target","optionValue","optionLabel","previousValue","hiddenInput","options","option","el","repeat","index","isSelected","isFocused","html","focusedOption","longestText","text","selectClasses","displayLabel","labelId","classMap","ifDefined","__decorateClass","property","state","customElement"],"mappings":";;;;;AAEO,MAAMA,IAAeC;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;;;;;;ACQrB,IAAMC,IAAN,cAAuBC,EAAW;AAAA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"}
@@ -1 +1 @@
1
- {"version":3,"file":"skeleton.js","sources":["../../source/components/skeleton/skeleton.style.ts","../../source/components/skeleton/skeleton.ts"],"sourcesContent":["import { css } from 'lit';\r\n\r\nexport const skeletonStyles = css`\r\n /* Base styles */\r\n :host {\r\n display: block;\r\n }\r\n\r\n .skeleton {\r\n background-color: var(--bp-color-surface-subdued);\r\n overflow: hidden;\r\n position: relative;\r\n width: var(--skeleton-width, auto);\r\n height: var(--skeleton-height, auto);\r\n }\r\n\r\n /* Animation */\r\n .skeleton--animated::after {\r\n content: '';\r\n position: absolute;\r\n inset: 0;\r\n background: linear-gradient(\r\n 90deg,\r\n transparent 0%,\r\n rgba(255, 255, 255, 0.6) 50%,\r\n transparent 100%\r\n );\r\n animation: skeleton-shimmer 1.5s infinite linear;\r\n transform: translateX(-100%);\r\n }\r\n\r\n @keyframes skeleton-shimmer {\r\n 0% {\r\n transform: translateX(-100%);\r\n }\r\n 100% {\r\n transform: translateX(100%);\r\n }\r\n }\r\n\r\n /* Respect user motion preferences */\r\n @media (prefers-reduced-motion: reduce) {\r\n .skeleton--animated::after {\r\n animation: none;\r\n opacity: 0.7;\r\n }\r\n }\r\n\r\n /* Variants */\r\n .skeleton--text {\r\n border-radius: var(--bp-border-radius-sm);\r\n width: 100%;\r\n }\r\n\r\n .skeleton--circular {\r\n border-radius: var(--bp-border-radius-full);\r\n }\r\n\r\n .skeleton--rectangular {\r\n border-radius: 2px;\r\n }\r\n\r\n .skeleton--rounded {\r\n border-radius: var(--bp-border-radius-lg);\r\n }\r\n\r\n /* Sizes for text variant */\r\n .skeleton--text.skeleton--sm {\r\n height: var(--bp-spacing-3);\r\n }\r\n\r\n .skeleton--text.skeleton--md {\r\n height: var(--bp-spacing-4);\r\n }\r\n\r\n .skeleton--text.skeleton--lg {\r\n height: var(--bp-spacing-6);\r\n }\r\n\r\n /* Sizes for circular variant */\r\n .skeleton--circular.skeleton--sm {\r\n width: var(--bp-spacing-8);\r\n height: var(--bp-spacing-8);\r\n }\r\n\r\n .skeleton--circular.skeleton--md {\r\n width: var(--bp-spacing-10);\r\n height: var(--bp-spacing-10);\r\n }\r\n\r\n .skeleton--circular.skeleton--lg {\r\n width: var(--bp-spacing-12);\r\n height: var(--bp-spacing-12);\r\n }\r\n\r\n /* Sizes for rectangular/rounded variants */\r\n .skeleton--rectangular.skeleton--sm,\r\n .skeleton--rounded.skeleton--sm {\r\n height: var(--bp-spacing-10);\r\n }\r\n\r\n .skeleton--rectangular.skeleton--md,\r\n .skeleton--rounded.skeleton--md {\r\n height: var(--bp-spacing-16);\r\n }\r\n\r\n .skeleton--rectangular.skeleton--lg,\r\n .skeleton--rounded.skeleton--lg {\r\n height: var(--bp-spacing-24);\r\n }\r\n\r\n /* Text lines container */\r\n .skeleton__lines {\r\n display: flex;\r\n flex-direction: column;\r\n gap: var(--bp-spacing-3);\r\n }\r\n\r\n /* Last line in multi-line text is shorter */\r\n .skeleton--last-line {\r\n width: 75%;\r\n }\r\n\r\n /* Static state (no animation) */\r\n :host([animated='false']) .skeleton::after,\r\n .skeleton:not(.skeleton--animated)::after {\r\n display: none;\r\n }\r\n\r\n :host([animated='false']) .skeleton,\r\n .skeleton:not(.skeleton--animated) {\r\n opacity: 0.6;\r\n }\r\n`;\r\n","import { LitElement, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport { skeletonStyles } from './skeleton.style.js';\r\nimport { booleanConverter } from '../../utilities/boolean-converter.js';\r\n\r\n/**\r\n * A skeleton loading placeholder that indicates content is loading.\r\n * Use skeletons to reduce perceived loading time and provide visual feedback.\r\n *\r\n * @slot - Optional slot for custom skeleton content\r\n *\r\n * @csspart base - The skeleton container element\r\n */\r\n@customElement('bp-skeleton')\r\nexport class BpSkeleton extends LitElement {\r\n /** The visual variant of the skeleton */\r\n @property({\r\n type: String,\r\n reflect: true,\r\n converter: {\r\n fromAttribute: (value: string | null) => {\r\n const valid = ['text', 'circular', 'rectangular', 'rounded'];\r\n return value && valid.includes(value) ? value : 'text';\r\n },\r\n },\r\n })\r\n declare variant: 'text' | 'circular' | 'rectangular' | 'rounded';\r\n\r\n /** Width of the skeleton. Can be any valid CSS value. */\r\n @property({ type: String }) declare width: string;\r\n\r\n /** Height of the skeleton. Can be any valid CSS value. */\r\n @property({ type: String }) declare height: string;\r\n\r\n /** Whether to animate the skeleton with a shimmer effect */\r\n @property({ converter: booleanConverter, reflect: true })\r\n declare animated: boolean;\r\n\r\n /** Number of lines to display (only for text variant) */\r\n @property({\r\n type: Number,\r\n converter: (value: string | null) => {\r\n const num = Number(value);\r\n return num > 0 ? num : 1;\r\n },\r\n })\r\n declare lines: number;\r\n\r\n /** The size preset (affects default dimensions) */\r\n @property({ type: String }) declare size: 'sm' | 'md' | 'lg';\r\n\r\n static styles = [skeletonStyles];\r\n\r\n constructor() {\r\n super();\r\n this.variant = 'text';\r\n this.width = '';\r\n this.height = '';\r\n this.animated = true;\r\n this.lines = 1;\r\n this.size = 'md';\r\n }\r\n\r\n /**\r\n * Generates CSS custom properties for width and height.\r\n * Uses custom properties instead of inline styles for CSP compliance.\r\n * @returns CSS string with custom property declarations\r\n */\r\n private getCustomProperties(): string {\r\n const props: string[] = [];\r\n\r\n if (this.width) {\r\n props.push(`--skeleton-width: ${this.width}`);\r\n }\r\n\r\n if (this.height) {\r\n props.push(`--skeleton-height: ${this.height}`);\r\n }\r\n\r\n return props.join('; ');\r\n }\r\n\r\n /**\r\n * Renders a single skeleton element with appropriate classes and styles.\r\n * @returns Template result for a single skeleton\r\n */\r\n private renderSingleSkeleton() {\r\n const classes = [\r\n 'skeleton',\r\n `skeleton--${this.variant}`,\r\n `skeleton--${this.size}`,\r\n this.animated ? 'skeleton--animated' : '',\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n\r\n const customProps = this.getCustomProperties();\r\n\r\n return html`\r\n <div class=${classes} part=\"base\" style=${customProps || nothing}>\r\n <slot></slot>\r\n </div>\r\n `;\r\n }\r\n\r\n /**\r\n * Renders text skeleton lines.\r\n * If variant is text and lines > 1, renders multiple lines with a container.\r\n * Otherwise delegates to renderSingleSkeleton.\r\n * @returns Template result for text lines or single skeleton\r\n */\r\n private renderTextLines() {\r\n if (this.variant !== 'text' || this.lines <= 1) {\r\n return this.renderSingleSkeleton();\r\n }\r\n\r\n const customProps = this.getCustomProperties();\r\n const lineElements = [];\r\n for (let i = 0; i < this.lines; i++) {\r\n const isLastLine = i === this.lines - 1;\r\n const classes = [\r\n 'skeleton',\r\n 'skeleton--text',\r\n `skeleton--${this.size}`,\r\n this.animated ? 'skeleton--animated' : '',\r\n isLastLine ? 'skeleton--last-line' : '',\r\n ]\r\n .filter(Boolean)\r\n .join(' ');\r\n\r\n lineElements.push(\r\n html`<div\r\n class=${classes}\r\n part=\"base\"\r\n style=${customProps || nothing}\r\n ></div>`\r\n );\r\n }\r\n\r\n return html`<div class=\"skeleton__lines\">${lineElements}</div>`;\r\n }\r\n\r\n render() {\r\n return this.renderTextLines();\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'bp-skeleton': BpSkeleton;\r\n }\r\n}\r\n"],"names":["skeletonStyles","css","BpSkeleton","LitElement","props","classes","customProps","html","nothing","lineElements","i","isLastLine","__decorateClass","property","value","booleanConverter","num","customElement"],"mappings":"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"}
1
+ {"version":3,"file":"skeleton.js","sources":["../../source/components/skeleton/skeleton.style.ts","../../source/components/skeleton/skeleton.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const skeletonStyles = css`\n /* Base styles */\n :host {\n display: block;\n }\n\n .skeleton {\n background-color: var(--bp-color-surface-subdued);\n overflow: hidden;\n position: relative;\n width: var(--skeleton-width, auto);\n height: var(--skeleton-height, auto);\n }\n\n /* Animation */\n .skeleton--animated::after {\n content: '';\n position: absolute;\n inset: 0;\n background: linear-gradient(\n 90deg,\n transparent 0%,\n rgba(255, 255, 255, 0.6) 50%,\n transparent 100%\n );\n animation: skeleton-shimmer 1.5s infinite linear;\n transform: translateX(-100%);\n }\n\n @keyframes skeleton-shimmer {\n 0% {\n transform: translateX(-100%);\n }\n 100% {\n transform: translateX(100%);\n }\n }\n\n /* Respect user motion preferences */\n @media (prefers-reduced-motion: reduce) {\n .skeleton--animated::after {\n animation: none;\n opacity: 0.7;\n }\n }\n\n /* Variants */\n .skeleton--text {\n border-radius: var(--bp-border-radius-sm);\n width: 100%;\n }\n\n .skeleton--circular {\n border-radius: var(--bp-border-radius-full);\n }\n\n .skeleton--rectangular {\n border-radius: 2px;\n }\n\n .skeleton--rounded {\n border-radius: var(--bp-border-radius-lg);\n }\n\n /* Sizes for text variant */\n .skeleton--text.skeleton--sm {\n height: var(--bp-spacing-3);\n }\n\n .skeleton--text.skeleton--md {\n height: var(--bp-spacing-4);\n }\n\n .skeleton--text.skeleton--lg {\n height: var(--bp-spacing-6);\n }\n\n /* Sizes for circular variant */\n .skeleton--circular.skeleton--sm {\n width: var(--bp-spacing-8);\n height: var(--bp-spacing-8);\n }\n\n .skeleton--circular.skeleton--md {\n width: var(--bp-spacing-10);\n height: var(--bp-spacing-10);\n }\n\n .skeleton--circular.skeleton--lg {\n width: var(--bp-spacing-12);\n height: var(--bp-spacing-12);\n }\n\n /* Sizes for rectangular/rounded variants */\n .skeleton--rectangular.skeleton--sm,\n .skeleton--rounded.skeleton--sm {\n height: var(--bp-spacing-10);\n }\n\n .skeleton--rectangular.skeleton--md,\n .skeleton--rounded.skeleton--md {\n height: var(--bp-spacing-16);\n }\n\n .skeleton--rectangular.skeleton--lg,\n .skeleton--rounded.skeleton--lg {\n height: var(--bp-spacing-24);\n }\n\n /* Text lines container */\n .skeleton__lines {\n display: flex;\n flex-direction: column;\n gap: var(--bp-spacing-3);\n }\n\n /* Last line in multi-line text is shorter */\n .skeleton--last-line {\n width: 75%;\n }\n\n /* Static state (no animation) */\n :host([animated='false']) .skeleton::after,\n .skeleton:not(.skeleton--animated)::after {\n display: none;\n }\n\n :host([animated='false']) .skeleton,\n .skeleton:not(.skeleton--animated) {\n opacity: 0.6;\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { skeletonStyles } from './skeleton.style.js';\nimport { booleanConverter } from '../../utilities/boolean-converter.js';\n\n/**\n * A skeleton loading placeholder that indicates content is loading.\n * Use skeletons to reduce perceived loading time and provide visual feedback.\n *\n * @slot - Optional slot for custom skeleton content\n *\n * @csspart base - The skeleton container element\n */\n@customElement('bp-skeleton')\nexport class BpSkeleton extends LitElement {\n /** The visual variant of the skeleton */\n @property({\n type: String,\n reflect: true,\n converter: {\n fromAttribute: (value: string | null) => {\n const valid = ['text', 'circular', 'rectangular', 'rounded'];\n return value && valid.includes(value) ? value : 'text';\n },\n },\n })\n declare variant: 'text' | 'circular' | 'rectangular' | 'rounded';\n\n /** Width of the skeleton. Can be any valid CSS value. */\n @property({ type: String }) declare width: string;\n\n /** Height of the skeleton. Can be any valid CSS value. */\n @property({ type: String }) declare height: string;\n\n /** Whether to animate the skeleton with a shimmer effect */\n @property({ converter: booleanConverter, reflect: true })\n declare animated: boolean;\n\n /** Number of lines to display (only for text variant) */\n @property({\n type: Number,\n converter: (value: string | null) => {\n const num = Number(value);\n return num > 0 ? num : 1;\n },\n })\n declare lines: number;\n\n /** The size preset (affects default dimensions) */\n @property({ type: String }) declare size: 'sm' | 'md' | 'lg';\n\n static styles = [skeletonStyles];\n\n constructor() {\n super();\n this.variant = 'text';\n this.width = '';\n this.height = '';\n this.animated = true;\n this.lines = 1;\n this.size = 'md';\n }\n\n /**\n * Generates CSS custom properties for width and height.\n * Uses custom properties instead of inline styles for CSP compliance.\n * @returns CSS string with custom property declarations\n */\n private getCustomProperties(): string {\n const props: string[] = [];\n\n if (this.width) {\n props.push(`--skeleton-width: ${this.width}`);\n }\n\n if (this.height) {\n props.push(`--skeleton-height: ${this.height}`);\n }\n\n return props.join('; ');\n }\n\n /**\n * Renders a single skeleton element with appropriate classes and styles.\n * @returns Template result for a single skeleton\n */\n private renderSingleSkeleton() {\n const classes = [\n 'skeleton',\n `skeleton--${this.variant}`,\n `skeleton--${this.size}`,\n this.animated ? 'skeleton--animated' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n const customProps = this.getCustomProperties();\n\n return html`\n <div class=${classes} part=\"base\" style=${customProps || nothing}>\n <slot></slot>\n </div>\n `;\n }\n\n /**\n * Renders text skeleton lines.\n * If variant is text and lines > 1, renders multiple lines with a container.\n * Otherwise delegates to renderSingleSkeleton.\n * @returns Template result for text lines or single skeleton\n */\n private renderTextLines() {\n if (this.variant !== 'text' || this.lines <= 1) {\n return this.renderSingleSkeleton();\n }\n\n const customProps = this.getCustomProperties();\n const lineElements = [];\n for (let i = 0; i < this.lines; i++) {\n const isLastLine = i === this.lines - 1;\n const classes = [\n 'skeleton',\n 'skeleton--text',\n `skeleton--${this.size}`,\n this.animated ? 'skeleton--animated' : '',\n isLastLine ? 'skeleton--last-line' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n lineElements.push(\n html`<div\n class=${classes}\n part=\"base\"\n style=${customProps || nothing}\n ></div>`\n );\n }\n\n return html`<div class=\"skeleton__lines\">${lineElements}</div>`;\n }\n\n render() {\n return this.renderTextLines();\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'bp-skeleton': BpSkeleton;\n }\n}\n"],"names":["skeletonStyles","css","BpSkeleton","LitElement","props","classes","customProps","html","nothing","lineElements","i","isLastLine","__decorateClass","property","value","booleanConverter","num","customElement"],"mappings":";;;AAEO,MAAMA,IAAiBC;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;;;;;;ACYvB,IAAMC,IAAN,cAAyBC,EAAW;AAAA,EAuCzC,cAAc;AACZ,UAAA,GACA,KAAK,UAAU,QACf,KAAK,QAAQ,IACb,KAAK,SAAS,IACd,KAAK,WAAW,IAChB,KAAK,QAAQ,GACb,KAAK,OAAO;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,sBAA8B;AACpC,UAAMC,IAAkB,CAAA;AAExB,WAAI,KAAK,SACPA,EAAM,KAAK,qBAAqB,KAAK,KAAK,EAAE,GAG1C,KAAK,UACPA,EAAM,KAAK,sBAAsB,KAAK,MAAM,EAAE,GAGzCA,EAAM,KAAK,IAAI;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,uBAAuB;AAC7B,UAAMC,IAAU;AAAA,MACd;AAAA,MACA,aAAa,KAAK,OAAO;AAAA,MACzB,aAAa,KAAK,IAAI;AAAA,MACtB,KAAK,WAAW,uBAAuB;AAAA,IAAA,EAEtC,OAAO,OAAO,EACd,KAAK,GAAG,GAELC,IAAc,KAAK,oBAAA;AAEzB,WAAOC;AAAA,mBACQF,CAAO,sBAAsBC,KAAeE,CAAO;AAAA;AAAA;AAAA;AAAA,EAIpE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,kBAAkB;AACxB,QAAI,KAAK,YAAY,UAAU,KAAK,SAAS;AAC3C,aAAO,KAAK,qBAAA;AAGd,UAAMF,IAAc,KAAK,oBAAA,GACnBG,IAAe,CAAA;AACrB,aAASC,IAAI,GAAGA,IAAI,KAAK,OAAOA,KAAK;AACnC,YAAMC,IAAaD,MAAM,KAAK,QAAQ,GAChCL,IAAU;AAAA,QACd;AAAA,QACA;AAAA,QACA,aAAa,KAAK,IAAI;AAAA,QACtB,KAAK,WAAW,uBAAuB;AAAA,QACvCM,IAAa,wBAAwB;AAAA,MAAA,EAEpC,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,MAAAF,EAAa;AAAA,QACXF;AAAA,kBACUF,CAAO;AAAA;AAAA,kBAEPC,KAAeE,CAAO;AAAA;AAAA,MAAA;AAAA,IAGpC;AAEA,WAAOD,iCAAoCE,CAAY;AAAA,EACzD;AAAA,EAEA,SAAS;AACP,WAAO,KAAK,gBAAA;AAAA,EACd;AACF;AAnIaP,EAqCJ,SAAS,CAACF,CAAc;AAzBvBY,EAAA;AAAA,EAVPC,EAAS;AAAA,IACR,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,MACT,eAAe,CAACC,MAEPA,KADO,CAAC,QAAQ,YAAY,eAAe,SAAS,EACrC,SAASA,CAAK,IAAIA,IAAQ;AAAA,IAClD;AAAA,EACF,CACD;AAAA,GAXUZ,EAYH,WAAA,WAAA,CAAA;AAG4BU,EAAA;AAAA,EAAnCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAffX,EAeyB,WAAA,SAAA,CAAA;AAGAU,EAAA;AAAA,EAAnCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAlBfX,EAkByB,WAAA,UAAA,CAAA;AAI5BU,EAAA;AAAA,EADPC,EAAS,EAAE,WAAWE,GAAkB,SAAS,IAAM;AAAA,GArB7Cb,EAsBH,WAAA,YAAA,CAAA;AAUAU,EAAA;AAAA,EAPPC,EAAS;AAAA,IACR,MAAM;AAAA,IACN,WAAW,CAACC,MAAyB;AACnC,YAAME,IAAM,OAAOF,CAAK;AACxB,aAAOE,IAAM,IAAIA,IAAM;AAAA,IACzB;AAAA,EAAA,CACD;AAAA,GA/BUd,EAgCH,WAAA,SAAA,CAAA;AAG4BU,EAAA;AAAA,EAAnCC,EAAS,EAAE,MAAM,OAAA,CAAQ;AAAA,GAnCfX,EAmCyB,WAAA,QAAA,CAAA;AAnCzBA,IAANU,EAAA;AAAA,EADNK,EAAc,aAAa;AAAA,GACff,CAAA;"}