vlite3 0.2.1 → 0.2.2

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
@@ -4,14 +4,10 @@ A lightweight Vue 3 UI component library built with Tailwind CSS, created for pe
4
4
 
5
5
  ## Installation
6
6
 
7
- ### NPM
8
-
9
7
  ```bash
10
8
  npm install vlite3
11
9
  ```
12
10
 
13
- ### Yarn
14
-
15
11
  ```bash
16
12
  yarn add vlite3
17
13
  ```
@@ -55,34 +51,148 @@ import { Button, Input } from 'vlite3'
55
51
  </template>
56
52
  ```
57
53
 
58
- ## 🎨 Theming & Customization
59
-
60
- vlite3 uses a semantic theming system inspired by **shadcn/ui** and compatible with **Tailwind CSS v4**. All colors are defined as CSS variables, making it easy to customize the look and feel of your application including Dark Mode support.
61
-
62
- ### Semantic Colors
63
-
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
-
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` | `text-muted` | Muted Text | Secondary text, Unactive Link, description. |
77
- | `--muted-foreground` | `text-muted-foreground` | Muted text color | Secondary text, hints, placeholders. |
78
- | `--accent` | `bg-accent` | Accent background | Used for hover states, selection highlights. |
79
- | `--accent-foreground` | `text-accent-foreground` | Accent text color | Text color on accent backgrounds. |
80
- | `--destructive` | `bg-destructive` | Destructive color | Used for error states and destructive actions. |
81
- | `--destructive-foreground` | `text-destructive-foreground` | Destructive text color | Text color on destructive backgrounds. |
82
- | `--border` | `border` | Default border color | Borders for inputs, cards, and dividers. |
83
- | `--input` | `border-input` | Input border color | Borders specifically for form inputs. |
84
- | `--ring` | `ring-ring` | Focus ring color | Outline color for focused elements. |
85
- | `--radius` | `rounded` | Border radius | Global border radius for components. |
54
+ ## Global Configuration (Registry System)
55
+
56
+ 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.
57
+
58
+ ### Setting up the Plugin
59
+
60
+ In your `main.ts` or `main.js`, import `createVLite` and `vScrollReveal` and register your services:
61
+
62
+ ```typescript
63
+ import { createApp } from 'vue'
64
+ import App from './App.vue'
65
+ import { env, createVLite, vScrollReveal, GoogleSignInPlugin } from 'vlite3'
66
+
67
+ const app = createApp(App)
68
+
69
+ // Register global directives
70
+ app.directive('scroll-reveal', vScrollReveal)
71
+
72
+ app.use(GoogleSignInPlugin, {
73
+ clientId: env.VITE_GOOGLE_CLIENT_ID,
74
+ })
75
+
76
+ // Initialize VLite with custom configuration
77
+ const vlite = createVLite({
78
+ services: {
79
+ /**
80
+ * Global File Upload Handler
81
+ *
82
+ * This function will be called automatically by:
83
+ * - useFileUpload() composable
84
+ * - Form components (when using 'file', 'fileUploader', or 'avatarUpload' types)
85
+ *
86
+ * @param file - The File object to upload
87
+ * @param folderId - (Optional) Folder ID passed from component props
88
+ * @returns Promise<string> - The public URL of the uploaded file
89
+ */
90
+ upload: async (file, folderId) => {
91
+ // Example: Upload to your own backend
92
+ const formData = new FormData()
93
+ formData.append('file', file)
94
+ if (folderId) formData.append('folder_id', folderId)
95
+
96
+ // Replace with your actual API call (e.g., Axios, Fetch)
97
+ const response = await fetch(
98
+ '[https://api.yourdomain.com/v1/upload](https://api.yourdomain.com/v1/upload)',
99
+ {
100
+ method: 'POST',
101
+ body: formData,
102
+ headers: {
103
+ Authorization: 'Bearer ...',
104
+ },
105
+ }
106
+ )
107
+
108
+ if (!response.ok) throw new Error('Upload failed')
109
+
110
+ const data = await response.json()
111
+ return data.url // MUST return the file URL string
112
+ },
113
+ },
114
+ })
115
+
116
+ app.use(vlite)
117
+ app.mount('#app')
118
+ ```
119
+
120
+ ### How it works
121
+
122
+ Once registered, you don't need to pass upload handlers to individual components.
123
+
124
+ 1. **Automatic Injection**: The `Form` component detects input types like `file`, `avatarUpload`, or `fileUploader`.
125
+ 2. **Parallel Processing**: When the form is submitted, it automatically uploads all files in **parallel** using your registered `upload` service.
126
+ 3. **URL Replacement**: The File objects in your form data are replaced with the returned URLs before the final `onSubmit` event is triggered.
127
+
128
+ ## 4. Usage
129
+
130
+ Import components directly in your Vue files:
131
+
132
+ ```vue
133
+ <script setup>
134
+ import { Button, Input, Form } from 'vlite3'
135
+
136
+ // The form will automatically use the global upload service defined in main.ts
137
+ const schema = [
138
+ {
139
+ name: 'avatar',
140
+ label: 'Profile Picture',
141
+ type: 'avatarUpload',
142
+ },
143
+ {
144
+ name: 'documents',
145
+ label: 'Attachments',
146
+ type: 'fileUploader',
147
+ props: { multiple: true },
148
+ },
149
+ ]
150
+
151
+ const handleSubmit = (payload) => {
152
+ // payload.values.avatar will be a URL string (e.g., "https://api...")
153
+ // payload.values.documents will be an array of URL strings
154
+ console.log(payload.values)
155
+ }
156
+ </script>
157
+
158
+ <template>
159
+ <div class="">
160
+ <Form :schema="schema" @onSubmit="handleSubmit" />
161
+ </div>
162
+ </template>
163
+ ```
164
+
165
+ # 🎨 Theming & Customization
166
+
167
+ Reference guide for **vlite3** and the Tailwind CSS v4 theming system. This setup uses a semantic design token approach inspired by shadcn/ui and optimized for Tailwind CSS v4.
168
+
169
+ All colors are defined as CSS variables, allowing you to customize the appearance of your application with minimal effort, including full Dark Mode support.
170
+
171
+ ---
172
+
173
+ ## Semantic Colors
174
+
175
+ Override these variables in `:root` or within a `.dark` class (when using class-based dark mode) to adjust your theme.
176
+
177
+ | Variable | Utility Class | Description | Recommended Usage |
178
+ | -------------------------------- | ----------------------------- | --------------------------------------- | ----------------------------------------------- |
179
+ | `--color-background` | `bg-background` | Default page background (white) | Main application background |
180
+ | `--color-foreground` | `text-foreground` | Default text color (gray-900) | Primary content text |
181
+ | `--color-card` | `bg-card` | Card background (gray-100) | Cards, containers, surfaces, panels, dialogs |
182
+ | `--color-primary` | `bg-primary` | Primary brand color (blue) | Main actions, buttons, active states |
183
+ | `--color-primary-foreground` | `text-primary-foreground` | Text on primary background (white) | Text/icons displayed on primary elements |
184
+ | `--color-secondary` | `bg-secondary` | Secondary background (gray-200) | Secondary actions, muted sections |
185
+ | `--color-secondary-foreground` | `text-secondary-foreground` | Text on secondary background (gray-900) | Content displayed on secondary elements |
186
+ | `--color-muted` | `bg-muted` | Muted background (gray-150) | Subtle surfaces, table headers, disabled states |
187
+ | `--color-muted` | `text-muted` | Muted text (gray-600) | Secondary text, inactive links, descriptions |
188
+ | `--color-accent` | `bg-accent` | Accent background (gray-150) | Hover states, selection highlights |
189
+ | `--color-accent-foreground` | `text-accent-foreground` | Text on accent background (gray-900) | Content displayed on accent elements |
190
+ | `--color-destructive` | `bg-destructive` | Destructive color (red) | Errors, warnings, destructive actions |
191
+ | `--color-destructive-foreground` | `text-destructive-foreground` | Text on destructive background (white) | Content displayed on destructive elements |
192
+ | `--color-border` | `border` | Default border color (gray-250) | Inputs, cards, dividers |
193
+ | `--radius` | `rounded` | Global border radius | Shared radius across components |
194
+
195
+ ---
86
196
 
