@the-smithy/create-hearth-site 0.12.0 → 0.13.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@the-smithy/create-hearth-site",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Start a new client website powered by Hearth: pnpm create @the-smithy/hearth-site",
5
5
  "type": "module",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -29,7 +29,7 @@
29
29
  ],
30
30
  "devDependencies": {
31
31
  "vitest": "^5.0.3",
32
- "@the-smithy/hearth-schema": "^0.12.0"
32
+ "@the-smithy/hearth-schema": "^0.13.0"
33
33
  },
34
34
  "scripts": {
35
35
  "test": "node --test \"test/**/*.test.js\" && vitest run test/blocks.test.ts"
@@ -0,0 +1,20 @@
1
+ import type { BlockOf } from "@the-smithy/hearth";
2
+ import type { ComponentType } from "react";
3
+
4
+ /**
5
+ * This site's own blocks (Settings → Custom blocks in Hearth), one component per block key. Hearth stores what
6
+ * editors enter under `values`, keyed by each field's name; images come as { src, alt } with absolute URLs, links
7
+ * as { label, href }, lists as arrays of items. GET /custom-blocks (`hearth.customBlocks.list()`) describes them.
8
+ *
9
+ * "team-member": ({ values }) => <TeamMember name={values.name as string} photo={values.photo as ImageRef} />,
10
+ */
11
+ const customBlocks: Record<string, ComponentType<{ values: Record<string, unknown> }>> = {};
12
+
13
+ export function CustomBlock({ block }: { block: BlockOf<"custom"> }) {
14
+ const Component = customBlocks[block.data.block];
15
+ if (!Component) {
16
+ if (process.env.NODE_ENV !== "production") console.warn(`[hearth] No component for custom block "${block.data.block}"; add one in components/blocks/custom.tsx.`);
17
+ return null;
18
+ }
19
+ return <Component values={block.data.values} />;
20
+ }
@@ -4,11 +4,12 @@ import { Section, SectionHeading } from "@/components/ui";
4
4
  import { CollectionList } from "./collections";
5
5
  import { CallToAction, CardGrid, Faq, Hero, MediaText, Pricing, Projects, Quote, RichText, Stats } from "./content";
6
6
  import { EventSpotlight, UpcomingEvents } from "./events";
7
+ import { CustomBlock } from "./custom";
7
8
  import { EmberFormBlock } from "./EmberFormBlock";
8
9
  import { HearthForm } from "./Form";
9
10
  import { Donate, FundraiserGrid, FundraiserSpotlight } from "./giving";
10
11
  import { Location, Schedule } from "./info";
11
- import { Gallery, Logos, People, Video } from "./media";
12
+ import { Embed, Gallery, Logos, People, Video } from "./media";
12
13
 
13
14
  function FormBlock({ block }: { block: BlockOf<"form"> }) {
14
15
  return (
@@ -44,6 +45,7 @@ export const blocks: BlockComponents = {
44
45
  quote: Quote,
45
46
  gallery: Gallery,
46
47
  video: Video,
48
+ embed: Embed,
47
49
  people: People,
48
50
  logos: Logos,
49
51
  location: Location,
@@ -55,6 +57,7 @@ export const blocks: BlockComponents = {
55
57
  fundraiserSpotlight: FundraiserSpotlight,
56
58
  fundraiserGrid: FundraiserGrid,
57
59
  donate: Donate,
60
+ custom: CustomBlock,
58
61
  };
59
62
 
60
63
  export function Blocks({ blocks: list }: { blocks: ResolvedBlock[] }) {
@@ -1,4 +1,5 @@
1
1
  import { videoEmbedUrl, type BlockOf } from "@the-smithy/hearth";
2
+ import { HearthEmbed } from "@the-smithy/hearth/react";
2
3
  import { Img, Section, SectionHeading } from "@/components/ui";
3
4
 
4
5
  const columns = { "2": "sm:grid-cols-2", "3": "sm:grid-cols-2 lg:grid-cols-3", "4": "sm:grid-cols-2 lg:grid-cols-4" } as const;
@@ -46,6 +47,19 @@ export function Video({ block }: { block: BlockOf<"video"> }) {
46
47
  );
47
48
  }
48
49
 
50
+ /** Embed code from another service, in the SDK's sandboxed frame (it can't reach the rest of the page). */
51
+ export function Embed({ block }: { block: BlockOf<"embed"> }) {
52
+ const width = { narrow: "max-w-2xl", wide: "max-w-4xl", full: "" }[block.data.width];
53
+ return (
54
+ <Section>
55
+ <figure className={width}>
56
+ <HearthEmbed block={block} className="rounded-xl" />
57
+ {block.data.caption ? <figcaption className="mt-3 opacity-75">{block.data.caption}</figcaption> : null}
58
+ </figure>
59
+ </Section>
60
+ );
61
+ }
62
+
49
63
  export function People({ block }: { block: BlockOf<"people"> }) {
50
64
  const d = block.data;
51
65
  return (