@burdenoff/website-sdk 2026.522.4 → 2026.522.6

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/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { W as WebSDKClient, a as WebSDKClientConfig, b as WebSDKProvider, c as WebSDKProviderProps, u as useWebSDK, d as useWebSDKConfig } from './provider-D7Rij9UM.mjs';
2
2
  export { ContactCategory, ContactPage, ContactPageProps, DEFAULT_CONTACT_CATEGORIES } from './components/contact.mjs';
3
3
  export { PartnersPage, PartnersPageProps } from './components/partners.mjs';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
5
  export { NewsletterForm, NewsletterFormProps, NewsletterPage, NewsletterPageProps } from './components/newsletter.mjs';
5
6
  export { PlanCard, PricingPage, PricingProps, PricingSection } from './components/pricing.mjs';
6
7
  export { WaitlistForm, WaitlistFormProps, WaitlistPage, WaitlistPageProps } from './components/waitlist.mjs';
@@ -16,12 +17,39 @@ import * as React from 'react';
16
17
  import { VariantProps } from 'class-variance-authority';
17
18
  import * as LabelPrimitive from '@radix-ui/react-label';
18
19
  export { cn } from './utils/index.mjs';
19
- import 'react/jsx-runtime';
20
20
  import 'clsx';
21
21
 
22
+ interface CareersApplyFormProps {
23
+ /** Product name (falls back to product context / SDK config). */
24
+ productName?: string;
25
+ /** reCAPTCHA site key (falls back to SDK config). */
26
+ recaptchaSiteKey?: string;
27
+ /**
28
+ * Position options for the dropdown. When empty, a free-text "position"
29
+ * input is shown instead so the form works before a postings list exists.
30
+ */
31
+ positions?: readonly string[];
32
+ heroTitle?: string;
33
+ heroDescription?: string;
34
+ /**
35
+ * `1` (default) renders a full page hero `<h1>`; `2` renders a compact
36
+ * `<h2>` section header for embedding under a page that owns the `<h1>`.
37
+ */
38
+ headingLevel?: 1 | 2;
39
+ /** Max resume size in bytes (default 10MB, matches backend). */
40
+ maxResumeBytes?: number;
41
+ className?: string;
42
+ seo?: {
43
+ title?: string;
44
+ description?: string;
45
+ keywords?: string;
46
+ };
47
+ }
48
+ declare function CareersApplyForm({ productName, recaptchaSiteKey, positions, heroTitle, heroDescription, headingLevel, maxResumeBytes, className, seo, }: CareersApplyFormProps): react_jsx_runtime.JSX.Element;
49
+
22
50
  declare const buttonVariants: (props?: ({
23
51
  variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
24
- size?: "icon" | "default" | "sm" | "lg" | null | undefined;
52
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
25
53
  } & class_variance_authority_types.ClassProp) | undefined) => string;
26
54
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
27
55
  asChild?: boolean;
@@ -37,4 +65,4 @@ declare const Select: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLPro
37
65
 
38
66
  declare const Textarea: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
39
67
 
40
- export { Button, type ButtonProps, Input, Label, Select, Textarea, buttonVariants };
68
+ export { Button, type ButtonProps, CareersApplyForm, type CareersApplyFormProps, Input, Label, Select, Textarea, buttonVariants };
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { W as WebSDKClient, a as WebSDKClientConfig, b as WebSDKProvider, c as WebSDKProviderProps, u as useWebSDK, d as useWebSDKConfig } from './provider-D7Rij9UM.js';
2
2
  export { ContactCategory, ContactPage, ContactPageProps, DEFAULT_CONTACT_CATEGORIES } from './components/contact.js';
3
3
  export { PartnersPage, PartnersPageProps } from './components/partners.js';
4
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
5
  export { NewsletterForm, NewsletterFormProps, NewsletterPage, NewsletterPageProps } from './components/newsletter.js';
5
6
  export { PlanCard, PricingPage, PricingProps, PricingSection } from './components/pricing.js';
6
7
  export { WaitlistForm, WaitlistFormProps, WaitlistPage, WaitlistPageProps } from './components/waitlist.js';
@@ -16,12 +17,39 @@ import * as React from 'react';
16
17
  import { VariantProps } from 'class-variance-authority';
17
18
  import * as LabelPrimitive from '@radix-ui/react-label';
18
19
  export { cn } from './utils/index.js';
19
- import 'react/jsx-runtime';
20
20
  import 'clsx';
21
21
 