87
197
  ### Extended Color Variants
88
198
 
@@ -119,31 +229,17 @@ vlite3 also provides additional utility colors for specific feedback states:
119
229
  | `--color-info` | `text-info`, `bg-info` | For informational messages/badges. |
120
230
  | `--color-danger` | `text-danger`, `bg-danger` | Alias for destructive in some contexts. |
121
231
 
122
- ### Example Customization
123
-
124
- To customize the theme, simply override the CSS variables in your main CSS file:
125
-
126
- ```css
127
- @layer base {
128
- :root {
129
- --primary: #3b82f6; /* Blue-500 */
130
- --primary-foreground: #ffffff;
131
- --radius: 0.75rem;
132
- }
133
-
134
- .dark {
135
- --primary: #60a5fa; /* Blue-400 */
136
- --primary-foreground: #000000;
137
- }
138
- }
139
- ```
232
+ ---
140
233
 
141
234
  ## 8. Typography Scale System
142
235
 
143
- The system is divided into two groups:
236
+ The typography system is organized into two complementary scales:
144
237
 
145
- - Compact scale (prefixed with `--text--fs-*`) for smaller text
146
- - Progressive scale (prefixed with `--text-fs-*`) for base and larger text
238
+ - Compact scale (prefixed with `--text--fs-*`)
239
+ - Progressive scale (prefixed with `--text-fs-*`)
240
+
241
+ Use the progressive scale only when you need finer visual control beyond the standard Tailwind size tokens.
242
+ For most layout and content needs, prefer the default Tailwind text sizes to maintain consistency.
147
243
 
