@bettercms-ai/ui 0.10.0 → 0.12.0

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.
@@ -47,7 +47,7 @@ interface ButtonBlockProps extends ButtonProps, BcmsBindingProps {
47
47
  className?: string;
48
48
  align?: "left" | "center" | "right";
49
49
  }
50
- declare function Button({ text, href, variant, size, fullWidth, align, className, "data-bcms-field": field, "data-bcms-kind": kind, }: ButtonBlockProps): react_jsx_runtime.JSX.Element;
50
+ declare function Button({ text, href, variant, size, fullWidth, arrow, icon: iconProp, newTab, align, className, "data-bcms-field": field, "data-bcms-kind": kind, }: ButtonBlockProps): react_jsx_runtime.JSX.Element;
51
51
 
52
52
  interface SpacerBlockProps extends SpacerProps {
53
53
  className?: string;
package/dist/blocks.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { a as Button, C as Columns, H as Heading, I as Image, S as Spacer, T as Text, V as Video } from './Video-lCL18gKf.js';
1
+ export { a as Button, C as Columns, H as Heading, I as Image, S as Spacer, T as Text, V as Video } from './Video-BPXQ-e0c.js';
2
2
  import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { SectionProps, ContentBlock, NavbarProps, FooterProps, SliderProps, TabsProps, ComponentProps, FormProps } from '@bettercms-ai/types';
4
4
  import React from 'react';
package/dist/blocks.js CHANGED
@@ -32,7 +32,7 @@ function Heading({
32
32
  import React from "react";
33
33
  import { PortableText as PT } from "@portabletext/react";
34
34
 
35
- // ../../../../bettercms-backend/packages/richtext/src/types.ts
35
+ // ../richtext/src/types.ts
36
36
  var PT_TYPES = {
37
37
  /** A generic embedded block: `{schemaKey, schemaLabel, fields}`, the successor to Lexical's BlockNode. */
38
38
  block: "bcmsBlock",
@@ -77,7 +77,7 @@ var STORABLE_BLOCK_TYPES = /* @__PURE__ */ new Set([
77
77
  PT_TYPES.file
78
78
  ]);
79
79
 
80
- // ../../../../bettercms-backend/packages/richtext/src/styled.ts
80
+ // ../richtext/src/styled.ts
81
81
  var STYLED_TAGS = [
82
82
  "span",
83
83
  "small",
@@ -160,7 +160,7 @@ function styledAttrEntries(attrs) {
160
160
  return out;
161
161
  }
162
162
 
163
- // ../../../../bettercms-backend/packages/richtext/src/href.ts
163
+ // ../richtext/src/href.ts
164
164
  var SAFE_HREF_SCHEMES = ["http:", "https:", "mailto:", "tel:"];
165
165
  function safeHref(raw) {
166
166
  const trimmed = raw.trim();
@@ -173,7 +173,7 @@ function safeHref(raw) {
173
173
  }
174
174
  }
175
175
 
176
- // ../../../../bettercms-backend/packages/richtext/src/key.ts
176
+ // ../richtext/src/key.ts
177
177
  var ALPHABET = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
178
178
  var KEY_PATTERN = /^[A-Za-z0-9-]{1,32}$/;
179
179
  var isValidKey = (k) => typeof k === "string" && KEY_PATTERN.test(k);
@@ -192,7 +192,7 @@ function deterministicKeys(prefix = "k") {
192
192
  };
193
193
  }
194
194
 
195
- // ../../../../bettercms-backend/packages/richtext/src/table.ts
195
+ // ../richtext/src/table.ts
196
196
  var isRecord = (v) => !!v && typeof v === "object" && !Array.isArray(v);
197
197
  var isPortableTextTable = (n) => isRecord(n) && n._type === PT_TYPES.table && Array.isArray(n.rows);
198
198
  var isBuiltInTableBlock = (n) => isRecord(n) && n._type === PT_TYPES.block && n.schemaKey === BUILTIN_TABLE_KEY;
@@ -303,7 +303,7 @@ function migrateTable(node, key = randomKey, read = asIs) {
303
303
  };
304
304
  }
305
305
 
306
- // ../../../../bettercms-backend/packages/richtext/src/read.ts
306
+ // ../richtext/src/read.ts
307
307
  var isRecord2 = (v) => !!v && typeof v === "object" && !Array.isArray(v);
308
308
  function normalizePortableText(value, key = randomKey) {
309
309
  if (!Array.isArray(value)) return [];
@@ -575,13 +575,17 @@ function Image({
575
575
  }
576
576
 
577
577
  // src/blocks/Button.tsx
578
- import { jsx as jsx5 } from "react/jsx-runtime";
578
+ import { buttonIconOf, buttonIconSvg, buttonVariantOf } from "@bettercms-ai/types";
579
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
579
580
  function Button({
580
581
  text,
581
582
  href,
582
583
  variant = "primary",
583
584
  size = "md",
584
585
  fullWidth = false,
586
+ arrow = false,
587
+ icon: iconProp,
588
+ newTab = false,
585
589
  align = "left",
586
590
  className = "",
587
591
  "data-bcms-field": field,
@@ -590,8 +594,15 @@ function Button({
590
594
  const baseStyles = "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50";
591
595
  const variantStyles = {
592
596
  primary: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
593
- secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80"
597
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
598
+ tertiary: "bg-transparent text-primary hover:bg-primary/10",
599
+ brand: "bg-accent text-accent-foreground shadow hover:bg-accent/90",
600
+ dark: "bg-foreground text-background shadow hover:bg-foreground/90",
601
+ light: "border bg-background text-foreground shadow-sm hover:bg-muted",
602
+ outline: "border border-current bg-transparent text-primary hover:bg-primary/10",
603
+ link: "h-auto bg-transparent p-0 text-primary underline underline-offset-4"
594
604
  };
605
+ const icon = buttonIconOf(iconProp);
595
606
  const alignClass = {
596
607
  left: "justify-start",
597
608
  center: "justify-center",
@@ -604,20 +615,25 @@ function Button({
604
615
  };
605
616
  const sizeClass = size === "sm" || size === "lg" ? sizeStyles[size] : sizeStyles.md;
606
617
  const fullClass = fullWidth === true ? "flex w-full justify-center" : "";
607
- return /* @__PURE__ */ jsx5(
618
+ return /* @__PURE__ */ jsxs3(
608
619
  "a",
609
620
  {
610
621
  href,
622
+ ...newTab === true ? { target: "_blank", rel: "noopener noreferrer" } : {},
611
623
  "data-bcms-field": field,
612
624
  "data-bcms-kind": kind,
613
- className: cn(baseStyles, variantStyles[variant], alignClass, sizeClass, fullClass, className),
614
- children: text
625
+ className: cn(baseStyles, variantStyles[buttonVariantOf(variant)], alignClass, sizeClass, fullClass, className),
626
+ children: [
627
+ icon && /* @__PURE__ */ jsx5("span", { className: "mr-2 inline-flex", dangerouslySetInnerHTML: { __html: buttonIconSvg(icon, "bcms-btn-icon") } }),
628
+ text,
629
+ arrow === true && /* @__PURE__ */ jsx5("span", { className: "ml-2 inline-flex", dangerouslySetInnerHTML: { __html: buttonIconSvg("arrow-right", "bcms-btn-arrow") } })
630
+ ]
615
631
  }
616
632
  );
617
633
  }
618
634
 
619
635
  // src/blocks/Spacer.tsx
620
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
636
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
621
637
  function Spacer({ height = 32, className = "" }) {
622
638
  return /* @__PURE__ */ jsx6(
623
639
  "div",
@@ -625,7 +641,7 @@ function Spacer({ height = 32, className = "" }) {
625
641
  className: `w-full border border-dashed border-muted-foreground/20 rounded flex items-center justify-center ${className}`,
626
642
  style: { height: `${height}px` },
627
643
  "aria-hidden": "true",
628
- children: /* @__PURE__ */ jsxs3("span", { className: "text-xs text-muted-foreground/40 select-none", children: [
644
+ children: /* @__PURE__ */ jsxs4("span", { className: "text-xs text-muted-foreground/40 select-none", children: [
629
645
  height,
630
646
  "px"
631
647
  ] })
@@ -657,7 +673,7 @@ function Columns({
657
673
 
658
674
  // src/blocks/Video.tsx
659
675
  import { useState } from "react";
660
- import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
676
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
661
677
  function getEmbedUrl(url) {
662
678
  const ytMatch = url.match(
663
679
  /(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/
@@ -700,7 +716,7 @@ function Video({
700
716
  }
701
717
  );
702
718
  }
703
- return /* @__PURE__ */ jsxs4("div", { className: cn("w-full overflow-hidden rounded-md bg-black aspect-video", className), children: [
719
+ return /* @__PURE__ */ jsxs5("div", { className: cn("w-full overflow-hidden rounded-md bg-black aspect-video", className), children: [
704
720
  !isLoaded && poster && // eslint-disable-next-line @next/next/no-img-element
705
721
  /* @__PURE__ */ jsx8(
706
722
  "img",
@@ -747,9 +763,9 @@ function Section({
747
763
  }
748
764
 
749
765
  // src/blocks/Navbar.tsx
750
- import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
766
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
751
767
  function Navbar({ logo, links, cta, className = "" }) {
752
- return /* @__PURE__ */ jsxs5("nav", { className: cn("flex items-center gap-6 py-4", className), children: [
768
+ return /* @__PURE__ */ jsxs6("nav", { className: cn("flex items-center gap-6 py-4", className), children: [
753
769
  logo?.src ? /* @__PURE__ */ jsx10("a", { href: logo.href ?? "/", className: "shrink-0", children: /* @__PURE__ */ jsx10("img", { src: logo.src, alt: logo.alt, className: "h-8 w-auto" }) }) : null,
754
770
  /* @__PURE__ */ jsx10("div", { className: "flex flex-1 gap-5", children: (links ?? []).map((l, i) => /* @__PURE__ */ jsx10("a", { href: l.href, className: "text-inherit no-underline", children: l.label }, i)) }),
755
771
  cta ? /* @__PURE__ */ jsx10(
@@ -764,10 +780,10 @@ function Navbar({ logo, links, cta, className = "" }) {
764
780
  }
765
781
 
766
782
  // src/blocks/Footer.tsx
767
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
783
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
768
784
  function Footer({ columns, copyright, className = "" }) {
769
- return /* @__PURE__ */ jsxs6("footer", { className: cn("mt-12 border-t pt-8", className), children: [
770
- /* @__PURE__ */ jsx11("div", { className: "flex flex-wrap gap-12", children: (columns ?? []).map((col, i) => /* @__PURE__ */ jsxs6("div", { className: "flex flex-col gap-1.5", children: [
785
+ return /* @__PURE__ */ jsxs7("footer", { className: cn("mt-12 border-t pt-8", className), children: [
786
+ /* @__PURE__ */ jsx11("div", { className: "flex flex-wrap gap-12", children: (columns ?? []).map((col, i) => /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-1.5", children: [
771
787
  col.heading ? /* @__PURE__ */ jsx11("h4", { className: "mb-2 font-semibold", children: col.heading }) : null,
772
788
  (col.links ?? []).map((l, j) => /* @__PURE__ */ jsx11("a", { href: l.href, className: "text-neutral-500 no-underline", children: l.label }, j))
773
789
  ] }, i)) }),
@@ -777,13 +793,13 @@ function Footer({ columns, copyright, className = "" }) {
777
793
 
778
794
  // src/blocks/Slider.tsx
779
795
  import { useState as useState2 } from "react";
780
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
796
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
781
797
  function Slider({ slides, className = "", renderBlock }) {
782
798
  const [i, setI] = useState2(0);
783
799
  const list = slides ?? [];
784
800
  const go = (n) => setI((n + list.length) % (list.length || 1));
785
801
  const btn = "absolute top-1/2 -translate-y-1/2 flex h-9 w-9 items-center justify-center rounded-full border-0 bg-black/50 text-white cursor-pointer";
786
- return /* @__PURE__ */ jsxs7("div", { className: cn("relative w-full", className), children: [
802
+ return /* @__PURE__ */ jsxs8("div", { className: cn("relative w-full", className), children: [
787
803
  list.map((s, idx) => /* @__PURE__ */ jsx12("div", { hidden: idx !== i, className: "flex flex-col gap-4", children: (s.children ?? []).map((b) => /* @__PURE__ */ jsx12("span", { children: renderBlock ? renderBlock(b) : null }, b.id)) }, s.id)),
788
804
  /* @__PURE__ */ jsx12("button", { type: "button", "aria-label": "Previous", onClick: () => go(i - 1), className: cn(btn, "left-2"), children: "\u2039" }),
789
805
  /* @__PURE__ */ jsx12("button", { type: "button", "aria-label": "Next", onClick: () => go(i + 1), className: cn(btn, "right-2"), children: "\u203A" })
@@ -792,11 +808,11 @@ function Slider({ slides, className = "", renderBlock }) {
792
808
 
793
809
  // src/blocks/Tabs.tsx
794
810
  import { useState as useState3 } from "react";
795
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
811
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
796
812
  function Tabs({ tabs, className = "", renderBlock }) {
797
813
  const [active, setActive] = useState3(0);
798
814
  const list = tabs ?? [];
799
- return /* @__PURE__ */ jsxs8("div", { className: cn("w-full", className), children: [
815
+ return /* @__PURE__ */ jsxs9("div", { className: cn("w-full", className), children: [
800
816
  /* @__PURE__ */ jsx13("div", { role: "tablist", className: "mb-4 flex gap-1 border-b", children: list.map((t, idx) => /* @__PURE__ */ jsx13(
801
817
  "button",
802
818
  {
@@ -817,19 +833,19 @@ function Tabs({ tabs, className = "", renderBlock }) {
817
833
  }
818
834
 
819
835
  // src/blocks/Placeholders.tsx
820
- import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
836
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
821
837
  var box = "rounded border border-dashed border-neutral-300 bg-neutral-50 p-4 text-sm text-neutral-500";
822
838
  function ComponentInstance({
823
839
  componentId,
824
840
  className = ""
825
841
  }) {
826
- return /* @__PURE__ */ jsxs9("div", { className: cn(box, className), children: [
842
+ return /* @__PURE__ */ jsxs10("div", { className: cn(box, className), children: [
827
843
  "Component instance: ",
828
844
  /* @__PURE__ */ jsx14("code", { children: componentId })
829
845
  ] });
830
846
  }
831
847
  function FormPlaceholder({ formId, className = "" }) {
832
- return /* @__PURE__ */ jsxs9("div", { className: cn(box, className), children: [
848
+ return /* @__PURE__ */ jsxs10("div", { className: cn(box, className), children: [
833
849
  "Form: ",
834
850
  /* @__PURE__ */ jsx14("code", { children: formId })
835
851
  ] });