22
+ interface CareersApplyFormProps {
23
+ /** Product name (falls back to product context / SDK config). */
24
+ productName?: string;
25
+ /** reCAPTCHA site key (falls back to SDK config). */
26
+ recaptchaSiteKey?: string;
27
+ /**
28
+ * Position options for the dropdown. When empty, a free-text "position"
29
+ * input is shown instead so the form works before a postings list exists.
30
+ */
31
+ positions?: readonly string[];
32
+ heroTitle?: string;
33
+ heroDescription?: string;
34
+ /**
35
+ * `1` (default) renders a full page hero `<h1>`; `2` renders a compact
36
+ * `<h2>` section header for embedding under a page that owns the `<h1>`.
37
+ */
38
+ headingLevel?: 1 | 2;
39
+ /** Max resume size in bytes (default 10MB, matches backend). */
40
+ maxResumeBytes?: number;
41
+ className?: string;
42
+ seo?: {
43
+ title?: string;
44
+ description?: string;
45
+ keywords?: string;
46
+ };
47
+ }
48
+ declare function CareersApplyForm({ productName, recaptchaSiteKey, positions, heroTitle, heroDescription, headingLevel, maxResumeBytes, className, seo, }: CareersApplyFormProps): react_jsx_runtime.JSX.Element;
49
+
22
50
  declare const buttonVariants: (props?: ({
23
51
  variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
24
- size?: "icon" | "default" | "sm" | "lg" | null | undefined;
52
+ size?: "default" | "sm" | "lg" | "icon" | null | undefined;
25
53
  } & class_variance_authority_types.ClassProp) | undefined) => string;
26
54
  interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
27
55
  asChild?: boolean;
@@ -37,4 +65,4 @@ declare const Select: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLPro
37
65
 
38
66
  declare const Textarea: React.ForwardRefExoticComponent<Omit<React.DetailedHTMLProps<React.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref"> & React.RefAttributes<HTMLTextAreaElement>>;
39
67
 
40
- export { Button, type ButtonProps, Input, Label, Select, Textarea, buttonVariants };
68
+ export { Button, type ButtonProps, CareersApplyForm, type CareersApplyFormProps, Input, Label, Select, Textarea, buttonVariants };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  var React = require('react');
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var lucideReact = require('lucide-react');
6
- var ReCAPTCHA2 = require('react-google-recaptcha');
6
+ var ReCAPTCHA3 = require('react-google-recaptcha');
7
7
  var sonner = require('sonner');
8
8
  var reactHelmetAsync = require('react-helmet-async');
9
9
  var reactSlot = require('@radix-ui/react-slot');
@@ -36,7 +36,7 @@ function _interopNamespace(e) {
36
36
  }
37
37
 
38
38
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
39
- var ReCAPTCHA2__default = /*#__PURE__*/_interopDefault(ReCAPTCHA2);
39
+ var ReCAPTCHA3__default = /*#__PURE__*/_interopDefault(ReCAPTCHA3);
40
40
  var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
41
41
 
42
42
  var __defProp = Object.defineProperty;
@@ -935,7 +935,7 @@ function ContactPage({
935
935
  ] }),
936
936
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
937
937
  effectiveRecaptchaSiteKey && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center sm:justify-start", children: /* @__PURE__ */ jsxRuntime.jsx(
938
- ReCAPTCHA2__default.default,
938
+ ReCAPTCHA3__default.default,
939
939
  {
940
940
  ref: recaptchaRef,
941
941
  sitekey: effectiveRecaptchaSiteKey
@@ -1514,6 +1514,401 @@ function PartnersPage(props) {
1514
1514
  )
1515
1515
  ] });
1516
1516
  }
