@queuezero/react 0.1.9 → 0.1.11

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
@@ -84,6 +84,11 @@ A ready-to-use signup form.
84
84
  displayMode="modal"
85
85
  triggerText="Join Our Waitlist"
86
86
  modalSize="md"
87
+ // Headless modal mode (attaches to existing buttons)
88
+ <WaitlistForm
89
+ displayMode="modal"
90
+ attachToText="Join Waitlist"
91
+ modalSize="md"
87
92
  />
88
93
  ```
89
94
 
@@ -93,6 +98,7 @@ A ready-to-use signup form.
93
98
  |------|------|---------|-------------|
94
99
  | `displayMode` | `'inline' \| 'modal'` | `'inline'` | Display as inline form or modal |
95
100
  | `triggerText` | `string` | `'Join Waitlist'` | Button text (modal mode only) |
101
+ | `attachToText` | `string` | - | Text to match for auto-attaching modal (headless mode) |
96
102
  | `modalSize` | `'sm' \| 'md' \| 'lg'` | `'md'` | Modal width (modal mode only) |
97
103
 
98
104
  The modal automatically uses your campaign's branding (logo, cover image, theme color) from the API.
package/dist/index.d.mts CHANGED
@@ -80,6 +80,10 @@ interface WaitlistFormProps {
80
80
  triggerText?: string;
81
81
  /** Modal size (only used when displayMode is 'modal') */
82
82
  modalSize?: 'sm' | 'md' | 'lg';
83
+ /** CSS selector to attach modal trigger to existing elements */
84
+ triggerSelector?: string;
85
+ /** Text content to match for attaching modal trigger to <a> and <button> elements */
86
+ attachToText?: string;
83
87
  /** Children for custom rendering */
84
88
  children?: React.ReactNode;
85
89
  }
@@ -203,7 +207,7 @@ declare function useWaitlist(campaign: string, config?: WaitlistProviderProps['c
203
207
  * <WaitlistForm displayMode="modal" triggerText="Join Our Waitlist" />
204
208
  * ```
205
209
  */
206
- declare function WaitlistForm({ onSuccess, onError, referrerCode, metadata, className, placeholder, buttonText, loadingText, showLabel, labelText, displayMode, triggerText, modalSize, children, }: WaitlistFormProps): any;
210
+ declare function WaitlistForm({ onSuccess, onError, referrerCode, metadata, className, placeholder, buttonText, loadingText, showLabel, labelText, displayMode, triggerText, modalSize, triggerSelector, attachToText, children, }: WaitlistFormProps): any;
207
211
 
208
212
  /**
209
213
  * WaitlistStatus - Shows current position, score, and referral count
package/dist/index.d.ts CHANGED
@@ -80,6 +80,10 @@ interface WaitlistFormProps {
80
80
  triggerText?: string;
81
81
  /** Modal size (only used when displayMode is 'modal') */
82
82
  modalSize?: 'sm' | 'md' | 'lg';
83
+ /** CSS selector to attach modal trigger to existing elements */
84
+ triggerSelector?: string;
85
+ /** Text content to match for attaching modal trigger to <a> and <button> elements */
86
+ attachToText?: string;
83
87
  /** Children for custom rendering */
84
88
  children?: React.ReactNode;
85
89
  }
