@roottale/cms-renderer-next 0.2.0 → 0.2.1
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/CHANGELOG.md +27 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -0
- package/dist/server.d.ts +192 -0
- package/dist/server.js +630 -0
- package/dist/server.js.map +1 -0
- package/package.json +18 -9
- package/src/FloatingCta.tsx +0 -75
- package/src/LeadForm.tsx +0 -215
- package/src/PostCard.tsx +0 -45
- package/src/TableOfContents.tsx +0 -42
- package/src/__tests__/toc.test.ts +0 -118
- package/src/block-to-react.tsx +0 -199
- package/src/index.ts +0 -7
- package/src/server.tsx +0 -338
- package/src/toc.ts +0 -95
- /package/{src/styles → dist}/cms-public.css +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @roottale/cms-renderer-next
|
|
2
2
|
|
|
3
|
+
## 0.2.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- dist build 도입 — `.ts` 소스 직접 publish 폐기.
|
|
8
|
+
|
|
9
|
+
기존 (0.1.0/0.2.0): `exports` 가 `./src/server.ts` 가리킴 → 외부 Next.js
|
|
10
|
+
Turbopack/Webpack 이 npm 모듈에서 TS 자동 컴파일 안 해 build 실패 (customer
|
|
11
|
+
site 가 `transpilePackages` 명시해야 했음).
|
|
12
|
+
|
|
13
|
+
수정: `tsup` 으로 `dist/*.js` + `dist/*.d.ts` (ESM) 출력. `exports` 가 dist
|
|
14
|
+
가리킴. customer site 측 `transpilePackages` 불필요.
|
|
15
|
+
- `cms-client@0.1.1` — ESM `dist/server.js` + types
|
|
16
|
+
- `cms-core@0.2.1` — ESM `dist/index.js` + types
|
|
17
|
+
- `cms-renderer-next@0.2.1` — ESM `dist/{server,index}.js` + types + `dist/cms-public.css`
|
|
18
|
+
- `server.tsx` 의 `import "./styles/cms-public.css"` 제거 — customer 가
|
|
19
|
+
`@roottale/cms-renderer-next/styles` 로 명시 import (README 정합).
|
|
20
|
+
- `cms-renderer-astro@0.2.1` — ESM `dist/index.js` + types
|
|
21
|
+
|
|
22
|
+
후속 (customer site PR):
|
|
23
|
+
- roottale-web / kjmtax / theoneulsan 의 `next.config` 의 `transpilePackages`
|
|
24
|
+
에서 `@roottale/cms-*` 제거. `pnpm update @roottale/cms-client @roottale/cms-renderer-next` 로 patch 적용.
|
|
25
|
+
|
|
26
|
+
- Updated dependencies
|
|
27
|
+
- @roottale/cms-core@0.2.1
|
|
28
|
+
- @roottale/cms-client@0.1.1
|
|
29
|
+
|
|
3
30
|
## 0.2.0
|
|
4
31
|
|
|
5
32
|
### Minor Changes
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { ReactElement } from 'react';
|
|
2
|
+
import { CmsPostContent, CmsPostType } from '@roottale/cms-client/server';
|
|
3
|
+
import { Block } from '@roottale/cms-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `<RootTalePostCard>` — server-only summary card for a single CmsPostContent.
|
|
7
|
+
*
|
|
8
|
+
* Building block for `<RootTaleBlogList>` (and customer-side custom grids).
|
|
9
|
+
* Pure SSR — anchor + title + meta + excerpt. Featured image is left out for
|
|
10
|
+
* now: `CmsPostContent` only carries `featuredMediaId`, not a public URL.
|
|
11
|
+
* Media URL resolution belongs in a separate slice once `cms-client` exposes
|
|
12
|
+
* it (ADR-0034 §4 media followup — CF Images variants).
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
interface RootTalePostCardProps {
|
|
16
|
+
post: CmsPostContent;
|
|
17
|
+
/** Customer-side URL builder. Defaults to `/blog/${slug}`. */
|
|
18
|
+
href?: (post: CmsPostContent) => string;
|
|
19
|
+
}
|
|
20
|
+
declare function RootTalePostCard(props: RootTalePostCardProps): ReactElement;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* `@roottale/cms-renderer/toc` — Tiptap doc → TOC entries + heading id injection.
|
|
24
|
+
*
|
|
25
|
+
* Server-only utility. Walks a Tiptap JSON doc, extracts H2/H3 headings, and
|
|
26
|
+
* derives stable kebab-case ids (Korean-safe). The companion `attachHeadingIds`
|
|
27
|
+
* mutates a shallow clone of the doc so renderers can emit `<h2 id="...">`
|
|
28
|
+
* anchors that match what `<RootTaleTableOfContents>` links to.
|
|
29
|
+
*
|
|
30
|
+
* Internal ancestor: `roottale-internal/packages/cms-renderer/src/toc.ts`
|
|
31
|
+
* (HTML-string based, vendored snapshot). Ported to Tiptap-JSON because the
|
|
32
|
+
* platform renderer no longer round-trips through HTML before render.
|
|
33
|
+
*/
|
|
34
|
+
interface TocEntry {
|
|
35
|
+
level: 2 | 3;
|
|
36
|
+
text: string;
|
|
37
|
+
id: string;
|
|
38
|
+
}
|
|
39
|
+
declare function headingToId(text: string): string;
|
|
40
|
+
declare function extractToc(doc: Record<string, unknown>): TocEntry[];
|
|
41
|
+
/**
|
|
42
|
+
* Returns a shallow-cloned Tiptap doc where each H2/H3 carries the matching
|
|
43
|
+
* `attrs.id` from `entries` (same order as `extractToc` returns). Existing
|
|
44
|
+
* `id` attrs are overwritten so renderer + TOC always agree on anchors.
|
|
45
|
+
*/
|
|
46
|
+
declare function attachHeadingIds(doc: Record<string, unknown>, entries: TocEntry[]): Record<string, unknown>;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* `<RootTaleTableOfContents>` — server-only anchor list for blog posts.
|
|
50
|
+
*
|
|
51
|
+
* Pure SSR. Renders `<nav>` + ordered anchors that link to `#<id>` slots
|
|
52
|
+
* emitted by `attachHeadingIds`. No scroll-spy here — that requires an
|
|
53
|
+
* `IntersectionObserver` which only exists in the browser; a client-island
|
|
54
|
+
* variant can layer on top later without changing the data contract.
|
|
55
|
+
*
|
|
56
|
+
* Internal ancestor: `roottale-internal/packages/cms-renderer/src/TableOfContents.tsx`
|
|
57
|
+
* (had `'use client'` + IntersectionObserver). Stripped to server-safe form per
|
|
58
|
+
* the platform renderer contract (no `'use client'` boundary — ADR-0023 §5.3).
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
interface RootTaleTableOfContentsProps {
|
|
62
|
+
entries: TocEntry[];
|
|
63
|
+
title?: string;
|
|
64
|
+
}
|
|
65
|
+
declare function RootTaleTableOfContents(props: RootTaleTableOfContentsProps): ReactElement | null;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* `<RootTaleFloatingCta>` — fixed-position call-to-action stack.
|
|
69
|
+
*
|
|
70
|
+
* Server-only (anchors only, no state). External targets (`kakao` / `custom`)
|
|
71
|
+
* open in a new tab with `rel="noopener noreferrer"`; tel/contact stay in the
|
|
72
|
+
* same tab so iOS/Android can trigger the dialer / mailto handler.
|
|
73
|
+
*
|
|
74
|
+
* Internal ancestor: `roottale-internal/packages/cms-renderer/src/FloatingCta.tsx`.
|
|
75
|
+
*/
|
|
76
|
+
|
|
77
|
+
type CtaButtonType = "phone" | "contact" | "kakao" | "custom";
|
|
78
|
+
interface CtaButton {
|
|
79
|
+
type: CtaButtonType;
|
|
80
|
+
label: string;
|
|
81
|
+
href: string;
|
|
82
|
+
/** Optional override icon (emoji or short text). */
|
|
83
|
+
icon?: string;
|
|
84
|
+
}
|
|
85
|
+
type FloatingCtaPosition = "bottom-right" | "bottom-left" | "bottom-center";
|
|
86
|
+
interface RootTaleFloatingCtaProps {
|
|
87
|
+
buttons: CtaButton[];
|
|
88
|
+
position?: FloatingCtaPosition;
|
|
89
|
+
}
|
|
90
|
+
declare function RootTaleFloatingCta(props: RootTaleFloatingCtaProps): ReactElement | null;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* `@roottale/cms-renderer-next` — RootTaleLeadForm RSC.
|
|
94
|
+
*
|
|
95
|
+
* 외부 고객 사이트(roottale.com, 고객사 외주)의 진단 신청 폼. HTML form POST →
|
|
96
|
+
* admin-tenant `/api/lead-intake`. cross-origin POST 는 CORS 불필요 (HTML form
|
|
97
|
+
* submission). PII 는 server 측에서 암호화 후 `inquiries` insert, 302 redirect.
|
|
98
|
+
*
|
|
99
|
+
* vertical prop:
|
|
100
|
+
* - 미지정 = "분야 선택" select 노출 (consulting/medical/tax/legal)
|
|
101
|
+
* - 지정 = hidden input + 표시 라벨 + vertical 별 추가 필드
|
|
102
|
+
* (medical = 국외이전 동의 — ADR-0018)
|
|
103
|
+
*
|
|
104
|
+
* redirectPath prop:
|
|
105
|
+
* - 외부 사이트가 폼 제출 후 돌아갈 path (admin 이 allowlist 검증, ?ok=1 / ?err=*)
|
|
106
|
+
*
|
|
107
|
+
* 0 JS RSC. customer-facing className 전체 `.rt-cms-*` prefix, scoped via
|
|
108
|
+
* `[data-roottale-cms]` (cms-public.css). customer override 자유.
|
|
109
|
+
*/
|
|
110
|
+
|
|
111
|
+
type LeadFormVertical = "consulting" | "medical" | "tax" | "legal";
|
|
112
|
+
interface RootTaleLeadFormProps {
|
|
113
|
+
/** admin-tenant lead-intake endpoint. 예: `https://mysite.roottale.com/api/lead-intake` */
|
|
114
|
+
action: string;
|
|
115
|
+
/**
|
|
116
|
+
* vertical 고정. 미지정 시 select 노출.
|
|
117
|
+
* `medical` 일 때 국외이전 동의 체크박스 추가 (ADR-0018).
|
|
118
|
+
*/
|
|
119
|
+
vertical?: LeadFormVertical;
|
|
120
|
+
/**
|
|
121
|
+
* 폼 제출 후 admin이 돌려보낼 절대 URL.
|
|
122
|
+
* admin 측 `LEAD_INTAKE_ALLOWED_ORIGINS` allowlist 검증. fail = fallback.
|
|
123
|
+
* 미지정 시 admin env의 LEAD_INTAKE_REDIRECT_BASE 사용.
|
|
124
|
+
*/
|
|
125
|
+
redirectUrl?: string;
|
|
126
|
+
heading?: string;
|
|
127
|
+
description?: string;
|
|
128
|
+
submitLabel?: string;
|
|
129
|
+
/** 추가 클래스 (customer 디자인 hook). */
|
|
130
|
+
className?: string;
|
|
131
|
+
}
|
|
132
|
+
declare function RootTaleLeadForm(props: RootTaleLeadFormProps): ReactElement;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* 단일 block 을 ReactElement 로 변환. `block-to-html.ts` 와 동일 분기.
|
|
136
|
+
*/
|
|
137
|
+
declare function renderBlock(block: Block, key?: number): ReactElement;
|
|
138
|
+
/** Block tree 전체를 React element 배열로 직렬화. */
|
|
139
|
+
declare function renderBlocks(blocks: readonly Block[]): ReactElement[];
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* `@roottale/cms-renderer-next/server` — RootTale CMS public-render React Server Components.
|
|
143
|
+
*
|
|
144
|
+
* Drop into any RSC-capable framework (Next.js App Router, Astro server islands,
|
|
145
|
+
* React Router server). Single-line import, SSR-only, no `'use client'` boundary.
|
|
146
|
+
*
|
|
147
|
+
* ```tsx
|
|
148
|
+
* import { RootTaleBlogList } from "@roottale/cms-renderer-next/server";
|
|
149
|
+
*
|
|
150
|
+
* export default function BlogPage() {
|
|
151
|
+
* return <RootTaleBlogList apiKey={process.env.ROOTTALE_API_KEY!} />;
|
|
152
|
+
* }
|
|
153
|
+
* ```
|
|
154
|
+
*
|
|
155
|
+
* Customer site MUST keep `apiKey` server-side. Browser bundle ships zero
|
|
156
|
+
* RootTale credentials (ADR-0023 §5.1 #15).
|
|
157
|
+
*
|
|
158
|
+
* Design tokens auto-apply via the CSS import below. Customers can override
|
|
159
|
+
* any class with their own CSS or Tailwind utilities — scoped selectors use
|
|
160
|
+
* `:where()` to keep specificity at zero (ADR-0023 §5.1 #10).
|
|
161
|
+
*/
|
|
162
|
+
|
|
163
|
+
type RootTaleBlogListProps = {
|
|
164
|
+
apiKey: string;
|
|
165
|
+
baseUrl?: string;
|
|
166
|
+
limit?: number;
|
|
167
|
+
/** Filter by post type (`post` or `page`). Default = `post` only (blog list 의도). */
|
|
168
|
+
type?: CmsPostType;
|
|
169
|
+
/** Build a customer-side URL for a single post. Defaults to `/blog/${slug}`. */
|
|
170
|
+
postHref?: (post: CmsPostContent) => string;
|
|
171
|
+
/** Rendered when the tenant has no published posts yet. */
|
|
172
|
+
emptyMessage?: string;
|
|
173
|
+
};
|
|
174
|
+
declare function RootTaleBlogList(props: RootTaleBlogListProps): Promise<ReactElement>;
|
|
175
|
+
type RootTaleBlogPostProps = {
|
|
176
|
+
apiKey: string;
|
|
177
|
+
slugOrId: string;
|
|
178
|
+
baseUrl?: string;
|
|
179
|
+
/** Rendered when the slug is not found or not published. */
|
|
180
|
+
notFoundElement?: ReactElement;
|
|
181
|
+
/**
|
|
182
|
+
* When true, prepends an auto-derived `<RootTaleTableOfContents>` before
|
|
183
|
+
* the article body (H2/H3 headings only). Default: false — keep markup
|
|
184
|
+
* stable for customers who already control their own layout.
|
|
185
|
+
*/
|
|
186
|
+
showTableOfContents?: boolean;
|
|
187
|
+
/** Title shown above the TOC (only when `showTableOfContents`). */
|
|
188
|
+
tableOfContentsTitle?: string;
|
|
189
|
+
};
|
|
190
|
+
declare function RootTaleBlogPost(props: RootTaleBlogPostProps): Promise<ReactElement>;
|
|
191
|
+
|
|
192
|
+
export { type CtaButton, type CtaButtonType, type FloatingCtaPosition, type LeadFormVertical, RootTaleBlogList, type RootTaleBlogListProps, RootTaleBlogPost, type RootTaleBlogPostProps, RootTaleFloatingCta, type RootTaleFloatingCtaProps, RootTaleLeadForm, type RootTaleLeadFormProps, RootTalePostCard, type RootTalePostCardProps, RootTaleTableOfContents, type RootTaleTableOfContentsProps, type TocEntry, attachHeadingIds, extractToc, headingToId, renderBlock, renderBlocks };
|