vlite3 0.0.9 → 0.1.1

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
@@ -63,30 +63,25 @@ vlite3 uses a semantic theming system inspired by **shadcn/ui** and compatible w
63
63
 
64
64
  You can customize these colors in your CSS by overriding the variables in `:root` or `.dark` classes (if you are using a class-based dark mode switcher).
65
65
 
66
- | Variable | Class Name | Description | Recommended Usage |
67
- | :------------------------- | :---------------------------- | :----------------------- | :--------------------------------------------------------- |
68
- | `--background` | `bg-background` | Default page background | The main background color of your app. |
69
- | `--foreground` | `text-foreground` | Default text color | The primary text color for content. |
70
- | `--card` | `bg-card` | Card background | Background for cards, panels, and dialogs. |
71
- | `--card-foreground` | `text-card-foreground` | Card text color | Text color inside cards. |
72
- | `--card-muted` | `bg-card-muted` | Muted card background | Secondary background area within cards. |
73
- | `--popover` | `bg-popover` | Popover background | Background for popovers, tooltips, and dropdowns. |
74
- | `--popover-foreground` | `text-popover-foreground` | Popover text color | Text color inside popovers. |
75
- | `--popover-muted` | `bg-popover-muted` | Muted popover background | Secondary area within popovers (e.g., headers). |
76
- | `--primary` | `bg-primary` | Primary brand color | Used for main actions (buttons, active states). |
77
- | `--primary-foreground` | `text-primary-foreground` | Primary text color | Text color for content on top of primary background. |
78
- | `--secondary` | `bg-secondary` | Secondary background | Used for secondary actions or muted sections. |
79
- | `--secondary-foreground` | `text-secondary-foreground` | Secondary text color | Text color for content on top of secondary background. |
80
- | `--muted` | `bg-muted` | Muted background | Subtle backgrounds (e.g., table headers, disabled states). |
81
- | `--muted-foreground` | `text-muted-foreground` | Muted text color | Secondary text, hints, placeholders. |
82
- | `--accent` | `bg-accent` | Accent background | Used for hover states, selection highlights. |
83
- | `--accent-foreground` | `text-accent-foreground` | Accent text color | Text color on accent backgrounds. |
84
- | `--destructive` | `bg-destructive` | Destructive color | Used for error states and destructive actions. |
85
- | `--destructive-foreground` | `text-destructive-foreground` | Destructive text color | Text color on destructive backgrounds. |
86
- | `--border` | `border` | Default border color | Borders for inputs, cards, and dividers. |
87
- | `--input` | `border-input` | Input border color | Borders specifically for form inputs. |
88
- | `--ring` | `ring-ring` | Focus ring color | Outline color for focused elements. |
89
- | `--radius` | `rounded-radius` | Border radius | Global border radius for components. |
66
+ | Variable | Class Name | Description | Recommended Usage |
67
+ | :------------------------- | :---------------------------- | :---------------------- | :-------------------------------------------------------------------------- |
68
+ | `--background` | `bg-background` | Default page background | The main background color of your app. |
69
+ | `--foreground` | `text-foreground` | Default text color | The primary text color for content. |
70
+ | `--card` | `bg-card` | Card background | Little Gray Background for cards, containers, surfece, panels, and dialogs. |
71
+ | `--primary` | `bg-primary` | Primary brand color | Used for main actions (buttons, active states). |
72
+ | `--primary-foreground` | `text-primary-foreground` | Primary text color | Text color for content on top of primary background. |
73
+ | `--secondary` | `bg-secondary` | Secondary background | Used for secondary actions or muted sections. |
74
+ | `--secondary-foreground` | `text-secondary-foreground` | Secondary text color | Text color for content on top of secondary background. |
75
+ | `--muted` | `bg-muted` | Muted background | Subtle backgrounds (e.g., table headers, disabled states). |
76
+ | `--muted-foreground` | `text-muted-foreground` | Muted text color | Secondary text, hints, placeholders. |
77
+ | `--accent` | `bg-accent` | Accent background | Used for hover states, selection highlights. |
78
+ | `--accent-foreground` | `text-accent-foreground` | Accent text color | Text color on accent backgrounds. |
79
+ | `--destructive` | `bg-destructive` | Destructive color | Used for error states and destructive actions. |
80
+ | `--destructive-foreground` | `text-destructive-foreground` | Destructive text color | Text color on destructive backgrounds. |
81
+ | `--border` | `border` | Default border color | Borders for inputs, cards, and dividers. |
82
+ | `--input` | `border-input` | Input border color | Borders specifically for form inputs. |
83
+ | `--ring` | `ring-ring` | Focus ring color | Outline color for focused elements. |
84
+ | `--radius` | `rounded` | Border radius | Global border radius for components. |
90
85
 
