@bettercms-ai/ui 0.10.0 → 0.11.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.
package/dist/renderer.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,16 @@ 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,
585
588
  align = "left",
586
589
  className = "",
587
590
  "data-bcms-field": field,
@@ -590,8 +593,15 @@ function Button({
590
593
  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
594
  const variantStyles = {
592
595
  primary: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
593
- secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80"
596
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
597
+ tertiary: "bg-transparent text-primary hover:bg-primary/10",
598
+ brand: "bg-accent text-accent-foreground shadow hover:bg-accent/90",
599
+ dark: "bg-foreground text-background shadow hover:bg-foreground/90",
600
+ light: "border bg-background text-foreground shadow-sm hover:bg-muted",
601
+ outline: "border border-current bg-transparent text-primary hover:bg-primary/10",
602
+ link: "h-auto bg-transparent p-0 text-primary underline underline-offset-4"
594
603
  };
604
+ const icon = buttonIconOf(iconProp);
595
605
  const alignClass = {
596
606
  left: "justify-start",
597
607
  center: "justify-center",
@@ -604,20 +614,24 @@ function Button({
604
614
  };
605
615
  const sizeClass = size === "sm" || size === "lg" ? sizeStyles[size] : sizeStyles.md;
606
616
  const fullClass = fullWidth === true ? "flex w-full justify-center" : "";
607
- return /* @__PURE__ */ jsx5(
617
+ return /* @__PURE__ */ jsxs3(
608
618
  "a",
609
619
  {
610
620
  href,
611
621
  "data-bcms-field": field,
612
622
  "data-bcms-kind": kind,
613
- className: cn(baseStyles, variantStyles[variant], alignClass, sizeClass, fullClass, className),
614
- children: text
623
+ className: cn(baseStyles, variantStyles[buttonVariantOf(variant)], alignClass, sizeClass, fullClass, className),
624
+ children: [
625
+ icon && /* @__PURE__ */ jsx5("span", { className: "mr-2 inline-flex", dangerouslySetInnerHTML: { __html: buttonIconSvg(icon, "bcms-btn-icon") } }),
626
+ text,
627
+ arrow === true && /* @__PURE__ */ jsx5("span", { className: "ml-2 inline-flex", dangerouslySetInnerHTML: { __html: buttonIconSvg("arrow-right", "bcms-btn-arrow") } })
628
+ ]
615
629
  }
616
630
  );
617
631
  }
618
632
 
619
633
  // src/blocks/Spacer.tsx
620
- import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
634
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
621
635
  function Spacer({ height = 32, className = "" }) {
622
636
  return /* @__PURE__ */ jsx6(
623
637
  "div",
@@ -625,7 +639,7 @@ function Spacer({ height = 32, className = "" }) {
625
639
  className: `w-full border border-dashed border-muted-foreground/20 rounded flex items-center justify-center ${className}`,
626
640
  style: { height: `${height}px` },
627
641
  "aria-hidden": "true",
628
- children: /* @__PURE__ */ jsxs3("span", { className: "text-xs text-muted-foreground/40 select-none", children: [
642
+ children: /* @__PURE__ */ jsxs4("span", { className: "text-xs text-muted-foreground/40 select-none", children: [
629
643
  height,
630
644
  "px"
631
645
  ] })
@@ -657,7 +671,7 @@ function Columns({
657
671
 
658
672
  // src/blocks/Video.tsx
659
673
  import { useState } from "react";
660
- import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
674
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
661
675
  function getEmbedUrl(url) {
662
676
  const ytMatch = url.match(
663
677
  /(?:youtube\.com\/(?:watch\?v=|embed\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/
@@ -700,7 +714,7 @@ function Video({
700
714
  }
701
715
  );
702
716
  }
703
- return /* @__PURE__ */ jsxs4("div", { className: cn("w-full overflow-hidden rounded-md bg-black aspect-video", className), children: [
717
+ return /* @__PURE__ */ jsxs5("div", { className: cn("w-full overflow-hidden rounded-md bg-black aspect-video", className), children: [
704
718
  !isLoaded && poster && // eslint-disable-next-line @next/next/no-img-element
705
719
  /* @__PURE__ */ jsx8(
706
720
  "img",
@@ -747,9 +761,9 @@ function Section({
747
761
  }
748
762
 
749
763
  // src/blocks/Navbar.tsx
750
- import { jsx as jsx10, jsxs as jsxs5 } from "react/jsx-runtime";
764
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
751
765
  function Navbar({ logo, links, cta, className = "" }) {
752
- return /* @__PURE__ */ jsxs5("nav", { className: cn("flex items-center gap-6 py-4", className), children: [
766
+ return /* @__PURE__ */ jsxs6("nav", { className: cn("flex items-center gap-6 py-4", className), children: [
753
767
  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
768
  /* @__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
769
  cta ? /* @__PURE__ */ jsx10(
@@ -764,10 +778,10 @@ function Navbar({ logo, links, cta, className = "" }) {
764
778
  }
765
779
 
766
780
  // src/blocks/Footer.tsx
767
- import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
781
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
768
782
  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: [
783
+ return /* @__PURE__ */ jsxs7("footer", { className: cn("mt-12 border-t pt-8", className), children: [
784
+ /* @__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
785
  col.heading ? /* @__PURE__ */ jsx11("h4", { className: "mb-2 font-semibold", children: col.heading }) : null,
772
786
  (col.links ?? []).map((l, j) => /* @__PURE__ */ jsx11("a", { href: l.href, className: "text-neutral-500 no-underline", children: l.label }, j))
773
787
  ] }, i)) }),
@@ -777,13 +791,13 @@ function Footer({ columns, copyright, className = "" }) {
777
791
 
778
792
  // src/blocks/Slider.tsx
779
793
  import { useState as useState2 } from "react";
780
- import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
794
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
781
795
  function Slider({ slides, className = "", renderBlock }) {
782
796
  const [i, setI] = useState2(0);
783
797
  const list = slides ?? [];
784
798
  const go = (n) => setI((n + list.length) % (list.length || 1));
785
799
  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: [
800
+ return /* @__PURE__ */ jsxs8("div", { className: cn("relative w-full", className), children: [
787
801
  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
802
  /* @__PURE__ */ jsx12("button", { type: "button", "aria-label": "Previous", onClick: () => go(i - 1), className: cn(btn, "left-2"), children: "\u2039" }),
789
803
  /* @__PURE__ */ jsx12("button", { type: "button", "aria-label": "Next", onClick: () => go(i + 1), className: cn(btn, "right-2"), children: "\u203A" })
@@ -792,11 +806,11 @@ function Slider({ slides, className = "", renderBlock }) {
792
806
 
793
807
  // src/blocks/Tabs.tsx
794
808
  import { useState as useState3 } from "react";
795
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
809
+ import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
796
810
  function Tabs({ tabs, className = "", renderBlock }) {
797
811
  const [active, setActive] = useState3(0);
798
812
  const list = tabs ?? [];
799
- return /* @__PURE__ */ jsxs8("div", { className: cn("w-full", className), children: [
813
+ return /* @__PURE__ */ jsxs9("div", { className: cn("w-full", className), children: [
800
814
  /* @__PURE__ */ jsx13("div", { role: "tablist", className: "mb-4 flex gap-1 border-b", children: list.map((t, idx) => /* @__PURE__ */ jsx13(
801
815
  "button",
802
816
  {
@@ -817,19 +831,19 @@ function Tabs({ tabs, className = "", renderBlock }) {
817
831
  }
818
832
 
819
833
  // src/blocks/Placeholders.tsx
820
- import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
834
+ import { Fragment as Fragment2, jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
821
835
  var box = "rounded border border-dashed border-neutral-300 bg-neutral-50 p-4 text-sm text-neutral-500";
822
836
  function ComponentInstance({
823
837
  componentId,
824
838
  className = ""
825
839
  }) {
826
- return /* @__PURE__ */ jsxs9("div", { className: cn(box, className), children: [
840
+ return /* @__PURE__ */ jsxs10("div", { className: cn(box, className), children: [
827
841
  "Component instance: ",
828
842
  /* @__PURE__ */ jsx14("code", { children: componentId })
829
843
  ] });
830
844
  }
831
845
  function FormPlaceholder({ formId, className = "" }) {
832
- return /* @__PURE__ */ jsxs9("div", { className: cn(box, className), children: [
846
+ return /* @__PURE__ */ jsxs10("div", { className: cn(box, className), children: [
833
847
  "Form: ",
834
848
  /* @__PURE__ */ jsx14("code", { children: formId })
835
849
  ] });
@@ -838,9 +852,9 @@ function CollectionPlaceholder({
838
852
  cardComponentId,
839
853
  className = ""
840
854
  }) {
841
- return /* @__PURE__ */ jsxs9("div", { className: cn(box, className), children: [
855
+ return /* @__PURE__ */ jsxs10("div", { className: cn(box, className), children: [
842
856
  "Collection: entries of this page",
843
- cardComponentId ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
857
+ cardComponentId ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
844
858
  " as ",
845
859
  /* @__PURE__ */ jsx14("code", { children: cardComponentId })
846
860
  ] }) : /* @__PURE__ */ jsx14(Fragment2, { children: " (default card)" })
@@ -945,7 +959,7 @@ function blockStyleToReactStyle(style) {
945
959
 
946
960
  // src/renderer.tsx
947
961
  import "react";
948
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
962
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
949
963
  var CONTAINER_TYPES = /* @__PURE__ */ new Set(["columns", "section", "slider", "tabs"]);
950
964
  function bindingProps(block, annotate) {
951
965
  if (!annotate || !block.id) return {};
@@ -965,7 +979,7 @@ function bindingProps(block, annotate) {
965
979
  function resolveBlock(block, className, annotate = false) {
966
980
  const entry = BLOCK_REGISTRY[block.type];
967
981
  if (!entry) {
968
- return /* @__PURE__ */ jsxs10(
982
+ return /* @__PURE__ */ jsxs11(
969
983
  "div",
970
984
  {
971
985
  className: `w-full p-4 border border-dashed border-red-400 bg-red-50 text-red-600 text-sm rounded ${className ?? ""}`,
@@ -989,7 +1003,7 @@ function BlockRenderer({
989
1003
  }) {
990
1004
  const entry = BLOCK_REGISTRY[block.type];
991
1005
  if (!entry) {
992
- return /* @__PURE__ */ jsxs10(
1006
+ return /* @__PURE__ */ jsxs11(
993
1007
  "div",
994
1008
  {
995
1009
  className: `w-full p-4 border border-dashed border-red-400 bg-red-50 text-red-600 text-sm rounded ${className}`,