@olwiba/ui 0.0.28 → 0.0.30

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.ts CHANGED
@@ -125,16 +125,27 @@ interface AppShellProps {
125
125
  declare function AppShell({ brand, navItems, action, user, pageTitle, renderLink, collapsible, sidebarPosition, side, children, }?: AppShellProps): react_jsx_runtime.JSX.Element;
126
126
 
127
127
  interface AuthFormProps {
128
+ /** Controls form title, fields, and footer text. @default 'signin' */
129
+ mode?: 'signin' | 'signup';
128
130
  onSubmit?: (e: React.FormEvent<HTMLFormElement>) => void;
129
131
  onSso?: () => void;
132
+ /** (signin) Link to the sign-up page */
130
133
  signUpHref?: string;
134
+ /** (signup) Link back to the sign-in page */
135
+ signInHref?: string;
131
136
  forgotPasswordHref?: string;
132
137
  brand?: React.ReactNode;
138
+ /** Error message displayed below the form fields */
139
+ error?: string;
140
+ /** Disables the submit button and shows a loading label */
141
+ loading?: boolean;
142
+ /** Render prop for links — use to inject framework-native link components (e.g. TanStack Router Link) */
143
+ renderLink?: AppShellRenderLink;
133
144
  }
134
145
  interface AuthSectionProps extends AuthFormProps {
135
- /** Visual layout of the auth screen */
146
+ /** Visual layout of the auth screen. @default 'centered' */
136
147
  layout?: 'centered' | 'split';
137
- /** Custom form/card content. Defaults to the built-in sign-in form. */
148
+ /** Custom form/card content. Defaults to the built-in form. */
138
149
  children?: React.ReactNode;
139
150
  /** (split layout only) Custom content for the left decorative panel */
140
151
  panel?: React.ReactNode;
package/dist/index.js CHANGED
@@ -253,6 +253,7 @@ function AppShell({
253
253
  }
254
254
  return inner;
255
255
  }
256
+ var defaultRenderLink2 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
256
257
  function CenteredAuth({ children }) {
257
258
  return /* @__PURE__ */ jsx("section", { className: "flex h-full min-h-[720px] w-full flex-col items-center justify-center gap-6 rounded-2xl bg-muted p-6 md:p-10", children: /* @__PURE__ */ jsx("div", { className: "flex w-full max-w-sm flex-col gap-6", children }) });
258
259
  }
@@ -286,36 +287,70 @@ function SplitAuth({ children, panel }) {
286
287
  /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-6 lg:p-10", children })
287
288
  ] });
288
289
  }
289
- function DefaultForm({ onSubmit, onSso, signUpHref = "#", forgotPasswordHref = "#", brand }) {
290
+ function DefaultForm({
291
+ mode = "signin",
292
+ onSubmit,
293
+ onSso,
294
+ signUpHref = "#",
295
+ signInHref = "#",
296
+ forgotPasswordHref = "#",
297
+ brand,
298
+ error,
299
+ loading,
300
+ renderLink = defaultRenderLink2
301
+ }) {
302
+ const isSignUp = mode === "signup";
290
303
  return /* @__PURE__ */ jsxs(Card$1, { className: "w-full max-w-md", children: [
291
304
  /* @__PURE__ */ jsxs(CardHeader, { children: [
292
305
  brand && /* @__PURE__ */ jsx("div", { className: "mb-2", children: brand }),
293
- /* @__PURE__ */ jsx(CardTitle, { children: "Sign in" }),
294
- /* @__PURE__ */ jsx(CardDescription, { children: "Enter your email and password to continue." })
306
+ /* @__PURE__ */ jsx(CardTitle, { children: isSignUp ? "Create an account" : "Sign in" }),
307
+ /* @__PURE__ */ jsx(CardDescription, { children: isSignUp ? "Enter your details to create your account." : "Enter your email and password to continue." })
295
308
  ] }),
296
309
  /* @__PURE__ */ jsxs(CardContent, { className: "space-y-4", children: [
297
310
  /* @__PURE__ */ jsxs("form", { onSubmit, className: "space-y-4", children: [
311
+ isSignUp && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
312
+ /* @__PURE__ */ jsx(Label, { htmlFor: "auth-name", children: "Name" }),
313
+ /* @__PURE__ */ jsx(Input$1, { id: "auth-name", name: "name", type: "text", placeholder: "Your name", autoComplete: "name" })
314
+ ] }),
298
315
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
299
316
  /* @__PURE__ */ jsx(Label, { htmlFor: "auth-email", children: "Email" }),
300
- /* @__PURE__ */ jsx(Input$1, { id: "auth-email", type: "email", placeholder: "name@company.com" })
317
+ /* @__PURE__ */ jsx(Input$1, { id: "auth-email", name: "email", type: "email", placeholder: "name@company.com", autoComplete: "email" })
301
318
  ] }),
302
319
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
303
320
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
304
321
  /* @__PURE__ */ jsx(Label, { htmlFor: "auth-password", children: "Password" }),
305
- forgotPasswordHref && /* @__PURE__ */ jsx("a", { className: "text-xs text-muted-foreground underline underline-offset-4 hover:text-foreground", href: forgotPasswordHref, children: "Forgot password?" })
322
+ !isSignUp && forgotPasswordHref && renderLink({
323
+ href: forgotPasswordHref,
324
+ className: "text-xs text-muted-foreground underline underline-offset-4 hover:text-foreground",
325
+ children: "Forgot password?"
326
+ })
306
327
  ] }),
307
- /* @__PURE__ */ jsx(Input$1, { id: "auth-password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022" })
328
+ /* @__PURE__ */ jsx(
329
+ Input$1,
330
+ {
331
+ id: "auth-password",
332
+ name: "password",
333
+ type: "password",
334
+ placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022",
335
+ autoComplete: isSignUp ? "new-password" : "current-password"
336
+ }
337
+ )
308
338
  ] }),
