@referralgps/selectra 1.0.0 → 1.0.5

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/README.md CHANGED
@@ -1,7 +1,14 @@
1
1
  # Selectra
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@referralgps/selectra)](https://www.npmjs.com/package/@referralgps/selectra)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@referralgps/selectra)](https://www.npmjs.com/package/@referralgps/selectra)
5
+ [![license](https://img.shields.io/npm/l/@referralgps/selectra)](https://github.com/ReferralGPS/Selectra/blob/master/LICENSE)
6
+ [![GitHub stars](https://img.shields.io/github/stars/ReferralGPS/Selectra)](https://github.com/ReferralGPS/Selectra)
7
+
3
8
  > A powerful, extensible `<select>` UI control — rebuilt with **Alpine.js** and **Tailwind CSS**.
4
9
 
10
+ [**Live Demo →**](https://referralgps.github.io/Selectra/examples/index.html)
11
+
5
12
  Selectra is a modern rewrite of [Selectize.js](https://github.com/selectize/selectize.js), designed for tagging, contact lists, country selectors, and autocomplete. It drops the jQuery dependency entirely in favor of Alpine.js reactivity and Tailwind CSS styling.
6
13
 
7
14
  ---
@@ -38,36 +45,36 @@ Selectra is a modern rewrite of [Selectize.js](https://github.com/selectize/sele
38
45
 
39
46
  ---
40
47
 
41
- ## Installation
42
-
43
- ```bash
44
- npm install selectra alpinejs
45
- ```
46
-
47
- ### CDN
48
+ ## Requirements
48
49
 
49
- ```html
50
- <script src="https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js" defer></script>
51
- <script src="https://cdn.jsdelivr.net/npm/selectra/dist/selectra.iife.js"></script>
52
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/selectra/dist/selectra.css">
53
- ```
50
+ - **Node.js** v14 or newer (for npm/yarn install)
51
+ - **Alpine.js** v3.x (peer dependency)
52
+ - **Tailwind CSS** v2.x or v3.x (for styling, optional but recommended)
54
53
 
55
54
  ---
56
55
 
57
- ## Quick Start
56
+ ## Installation
57
+
58
+ ```bash
59
+ npm install @referralgps/selectra alpinejs
60
+ ```
58
61
 
59
- ### 1. Register the Plugin
62
+ Import and register the plugin in your JavaScript entry point:
60
63
 
61
64
  ```js
62
65
  import Alpine from 'alpinejs';
63
- import Selectra from 'selectra';
64
- import 'selectra/css';
66
+ import Selectra from '@referralgps/selectra';
67
+ import '@referralgps/selectra/css';
65
68
 
66
69
  Alpine.plugin(Selectra);
67
70
  Alpine.start();
68
71
  ```
69
72
 
70
- ### 2. Use in HTML
73
+ ---
74
+
75
+ ## Quick Start
76
+
77
+ Add `x-data="selectra({...})"` and `x-selectra` to any element. The template is rendered automatically by the `x-selectra` directive — no manual markup required.
71
78
 
72
79
  #### Single Select
73
80
 
@@ -80,42 +87,7 @@ Alpine.start();
80
87
  { value: 'ca', text: 'Canada' },
81
88
  { value: 'mx', text: 'Mexico' },
82
89
  ]
83
- })" class="relative max-w-md">
84
-
85
- <!-- Control -->
86
- <div @click="focus()"
87
- :class="{ 'ring-2 ring-blue-500/20 border-blue-500': isFocused }"
88
- class="relative flex items-center w-full min-h-[42px] px-3 py-1.5 bg-white border border-gray-300 rounded-lg cursor-pointer hover:border-gray-400">
89
-
90
- <span x-show="items.length && !isFocused" x-text="currentValueText" class="truncate text-gray-900"></span>
91
-
92
- <input x-ref="searchInput" x-model="query"
93
- @input="onInput()" @focus="focus()" @blur.debounce.150ms="blur()"
94
- @keydown="onKeyDown($event)"
95
- :placeholder="placeholderText"
96
- x-show="isFocused || !items.length"
97
- class="flex-1 min-w-0 bg-transparent outline-none border-none p-0 text-gray-900 placeholder-gray-400">
98
-
99
- <svg :class="{'rotate-180': isOpen}" class="w-4 h-4 text-gray-400 ml-2 transition-transform"
100
- fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
101
- <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7" />
102
- </svg>
103
- </div>
104
-
105
- <!-- Dropdown -->
106
- <div x-show="isOpen" x-ref="dropdown"
107
- x-transition class="absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden">
108
- <div class="max-h-60 overflow-y-auto py-1">
109
- <template x-for="(option, index) in filteredOptions" :key="optionKey(option)">
110
- <div @click="selectOption(option)" @mouseenter="activeIndex = index"
111
- :class="{ 'bg-blue-500 text-white': activeIndex === index }"
112
- class="px-3 py-2 cursor-pointer"
113
- x-html="renderOption(option)">
114
- </div>
115
- </template>
116
- </div>
117
- </div>
118
- </div>
90
+ })" x-selectra></div>
119
91
  ```
120
92
 
121
93
  #### Multi Select with Tags
@@ -130,41 +102,21 @@ Alpine.start();
130
102
  { value: 'py', text: 'Python' },
131
103
  { value: 'go', text: 'Go' },
132
104
  ]
133
- })" class="relative max-w-md">
134
-
135
- <div @click="focus()"
136
- :class="{ 'ring-2 ring-blue-500/20 border-blue-500': isFocused }"
137
- class="relative flex flex-wrap items-center gap-1 w-full min-h-[42px] px-2 py-1.5 bg-white border border-gray-300 rounded-lg cursor-text hover:border-gray-400">
138
-
139
- <template x-for="val in items" :key="val">
140
- <span class="inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-blue-50 text-blue-700 border border-blue-200 text-sm">
141
- <span x-text="options[val]?.text || val"></span>
142
- <button @click.stop="removeItem(val)" class="w-4 h-4 rounded-full text-blue-400 hover:text-blue-600">&times;</button>
143
- </span>
144
- </template>
145
-
146
- <input x-ref="searchInput" x-model="query"
147
- @input="onInput()" @focus="focus()" @blur.debounce.150ms="blur()"
148
- @keydown="onKeyDown($event)" @paste="onPaste($event)"
149
- :placeholder="items.length ? '' : placeholderText"
150
- class="flex-1 min-w-[60px] bg-transparent outline-none border-none p-0 text-sm">
151
- </div>
152
-
153
- <div x-show="isOpen" x-ref="dropdown" x-transition
154
- class="absolute z-50 w-full mt-1 bg-white border border-gray-200 rounded-lg shadow-lg overflow-hidden">
155
- <div class="max-h-60 overflow-y-auto py-1">
156
- <template x-for="(option, index) in filteredOptions" :key="optionKey(option)">
157
- <div @click="selectOption(option)" @mouseenter="activeIndex = index"
158
- :class="{ 'bg-blue-500 text-white': activeIndex === index }"
159
- class="px-3 py-2 cursor-pointer" x-html="renderOption(option)">
160
- </div>
161
- </template>
162
- <div x-show="canCreate" @click="createItem()"
163
- class="px-3 py-2 cursor-pointer text-gray-500 border-t border-gray-100"
164
- x-html="renderOptionCreate()">
165
- </div>
166
- </div>
167
- </div>
105
+ })" x-selectra></div>
106
+ ```
107
+
108
+ #### Native `<select>` Enhancement
109
+
110
+ Enhance a standard `<select>` element — options are read automatically:
111
+
112
+ ```html
113
+ <div x-data="selectra()" x-selectra>
114
+ <select>
115
+ <option value="">Pick a fruit...</option>
116
+ <option value="apple">Apple</option>
117
+ <option value="banana">Banana</option>
118
+ <option value="cherry">Cherry</option>
119
+ </select>
168
120
  </div>
169
121
  ```
170
122
 
@@ -199,6 +151,7 @@ Alpine.start();
199
151
  | `load` | `function \| null` | `null` | Remote data loader |
200
152
  | `loadThrottle` | `number` | `300` | Load debounce delay (ms) |
201
153
  | `plugins` | `Array` | `[]` | Plugins to activate |
154
+ | `dropdownPlaceholder` | `string` | `''` | Pre-search placeholder
202
155
 
203
156
  ### Custom Rendering
204
157
 
@@ -306,7 +259,7 @@ selectra({
306
259
  ### Custom Plugins
307
260
 
308
261
  ```js
309
- import { registerPlugin } from 'selectra';
262
+ import { registerPlugin } from '@referralgps/selectra';
310
263
 
311
264
  registerPlugin('my_plugin', function(options) {
312
265
  // `this` is the selectra component instance
package/dist/selectra.css CHANGED
@@ -1 +1 @@
1
- *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.selectra-option.is-active .highlight{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.highlight{font-weight:600;color:inherit}.pointer-events-none{pointer-events:none}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.top-0{top:0}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.mt-1{margin-top:.25rem}.mt-16{margin-top:4rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.hidden{display:none}.h-3{height:.75rem}.h-4{height:1rem}.max-h-60{max-height:15rem}.min-h-\[42px\]{min-height:42px}.min-h-screen{min-height:100vh}.w-3{width:.75rem}.w-4{width:1rem}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[60px\]{min-width:60px}.max-w-4xl{max-width:56rem}.max-w-md{max-width:28rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.-translate-y-1{--tw-translate-y: -.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-180{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-pointer{cursor:pointer}.cursor-text{cursor:text}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-center{justify-content:center}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-none{border-style:none}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity, 1))}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-emerald-200{--tw-border-opacity: 1;border-color:rgb(167 243 208 / var(--tw-border-opacity, 1))}.border-gray-100{--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-violet-200{--tw-border-opacity: 1;border-color:rgb(221 214 254 / var(--tw-border-opacity, 1))}.border-t-blue-500{--tw-border-opacity: 1;border-top-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-violet-50{--tw-bg-opacity: 1;background-color:rgb(245 243 255 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.p-0{padding:0}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pt-8{padding-top:2rem}.text-center{text-align:center}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tracking-wider{letter-spacing:.05em}.text-amber-400{--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-emerald-400{--tw-text-opacity: 1;color:rgb(52 211 153 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-inherit{color:inherit}.text-violet-400{--tw-text-opacity: 1;color:rgb(167 139 250 / var(--tw-text-opacity, 1))}.text-violet-700{--tw-text-opacity: 1;color:rgb(109 40 217 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.decoration-blue-300{text-decoration-color:#93c5fd}.placeholder-gray-400::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.placeholder-gray-400::placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.opacity-0{opacity:0}.opacity-100{opacity:1}.opacity-50{opacity:.5}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring-2{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-blue-500\/20{--tw-ring-color: rgb(59 130 246 / .2)}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-150{transition-duration:.15s}.duration-200{transition-duration:.2s}.duration-75{transition-duration:75ms}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}@keyframes fade-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes dropdown-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.animate-fade-in{animation:fade-in .15s ease-out}.animate-dropdown-in{animation:dropdown-in .15s ease-out}.selectra-dropdown-content::-webkit-scrollbar{width:6px}.selectra-dropdown-content::-webkit-scrollbar-track{background:transparent}.selectra-dropdown-content::-webkit-scrollbar-thumb{border-radius:9999px;--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.selectra-dropdown-content::-webkit-scrollbar-thumb:hover{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.hover\:border-gray-400:hover{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1))}.hover\:bg-amber-100:hover{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-100:hover{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.hover\:bg-emerald-100:hover{--tw-bg-opacity: 1;background-color:rgb(209 250 229 / var(--tw-bg-opacity, 1))}.hover\:bg-violet-100:hover{--tw-bg-opacity: 1;background-color:rgb(237 233 254 / var(--tw-bg-opacity, 1))}.hover\:text-amber-600:hover{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.hover\:text-emerald-600:hover{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.hover\:text-violet-600:hover{--tw-text-opacity: 1;color:rgb(124 58 237 / var(--tw-text-opacity, 1))}
1
+ *,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.selectra-control{position:relative;width:100%;font-size:.875rem;line-height:1.25rem}.selectra-control.is-disabled{pointer-events:none;opacity:.5}.selectra-input{position:relative;display:flex;min-height:38px;width:100%;cursor:text;flex-wrap:wrap;align-items:center;gap:.25rem;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));padding:.375rem .75rem;--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1));transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.selectra-input:hover{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1))}.selectra-input.is-focused{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1));outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(59 130 246 / .2)}.selectra-input.is-invalid{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1));--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-color: rgb(239 68 68 / .2)}.selectra-input.is-locked{cursor:default;--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.selectra-input.is-single{cursor:pointer;padding-right:2rem}.selectra-input.is-single.has-items .selectra-search{position:absolute;top:0;right:0;bottom:0;left:0;padding:.375rem .75rem}.selectra-search{margin:0;min-width:60px;flex:1 1 0%;border-style:none;background-color:transparent;padding:0;--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.selectra-search::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.selectra-search::placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.selectra-search{outline:2px solid transparent;outline-offset:2px}.selectra-search:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.selectra-input.is-single .selectra-search{width:100%;min-width:0px}.selectra-item{display:inline-flex}.selectra-item{align-items:center;gap:.25rem;border-radius:.375rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1));padding:.125rem .5rem;font-size:.875rem;line-height:1.25rem;line-height:1.375;--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1));animation:fade-in .15s ease-out}.selectra-item .selectra-item-remove{margin-right:-.125rem;margin-left:.125rem;display:inline-flex;height:1rem;width:1rem;cursor:pointer;align-items:center;justify-content:center;border-radius:9999px;--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.1s}.selectra-item .selectra-item-remove:hover{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.selectra-single-value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.selectra-arrow{pointer-events:none;position:absolute;right:.625rem;top:50%;height:1rem;width:1rem;--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1));transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.2s}.selectra-arrow.is-open{--tw-rotate: 180deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.selectra-dropdown{position:absolute;z-index:50;margin-top:.25rem;width:100%}.selectra-dropdown{overflow:hidden;border-radius:.5rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1));--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);animation:dropdown-in .15s ease-out}.selectra-dropdown.is-top{bottom:100%;top:auto;margin-bottom:.25rem;margin-top:0}.selectra-dropdown-content{max-height:15rem;overflow-y:auto;overscroll-behavior:contain;padding-top:.25rem;padding-bottom:.25rem}.selectra-option{cursor:pointer;padding:.5rem .75rem;line-height:1.375;--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:75ms}.selectra-option:hover,.selectra-option.is-active{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.selectra-option.is-active .highlight{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.selectra-option.is-disabled{cursor:not-allowed;opacity:.5}.selectra-option.is-selected{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.selectra-option.is-selected.is-active{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.selectra-option-create{cursor:pointer;border-top-width:1px;--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1));padding:.5rem .75rem;--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1));transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:75ms}.selectra-option-create:hover,.selectra-option-create.is-active{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1));--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.selectra-no-results{padding:.75rem;text-align:center;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.selectra-loading{display:flex;align-items:center;justify-content:center;gap:.5rem;padding:.75rem;text-align:center;font-size:.875rem;line-height:1.25rem;--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.selectra-spinner{height:1rem;width:1rem}@keyframes spin{to{transform:rotate(360deg)}}.selectra-spinner{animation:spin 1s linear infinite;border-radius:9999px;border-width:2px;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1));--tw-border-opacity: 1;border-top-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.selectra-optgroup-header{border-bottom-width:1px;--tw-border-opacity: 1;border-color:rgb(243 244 246 / var(--tw-border-opacity, 1));--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1));padding:.375rem .75rem;font-size:.75rem;line-height:1rem;font-weight:600;text-transform:uppercase;letter-spacing:.05em;--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.selectra-input.is-single .selectra-clear-button{right:2rem}.selectra-max-badge{margin-left:.25rem;white-space:nowrap;font-size:.75rem;line-height:1rem;--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.highlight{font-weight:600;color:inherit}.mx-auto{margin-left:auto;margin-right:auto}.mb-1{margin-bottom:.25rem}.mb-12{margin-bottom:3rem}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mt-16{margin-top:4rem}.mt-4{margin-top:1rem}.block{display:block}.inline-flex{display:inline-flex}.hidden{display:none}.min-h-screen{min-height:100vh}.max-w-4xl{max-width:56rem}.max-w-md{max-width:28rem}.-translate-y-1{--tw-translate-y: -.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-0{--tw-translate-y: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.items-center{align-items:center}.rounded{border-radius:.25rem}.rounded-lg{border-radius:.5rem}.border{border-width:1px}.border-t{border-top-width:1px}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.p-4{padding:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-12{padding-top:3rem;padding-bottom:3rem}.pt-8{padding-top:2rem}.text-center{text-align:center}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.text-blue-800{--tw-text-opacity: 1;color:rgb(30 64 175 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-inherit{color:inherit}.opacity-0{opacity:0}.opacity-100{opacity:1}.blur{--tw-blur: blur(8px);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-100{transition-duration:.1s}.duration-150{transition-duration:.15s}.ease-in{transition-timing-function:cubic-bezier(.4,0,1,1)}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}@keyframes fade-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}@keyframes dropdown-in{0%{opacity:0;transform:translateY(-4px)}to{opacity:1;transform:translateY(0)}}.selectra-dropdown-content::-webkit-scrollbar{width:6px}.selectra-dropdown-content::-webkit-scrollbar-track{background:transparent}.selectra-dropdown-content::-webkit-scrollbar-thumb{border-radius:9999px;--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.selectra-dropdown-content::-webkit-scrollbar-thumb:hover{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}
@@ -1,3 +1,4 @@
1
+ /*! Selectra v1.0.5 | Apache-2.0 License */
1
2
  const DIACRITICS = {
2
3
  a: "[aḀḁĂăÂâǍǎȺⱥȦȧẠạÄäÀàÁáĀāÃãÅåąĄÃąĄ]",
3
4
  b: "[b␢βΒB฿𐌁ᛒ]",
@@ -329,6 +330,7 @@ const DEFAULTS = {
329
330
  loadThrottle: 300,
330
331
  loadingClass: "loading",
331
332
  placeholder: "",
333
+ dropdownPlaceholder: "",
332
334
  mode: null,
333
335
  // 'single' | 'multi' — auto-detected
334
336
  search: true,
@@ -352,6 +354,7 @@ const DEFAULTS = {
352
354
  optionCreate: null,
353
355
  optgroupHeader: null,
354
356
  noResults: null,
357
+ dropdownPlaceholder: null,
355
358
  loading: null
356
359
  },
357
360
  // Callbacks
@@ -608,10 +611,10 @@ function createSelectizeComponent(userConfig = {}) {
608
611
  const key = hashKey(value);
609
612
  if (!key || !this.options[key]) return;
610
613
  if (this.items.includes(key)) return;
611
- if (this.isFull) return;
612
614
  if (this.isSingle && this.items.length) {
613
615
  this.removeItem(this.items[0], true);
614
616
  }
617
+ if (this.isFull) return;
615
618
  this.items.push(key);
616
619
  this.caretPos = this.items.length;
617
620
  this._syncSourceElement();
@@ -911,9 +914,15 @@ function createSelectizeComponent(userConfig = {}) {
911
914
  const value = option[this._config.valueField];
912
915
  this.addItem(value);
913
916
  this.query = "";
914
- if (this.$refs.searchInput) {
917
+ if (this.isSingle) {
918
+ this.isFocused = false;
919
+ this.loadedSearches = {};
920
+ if (this.$refs.searchInput) {
921
+ this.$refs.searchInput.blur();
922
+ }
923
+ } else if (this.$refs.searchInput) {
915
924
  this.$refs.searchInput.focus();
916
- if (this.isMultiple) autoGrow(this.$refs.searchInput);
925
+ autoGrow(this.$refs.searchInput);
917
926
  }
918
927
  },
919
928
  // ── Remote Loading ──────────────────────────────────────
@@ -947,6 +956,7 @@ function createSelectizeComponent(userConfig = {}) {
947
956
  },
948
957
  renderItem(option) {
949
958
  var _a;
959
+ if (!option) return "";
950
960
  const config = this._config;
951
961
  const label = option[config.labelField] || "";
952
962
  if ((_a = config.render) == null ? void 0 : _a.item) {
@@ -970,6 +980,14 @@ function createSelectizeComponent(userConfig = {}) {
970
980
  }
971
981
  return "No results found";
972
982
  },
983
+ renderDropdownPlaceholder() {
984
+ var _a;
985
+ const config = this._config;
986
+ if ((_a = config.render) == null ? void 0 : _a.dropdownPlaceholder) {
987
+ return config.render.dropdownPlaceholder({}, escapeHtml);
988
+ }
989
+ return escapeHtml(config.dropdownPlaceholder || "");
990
+ },
973
991
  renderLoading() {
974
992
  var _a;
975
993
  const config = this._config;
@@ -1015,6 +1033,24 @@ function createSelectizeComponent(userConfig = {}) {
1015
1033
  }
1016
1034
  return result;
1017
1035
  },
1036
+ /**
1037
+ * Get grouped options with precomputed offsets for template binding.
1038
+ * Works for both grouped and flat option lists.
1039
+ */
1040
+ _getGroupedView() {
1041
+ const groups = this.getGroupedOptions();
1042
+ let offset = 0;
1043
+ return groups.map((g, i) => {
1044
+ const view = {
1045
+ key: g.id || "__ungrouped_" + i,
1046
+ label: g.label,
1047
+ options: g.options,
1048
+ offset
1049
+ };
1050
+ offset += g.options.length;
1051
+ return view;
1052
+ });
1053
+ },
1018
1054
  get hasOptgroups() {
1019
1055
  return Object.keys(this.optgroups).length > 0;
1020
1056
  },
@@ -1277,18 +1313,16 @@ registerPlugin("auto_position", function() {
1277
1313
  *
1278
1314
  * Usage:
1279
1315
  *
1280
- * // Register the plugin
1316
+ * // 1. Register the plugin
1281
1317
  * import Alpine from 'alpinejs';
1282
1318
  * import Selectra from 'selectra';
1283
1319
  * Alpine.plugin(Selectra);
1284
1320
  * Alpine.start();
1285
1321
  *
1286
- * // In HTML (directive approach):
1287
- * <div x-data="selectra({ options: [...], create: true })">
1288
- * <template x-selectra></template>
1289
- * </div>
1322
+ * // 2. Use it — that's it!
1323
+ * <div x-data="selectra({ options: [...], placeholder: 'Pick...' })" x-selectra></div>
1290
1324
  *
1291
- * // Or initialize on existing <select>:
1325
+ * // Or with a native <select> for progressive enhancement:
1292
1326
  * <div x-data="selectra()" x-selectra>
1293
1327
  * <select>
1294
1328
  * <option value="1">One</option>
@@ -1296,17 +1330,99 @@ registerPlugin("auto_position", function() {
1296
1330
  * </select>
1297
1331
  * </div>
1298
1332
  */
1333
+ const SELECTRA_TEMPLATE = `
1334
+ <div class="selectra-control" :class="{'is-disabled': isDisabled}">
1335
+ <div @click="focus()" class="selectra-input"
1336
+ :class="{'is-focused': isFocused, 'is-invalid': isInvalid, 'is-locked': isLocked, 'is-single': isSingle, 'has-items': items.length > 0}">
1337
+ <span x-show="isSingle && items.length && !isFocused"
1338
+ x-text="currentValueText"
1339
+ class="selectra-single-value"></span>
1340
+ <template x-for="val in items" :key="val">
1341
+ <span x-show="isMultiple" class="selectra-item">
1342
+ <span x-html="options[val] ? renderItem(options[val]) : val"></span>
1343
+ <span @click.stop="removeItem(val)" class="selectra-item-remove">&times;</span>
1344
+ </span>
1345
+ </template>
1346
+ <input x-ref="searchInput"
1347
+ x-model="query"
1348
+ @input="onInput()"
1349
+ @focus="focus()"
1350
+ @blur.debounce.150ms="blur()"
1351
+ @keydown="onKeyDown($event)"
1352
+ @paste="onPaste($event)"
1353
+ :placeholder="placeholderText"
1354
+ x-show="(isSingle || !isFull) && (isMultiple || isFocused || !items.length)"
1355
+ class="selectra-search">
1356
+ <span x-show="isFull && isMultiple" class="selectra-max-badge">Max reached</span>
1357
+ <div x-show="isLoading && !isOpen" class="selectra-spinner"></div>
1358
+ <svg x-show="isSingle"
1359
+ class="selectra-arrow" :class="{'is-open': isOpen}"
1360
+ fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
1361
+ <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/>
1362
+ </svg>
1363
+ </div>
1364
+ <div x-show="isOpen" x-ref="dropdown" x-cloak class="selectra-dropdown"
1365
+ x-transition:enter="transition ease-out duration-150"
1366
+ x-transition:enter-start="opacity-0 -translate-y-1"
1367
+ x-transition:enter-end="opacity-100 translate-y-0"
1368
+ x-transition:leave="transition ease-in duration-100"
1369
+ x-transition:leave-start="opacity-100 translate-y-0"
1370
+ x-transition:leave-end="opacity-0 -translate-y-1">
1371
+ <div class="selectra-dropdown-content">
1372
+ <template x-for="group in _getGroupedView()" :key="group.key">
1373
+ <div>
1374
+ <div x-show="group.label" x-text="group.label" class="selectra-optgroup-header"></div>
1375
+ <template x-for="(option, idx) in group.options" :key="optionKey(option)">
1376
+ <div @click="selectOption(option)"
1377
+ @mouseenter="activeIndex = group.offset + idx"
1378
+ :data-active="activeIndex === group.offset + idx"
1379
+ :class="{'is-active': activeIndex === group.offset + idx}"
1380
+ class="selectra-option"
1381
+ x-html="renderOption(option)">
1382
+ </div>
1383
+ </template>
1384
+ </div>
1385
+ </template>
1386
+ <div x-show="canCreate"
1387
+ @click="createItem()"
1388
+ @mouseenter="activeIndex = filteredOptions.length"
1389
+ :data-active="activeIndex === filteredOptions.length"
1390
+ :class="{'is-active': activeIndex === filteredOptions.length}"
1391
+ class="selectra-option-create"
1392
+ x-html="renderOptionCreate()">
1393
+ </div>
1394
+ <div x-show="filteredOptions.length === 0 && !isLoading && !canCreate && query.length > 0"
1395
+ class="selectra-no-results"
1396
+ x-html="renderNoResults()">
1397
+ </div>
1398
+ <div x-show="filteredOptions.length === 0 && !isLoading && !canCreate && query.length === 0 && _config.dropdownPlaceholder"
1399
+ class="selectra-no-results"
1400
+ x-html="renderDropdownPlaceholder()">
1401
+ </div>
1402
+ <div x-show="isLoading" class="selectra-loading">
1403
+ <div class="selectra-spinner"></div>
1404
+ <span x-html="renderLoading()"></span>
1405
+ </div>
1406
+ </div>
1407
+ </div>
1408
+ </div>
1409
+ `.trim();
1299
1410
  function SelectraPlugin(Alpine) {
1300
1411
  Alpine.data("selectra", (config = {}) => {
1301
1412
  const componentFactory = createSelectizeComponent(config);
1302
1413
  return componentFactory();
1303
1414
  });
1304
1415
  Alpine.directive("selectra", (el, { expression }, { evaluate, cleanup }) => {
1416
+ if (!el.querySelector(".selectra-control")) {
1417
+ el.insertAdjacentHTML("beforeend", SELECTRA_TEMPLATE);
1418
+ }
1305
1419
  });
1306
1420
  }
1307
- SelectraPlugin.version = "1.0.0";
1421
+ SelectraPlugin.version = "1.0.5";
1422
+ SelectraPlugin.template = SELECTRA_TEMPLATE;
1308
1423
  export {
1309
1424
  DEFAULTS,
1425
+ SELECTRA_TEMPLATE,
1310
1426
  Sifter,
1311
1427
  createSelectizeComponent,
1312
1428
  SelectraPlugin as default,