91
86
  ### Extended Color Variants
92
87
 
@@ -197,3 +192,110 @@ To customize the theme, simply override the CSS variables in your main CSS file:
197
192
  - **ToastNotification**
198
193
  - **Tooltip**
199
194
  - **Dropdown**
195
+
196
+ ## Global Configuration (Registry System)
197
+
198
+ vlite3 features a plugin-based architecture that allows you to register global services. This is particularly useful for dependency injection, such as defining how file uploads should be handled across all `Form` components in your app.
199
+
200
+ ### Setting up the Plugin
201
+
202
+ In your `main.ts` or `main.js`, import `createVLite` and register your services:
203
+
204
+ ```typescript
205
+ import { createApp } from 'vue'
206
+ import App from './App.vue'
207
+ import { createVLite } from 'vlite3'
208
+
209
+ const app = createApp(App)
210
+
211
+ // Initialize VLite with custom configuration
212
+ const vlite = createVLite({
213
+ services: {
214
+ /**
215
+ * Global File Upload Handler
216
+ *
217
+ * This function will be called automatically by:
218
+ * - useFileUpload() composable
219
+ * - Form components (when using 'file', 'fileUploader', or 'avatarUpload' types)
220
+ *
221
+ * @param file - The File object to upload
222
+ * @param folderId - (Optional) Folder ID passed from component props
223
+ * @returns Promise<string> - The public URL of the uploaded file
224
+ */
225
+ upload: async (file, folderId) => {
226
+ // Example: Upload to your own backend
227
+ const formData = new FormData()
228
+ formData.append('file', file)
229
+ if (folderId) formData.append('folder_id', folderId)
230
+
231
+ // Replace with your actual API call (e.g., Axios, Fetch)
232
+ const response = await fetch(
233
+ '[https://api.yourdomain.com/v1/upload](https://api.yourdomain.com/v1/upload)',
234
+ {
235
+ method: 'POST',
236
+ body: formData,
237
+ headers: {
238
+ Authorization: 'Bearer ...',
239
+ },
240
+ }
241
+ )
242
+
243
+ if (!response.ok) throw new Error('Upload failed')
244
+
245
+ const data = await response.json()
246
+ return data.url // MUST return the file URL string
247
+ },
248
+ },
249
+ })
250
+
251
+ app.use(vlite)
252
+ app.mount('#app')
253
+ ```
254
+
255
+ ### How it works
256
+
257
+ Once registered, you don't need to pass upload handlers to individual components.
258
+
259
+ 1. **Automatic Injection**: The `Form` component detects input types like `file`, `avatarUpload`, or `fileUploader`.
260
+ 2. **Parallel Processing**: When the form is submitted, it automatically uploads all files in **parallel** using your registered `upload` service.
261
+ 3. **URL Replacement**: The File objects in your form data are replaced with the returned URLs before the final `onSubmit` event is triggered.
262
+
263
+ ## 4. Usage
264
+
265
+ Import components directly in your Vue files:
266
+
267
+ ```vue
268
+ <script setup>
269
+ import { Button, Input, Form } from 'vlite3'
270
+
271
+ // The form will automatically use the global upload service defined in main.ts
272
+ const schema = [
273
+ {
274
+ name: 'avatar',
275
+ label: 'Profile Picture',
276
+ type: 'avatarUpload',
277
+ },
278
+ {
279
+ name: 'documents',
280
+ label: 'Attachments',
281
+ type: 'fileUploader',
282
+ props: { multiple: true },
283
+ },
284
+ ]
285
+
286
+ const handleSubmit = (payload) => {
287
+ // payload.values.avatar will be a URL string (e.g., "https://api...")
288
+ // payload.values.documents will be an array of URL strings
289
+ console.log(payload.values)
290
+ }
291
+ </script>
292
+
293
+ <template>
294
+ <div class="p-4 space-y-4">
295
+ <Button>Click Me</Button>
296
+ <Input placeholder="Type here..." />
297
+
298
+ <Form :schema="schema" @onSubmit="handleSubmit" />
299
+ </div>
300
+ </template>
301
+ ```
@@ -19,15 +19,15 @@ const j = ["role"], E = {
19
19
  const t = e, p = f, c = V(!0), y = () => {
20
20
  c.value = !1, p("close");
21
21
  }, b = a(() => ({
22
- primary: "bg-primary-light text-primary border-primary/20",
23
- success: "bg-success-light text-success-dark border-success/20",
22
+ primary: "bg-primary-light text-primary border-primary/15",
23
+ success: "bg-success-light text-success-dark border-success/25",
24
24
  warning: "bg-warning-light text-warning-dark border-warning/20",
25
- danger: "bg-danger-light text-danger-dark border-danger/20"
25
+ danger: "bg-danger-light text-danger-dark border-danger/15"
26
26
  })[t.variant]), k = a(() => ({
27
- primary: "text-primary",
28
- success: "text-success-dark",
29
- warning: "text-warning-dark",
30
- danger: "text-danger-dark"
27
+ primary: "text-primary!",
28
+ success: "text-success-dark!",
29
+ warning: "text-warning-dark!",
30
+ danger: "text-danger-dark!"
31
31
  })[t.variant]), l = a(() => !t.description && !$().default), x = a(() => [
32
32
  "relative w-full rounded-lg border px-4 [&>svg]:absolute [&>svg]:left-4 [&>svg]:text-foreground",
33
33
  l.value ? "py-3" : "pt-4 pb-2",
@@ -35,7 +35,10 @@ const j = ["role"], E = {
35
35
  l.value ? "[&>svg]:top-1/2 [&>svg]:-translate-y-1/2" : "[&>svg]:top-4 top-4 [&>svg+div]:translate-y-[-3px]",
36
36
  b.value,
37
37
  t.class
38
- ].join(" ")), h = a(() => ["font-medium leading-none tracking-tight", l.value ? "" : "mb-1"].join(" ")), w = a(() => t.role ? t.role : ["danger", "warning"].includes(t.variant) ? "alert" : "status");
38
+ ].join(" ")), h = a(() => [
39
+ "font-medium leading-none tracking-tight text-inherit!",
40
+ l.value ? "" : "mb-1"
41
+ ].join(" ")), w = a(() => t.role ? t.role : ["danger", "warning"].includes(t.variant) ? "alert" : "status");
39
42
  return (s, u) => c.value ? (n(), i("div", {
40
43
  key: 0,
41
44
  class: r(x.value),
@@ -1,4 +1,4 @@
1
- import { defineComponent as k, ref as c, watch as w, computed as a, openBlock as t, createElementBlock as r, normalizeClass as d, renderSlot as g, toDisplayString as b, createBlock as C } from "vue";
1
+ import { defineComponent as k, ref as c, watch as w, computed as a, openBlock as t, createElementBlock as r, normalizeClass as d, renderSlot as b, toDisplayString as g, createBlock as C } from "vue";
2
2
  import _ from "./Icon.vue.js";
3
3
  const y = ["src", "alt"], z = { key: 0 }, A = /* @__PURE__ */ k({
4
4
  __name: "Avatar",
@@ -10,18 +10,18 @@ const y = ["src", "alt"], z = { key: 0 }, A = /* @__PURE__ */ k({
10
10
  rounded: { default: "full" },
11
11
  class: { default: "" }
12
12
  },
13
- setup(n) {
14
- const e = n, s = c(!1), o = c(!1);
13
+ setup(o) {
14
+ const e = o, s = c(!1), n = c(!1);
15
15
  w(
16
16
  () => e.src,
17
17
  () => {
18
- s.value = !1, o.value = !1;
18
+ s.value = !1, n.value = !1;
19
19
  }
20
20
  );
21
21
  const f = () => {
22
- s.value = !0, o.value = !1;
22
+ s.value = !0, n.value = !1;
23
23
  }, i = () => {
24
- o.value = !0, s.value = !1;
24
+ n.value = !0, s.value = !1;
25
25
  }, m = a(() => e.src && !s.value), u = a(() => {
26
26
  if (e.fallback) return e.fallback;
27
27
  if (!e.alt) return "";
@@ -43,7 +43,7 @@ const y = ["src", "alt"], z = { key: 0 }, A = /* @__PURE__ */ k({
43
43
  "2xl": "rounded-2xl",
44
44
  full: "rounded-full"
45
45
  }, v = a(() => [
46
- "relative flex shrink-0 overflow-hidden bg-muted",
46
+ "relative flex shrink-0 overflow-hidden bg-muted border border-border/50",
47
47
  x[e.size],
48
48
  h[e.rounded],
49
49
  e.class
@@ -53,8 +53,8 @@ const y = ["src", "alt"], z = { key: 0 }, A = /* @__PURE__ */ k({
53
53
  }, [
54
54
  m.value ? (t(), r("img", {
55
55
  key: 0,
56
- src: n.src,
57
- alt: n.alt,
56
+ src: o.src,
57
+ alt: o.alt,
58
58
  class: "aspect-square h-full w-full object-cover",
59
59
  onError: f,
60
60
  onLoad: i
@@ -62,8 +62,8 @@ const y = ["src", "alt"], z = { key: 0 }, A = /* @__PURE__ */ k({
62
62
  key: 1,
63
63
  class: d(p.value)
64
64
  }, [
65
- g(l.$slots, "fallback", {}, () => [
66
- u.value ? (t(), r("span", z, b(u.value), 1)) : (t(), C(_, {
65
+ b(l.$slots, "fallback", {}, () => [
66
+ u.value ? (t(), r("span", z, g(u.value), 1)) : (t(), C(_, {
67
67
  key: 1,
68
68
  icon: "lucide:user",
69
69
  class: "h-1/2 w-1/2"
@@ -1,4 +1,4 @@
1
- import { FilePickerValue } from '../FilePicker';
1
+ import { FilePickerValue } from '../FilePicker/FilePicker.vue';
2
2
  import { AvatarSize, AvatarRounded } from '../../types';
3
3
  export interface Props {
4
4
  modelValue?: any;
@@ -1,8 +1,9 @@
1
- import { defineComponent as w, ref as z, computed as f, openBlock as n, createElementBlock as r, normalizeClass as l, createVNode as o, unref as C, withCtx as A, createElementVNode as B, createCommentVNode as g, withModifiers as N } from "vue";
1
+ import { defineComponent as x, ref as w, computed as z, openBlock as n, createElementBlock as o, createElementVNode as b, normalizeClass as l, createVNode as d, withCtx as C, createCommentVNode as f, withModifiers as A } from "vue";
2
2
  import u from "../Icon.vue.js";
3
- import j from "../FilePicker/FilePicker.vue.js";
4
- import E from "../Avatar.vue.js";
5
- const $ = ["onClick"], I = /* @__PURE__ */ w({
3
+ import B from "../FilePicker/FilePicker.vue.js";
4
+ import N from "../Avatar.vue.js";
5
+ const E = { class: "inline-block" }, $ = ["onClick"], I = /* @__PURE__ */ x({
6
+ name: "AvatarUploader",
6
7
  __name: "AvatarUploader",
7
8
  props: {
8
9
  modelValue: { default: null },
@@ -17,81 +18,80 @@ const $ = ["onClick"], I = /* @__PURE__ */ w({
17
18
  className: {}
18
19
  },
19
20
  emits: ["update:modelValue", "change", "error"],
20
- setup(e, { emit: v }) {
21
- const s = e, t = v, i = z(null), c = f(() => i.value || s.modelValue), h = (a) => {
21
+ setup(e, { emit: g }) {
22
+ const v = e, t = g, i = w(null), s = z(() => i.value || v.modelValue), h = (a) => {
22
23
  if (!a || Array.isArray(a)) {
23
- Array.isArray(a) && a.length === 0 && m();
24
+ Array.isArray(a) && a.length === 0 && c();
24
25
  return;
25
26
  }
26
27
  a.base64 && (i.value = a.base64, t("update:modelValue", a.base64)), t("change", a);
27
28
  }, y = (a) => {
28
29
  t("error", a);
29
- }, m = () => {
30
+ }, c = () => {
30
31
  i.value = null, t("update:modelValue", null), t("change", null);
31
- }, k = f(() => [
32
- "group relative inline-block",
33
- // If rounded is full, we need overflow hidden on the container to clip the overlay
34
- s.rounded === "full" ? "rounded-full" : ""
35
- ].join(" "));
36
- return (a, b) => (n(), r("div", {
37
- class: l(k.value)
38
- }, [
39
- o(C(j), {
40
- disabled: !e.editable || e.disabled || e.loading,
41
- "return-format": "base64",
42
- "file-types": ["image/jpeg", "image/png", "image/webp", "image/gif"],
43
- "max-size": e.maxSize,
44
- class: "w-auto h-auto block",
45
- onChange: b[0] || (b[0] = (d) => h(d)),
46
- onError: y
47
- }, {
48
- trigger: A(({ trigger: d, isLoading: x }) => [
49
- B("div", {
50
- class: l(["relative cursor-pointer transition-transform active:scale-95 inline-block", { "cursor-default": !e.editable || e.disabled }]),
51
- onClick: (R) => e.editable && !e.disabled ? d() : null
52
- }, [
53
- o(E, {
54
- src: c.value || void 0,
55
- fallback: e.fallback,
56
- alt: e.alt,
57
- size: e.size,
58
- rounded: e.rounded,
59
- class: l(e.className)
60
- }, null, 8, ["src", "fallback", "alt", "size", "rounded", "class"]),
61
- e.loading || x ? (n(), r("div", {
62
- key: 0,
63
- class: l(["absolute inset-0 flex items-center justify-center bg-black/40 backdrop-blur-[1px] text-white transition-opacity", e.rounded === "full" ? "rounded-full" : "rounded-md"])
64
- }, [
65
- o(u, {
66
- icon: "lucide:loader-2",
67
- class: "animate-spin w-1/3 h-1/3"
68
- })
69
- ], 2)) : e.editable && !e.disabled ? (n(), r("div", {
70
- key: 1,
71
- class: l(["absolute inset-0 flex items-center justify-center bg-black/40 text-white opacity-0 transition-opacity duration-200 group-hover:opacity-100", e.rounded === "full" ? "rounded-full" : "rounded-md"])
72
- }, [
73
- o(u, {
74
- icon: "lucide:camera",
75
- class: "w-1/3 h-1/3"
76
- })
77
- ], 2)) : g("", !0)
78
- ], 10, $)
79
- ]),
80
- _: 1
81
- }, 8, ["disabled", "max-size"]),
82
- c.value && e.editable && !e.disabled && !e.loading ? (n(), r("button", {
83
- key: 0,
84
- type: "button",
85
- class: "absolute -top-1 -right-1 z-10 p-1 bg-background border border-border rounded-full text-muted-foreground shadow-sm hover:text-destructive hover:border-destructive transition-colors opacity-0 group-hover:opacity-100 scale-75 group-hover:scale-100 duration-200 transform",
86
- onClick: N(m, ["stop"]),
87
- title: "Remove image"
32
+ };
33
+ return (a, m) => (n(), o("div", E, [
34
+ b("div", {
35
+ class: l(["relative inline-block group", e.rounded === "full" ? "rounded-full" : "rounded-md"])
88
36
  }, [
89
- o(u, {
90
- icon: "lucide:x",
91
- class: "w-3 h-3"
92
- })
93
- ])) : g("", !0)
94
- ], 2));
37
+ d(N, {
38
+ src: s.value || void 0,
39
+ fallback: e.fallback,
40
+ alt: e.alt,
41
+ size: e.size,
42
+ rounded: e.rounded,
43
+ class: l(e.className)
44
+ }, null, 8, ["src", "fallback", "alt", "size", "rounded", "class"]),
45
+ d(B, {
46
+ disabled: !e.editable || e.disabled || e.loading,
47
+ "return-format": "base64",
48
+ "file-types": ["image/jpeg", "image/png", "image/webp", "image/gif"],
49
+ "max-size": e.maxSize,
50
+ class: "absolute inset-0",
51
+ onChange: m[0] || (m[0] = (r) => h(r)),
52
+ onError: y
53
+ }, {
54
+ trigger: C(({ trigger: r, isLoading: k }) => [
55
+ b("button", {
56
+ type: "button",
57
+ class: l(["absolute inset-0 cursor-pointer", { "cursor-default": !e.editable || e.disabled }]),
58
+ onClick: (j) => e.editable && !e.disabled ? r() : null
59
+ }, [
60
+ e.loading || k ? (n(), o("div", {
61
+ key: 0,
62
+ class: l(["absolute inset-0 flex items-center justify-center bg-black/40 text-white", e.rounded === "full" ? "rounded-full" : "rounded-md"])
63
+ }, [
64
+ d(u, {
65
+ icon: "lucide:loader-2",
66
+ class: "animate-spin w-1/3 h-1/3"
67
+ })
68
+ ], 2)) : e.editable && !e.disabled ? (n(), o("div", {
69
+ key: 1,
70
+ class: l(["absolute inset-0 flex items-center justify-center bg-black/40 text-white opacity-0 group-hover:opacity-100 transition-opacity", e.rounded === "full" ? "rounded-full" : "rounded-md"])
71
+ }, [
72
+ d(u, {
73
+ icon: "lucide:camera",
74
+ class: "w-1/3 h-1/3"
75
+ })
76
+ ], 2)) : f("", !0)
77
+ ], 10, $)
78
+ ]),
79
+ _: 1
80
+ }, 8, ["disabled", "max-size"]),
81
+ s.value && e.editable && !e.disabled && !e.loading ? (n(), o("button", {
82
+ key: 0,
83
+ type: "button",
84
+ class: "absolute -top-1 -right-1 z-10 p-1 bg-background border border-border rounded-full text-muted-foreground shadow-sm hover:text-destructive hover:border-destructive transition-all opacity-0 group-hover:opacity-100 scale-75 group-hover:scale-100",
85
+ onClick: A(c, ["stop"]),
86
+ title: "Remove image"
87
+ }, [
88
+ d(u, {
89
+ icon: "lucide:x",
90
+ class: "w-3 h-3"
91
+ })
92
+ ])) : f("", !0)
93
+ ], 2)
94
+ ]));
95
95
  }
96
96
  });
97
97
  export {
@@ -26,9 +26,9 @@ const B = { class: "flex items-center space-x-2" }, N = ["aria-checked", "data-s
26
26
  }, b = {
27
27
  xs: "h-3.5 w-3.5",
28
28
  sm: "h-4 w-4",
29
- md: "h-5 w-5",
30
- lg: "h-6 w-6",
31
- xl: "h-7 w-7"
29
+ md: "h-4.5 w-4.5",
30
+ lg: "h-5 w-5",
31
+ xl: "h-5.5 w-5.5"
32
32
  }, s = {
33
33
  xs: "h-2.5 w-2.5",
34
34
  sm: "h-3 w-3",
@@ -1,4 +1,4 @@
1
- import { defineComponent as w, computed as y, openBlock as t, createElementBlock as i, toDisplayString as n, createCommentVNode as a, createElementVNode as c, normalizeClass as u, Fragment as V, renderList as _, withKeys as C, withModifiers as B, createVNode as A, createBlock as h } from "vue";
1
+ import { defineComponent as w, computed as y, openBlock as t, createElementBlock as i, toDisplayString as o, createCommentVNode as a, createElementVNode as c, normalizeClass as u, Fragment as V, renderList as _, withKeys as C, withModifiers as B, createVNode as A, createBlock as x } from "vue";
2
2
  import m from "../Icon.vue.js";
3
3
  const K = { class: "w-full" }, N = {
4
4
  key: 0,
@@ -31,8 +31,8 @@ const K = { class: "w-full" }, N = {
31
31
  gap: { default: 4 }
32
32
  },
33
33
  emits: ["update:modelValue", "change"],
34
- setup(r, { emit: x }) {
35
- const s = r, g = x, o = (l) => Array.isArray(s.modelValue) ? s.modelValue.includes(l) : s.modelValue === l, f = (l) => {
34
+ setup(r, { emit: h }) {
35
+ const s = r, g = h, n = (l) => Array.isArray(s.modelValue) ? s.modelValue.includes(l) : s.modelValue === l, f = (l) => {
36
36
  if (s.disabled || s.options.find((d) => d.id === l)?.disabled) return;
37
37
  let e;
38
38
  if (s.multiple) {
@@ -72,16 +72,16 @@ const K = { class: "w-full" }, N = {
72
72
  });
73
73
  return (l, k) => (t(), i("div", K, [
74
74
  r.title || r.description ? (t(), i("div", N, [
75
- r.title ? (t(), i("h3", $, n(r.title), 1)) : a("", !0),
76
- r.description ? (t(), i("p", E, n(r.description), 1)) : a("", !0)
75
+ r.title ? (t(), i("h3", $, o(r.title), 1)) : a("", !0),
76
+ r.description ? (t(), i("p", E, o(r.description), 1)) : a("", !0)
77
77
  ])) : a("", !0),
78
78
  c("div", {
79
79
  class: u(["grid", [b.value, v.value]])
80
80
  }, [
81
81
  (t(!0), i(V, null, _(r.options, (e) => (t(), i("div", {
82
82
  key: e.id,
83
- class: u(["relative flex cursor-pointer rounded-xl border border-border p-4 shadow-sm transition-all duration-200 outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2", [
84
- o(e.id) ? "border-primary bg-accent" : "bg-card hover:border-primary/50 hover:bg-accent",
83
+ class: u(["relative flex cursor-pointer rounded-xl border border-border p-4 transition-all duration-200 outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2", [
84
+ n(e.id) ? "border-primary bg-accent" : "bg-card hover:border-primary/50 hover:bg-accent",
85
85
  r.disabled || e.disabled ? "opacity-50 cursor-not-allowed grayscale" : ""
86
86
  ]]),
87
87
  onClick: (d) => f(e.id),
@@ -93,7 +93,7 @@ const K = { class: "w-full" }, N = {
93
93
  c("div", {
94
94
  class: u([
95
95
  "flex h-10 w-10 items-center justify-center rounded-full transition-colors",
96
- o(e.id) ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground"
96
+ n(e.id) ? "bg-primary/10 text-primary" : "bg-muted text-muted-foreground"
97
97
  ])
98
98
  }, [
99
99
  A(m, {
@@ -106,26 +106,26 @@ const K = { class: "w-full" }, N = {
106
106
  c("div", z, [
107
107
  c("span", {
108
108
  class: u(["font-semibold text-foreground", {
109
- "text-primary": o(e.id)
109
+ "text-primary": n(e.id)
110
110
  }])
111
- }, n(e.title), 3),
111
+ }, o(e.title), 3),
112
112
  e.badge ? (t(), i("span", {
113
113
  key: 0,
114
114
  class: u([
115
115
  "inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium",
116
- o(e.id) ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
116
+ n(e.id) ? "bg-primary text-primary-foreground" : "bg-muted text-muted-foreground"
117
117
  ])
118
- }, n(e.badge), 3)) : a("", !0)
118
+ }, o(e.badge), 3)) : a("", !0)
119
119
  ]),
120
- e.description ? (t(), i("span", D, n(e.description), 1)) : a("", !0)
120
+ e.description ? (t(), i("span", D, o(e.description), 1)) : a("", !0)
121
121
  ])
122
122
  ]),
123
- o(e.id) ? (t(), i("div", F, [
124
- r.multiple ? (t(), h(m, {
123
+ n(e.id) ? (t(), i("div", F, [
124
+ r.multiple ? (t(), x(m, {
125
125
  key: 0,
126
126
  icon: "lucide:check-square",
127
127
  class: "h-5 w-5"
128
- })) : (t(), h(m, {
128
+ })) : (t(), x(m, {
129
129
  key: 1,
130
130
  icon: "lucide:check-circle-2",
131
131
  class: "h-5 w-5"
@@ -61,9 +61,9 @@ const F = ["data-state"], L = { class: "flex items-center justify-center" }, U =
61
61
  };
62
62
  return (e, n) => (c(), a("tr", {
63
63
  class: u(["border-b border-border/70 transition-colors data-[state=selected]:bg-muted h-full", [
64
- t.hoverable ? "hover:bg-muted/20" : "",
64
+ t.hoverable ? "hover:bg-muted/80" : "",
65
65
  t.striped && t.index % 2 === 1 ? "bg-muted/20" : "bg-background",
66
- t.isSelected ? "bg-muted/10! hover:bg-muted/30" : "",
66
+ t.isSelected ? "bg-muted! hover:bg-muted/30" : "",
67
67
  "group"
68
68
  ]]),
69
69
  "data-state": t.isSelected ? "selected" : void 0,