339
+ error && /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-destructive", children: error }),
309
340
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
310
- /* @__PURE__ */ jsx(Button$1, { type: "submit", className: "w-full", children: "Continue" }),
311
- onSso && /* @__PURE__ */ jsx(Button$1, { type: "button", variant: "outline", className: "w-full", onClick: onSso, children: "Use SSO" })
341
+ /* @__PURE__ */ jsx(Button$1, { type: "submit", className: "w-full", disabled: loading, children: loading ? "Please wait\u2026" : isSignUp ? "Create account" : "Sign in" }),
342
+ onSso && /* @__PURE__ */ jsx(Button$1, { type: "button", variant: "outline", className: "w-full", onClick: onSso, disabled: loading, children: "Use SSO" })
312
343
  ] })
313
344
  ] }),
314
- signUpHref && /* @__PURE__ */ jsxs("p", { className: "text-center text-xs text-muted-foreground", children: [
345
+ /* @__PURE__ */ jsx("p", { className: "text-center text-xs text-muted-foreground", children: isSignUp ? /* @__PURE__ */ jsxs(Fragment, { children: [
346
+ "Already have an account?",
347
+ " ",
348
+ renderLink({ href: signInHref, className: "text-foreground underline underline-offset-4", children: "Sign in" })
349
+ ] }) : signUpHref && /* @__PURE__ */ jsxs(Fragment, { children: [
315
350
  "New here?",
316
351
  " ",
317
- /* @__PURE__ */ jsx("a", { className: "text-foreground underline underline-offset-4", href: signUpHref, children: "Create an account" })
318
- ] })
352
+ renderLink({ href: signUpHref, className: "text-foreground underline underline-offset-4", children: "Create an account" })
353
+ ] }) })
319
354
  ] })
320
355
  ] });
321
356
  }
@@ -349,14 +384,14 @@ function EmptyState({ icon: Icon, title, description, action, className, ...prop
349
384
  }
350
385
  );
351
386
  }
352
- var defaultRenderLink2 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
387
+ var defaultRenderLink3 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
353
388
  function ErrorPage({
354
389
  statusCode = "404",
355
390
  title = "Page not found",
356
391
  description = "The page you're looking for doesn't exist or has been moved. Check the URL or head back home.",
357
392
  action = { label: "Take me home", href: "/" },
358
393
  backAction = { label: "Go back" },
359
- renderLink = defaultRenderLink2
394
+ renderLink = defaultRenderLink3
360
395
  }) {
361
396
  return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", children: /* @__PURE__ */ jsxs("div", { className: "relative flex min-h-[560px] flex-col items-center justify-center px-6 py-16 text-center", children: [
362
397
  /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[radial-gradient(circle_at_center,hsl(var(--muted)/0.8),transparent_70%)]" }),
@@ -567,7 +602,7 @@ function SectionTitle({ title, description, badge, className }) {
567
602
  description && /* @__PURE__ */ jsx("p", { className: "mx-auto mt-4 max-w-2xl text-pretty text-muted-foreground", children: description })
568
603
  ] }) });
569
604
  }
