@sandboxsonny/ace-kit 0.5.0 → 0.6.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/astro-integration.js +1 -1
  3. package/dist/chunk-7M26C36M.js +35 -0
  4. package/dist/cli.js +14 -1179
  5. package/dist/environment-T5K5ZJ2M.js +222 -0
  6. package/dist/main-YRQQWLHX.js +1454 -0
  7. package/dist/vite.js +1 -1
  8. package/docs/command-line.md +30 -1
  9. package/docs/getting-started.md +8 -0
  10. package/package.json +5 -2
  11. package/templates/astro/.dockerignore +7 -0
  12. package/templates/astro/.github/dependabot.yml +19 -0
  13. package/templates/astro/.github/workflows/ci.yml +23 -0
  14. package/templates/astro/.prettierignore +6 -0
  15. package/templates/astro/.prettierrc.json +20 -0
  16. package/templates/astro/.vscode/extensions.json +4 -0
  17. package/templates/astro/.vscode/launch.json +11 -0
  18. package/templates/astro/AGENTS.md +22 -0
  19. package/templates/astro/Dockerfile +17 -0
  20. package/templates/astro/_gitignore +26 -0
  21. package/templates/astro/astro.config.mjs +18 -0
  22. package/templates/astro/eslint.config.js +56 -0
  23. package/templates/astro/package.json +41 -0
  24. package/templates/astro/public/favicon.ico +0 -0
  25. package/templates/astro/public/favicon.svg +9 -0
  26. package/templates/astro/src/ace-kit.generated.d.ts +24 -0
  27. package/templates/astro/src/components/PageContent.astro +113 -0
  28. package/templates/astro/src/components/SiteFooter.astro +19 -0
  29. package/templates/astro/src/components/SiteHeader.astro +121 -0
  30. package/templates/astro/src/components/sections/Faq.astro +54 -0
  31. package/templates/astro/src/components/sections/Faq.schema.ts +17 -0
  32. package/templates/astro/src/components/sections/Gallery.astro +74 -0
  33. package/templates/astro/src/components/sections/Gallery.schema.ts +20 -0
  34. package/templates/astro/src/components/sections/Hero.astro +58 -0
  35. package/templates/astro/src/components/sections/Hero.schema.ts +14 -0
  36. package/templates/astro/src/layouts/BaseLayout.astro +36 -0
  37. package/templates/astro/src/pages/[...slug].astro +31 -0
  38. package/templates/astro/src/styles/global.css +56 -0
  39. package/templates/astro/src/types/page.d.ts +4 -0
  40. package/templates/astro/tsconfig.json +11 -0
  41. package/templates/astro/vitest.config.ts +4 -0
  42. package/templates/astro.section-types.json +109 -0
  43. package/templates/react-router/.prettierignore +5 -0
  44. package/templates/react-router/.prettierrc.json +11 -0
  45. package/templates/react-router/_gitignore +7 -0
  46. package/templates/react-router/app/ace-kit.generated.d.ts +18 -0
  47. package/templates/react-router/app/app.css +172 -0
  48. package/templates/react-router/app/components/page-content.tsx +32 -0
  49. package/templates/react-router/app/components/site-footer.tsx +9 -0
  50. package/templates/react-router/app/components/site-header.tsx +49 -0
  51. package/templates/react-router/app/entry.server.tsx +1 -0
  52. package/templates/react-router/app/root.tsx +75 -0
  53. package/templates/react-router/app/routes/page.test.tsx +64 -0
  54. package/templates/react-router/app/routes/page.tsx +22 -0
  55. package/templates/react-router/app/routes.ts +4 -0
  56. package/templates/react-router/app/types/page.d.ts +4 -0
  57. package/templates/react-router/eslint.config.js +76 -0
  58. package/templates/react-router/package.json +51 -0
  59. package/templates/react-router/public/favicon.svg +9 -0
  60. package/templates/react-router/react-router.config.ts +6 -0
  61. package/templates/react-router/tsconfig.json +22 -0
  62. package/templates/react-router/vite.config.ts +10 -0
  63. package/templates/react-router/vitest.config.ts +15 -0
  64. /package/dist/{chunk-WM5NOQE3.js → chunk-G5FGBOFT.js} +0 -0
