@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 +42 -89
- package/dist/selectra.css +1 -1
- package/dist/selectra.es.js +126 -10
- package/dist/selectra.es.js.map +1 -1
- package/dist/selectra.iife.js +6 -8
- package/dist/selectra.iife.js.map +1 -1
- package/dist/selectra.umd.js +6 -8
- package/dist/selectra.umd.js.map +1 -1
- package/package.json +13 -18
- package/src-alpine/README.md +58 -75
- package/src-alpine/index.d.ts +3 -0
- package/src-alpine/index.js +98 -10
- package/src-alpine/selectize.js +49 -4
- package/src-alpine/styles/selectra.css +5 -0
package/README.md
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# Selectra
|
|
2
2
|
|
|
3
|
+
[](https://www.npmjs.com/package/@referralgps/selectra)
|
|
4
|
+
[](https://www.npmjs.com/package/@referralgps/selectra)
|
|
5
|
+
[](https://github.com/ReferralGPS/Selectra/blob/master/LICENSE)
|
|
6
|
+
[](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
|
-
##
|
|
42
|
-
|
|
43
|
-
```bash
|
|
44
|
-
npm install selectra alpinejs
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
### CDN
|
|
48
|
+
## Requirements
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
-
##
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npm install @referralgps/selectra alpinejs
|
|
60
|
+
```
|
|
58
61
|
|
|
59
|
-
|
|
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
|
-
|
|
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
|
-
})"
|
|
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
|
-
})"
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
</
|
|
145
|
-
|
|
146
|
-
<
|
|
147
|
-
|
|
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))}
|
package/dist/selectra.es.js
CHANGED
|
@@ -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
|
|
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
|
-
|
|
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
|
-
* //
|
|
1287
|
-
* <div x-data="selectra({ options: [...],
|
|
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
|
|
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">×</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.
|
|
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,
|