570
- var defaultRenderLink3 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
605
+ var defaultRenderLink4 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
571
606
  function HeroSection({
572
607
  heading,
573
608
  badge,
@@ -577,7 +612,7 @@ function HeroSection({
577
612
  heroImage,
578
613
  avatarUrls,
579
614
  socialProofText,
580
- renderLink = defaultRenderLink3
615
+ renderLink = defaultRenderLink4
581
616
  }) {
582
617
  return /* @__PURE__ */ jsx("section", { className: "overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "px-6 py-14 sm:px-10 sm:py-20", children: [
583
618
  /* @__PURE__ */ jsxs("div", { className: "mx-auto grid max-w-6xl items-center gap-10 lg:grid-cols-2 lg:gap-16", children: [
@@ -707,14 +742,14 @@ function FeaturesSection({
707
742
  )) })
708
743
  ] }) }) });
709
744
  }
710
- var defaultRenderLink4 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
745
+ var defaultRenderLink5 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
711
746
  function CtaSection({
712
747
  heading,
713
748
  description,
714
749
  primaryCta,
715
750
  secondaryCta,
716
751
  footnote,
717
- renderLink = defaultRenderLink4
752
+ renderLink = defaultRenderLink5
718
753
  }) {
719
754
  return /* @__PURE__ */ jsx("section", { className: "overflow-hidden rounded-2xl border bg-card", children: /* @__PURE__ */ jsxs("div", { className: "relative px-6 py-16 sm:px-10 sm:py-24", children: [
720
755
  /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-[radial-gradient(ellipse_at_center,hsl(var(--primary)/0.15),transparent_70%)]" }),
@@ -792,7 +827,7 @@ function PricingCard({
792
827
  }
793
828
  );
794
829
  }
795
- var defaultRenderLink5 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
830
+ var defaultRenderLink6 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
796
831
  function PricingSection({
797
832
  title = "Simple, transparent pricing",
798
833
  description = "Start for free. Scale as you grow. No hidden fees.",
@@ -800,7 +835,7 @@ function PricingSection({
800
835
  plans,
801
836
  saveBadge = "Save 34%",
802
837
  isAuthenticated,
803
- renderLink = defaultRenderLink5,
838
+ renderLink = defaultRenderLink6,
804
839
  footnote
805
840
  }) {
806
841
  const [annual, setAnnual] = React25.useState(false);
@@ -1235,13 +1270,13 @@ function ThemeSwitchMinimal() {
1235
1270
  };
1236
1271
  return /* @__PURE__ */ jsx(Button$1, { variant: "ghost", size: "icon", onClick: toggle, className: "size-8", "aria-label": "Toggle theme", children: theme === "dark" ? /* @__PURE__ */ jsx(Sun, { className: "size-4" }) : /* @__PURE__ */ jsx(Moon, { className: "size-4" }) });
1237
1272
  }
1238
- var defaultRenderLink6 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
1273
+ var defaultRenderLink7 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
1239
1274
  function Navbar({
1240
1275
  brand,
1241
1276
  navLinks,
1242
1277
  cta,
1243
1278
  showThemeToggle = false,
1244
- renderLink = defaultRenderLink6
1279
+ renderLink = defaultRenderLink7
1245
1280
  }) {
1246
1281
  const [open, setOpen] = React25.useState(false);
1247
1282
  const brandHref = brand.href ?? "/";
@@ -1311,13 +1346,13 @@ function Navbar({
1311
1346
  ] })
1312
1347
  ] }) });
1313
1348
  }
1314
- var defaultRenderLink7 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
1349
+ var defaultRenderLink8 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
1315
1350
  function Footer({
1316
1351
  brand,
1317
1352
  navLinks,
1318
1353
  socialLinks,
1319
1354
  legal,
1320
- renderLink = defaultRenderLink7
1355
+ renderLink = defaultRenderLink8
1321
1356
  }) {
1322
1357
  const brandHref = brand.href ?? "/";
1323
1358
  const copyrightText = legal ?? `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${brand.name}. All rights reserved.`;
@@ -1835,13 +1870,13 @@ function FullPageSpinner({ message }) {
1835
1870
  message && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-sm", children: message })
1836
1871
  ] });
1837
1872
  }
1838
- var defaultRenderLink8 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
1873
+ var defaultRenderLink9 = ({ href, children, className }) => /* @__PURE__ */ jsx("a", { href, className, children });
1839
1874
  function PageHeader({
1840
1875
  title,
1841
1876
  description,
1842
1877
  breadcrumbs,
1843
1878
  backButton,
1844
- renderLink = defaultRenderLink8,
1879
+ renderLink = defaultRenderLink9,
1845
1880
  className,
1846
1881
  children
1847
1882
  }) {