@@ -203,7 +207,7 @@ declare function useWaitlist(campaign: string, config?: WaitlistProviderProps['c
203
207
  * <WaitlistForm displayMode="modal" triggerText="Join Our Waitlist" />
204
208
  * ```
205
209
  */
206
- declare function WaitlistForm({ onSuccess, onError, referrerCode, metadata, className, placeholder, buttonText, loadingText, showLabel, labelText, displayMode, triggerText, modalSize, children, }: WaitlistFormProps): any;
210
+ declare function WaitlistForm({ onSuccess, onError, referrerCode, metadata, className, placeholder, buttonText, loadingText, showLabel, labelText, displayMode, triggerText, modalSize, triggerSelector, attachToText, children, }: WaitlistFormProps): any;
207
211
 
208
212
  /**
209
213
  * WaitlistStatus - Shows current position, score, and referral count
package/dist/index.js CHANGED
@@ -182,6 +182,8 @@ function WaitlistForm({
182
182
  displayMode = "inline",
183
183
  triggerText = "Join Waitlist",
184
184
  modalSize = "md",
185
+ triggerSelector,
186
+ attachToText,
185
187
  children
186
188
  }) {
187
189
  const { join, loading, error, isJoined, config, configLoading } = useWaitlistContext();
@@ -348,8 +350,33 @@ function WaitlistForm({
348
350
  if (displayMode === "inline") {
349
351
  return formContent;
350
352
  }
353
+ const isHeadless = !!(triggerSelector || attachToText);
354
+ (0, import_react2.useEffect)(() => {
355
+ if (displayMode !== "modal") return;
356
+ const cleanupFns = [];
357
+ const attach = (element) => {
358
+ const handler = (e) => {
359
+ e.preventDefault();
360
+ setIsModalOpen(true);
361
+ };
362
+ element.addEventListener("click", handler);
363
+ cleanupFns.push(() => element.removeEventListener("click", handler));
364
+ };
365
+ if (triggerSelector) {
366
+ document.querySelectorAll(triggerSelector).forEach(attach);
367
+ }
368
+ if (attachToText) {
369
+ const lowerText = attachToText.toLowerCase();
370
+ document.querySelectorAll("a, button").forEach((el) => {
371
+ if (el.textContent?.toLowerCase().includes(lowerText)) {
372
+ attach(el);
373
+ }
374
+ });
375
+ }
376
+ return () => cleanupFns.forEach((fn) => fn());
377
+ }, [displayMode, triggerSelector, attachToText]);
351
378
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
352
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
379
+ !isHeadless && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
353
380
  "button",
354
381
  {
355
382
  type: "button",
package/dist/index.mjs CHANGED
@@ -148,6 +148,8 @@ function WaitlistForm({
148
148
  displayMode = "inline",
149
149
  triggerText = "Join Waitlist",
150
150
  modalSize = "md",
151
+ triggerSelector,
152
+ attachToText,
151
153
  children
152
154
  }) {
153
155
  const { join, loading, error, isJoined, config, configLoading } = useWaitlistContext();
@@ -314,8 +316,33 @@ function WaitlistForm({
314
316
  if (displayMode === "inline") {
315
317
  return formContent;
316
318
  }
319
+ const isHeadless = !!(triggerSelector || attachToText);
320
+ useEffect2(() => {
321
+ if (displayMode !== "modal") return;
322
+ const cleanupFns = [];
323
+ const attach = (element) => {
324
+ const handler = (e) => {
325
+ e.preventDefault();
326
+ setIsModalOpen(true);
327
+ };
328
+ element.addEventListener("click", handler);
329
+ cleanupFns.push(() => element.removeEventListener("click", handler));
330
+ };
331
+ if (triggerSelector) {
332
+ document.querySelectorAll(triggerSelector).forEach(attach);
333
+ }
334
+ if (attachToText) {
335
+ const lowerText = attachToText.toLowerCase();
336
+ document.querySelectorAll("a, button").forEach((el) => {
337
+ if (el.textContent?.toLowerCase().includes(lowerText)) {
338
+ attach(el);
339
+ }
340
+ });
341
+ }
342
+ return () => cleanupFns.forEach((fn) => fn());
343
+ }, [displayMode, triggerSelector, attachToText]);
317
344
  return /* @__PURE__ */ jsxs(Fragment, { children: [
318
- /* @__PURE__ */ jsx2(
345
+ !isHeadless && /* @__PURE__ */ jsx2(
319
346
  "button",
320
347
  {
321
348
  type: "button",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@queuezero/react",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "React components and hooks for QueueZero viral waitlists",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",