PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.1
Tutor LMS – eLearning and online course solution v4.0.1
4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / assets / js / lazy-chunks / tutor-select.js
tutor / assets / js / lazy-chunks Last commit date
tutor-calendar.js 5 days ago tutor-chart-js.js 5 days ago tutor-coupon-main-content.js 5 days ago tutor-course-builder-additional.js 5 days ago tutor-course-builder-basic.js 5 days ago tutor-course-builder-curriculum.js 5 days ago tutor-course-builder-icon.js 5 days ago tutor-dnd-kit.js 5 days ago tutor-file-uploader.js 5 days ago tutor-form.js 5 days ago tutor-react-datepicker.js 5 days ago tutor-select.js 5 days ago tutor-time-input.js 5 days ago
tutor-select.js
46 lines
1 "use strict";(self["webpackChunktutor"]=self["webpackChunktutor"]||[]).push([["855"],{35293:function(e,t,i){i.d(t,{selectMeta:()=>a});/* import */var s=i(93640);/* import */var l=i(41147);/* import */var n=i(14206);/**
2 * Tutor Select Component
3 *
4 * @package Tutor\Core
5 * @since 4.0.0
6 */var r=function(){var e=arguments.length>0&&arguments[0]!==void 0?arguments[0]:{};var t={isOpen:false,searchQuery:"",highlightedIndex:-1,selectedValues:new Set,isLoading:false,asyncOptions:[],dropdownPosition:"bottom",isFocused:false};var i;return(0,n._)((0,l._)({// Props with defaults
7 options:e.options||[],groups:e.groups||[],multiple:e.multiple||false,searchable:e.searchable||false,clearable:e.clearable||false,disabled:e.disabled||false,loading:e.loading||false,closeOnSelect:(i=e.closeOnSelect)!==null&&i!==void 0?i:!e.multiple,placeholder:e.placeholder||"Select...",searchPlaceholder:e.searchPlaceholder||"Search...",emptyMessage:e.emptyMessage||"No options found",loadingMessage:e.loadingMessage||"Loading...",maxHeight:e.maxHeight||280,name:e.name||"",required:e.required||false,maxSelections:e.maxSelections},t),{_boundReposition:null,// Computed
8 get allOptions(){if(this.groups.length>0){return this.groups.flatMap(e=>e.options)}return[...this.options,...this.asyncOptions]},get filteredOptions(){var r=this.searchQuery.toLowerCase().trim();if(!r)return this.allOptions;return this.allOptions.filter(e=>{var t;return e.label.toLowerCase().includes(r)||((t=e.description)===null||t===void 0?void 0:t.toLowerCase().includes(r))})},get filteredGroups(){if(this.groups.length===0)return[];var a=this.searchQuery.toLowerCase().trim();if(!a)return this.groups;return this.groups.map(e=>(0,n._)((0,l._)({},e),{options:e.options.filter(e=>{var t;return e.label.toLowerCase().includes(a)||((t=e.description)===null||t===void 0?void 0:t.toLowerCase().includes(a))})})).filter(e=>e.options.length>0)},get hasGroups(){return this.groups.length>0},get selectedOptions(){return this.allOptions.filter(e=>this.selectedValues.has(e.value))},get displayValue(){if(this.selectedValues.size===0)return this.placeholder;if(this.multiple){var o=this.selectedValues.size;if(o===1){var h=this.selectedOptions[0];var d;return h?(d=h.display_label)!==null&&d!==void 0?d:h.label:this.placeholder}return"".concat(o," selected")}var u=this.selectedOptions[0];var c;return u?(c=u.display_label)!==null&&c!==void 0?c:u.label:this.placeholder},get canClear(){return this.clearable&&this.selectedValues.size>0&&!this.disabled},get isMaxSelectionsReached(){return this.multiple&&this.maxSelections!==undefined&&this.selectedValues.size>=this.maxSelections},// Lifecycle
9 init(){this.initializeValue();this.setupFormIntegration();this.setupKeyboardNavigation();this.syncHiddenInput();this._boundReposition=this.calculateDropdownPosition.bind(this)},destroy(){// Cleanup
10 if(this._boundReposition){window.removeEventListener("resize",this._boundReposition);window.removeEventListener("scroll",this._boundReposition)}},// Initialization
11 initializeValue(){var t;var i=(t=e.value)!==null&&t!==void 0?t:e.defaultValue;if(i===undefined||i===null)return;if(Array.isArray(i)){this.selectedValues=new Set(i)}else{this.selectedValues=new Set([i])}},setupFormIntegration(){if(!this.name)return;var e=this.$el;var t=e.closest('form[x-data*="tutorForm"], form[x-data*="form("]');if(t){try{var i=window.Alpine;// eslint-disable-next-line @typescript-eslint/no-explicit-any
12 var s=i===null||i===void 0?void 0:i.$data(t);if(s&&typeof s.register==="function"){var l;// Build validation rules
13 // eslint-disable-next-line @typescript-eslint/no-explicit-any
14 var n={};if(this.required){n.required=this.required}// Register with form
15 // eslint-disable-next-line @typescript-eslint/no-explicit-any
16 s.register(this.name,n);// If form already has a value for this field (e.g. from reset() called earlier), sync it TO this component
17 var r=(l=s.values)===null||l===void 0?void 0:l[this.name];if(r!==undefined&&r!==null&&r!==""){if(Array.isArray(r)){this.selectedValues=new Set(r)}else{this.selectedValues=new Set([r])}this.syncHiddenInput()}else{// Otherwise, set form value from component's initial state
18 var a=this.getCurrentValue();s.setValue(this.name,a!==null&&a!==void 0?a:"",{shouldValidate:false})}// Watch for external form changes
19 // eslint-disable-next-line @typescript-eslint/no-explicit-any
20 var o=this;if(o.$watch){// eslint-disable-next-line @typescript-eslint/no-explicit-any
21 o.$watch("values.".concat(this.name),e=>{var t=this.getCurrentValue();var i=Array.isArray(e)?JSON.stringify([...e].sort())===JSON.stringify(Array.isArray(t)?[...t].sort():[t]):String(e)===String(t);if(!i){if(Array.isArray(e)){this.selectedValues=new Set(e)}else if(e===null||e===undefined||e===""){this.selectedValues.clear()}else{this.selectedValues=new Set([e])}this.syncHiddenInput()}})}}}catch(e){// eslint-disable-next-line no-console
22 console.warn("Failed to integrate with form:",e)}}},setupKeyboardNavigation(){var e=this.$el;e.addEventListener("keydown",e=>{if(this.disabled)return;this.handleKeyDown(e)})},// Actions
23 open(){return(0,s._)(function*(){var t;if(this.disabled||this.isOpen)return;this.isOpen=true;this.isFocused=true;(t=e.onOpen)===null||t===void 0?void 0:t.call(e);// Wait for dropdown to render, then calculate position
24 yield this.nextTick();this.calculateDropdownPosition();// Listen for resize/scroll to update position
25 if(this._boundReposition){window.addEventListener("resize",this._boundReposition);window.addEventListener("scroll",this._boundReposition,{passive:true})}// Focus search input if searchable
26 if(this.searchable){this.focusSearchInput()}// Scroll to selected option
27 this.scrollToSelected()}).call(this)},close(){var t;if(!this.isOpen)return;this.isOpen=false;this.searchQuery="";this.highlightedIndex=-1;(t=e.onClose)===null||t===void 0?void 0:t.call(e);if(this._boundReposition){window.removeEventListener("resize",this._boundReposition);window.removeEventListener("scroll",this._boundReposition)}},toggle(){if(this.isOpen){this.close()}else{this.open()}},selectOption(e){return(0,s._)(function*(){if(e.disabled)return;if(this.multiple){this.toggleMultipleSelection(e)}else{this.setSingleSelection(e)}this.notifyChange();this.syncHiddenInput();this.updateFormValue();if(this.closeOnSelect){this.close()}}).call(this)},toggleMultipleSelection(e){if(this.selectedValues.has(e.value)){this.selectedValues.delete(e.value)}else{if(this.isMaxSelectionsReached)return;this.selectedValues.add(e.value)}},setSingleSelection(e){this.selectedValues.clear();this.selectedValues.add(e.value)},deselectOption(e,t){t===null||t===void 0?void 0:t.stopPropagation();this.selectedValues.delete(e.value);this.notifyChange();this.syncHiddenInput();this.updateFormValue()},clear(e){e===null||e===void 0?void 0:e.stopPropagation();this.selectedValues.clear();this.notifyChange();this.syncHiddenInput();this.updateFormValue()},handleSearch(t){return(0,s._)(function*(){this.searchQuery=t;this.highlightedIndex=0;if(e.onSearch){this.isLoading=true;try{var i=e.onSearch(t);if(i instanceof Promise){var s=yield i;this.asyncOptions=s||[]}}finally{this.isLoading=false}}}).call(this)},// Keyboard Navigation
28 handleKeyDown(e){var t={Enter:()=>this.handleEnterKey(e)," ":()=>this.handleSpaceKey(e),Escape:()=>this.close(),ArrowDown:()=>this.handleArrowDown(e),ArrowUp:()=>this.handleArrowUp(e),Home:()=>this.handleHomeKey(e),End:()=>this.handleEndKey(e),Tab:()=>this.handleTabKey(e),Backspace:()=>this.handleBackspaceKey(e)};var i=t[e.key];if(i){i()}},handleEnterKey(e){e.preventDefault();if(!this.isOpen){this.open();return}if(this.highlightedIndex>=0){var t=this.filteredOptions[this.highlightedIndex];if(t){this.selectOption(t)}}},handleSpaceKey(e){// Only toggle if not in search input
29 var t=e.target;if(t.tagName==="INPUT")return;e.preventDefault();if(!this.isOpen){this.open()}},handleArrowDown(e){e.preventDefault();if(!this.isOpen){this.open();return}this.moveHighlight(1)},handleArrowUp(e){e.preventDefault();if(!this.isOpen){this.open();return}this.moveHighlight(-1)},handleHomeKey(e){e.preventDefault();this.highlightedIndex=this.findNextEnabledIndex(0,1);this.scrollToHighlighted()},handleEndKey(e){e.preventDefault();this.highlightedIndex=this.findNextEnabledIndex(this.filteredOptions.length-1,-1);this.scrollToHighlighted()},// eslint-disable-next-line @typescript-eslint/no-unused-vars
30 handleTabKey(e){if(this.isOpen){this.close()}},handleBackspaceKey(e){// Remove last selected item if search is empty
31 var t=e.target;if(t.tagName==="INPUT"&&t.value===""&&this.multiple){var i=this.selectedOptions[this.selectedOptions.length-1];if(i){this.deselectOption(i)}}},moveHighlight(e){var t=this.filteredOptions;if(t.length===0)return;var i=this.highlightedIndex+e;i=this.findNextEnabledIndex(i,e);if(i>=0&&i<t.length){this.highlightedIndex=i;this.scrollToHighlighted()}},findNextEnabledIndex(e,t){var i=this.filteredOptions;var s=e;while(s>=0&&s<i.length){var l;if(!((l=i[s])===null||l===void 0?void 0:l.disabled)){return s}s+=t}return-1},// Helpers
32 isSelected(e){return this.selectedValues.has(e.value)},isHighlighted(e){return this.highlightedIndex===e},getCurrentValue(){if(this.selectedValues.size===0)return null;if(this.multiple){return Array.from(this.selectedValues)}return Array.from(this.selectedValues)[0]},notifyChange(){var t=this.getCurrentValue();if(t!==null){var i;(i=e.onChange)===null||i===void 0?void 0:i.call(e,t)}},updateFormValue(){if(!this.name)return;var e=this.$el;var t=e.closest('form[x-data*="tutorForm"], form[x-data*="form("]');if(t){try{var i;// eslint-disable-next-line @typescript-eslint/no-explicit-any
33 var s=(i=window.Alpine)===null||i===void 0?void 0:i.$data(t);if(s&&typeof s.setValue==="function"){var l=this.getCurrentValue();// Always update, even if null (for required validation)
34 s.setValue(this.name,l!==null&&l!==void 0?l:"",{shouldValidate:true,shouldTouch:true,shouldDirty:true})}}catch(e){// eslint-disable-next-line no-console
35 console.warn("Failed to update form value:",e)}}},syncHiddenInput(){if(!this.name)return;// Always get the root select container (not the clicked element)
36 var e=this.$el;// If $el is not the root select container, find it
37 if(!e.classList.contains("tutor-select")){var t=e.closest(".tutor-select");if(t){e=t}}var i=this.getCurrentValue();if(this.multiple&&Array.isArray(i)){// Remove ALL existing hidden inputs for this field
38 e.querySelectorAll('input[type="hidden"][name^="'.concat(this.name,'"]')).forEach(e=>e.remove());// Create hidden input for each value
39 i.forEach((t,i)=>{var s=document.createElement("input");s.type="hidden";s.name="".concat(this.name,"[").concat(i,"]");s.value=String(t);e.appendChild(s)})}else{// Single value - remove all existing first, then create one
40 e.querySelectorAll('input[type="hidden"][name="'.concat(this.name,'"]')).forEach(e=>e.remove());var s=document.createElement("input");s.type="hidden";s.name=this.name;s.value=i!==null?String(i):"";e.appendChild(s)}},calculateDropdownPosition(){var e=this.$el;// Find the root select container
41 var t=e;if(!e.classList.contains("tutor-select")){var i=e.closest(".tutor-select");if(i)t=i}var s=t.querySelector("[data-select-trigger]");if(!s){return}var l=s.getBoundingClientRect();var n=window.innerHeight;var r=n-l.bottom;var a=l.top;// Calculate estimated dropdown height
42 // Account for: options + search box (if searchable) + padding
43 var o=44;// Height per option
44 var h=this.searchable?60:0;var d=16;var u=this.filteredOptions.length||this.allOptions.length;var c=Math.min(this.maxHeight,u*o+h+d);// Add some buffer space (8px)
45 var p=8;// Prefer bottom, but flip to top if not enough space below AND more space above
46 if(r<c+p&&a>r){this.dropdownPosition="top"}else{this.dropdownPosition="bottom"}},nextTick(){return(0,s._)(function*(){return new Promise(e=>{var t=this;if(t.$nextTick){t.$nextTick(()=>e(undefined))}else{setTimeout(()=>e(undefined),0)}})}).call(this)},focusSearchInput(){var e=this.$el;var t=e.querySelector("[data-select-search]");if(t){t.focus()}},scrollToSelected(){var e=this.filteredOptions.findIndex(e=>this.isSelected(e));if(e>=0){this.highlightedIndex=e;this.scrollToHighlighted()}},scrollToHighlighted(){this.nextTick().then(()=>{var e=this.$el;var t=e.querySelector("[data-select-menu]");var i=t===null||t===void 0?void 0:t.querySelectorAll("[data-select-option]");if(i&&this.highlightedIndex>=0&&this.highlightedIndex<i.length){var s=i[this.highlightedIndex];s===null||s===void 0?void 0:s.scrollIntoView({block:"nearest",behavior:"smooth"})}})}})};var a={name:"select",component:r}}}]);