@krollins/blueprint 0.1.12 → 0.1.13
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.
- package/dist/components/accordion.js +393 -0
- package/dist/components/accordion.js.map +1 -0
- package/dist/components/alert.js +213 -0
- package/dist/components/alert.js.map +1 -0
- package/dist/components/avatar.js +237 -0
- package/dist/components/avatar.js.map +1 -0
- package/dist/components/badge.js +144 -0
- package/dist/components/badge.js.map +1 -0
- package/dist/components/breadcrumb.js +481 -0
- package/dist/components/breadcrumb.js.map +1 -0
- package/dist/components/button.js +192 -0
- package/dist/components/button.js.map +1 -0
- package/dist/components/card.js +223 -0
- package/dist/components/card.js.map +1 -0
- package/dist/components/checkbox.js +337 -0
- package/dist/components/checkbox.js.map +1 -0
- package/dist/components/color-picker.js +1660 -0
- package/dist/components/color-picker.js.map +1 -0
- package/dist/components/combobox.js +595 -0
- package/dist/components/combobox.js.map +1 -0
- package/dist/components/date-picker.js +726 -0
- package/dist/components/date-picker.js.map +1 -0
- package/dist/components/divider.js +214 -0
- package/dist/components/divider.js.map +1 -0
- package/dist/components/drawer.js +568 -0
- package/dist/components/drawer.js.map +1 -0
- package/dist/components/dropdown.js +377 -0
- package/dist/components/dropdown.js.map +1 -0
- package/dist/components/file-upload.js +669 -0
- package/dist/components/file-upload.js.map +1 -0
- package/dist/components/heading.js +161 -0
- package/dist/components/heading.js.map +1 -0
- package/dist/components/icon.js +599 -0
- package/dist/components/icon.js.map +1 -0
- package/dist/components/input.js +363 -0
- package/dist/components/input.js.map +1 -0
- package/dist/components/link.js +178 -0
- package/dist/components/link.js.map +1 -0
- package/dist/components/menu.js +331 -0
- package/dist/components/menu.js.map +1 -0
- package/dist/components/modal.js +317 -0
- package/dist/components/modal.js.map +1 -0
- package/dist/components/multi-select.js +642 -0
- package/dist/components/multi-select.js.map +1 -0
- package/dist/components/notification.js +429 -0
- package/dist/components/notification.js.map +1 -0
- package/dist/components/number-input.js +556 -0
- package/dist/components/number-input.js.map +1 -0
- package/dist/components/pagination.js +320 -0
- package/dist/components/pagination.js.map +1 -0
- package/dist/components/popover.js +597 -0
- package/dist/components/popover.js.map +1 -0
- package/dist/components/progress.js +219 -0
- package/dist/components/progress.js.map +1 -0
- package/dist/components/radio.js +321 -0
- package/dist/components/radio.js.map +1 -0
- package/dist/components/select.js +498 -0
- package/dist/components/select.js.map +1 -0
- package/dist/components/skeleton.js +240 -0
- package/dist/components/skeleton.js.map +1 -0
- package/dist/components/slider.js +9 -0
- package/dist/components/slider.js.map +1 -0
- package/dist/components/spinner.js +133 -0
- package/dist/components/spinner.js.map +1 -0
- package/dist/components/stepper.js +812 -0
- package/dist/components/stepper.js.map +1 -0
- package/dist/components/switch.js +380 -0
- package/dist/components/switch.js.map +1 -0
- package/dist/components/table.js +642 -0
- package/dist/components/table.js.map +1 -0
- package/dist/components/tabs.js +547 -0
- package/dist/components/tabs.js.map +1 -0
- package/dist/components/tag.js +291 -0
- package/dist/components/tag.js.map +1 -0
- package/dist/components/text.js +278 -0
- package/dist/components/text.js.map +1 -0
- package/dist/components/textarea.js +380 -0
- package/dist/components/textarea.js.map +1 -0
- package/dist/components/time-picker.js +457 -0
- package/dist/components/time-picker.js.map +1 -0
- package/dist/components/tooltip.js +239 -0
- package/dist/components/tooltip.js.map +1 -0
- package/dist/components/tree.js +582 -0
- package/dist/components/tree.js.map +1 -0
- package/dist/index.js +93 -17799
- package/dist/index.js.map +1 -1
- package/dist/shared/boolean-converter-XDGfS9LC.js +12 -0
- package/dist/shared/boolean-converter-XDGfS9LC.js.map +1 -0
- package/dist/shared/debounce-BckY30Sf.js +23 -0
- package/dist/shared/debounce-BckY30Sf.js.map +1 -0
- package/dist/shared/memoize-DlOFy-92.js +16 -0
- package/dist/shared/memoize-DlOFy-92.js.map +1 -0
- package/dist/shared/slider-BNt5TITl.js +484 -0
- package/dist/shared/slider-BNt5TITl.js.map +1 -0
- package/package.json +44 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multi-select.js","sources":["../../source/components/multi-select/multi-select.style.ts","../../source/components/multi-select/multi-select.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const multiSelectStyles = css`\n /* Base styles */\n :host {\n display: block;\n font-family: var(--bp-font-family);\n }\n\n .multi-select {\n position: relative;\n width: 100%;\n }\n\n .multi-select__control {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--bp-spacing-sm);\n min-height: var(--bp-spacing-10);\n padding: var(--bp-spacing-xs) var(--bp-spacing-sm);\n background-color: var(--bp-color-surface);\n border: var(--bp-border-width) solid var(--bp-color-border);\n border-radius: var(--bp-border-radius-md);\n cursor: pointer;\n transition: border-color var(--bp-transition-fast);\n }\n\n .multi-select__control:hover:not(\n .multi-select--disabled .multi-select__control\n ) {\n border-color: var(--bp-color-primary);\n }\n\n .multi-select__control:focus-visible {\n outline: var(--bp-focus-width) solid var(--bp-color-focus);\n outline-offset: var(--bp-focus-width);\n }\n\n .multi-select__value-container {\n display: flex;\n flex-wrap: wrap;\n gap: var(--bp-spacing-xs);\n flex: 1;\n min-width: 0;\n }\n\n .multi-select__placeholder {\n color: var(--bp-color-text-muted);\n user-select: none;\n }\n\n .multi-select__tag {\n display: inline-flex;\n align-items: center;\n gap: var(--bp-spacing-xs);\n padding: var(--bp-spacing-2xs) var(--bp-spacing-xs);\n background-color: color-mix(\n in srgb,\n var(--bp-color-primary) 8%,\n transparent\n );\n color: var(--bp-color-primary);\n border: none;\n border-radius: var(--bp-border-radius-md);\n font-size: var(--bp-font-size-sm);\n max-width: 100%;\n }\n\n .multi-select__tag-label {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .multi-select__tag-remove {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--bp-spacing-4);\n height: var(--bp-spacing-4);\n padding: 0;\n background: transparent;\n border: none;\n border-radius: var(--bp-border-radius-sm);\n color: var(--bp-color-primary);\n cursor: pointer;\n font-size: var(--bp-font-size-lg);\n line-height: 1;\n transition: all var(--bp-transition-fast);\n }\n\n .multi-select__tag-remove:hover {\n background-color: color-mix(\n in srgb,\n var(--bp-color-primary) 15%,\n transparent\n );\n color: var(--bp-color-primary);\n }\n\n .multi-select__tag-remove:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n .multi-select__indicators {\n display: flex;\n align-items: center;\n gap: var(--bp-spacing-xs);\n flex-shrink: 0;\n }\n\n .multi-select__clear {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--bp-spacing-6);\n height: var(--bp-spacing-6);\n padding: 0;\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 font-size: var(--bp-font-size-xl);\n line-height: 1;\n transition: all var(--bp-transition-fast);\n }\n\n .multi-select__clear:hover {\n background-color: var(--bp-color-surface-subdued);\n color: var(--bp-color-text);\n }\n\n .multi-select__clear:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n .multi-select__dropdown-indicator {\n color: var(--bp-color-text-muted);\n font-size: var(--bp-font-size-xs);\n transition: transform var(--bp-transition-fast);\n user-select: none;\n }\n\n .multi-select--open .multi-select__dropdown-indicator {\n transform: rotate(180deg);\n }\n\n .multi-select__dropdown {\n position: absolute;\n top: calc(100% + var(--bp-spacing-xs));\n left: 0;\n right: 0;\n z-index: var(--bp-z-dropdown);\n background-color: var(--bp-color-surface);\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-md);\n max-height: calc(var(--bp-spacing-10) * 6);\n overflow-y: auto;\n opacity: 0;\n visibility: hidden;\n transform: translateY(calc(-1 * var(--bp-spacing-md)));\n transition:\n opacity var(--bp-transition-fast),\n transform var(--bp-transition-fast),\n visibility var(--bp-transition-fast);\n contain: layout style paint;\n }\n\n .multi-select--open .multi-select__dropdown {\n opacity: 1;\n visibility: visible;\n transform: translateY(0);\n }\n\n .multi-select__options {\n list-style: none;\n margin: 0;\n padding: var(--bp-spacing-2xs);\n }\n\n .multi-select__option {\n display: flex;\n align-items: center;\n gap: var(--bp-spacing-sm);\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\n cursor: pointer;\n border-radius: var(--bp-border-radius-md);\n transition:\n background-color var(--bp-transition-fast),\n color var(--bp-transition-fast);\n }\n\n .multi-select__option:hover {\n background-color: var(--bp-color-surface-elevated);\n }\n\n .multi-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 .multi-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 }\n\n .multi-select__option--selected:hover {\n background-color: color-mix(\n in srgb,\n var(--bp-color-primary) 12%,\n transparent\n );\n }\n\n .multi-select__option--empty {\n color: var(--bp-color-text-muted);\n cursor: default;\n text-align: center;\n padding: var(--bp-spacing-xl) var(--bp-spacing-lg);\n font-style: italic;\n }\n\n .multi-select__checkbox {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--bp-spacing-4);\n height: var(--bp-spacing-4);\n border: var(--bp-border-width) solid var(--bp-color-border);\n border-radius: var(--bp-border-radius-sm);\n font-size: var(--bp-font-size-xs);\n flex-shrink: 0;\n transition: all var(--bp-transition-fast);\n }\n\n .multi-select__option--selected .multi-select__checkbox {\n border-color: var(--bp-color-primary);\n background-color: var(--bp-color-primary);\n color: var(--bp-color-text-inverse);\n }\n\n .multi-select__option-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* Sizes */\n .multi-select--sm .multi-select__control {\n min-height: var(--bp-spacing-8);\n padding: var(--bp-spacing-2xs) var(--bp-spacing-xs);\n font-size: var(--bp-font-size-sm);\n }\n\n .multi-select--sm .multi-select__tag {\n padding: var(--bp-spacing-0-5) var(--bp-spacing-2xs);\n font-size: var(--bp-font-size-xs);\n }\n\n .multi-select--lg .multi-select__control {\n min-height: var(--bp-spacing-12);\n padding: var(--bp-spacing-sm) var(--bp-spacing-md);\n font-size: var(--bp-font-size-lg);\n }\n\n .multi-select--lg .multi-select__tag {\n padding: var(--bp-spacing-xs) var(--bp-spacing-sm);\n font-size: var(--bp-font-size-base);\n }\n\n /* Variants */\n .multi-select--default .multi-select__control {\n border-color: var(--bp-color-border);\n }\n\n .multi-select--success .multi-select__control {\n border-color: var(--bp-color-success);\n }\n\n .multi-select--error .multi-select__control {\n border-color: var(--bp-color-error);\n }\n\n .multi-select--warning .multi-select__control {\n border-color: var(--bp-color-warning);\n }\n\n .multi-select--info .multi-select__control {\n border-color: var(--bp-color-info);\n }\n\n .multi-select--success\n .multi-select__control:hover:not(\n .multi-select--disabled .multi-select__control\n ) {\n border-color: var(--bp-color-success);\n }\n\n .multi-select--error\n .multi-select__control:hover:not(\n .multi-select--disabled .multi-select__control\n ) {\n border-color: var(--bp-color-error);\n }\n\n .multi-select--warning\n .multi-select__control:hover:not(\n .multi-select--disabled .multi-select__control\n ) {\n border-color: var(--bp-color-warning);\n }\n\n .multi-select--info\n .multi-select__control:hover:not(\n .multi-select--disabled .multi-select__control\n ) {\n border-color: var(--bp-color-info);\n }\n\n /* States */\n .multi-select--disabled .multi-select__control {\n background-color: var(--bp-color-surface-subdued);\n cursor: not-allowed;\n opacity: 0.6;\n }\n\n .multi-select--disabled .multi-select__placeholder {\n color: var(--bp-color-text-muted);\n }\n\n /* Hide slot */\n slot {\n display: none;\n }\n\n /* Hide hidden inputs */\n input[type='hidden'] {\n display: none;\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\nimport { classMap } from 'lit/directives/class-map.js';\r\nimport { repeat } from 'lit/directives/repeat.js';\r\nimport { multiSelectStyles } from './multi-select.style.js';\r\nimport { memoizeOne } from '../../utilities/memoize.js';\r\nimport { booleanConverter } from '../../utilities/boolean-converter.js';\r\n\r\nexport type MultiSelectSize = 'sm' | 'md' | 'lg';\r\nexport type MultiSelectVariant =\r\n | 'default'\r\n | 'success'\r\n | 'error'\r\n | 'warning'\r\n | 'info';\r\n\r\nexport interface MultiSelectOption {\r\n value: string;\r\n label: string;\r\n}\r\n\r\n@customElement('bp-multi-select')\r\nexport class BpMultiSelect extends LitElement {\r\n /** The current selected values as an array */\r\n @property({ type: Array }) declare value: string[];\r\n\r\n /** Name attribute for form submission */\r\n @property({ type: String }) declare name: string;\r\n\r\n /** Placeholder text when no values are selected */\r\n @property({ type: String }) declare placeholder: string;\r\n\r\n /** Whether the multi-select is disabled */\r\n @property({ type: Boolean, reflect: true }) declare disabled: boolean;\r\n\r\n /** Whether the multi-select is required */\r\n @property({ type: Boolean, reflect: true }) declare required: boolean;\r\n\r\n /** Size variant of the multi-select */\r\n @property({ type: String, reflect: true }) declare size: MultiSelectSize;\r\n\r\n /** Visual variant for validation states */\r\n @property({ type: String, reflect: true })\r\n declare variant: MultiSelectVariant;\r\n\r\n /** Maximum number of selections allowed (0 = unlimited) */\r\n @property({ type: Number, attribute: 'max-selections' })\r\n declare maxSelections: number;\r\n\r\n /** Whether to show a clear all button */\r\n @property({ converter: booleanConverter }) declare clearable: boolean;\r\n\r\n /** Whether the dropdown is currently open */\r\n @state() private isOpen = false;\r\n\r\n /** Index of the focused option for keyboard navigation */\r\n @state() private focusedIndex = -1;\r\n\r\n /** Cached options from slotted elements */\r\n @state() private cachedOptions: MultiSelectOption[] = [];\r\n\r\n /**\r\n * Memoized label lookup map for efficient tag rendering.\r\n * Only recomputes when cachedOptions reference changes.\r\n */\r\n private computeLabelMap = memoizeOne(\r\n (options: MultiSelectOption[]): Map<string, string> => {\r\n const map = new Map<string, string>();\r\n for (const opt of options) {\r\n map.set(opt.value, opt.label);\r\n }\r\n return map;\r\n }\r\n );\r\n\r\n static styles = [multiSelectStyles];\r\n\r\n constructor() {\r\n super();\r\n this.value = [];\r\n this.name = '';\r\n this.placeholder = 'Select options';\r\n this.disabled = false;\r\n this.required = false;\r\n this.size = 'md';\r\n this.variant = 'default';\r\n this.maxSelections = 0;\r\n this.clearable = true;\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 // Initialize cached options and pre-selected values after first render\r\n this.updateComplete.then(() => {\r\n this.cachedOptions = this.getOptions();\r\n this.initializeSelectedValues();\r\n });\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 handleDocumentClick = (event: MouseEvent) => {\r\n if (!this.contains(event.target as globalThis.Node)) {\r\n this.isOpen = false;\r\n this.focusedIndex = -1;\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 if (this.isOpen) {\r\n this.focusedIndex = 0;\r\n }\r\n };\r\n\r\n private getOptions(): MultiSelectOption[] {\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 options.map((option) => ({\r\n value: option.value || option.textContent || '',\r\n label: option.textContent || '',\r\n }));\r\n }\r\n\r\n /**\r\n * Handle slot changes by refreshing the cached options.\r\n */\r\n private handleSlotChange = () => {\r\n this.cachedOptions = this.getOptions();\r\n this.initializeSelectedValues();\r\n };\r\n\r\n /**\r\n * Read the `selected` attribute from slotted <option> elements\r\n * and set the initial value array if no values are already set.\r\n */\r\n private initializeSelectedValues() {\r\n if (this.value.length > 0) return;\r\n\r\n const slot = this.shadowRoot?.querySelector('slot');\r\n const assignedElements = slot?.assignedElements() || [];\r\n const selectedValues = assignedElements\r\n .filter(\r\n (el): el is globalThis.HTMLOptionElement =>\r\n el.tagName === 'OPTION' && el.hasAttribute('selected')\r\n )\r\n .map((el) => el.value || el.textContent || '');\r\n\r\n if (selectedValues.length > 0) {\r\n this.value = selectedValues;\r\n }\r\n }\r\n\r\n private isSelected(value: string): boolean {\r\n return this.value.includes(value);\r\n }\r\n\r\n private dispatchChangeEvent(newValue: string[], previousValue: string[]) {\r\n this.dispatchEvent(\r\n new CustomEvent('bp-change', {\r\n detail: {\r\n value: newValue,\r\n previousValue,\r\n },\r\n bubbles: true,\r\n composed: true,\r\n })\r\n );\r\n }\r\n\r\n private handleOptionClick = (option: MultiSelectOption) => {\r\n if (this.disabled) return;\r\n\r\n const previousValue = [...this.value];\r\n let newValue: string[];\r\n\r\n if (this.isSelected(option.value)) {\r\n // Deselect — but prevent removing the last item when not clearable\r\n newValue = this.value.filter((v) => v !== option.value);\r\n if (!this.clearable && newValue.length === 0) {\r\n return;\r\n }\r\n } else {\r\n // Select (check max selections)\r\n if (this.maxSelections > 0 && this.value.length >= this.maxSelections) {\r\n return;\r\n }\r\n newValue = [...this.value, option.value];\r\n }\r\n\r\n this.value = newValue;\r\n this.dispatchChangeEvent(newValue, previousValue);\r\n };\r\n\r\n private handleRemoveTag = (value: string, event: Event) => {\r\n event.stopPropagation();\r\n if (this.disabled) return;\r\n\r\n const previousValue = [...this.value];\r\n const newValue = this.value.filter((v) => v !== value);\r\n this.value = newValue;\r\n this.dispatchChangeEvent(newValue, previousValue);\r\n };\r\n\r\n private handleClearAll = (event: Event) => {\r\n event.stopPropagation();\r\n if (this.disabled) return;\r\n\r\n const previousValue = [...this.value];\r\n const newValue: string[] = [];\r\n this.value = newValue;\r\n this.dispatchChangeEvent(newValue, previousValue);\r\n };\r\n\r\n private handleKeyDown = (event: globalThis.KeyboardEvent) => {\r\n if (this.disabled) return;\r\n\r\n const options = this.cachedOptions;\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 const option = options[this.focusedIndex];\r\n if (option) {\r\n this.handleOptionClick(option);\r\n }\r\n } else {\r\n this.handleToggle();\r\n }\r\n break;\r\n case 'Escape':\r\n event.preventDefault();\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 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 break;\r\n }\r\n };\r\n\r\n private getLabelForValue(value: string): string {\r\n const labelMap = this.computeLabelMap(this.cachedOptions);\r\n return labelMap.get(value) || value;\r\n }\r\n\r\n private renderDropdown() {\r\n const options = this.cachedOptions;\r\n\r\n return html`\r\n <div class=\"multi-select__dropdown\" part=\"dropdown\">\r\n <ul\r\n class=\"multi-select__options\"\r\n role=\"listbox\"\r\n aria-multiselectable=\"true\"\r\n >\r\n ${options.length === 0\r\n ? html`<li class=\"multi-select__option multi-select__option--empty\">\r\n No options available\r\n </li>`\r\n : repeat(\r\n options,\r\n (opt) => opt.value,\r\n (opt, index) => {\r\n const selected = this.isSelected(opt.value);\r\n const focused = index === this.focusedIndex;\r\n return html`\r\n <li\r\n class=${classMap({\r\n 'multi-select__option': true,\r\n 'multi-select__option--selected': selected,\r\n 'multi-select__option--focused': focused,\r\n })}\r\n role=\"option\"\r\n aria-selected=${selected}\r\n @click=${() => this.handleOptionClick(opt)}\r\n part=\"option ${selected ? 'option-selected' : ''}\"\r\n >\r\n <span class=\"multi-select__checkbox\">\r\n ${selected ? '\\u2713' : ''}\r\n </span>\r\n <span class=\"multi-select__option-label\"\r\n >${opt.label}</span\r\n >\r\n </li>\r\n `;\r\n }\r\n )}\r\n </ul>\r\n </div>\r\n `;\r\n }\r\n\r\n render() {\r\n const hasSelection = this.value.length > 0;\r\n\r\n return html`\r\n <div\r\n class=${classMap({\r\n 'multi-select': true,\r\n 'multi-select--open': this.isOpen,\r\n 'multi-select--disabled': this.disabled,\r\n [`multi-select--${this.size}`]: true,\r\n [`multi-select--${this.variant}`]: true,\r\n })}\r\n >\r\n <div\r\n class=\"multi-select__control\"\r\n @click=${this.handleToggle}\r\n @keydown=${this.handleKeyDown}\r\n tabindex=${this.disabled ? '-1' : '0'}\r\n role=\"combobox\"\r\n aria-haspopup=\"listbox\"\r\n aria-expanded=${this.isOpen}\r\n aria-disabled=${this.disabled}\r\n part=\"control\"\r\n >\r\n <div class=\"multi-select__value-container\">\r\n ${hasSelection\r\n ? repeat(\r\n this.value,\r\n (v) => v,\r\n (v) => html`\r\n <span class=\"multi-select__tag\" part=\"tag\">\r\n <span class=\"multi-select__tag-label\">\r\n ${this.getLabelForValue(v)}\r\n </span>\r\n ${this.clearable\r\n ? html`<button\r\n type=\"button\"\r\n class=\"multi-select__tag-remove\"\r\n @click=${(e: Event) => this.handleRemoveTag(v, e)}\r\n aria-label=\"Remove ${this.getLabelForValue(v)}\"\r\n tabindex=\"-1\"\r\n ?disabled=${this.disabled}\r\n >\r\n ×\r\n </button>`\r\n : nothing}\r\n </span>\r\n `\r\n )\r\n : html`<span class=\"multi-select__placeholder\"\r\n >${this.placeholder}</span\r\n >`}\r\n </div>\r\n\r\n <div class=\"multi-select__indicators\">\r\n ${this.clearable && hasSelection\r\n ? html`\r\n <button\r\n type=\"button\"\r\n class=\"multi-select__clear\"\r\n @click=${this.handleClearAll}\r\n aria-label=\"Clear all selections\"\r\n tabindex=\"-1\"\r\n ?disabled=${this.disabled}\r\n part=\"clear-button\"\r\n >\r\n ×\r\n </button>\r\n `\r\n : ''}\r\n <span class=\"multi-select__dropdown-indicator\" part=\"indicator\">\r\n ▼\r\n </span>\r\n </div>\r\n </div>\r\n\r\n ${this.isOpen ? this.renderDropdown() : nothing}\r\n\r\n <!-- Hidden slot for options -->\r\n <slot @slotchange=${this.handleSlotChange}></slot>\r\n\r\n <!-- Hidden inputs for form submission -->\r\n ${this.value.map(\r\n (v) => html`\r\n <input type=\"hidden\" name=\"${this.name}\" value=\"${v}\" />\r\n `\r\n )}\r\n </div>\r\n `;\r\n }\r\n}\r\n\r\ndeclare global {\r\n interface HTMLElementTagNameMap {\r\n 'bp-multi-select': BpMultiSelect;\r\n }\r\n}\r\n"],"names":["multiSelectStyles","css","BpMultiSelect","LitElement","memoizeOne","options","map","opt","event","option","previousValue","newValue","v","value","el","selectedValues","html","repeat","index","selected","focused","classMap","hasSelection","e","nothing","__decorateClass","property","booleanConverter","state","customElement"],"mappings":";;;;;;AAEO,MAAMA,IAAoBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;A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"}
|
|
@@ -0,0 +1,429 @@
|
|
|
1
|
+
import { css as h, LitElement as d, html as s, nothing as u } from "lit";
|
|
2
|
+
import { property as n, state as c, customElement as m } from "lit/decorators.js";
|
|
3
|
+
import { b } from "../shared/boolean-converter-XDGfS9LC.js";
|
|
4
|
+
const v = h`
|
|
5
|
+
/* Base styles */
|
|
6
|
+
:host {
|
|
7
|
+
display: block;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.notification {
|
|
11
|
+
display: flex;
|
|
12
|
+
align-items: flex-start;
|
|
13
|
+
gap: var(--bp-spacing-3);
|
|
14
|
+
padding: var(--bp-spacing-4);
|
|
15
|
+
background-color: var(--bp-color-surface-elevated);
|
|
16
|
+
border: var(--bp-border-width) solid var(--bp-color-border);
|
|
17
|
+
border-radius: var(--bp-border-radius-lg);
|
|
18
|
+
box-shadow: var(--bp-shadow-lg);
|
|
19
|
+
font-family: var(--bp-font-sans);
|
|
20
|
+
font-size: var(--bp-font-size-sm);
|
|
21
|
+
line-height: var(--bp-line-height-normal);
|
|
22
|
+
color: var(--bp-color-text);
|
|
23
|
+
max-width: 400px;
|
|
24
|
+
min-width: 300px;
|
|
25
|
+
animation: notification-slide-in var(--bp-duration-fast) var(--bp-ease-out);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@keyframes notification-slide-in {
|
|
29
|
+
from {
|
|
30
|
+
opacity: 0;
|
|
31
|
+
transform: translateY(calc(-1 * var(--bp-spacing-2)));
|
|
32
|
+
}
|
|
33
|
+
to {
|
|
34
|
+
opacity: 1;
|
|
35
|
+
transform: translateY(0);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
@keyframes notification-slide-out {
|
|
40
|
+
from {
|
|
41
|
+
opacity: 1;
|
|
42
|
+
transform: translateY(0);
|
|
43
|
+
}
|
|
44
|
+
to {
|
|
45
|
+
opacity: 0;
|
|
46
|
+
transform: translateY(calc(-1 * var(--bp-spacing-2)));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.notification--exiting {
|
|
51
|
+
animation: notification-slide-out var(--bp-duration-fast) var(--bp-ease-in)
|
|
52
|
+
forwards;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@media (prefers-reduced-motion: reduce) {
|
|
56
|
+
.notification {
|
|
57
|
+
animation: none;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.notification--exiting {
|
|
61
|
+
animation: none;
|
|
62
|
+
opacity: 0;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Icon */
|
|
67
|
+
.notification__icon {
|
|
68
|
+
flex-shrink: 0;
|
|
69
|
+
display: flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
justify-content: center;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.notification__icon svg {
|
|
75
|
+
width: 100%;
|
|
76
|
+
height: 100%;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* Content */
|
|
80
|
+
.notification__content {
|
|
81
|
+
flex: 1;
|
|
82
|
+
min-width: 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.notification__title {
|
|
86
|
+
font-weight: var(--bp-font-weight-semibold);
|
|
87
|
+
margin-bottom: var(--bp-spacing-1);
|
|
88
|
+
color: var(--bp-color-text-strong);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.notification__message {
|
|
92
|
+
color: var(--bp-color-text-muted);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* Action */
|
|
96
|
+
.notification__action {
|
|
97
|
+
display: flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
gap: var(--bp-spacing-1);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.notification__action:empty {
|
|
103
|
+
display: none;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Close button */
|
|
107
|
+
.notification__close {
|
|
108
|
+
flex-shrink: 0;
|
|
109
|
+
display: flex;
|
|
110
|
+
align-items: center;
|
|
111
|
+
justify-content: center;
|
|
112
|
+
width: var(--bp-spacing-11);
|
|
113
|
+
height: var(--bp-spacing-11);
|
|
114
|
+
padding: 0;
|
|
115
|
+
margin: calc(-1 * var(--bp-spacing-2));
|
|
116
|
+
background: none;
|
|
117
|
+
border: none;
|
|
118
|
+
border-radius: var(--bp-border-radius-sm);
|
|
119
|
+
color: var(--bp-color-text-muted);
|
|
120
|
+
cursor: pointer;
|
|
121
|
+
transition:
|
|
122
|
+
color var(--bp-transition-fast),
|
|
123
|
+
background-color var(--bp-transition-fast);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.notification__close:hover {
|
|
127
|
+
color: var(--bp-color-text);
|
|
128
|
+
background-color: var(--bp-color-surface-subdued);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.notification__close:focus-visible {
|
|
132
|
+
outline: var(--bp-focus-width) var(--bp-focus-style) var(--bp-color-focus);
|
|
133
|
+
outline-offset: var(--bp-focus-offset);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.notification__close svg {
|
|
137
|
+
width: var(--bp-spacing-4);
|
|
138
|
+
height: var(--bp-spacing-4);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/* Variants */
|
|
142
|
+
.notification--info {
|
|
143
|
+
border-left: var(--bp-spacing-1) solid var(--bp-color-info);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.notification--info .notification__icon {
|
|
147
|
+
color: var(--bp-color-info);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.notification--success {
|
|
151
|
+
border-left: var(--bp-spacing-1) solid var(--bp-color-success);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.notification--success .notification__icon {
|
|
155
|
+
color: var(--bp-color-success);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.notification--warning {
|
|
159
|
+
border-left: var(--bp-spacing-1) solid var(--bp-color-warning);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.notification--warning .notification__icon {
|
|
163
|
+
color: var(--bp-color-warning);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.notification--error {
|
|
167
|
+
border-left: var(--bp-spacing-1) solid var(--bp-color-error);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.notification--error .notification__icon {
|
|
171
|
+
color: var(--bp-color-error);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/* Position variants */
|
|
175
|
+
.notification--top-left,
|
|
176
|
+
.notification--top-center,
|
|
177
|
+
.notification--top-right,
|
|
178
|
+
.notification--bottom-left,
|
|
179
|
+
.notification--bottom-center,
|
|
180
|
+
.notification--bottom-right {
|
|
181
|
+
position: fixed;
|
|
182
|
+
z-index: 10000;
|
|
183
|
+
margin: var(--bp-spacing-4);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.notification--top-left {
|
|
187
|
+
top: 0;
|
|
188
|
+
left: 0;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.notification--top-center {
|
|
192
|
+
top: 0;
|
|
193
|
+
left: 50%;
|
|
194
|
+
transform: translateX(-50%);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.notification--top-right {
|
|
198
|
+
top: 0;
|
|
199
|
+
right: 0;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.notification--bottom-left {
|
|
203
|
+
bottom: 0;
|
|
204
|
+
left: 0;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.notification--bottom-center {
|
|
208
|
+
bottom: 0;
|
|
209
|
+
left: 50%;
|
|
210
|
+
transform: translateX(-50%);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.notification--bottom-right {
|
|
214
|
+
bottom: 0;
|
|
215
|
+
right: 0;
|
|
216
|
+
}
|
|
217
|
+
`;
|
|
218
|
+
var g = Object.defineProperty, _ = Object.getOwnPropertyDescriptor, o = (t, r, l, a) => {
|
|
219
|
+
for (var e = a > 1 ? void 0 : a ? _(r, l) : r, p = t.length - 1, f; p >= 0; p--)
|
|
220
|
+
(f = t[p]) && (e = (a ? f(r, l, e) : f(e)) || e);
|
|
221
|
+
return a && e && g(r, l, e), e;
|
|
222
|
+
};
|
|
223
|
+
let i = class extends d {
|
|
224
|
+
constructor() {
|
|
225
|
+
super(), this.autoCloseTimer = null, this.remainingTime = 0, this.timerPaused = !1, this.isExiting = !1, this.variant = "info", this.open = !1, this.closable = !0, this.duration = 0, this.title = "", this.message = "", this.position = "top-right";
|
|
226
|
+
}
|
|
227
|
+
updated(t) {
|
|
228
|
+
t.has("open") && (this.open ? this.handleOpen() : this.handleClose()), t.has("duration") && this.open && this.startAutoCloseTimer();
|
|
229
|
+
}
|
|
230
|
+
disconnectedCallback() {
|
|
231
|
+
super.disconnectedCallback(), this.clearAutoCloseTimer();
|
|
232
|
+
}
|
|
233
|
+
/** Show the notification */
|
|
234
|
+
show() {
|
|
235
|
+
this.open || (this.open = !0);
|
|
236
|
+
}
|
|
237
|
+
/** Hide the notification */
|
|
238
|
+
hide() {
|
|
239
|
+
this.open && (this.open = !1);
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Handles the notification opening.
|
|
243
|
+
* Dispatches bp-show event, starts auto-close timer, and manages focus.
|
|
244
|
+
*/
|
|
245
|
+
handleOpen() {
|
|
246
|
+
this.isExiting = !1, this.dispatchEvent(
|
|
247
|
+
new CustomEvent("bp-show", { bubbles: !0, composed: !0 })
|
|
248
|
+
), this.startAutoCloseTimer(), this.updateComplete.then(() => {
|
|
249
|
+
this.closable && this.shadowRoot?.querySelector(
|
|
250
|
+
".notification__close"
|
|
251
|
+
)?.focus();
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Handles the notification closing.
|
|
256
|
+
* Clears auto-close timer and dispatches bp-hide event.
|
|
257
|
+
*/
|
|
258
|
+
handleClose() {
|
|
259
|
+
this.clearAutoCloseTimer(), this.dispatchEvent(
|
|
260
|
+
new CustomEvent("bp-hide", { bubbles: !0, composed: !0 })
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Starts the auto-close timer based on the duration property.
|
|
265
|
+
* Timer can be paused/resumed with pauseAutoCloseTimer/resumeAutoCloseTimer.
|
|
266
|
+
*/
|
|
267
|
+
startAutoCloseTimer() {
|
|
268
|
+
this.clearAutoCloseTimer(), this.duration > 0 && !this.timerPaused && (this.remainingTime = this.duration, this.autoCloseTimer = window.setTimeout(() => {
|
|
269
|
+
this.hide();
|
|
270
|
+
}, this.duration));
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Clears the auto-close timer if it exists.
|
|
274
|
+
*/
|
|
275
|
+
clearAutoCloseTimer() {
|
|
276
|
+
this.autoCloseTimer && (window.clearTimeout(this.autoCloseTimer), this.autoCloseTimer = null);
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Pauses the auto-close timer when user hovers or focuses.
|
|
280
|
+
* Allows users to read content or interact with actions.
|
|
281
|
+
*/
|
|
282
|
+
pauseAutoCloseTimer() {
|
|
283
|
+
this.autoCloseTimer && this.duration > 0 && (this.timerPaused = !0, window.clearTimeout(this.autoCloseTimer), this.autoCloseTimer = null);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Resumes the auto-close timer with remaining time.
|
|
287
|
+
*/
|
|
288
|
+
resumeAutoCloseTimer() {
|
|
289
|
+
this.timerPaused && this.duration > 0 && (this.timerPaused = !1, this.autoCloseTimer = window.setTimeout(() => {
|
|
290
|
+
this.hide();
|
|
291
|
+
}, this.remainingTime));
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Handles close button click.
|
|
295
|
+
* Hides notification and dispatches bp-close event.
|
|
296
|
+
*/
|
|
297
|
+
handleCloseClick() {
|
|
298
|
+
this.hide(), this.dispatchEvent(
|
|
299
|
+
new CustomEvent("bp-close", { bubbles: !0, composed: !0 })
|
|
300
|
+
);
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Handles keyboard events.
|
|
304
|
+
* Closes notification on Escape key if closable.
|
|
305
|
+
*/
|
|
306
|
+
handleKeydown(t) {
|
|
307
|
+
t.key === "Escape" && this.closable && this.handleCloseClick();
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Returns the default icon for the notification variant.
|
|
311
|
+
* Uses the bp-icon component for consistency with the design system.
|
|
312
|
+
*/
|
|
313
|
+
getDefaultIcon() {
|
|
314
|
+
return s`<bp-icon name=${{
|
|
315
|
+
success: "check",
|
|
316
|
+
warning: "warning-circle",
|
|
317
|
+
error: "cross",
|
|
318
|
+
info: "info-circle"
|
|
319
|
+
}[this.variant]} size="md"></bp-icon>`;
|
|
320
|
+
}
|
|
321
|
+
render() {
|
|
322
|
+
return this.open ? s`
|
|
323
|
+
<div
|
|
324
|
+
class="notification notification--${this.variant} notification--${this.position} ${this.isExiting ? "notification--exiting" : "notification--entering"}"
|
|
325
|
+
part="base"
|
|
326
|
+
role="alert"
|
|
327
|
+
aria-live=${this.variant === "error" ? "assertive" : "polite"}
|
|
328
|
+
@keydown=${this.handleKeydown}
|
|
329
|
+
@mouseenter=${this.pauseAutoCloseTimer}
|
|
330
|
+
@mouseleave=${this.resumeAutoCloseTimer}
|
|
331
|
+
@focusin=${this.pauseAutoCloseTimer}
|
|
332
|
+
@focusout=${this.resumeAutoCloseTimer}
|
|
333
|
+
>
|
|
334
|
+
<div class="notification__icon" part="icon">
|
|
335
|
+
<slot name="icon">${this.getDefaultIcon()}</slot>
|
|
336
|
+
</div>
|
|
337
|
+
|
|
338
|
+
<div class="notification__content" part="content">
|
|
339
|
+
${this.title ? s`<div class="notification__title">${this.title}</div>` : u}
|
|
340
|
+
<div class="notification__message" part="message">
|
|
341
|
+
${this.message || s`<slot></slot>`}
|
|
342
|
+
</div>
|
|
343
|
+
</div>
|
|
344
|
+
|
|
345
|
+
<div class="notification__action" part="action">
|
|
346
|
+
<slot name="action"></slot>
|
|
347
|
+
</div>
|
|
348
|
+
|
|
349
|
+
${this.closable ? s`
|
|
350
|
+
<button
|
|
351
|
+
type="button"
|
|
352
|
+
class="notification__close"
|
|
353
|
+
part="close-button"
|
|
354
|
+
aria-label="Close notification"
|
|
355
|
+
@click=${this.handleCloseClick}
|
|
356
|
+
>
|
|
357
|
+
<svg
|
|
358
|
+
viewBox="0 0 24 24"
|
|
359
|
+
fill="none"
|
|
360
|
+
stroke="currentColor"
|
|
361
|
+
stroke-width="2"
|
|
362
|
+
>
|
|
363
|
+
<path d="M18 6L6 18M6 6l12 12" />
|
|
364
|
+
</svg>
|
|
365
|
+
</button>
|
|
366
|
+
` : u}
|
|
367
|
+
</div>
|
|
368
|
+
` : u;
|
|
369
|
+
}
|
|
370
|
+
};
|
|
371
|
+
i.styles = [v];
|
|
372
|
+
o([
|
|
373
|
+
n({
|
|
374
|
+
type: String,
|
|
375
|
+
reflect: !0,
|
|
376
|
+
converter: {
|
|
377
|
+
fromAttribute: (t) => t && ["info", "success", "warning", "error"].includes(t) ? t : "info"
|
|
378
|
+
}
|
|
379
|
+
})
|
|
380
|
+
], i.prototype, "variant", 2);
|
|
381
|
+
o([
|
|
382
|
+
n({ type: Boolean, reflect: !0 })
|
|
383
|
+
], i.prototype, "open", 2);
|
|
384
|
+
o([
|
|
385
|
+
n({ converter: b, reflect: !0 })
|
|
386
|
+
], i.prototype, "closable", 2);
|
|
387
|
+
o([
|
|
388
|
+
n({ type: Number })
|
|
389
|
+
], i.prototype, "duration", 2);
|
|
390
|
+
o([
|
|
391
|
+
n({ type: String })
|
|
392
|
+
], i.prototype, "title", 2);
|
|
393
|
+
o([
|
|
394
|
+
n({ type: String })
|
|
395
|
+
], i.prototype, "message", 2);
|
|
396
|
+
o([
|
|
397
|
+
n({
|
|
398
|
+
type: String,
|
|
399
|
+
converter: {
|
|
400
|
+
fromAttribute: (t) => t && [
|
|
401
|
+
"top-left",
|
|
402
|
+
"top-center",
|
|
403
|
+
"top-right",
|
|
404
|
+
"bottom-left",
|
|
405
|
+
"bottom-center",
|
|
406
|
+
"bottom-right"
|
|
407
|
+
].includes(t) ? t : "top-right"
|
|
408
|
+
}
|
|
409
|
+
})
|
|
410
|
+
], i.prototype, "position", 2);
|
|
411
|
+
o([
|
|
412
|
+
c()
|
|
413
|
+
], i.prototype, "autoCloseTimer", 2);
|
|
414
|
+
o([
|
|
415
|
+
c()
|
|
416
|
+
], i.prototype, "remainingTime", 2);
|
|
417
|
+
o([
|
|
418
|
+
c()
|
|
419
|
+
], i.prototype, "timerPaused", 2);
|
|
420
|
+
o([
|
|
421
|
+
c()
|
|
422
|
+
], i.prototype, "isExiting", 2);
|
|
423
|
+
i = o([
|
|
424
|
+
m("bp-notification")
|
|
425
|
+
], i);
|
|
426
|
+
export {
|
|
427
|
+
i as BpNotification
|
|
428
|
+
};
|
|
429
|
+
//# sourceMappingURL=notification.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification.js","sources":["../../source/components/notification/notification.style.ts","../../source/components/notification/notification.ts"],"sourcesContent":["import { css } from 'lit';\r\n\r\nexport const notificationStyles = css`\r\n /* Base styles */\r\n :host {\r\n display: block;\r\n }\r\n\r\n .notification {\r\n display: flex;\r\n align-items: flex-start;\r\n gap: var(--bp-spacing-3);\r\n padding: var(--bp-spacing-4);\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 font-family: var(--bp-font-sans);\r\n font-size: var(--bp-font-size-sm);\r\n line-height: var(--bp-line-height-normal);\r\n color: var(--bp-color-text);\r\n max-width: 400px;\r\n min-width: 300px;\r\n animation: notification-slide-in var(--bp-duration-fast) var(--bp-ease-out);\r\n }\r\n\r\n @keyframes notification-slide-in {\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 @keyframes notification-slide-out {\r\n from {\r\n opacity: 1;\r\n transform: translateY(0);\r\n }\r\n to {\r\n opacity: 0;\r\n transform: translateY(calc(-1 * var(--bp-spacing-2)));\r\n }\r\n }\r\n\r\n .notification--exiting {\r\n animation: notification-slide-out var(--bp-duration-fast) var(--bp-ease-in)\r\n forwards;\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .notification {\r\n animation: none;\r\n }\r\n\r\n .notification--exiting {\r\n animation: none;\r\n opacity: 0;\r\n }\r\n }\r\n\r\n /* Icon */\r\n .notification__icon {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n }\r\n\r\n .notification__icon svg {\r\n width: 100%;\r\n height: 100%;\r\n }\r\n\r\n /* Content */\r\n .notification__content {\r\n flex: 1;\r\n min-width: 0;\r\n }\r\n\r\n .notification__title {\r\n font-weight: var(--bp-font-weight-semibold);\r\n margin-bottom: var(--bp-spacing-1);\r\n color: var(--bp-color-text-strong);\r\n }\r\n\r\n .notification__message {\r\n color: var(--bp-color-text-muted);\r\n }\r\n\r\n /* Action */\r\n .notification__action {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--bp-spacing-1);\r\n }\r\n\r\n .notification__action:empty {\r\n display: none;\r\n }\r\n\r\n /* Close button */\r\n .notification__close {\r\n flex-shrink: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: var(--bp-spacing-11);\r\n height: var(--bp-spacing-11);\r\n padding: 0;\r\n margin: calc(-1 * var(--bp-spacing-2));\r\n background: none;\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 color var(--bp-transition-fast),\r\n background-color var(--bp-transition-fast);\r\n }\r\n\r\n .notification__close:hover {\r\n color: var(--bp-color-text);\r\n background-color: var(--bp-color-surface-subdued);\r\n }\r\n\r\n .notification__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 .notification__close svg {\r\n width: var(--bp-spacing-4);\r\n height: var(--bp-spacing-4);\r\n }\r\n\r\n /* Variants */\r\n .notification--info {\r\n border-left: var(--bp-spacing-1) solid var(--bp-color-info);\r\n }\r\n\r\n .notification--info .notification__icon {\r\n color: var(--bp-color-info);\r\n }\r\n\r\n .notification--success {\r\n border-left: var(--bp-spacing-1) solid var(--bp-color-success);\r\n }\r\n\r\n .notification--success .notification__icon {\r\n color: var(--bp-color-success);\r\n }\r\n\r\n .notification--warning {\r\n border-left: var(--bp-spacing-1) solid var(--bp-color-warning);\r\n }\r\n\r\n .notification--warning .notification__icon {\r\n color: var(--bp-color-warning);\r\n }\r\n\r\n .notification--error {\r\n border-left: var(--bp-spacing-1) solid var(--bp-color-error);\r\n }\r\n\r\n .notification--error .notification__icon {\r\n color: var(--bp-color-error);\r\n }\r\n\r\n /* Position variants */\r\n .notification--top-left,\r\n .notification--top-center,\r\n .notification--top-right,\r\n .notification--bottom-left,\r\n .notification--bottom-center,\r\n .notification--bottom-right {\r\n position: fixed;\r\n z-index: 10000;\r\n margin: var(--bp-spacing-4);\r\n }\r\n\r\n .notification--top-left {\r\n top: 0;\r\n left: 0;\r\n }\r\n\r\n .notification--top-center {\r\n top: 0;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n }\r\n\r\n .notification--top-right {\r\n top: 0;\r\n right: 0;\r\n }\r\n\r\n .notification--bottom-left {\r\n bottom: 0;\r\n left: 0;\r\n }\r\n\r\n .notification--bottom-center {\r\n bottom: 0;\r\n left: 50%;\r\n transform: translateX(-50%);\r\n }\r\n\r\n .notification--bottom-right {\r\n bottom: 0;\r\n right: 0;\r\n }\r\n`;\r\n","import { LitElement, html, nothing } from 'lit';\r\nimport { customElement, property, state } from 'lit/decorators.js';\r\nimport { notificationStyles } from './notification.style.js';\r\nimport { booleanConverter } from '../../utilities/boolean-converter.js';\r\nimport '../icon/icon.js';\r\n\r\n/**\r\n * A notification/toast component for displaying non-blocking messages.\r\n * Notifications can be dismissed manually or auto-close after a duration.\r\n *\r\n * @fires bp-close - Dispatched when the notification is closed\r\n * @fires bp-show - Dispatched when the notification becomes visible\r\n * @fires bp-hide - Dispatched when the notification is hidden\r\n *\r\n * @slot - Default slot for notification content\r\n * @slot icon - Custom icon to display\r\n * @slot action - Action buttons or links\r\n *\r\n * @csspart base - The notification container\r\n * @csspart icon - The icon container\r\n * @csspart content - The content area\r\n * @csspart message - The message text container\r\n * @csspart action - The action slot container\r\n * @csspart close-button - The close button\r\n */\r\n@customElement('bp-notification')\r\nexport class BpNotification extends LitElement {\r\n /** The notification variant */\r\n @property({\r\n type: String,\r\n reflect: true,\r\n converter: {\r\n fromAttribute: (value: string | null) => {\r\n const valid = ['info', 'success', 'warning', 'error'];\r\n return value && valid.includes(value) ? value : 'info';\r\n },\r\n },\r\n })\r\n declare variant: 'info' | 'success' | 'warning' | 'error';\r\n\r\n /** Whether the notification is visible */\r\n @property({ type: Boolean, reflect: true }) declare open: boolean;\r\n\r\n /** Whether the notification can be dismissed */\r\n @property({ converter: booleanConverter, reflect: true })\r\n declare closable: boolean;\r\n\r\n /** Duration in milliseconds before auto-close (0 = no auto-close) */\r\n @property({ type: Number }) declare duration: number;\r\n\r\n /** Title of the notification */\r\n @property({ type: String }) declare title: string;\r\n\r\n /** Message content of the notification */\r\n @property({ type: String }) declare message: string;\r\n\r\n /**\r\n * Position of the notification on screen.\r\n * Note: For multiple notifications, consider using a container component.\r\n */\r\n @property({\r\n type: String,\r\n converter: {\r\n fromAttribute: (value: string | null) => {\r\n const valid = [\r\n 'top-left',\r\n 'top-center',\r\n 'top-right',\r\n 'bottom-left',\r\n 'bottom-center',\r\n 'bottom-right',\r\n ];\r\n return value && valid.includes(value) ? value : 'top-right';\r\n },\r\n },\r\n })\r\n declare position:\r\n | 'top-left'\r\n | 'top-center'\r\n | 'top-right'\r\n | 'bottom-left'\r\n | 'bottom-center'\r\n | 'bottom-right';\r\n\r\n @state() private autoCloseTimer: number | null = null;\r\n @state() private remainingTime: number = 0;\r\n @state() private timerPaused: boolean = false;\r\n @state() private isExiting: boolean = false;\r\n\r\n static styles = [notificationStyles];\r\n\r\n constructor() {\r\n super();\r\n this.variant = 'info';\r\n this.open = false;\r\n this.closable = true;\r\n this.duration = 0;\r\n this.title = '';\r\n this.message = '';\r\n this.position = 'top-right';\r\n }\r\n\r\n updated(changedProperties: Map<string, unknown>) {\r\n if (changedProperties.has('open')) {\r\n if (this.open) {\r\n this.handleOpen();\r\n } else {\r\n this.handleClose();\r\n }\r\n }\r\n\r\n if (changedProperties.has('duration') && this.open) {\r\n this.startAutoCloseTimer();\r\n }\r\n }\r\n\r\n disconnectedCallback() {\r\n super.disconnectedCallback();\r\n this.clearAutoCloseTimer();\r\n }\r\n\r\n /** Show the notification */\r\n show() {\r\n if (this.open) return;\r\n this.open = true;\r\n }\r\n\r\n /** Hide the notification */\r\n hide() {\r\n if (!this.open) return;\r\n this.open = false;\r\n }\r\n\r\n /**\r\n * Handles the notification opening.\r\n * Dispatches bp-show event, starts auto-close timer, and manages focus.\r\n */\r\n private handleOpen() {\r\n this.isExiting = false;\r\n this.dispatchEvent(\r\n new CustomEvent('bp-show', { bubbles: true, composed: true })\r\n );\r\n this.startAutoCloseTimer();\r\n\r\n // Focus close button for accessibility\r\n this.updateComplete.then(() => {\r\n if (this.closable) {\r\n const closeButton = this.shadowRoot?.querySelector(\r\n '.notification__close'\r\n ) as HTMLElement;\r\n closeButton?.focus();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Handles the notification closing.\r\n * Clears auto-close timer and dispatches bp-hide event.\r\n */\r\n private handleClose() {\r\n this.clearAutoCloseTimer();\r\n this.dispatchEvent(\r\n new CustomEvent('bp-hide', { bubbles: true, composed: true })\r\n );\r\n }\r\n\r\n /**\r\n * Starts the auto-close timer based on the duration property.\r\n * Timer can be paused/resumed with pauseAutoCloseTimer/resumeAutoCloseTimer.\r\n */\r\n private startAutoCloseTimer() {\r\n this.clearAutoCloseTimer();\r\n\r\n if (this.duration > 0 && !this.timerPaused) {\r\n this.remainingTime = this.duration;\r\n this.autoCloseTimer = window.setTimeout(() => {\r\n this.hide();\r\n }, this.duration);\r\n }\r\n }\r\n\r\n /**\r\n * Clears the auto-close timer if it exists.\r\n */\r\n private clearAutoCloseTimer() {\r\n if (this.autoCloseTimer) {\r\n window.clearTimeout(this.autoCloseTimer);\r\n this.autoCloseTimer = null;\r\n }\r\n }\r\n\r\n /**\r\n * Pauses the auto-close timer when user hovers or focuses.\r\n * Allows users to read content or interact with actions.\r\n */\r\n private pauseAutoCloseTimer() {\r\n if (this.autoCloseTimer && this.duration > 0) {\r\n this.timerPaused = true;\r\n window.clearTimeout(this.autoCloseTimer);\r\n this.autoCloseTimer = null;\r\n }\r\n }\r\n\r\n /**\r\n * Resumes the auto-close timer with remaining time.\r\n */\r\n private resumeAutoCloseTimer() {\r\n if (this.timerPaused && this.duration > 0) {\r\n this.timerPaused = false;\r\n this.autoCloseTimer = window.setTimeout(() => {\r\n this.hide();\r\n }, this.remainingTime);\r\n }\r\n }\r\n\r\n /**\r\n * Handles close button click.\r\n * Hides notification and dispatches bp-close event.\r\n */\r\n private handleCloseClick() {\r\n this.hide();\r\n this.dispatchEvent(\r\n new CustomEvent('bp-close', { bubbles: true, composed: true })\r\n );\r\n }\r\n\r\n /**\r\n * Handles keyboard events.\r\n * Closes notification on Escape key if closable.\r\n */\r\n private handleKeydown(event: KeyboardEvent) {\r\n if (event.key === 'Escape' && this.closable) {\r\n this.handleCloseClick();\r\n }\r\n }\r\n\r\n /**\r\n * Returns the default icon for the notification variant.\r\n * Uses the bp-icon component for consistency with the design system.\r\n */\r\n private getDefaultIcon() {\r\n const iconMap = {\r\n success: 'check',\r\n warning: 'warning-circle',\r\n error: 'cross',\r\n info: 'info-circle',\r\n } as const;\r\n return html`<bp-icon name=${iconMap[this.variant]} size=\"md\"></bp-icon>`;\r\n }\r\n\r\n render() {\r\n if (!this.open) {\r\n return nothing;\r\n }\r\n\r\n return html`\r\n <div\r\n class=\"notification notification--${this.variant} notification--${this\r\n .position} ${this.isExiting\r\n ? 'notification--exiting'\r\n : 'notification--entering'}\"\r\n part=\"base\"\r\n role=\"alert\"\r\n aria-live=${this.variant === 'error' ? 'assertive' : 'polite'}\r\n @keydown=${this.handleKeydown}\r\n @mouseenter=${this.pauseAutoCloseTimer}\r\n @mouseleave=${this.resumeAutoCloseTimer}\r\n @focusin=${this.pauseAutoCloseTimer}\r\n @focusout=${this.resumeAutoCloseTimer}\r\n >\r\n <div class=\"notification__icon\" part=\"icon\">\r\n <slot name=\"icon\">${this.getDefaultIcon()}</slot>\r\n </div>\r\n\r\n <div class=\"notification__content\" part=\"content\">\r\n ${this.title\r\n ? html`<div class=\"notification__title\">${this.title}</div>`\r\n : nothing}\r\n <div class=\"notification__message\" part=\"message\">\r\n ${this.message || html`<slot></slot>`}\r\n </div>\r\n </div>\r\n\r\n <div class=\"notification__action\" part=\"action\">\r\n <slot name=\"action\"></slot>\r\n </div>\r\n\r\n ${this.closable\r\n ? html`\r\n <button\r\n type=\"button\"\r\n class=\"notification__close\"\r\n part=\"close-button\"\r\n aria-label=\"Close notification\"\r\n @click=${this.handleCloseClick}\r\n >\r\n <svg\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n stroke=\"currentColor\"\r\n stroke-width=\"2\"\r\n >\r\n <path d=\"M18 6L6 18M6 6l12 12\" />\r\n </svg>\r\n </button>\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-notification': BpNotification;\r\n }\r\n}\r\n"],"names":["notificationStyles","css","BpNotification","LitElement","changedProperties","event","html","nothing","__decorateClass","property","value","booleanConverter","state","customElement"],"mappings":"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"}
|