@referralgps/selectra 1.0.0 → 1.0.3

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
 
@@ -306,7 +258,7 @@ selectra({
306
258
  ### Custom Plugins
307
259
 
308
260
  ```js
309
- import { registerPlugin } from 'selectra';
261
+ import { registerPlugin } from '@referralgps/selectra';
310
262
 
311
263
  registerPlugin('my_plugin', function(options) {
312
264
  // `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.3 | Apache-2.0 License */
1
2
  const DIACRITICS = {
2
3
  a: "[aḀḁĂăÂâǍǎȺⱥȦȧẠạÄäÀàÁáĀāÃãÅåąĄÃąĄ]",
3
4
  b: "[b␢βΒB฿𐌁ᛒ]",
@@ -608,10 +609,10 @@ function createSelectizeComponent(userConfig = {}) {
608
609
  const key = hashKey(value);
609
610
  if (!key || !this.options[key]) return;
610
611
  if (this.items.includes(key)) return;
611
- if (this.isFull) return;
612
612
  if (this.isSingle && this.items.length) {
613
613
  this.removeItem(this.items[0], true);
614
614
  }
615
+ if (this.isFull) return;
615
616
  this.items.push(key);
616
617
  this.caretPos = this.items.length;
617
618
  this._syncSourceElement();
@@ -911,9 +912,15 @@ function createSelectizeComponent(userConfig = {}) {
911
912
  const value = option[this._config.valueField];
912
913
  this.addItem(value);
913
914
  this.query = "";
914
- if (this.$refs.searchInput) {
915
+ if (this.isSingle) {
916
+ this.isFocused = false;
917
+ this.loadedSearches = {};
918
+ if (this.$refs.searchInput) {
919
+ this.$refs.searchInput.blur();
920
+ }
921
+ } else if (this.$refs.searchInput) {
915
922
  this.$refs.searchInput.focus();
916
- if (this.isMultiple) autoGrow(this.$refs.searchInput);
923
+ autoGrow(this.$refs.searchInput);
917
924
  }
918
925
  },
919
926
  // ── Remote Loading ──────────────────────────────────────
@@ -947,6 +954,7 @@ function createSelectizeComponent(userConfig = {}) {
947
954
  },
948
955
  renderItem(option) {
949
956
  var _a;
957
+ if (!option) return "";
950
958
  const config = this._config;
951
959
  const label = option[config.labelField] || "";
952
960
  if ((_a = config.render) == null ? void 0 : _a.item) {
@@ -1015,6 +1023,24 @@ function createSelectizeComponent(userConfig = {}) {
1015
1023
  }
1016
1024
  return result;
1017
1025
  },
1026
+ /**
1027
+ * Get grouped options with precomputed offsets for template binding.
1028
+ * Works for both grouped and flat option lists.
1029
+ */
1030
+ _getGroupedView() {
1031
+ const groups = this.getGroupedOptions();
1032
+ let offset = 0;
1033
+ return groups.map((g, i) => {
1034
+ const view = {
1035
+ key: g.id || "__ungrouped_" + i,
1036
+ label: g.label,
1037
+ options: g.options,
1038
+ offset
1039
+ };
1040
+ offset += g.options.length;
1041
+ return view;
1042
+ });
1043
+ },
1018
1044
  get hasOptgroups() {
1019
1045
  return Object.keys(this.optgroups).length > 0;
1020
1046
  },
@@ -1277,18 +1303,16 @@ registerPlugin("auto_position", function() {
1277
1303
  *
1278
1304
  * Usage:
1279
1305
  *
1280
- * // Register the plugin
1306
+ * // 1. Register the plugin
1281
1307
  * import Alpine from 'alpinejs';
1282
1308
  * import Selectra from 'selectra';
1283
1309
  * Alpine.plugin(Selectra);
1284
1310
  * Alpine.start();
1285
1311
  *
1286
- * // In HTML (directive approach):
1287
- * <div x-data="selectra({ options: [...], create: true })">
1288
- * <template x-selectra></template>
1289
- * </div>
1312
+ * // 2. Use it — that's it!
1313
+ * <div x-data="selectra({ options: [...], placeholder: 'Pick...' })" x-selectra></div>
1290
1314
  *
1291
- * // Or initialize on existing <select>:
1315
+ * // Or with a native <select> for progressive enhancement:
1292
1316
  * <div x-data="selectra()" x-selectra>
1293
1317
  * <select>
1294
1318
  * <option value="1">One</option>
@@ -1296,17 +1320,95 @@ registerPlugin("auto_position", function() {
1296
1320
  * </select>
1297
1321
  * </div>
1298
1322
  */
1323
+ const SELECTRA_TEMPLATE = `
1324
+ <div class="selectra-control" :class="{'is-disabled': isDisabled}">
1325
+ <div @click="focus()" class="selectra-input"
1326
+ :class="{'is-focused': isFocused, 'is-invalid': isInvalid, 'is-locked': isLocked, 'is-single': isSingle, 'has-items': items.length > 0}">
1327
+ <span x-show="isSingle && items.length && !isFocused"
1328
+ x-text="currentValueText"
1329
+ class="selectra-single-value"></span>
1330
+ <template x-for="val in items" :key="val">
1331
+ <span x-show="isMultiple" class="selectra-item">
1332
+ <span x-html="options[val] ? renderItem(options[val]) : val"></span>
1333
+ <span @click.stop="removeItem(val)" class="selectra-item-remove">&times;</span>
1334
+ </span>
1335
+ </template>
1336
+ <input x-ref="searchInput"
1337
+ x-model="query"
1338
+ @input="onInput()"
1339
+ @focus="focus()"
1340
+ @blur.debounce.150ms="blur()"
1341
+ @keydown="onKeyDown($event)"
1342
+ @paste="onPaste($event)"
1343
+ :placeholder="placeholderText"
1344
+ x-show="(isSingle || !isFull) && (isMultiple || isFocused || !items.length)"
1345
+ class="selectra-search">
1346
+ <span x-show="isFull && isMultiple" class="selectra-max-badge">Max reached</span>
1347
+ <div x-show="isLoading && !isOpen" class="selectra-spinner"></div>
1348
+ <svg x-show="isSingle"
1349
+ class="selectra-arrow" :class="{'is-open': isOpen}"
1350
+ fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
1351
+ <path stroke-linecap="round" stroke-linejoin="round" d="M19 9l-7 7-7-7"/>
1352
+ </svg>
1353
+ </div>
1354
+ <div x-show="isOpen" x-ref="dropdown" x-cloak class="selectra-dropdown"
1355
+ x-transition:enter="transition ease-out duration-150"
1356
+ x-transition:enter-start="opacity-0 -translate-y-1"
1357
+ x-transition:enter-end="opacity-100 translate-y-0"
1358
+ x-transition:leave="transition ease-in duration-100"
1359
+ x-transition:leave-start="opacity-100 translate-y-0"
1360
+ x-transition:leave-end="opacity-0 -translate-y-1">
1361
+ <div class="selectra-dropdown-content">
1362
+ <template x-for="group in _getGroupedView()" :key="group.key">
1363
+ <div>
1364
+ <div x-show="group.label" x-text="group.label" class="selectra-optgroup-header"></div>
1365
+ <template x-for="(option, idx) in group.options" :key="optionKey(option)">
1366
+ <div @click="selectOption(option)"
1367
+ @mouseenter="activeIndex = group.offset + idx"
1368
+ :data-active="activeIndex === group.offset + idx"
1369
+ :class="{'is-active': activeIndex === group.offset + idx}"
1370
+ class="selectra-option"
1371
+ x-html="renderOption(option)">
1372
+ </div>
1373
+ </template>
1374
+ </div>
1375
+ </template>
1376
+ <div x-show="canCreate"
1377
+ @click="createItem()"
1378
+ @mouseenter="activeIndex = filteredOptions.length"
1379
+ :data-active="activeIndex === filteredOptions.length"
1380
+ :class="{'is-active': activeIndex === filteredOptions.length}"
1381
+ class="selectra-option-create"
1382
+ x-html="renderOptionCreate()">
1383
+ </div>
1384
+ <div x-show="filteredOptions.length === 0 && !isLoading && !canCreate"
1385
+ class="selectra-no-results"
1386
+ x-html="renderNoResults()">
1387
+ </div>
1388
+ <div x-show="isLoading" class="selectra-loading">
1389
+ <div class="selectra-spinner"></div>
1390
+ <span x-html="renderLoading()"></span>
1391
+ </div>
1392
+ </div>
1393
+ </div>
1394
+ </div>
1395
+ `.trim();
1299
1396
  function SelectraPlugin(Alpine) {
1300
1397
  Alpine.data("selectra", (config = {}) => {
1301
1398
  const componentFactory = createSelectizeComponent(config);
1302
1399
  return componentFactory();
1303
1400
  });
1304
1401
  Alpine.directive("selectra", (el, { expression }, { evaluate, cleanup }) => {
1402
+ if (!el.querySelector(".selectra-control")) {
1403
+ el.insertAdjacentHTML("beforeend", SELECTRA_TEMPLATE);
1404
+ }
1305
1405
  });
1306
1406
  }
1307
- SelectraPlugin.version = "1.0.0";
1407
+ SelectraPlugin.version = "1.0.3";
1408
+ SelectraPlugin.template = SELECTRA_TEMPLATE;
1308
1409
  export {
1309
1410
  DEFAULTS,
1411
+ SELECTRA_TEMPLATE,
1310
1412
  Sifter,
1311
1413
  createSelectizeComponent,
1312
1414
  SelectraPlugin as default,