@@ -0,0 +1,121 @@
1
+ ---
2
+ import { isCurrentPage } from "@sandboxsonny/ace-kit";
3
+ import { getMenuLinks } from "@sandboxsonny/ace-kit/astro";
4
+
5
+ // The CMS menu with the handle "main-menu", or the built-in links if the site has none yet or the CMS can't be reached.
6
+ const links = await getMenuLinks("main-menu", {
7
+ fallback: [
8
+ { label: "Home", to: "/" },
9
+ { label: "About", to: "/pages/about" },
10
+ { label: "Contact", to: "/pages/contact" },
11
+ ],
12
+ });
13
+ const { pathname } = Astro.url;
14
+ ---
15
+
16
+ <header class="site-header">
17
+ <div class="container site-header__inner">
18
+ <a href="/" class="site-header__name">
19
+ Example Site
20
+ </a>
21
+ <nav aria-label="Main">
22
+ <ul class="site-header__links">
23
+ {links.map((link) => (
24
+ <li>
25
+ <a href={link.to} aria-current={isCurrentPage(link, pathname) ? "page" : undefined}>
26
+ {link.label}
27
+ </a>
28
+ {link.children && link.children.length > 0 && (
29
+ <ul class="site-header__sublinks">
30
+ {link.children.map((child) => (
31
+ <li>
32
+ <a href={child.to} aria-current={isCurrentPage(child, pathname) ? "page" : undefined}>
33
+ {child.label}
34
+ </a>
35
+ {child.children && child.children.length > 0 && (
36
+ <ul class="site-header__sublinks site-header__sublinks--deep">
37
+ {child.children.map((grandchild) => (
38
+ <li>
39
+ <a href={grandchild.to}>{grandchild.label}</a>
40
+ </li>
41
+ ))}
42
+ </ul>
43
+ )}
44
+ </li>
45
+ ))}
46
+ </ul>
47
+ )}
48
+ </li>
49
+ ))}
50
+ </ul>
51
+ </nav>
52
+ </div>
53
+ </header>
54
+
55
+ <style>
56
+ .site-header {
57
+ border-bottom: 1px solid var(--colour-surface);
58
+ }
59
+ .site-header__inner {
60
+ display: flex;
61
+ align-items: center;
62
+ justify-content: space-between;
63
+ padding-block: 1rem;
64
+ }
65
+ .site-header__name {
66
+ font-weight: 700;
67
+ font-size: 1.25rem;
68
+ color: var(--colour-text);
69
+ text-decoration: none;
70
+ }
71
+ .site-header__links {
72
+ display: flex;
73
+ gap: 1.5rem;
74
+ margin: 0;
75
+ padding: 0;
76
+ list-style: none;
77
+ }
78
+ .site-header__links a {
79
+ color: var(--colour-muted);
80
+ text-decoration: none;
81
+ }
82
+ .site-header__links > li {
83
+ position: relative;
84
+ }
85
+ .site-header__sublinks {
86
+ display: none;
87
+ position: absolute;
88
+ z-index: 10;
89
+ top: 100%;
90
+ left: 0;
91
+ min-width: 12rem;
92
+ margin: 0;
93
+ padding: 0.5rem 0;
94
+ list-style: none;
95
+ background: var(--colour-background);
96
+ border: 1px solid var(--colour-surface);
97
+ border-radius: 0.5rem;
98
+ }
99
+ .site-header__sublinks li {
100
+ position: relative;
101
+ }
102
+ .site-header__sublinks a {
103
+ display: block;
104
+ padding: 0.4rem 1rem;
105
+ white-space: nowrap;
106
+ }
107
+ .site-header__sublinks--deep {
108
+ top: 0;
109
+ left: 100%;
110
+ }
111
+ .site-header__links > li:hover > .site-header__sublinks,
112
+ .site-header__links > li:focus-within > .site-header__sublinks,
113
+ .site-header__sublinks li:hover > .site-header__sublinks,
114
+ .site-header__sublinks li:focus-within > .site-header__sublinks {
115
+ display: block;
116
+ }
117
+ .site-header__links a[aria-current="page"] {
118
+ color: var(--colour-text);
119
+ font-weight: 600;
120
+ }
121
+ </style>
@@ -0,0 +1,54 @@
1
+ ---
2
+ import AceRichText from "@sandboxsonny/ace-kit/astro/AceRichText.astro";
3
+
4
+ import type { SectionOf } from "@sandboxsonny/ace-kit";
5
+ import type faq from "./Faq.schema";
6
+
7
+ type Props = {
8
+ section: SectionOf<typeof faq>;
9
+ };
10
+
11
+ const { section } = Astro.props;
12
+ const { heading } = section.values;
13
+ ---
14
+
15
+ <section class="section" data-section={section.type}>
16
+ <div class="container faq">
17
+ {heading && <h2>{heading}</h2>}
18
+ {section.blocks.map((block) => (
19
+ <details>
20
+ <summary>{block.values.question}</summary>
21
+ {block.values.answer && (
22
+ <div class="answer">
23
+ <AceRichText document={block.values.answer} />
24
+ </div>
25
+ )}
26
+ </details>
27
+ ))}
28
+ </div>
29
+ </section>
30
+
31
+ <style>
32
+ .faq {
33
+ max-width: 42rem;
34
+ }
35
+ h2 {
36
+ margin: 0 0 1rem;
37
+ font-size: 1.75rem;
38
+ }
39
+ details {
40
+ border-bottom: 1px solid var(--colour-surface);
41
+ padding-block: 0.75rem;
42
+ }
43
+ summary {
44
+ cursor: pointer;
45
+ font-weight: 600;
46
+ }
47
+ .answer {
48
+ margin-top: 0.5rem;
49
+ color: var(--colour-muted);
50
+ }
51
+ .answer :global(* + *) {
52
+ margin-top: 0.75rem;
53
+ }
54
+ </style>
@@ -0,0 +1,17 @@
1
+ import { defineSection } from "@sandboxsonny/ace-kit";
2
+
3
+ // An FAQ is a heading and a list of questions. The questions are blocks: the editor adds as many as they like.
4
+ export default defineSection({
5
+ handle: "faq",
6
+ name: "FAQ",
7
+ fields: [{ handle: "heading", label: "Heading", type: "text" }],
8
+ blocks: {
9
+ question: {
10
+ name: "Question",
11
+ fields: [
12
+ { handle: "question", label: "Question", type: "text", required: true },
13
+ { handle: "answer", label: "Answer", type: "richtext" },
14
+ ],
15
+ },
16
+ },
17
+ });
@@ -0,0 +1,74 @@
1
+ ---
2
+ import { formatAceDate } from "@sandboxsonny/ace-kit";
3
+ import AceImage from "@sandboxsonny/ace-kit/astro/AceImage.astro";
4
+
5
+ import type { SectionOf } from "@sandboxsonny/ace-kit";
6
+ import type gallery from "./Gallery.schema";
7
+
8
+ type Props = {
9
+ section: SectionOf<typeof gallery>;
10
+ };
11
+
12
+ const { section } = Astro.props;
13
+ const { heading, published } = section.values;
14
+ const photos = section.blocks.filter((block) => block.values.image || block.values.caption);
15
+ ---
16
+
17
+ <section class="section" data-section={section.type}>
18
+ <div class="container">
19
+ {heading && <h2>{heading}</h2>}
20
+ {published && (
21
+ <p class="published">
22
+ <time datetime={published}>{formatAceDate(published, { locale: "en-GB" }) ?? published}</time>
23
+ </p>
24
+ )}
25
+ {photos.length > 0 ? (
26
+ <ul class="photos">
27
+ {photos.map((photo) => (
28
+ <li>
29
+ <figure>
30
+ {photo.values.image && <AceImage image={photo.values.image} sizes="(min-width: 48rem) 20rem, 100vw" />}
31
+ {photo.values.caption && <figcaption>{photo.values.caption}</figcaption>}
32
+ </figure>
33
+ </li>
34
+ ))}
35
+ </ul>
36
+ ) : (
37
+ <p class="empty">No photos yet.</p>
38
+ )}
39
+ </div>
40
+ </section>
41
+
42
+ <style>
43
+ h2 {
44
+ margin: 0 0 0.25rem;
45
+ font-size: 1.75rem;
46
+ }
47
+ .published,
48
+ .empty {
49
+ margin: 0 0 1rem;
50
+ color: var(--colour-muted);
51
+ font-size: 0.9rem;
52
+ }
53
+ .photos {
54
+ display: grid;
55
+ grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
56
+ gap: 1rem;
57
+ margin: 0;
58
+ padding: 0;
59
+ list-style: none;
60
+ }
61
+ figure {
62
+ margin: 0;
63
+ }
64
+ figure :global(img) {
65
+ border-radius: 0.5rem;
66
+ width: 100%;
67
+ object-fit: cover;
68
+ }
69
+ figcaption {
70
+ margin-top: 0.4rem;
71
+ color: var(--colour-muted);
72
+ font-size: 0.9rem;
73
+ }
74
+ </style>
@@ -0,0 +1,20 @@
1
+ import { defineSection } from "@sandboxsonny/ace-kit";
2
+
3
+ // A gallery is a heading, a date and a list of photos. The photos are blocks.
4
+ export default defineSection({
5
+ handle: "gallery",
6
+ name: "Gallery",
7
+ fields: [
8
+ { handle: "heading", label: "Heading", type: "text" },
9
+ { handle: "published", label: "Published", type: "date" },
10
+ ],
11
+ blocks: {
12
+ photo: {
13
+ name: "Photo",
14
+ fields: [
15
+ { handle: "image", label: "Image", type: "image" },
16
+ { handle: "caption", label: "Caption", type: "text" },
17
+ ],
18
+ },
19
+ },
20
+ });
@@ -0,0 +1,58 @@
1
+ ---
2
+ import AceImage from "@sandboxsonny/ace-kit/astro/AceImage.astro";
3
+ import AceLink from "@sandboxsonny/ace-kit/astro/AceLink.astro";
4
+
5
+ import type { SectionOf } from "@sandboxsonny/ace-kit";
6
+ import type hero from "./Hero.schema";
7
+
8
+ type Props = {
9
+ section: SectionOf<typeof hero>;
10
+ };
11
+
12
+ const { section } = Astro.props;
13
+ const { heading, subheading, picture, button } = section.values;
14
+ ---
15
+
16
+ <section class="hero section--surface" data-section={section.type}>
17
+ <div class="container hero__inner">
18
+ <div class="hero__text">
19
+ <h2>{heading}</h2>
20
+ {subheading && <p class="hero__subheading">{subheading}</p>}
21
+ {button && <AceLink link={button} class="button" />}
22
+ </div>
23
+ {picture && (
24
+ <div class="hero__picture">
25
+ <AceImage image={picture} sizes="(min-width: 64rem) 32rem, 100vw" lazy={false} />
26
+ </div>
27
+ )}
28
+ </div>
29
+ </section>
30
+
31
+ <style>
32
+ .hero {
33
+ padding-block: 3rem;
34
+ }
35
+ .hero__inner {
36
+ display: grid;
37
+ gap: 2rem;
38
+ align-items: center;
39
+ }
40
+ @media (min-width: 48rem) {
41
+ .hero__inner:has(.hero__picture) {
42
+ grid-template-columns: 1fr 1fr;
43
+ }
44
+ }
45
+ h2 {
46
+ margin: 0 0 0.75rem;
47
+ font-size: 2.25rem;
48
+ line-height: 1.15;
49
+ }
50
+ .hero__subheading {
51
+ margin: 0 0 1.5rem;
52
+ color: var(--colour-muted);
53
+ font-size: 1.15rem;
54
+ }
55
+ .hero__picture :global(img) {
56
+ border-radius: 0.5rem;
57
+ }
58
+ </style>
@@ -0,0 +1,14 @@
1
+ import { defineSection } from "@sandboxsonny/ace-kit";
2
+
3
+ // What a hero can hold. The CMS learns it from this file (the dev server syncs it when it changes), and Hero.astro's
4
+ // props are typed from it.
5
+ export default defineSection({
6
+ handle: "hero",
7
+ name: "Hero",
8
+ fields: [
9
+ { handle: "heading", label: "Heading", type: "text", required: true },
10
+ { handle: "subheading", label: "Subheading", type: "textarea" },
11
+ { handle: "picture", label: "Picture", type: "image" },
12
+ { handle: "button", label: "Button", type: "link" },
13
+ ],
14
+ });
@@ -0,0 +1,36 @@
1
+ ---
2
+ import AcePreviewRefresh from "@sandboxsonny/ace-kit/astro/AcePreviewRefresh.astro";
3
+ import SiteFooter from "~/components/SiteFooter.astro";
4
+ import SiteHeader from "~/components/SiteHeader.astro";
5
+ import "~/styles/global.css";
6
+
7
+ type Props = {
8
+ title: string;
9
+ description?: string;
10
+ /** True when the page is showing a draft inside the CMS's preview frame. */
11
+ preview?: boolean;
12
+ };
13
+
14
+ const { title, description = "A simple example site for testing CMS Ace.", preview = false } = Astro.props;
15
+ ---
16
+
17
+ <!doctype html>
18
+ <html lang="en">
19
+ <head>
20
+ <meta charset="utf-8" />
21
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
22
+ <meta name="description" content={description} />
23
+ <meta name="generator" content={Astro.generator} />
24
+ {preview && <meta name="robots" content="noindex" />}
25
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
26
+ <title>{title}</title>
27
+ </head>
28
+ <body>
29
+ <SiteHeader />
30
+ <main>
31
+ <slot />
32
+ </main>
33
+ <SiteFooter />
34
+ <AcePreviewRefresh />
35
+ </body>
36
+ </html>
@@ -0,0 +1,31 @@
1
+ ---
2
+ import { getPage } from "@sandboxsonny/ace-kit/astro";
3
+ import AceNotice from "@sandboxsonny/ace-kit/astro/AceNotice.astro";
4
+
5
+ import PageContent from "~/components/PageContent.astro";
6
+ import BaseLayout from "~/layouts/BaseLayout.astro";
7
+ import type { PageValues } from "~/types/page";
8
+
9
+ // Addresses are /{content type}/{entry}, as on Shopify: "/pages/about" is the entry "about" of the content type
10
+ // "pages", and "/" is the home entry. getPage works out what to show and sets the status and headers.
11
+ const page = await getPage<PageValues>(Astro);
12
+ if (page.kind === "redirect") return Astro.redirect(page.location, page.status);
13
+
14
+ const isPreview = Boolean(page.headers["Cache-Control"]);
15
+ ---
16
+
17
+ {page.kind === "entry" ? (
18
+ <BaseLayout
19
+ title={`${page.entry.title} | Example Site`}
20
+ description={page.entry.description || undefined}
21
+ preview={isPreview}
22
+ >
23
+ <PageContent entry={page.entry} />
24
+ </BaseLayout>
25
+ ) : (
26
+ <BaseLayout title="Example Site" preview={isPreview}>
27
+ <section class="section">
28
+ <AceNotice page={page} class="container" />
29
+ </section>
30
+ </BaseLayout>
31
+ )}
@@ -0,0 +1,56 @@
1
+ :root {
2
+ --colour-background: #ffffff;
3
+ --colour-surface: #f4f6f8;
4
+ --colour-text: #1b2430;
5
+ --colour-muted: #5b6776;
6
+ --colour-accent: #2f5bea;
7
+ --colour-accent-text: #ffffff;
8
+ --content-width: 64rem;
9
+ --font-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
10
+ }
11
+
12
+ *,
13
+ *::before,
14
+ *::after {
15
+ box-sizing: border-box;
16
+ }
17
+
18
+ body {
19
+ margin: 0;
20
+ font-family: var(--font-body);
21
+ line-height: 1.6;
22
+ color: var(--colour-text);
23
+ background: var(--colour-background);
24
+ }
25
+
26
+ img {
27
+ max-width: 100%;
28
+ height: auto;
29
+ }
30
+
31
+ a {
32
+ color: var(--colour-accent);
33
+ }
34
+
35
+ .container {
36
+ width: min(100% - 2rem, var(--content-width));
37
+ margin-inline: auto;
38
+ }
39
+
40
+ .button {
41
+ display: inline-block;
42
+ padding: 0.75rem 1.25rem;
43
+ border-radius: 0.5rem;
44
+ background: var(--colour-accent);
45
+ color: var(--colour-accent-text);
46
+ font-weight: 600;
47
+ text-decoration: none;
48
+ }
49
+
50
+ .section {
51
+ padding-block: 3rem;
52
+ }
53
+
54
+ .section--surface {
55
+ background: var(--colour-surface);
56
+ }
@@ -0,0 +1,4 @@
1
+ import type { AceContentTypes } from "@sandboxsonny/ace-kit";
2
+
3
+ /** The fields of the "Pages" content type, as generated from the CMS (see `npm run generate`). */
4
+ export type PageValues = AceContentTypes["pages"];
@@ -0,0 +1,11 @@
1
+ {
2
+ "extends": "astro/tsconfigs/strict",
3
+ "include": [".astro/types.d.ts", "**/*"],
4
+ "exclude": ["dist"],
5
+ "compilerOptions": {
6
+ "baseUrl": ".",
7
+ "paths": {
8
+ "~/*": ["src/*"]
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,4 @@
1
+ /// <reference types="vitest/config" />
2
+ import { getViteConfig } from "astro/config";
3
+
4
+ export default getViteConfig({ test: { include: ["src/**/*.test.ts"] } });
@@ -0,0 +1,109 @@
1
+ {
2
+ "sections": [
3
+ {
4
+ "handle": "faq",
5
+ "name": "FAQ",
6
+ "fields": [
7
+ {
8
+ "handle": "heading",
9
+ "label": "Heading",
10
+ "component_key": "text",
11
+ "config": {}
12
+ }
13
+ ],
14
+ "blocks": [
15
+ {
16
+ "handle": "question",
17
+ "name": "Question",
18
+ "fields": [
19
+ {
20
+ "handle": "question",
21
+ "label": "Question",
22
+ "component_key": "text",
23
+ "config": {
24
+ "required": true
25
+ }
26
+ },
27
+ {
28
+ "handle": "answer",
29
+ "label": "Answer",
30
+ "component_key": "richtext",
31
+ "config": {}
32
+ }
33
+ ]
34
+ }
35
+ ]
36
+ },
37
+ {
38
+ "handle": "gallery",
39
+ "name": "Gallery",
40
+ "fields": [
41
+ {
42
+ "handle": "heading",
43
+ "label": "Heading",
44
+ "component_key": "text",
45
+ "config": {}
46
+ },
47
+ {
48
+ "handle": "published",
49
+ "label": "Published",
50
+ "component_key": "date",
51
+ "config": {}
52
+ }
53
+ ],
54
+ "blocks": [
55
+ {
56
+ "handle": "photo",
57
+ "name": "Photo",
58
+ "fields": [
59
+ {
60
+ "handle": "image",
61
+ "label": "Image",
62
+ "component_key": "image",
63
+ "config": {}
64
+ },
65
+ {
66
+ "handle": "caption",
67
+ "label": "Caption",
68
+ "component_key": "text",
69
+ "config": {}
70
+ }
71
+ ]
72
+ }
73
+ ]
74
+ },
75
+ {
76
+ "handle": "hero",
77
+ "name": "Hero",
78
+ "fields": [
79
+ {
80
+ "handle": "heading",
81
+ "label": "Heading",
82
+ "component_key": "text",
83
+ "config": {
84
+ "required": true
85
+ }
86
+ },
87
+ {
88
+ "handle": "subheading",
89
+ "label": "Subheading",
90
+ "component_key": "textarea",
91
+ "config": {}
92
+ },
93
+ {
94
+ "handle": "picture",
95
+ "label": "Picture",
96
+ "component_key": "image",
97
+ "config": {}
98
+ },
99
+ {
100
+ "handle": "button",
101
+ "label": "Button",
102
+ "component_key": "link",
103
+ "config": {}
104
+ }
105
+ ],
106
+ "blocks": []
107
+ }
108
+ ]
109
+ }
@@ -0,0 +1,5 @@
1
+ node_modules
2
+ build
3
+ .react-router
4
+ package-lock.json
5
+ app/ace-kit.generated.d.ts
@@ -0,0 +1,11 @@
1
+ {
2
+ "printWidth": 120,
3
+ "tabWidth": 2,
4
+ "useTabs": false,
5
+ "semi": true,
6
+ "singleQuote": false,
7
+ "trailingComma": "all",
8
+ "bracketSpacing": true,
9
+ "arrowParens": "always",
10
+ "endOfLine": "lf"
11
+ }
@@ -0,0 +1,7 @@
1
+ node_modules
2
+ build
3
+ .react-router
4
+ .env
5
+ .env.*
6
+ !.env.example
7
+ .DS_Store
@@ -0,0 +1,18 @@
1
+ // Generated by ace-kit from localhost. Do not edit: run `ace-kit generate` to update it.
2
+ import type { AceImageData, AceRichTextDocument } from "@sandboxsonny/ace-kit";
3
+
4
+ declare module "@sandboxsonny/ace-kit" {
5
+ interface AceContentTypes {
6
+ /** Pages */
7
+ "pages": {
8
+ /** Headline */
9
+ "headline": string;
10
+ /** Body */
11
+ "body"?: AceRichTextDocument;
12
+ /** Hero image */
13
+ "hero"?: AceImageData;
14
+ };
15
+ }
16
+ }
17
+
18
+ export {};