148
244
  ### Compact Text Scale
149
245
 
@@ -156,6 +252,11 @@ The system is divided into two groups:
156
252
  --text--fs-6: 0.6em;
157
253
  --text--fs-7: 0.55em;
158
254
  --text--fs-8: 0.5em;
255
+ ```
256
+
257
+ ### Progressive Text Scale
258
+
259
+ ```css
159
260
  --text-fs-0.5: 1.05em;
160
261
  --text-fs-1: 1.1em;
161
262
  --text-fs-1.5: 1.14em;
@@ -176,13 +277,19 @@ The system is divided into two groups:
176
277
  --text-fs-9: 1.8em;
177
278
  --text-fs-9.5: 2em;
178
279
  --text-fs-10: 2.5em;
280
+ ```
281
+
282
+ ### Tailwind Size Tokens
179
283
 
284
+ ```css
180
285
  --text-xs: 0.75rem --text-sm: 0.875rem --text-base: 1rem --text-lg: 1.125rem --text-xl: 1.25rem
181
286
  --text-2xl: 1.5rem --text-3xl: 1.875rem --text-4xl: 2.25rem --text-5xl: 3rem --text-6xl: 4rem;
182
287
  ```
183
288
 
184
289
  ---
185
290
 
291
+ ### Usage Examples
292
+
186
293
  ```html
187
294
  <p class="text-fs-2">Body text</p>
188
295
 
@@ -191,6 +298,18 @@ The system is divided into two groups:
191
298
  <h1 class="text-xl font-semibold">Page Title</h1>
192
299
  ```
193
300
 
301
+ ## Hard Rules
302
+
303
+ Follow these rules strictly to ensure visual consistency and predictable styling across the system:
304
+
305
+ - Use `border` instead of `border-border` (the default border color (gray-250) is already applied).
306
+ - Use `rounded` instead of `rounded-rounded`.
307
+ - Use `bg-muted` instead of `bg-secondary/20`.
308
+ - Use `gap-x-*` instead of applying `ml-*` or `mr-*` directly on sibling items.
309
+ - Use `gap-y-*` instead of applying `mt
310
+
311
+ ---
312
+
194
313
  ## ✅ Components
195
314
 
196
315
  - **Button**
@@ -251,7 +370,7 @@ The system is divided into two groups:
251
370
  - **ProgressBar**
252
371
  - **Spinner**
253
372
 
254
- # Complete reference for AI agents and developers:
373
+ ## Complete reference for AI agents and developers:
255
374
 
