@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 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
@@ -0,0 +1,2 @@
1
+
2
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -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 };