1517
+ var ALLOWED_RESUME_TYPES = {
1518
+ "application/pdf": "PDF",
1519
+ "application/msword": "DOC",
1520
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "DOCX"
1521
+ };
1522
+ var EXT_TO_MIME = {
1523
+ pdf: "application/pdf",
1524
+ doc: "application/msword",
1525
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
1526
+ };
1527
+ var DEFAULT_MAX_RESUME_BYTES = 10 * 1024 * 1024;
1528
+ function resolveResumeType(file) {
1529
+ if (ALLOWED_RESUME_TYPES[file.type]) return file.type;
1530
+ const ext = file.name.split(".").pop()?.toLowerCase();
1531
+ return ext && EXT_TO_MIME[ext] ? EXT_TO_MIME[ext] : null;
1532
+ }
1533
+ var SUBMIT_JOB_APPLICATION_MUTATION = (
1534
+ /* GraphQL */
1535
+ `
1536
+ mutation SubmitJobApplication($input: SubmitJobApplicationInput!) {
1537
+ submitJobApplication(input: $input) {
1538
+ success
1539
+ message
1540
+ }
1541
+ }
1542
+ `
1543
+ );
1544
+ function fileToBase64(file) {
1545
+ return new Promise((resolve, reject) => {
1546
+ const reader = new FileReader();
1547
+ reader.onload = () => {
1548
+ const result = typeof reader.result === "string" ? reader.result : "";
1549
+ const comma = result.indexOf(",");
1550
+ resolve(comma >= 0 ? result.slice(comma + 1) : result);
1551
+ };
1552
+ reader.onerror = () => reject(new Error("Failed to read the resume file"));
1553
+ reader.readAsDataURL(file);
1554
+ });
1555
+ }
1556
+ async function submitApplication(client, data, productId) {
1557
+ try {
1558
+ const result = await client.mutate(SUBMIT_JOB_APPLICATION_MUTATION, {
1559
+ input: {
1560
+ firstName: data.firstName,
1561
+ lastName: data.lastName,
1562
+ email: data.email.trim().toLowerCase(),
1563
+ position: data.position,
1564
+ resumeBase64: data.resumeBase64,
1565
+ resumeFileName: data.resumeFileName,
1566
+ resumeContentType: data.resumeContentType,
1567
+ productId,
1568
+ ...data.phone ? { phone: data.phone } : {},
1569
+ ...data.linkedinUrl ? { linkedinUrl: data.linkedinUrl } : {},
1570
+ ...data.portfolioUrl ? { portfolioUrl: data.portfolioUrl } : {},
1571
+ ...data.coverLetter ? { coverLetter: data.coverLetter } : {},
1572
+ ...data.recaptchaToken ? { recaptchaToken: data.recaptchaToken } : {}
1573
+ }
1574
+ });
1575
+ if (result.errors?.length) {
1576
+ return {
1577
+ success: false,
1578
+ message: result.errors[0]?.message ?? "Failed to submit application"
1579
+ };
1580
+ }
1581
+ const response = result.data?.submitJobApplication;
1582
+ return response?.success ? { success: true, message: response.message || "Application submitted!" } : {
1583
+ success: false,
1584
+ message: response?.message || "Failed to submit application"
1585
+ };
1586
+ } catch (error) {
1587
+ console.error("Job application submission error:", error);
1588
+ return { success: false, message: "Network error. Please try again." };
1589
+ }
1590
+ }
1591
+ function CareersApplyForm({
1592
+ productName,
1593
+ recaptchaSiteKey,
1594
+ positions = [],
1595
+ heroTitle = "Become a part of the team",
1596
+ heroDescription = "Tell us about yourself and upload your resume \u2014 we'll be in touch.",
1597
+ headingLevel = 1,
1598
+ maxResumeBytes = DEFAULT_MAX_RESUME_BYTES,
1599
+ className,
1600
+ seo
1601
+ }) {
1602
+ const client = useWebSDK();
1603
+ const config = useWebSDKConfig();
1604
+ const { product } = useProduct();
1605
+ const resolvedProductId = product?.id || config.productId;
1606
+ const displayName = productName ?? product?.name ?? config.productId;
1607
+ const effectiveRecaptchaSiteKey = recaptchaSiteKey ?? config.recaptchaSiteKey ?? "";
1608
+ const recaptchaRef = React.useRef(null);
1609
+ const [isSubmitting, setIsSubmitting] = React.useState(false);
1610
+ const [submitted, setSubmitted] = React.useState(false);
1611
+ const [resumeFile, setResumeFile] = React.useState(null);
1612
+ const [resumeType, setResumeType] = React.useState(null);
1613
+ const [resumeError, setResumeError] = React.useState(null);
1614
+ const maxMb = Math.floor(maxResumeBytes / (1024 * 1024));
1615
+ const clearResume = () => {
1616
+ setResumeFile(null);
1617
+ setResumeType(null);
1618
+ };
1619
+ const handleFileChange = (e) => {
1620
+ setResumeError(null);
1621
+ const file = e.target.files?.[0] ?? null;
1622
+ if (!file) {
1623
+ clearResume();
1624
+ return;
1625
+ }
1626
+ const type = resolveResumeType(file);
1627
+ if (!type) {
1628
+ clearResume();
1629
+ setResumeError("Resume must be a PDF, DOC, or DOCX file.");
1630
+ return;
1631
+ }
1632
+ if (file.size > maxResumeBytes) {
1633
+ clearResume();
1634
+ setResumeError(`Resume must be ${maxMb}MB or smaller.`);
1635
+ return;
1636
+ }
1637
+ setResumeFile(file);
1638
+ setResumeType(type);
1639
+ };
1640
+ const handleSubmit = async (e) => {
1641
+ e.preventDefault();
1642
+ const recaptchaToken = recaptchaRef.current?.getValue() ?? "";
1643
+ if (effectiveRecaptchaSiteKey && !recaptchaToken) {
1644
+ sonner.toast.error("Please complete the reCAPTCHA verification");
1645
+ return;
1646
+ }
1647
+ if (!resumeFile) {
1648
+ setResumeError("Please attach your resume (PDF, DOC, or DOCX).");
1649
+ return;
1650
+ }
1651
+ if (!resolvedProductId) {
1652
+ console.warn(
1653
+ "[CareersApplyForm] No productId resolved \u2014 submission will not be attributed to a product."
1654
+ );
1655
+ }
1656
+ const form = e.currentTarget;
1657
+ setIsSubmitting(true);
1658
+ try {
1659
+ const formData = new FormData(form);
1660
+ const resumeBase64 = await fileToBase64(resumeFile);
1661
+ const result = await submitApplication(
1662
+ client,
1663
+ {
1664
+ firstName: formData.get("firstName") ?? "",
1665
+ lastName: formData.get("lastName") ?? "",
1666
+ email: formData.get("email") ?? "",
1667
+ phone: formData.get("phone") || void 0,
1668
+ position: formData.get("position") ?? "",
1669
+ linkedinUrl: formData.get("linkedinUrl") || void 0,
1670
+ portfolioUrl: formData.get("portfolioUrl") || void 0,
1671
+ coverLetter: formData.get("coverLetter") || void 0,
1672
+ resumeBase64,
1673
+ resumeFileName: resumeFile.name,
1674
+ // Use the resolved type (handles browsers that report an empty
1675
+ // file.type for .doc/.docx).
1676
+ resumeContentType: resumeType ?? resumeFile.type,
1677
+ recaptchaToken
1678
+ },
1679
+ resolvedProductId
1680
+ );
1681
+ if (result.success) {
1682
+ setSubmitted(true);
1683
+ sonner.toast.success(result.message ?? "Application submitted!");
1684
+ } else {
1685
+ sonner.toast.error(result.message ?? "Failed to submit application");
1686
+ recaptchaRef.current?.reset();
1687
+ }
1688
+ } catch (err) {
1689
+ console.error("Careers form error:", err);
1690
+ sonner.toast.error("Something went wrong. Please try again.");
1691
+ recaptchaRef.current?.reset();
1692
+ } finally {
1693
+ setIsSubmitting(false);
1694
+ }
1695
+ };
1696
+ const Heading = headingLevel === 2 ? "h2" : "h1";
1697
+ const headingClass = headingLevel === 2 ? "text-2xl md:text-3xl font-bold mb-3" : "text-3xl sm:text-4xl md:text-5xl font-bold mb-4 sm:mb-6";
1698
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
1699
+ seo && /* @__PURE__ */ jsxRuntime.jsx(
1700
+ PageHead,
1701
+ {
1702
+ title: seo.title ?? `Careers \u2014 ${displayName}`,
1703
+ description: seo.description ?? heroDescription,
1704
+ keywords: seo.keywords
1705
+ }
1706
+ ),
1707
+ /* @__PURE__ */ jsxRuntime.jsx(
1708
+ "section",
1709
+ {
1710
+ className: headingLevel === 2 ? "py-12 md:py-16" : "bg-gradient-to-b from-background to-muted/20 py-12 sm:py-16 md:py-20 lg:py-24",
1711
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-3xl mx-auto px-4 sm:px-6 lg:px-8", children: [
1712
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center mb-8 sm:mb-10", children: [
1713
+ /* @__PURE__ */ jsxRuntime.jsx(Heading, { className: headingClass, children: heroTitle }),
1714
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg text-muted-foreground leading-relaxed", children: heroDescription })
1715
+ ] }),
1716
+ submitted ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center rounded-xl border border-border bg-card p-10", children: [
1717
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "mx-auto mb-4 h-12 w-12 text-accent" }),
1718
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-xl font-semibold text-foreground mb-2", children: "Application received" }),
1719
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-muted-foreground", children: [
1720
+ "Thanks for applying to ",
1721
+ displayName,
1722
+ ". We've emailed you a confirmation and our team will be in touch."
1723
+ ] })
1724
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "space-y-5", children: [
1725
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-5", children: [
1726
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1727
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "firstName", children: "First name *" }),
1728
+ /* @__PURE__ */ jsxRuntime.jsx(
1729
+ Input,
1730
+ {
1731
+ id: "firstName",
1732
+ name: "firstName",
1733
+ required: true,
1734
+ placeholder: "Ada"
1735
+ }
1736
+ )
1737
+ ] }),
1738
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1739
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "lastName", children: "Last name *" }),
1740
+ /* @__PURE__ */ jsxRuntime.jsx(
1741
+ Input,
1742
+ {
1743
+ id: "lastName",
1744
+ name: "lastName",
1745
+ required: true,
1746
+ placeholder: "Lovelace"
1747
+ }
1748
+ )
1749
+ ] })
1750
+ ] }),
1751
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-5", children: [
1752
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1753
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "email", children: "Email *" }),
1754
+ /* @__PURE__ */ jsxRuntime.jsx(
1755
+ Input,
1756
+ {
1757
+ id: "email",
1758
+ name: "email",
1759
+ type: "email",
1760
+ required: true,
1761
+ placeholder: "ada@example.com"
1762
+ }
1763
+ )
1764
+ ] }),
1765
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1766
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "phone", children: "Phone" }),
1767
+ /* @__PURE__ */ jsxRuntime.jsx(
1768
+ Input,
1769
+ {
1770
+ id: "phone",
1771
+ name: "phone",
1772
+ placeholder: "+1 555 010 0100"
1773
+ }
1774
+ )
1775
+ ] })
1776
+ ] }),
1777
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1778
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "position", children: "Position *" }),
1779
+ positions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
1780
+ "select",
1781
+ {
1782
+ id: "position",
1783
+ name: "position",
1784
+ required: true,
1785
+ defaultValue: "",
1786
+ className: "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring",
1787
+ children: [
1788
+ /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select a role" }),
1789
+ positions.map((p) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: p, children: p }, p))
1790
+ ]
1791
+ }
1792
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1793
+ Input,
1794
+ {
1795
+ id: "position",
1796
+ name: "position",
1797
+ required: true,
1798
+ placeholder: "Role you're applying for"
1799
+ }
1800
+ )
1801
+ ] }),
1802
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-5", children: [
1803
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1804
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "linkedinUrl", children: "LinkedIn" }),
1805
+ /* @__PURE__ */ jsxRuntime.jsx(
1806
+ Input,
1807
+ {
1808
+ id: "linkedinUrl",
1809
+ name: "linkedinUrl",
1810
+ type: "url",
1811
+ placeholder: "https://linkedin.com/in/\u2026"
1812
+ }
1813
+ )
1814
+ ] }),
1815
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1816
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "portfolioUrl", children: "Portfolio / GitHub" }),
1817
+ /* @__PURE__ */ jsxRuntime.jsx(
1818
+ Input,
1819
+ {
1820
+ id: "portfolioUrl",
1821
+ name: "portfolioUrl",
1822
+ type: "url",
1823
+ placeholder: "https://\u2026"
1824
+ }
1825
+ )
1826
+ ] })
1827
+ ] }),
1828
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1829
+ /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "coverLetter", children: "Cover letter" }),
1830
+ /* @__PURE__ */ jsxRuntime.jsx(
1831
+ Textarea,
1832
+ {
1833
+ id: "coverLetter",
1834
+ name: "coverLetter",
1835
+ rows: 5,
1836
+ placeholder: "Tell us why you'd be a great fit\u2026"
1837
+ }
1838
+ )
1839
+ ] }),
1840
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1841
+ /* @__PURE__ */ jsxRuntime.jsxs(Label, { htmlFor: "resume", children: [
1842
+ "Resume * (PDF, DOC, or DOCX \u2014 max ",
1843
+ maxMb,
1844
+ "MB)"
1845
+ ] }),
1846
+ /* @__PURE__ */ jsxRuntime.jsxs(
1847
+ "label",
1848
+ {
1849
+ htmlFor: "resume",
1850
+ className: "mt-1 flex cursor-pointer items-center gap-3 rounded-md border border-dashed border-input bg-background px-4 py-3 text-sm hover:bg-muted/40 transition-colors",
1851
+ children: [
1852
+ /* @__PURE__ */ jsxRuntime.jsx(
1853
+ lucideReact.Upload,
1854
+ {
1855
+ className: "h-5 w-5 text-muted-foreground",
1856
+ "aria-hidden": "true"
1857
+ }
1858
+ ),
1859
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-foreground", children: resumeFile ? resumeFile.name : "Choose a file\u2026" }),
1860
+ /* @__PURE__ */ jsxRuntime.jsx(
1861
+ "input",
1862
+ {
1863
+ id: "resume",
1864
+ name: "resume",
1865
+ type: "file",
1866
+ accept: ".pdf,.doc,.docx,application/pdf,application/msword,application/vnd.openxmlformats-officedocument.wordprocessingml.document",
1867
+ className: "sr-only",
1868
+ "aria-describedby": resumeError ? "resume-error" : void 0,
1869
+ "aria-invalid": resumeError ? true : void 0,
1870
+ onChange: handleFileChange
1871
+ }
1872
+ )
1873
+ ]
1874
+ }
1875
+ ),
1876
+ resumeError && /* @__PURE__ */ jsxRuntime.jsx(
1877
+ "p",
1878
+ {
1879
+ id: "resume-error",
1880
+ role: "alert",
1881
+ className: "mt-1 text-sm text-destructive",
1882
+ children: resumeError
1883
+ }
1884
+ )
1885
+ ] }),
1886
+ effectiveRecaptchaSiteKey && /* @__PURE__ */ jsxRuntime.jsx(
1887
+ ReCAPTCHA3__default.default,
1888
+ {
1889
+ ref: recaptchaRef,
1890
+ sitekey: effectiveRecaptchaSiteKey
1891
+ }
1892
+ ),
1893
+ /* @__PURE__ */ jsxRuntime.jsx(
1894
+ Button,
1895
+ {
1896
+ type: "submit",
1897
+ size: "lg",
1898
+ disabled: isSubmitting,
1899
+ className: "w-full sm:w-auto",
1900
+ children: isSubmitting ? "Submitting\u2026" : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1901
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "mr-2 h-4 w-4" }),
1902
+ " Submit application"
1903
+ ] })
1904
+ }
1905
+ )
1906
+ ] })
1907
+ ] })
1908
+ }
1909
+ )
1910
+ ] });
1911
+ }
1517
1912
  var newsletterSchema = zod.z.object({
1518
1913
  email: zod.z.string().email("Please enter a valid email address")
1519
1914
  });