256
375
  - [llms.txt](https://github.com/safdar-azeem/vlite3/blob/main/llms.txt).
257
376
  - [llms-theming.txt](https://github.com/safdar-azeem/vlite3/blob/main/llms-theming.txt).
@@ -1,4 +1,4 @@
1
- import { defineComponent as G, defineAsyncComponent as J, ref as B, computed as I, watch as C, toRef as Q, onMounted as W, onBeforeUnmount as X, openBlock as o, createElementBlock as c, createVNode as p, createCommentVNode as u, renderSlot as v, createElementVNode as g, unref as n, normalizeStyle as Y, normalizeClass as T, createBlock as m, Fragment as N, renderList as Z, withCtx as V, toDisplayString as ee, createSlots as te, mergeProps as le, nextTick as se } from "vue";
1
+ import { defineComponent as G, defineAsyncComponent as J, ref as B, computed as I, watch as C, toRef as Q, onMounted as W, onBeforeUnmount as X, openBlock as o, createElementBlock as c, createVNode as x, createCommentVNode as i, renderSlot as v, unref as n, normalizeStyle as Y, normalizeClass as T, createBlock as m, Fragment as N, renderList as Z, withCtx as V, createElementVNode as p, toDisplayString as ee, createSlots as te, mergeProps as le, nextTick as se } from "vue";
2
2
  import S from "../Icon.vue.js";
3
3
  import oe from "../Input.vue.js";
4
4
  import ne from "./DropdownItem.vue.js";
@@ -22,7 +22,7 @@ const ie = ["dir"], ue = {
22
22
  key: 3,
23
23
  class: "flex justify-center py-2"
24
24
  }, be = {
25
- key: 2,
25
+ key: 3,
26
26
  class: "shrink-0 border-t mt-1 pt-1"
27
27
  }, Ie = /* @__PURE__ */ G({
28
28
  __name: "DropdownMenu",
@@ -45,34 +45,34 @@ const ie = ["dir"], ue = {
45
45
  direction: { default: "ltr" }
46
46
  },
47
47
  emits: ["select", "close", "load-more", "search"],
48
- setup(r, { emit: _ }) {
49
- const j = J(() => import("./Dropdown.vue2.js")), t = r, i = _, M = B(null), f = B(""), { getMenuId: D, getAllRecursiveIds: E } = ae(), P = I(() => t.remote ? t.searchable : t.searchable && (t.options?.length || 0) > 9);
50
- let k = null;
48
+ setup(r, { emit: j }) {
49
+ const D = J(() => import("./Dropdown.vue2.js")), t = r, u = j, $ = B(null), f = B(""), { getMenuId: E, getAllRecursiveIds: P } = ae(), _ = I(() => t.remote ? t.searchable : t.searchable && (t.options?.length || 0) > 9);
50
+ let g = null;
51
51
  C(f, (e) => {
52
- t.remote && (k && clearTimeout(k), k = setTimeout(() => {
53
- e && i("search", e);
52
+ t.remote && (g && clearTimeout(g), g = setTimeout(() => {
53
+ e && u("search", e);
54
54
  }, 100));
55
55
  });
56
56
  const H = (e) => {
57
57
  const s = e.target;
58
- s.scrollTop + s.clientHeight >= s.scrollHeight - 50 && t.hasMore && !t.loading && i("load-more");
59
- }, b = (e, s) => {
60
- e.disabled || i("select", e);
58
+ s.scrollTop + s.clientHeight >= s.scrollHeight - 50 && t.hasMore && !t.loading && u("load-more");
59
+ }, k = (e, s) => {
60
+ e.disabled || u("select", e);
61
61
  }, {
62
62
  focusedIndex: h,
63
- isKeyboardMode: w,
63
+ isKeyboardMode: b,
64
64
  filteredOptions: R,
65
65
  // rename
66
- handleKeyDown: $,
66
+ handleKeyDown: M,
67
67
  handleMouseMove: O,
68
- onMouseEnterItem: x,
68
+ onMouseEnterItem: w,
69
69
  scrollToIndex: z
70
70
  } = ce({
71
71
  options: Q(t, "options"),
72
72
  searchQuery: f,
73
- containerRef: M,
74
- emit: (e, ...s) => i(e, ...s),
75
- handleSelect: (e, s) => b(e)
73
+ containerRef: $,
74
+ emit: (e, ...s) => u(e, ...s),
75
+ handleSelect: (e, s) => k(e)
76
76
  }), y = I(() => t.remote ? f.value ? t.options : t.cachedOptions.length ? t.cachedOptions : t.options : R.value), A = (e) => {
77
77
  if (!(!t.selected || typeof t.selected != "object") && e.key && e.key in t.selected)
78
78
  return t.selected[e.key];
@@ -84,7 +84,7 @@ const ie = ["dir"], ue = {
84
84
  key: s.key,
85
85
  data: s.data
86
86
  };
87
- i("select", l);
87
+ u("select", l);
88
88
  }, U = (e, s) => {
89
89
  let l = s.value;
90
90
  e.key && (l = { [e.key]: l });
@@ -94,7 +94,7 @@ const ie = ["dir"], ue = {
94
94
  data: s.data,
95
95
  key: e.key
96
96
  };
97
- i("select", d);
97
+ u("select", d);
98
98
  }, q = async () => {
99
99
  await se();
100
100
  let e = -1;
@@ -106,15 +106,15 @@ const ie = ["dir"], ue = {
106
106
  h.value = -1;
107
107
  }
108
108
  ), W(() => {
109
- q(), window.addEventListener("keydown", $);
109
+ q(), window.addEventListener("keydown", M);
110
110
  }), X(() => {
111
- window.removeEventListener("keydown", $);
111
+ window.removeEventListener("keydown", M);
112
112
  }), (e, s) => (o(), c("div", {
113
113
  class: "dropdown-menu w-full min-w-[150px] flex flex-col",
114
114
  dir: r.direction
115
115
  }, [
116
- P.value ? (o(), c("div", ue, [
117
- p(oe, {
116
+ _.value ? (o(), c("div", ue, [
117
+ x(oe, {
118
118
  modelValue: f.value,
119
119
  "onUpdate:modelValue": s[0] || (s[0] = (l) => f.value = l),
120
120
  placeholder: "Search...",
@@ -124,13 +124,14 @@ const ie = ["dir"], ue = {
124
124
  variant: "transparent",
125
125
  "show-clear-button": !1
126
126
  }, null, 8, ["modelValue"])
127
- ])) : u("", !0),
127
+ ])) : i("", !0),
128
128
  e.$slots.header ? (o(), c("div", fe, [
129
129
  v(e.$slots, "header")
130
- ])) : u("", !0),
131
- g("div", {
130
+ ])) : i("", !0),
131
+ t?.options.length > 0 || e.$slots.menu ? (o(), c("div", {
132
+ key: 2,
132
133
  ref_key: "containerRef",
133
- ref: M,
134
+ ref: $,
134
135
  tabindex: "0",
135
136
  role: "menu",
136
137
  class: T([
@@ -142,55 +143,55 @@ const ie = ["dir"], ue = {
142
143
  (...l) => n(O) && n(O)(...l)),
143
144
  onScroll: H
144
145
  }, [
145
- y.value.length === 0 && r.options?.length > 0 && !r.loading ? (o(), c("div", me, " No options found ")) : u("", !0),
146
+ y.value.length === 0 && r.options?.length > 0 && !r.loading ? (o(), c("div", me, " No options found ")) : i("", !0),
146
147
  r.layout === "grouped" ? (o(), m(de, {
147
148
  key: 1,
148
149
  options: y.value,
149
150
  selected: r.selected,
150
151
  selectable: r.selectable,
151
152
  columns: r.columns,
152
- onSelect: b
153
+ onSelect: k
153
154
  }, null, 8, ["options", "selected", "selectable", "columns"])) : (o(!0), c(N, { key: 2 }, Z(y.value, (l, d) => (o(), c(N, { key: d }, [
154
155
  l.label === "---" ? (o(), c("div", he)) : l.data?.isBoolean ? (o(), m(re, {
155
156
  key: 1,
156
157
  option: l,
157
158
  value: F(l),
158
- focused: n(w) && n(h) === d,
159
+ focused: n(b) && n(h) === d,
159
160
  onChange: K,
160
- onMouseenter: (a) => n(x)(d)
161
- }, null, 8, ["option", "value", "focused", "onMouseenter"])) : l.children && l.children.length > 0 ? (o(), m(n(j), {
161
+ onMouseenter: (a) => n(w)(d)
162
+ }, null, 8, ["option", "value", "focused", "onMouseenter"])) : l.children && l.children.length > 0 ? (o(), m(n(D), {
162
163
  key: 2,
163
164
  position: l.position || t.nestedPosition,
164
165
  offset: l.offset || t.nestedOffset,
165
166
  class: "w-full",
166
167
  options: l.children,
167
168
  selected: A(l),
168
- menuId: n(D)(l),
169
+ menuId: n(E)(l),
169
170
  nestedPosition: t.nestedPosition,
170
171
  nestedOffset: t.nestedOffset,
171
172
  selectable: t.selectable,
172
- ignoreClickOutside: n(E)(l.children),
173
+ ignoreClickOutside: n(P)(l.children),
173
174
  direction: r.direction,
174
175
  onOnSelect: (a) => U(l, a)
175
176
  }, {
176
177
  trigger: V(() => [
177
- g("div", {
178
+ p("div", {
178
179
  "data-dropdown-item": "",
179
180
  class: T(["relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm font-medium outline-none transition-colors justify-between w-full", [
180
- n(w) && n(h) === d ? "bg-accent text-accent-foreground" : "hover:bg-accent hover:text-accent-foreground",
181
+ n(b) && n(h) === d ? "bg-accent text-accent-foreground" : "hover:bg-accent hover:text-accent-foreground",
181
182
  l.disabled ? "opacity-50 cursor-not-allowed" : ""
182
183
  ]]),
183
- onMouseenter: (a) => n(x)(d)
184
+ onMouseenter: (a) => n(w)(d)
184
185
  }, [
185
- g("div", ve, [
186
+ p("div", ve, [
186
187
  l.icon ? (o(), m(S, {
187
188
  key: 0,
188
189
  icon: l.icon,
189
190
  class: "mr-2 h-4 w-4 shrink-0 mt-0.5"
190
- }, null, 8, ["icon"])) : u("", !0),
191
- g("span", ge, ee(l.label), 1)
191
+ }, null, 8, ["icon"])) : i("", !0),
192
+ p("span", ge, ee(l.label), 1)
192
193
  ]),
193
- p(S, {
194
+ x(S, {
194
195
  icon: r.direction === "rtl" ? "lucide:chevron-left" : "lucide:chevron-right",
195
196
  class: "h-4 w-4 text-muted-foreground shrink-0 ml-2"
196
197
  }, null, 8, ["icon"])
@@ -202,10 +203,10 @@ const ie = ["dir"], ue = {
202
203
  option: l,
203
204
  index: d,
204
205
  selected: L(l),
205
- focused: n(w) && n(h) === d,
206
+ focused: n(b) && n(h) === d,
206
207
  selectable: r.selectable,
207
- onClick: (a) => b(l),
208
- onMouseenter: (a) => n(x)(d)
208
+ onClick: (a) => k(l),
209
+ onMouseenter: (a) => n(w)(d)
209
210
  }, te({ _: 2 }, [
210
211
  e.$slots.item ? {
211
212
  name: "default",
@@ -217,16 +218,16 @@ const ie = ["dir"], ue = {
217
218
  ]), 1032, ["option", "index", "selected", "focused", "selectable", "onClick", "onMouseenter"]))
218
219
  ], 64))), 128)),
219
220
  r.loading ? (o(), c("div", ke, [
220
- p(S, {
221
+ x(S, {
221
222
  icon: "lucide:loader-2",
222
223
  class: "w-4 h-4 animate-spin text-muted-foreground"
223
224
  })
224
- ])) : u("", !0),
225
+ ])) : i("", !0),
225
226
  v(e.$slots, "menu")
226
- ], 38),
227
+ ], 38)) : i("", !0),
227
228
  e.$slots.footer ? (o(), c("div", be, [
228
229
  v(e.$slots, "footer")
229
- ])) : u("", !0)
230
+ ])) : i("", !0)
230
231
  ], 8, ie));
231
232
  }
232
233
  });
@@ -1,6 +1,6 @@
1
1
  export interface GoogleLoginProps {
2
- clientId: string;
3
2
  buttonText?: string;
3
+ btnClass?: string;
4
4
  variant?: any;
5
5
  size?: any;
6
6
  rounded?: any;
@@ -10,7 +10,7 @@ declare function __VLS_template(): {
10
10
  attrs: Partial<{}>;
11
11
  slots: {
12
12
  default?(_: {
13
- login: () => Promise<void>;
13
+ login: () => void;
14
14
  loading: boolean;
15
15
  disabled: boolean;
16
16
  }): any;
@@ -31,7 +31,7 @@ declare const __VLS_component: import('vue').DefineComponent<GoogleLoginProps, {
31
31
  variant: any;
32
32
  rounded: any;
33
33
  buttonText: string;
34
- }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
34
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, HTMLDivElement>;
35
35
  declare const _default: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
36
36
  export default _default;
37
37
  type __VLS_WithTemplateSlots<T, S> = T & {
@@ -0,0 +1,60 @@
1
+ import { defineComponent as d, ref as u, openBlock as c, createElementBlock as f, renderSlot as m, createVNode as g, normalizeClass as v, unref as b, withCtx as C, createElementVNode as h, toDisplayString as k } from "vue";
2
+ import { useTokenClient as w } from "../node_modules/vue3-google-signin/dist/index.es.js";
3
+ import z from "./Button.vue.js";
4
+ const x = { class: "google-login-wrapper inline-block w-full" }, y = { class: "font-medium" }, L = /* @__PURE__ */ d({
5
+ __name: "GoogleLogin",
6
+ props: {
7
+ buttonText: { default: "Sign in with Google" },
8
+ btnClass: {},
9
+ variant: { default: "outline" },
10
+ size: { default: "md" },
11
+ rounded: { default: "md" },
12
+ disabled: { type: Boolean, default: !1 }
13
+ },
14
+ emits: ["success", "error"],
15
+ setup(e, { emit: n }) {
16
+ const s = e, o = n, l = u(!1), { login: i, isReady: r } = w({
17
+ onSuccess: (a) => {
18
+ l.value = !1, o("success", a);
19
+ },
20
+ onError: (a) => {
21
+ l.value = !1, o("error", a);
22
+ }
23
+ }), t = () => {
24
+ if (!(s.disabled || l.value)) {
25
+ l.value = !0;
26
+ try {
27
+ i();
28
+ } catch (a) {
29
+ l.value = !1, o("error", a);
30
+ }
31
+ }
32
+ };
33
+ return (a, S) => (c(), f("div", x, [
34
+ m(a.$slots, "default", {
35
+ login: t,
36
+ loading: l.value,
37
+ disabled: e.disabled
38
+ }, () => [
39
+ g(z, {
40
+ variant: e.variant,
41
+ size: e.size,
42
+ rounded: e.rounded,
43
+ disabled: !b(r) || e.disabled || l.value,
44
+ loading: l.value,
45
+ class: v([e.btnClass, "w-full"]),
46
+ icon: "flat-color-icons:google",
47
+ onClick: t
48
+ }, {
49
+ default: C(() => [
50
+ h("span", y, k(e.buttonText), 1)
51
+ ]),
52
+ _: 1
53
+ }, 8, ["variant", "size", "rounded", "disabled", "loading", "class"])
54
+ ])
55
+ ]));
56
+ }
57
+ });
58
+ export {
59
+ L as default
60
+ };
@@ -0,0 +1,4 @@
1
+ import f from "./GoogleLogin.vue.js";
2
+ export {
3
+ f as default
4
+ };
@@ -0,0 +1,7 @@
1
+ import o from "./ProgressBar.vue2.js";
2
+ /* empty css */
3
+ import r from "../../_virtual/_plugin-vue_export-helper.js";
4
+ const m = /* @__PURE__ */ r(o, [["__scopeId", "data-v-454a1505"]]);
5
+ export {
6
+ m as default
7
+ };