@queuezero/vue 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,203 @@
1
+ # @queuezero/vue
2
+
3
+ Vue components and composables for QueueZero viral waitlists.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @queuezero/vue
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```vue
14
+ <script setup>
15
+ import { provideWaitlist, WaitlistForm, WaitlistStatus, ReferralShare } from '@queuezero/vue';
16
+
17
+ // Get referral code from URL if present
18
+ const referrerCode = new URLSearchParams(window.location.search).get('ref');
19
+
20
+ // Provide waitlist to all child components
21
+ provideWaitlist('my-campaign', {
22
+ apiUrl: 'https://api.queuezero.io'
23
+ });
24
+ </script>
25
+
26
+ <template>
27
+ <WaitlistForm
28
+ :referrer-code="referrerCode"
29
+ @success="(res) => console.log('Joined!', res)"
30
+ />
31
+ <WaitlistStatus />
32
+ <ReferralShare show-social-buttons />
33
+ </template>
34
+ ```
35
+
36
+ ## Plugin Usage
37
+
38
+ For app-wide integration:
39
+
40
+ ```ts
41
+ import { createApp } from 'vue';
42
+ import { createWaitlistPlugin } from '@queuezero/vue';
43
+
44
+ const app = createApp(App);
45
+
46
+ app.use(createWaitlistPlugin({
47
+ campaign: 'my-campaign',
48
+ config: { apiUrl: 'https://api.queuezero.io' }
49
+ }));
50
+
51
+ app.mount('#app');
52
+ ```
53
+
54
+ ## Components
55
+
56
+ ### WaitlistForm
57
+
58
+ Ready-to-use signup form.
59
+
60
+ ```vue
61
+ <template>
62
+ <!-- Basic -->
63
+ <WaitlistForm />
64
+
65
+ <!-- With options -->
66
+ <WaitlistForm
67
+ :referrer-code="referrerCode"
68
+ :metadata="{ role: 'Developer' }"
69
+ placeholder="Enter your work email"
70
+ button-text="Get Early Access"
71
+ @success="onSuccess"
72
+ @error="onError"
73
+ />
74
+
75
+ <!-- With scoped slot -->
76
+ <WaitlistForm v-slot="{ email, setEmail, submit, loading, error }">
77
+ <input :value="email" @input="setEmail($event.target.value)" />
78
+ <button @click="submit">{{ loading ? '...' : 'Join' }}</button>
79
+ </WaitlistForm>
80
+ </template>
81
+ ```
82
+
83
+ ### WaitlistStatus
84
+
85
+ Displays position, score, and referral count.
86
+
87
+ ```vue
88
+ <template>
89
+ <!-- Basic -->
90
+ <WaitlistStatus />
91
+
92
+ <!-- With options -->
93
+ <WaitlistStatus
94
+ :show-score="true"
95
+ :show-referrals="true"
96
+ position-label="Your position:"
97
+ />
98
+
99
+ <!-- With scoped slot -->
100
+ <WaitlistStatus v-slot="status">
101
+ <h2>#{{ status.position }}</h2>
102
+ <p>{{ status.priority_score }} points</p>
103
+ </WaitlistStatus>
104
+ </template>
105
+ ```
106
+
107
+ ### ReferralShare
108
+
109
+ Share referral link with copy and social buttons.
110
+
111
+ ```vue
112
+ <template>
113
+ <!-- Basic -->
114
+ <ReferralShare />
115
+
116
+ <!-- With social buttons -->
117
+ <ReferralShare
118
+ show-social-buttons
119
+ share-message="Join me on this awesome waitlist!"
120
+ />
121
+
122
+ <!-- With scoped slot -->
123
+ <ReferralShare v-slot="{ link, code, copy, copied }">
124
+ <code>{{ code }}</code>
125
+ <button @click="copy">{{ copied ? 'Copied!' : 'Copy' }}</button>
126
+ </ReferralShare>
127
+ </template>
128
+ ```
129
+
130
+ ## Composables
131
+
132
+ ### useWaitlist
133
+
134
+ Standalone composable for full control.
135
+
136
+ ```vue
137
+ <script setup>
138
+ import { useWaitlist } from '@queuezero/vue';
139
+
140
+ const { status, loading, join, getReferralLink } = useWaitlist('my-campaign', {
141
+ apiUrl: 'https://api.queuezero.io',
142
+ });
143
+
144
+ async function handleSubmit(email) {
145
+ await join(email, { role: 'Developer' });
146
+ }
147
+ </script>
148
+ ```
149
+
150
+ ### provideWaitlist / useWaitlistContext
151
+
152
+ For component tree sharing.
153
+
154
+ ```vue
155
+ <!-- Parent.vue -->
156
+ <script setup>
157
+ import { provideWaitlist } from '@queuezero/vue';
158
+
159
+ provideWaitlist('my-campaign');
160
+ </script>
161
+
162
+ <!-- Child.vue -->
163
+ <script setup>
164
+ import { useWaitlistContext } from '@queuezero/vue';
165
+
166
+ const { status, join } = useWaitlistContext();
167
+ </script>
168
+ ```
169
+
170
+ ## Styling
171
+
172
+ Components use `qz-*` class names:
173
+
174
+ ```css
175
+ .qz-form { }
176
+ .qz-form-row { display: flex; gap: 8px; }
177
+ .qz-form-input { flex: 1; padding: 12px; }
178
+ .qz-form-button { padding: 12px 24px; }
179
+ .qz-form-error { color: red; }
180
+
181
+ .qz-status { display: flex; gap: 16px; }
182
+ .qz-status-label { font-size: 12px; }
183
+ .qz-status-value { font-size: 24px; font-weight: bold; }
184
+
185
+ .qz-share-input { flex: 1; }
186
+ .qz-share-social { display: flex; gap: 8px; }
187
+ ```
188
+
189
+ ## TypeScript
190
+
191
+ Full TypeScript support:
192
+
193
+ ```ts
194
+ import type {
195
+ UseWaitlistReturn,
196
+ WaitlistFormProps,
197
+ UserStatus
198
+ } from '@queuezero/vue';
199
+ ```
200
+
201
+ ## License
202
+
203
+ MIT
@@ -0,0 +1,374 @@
1
+ import * as vue from 'vue';
2
+ import { Ref, App, InjectionKey, PropType, VNode } from 'vue';
3
+ import { UserStatus, PublicCampaignConfig, UserMetadata, SubmitResponse, QueueZeroConfig } from 'queuezero';
4
+ export { InMemoryStorageAdapter, LeadStatus, LocalStorageAdapter, QueueZeroClient, QueueZeroConfig, SubmitResponse, UserMetadata, UserStatus } from 'queuezero';
5
+
6
+ /**
7
+ * @queuezero/vue - Types
8
+ *
9
+ * TypeScript type definitions for Vue components and composables.
10
+ */
11
+
12
+ /**
13
+ * Waitlist composable return value
14
+ */
15
+ interface UseWaitlistReturn {
16
+ /** Current loading state */
17
+ loading: Ref<boolean>;
18
+ /** Current user status (if joined) */
19
+ status: Ref<UserStatus | null>;
20
+ /** Last error (if any) */
21
+ error: Ref<Error | null>;
22
+ /** Whether the user has joined */
23
+ isJoined: Ref<boolean>;
24
+ /** Public campaign configuration (branding, form fields, features) */
25
+ publicConfig: Ref<PublicCampaignConfig | null>;
26
+ /** Campaign slug */
27
+ campaign: string;
28
+ /** Join the waitlist */
29
+ join: (email: string, metadata?: UserMetadata, referrerCode?: string) => Promise<SubmitResponse | null>;
30
+ /** Refresh status */
31
+ refresh: () => Promise<UserStatus | null>;
32
+ /** Fetch public campaign configuration */
33
+ fetchPublicConfig: () => Promise<PublicCampaignConfig | null>;
34
+ /** Get referral link */
35
+ getReferralLink: () => string | null;
36
+ /** Get referral code */
37
+ getReferralCode: () => string | null;
38
+ /** Reset/logout */
39
+ reset: () => void;
40
+ }
41
+ /**
42
+ * Props for WaitlistForm component
43
+ */
44
+ interface WaitlistFormProps {
45
+ /** Referral code (if from a referral link) */
46
+ referrerCode?: string;
47
+ /** Additional metadata to include */
48
+ metadata?: UserMetadata;
49
+ /** Custom placeholder text */
50
+ placeholder?: string;
51
+ /** Custom button text */
52
+ buttonText?: string;
53
+ /** Custom loading text */
54
+ loadingText?: string;
55
+ /** Show labels */
56
+ showLabel?: boolean;
57
+ /** Label text */
58
+ labelText?: string;
59
+ }
60
+ /**
61
+ * Props for WaitlistStatus component
62
+ */
63
+ interface WaitlistStatusProps {
64
+ /** Show referral stats */
65
+ showReferrals?: boolean;
66
+ /** Show score */
67
+ showScore?: boolean;
68
+ /** Custom position label */
69
+ positionLabel?: string;
70
+ /** Custom score label */
71
+ scoreLabel?: string;
72
+ /** Custom referrals label */
73
+ referralsLabel?: string;
74
+ }
75
+ /**
76
+ * Props for ReferralShare component
77
+ */
78
+ interface ReferralShareProps {
79
+ /** Text to display before the link */
80
+ label?: string;
81
+ /** Button text for copy action */
82
+ copyButtonText?: string;
83
+ /** Text shown after copying */
84
+ copiedText?: string;
85
+ /** Custom message for sharing */
86
+ shareMessage?: string;
87
+ /** Show social share buttons */
88
+ showSocialButtons?: boolean;
89
+ }
90
+ /**
91
+ * Plugin options for createWaitlist
92
+ */
93
+ interface WaitlistPluginOptions {
94
+ /** Campaign slug/identifier */
95
+ campaign: string;
96
+ /** SDK configuration */
97
+ config?: QueueZeroConfig;
98
+ }
99
+
100
+ /**
101
+ * @queuezero/vue - Composables
102
+ *
103
+ * Vue composables for waitlist functionality.
104
+ */
105
+
106
+ /**
107
+ * Injection key for waitlist context
108
+ */
109
+ declare const WAITLIST_INJECTION_KEY: InjectionKey<UseWaitlistReturn>;
110
+ /**
111
+ * useWaitlist - Composable for waitlist functionality
112
+ *
113
+ * Can be used standalone or with the plugin.
114
+ *
115
+ * @example
116
+ * ```vue
117
+ * <script setup>
118
+ * import { useWaitlist } from '@queuezero/vue';
119
+ *
120
+ * const { status, join, loading, getReferralLink, publicConfig } = useWaitlist('my-campaign');
121
+ *
122
+ * async function handleSubmit(email) {
123
+ * await join(email, { role: 'Developer' });
124
+ * }
125
+ * </script>
126
+ * ```
127
+ */
128
+ declare function useWaitlist(campaign?: string, config?: QueueZeroConfig): UseWaitlistReturn;
129
+ /**
130
+ * provideWaitlist - Provide waitlist context to child components
131
+ *
132
+ * @example
133
+ * ```vue
134
+ * <script setup>
135
+ * import { provideWaitlist } from '@queuezero/vue';
136
+ *
137
+ * provideWaitlist('my-campaign', { apiUrl: 'https://api.example.com' });
138
+ * </script>
139
+ * ```
140
+ */
141
+ declare function provideWaitlist(campaign: string, config?: QueueZeroConfig): UseWaitlistReturn;
142
+ /**
143
+ * useWaitlistContext - Use provided waitlist context
144
+ *
145
+ * @throws Error if used outside of provider
146
+ *
147
+ * @example
148
+ * ```vue
149
+ * <script setup>
150
+ * import { useWaitlistContext } from '@queuezero/vue';
151
+ *
152
+ * const { status, join } = useWaitlistContext();
153
+ * </script>
154
+ * ```
155
+ */
156
+ declare function useWaitlistContext(): UseWaitlistReturn;
157
+ /**
158
+ * createWaitlistPlugin - Create Vue plugin for app-wide waitlist
159
+ *
160
+ * @example
161
+ * ```ts
162
+ * import { createApp } from 'vue';
163
+ * import { createWaitlistPlugin } from '@queuezero/vue';
164
+ *
165
+ * const app = createApp(App);
166
+ * app.use(createWaitlistPlugin({ campaign: 'my-campaign' }));
167
+ * app.mount('#app');
168
+ * ```
169
+ */
170
+ declare function createWaitlistPlugin(options: WaitlistPluginOptions): {
171
+ install(app: App): void;
172
+ };
173
+
174
+ declare const WaitlistForm: vue.DefineComponent<vue.ExtractPropTypes<{
175
+ referrerCode: {
176
+ type: PropType<string>;
177
+ default: undefined;
178
+ };
179
+ metadata: {
180
+ type: PropType<UserMetadata>;
181
+ default: () => {};
182
+ };
183
+ placeholder: {
184
+ type: StringConstructor;
185
+ default: string;
186
+ };
187
+ buttonText: {
188
+ type: StringConstructor;
189
+ default: string;
190
+ };
191
+ loadingText: {
192
+ type: StringConstructor;
193
+ default: string;
194
+ };
195
+ showLabel: {
196
+ type: BooleanConstructor;
197
+ default: boolean;
198
+ };
199
+ labelText: {
200
+ type: StringConstructor;
201
+ default: string;
202
+ };
203
+ }>, () => VNode<vue.RendererNode, vue.RendererElement, {
204
+ [key: string]: any;
205
+ }> | VNode<vue.RendererNode, vue.RendererElement, {
206
+ [key: string]: any;
207
+ }>[] | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
208
+ success: (response: SubmitResponse) => true;
209
+ error: (error: Error) => true;
210
+ }, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
211
+ referrerCode: {
212
+ type: PropType<string>;
213
+ default: undefined;
214
+ };
215
+ metadata: {
216
+ type: PropType<UserMetadata>;
217
+ default: () => {};
218
+ };
219
+ placeholder: {
220
+ type: StringConstructor;
221
+ default: string;
222
+ };
223
+ buttonText: {
224
+ type: StringConstructor;
225
+ default: string;
226
+ };
227
+ loadingText: {
228
+ type: StringConstructor;
229
+ default: string;
230
+ };
231
+ showLabel: {
232
+ type: BooleanConstructor;
233
+ default: boolean;
234
+ };
235
+ labelText: {
236
+ type: StringConstructor;
237
+ default: string;
238
+ };
239
+ }>> & Readonly<{
240
+ onSuccess?: ((response: SubmitResponse) => any) | undefined;
241
+ onError?: ((error: Error) => any) | undefined;
242
+ }>, {
243
+ placeholder: string;
244
+ referrerCode: string;
245
+ metadata: UserMetadata;
246
+ buttonText: string;
247
+ loadingText: string;
248
+ showLabel: boolean;
249
+ labelText: string;
250
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
251
+
252
+ /**
253
+ * @queuezero/vue - WaitlistStatus Component
254
+ *
255
+ * Displays the user's current waitlist position and stats.
256
+ */
257
+ declare const WaitlistStatus: vue.DefineComponent<vue.ExtractPropTypes<{
258
+ showReferrals: {
259
+ type: BooleanConstructor;
260
+ default: boolean;
261
+ };
262
+ showScore: {
263
+ type: BooleanConstructor;
264
+ default: boolean;
265
+ };
266
+ positionLabel: {
267
+ type: StringConstructor;
268
+ default: string;
269
+ };
270
+ scoreLabel: {
271
+ type: StringConstructor;
272
+ default: string;
273
+ };
274
+ referralsLabel: {
275
+ type: StringConstructor;
276
+ default: string;
277
+ };
278
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
279
+ [key: string]: any;
280
+ }> | vue.VNode<vue.RendererNode, vue.RendererElement, {
281
+ [key: string]: any;
282
+ }>[] | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {}, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
283
+ showReferrals: {
284
+ type: BooleanConstructor;
285
+ default: boolean;
286
+ };
287
+ showScore: {
288
+ type: BooleanConstructor;
289
+ default: boolean;
290
+ };
291
+ positionLabel: {
292
+ type: StringConstructor;
293
+ default: string;
294
+ };
295
+ scoreLabel: {
296
+ type: StringConstructor;
297
+ default: string;
298
+ };
299
+ referralsLabel: {
300
+ type: StringConstructor;
301
+ default: string;
302
+ };
303
+ }>> & Readonly<{}>, {
304
+ showReferrals: boolean;
305
+ showScore: boolean;
306
+ positionLabel: string;
307
+ scoreLabel: string;
308
+ referralsLabel: string;
309
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
310
+
311
+ /**
312
+ * @queuezero/vue - ReferralShare Component
313
+ *
314
+ * Component for sharing referral links.
315
+ */
316
+ declare const ReferralShare: vue.DefineComponent<vue.ExtractPropTypes<{
317
+ label: {
318
+ type: StringConstructor;
319
+ default: string;
320
+ };
321
+ copyButtonText: {
322
+ type: StringConstructor;
323
+ default: string;
324
+ };
325
+ copiedText: {
326
+ type: StringConstructor;
327
+ default: string;
328
+ };
329
+ shareMessage: {
330
+ type: StringConstructor;
331
+ default: string;
332
+ };
333
+ showSocialButtons: {
334
+ type: BooleanConstructor;
335
+ default: boolean;
336
+ };
337
+ }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
338
+ [key: string]: any;
339
+ }> | vue.VNode<vue.RendererNode, vue.RendererElement, {
340
+ [key: string]: any;
341
+ }>[] | null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, {
342
+ copy: (link: string) => true;
343
+ }, string, vue.PublicProps, Readonly<vue.ExtractPropTypes<{
344
+ label: {
345
+ type: StringConstructor;
346
+ default: string;
347
+ };
348
+ copyButtonText: {
349
+ type: StringConstructor;
350
+ default: string;
351
+ };
352
+ copiedText: {
353
+ type: StringConstructor;
354
+ default: string;
355
+ };
356
+ shareMessage: {
357
+ type: StringConstructor;
358
+ default: string;
359
+ };
360
+ showSocialButtons: {
361
+ type: BooleanConstructor;
362
+ default: boolean;
363
+ };
364
+ }>> & Readonly<{
365
+ onCopy?: ((link: string) => any) | undefined;
366
+ }>, {
367
+ label: string;
368
+ copyButtonText: string;
369
+ copiedText: string;
370
+ shareMessage: string;
371
+ showSocialButtons: boolean;
372
+ }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
373
+
374
+ export { ReferralShare, type ReferralShareProps, type UseWaitlistReturn, WAITLIST_INJECTION_KEY, WaitlistForm, type WaitlistFormProps, type WaitlistPluginOptions, WaitlistStatus, type WaitlistStatusProps, createWaitlistPlugin, provideWaitlist, useWaitlist, useWaitlistContext };