@@ -1803,7 +2198,7 @@ function NewsletterPage({
1803
2198
  errors.email && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: errors.email.message })
1804
2199
  ] }),
1805
2200
  effectiveRecaptchaSiteKey && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
1806
- ReCAPTCHA2__default.default,
2201
+ ReCAPTCHA3__default.default,
1807
2202
  {
1808
2203
  ref: recaptchaRef,
1809
2204
  sitekey: effectiveRecaptchaSiteKey
@@ -1855,7 +2250,7 @@ function NewsletterPage({
1855
2250
  errors.email && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: errors.email.message })
1856
2251
  ] }),
1857
2252
  effectiveRecaptchaSiteKey && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center sm:justify-start", children: /* @__PURE__ */ jsxRuntime.jsx(
1858
- ReCAPTCHA2__default.default,
2253
+ ReCAPTCHA3__default.default,
1859
2254
  {
1860
2255
  ref: recaptchaRef,
1861
2256
  sitekey: effectiveRecaptchaSiteKey
@@ -2024,7 +2419,7 @@ function NewsletterForm({
2024
2419
  }
2025
2420
  ` }),
2026
2421
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { position: "relative", zIndex: 50 }, children: /* @__PURE__ */ jsxRuntime.jsx(
2027
- ReCAPTCHA2__default.default,
2422
+ ReCAPTCHA3__default.default,
2028
2423
  {
2029
2424
  ref: recaptchaRef,
2030
2425
  sitekey: effectiveRecaptchaSiteKey,
@@ -4524,6 +4919,7 @@ function PressKitPage(props) {
4524
4919
  exports.BlogListPage = BlogListPage;
4525
4920
  exports.BlogPostPage = BlogPostPage;
4526
4921
  exports.Button = Button;
4922
+ exports.CareersApplyForm = CareersApplyForm;
4527
4923
  exports.ContactPage = ContactPage;
4528
4924
  exports.ContentRenderer = ContentRenderer;
4529
4925
  exports.DEFAULT_CONTACT_CATEGORIES = DEFAULT_CONTACT_CATEGORIES;