UNPKG

@scania/tegel

Version:
305 lines (304 loc) 14 kB
function setupOptionTabindex(container, selector = '.tl-dropdown__option', disableCheckboxes = false) { container.querySelectorAll(selector).forEach((option) => { const isDisabled = option.classList.contains('tl-dropdown__option--disabled'); option.setAttribute('tabindex', isDisabled ? '-1' : '0'); if (disableCheckboxes) { const checkbox = option.querySelector('.tl-checkbox__input'); if (checkbox) checkbox.setAttribute('tabindex', '-1'); } }); } function setupClickOutside(root, closeCallback) { document.addEventListener('click', (e) => { if (!root.contains(e.target)) closeCallback(); }); root.addEventListener('focusout', (e) => { setTimeout(() => { if (!root.contains(e.relatedTarget)) closeCallback(); }, 20); }); } function handleKeyboardSelection(e, selector, callback) { var _a; if (e.key === 'Enter' || e.key === ' ') { const focusedOption = (_a = document.activeElement) === null || _a === void 0 ? void 0 : _a.closest(selector); if (focusedOption) { e.preventDefault(); callback(focusedOption); } } } function createToggleDropdown(trigger) { return () => { const isOpen = trigger.getAttribute('aria-expanded') === 'true'; trigger.setAttribute('aria-expanded', isOpen ? 'false' : 'true'); }; } function createCloseDropdown(trigger) { return () => trigger.setAttribute('aria-expanded', 'false'); } function getSelectedCheckboxLabels(container) { return Array.from(container.querySelectorAll('.tl-checkbox__input:checked')) .map((checkbox) => { var _a, _b; const label = (_a = checkbox.closest('.tl-dropdown__option')) === null || _a === void 0 ? void 0 : _a.querySelector('.tl-checkbox__label'); return ((_b = label === null || label === void 0 ? void 0 : label.textContent) === null || _b === void 0 ? void 0 : _b.trim()) || ''; }) .filter(Boolean) .join(', '); } function setupInputWrapperToggle(inputWrapper, input, openDropdown, closeDropdown, filterOptions) { inputWrapper === null || inputWrapper === void 0 ? void 0 : inputWrapper.addEventListener('mousedown', (e) => { const target = e.target; if (target === input || target.closest('.tl-dropdown__input-clear') || input.disabled) return; e.preventDefault(); e.stopPropagation(); const isOpen = input.getAttribute('aria-expanded') === 'true'; if (isOpen) { closeDropdown(); input.blur(); } else { openDropdown(); input.focus(); filterOptions(); } }); } function setupClearButton(clearButton, callback) { clearButton === null || clearButton === void 0 ? void 0 : clearButton.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); callback(); }); } function createUpdateClearButtonTabindex(input, clearButton) { return () => { const isVisible = input.getAttribute('aria-expanded') === 'true' && input.value.trim() !== ''; clearButton === null || clearButton === void 0 ? void 0 : clearButton.setAttribute('tabindex', isVisible ? '0' : '-1'); }; } function setupInputEvents(input, openDropdown, filterOptions, updateClearButtonTabindex, getInitialValue) { input.addEventListener('focus', () => { openDropdown(); const initialValue = getInitialValue === null || getInitialValue === void 0 ? void 0 : getInitialValue(); if (initialValue) input.value = ''; filterOptions(); updateClearButtonTabindex(); }); input.addEventListener('input', () => { filterOptions(); updateClearButtonTabindex(); }); input.addEventListener('keydown', (e) => { if (e.key === 'Tab') updateClearButtonTabindex(); }); } function setupListClickHandler(list, selector, callback, preventDefault = false) { list.addEventListener('click', (e) => { const clickedOption = e.target.closest(selector); if (clickedOption) { if (preventDefault) e.preventDefault(); callback(clickedOption); } }); } function createCheckboxToggleHandler(updateDisplay) { return (option) => { const checkbox = option.querySelector('.tl-checkbox__input'); if (checkbox) { checkbox.checked = !checkbox.checked; option.classList.toggle('tl-dropdown__option--selected', checkbox.checked); updateDisplay(); const changeEvent = new Event('change', { bubbles: true }); checkbox.dispatchEvent(changeEvent); } }; } function setupButtonDropdownEvents(button, toggleDropdown, root, closeDropdown) { button.addEventListener('click', (e) => { e.stopPropagation(); toggleDropdown(); }); setupClickOutside(root, closeDropdown); } export function tlDropdownSingleScriptDemo(menuId) { const list = document.getElementById(menuId); if (!list) return; const root = list.closest('.tl-dropdown'); const button = root === null || root === void 0 ? void 0 : root.querySelector('.tl-dropdown__button'); const textDisplay = root === null || root === void 0 ? void 0 : root.querySelector('.tl-dropdown__text'); if (!root || !button) return; setupOptionTabindex(list); const toggleDropdown = createToggleDropdown(button); const closeDropdown = createCloseDropdown(button); const selectOption = (selectedOption) => { var _a; list.querySelectorAll('.tl-dropdown__option').forEach((option) => { option.classList.remove('tl-dropdown__option--selected'); }); selectedOption.classList.add('tl-dropdown__option--selected'); if (textDisplay) textDisplay.textContent = ((_a = selectedOption.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || ''; closeDropdown(); button.focus(); }; setupButtonDropdownEvents(button, toggleDropdown, root, closeDropdown); setupListClickHandler(list, '.tl-dropdown__option:not(.tl-dropdown__option--disabled)', selectOption); list.addEventListener('keydown', (e) => handleKeyboardSelection(e, '.tl-dropdown__option:not(.tl-dropdown__option--disabled)', selectOption)); } export function tlDropdownMultiScriptDemo(menuId) { const list = document.getElementById(menuId); if (!list) return; const root = list.closest('.tl-dropdown'); const button = root === null || root === void 0 ? void 0 : root.querySelector('.tl-dropdown__button'); const textDisplay = root === null || root === void 0 ? void 0 : root.querySelector('.tl-dropdown__text'); if (!root || !button) return; setupOptionTabindex(list, '.tl-dropdown__option', true); const toggleDropdown = createToggleDropdown(button); const closeDropdown = createCloseDropdown(button); const updateDisplay = () => { if (textDisplay) textDisplay.textContent = getSelectedCheckboxLabels(list); }; const handleOptionToggle = createCheckboxToggleHandler(updateDisplay); setupButtonDropdownEvents(button, toggleDropdown, root, closeDropdown); setupListClickHandler(list, '.tl-dropdown__option:not(.tl-dropdown__option--disabled)', handleOptionToggle, true); list.addEventListener('keydown', (e) => handleKeyboardSelection(e, '.tl-dropdown__option:not(.tl-dropdown__option--disabled)', handleOptionToggle)); } export function tlDropdownFilterSingleScriptDemo(listId, inputId) { const list = document.getElementById(listId); const input = document.getElementById(inputId); if (!list || !input) return; const root = list.closest('.tl-dropdown'); const inputWrapper = input.parentElement; const clearButton = inputWrapper === null || inputWrapper === void 0 ? void 0 : inputWrapper.querySelector('.tl-dropdown__input-clear'); const noResultMessage = list.querySelector('.tl-dropdown__option--no-result'); const options = Array.from(list.querySelectorAll('.tl-dropdown__option:not(.tl-dropdown__option--no-result)')); setupOptionTabindex(list, '.tl-dropdown__option:not(.tl-dropdown__option--no-result)'); if (noResultMessage) noResultMessage.setAttribute('tabindex', '-1'); let selectedValue = ''; const openDropdown = () => input.setAttribute('aria-expanded', 'true'); const closeDropdown = createCloseDropdown(input); const updateClearButtonTabindex = createUpdateClearButtonTabindex(input, clearButton); const filterOptions = () => { const searchQuery = input.value.toLowerCase().trim(); let visibleCount = 0; options.forEach((option) => { var _a; const optionText = ((_a = option.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || ''; const isVisible = !searchQuery || optionText.toLowerCase().includes(searchQuery); option.style.display = isVisible ? '' : 'none'; if (isVisible) visibleCount++; }); const showNoResults = !!searchQuery && visibleCount === 0; if (noResultMessage) { noResultMessage.style.display = showNoResults ? '' : 'none'; } }; const selectOption = (selectedOption) => { var _a; options.forEach((option) => { option.classList.remove('tl-dropdown__option--selected'); }); selectedOption.classList.add('tl-dropdown__option--selected'); selectedValue = ((_a = selectedOption.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || ''; input.value = selectedValue; input.blur(); }; const handleClearButton = () => { selectedValue = ''; input.value = ''; input.focus(); filterOptions(); updateClearButtonTabindex(); }; setupClearButton(clearButton, handleClearButton); setupInputWrapperToggle(inputWrapper, input, openDropdown, closeDropdown, filterOptions); setupInputEvents(input, openDropdown, filterOptions, updateClearButtonTabindex, () => selectedValue); setupListClickHandler(list, '.tl-dropdown__option:not(.tl-dropdown__option--no-result):not(.tl-dropdown__option--disabled)', selectOption, true); root === null || root === void 0 ? void 0 : root.addEventListener('focusout', (e) => { setTimeout(() => { const newFocus = e.relatedTarget || document.activeElement; const isClearButton = clearButton && newFocus === clearButton; if (!root.contains(newFocus) && !isClearButton) { closeDropdown(); if (selectedValue) input.value = selectedValue; } }, 20); }); filterOptions(); updateClearButtonTabindex(); } export function tlDropdownFilterMultiScriptDemo(listId, inputId) { const list = document.getElementById(listId); const input = document.getElementById(inputId); if (!list || !input) return; const root = list.closest('.tl-dropdown'); const inputWrapper = input.parentElement; const clearButton = inputWrapper === null || inputWrapper === void 0 ? void 0 : inputWrapper.querySelector('.tl-dropdown__input-clear'); const options = Array.from(list.querySelectorAll('.tl-dropdown__option')); setupOptionTabindex(list, '.tl-dropdown__option', true); const openDropdown = () => input.setAttribute('aria-expanded', 'true'); const closeDropdown = createCloseDropdown(input); const updateClearButtonTabindex = createUpdateClearButtonTabindex(input, clearButton); const getSelectedValues = () => getSelectedCheckboxLabels(list); const filterOptions = () => { const searchQuery = input.value.toLowerCase().trim(); options.forEach((option) => { var _a; const optionText = ((_a = option.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || ''; const isVisible = !searchQuery || optionText.toLowerCase().includes(searchQuery); option.style.display = isVisible ? '' : 'none'; }); }; const updateDisplay = () => { input.value = getSelectedValues(); updateClearButtonTabindex(); }; const handleClearButton = () => { list.querySelectorAll('.tl-checkbox__input:checked').forEach((cb) => { var _a; cb.checked = false; (_a = cb.closest('.tl-dropdown__option')) === null || _a === void 0 ? void 0 : _a.classList.remove('tl-dropdown__option--selected'); }); input.value = ''; input.focus(); filterOptions(); updateClearButtonTabindex(); }; const handleOptionToggle = createCheckboxToggleHandler(updateDisplay); setupClearButton(clearButton, handleClearButton); setupInputWrapperToggle(inputWrapper, input, openDropdown, closeDropdown, filterOptions); setupInputEvents(input, openDropdown, filterOptions, updateClearButtonTabindex, getSelectedValues); setupListClickHandler(list, '.tl-dropdown__option:not(.tl-dropdown__option--disabled)', handleOptionToggle, true); list.addEventListener('keydown', (e) => handleKeyboardSelection(e, '.tl-dropdown__option:not(.tl-dropdown__option--disabled)', handleOptionToggle)); root === null || root === void 0 ? void 0 : root.addEventListener('focusout', (e) => { setTimeout(() => { const newFocus = e.relatedTarget || document.activeElement; const isClearButton = clearButton && newFocus === clearButton; if (!root.contains(newFocus) && !isClearButton) { closeDropdown(); input.value = getSelectedValues(); } }, 20); }); filterOptions(); updateClearButtonTabindex(); }