@olwiba/ui 0.1.10 → 0.1.12

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
@@ -521,10 +521,14 @@ interface PricingCardProps extends React.HTMLAttributes<HTMLDivElement> {
521
521
  cta: string;
522
522
  highlighted?: boolean;
523
523
  disabled?: boolean;
524
+ /** Disables only the CTA button, leaving the rest of the card interactive. */
525
+ ctaDisabled?: boolean;
524
526
  badge?: React.ReactNode;
527
+ /** Rendered directly below the CTA button (e.g. a "Get notified" link). */
528
+ footer?: React.ReactNode;
525
529
  onSelect?: () => void;
526
530
  }
527
- declare function PricingCard({ name, price, period, description, features, cta, highlighted, disabled, badge, onSelect, className, ...props }: PricingCardProps): react_jsx_runtime.JSX.Element;
531
+ declare function PricingCard({ name, price, period, description, features, cta, highlighted, disabled, ctaDisabled, badge, footer, onSelect, className, ...props }: PricingCardProps): react_jsx_runtime.JSX.Element;
528
532
 
529
533
  interface PricingPlan {
530
534
  name: string;
@@ -534,6 +538,8 @@ interface PricingPlan {
534
538
  cta: string;
535
539
  highlighted?: boolean;
536
540
  disabled?: boolean;
541
+ /** Disables only the CTA button, leaving the rest of the card interactive. */
542
+ ctaDisabled?: boolean;
537
543
  features: PricingFeature[];
538
544
  /** Overrides computed price display (e.g. "$?" for community/reach-out tiers). */
539
545
  priceDisplay?: string;
@@ -551,8 +557,10 @@ interface PricingSectionProps {
551
557
  footnote?: string;
552
558
  mode?: 'subscription' | 'one-time';
553
559
  foundingDeadline?: string;
560
+ /** Rendered below each plan's CTA button (e.g. a "Get notified" link). */
561
+ renderPlanFooter?: (plan: PricingPlan) => React.ReactNode;
554
562
  }
555
- declare function PricingSection({ title, description, badge, plans, saveBadge, isAuthenticated, renderLink, footnote, mode, foundingDeadline, }: PricingSectionProps): react_jsx_runtime.JSX.Element;
563
+ declare function PricingSection({ title, description, badge, plans, saveBadge, isAuthenticated, renderLink, footnote, mode, foundingDeadline, renderPlanFooter, }: PricingSectionProps): react_jsx_runtime.JSX.Element;
556
564
 
557
565
  interface TestimonialsSectionProps {
558
566
  title?: string;
@@ -1056,6 +1064,10 @@ interface FlowBracketProps {
1056
1064
  * Defaults to 8 (near the top of the first child).
1057
1065
  */
1058
1066
  anchorTop?: number;
1067
+ /** Per-side override for the top anchor of the left bracket. Falls back to anchorTop. */
1068
+ anchorTopLeft?: number;
1069
+ /** Per-side override for the top anchor of the right bracket. Falls back to anchorTop. */
1070
+ anchorTopRight?: number;
1059
1071
  /**
1060
1072
  * Vertical anchor for the bottom connection as a percentage of the wrapper height (0–100).
1061
1073
  * Defaults to 92 (near the bottom of the last child).
@@ -1102,7 +1114,7 @@ interface FlowBracketProps {
1102
1114
  * they render at a consistent pixel size regardless of the bracket SVG's aspect
1103
1115
  * ratio (which spans the full section height with preserveAspectRatio="none").
1104
1116
  */
1105
- declare function FlowBracket({ anchorTop, anchorBottom, extent, arrow, color, colorLeft, colorRight, left, right, animate, animateDur, reverseRight, style, className, children, }: FlowBracketProps): react_jsx_runtime.JSX.Element;
1117
+ declare function FlowBracket({ anchorTop, anchorTopLeft, anchorTopRight, anchorBottom, extent, arrow, color, colorLeft, colorRight, left, right, animate, animateDur, reverseRight, style, className, children, }: FlowBracketProps): react_jsx_runtime.JSX.Element;
1106
1118
 
1107
1119
  interface FullPageSpinnerProps {
1108
1120
  message?: string;
package/dist/index.js CHANGED
@@ -498,7 +498,8 @@ function DefaultForm({
498
498
  const hasPrefill = !!(defaultEmail || defaultPassword);
499
499
  const prefillStyle = (active) => active ? { animation: "auth-prefill 1.6s ease-out 0.35s 1 both" } : void 0;
500
500
  return /* @__PURE__ */ jsxs(Card, { className: "w-full", children: [
501
- hasPrefill && /* @__PURE__ */ jsx("style", { children: `@keyframes auth-prefill{0%{box-shadow:0 0 0 0 hsl(var(--primary)/0)}40%{box-shadow:0 0 0 3px hsl(var(--primary)/0.4)}100%{box-shadow:0 0 0 0 hsl(var(--primary)/0)}}` }),
501
+ hasPrefill && // Theme tokens hold full color values (oklch), so opacity must come from color-mix, not hsl(var()/a)
502
+ /* @__PURE__ */ jsx("style", { children: `@keyframes auth-prefill{0%{box-shadow:0 0 0 0 transparent}40%{box-shadow:0 0 0 3px color-mix(in oklab,var(--primary) 45%,transparent),0 0 16px 2px color-mix(in oklab,var(--primary) 35%,transparent)}100%{box-shadow:0 0 0 0 transparent}}` }),
502
503
  /* @__PURE__ */ jsxs(CardHeader, { children: [
503
504
  brand && /* @__PURE__ */ jsx("div", { className: "mb-2", children: brand }),
504
505
  /* @__PURE__ */ jsx(CardTitle, { children: isSignUp ? "Create an account" : "Sign in" }),
@@ -1455,7 +1456,9 @@ function PricingCard({
1455
1456
  cta,
1456
1457
  highlighted = false,
1457
1458
  disabled = false,
1459
+ ctaDisabled = false,
1458
1460
  badge,
1461
+ footer,
1459
1462
  onSelect,
1460
1463
  className,
1461
1464
  ...props
@@ -1488,10 +1491,11 @@ function PricingCard({
1488
1491
  variant: highlighted ? "default" : "outline",
1489
1492
  className: "mt-6 w-full",
1490
1493
  onClick: onSelect,
1491
- disabled,
1494
+ disabled: disabled || ctaDisabled,
1492
1495
  children: cta
1493
1496
  }
1494
1497
  ),
1498
+ footer && /* @__PURE__ */ jsx("div", { className: "mt-3 text-center text-sm", children: footer }),
1495
1499
  /* @__PURE__ */ jsx(Separator, { className: "my-6" }),
1496
1500
  /* @__PURE__ */ jsx("ul", { className: "space-y-3 text-sm", children: features.map((feat) => /* @__PURE__ */ jsx("li", { className: "flex items-center gap-2", children: feat.included ? /* @__PURE__ */ jsxs(Fragment, { children: [
1497
1501
  /* @__PURE__ */ jsx(Check, { className: "size-4 shrink-0 text-primary" }),
@@ -1583,7 +1587,8 @@ function PricingSection({
1583
1587
  renderLink = defaultRenderLink7,
1584
1588
  footnote,
1585
1589
  mode = "subscription",
1586
- foundingDeadline
1590
+ foundingDeadline,
1591
+ renderPlanFooter
1587
1592
  }) {
1588
1593
  const [annual, setAnnual] = React29.useState(false);
1589
1594
  const isOneTime = mode === "one-time";
@@ -1647,7 +1652,9 @@ function PricingSection({
1647
1652
  cta: plan.cta,
1648
1653
  highlighted: plan.highlighted,
1649
1654
  disabled: plan.disabled,
1650
- badge: badge2
1655
+ ctaDisabled: plan.ctaDisabled,
1656
+ badge: badge2,
1657
+ footer: renderPlanFooter?.(plan)
1651
1658
  },
1652
1659
  plan.name
1653
1660
  );
@@ -2346,27 +2353,19 @@ function Navbar({
2346
2353
  })
2347
2354
  ] }),
2348
2355
  /* @__PURE__ */ jsxs(Sheet, { open, onOpenChange: setOpen, children: [
2349
- /* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button$1, { variant: "ghost", size: "icon", className: "justify-self-end md:hidden", children: [
2356
+ /* @__PURE__ */ jsx(SheetTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button$1, { variant: "ghost", size: "icon", className: "col-start-3 justify-self-end md:hidden", children: [
2350
2357
  /* @__PURE__ */ jsx(Menu, { className: "size-5" }),
2351
2358
  /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Open menu" })
2352
2359
  ] }) }),
2353
- /* @__PURE__ */ jsxs(SheetContent, { side: "right", className: "w-72", children: [
2354
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pb-4", children: [
2355
- /* @__PURE__ */ jsx("span", { onClick: () => setOpen(false), className: "cursor-pointer", children: renderLink({
2356
- href: brandHref,
2357
- children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 font-semibold", children: [
2358
- brand.logo,
2359
- /* @__PURE__ */ jsx("span", { children: brand.name })
2360
- ] })
2361
- }) }),
2362
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
2363
- controls?.map((control, i) => /* @__PURE__ */ jsx(React29.Fragment, { children: control }, i)),
2364
- /* @__PURE__ */ jsxs(Button$1, { variant: "ghost", size: "icon", onClick: () => setOpen(false), children: [
2365
- /* @__PURE__ */ jsx(X, { className: "size-4" }),
2366
- /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close menu" })
2367
- ] })
2360
+ /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "w-72", children: [
2361
+ /* @__PURE__ */ jsx("div", { className: "flex items-center pb-4", children: /* @__PURE__ */ jsx("span", { onClick: () => setOpen(false), className: "cursor-pointer", children: renderLink({
2362
+ href: brandHref,
2363
+ children: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2 font-semibold", children: [
2364
+ brand.logo,
2365
+ /* @__PURE__ */ jsx("span", { children: brand.name })
2368
2366
  ] })
2369
- ] }),
2367
+ }) }) }),
2368
+ controls?.length ? /* @__PURE__ */ jsx("div", { className: "mb-4 flex w-full items-center justify-between gap-1", children: controls.map((control, i) => /* @__PURE__ */ jsx(React29.Fragment, { children: control }, i)) }) : null,
2370
2369
  /* @__PURE__ */ jsx(Separator, {}),
2371
2370
  /* @__PURE__ */ jsx("nav", { className: "mt-4 flex flex-col gap-1", children: navLinks.map((link) => /* @__PURE__ */ jsx("span", { onClick: () => setOpen(false), children: renderLink({
2372
2371
  href: link.href,
@@ -3094,6 +3093,8 @@ function FlowConnector({
3094
3093
  }
3095
3094
  function FlowBracket({
3096
3095
  anchorTop = 8,
3096
+ anchorTopLeft,
3097
+ anchorTopRight,
3097
3098
  anchorBottom = 92,
3098
3099
  extent = 22,
3099
3100
  arrow = true,
@@ -3113,30 +3114,32 @@ function FlowBracket({
3113
3114
  const R = 1e3 + extent;
3114
3115
  const cl = colorLeft ?? color;
3115
3116
  const cr = colorRight ?? color;
3116
- const leftD = `M 0,${anchorBottom} L ${L},${anchorBottom} L ${L},${anchorTop} L 0,${anchorTop}`;
3117
- const rightD = reverseRight ? `M 1000,${anchorTop} L ${R},${anchorTop} L ${R},${anchorBottom} L 1000,${anchorBottom}` : `M 1000,${anchorBottom} L ${R},${anchorBottom} L ${R},${anchorTop} L 1000,${anchorTop}`;
3117
+ const aTL = anchorTopLeft ?? anchorTop;
3118
+ const aTR = anchorTopRight ?? anchorTop;
3119
+ const leftD = `M 0,${anchorBottom} L ${L},${anchorBottom} L ${L},${aTL} L 0,${aTL}`;
3120
+ const rightD = reverseRight ? `M 1000,${aTR} L ${R},${aTR} L ${R},${anchorBottom} L 1000,${anchorBottom}` : `M 1000,${anchorBottom} L ${R},${anchorBottom} L ${R},${aTR} L 1000,${aTR}`;
3118
3121
  const ep = `${(extent / 10).toFixed(1)}%`;
3119
3122
  const dotKeyframes = animate ? `
3120
3123
  @keyframes fb-dl{
3121
3124
  0%{top:${anchorBottom}%;left:0;opacity:0}
3122
3125
  6%{opacity:1}
3123
3126
  20%{top:${anchorBottom}%;left:-${ep}}
3124
- 80%{top:${anchorTop}%;left:-${ep};opacity:1}
3125
- 94%{top:${anchorTop}%;left:0;opacity:0}
3126
- 100%{top:${anchorTop}%;left:0;opacity:0}
3127
+ 80%{top:${aTL}%;left:-${ep};opacity:1}
3128
+ 94%{top:${aTL}%;left:0;opacity:0}
3129
+ 100%{top:${aTL}%;left:0;opacity:0}
3127
3130
  }
3128
3131
  @keyframes fb-dr{
3129
3132
  0%{top:${anchorBottom}%;left:100%;opacity:0}
3130
3133
  6%{opacity:1}
3131
3134
  20%{top:${anchorBottom}%;left:calc(100% + ${ep})}
3132
- 80%{top:${anchorTop}%;left:calc(100% + ${ep});opacity:1}
3133
- 94%{top:${anchorTop}%;left:100%;opacity:0}
3134
- 100%{top:${anchorTop}%;left:100%;opacity:0}
3135
+ 80%{top:${aTR}%;left:calc(100% + ${ep});opacity:1}
3136
+ 94%{top:${aTR}%;left:100%;opacity:0}
3137
+ 100%{top:${aTR}%;left:100%;opacity:0}
3135
3138
  }
3136
3139
  @keyframes fb-drr{
3137
- 0%{top:${anchorTop}%;left:100%;opacity:0}
3140
+ 0%{top:${aTR}%;left:100%;opacity:0}
3138
3141
  6%{opacity:1}
3139
- 20%{top:${anchorTop}%;left:calc(100% + ${ep})}
3142
+ 20%{top:${aTR}%;left:calc(100% + ${ep})}
3140
3143
  80%{top:${anchorBottom}%;left:calc(100% + ${ep});opacity:1}
3141
3144
  94%{top:${anchorBottom}%;left:100%;opacity:0}
3142
3145
  100%{top:${anchorBottom}%;left:100%;opacity:0}
@@ -3205,7 +3208,7 @@ function FlowBracket({
3205
3208
  {
3206
3209
  "aria-hidden": true,
3207
3210
  viewBox: "0 0 10 8",
3208
- style: { ...arrowBase, top: `${anchorTop}%`, left: 0 },
3211
+ style: { ...arrowBase, top: `${aTL}%`, left: 0 },
3209
3212
  children: /* @__PURE__ */ jsx("polyline", { points: "1,1 8,4 1,7", style: { stroke: cl }, ...chevronProps })
3210
3213
  }
3211
3214
  ),
@@ -3216,7 +3219,7 @@ function FlowBracket({
3216
3219
  viewBox: "0 0 10 8",
3217
3220
  style: {
3218
3221
  ...arrowBase,
3219
- top: reverseRight ? `${anchorBottom}%` : `${anchorTop}%`,
3222
+ top: reverseRight ? `${anchorBottom}%` : `${aTR}%`,
3220
3223
  left: "100%"
3221
3224
  },
3222
3225
  children: /* @__PURE__ */ jsx("polyline", { points: "9,1 2,4 9,7", style: { stroke: cr }, ...chevronProps })
@@ -3454,7 +3457,7 @@ function BrandColorSwitchMinimal() {
3454
3457
  /* @__PURE__ */ jsx(
3455
3458
  "span",
3456
3459
  {
3457
- className: "absolute -bottom-0.5 -right-0.5 size-1.5 rounded-full ring-1 ring-background",
3460
+ className: `absolute -bottom-0.5 -right-0.5 size-1.5 rounded-full ring-1 ring-background${active === "zinc" ? " dark:ring-white/25" : ""}`,
3458
3461
  style: { background: activeHex }
3459
3462
  }
3460
3463
  )
@@ -3474,7 +3477,7 @@ function BrandColorSwitchMinimal() {
3474
3477
  /* @__PURE__ */ jsx(
3475
3478
  "span",
3476
3479
  {
3477
- className: "flex size-7 items-center justify-center rounded-full ring-offset-background transition-all group-hover:scale-110",
3480
+ className: `flex size-7 items-center justify-center rounded-full ring-offset-background transition-all group-hover:scale-110${color.name === "zinc" ? " border border-transparent dark:border-white/25" : ""}`,
3478
3481
  style: {
3479
3482
  background: PREVIEW_HEX[color.name],
3480
3483
  boxShadow: active === color.name ? `0 0 0 2px var(--background), 0 0 0 4px ${PREVIEW_HEX[color.name]}` : void 0