/** * SearchSelectModal Component * * Reusable bottom sheet modal for searching and selecting items. * Works correctly with iPhone Dynamic Island by using bottom sheet pattern. * * Usage: * * * */ export default { name: 'SearchSelectModal', emits: ['select', 'close', 'update:modelValue'], props: { show: { type: Boolean, default: false }, title: { type: String, default: 'Auswählen' }, searchable: { type: Boolean, default: false }, searchPlaceholder: { type: String, default: 'Suchen...' }, modelValue: { type: String, default: '' }, items: { type: Array, default: () => [] }, loading: { type: Boolean, default: false }, emptyText: { type: String, default: 'Keine Ergebnisse gefunden' }, emptyIcon: { type: String, default: 'search' // search, users, box, list }, selectedId: { type: [String, Number], default: null }, itemKey: { type: String, default: 'id' }, showNoneOption: { type: Boolean, default: false }, noneOptionText: { type: String, default: 'Keine Auswahl' } }, setup(props, { emit, slots }) { const { ref, computed, watch } = Vue; const searchInput = ref(null); // Focus search input when modal opens watch(() => props.show, (newVal) => { if (newVal && props.searchable) { setTimeout(() => { searchInput.value?.focus(); }, 100); } }); const updateSearch = (event) => { emit('update:modelValue', event.target.value); }; const selectItem = (item) => { emit('select', item); }; const selectNone = () => { emit('select', null); }; const close = () => { emit('close'); }; const isSelected = (item) => { if (props.selectedId === null || props.selectedId === undefined) return false; return item[props.itemKey] === props.selectedId; }; // Icons for empty states const emptyIcons = { search: ``, users: ``, box: ``, list: `` }; const getEmptyIcon = computed(() => { return emptyIcons[props.emptyIcon] || emptyIcons.search; }); return { searchInput, updateSearch, selectItem, selectNone, close, isSelected, getEmptyIcon }; }, template: `

{{ title }}

{{ emptyText }}

` };