@roottale/cms-renderer-next 0.44.0 → 0.45.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/CHANGELOG.md +21 -0
- package/dist/{chunk-75LHSTKC.js → chunk-45KYMMDY.js} +68 -17
- package/dist/chunk-45KYMMDY.js.map +1 -0
- package/dist/{chunk-4LQPZDXZ.js → chunk-6MFHA555.js} +24 -6
- package/dist/chunk-6MFHA555.js.map +1 -0
- package/dist/chunk-FZK3EXYZ.js +103 -0
- package/dist/chunk-FZK3EXYZ.js.map +1 -0
- package/dist/{chunk-6PDZSFVZ.js → chunk-GUV5WHD5.js} +33 -2
- package/dist/chunk-GUV5WHD5.js.map +1 -0
- package/dist/chunk-LEHHSI6G.js +64 -0
- package/dist/chunk-LEHHSI6G.js.map +1 -0
- package/dist/chunk-OMXEU4LS.js +414 -0
- package/dist/chunk-OMXEU4LS.js.map +1 -0
- package/dist/chunk-YLSQAT6B.js +59 -0
- package/dist/chunk-YLSQAT6B.js.map +1 -0
- package/dist/{chunk-WWS43XCT.js → chunk-Z3ZSCPG4.js} +82 -20
- package/dist/chunk-Z3ZSCPG4.js.map +1 -0
- package/dist/concerns-client.d.ts +1 -1
- package/dist/contact-map-client.d.ts +27 -0
- package/dist/contact-map-client.js +8 -0
- package/dist/contact-map-client.js.map +1 -0
- package/dist/expertise-client.d.ts +7 -1
- package/dist/expertise-client.js +2 -1
- package/dist/hero-carousel-client.d.ts +18 -2
- package/dist/hero-carousel-client.js +2 -1
- package/dist/routes.js +1 -1
- package/dist/server.js +8 -5
- package/dist/{site-config-BHcVF993.d.ts → site-config-kqurIH-k.d.ts} +38 -0
- package/dist/spaces-client.d.ts +1 -1
- package/dist/team-expanding-stage-client.d.ts +35 -0
- package/dist/team-expanding-stage-client.js +8 -0
- package/dist/team-expanding-stage-client.js.map +1 -0
- package/dist/templates.css +457 -5
- package/dist/templates.d.ts +26 -3
- package/dist/templates.js +13 -6
- package/dist/templates.js.map +1 -1
- package/dist/ui-react-motion-client.d.ts +1 -0
- package/dist/ui-react-motion-client.js +3 -1
- package/dist/validate.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-4LQPZDXZ.js.map +0 -1
- package/dist/chunk-6PDZSFVZ.js.map +0 -1
- package/dist/chunk-75LHSTKC.js.map +0 -1
- package/dist/chunk-F3G6RVIR.js +0 -220
- package/dist/chunk-F3G6RVIR.js.map +0 -1
- package/dist/chunk-WWS43XCT.js.map +0 -1
package/dist/templates.css
CHANGED
|
@@ -1916,6 +1916,12 @@
|
|
|
1916
1916
|
color: var(--rt-color-primary);
|
|
1917
1917
|
}
|
|
1918
1918
|
|
|
1919
|
+
[data-roottale-tpl="expertise"] :where(.rt-tpl-expertise-tab:focus-visible),
|
|
1920
|
+
[data-roottale-tpl="expertise"] :where(.rt-tpl-expertise-panel:focus-visible) {
|
|
1921
|
+
outline: 2px solid var(--rt-color-ring, var(--rt-color-primary));
|
|
1922
|
+
outline-offset: -2px;
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1919
1925
|
[data-roottale-tpl="expertise"] :where(.rt-tpl-expertise-tab-label),
|
|
1920
1926
|
[data-roottale-tpl="expertise"] :where(.rt-tpl-expertise-kicker) {
|
|
1921
1927
|
margin: 0;
|
|
@@ -2399,6 +2405,101 @@
|
|
|
2399
2405
|
}
|
|
2400
2406
|
}
|
|
2401
2407
|
|
|
2408
|
+
/* ---- curtain transition (ADR-0086 P2 D3, chambarun 이식) ----
|
|
2409
|
+
* 절대배치 스택 — 각 슬라이드가 clip-path 와이프로 스스로를 드러낸다(embla
|
|
2410
|
+
* 가로 스크롤 없음). 타이밍·이징·클립 경로는 원본
|
|
2411
|
+
* chambarun `assets/site.css` `@keyframes curtainReveal`/`.curtain-sheen` 값을
|
|
2412
|
+
* 그대로 유지, 색만 하드코딩 헥스 대신 --rt-* 토큰으로 치환했다. */
|
|
2413
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2414
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide) {
|
|
2415
|
+
position: absolute;
|
|
2416
|
+
inset: 0;
|
|
2417
|
+
flex: none;
|
|
2418
|
+
opacity: 0;
|
|
2419
|
+
z-index: 0;
|
|
2420
|
+
pointer-events: none;
|
|
2421
|
+
clip-path: inset(0 0 0 0);
|
|
2422
|
+
}
|
|
2423
|
+
|
|
2424
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2425
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide[data-leaving="true"]) {
|
|
2426
|
+
opacity: 1;
|
|
2427
|
+
z-index: 1;
|
|
2428
|
+
}
|
|
2429
|
+
|
|
2430
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2431
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide[data-active="true"]) {
|
|
2432
|
+
opacity: 1;
|
|
2433
|
+
z-index: 2;
|
|
2434
|
+
pointer-events: auto;
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2437
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
2438
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2439
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide[data-active="true"]) {
|
|
2440
|
+
animation: rt-hero-carousel-curtain-reveal 0.92s cubic-bezier(0.76, 0, 0.24, 1) both;
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
|
|
2444
|
+
@keyframes rt-hero-carousel-curtain-reveal {
|
|
2445
|
+
from {
|
|
2446
|
+
clip-path: inset(0 100% 0 0);
|
|
2447
|
+
}
|
|
2448
|
+
to {
|
|
2449
|
+
clip-path: inset(0 0 0 0);
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
/* 신 스윕 — 활성 슬라이드 위를 가로지르는 얇은 하이라이트 밴드. chambarun 은
|
|
2454
|
+
* teal/green 2색 그라디언트였으나 고객사 테마마다 브랜드색이 달라 토큰
|
|
2455
|
+
* 하나(primary-foreground)의 color-mix 농도 변화로 대체(대면적 채도 배색
|
|
2456
|
+
* 하드코딩 금지 관행과 동일 이유). */
|
|
2457
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2458
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-sheen) {
|
|
2459
|
+
position: absolute;
|
|
2460
|
+
inset-block: 0;
|
|
2461
|
+
inset-inline-start: 0;
|
|
2462
|
+
z-index: 1;
|
|
2463
|
+
inline-size: clamp(82px, 10cqi, 150px);
|
|
2464
|
+
pointer-events: none;
|
|
2465
|
+
opacity: 0;
|
|
2466
|
+
transform: translate3d(-160px, 0, 0);
|
|
2467
|
+
background: linear-gradient(
|
|
2468
|
+
90deg,
|
|
2469
|
+
transparent 0%,
|
|
2470
|
+
color-mix(in srgb, var(--rt-color-primary-foreground, #ffffff) 22%, transparent) 30%,
|
|
2471
|
+
color-mix(in srgb, var(--rt-color-primary-foreground, #ffffff) 58%, transparent) 48%,
|
|
2472
|
+
color-mix(in srgb, var(--rt-color-primary-foreground, #ffffff) 18%, transparent) 62%,
|
|
2473
|
+
transparent 100%
|
|
2474
|
+
);
|
|
2475
|
+
mix-blend-mode: screen;
|
|
2476
|
+
will-change: transform, opacity;
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
2480
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2481
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide[data-active="true"] .rt-tpl-hero-carousel-sheen) {
|
|
2482
|
+
animation: rt-hero-carousel-curtain-sheen 0.9s cubic-bezier(0.76, 0, 0.24, 1) both;
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
@keyframes rt-hero-carousel-curtain-sheen {
|
|
2487
|
+
0% {
|
|
2488
|
+
opacity: 0;
|
|
2489
|
+
transform: translate3d(-160px, 0, 0);
|
|
2490
|
+
}
|
|
2491
|
+
14% {
|
|
2492
|
+
opacity: 0.82;
|
|
2493
|
+
}
|
|
2494
|
+
76% {
|
|
2495
|
+
opacity: 0.68;
|
|
2496
|
+
}
|
|
2497
|
+
100% {
|
|
2498
|
+
opacity: 0;
|
|
2499
|
+
transform: translate3d(100cqi, 0, 0);
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2402
2503
|
/* 오버레이 eyebrow — 스크림 위에서는 테마 primary(잉크/민트)가 아니라 밝은
|
|
2403
2504
|
* 전경색이어야 읽힌다(미감 라운드 2 — 민트 eyebrow 소실 실측). */
|
|
2404
2505
|
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
@@ -2550,6 +2651,42 @@
|
|
|
2550
2651
|
letter-spacing: 0.06em;
|
|
2551
2652
|
}
|
|
2552
2653
|
|
|
2654
|
+
/* D4 — autoplay pause/재생 버튼: 도트·카운터와 같은 우측 클러스터에 절제된
|
|
2655
|
+
* 크기로 둔다(화살표와 동일 언어이나 더 작게 — 보조 컨트롤이라는 위계). */
|
|
2656
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2657
|
+
:where(.rt-tpl-hero-carousel-controls-right) {
|
|
2658
|
+
display: flex;
|
|
2659
|
+
align-items: center;
|
|
2660
|
+
gap: 0.75rem;
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2664
|
+
:where(.rt-tpl-hero-carousel-playpause) {
|
|
2665
|
+
display: inline-flex;
|
|
2666
|
+
align-items: center;
|
|
2667
|
+
justify-content: center;
|
|
2668
|
+
inline-size: 1.75rem;
|
|
2669
|
+
block-size: 1.75rem;
|
|
2670
|
+
border-radius: 999px;
|
|
2671
|
+
border: 1px solid color-mix(in srgb, var(--rt-color-primary-foreground, #ffffff) 28%, transparent);
|
|
2672
|
+
background: color-mix(in srgb, var(--rt-color-foreground, #06162f) 24%, transparent);
|
|
2673
|
+
color: var(--rt-color-primary-foreground, #ffffff);
|
|
2674
|
+
cursor: pointer;
|
|
2675
|
+
transition: background 180ms ease, border-color 180ms ease;
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2679
|
+
:where(.rt-tpl-hero-carousel-playpause:hover) {
|
|
2680
|
+
background: color-mix(in srgb, var(--rt-color-foreground, #06162f) 48%, transparent);
|
|
2681
|
+
border-color: color-mix(in srgb, var(--rt-color-primary-foreground, #ffffff) 45%, transparent);
|
|
2682
|
+
}
|
|
2683
|
+
|
|
2684
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
2685
|
+
:where(.rt-tpl-hero-carousel-playpause svg) {
|
|
2686
|
+
inline-size: 0.85rem;
|
|
2687
|
+
block-size: 0.85rem;
|
|
2688
|
+
}
|
|
2689
|
+
|
|
2553
2690
|
[data-roottale-tpl="hours"],
|
|
2554
2691
|
[data-roottale-tpl="pricing"],
|
|
2555
2692
|
[data-roottale-tpl="process"] {
|
|
@@ -3217,6 +3354,55 @@
|
|
|
3217
3354
|
gap: 0.5rem;
|
|
3218
3355
|
}
|
|
3219
3356
|
|
|
3357
|
+
/* 카피 스태거(chambarun `.hero-copy>*` 순차 등장, 타이밍 원본 유지) — curtain
|
|
3358
|
+
* 전환에서만, 슬라이드 전환마다 패널이 `key` 로 리마운트되어 매번 재생된다. */
|
|
3359
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
3360
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
3361
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide-panel > *) {
|
|
3362
|
+
animation:
|
|
3363
|
+
rt-hero-carousel-copy-in-opacity 0.68s cubic-bezier(0.45, 0, 0.2, 1) both,
|
|
3364
|
+
rt-hero-carousel-copy-in-transform 0.72s cubic-bezier(0.2, 0.75, 0.25, 1) both;
|
|
3365
|
+
}
|
|
3366
|
+
|
|
3367
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
3368
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide-panel > *:nth-child(1)) {
|
|
3369
|
+
animation-delay: 0.34s;
|
|
3370
|
+
}
|
|
3371
|
+
|
|
3372
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
3373
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide-panel > *:nth-child(2)) {
|
|
3374
|
+
animation-delay: 0.44s;
|
|
3375
|
+
}
|
|
3376
|
+
|
|
3377
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
3378
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide-panel > *:nth-child(3)) {
|
|
3379
|
+
animation-delay: 0.54s;
|
|
3380
|
+
}
|
|
3381
|
+
|
|
3382
|
+
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
3383
|
+
:where(.rt-tpl-hero-carousel[data-transition="curtain"] .rt-tpl-hero-carousel-slide-panel > *:nth-child(n + 4)) {
|
|
3384
|
+
animation-delay: 0.64s;
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
|
|
3388
|
+
@keyframes rt-hero-carousel-copy-in-opacity {
|
|
3389
|
+
from {
|
|
3390
|
+
opacity: 0;
|
|
3391
|
+
}
|
|
3392
|
+
to {
|
|
3393
|
+
opacity: 1;
|
|
3394
|
+
}
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
@keyframes rt-hero-carousel-copy-in-transform {
|
|
3398
|
+
from {
|
|
3399
|
+
transform: translateY(18px);
|
|
3400
|
+
}
|
|
3401
|
+
to {
|
|
3402
|
+
transform: none;
|
|
3403
|
+
}
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3220
3406
|
[data-roottale-tpl="hero"][data-variant="carousel"]
|
|
3221
3407
|
:where(.rt-tpl-hero-carousel-dots--tabs) {
|
|
3222
3408
|
gap: 0.4rem;
|
|
@@ -3446,6 +3632,56 @@
|
|
|
3446
3632
|
font-weight: 800;
|
|
3447
3633
|
}
|
|
3448
3634
|
|
|
3635
|
+
/*
|
|
3636
|
+
* 지도 클릭-투-로드 프리뷰(ADR-0086 P2 D3, `map.mapLoad === "click"`) —
|
|
3637
|
+
* `.rt-tpl-contact-map` 와 같은 박스(aspect-ratio/border/radius)를 그대로
|
|
3638
|
+
* 쓰고, 여기서는 배경 이미지·버튼·바깥 링크 배치만 얹는다.
|
|
3639
|
+
*/
|
|
3640
|
+
[data-roottale-tpl="contact"] :where(.rt-tpl-contact-map-click) {
|
|
3641
|
+
position: relative;
|
|
3642
|
+
display: grid;
|
|
3643
|
+
place-items: center;
|
|
3644
|
+
gap: 0.5rem;
|
|
3645
|
+
background: var(--muted);
|
|
3646
|
+
}
|
|
3647
|
+
|
|
3648
|
+
[data-roottale-tpl="contact"] :where(.rt-tpl-contact-map-click-bg) {
|
|
3649
|
+
position: absolute;
|
|
3650
|
+
inset: 0;
|
|
3651
|
+
inline-size: 100%;
|
|
3652
|
+
block-size: 100%;
|
|
3653
|
+
object-fit: cover;
|
|
3654
|
+
}
|
|
3655
|
+
|
|
3656
|
+
[data-roottale-tpl="contact"] :where(.rt-tpl-contact-map-click-btn) {
|
|
3657
|
+
position: relative;
|
|
3658
|
+
z-index: 1;
|
|
3659
|
+
display: inline-flex;
|
|
3660
|
+
align-items: center;
|
|
3661
|
+
gap: 0.4rem;
|
|
3662
|
+
padding: 0.55rem 1rem;
|
|
3663
|
+
border: 1px solid var(--rt-color-border);
|
|
3664
|
+
border-radius: var(--rt-radius-md);
|
|
3665
|
+
background: var(--card);
|
|
3666
|
+
color: var(--foreground);
|
|
3667
|
+
font-size: var(--font-size-sm);
|
|
3668
|
+
font-weight: var(--font-weight-semibold);
|
|
3669
|
+
cursor: pointer;
|
|
3670
|
+
}
|
|
3671
|
+
|
|
3672
|
+
[data-roottale-tpl="contact"] :where(.rt-tpl-contact-map-click-btn:hover) {
|
|
3673
|
+
background: color-mix(in srgb, var(--card) 85%, var(--rt-color-primary) 15%);
|
|
3674
|
+
}
|
|
3675
|
+
|
|
3676
|
+
[data-roottale-tpl="contact"] :where(.rt-tpl-contact-map-click-external) {
|
|
3677
|
+
position: relative;
|
|
3678
|
+
z-index: 1;
|
|
3679
|
+
font-size: 0.78rem;
|
|
3680
|
+
color: var(--accent-foreground);
|
|
3681
|
+
text-decoration: underline;
|
|
3682
|
+
text-underline-offset: var(--space-1);
|
|
3683
|
+
}
|
|
3684
|
+
|
|
3449
3685
|
[data-roottale-tpl="contact"] :where(.rt-tpl-contact-actions) {
|
|
3450
3686
|
display: flex;
|
|
3451
3687
|
flex-wrap: wrap;
|
|
@@ -3500,22 +3736,238 @@
|
|
|
3500
3736
|
text-decoration: none;
|
|
3501
3737
|
}
|
|
3502
3738
|
|
|
3739
|
+
/* ============ team: expanding-stage — hover/focus/tap 확장 (D3, chambarun
|
|
3740
|
+
* `.staff-stage`/`.staff-panel` 이식, mockup/assets/site.js·site.css 원본
|
|
3741
|
+
* 참조). 접힌 패널은 이름 칩만, 활성 패널은 확장되며 자격정보 패널이 드러난다.
|
|
3742
|
+
* 전환(transition) 선언은 전부 `prefers-reduced-motion: no-preference` 안에만
|
|
3743
|
+
* 둔다 — reduce 시 애니메이션 없이 최종 상태로 즉시 전환(상태 자체는 그대로
|
|
3744
|
+
* 바뀐다, ADR-0073 K3 C1 과 동일 관행). ============ */
|
|
3745
|
+
|
|
3503
3746
|
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-stage) {
|
|
3504
|
-
display:
|
|
3505
|
-
|
|
3506
|
-
gap: 0.
|
|
3747
|
+
display: flex;
|
|
3748
|
+
flex-direction: column;
|
|
3749
|
+
gap: 0.625rem;
|
|
3507
3750
|
padding: 0;
|
|
3508
3751
|
margin: 1.25rem 0 0;
|
|
3509
3752
|
list-style: none;
|
|
3510
3753
|
}
|
|
3511
3754
|
|
|
3755
|
+
@container (min-width: 46rem) {
|
|
3756
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-stage) {
|
|
3757
|
+
flex-direction: row;
|
|
3758
|
+
block-size: clamp(24rem, 46cqi, 38rem);
|
|
3759
|
+
}
|
|
3760
|
+
}
|
|
3761
|
+
|
|
3762
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-item) {
|
|
3763
|
+
position: relative;
|
|
3764
|
+
flex: none;
|
|
3765
|
+
block-size: 4.75rem;
|
|
3766
|
+
min-inline-size: 0;
|
|
3767
|
+
overflow: hidden;
|
|
3768
|
+
border-radius: var(--rt-radius-lg, 1.5rem);
|
|
3769
|
+
outline: none;
|
|
3770
|
+
cursor: pointer;
|
|
3771
|
+
background: var(--muted);
|
|
3772
|
+
box-shadow: 0 0.75rem 1.75rem -1rem color-mix(in srgb, var(--foreground) 45%, transparent);
|
|
3773
|
+
}
|
|
3774
|
+
|
|
3775
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-item[data-active="true"]) {
|
|
3776
|
+
block-size: 26rem;
|
|
3777
|
+
}
|
|
3778
|
+
|
|
3779
|
+
@container (min-width: 46rem) {
|
|
3780
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-item) {
|
|
3781
|
+
flex: 1 1 0;
|
|
3782
|
+
block-size: auto;
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-item[data-active="true"]) {
|
|
3786
|
+
flex-grow: 2.7;
|
|
3787
|
+
block-size: auto;
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
|
|
3791
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-item:focus-visible) {
|
|
3792
|
+
outline: 2px solid var(--primary);
|
|
3793
|
+
outline-offset: 3px;
|
|
3794
|
+
}
|
|
3795
|
+
|
|
3796
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-photo) {
|
|
3797
|
+
position: absolute;
|
|
3798
|
+
inset: 0;
|
|
3799
|
+
inline-size: 100%;
|
|
3800
|
+
block-size: 100%;
|
|
3801
|
+
object-fit: cover;
|
|
3802
|
+
object-position: center top;
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3805
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-photo--initials) {
|
|
3806
|
+
display: grid;
|
|
3807
|
+
place-items: center;
|
|
3808
|
+
color: var(--primary);
|
|
3809
|
+
font-family: var(--rt-font-display, var(--rt-font-body, system-ui, sans-serif));
|
|
3810
|
+
font-size: clamp(1.5rem, 8cqi, 2.5rem);
|
|
3811
|
+
font-weight: 800;
|
|
3812
|
+
}
|
|
3813
|
+
|
|
3814
|
+
[data-roottale-tpl="team"]
|
|
3815
|
+
:where(.rt-tpl-team-expanding-item[data-active="true"] .rt-tpl-team-expanding-photo) {
|
|
3816
|
+
filter: saturate(1.04) brightness(1.01);
|
|
3817
|
+
}
|
|
3818
|
+
|
|
3819
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-name) {
|
|
3820
|
+
position: absolute;
|
|
3821
|
+
inset-inline: 0;
|
|
3822
|
+
inset-block-end: 0;
|
|
3823
|
+
z-index: 2;
|
|
3824
|
+
display: flex;
|
|
3825
|
+
align-items: center;
|
|
3826
|
+
gap: 0.625rem;
|
|
3827
|
+
padding: 0.75rem 0.9rem;
|
|
3828
|
+
background: linear-gradient(
|
|
3829
|
+
0deg,
|
|
3830
|
+
color-mix(in srgb, var(--foreground) 78%, transparent),
|
|
3831
|
+
transparent
|
|
3832
|
+
);
|
|
3833
|
+
}
|
|
3834
|
+
|
|
3835
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-name b) {
|
|
3836
|
+
margin: 0;
|
|
3837
|
+
color: var(--background);
|
|
3838
|
+
font-family: var(--rt-font-display, var(--rt-font-body, system-ui, sans-serif));
|
|
3839
|
+
font-size: 0.95rem;
|
|
3840
|
+
font-weight: 800;
|
|
3841
|
+
}
|
|
3842
|
+
|
|
3843
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-name span) {
|
|
3844
|
+
color: color-mix(in srgb, var(--background) 78%, transparent);
|
|
3845
|
+
font-size: 0.75rem;
|
|
3846
|
+
font-weight: 700;
|
|
3847
|
+
white-space: nowrap;
|
|
3848
|
+
overflow: hidden;
|
|
3849
|
+
text-overflow: ellipsis;
|
|
3850
|
+
}
|
|
3851
|
+
|
|
3852
|
+
[data-roottale-tpl="team"]
|
|
3853
|
+
:where(.rt-tpl-team-expanding-item[data-active="true"] .rt-tpl-team-expanding-name) {
|
|
3854
|
+
opacity: 0;
|
|
3855
|
+
}
|
|
3856
|
+
|
|
3857
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-detail) {
|
|
3858
|
+
position: absolute;
|
|
3859
|
+
inset-inline: 0;
|
|
3860
|
+
inset-block-end: 0;
|
|
3861
|
+
z-index: 3;
|
|
3862
|
+
display: grid;
|
|
3863
|
+
gap: 0.5rem;
|
|
3864
|
+
padding: 1.75rem 1.25rem 1.25rem;
|
|
3865
|
+
background: linear-gradient(
|
|
3866
|
+
0deg,
|
|
3867
|
+
color-mix(in srgb, var(--foreground) 92%, transparent) 0%,
|
|
3868
|
+
color-mix(in srgb, var(--foreground) 55%, transparent) 55%,
|
|
3869
|
+
transparent 100%
|
|
3870
|
+
);
|
|
3871
|
+
opacity: 0;
|
|
3872
|
+
transform: translateY(1rem);
|
|
3873
|
+
pointer-events: none;
|
|
3874
|
+
}
|
|
3875
|
+
|
|
3876
|
+
[data-roottale-tpl="team"]
|
|
3877
|
+
:where(.rt-tpl-team-expanding-item[data-active="true"] .rt-tpl-team-expanding-detail) {
|
|
3878
|
+
opacity: 1;
|
|
3879
|
+
transform: none;
|
|
3880
|
+
pointer-events: auto;
|
|
3881
|
+
}
|
|
3882
|
+
|
|
3883
|
+
[data-roottale-tpl="team"]
|
|
3884
|
+
:where(.rt-tpl-team-expanding-detail .rt-tpl-team-expanding-role) {
|
|
3885
|
+
margin: 0;
|
|
3886
|
+
color: color-mix(in srgb, var(--background) 70%, transparent);
|
|
3887
|
+
font-size: 0.75rem;
|
|
3888
|
+
font-weight: 800;
|
|
3889
|
+
letter-spacing: 0.08em;
|
|
3890
|
+
text-transform: uppercase;
|
|
3891
|
+
}
|
|
3892
|
+
|
|
3893
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-detail .rt-tpl-team-name) {
|
|
3894
|
+
margin: 0;
|
|
3895
|
+
color: var(--background);
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
[data-roottale-tpl="team"]
|
|
3899
|
+
:where(.rt-tpl-team-expanding-detail .rt-tpl-team-specialties li) {
|
|
3900
|
+
color: var(--background);
|
|
3901
|
+
background: color-mix(in srgb, var(--background) 18%, transparent);
|
|
3902
|
+
}
|
|
3903
|
+
|
|
3904
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-detail .rt-tpl-team-credentials li),
|
|
3905
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-detail .rt-tpl-team-bio) {
|
|
3906
|
+
color: color-mix(in srgb, var(--background) 85%, transparent);
|
|
3907
|
+
}
|
|
3908
|
+
|
|
3909
|
+
[data-roottale-tpl="team"]
|
|
3910
|
+
:where(.rt-tpl-team-expanding-detail .rt-tpl-team-credentials li)::before {
|
|
3911
|
+
background: var(--primary);
|
|
3912
|
+
}
|
|
3913
|
+
|
|
3914
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-detail .rt-tpl-team-cta) {
|
|
3915
|
+
justify-self: start;
|
|
3916
|
+
margin-top: 0.25rem;
|
|
3917
|
+
padding: 0.55rem 0.9rem;
|
|
3918
|
+
border-radius: 999px;
|
|
3919
|
+
background: var(--primary);
|
|
3920
|
+
color: var(--primary-foreground, var(--background));
|
|
3921
|
+
}
|
|
3922
|
+
|
|
3923
|
+
[data-roottale-tpl="team"]
|
|
3924
|
+
:where(.rt-tpl-team-expanding-detail .rt-tpl-team-cta:focus-visible) {
|
|
3925
|
+
outline: 2px solid var(--background);
|
|
3926
|
+
outline-offset: 2px;
|
|
3927
|
+
}
|
|
3928
|
+
|
|
3512
3929
|
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-index) {
|
|
3513
|
-
|
|
3930
|
+
position: absolute;
|
|
3931
|
+
inset-block-start: 0.75rem;
|
|
3932
|
+
inset-inline-start: 0.9rem;
|
|
3933
|
+
z-index: 2;
|
|
3934
|
+
color: color-mix(in srgb, var(--background) 85%, transparent);
|
|
3514
3935
|
font-variant-numeric: tabular-nums;
|
|
3515
|
-
font-size: 0.
|
|
3936
|
+
font-size: 0.75rem;
|
|
3516
3937
|
font-weight: 800;
|
|
3517
3938
|
}
|
|
3518
3939
|
|
|
3940
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
3941
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-item) {
|
|
3942
|
+
transition:
|
|
3943
|
+
flex-grow 0.72s cubic-bezier(0.22, 0.9, 0.24, 1),
|
|
3944
|
+
block-size 0.6s cubic-bezier(0.22, 0.9, 0.24, 1),
|
|
3945
|
+
box-shadow 0.4s ease;
|
|
3946
|
+
}
|
|
3947
|
+
|
|
3948
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-photo) {
|
|
3949
|
+
transition: filter 0.55s ease;
|
|
3950
|
+
}
|
|
3951
|
+
|
|
3952
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-name) {
|
|
3953
|
+
transition: opacity 0.35s ease;
|
|
3954
|
+
}
|
|
3955
|
+
|
|
3956
|
+
[data-roottale-tpl="team"] :where(.rt-tpl-team-expanding-detail) {
|
|
3957
|
+
/* 접힐 때는 빠르게 사라져 패널 축소와 텍스트 잔상이 겹치지 않게. */
|
|
3958
|
+
transition:
|
|
3959
|
+
opacity 0.16s ease,
|
|
3960
|
+
transform 0.3s ease;
|
|
3961
|
+
}
|
|
3962
|
+
|
|
3963
|
+
[data-roottale-tpl="team"]
|
|
3964
|
+
:where(.rt-tpl-team-expanding-item[data-active="true"] .rt-tpl-team-expanding-detail) {
|
|
3965
|
+
transition:
|
|
3966
|
+
opacity 0.45s ease 0.18s,
|
|
3967
|
+
transform 0.5s cubic-bezier(0.16, 1, 0.3, 1) 0.18s;
|
|
3968
|
+
}
|
|
3969
|
+
}
|
|
3970
|
+
|
|
3519
3971
|
[data-roottale-tpl="footer"] {
|
|
3520
3972
|
background: color-mix(
|
|
3521
3973
|
in srgb,
|
package/dist/templates.d.ts
CHANGED
|
@@ -1,11 +1,34 @@
|
|
|
1
|
-
import { C as ConcernsSection, E as ExpertiseSection, S as SpacesSection, B as BeforeAfterSection, a as ContactSection, b as CtaBannerSection, F as FaqSection, c as FooterSection, H as HeroSection, d as HoursSection, P as PricingSection, e as ProcessSection, R as RichTextSection, f as ServicesSection, T as TeamSection, g as TestimonialsSection, h as TrustSection, i as SiteConfig, j as SiteConfigInput } from './site-config-
|
|
2
|
-
export { k as BUILTIN_SECTION_SCHEMAS, l as BUILTIN_SECTION_TYPES, m as BeforeAfterSectionSchema, n as BlogListSection, o as BlogListSectionSchema, p as ConcernsSectionSchema, q as ContactSectionSchema, r as CtaBannerSectionSchema, s as CustomSection, t as CustomSectionSchema, u as ExpertiseSectionSchema, v as FaqSectionSchema, w as FooterSectionSchema, x as HeroSectionSchema, y as HoursSectionSchema, L as LeadFormSection, z as LeadFormSectionSchema, N as NavItem, A as NavItemSchema, D as PricingSectionSchema, G as ProcessSectionSchema, I as RichTextSectionSchema, J as SECTION_VARIANTS, K as Section, M as SectionCta, O as SectionInput, Q as SectionSchema, U as ServicesSectionSchema, V as SiteConfigSchema, W as SpacesSectionSchema, X as TeamSectionSchema, Y as TestimonialsSectionSchema, Z as TrustSectionSchema, _ as defineSiteConfig, $ as parseSiteConfig } from './site-config-
|
|
1
|
+
import { C as ConcernsSection, E as ExpertiseSection, S as SpacesSection, B as BeforeAfterSection, a as ContactSection, b as CtaBannerSection, F as FaqSection, c as FooterSection, H as HeroSection, d as HoursSection, P as PricingSection, e as ProcessSection, R as RichTextSection, f as ServicesSection, T as TeamSection, g as TestimonialsSection, h as TrustSection, i as SiteConfig, j as SiteConfigInput } from './site-config-kqurIH-k.js';
|
|
2
|
+
export { k as BUILTIN_SECTION_SCHEMAS, l as BUILTIN_SECTION_TYPES, m as BeforeAfterSectionSchema, n as BlogListSection, o as BlogListSectionSchema, p as ConcernsSectionSchema, q as ContactSectionSchema, r as CtaBannerSectionSchema, s as CustomSection, t as CustomSectionSchema, u as ExpertiseSectionSchema, v as FaqSectionSchema, w as FooterSectionSchema, x as HeroSectionSchema, y as HoursSectionSchema, L as LeadFormSection, z as LeadFormSectionSchema, N as NavItem, A as NavItemSchema, D as PricingSectionSchema, G as ProcessSectionSchema, I as RichTextSectionSchema, J as SECTION_VARIANTS, K as Section, M as SectionCta, O as SectionInput, Q as SectionSchema, U as ServicesSectionSchema, V as SiteConfigSchema, W as SpacesSectionSchema, X as TeamSectionSchema, Y as TestimonialsSectionSchema, Z as TrustSectionSchema, _ as defineSiteConfig, $ as parseSiteConfig } from './site-config-kqurIH-k.js';
|
|
3
3
|
export { R as RootTaleCssVars, t as themeToCssVars } from './theme-css-vars-CD3jcEkp.js';
|
|
4
4
|
import { ReactElement, CSSProperties, ReactNode } from 'react';
|
|
5
5
|
import 'zod';
|
|
6
6
|
import '@roottale/cms-client/server';
|
|
7
7
|
import '@roottale/ui-react/theme';
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* `SiteConfig` 계약 버전 (ADR-0086 D2 — 팩 ↔ renderer 호환성 계약).
|
|
11
|
+
*
|
|
12
|
+
* `site-config.ts` 는 이미 SIZE_OK 상한 근처(canonical SectionSchema
|
|
13
|
+
* registry)라 버전 해석 로직은 별도 모듈에 두고 `site-config.ts` 에서
|
|
14
|
+
* re-export 한다.
|
|
15
|
+
*
|
|
16
|
+
* 팩 manifest(`packages/assembly/src/pack-manifest.ts`)의
|
|
17
|
+
* `siteConfigVersion` 필드가 이 버전과 비교 대상 — 팩이 요구하는 버전이
|
|
18
|
+
* renderer 가 실제로 해석하는 버전보다 높으면 조립 전 fail-fast 해야 한다.
|
|
19
|
+
*/
|
|
20
|
+
/** 현재 `SiteConfig` 스키마 버전. 계약 필드 추가 등 breaking 변경 시에만 올린다. */
|
|
21
|
+
declare const SITE_CONFIG_SCHEMA_VERSION = 1;
|
|
22
|
+
/**
|
|
23
|
+
* `config.schemaVersion` 해석 헬퍼 — 필드 미지정(기존 고객
|
|
24
|
+
* `site.config.ts`, `schemaVersion` 도입 이전 작성분)은 버전 1 로 해석한다
|
|
25
|
+
* (하위 호환, ADR-0086 D2). 현재 버전 상수가 아니라 리터럴 1 — 후일
|
|
26
|
+
* `SITE_CONFIG_SCHEMA_VERSION` 이 올라도 미지정 config 는 계속 1 이다.
|
|
27
|
+
*/
|
|
28
|
+
declare function resolveSiteConfigSchemaVersion(config: {
|
|
29
|
+
schemaVersion?: number;
|
|
30
|
+
}): number;
|
|
31
|
+
|
|
9
32
|
declare function TemplateExpertise(section: ExpertiseSection): ReactElement;
|
|
10
33
|
declare function TemplateSpaces(section: SpacesSection): ReactElement;
|
|
11
34
|
declare function TemplateConcerns(section: ConcernsSection): ReactElement;
|
|
@@ -106,4 +129,4 @@ interface SiteRendererProps {
|
|
|
106
129
|
*/
|
|
107
130
|
declare function SiteRenderer(props: SiteRendererProps): ReactElement;
|
|
108
131
|
|
|
109
|
-
export { BeforeAfterSection, ConcernsSection, ContactSection, CtaBannerSection, ExpertiseSection, FaqSection, FooterSection, HeroSection, HoursSection, PricingSection, ProcessSection, RichTextSection, type SectionComponent, ServicesSection, SiteConfig, SiteConfigInput, SiteRenderer, type SiteRendererProps, SpacesSection, TeamSection, TemplateBeforeAfter, TemplateConcerns, TemplateContact, TemplateCtaBanner, TemplateExpertise, TemplateFaq, TemplateFooter, TemplateHero, TemplateHours, TemplatePricing, TemplateProcess, TemplateRichText, TemplateServices, TemplateSpaces, TemplateTeam, TemplateTestimonials, TemplateTrust, TestimonialsSection, TrustSection, sectionThemeStyle };
|
|
132
|
+
export { BeforeAfterSection, ConcernsSection, ContactSection, CtaBannerSection, ExpertiseSection, FaqSection, FooterSection, HeroSection, HoursSection, PricingSection, ProcessSection, RichTextSection, SITE_CONFIG_SCHEMA_VERSION, type SectionComponent, ServicesSection, SiteConfig, SiteConfigInput, SiteRenderer, type SiteRendererProps, SpacesSection, TeamSection, TemplateBeforeAfter, TemplateConcerns, TemplateContact, TemplateCtaBanner, TemplateExpertise, TemplateFaq, TemplateFooter, TemplateHero, TemplateHours, TemplatePricing, TemplateProcess, TemplateRichText, TemplateServices, TemplateSpaces, TemplateTeam, TemplateTestimonials, TemplateTrust, TestimonialsSection, TrustSection, resolveSiteConfigSchemaVersion, sectionThemeStyle };
|
package/dist/templates.js
CHANGED
|
@@ -20,12 +20,14 @@ import {
|
|
|
20
20
|
TemplateTrust,
|
|
21
21
|
sectionThemeStyle,
|
|
22
22
|
themeToCssVars
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-45KYMMDY.js";
|
|
24
24
|
import "./chunk-U5AKACPN.js";
|
|
25
|
-
import "./chunk-
|
|
25
|
+
import "./chunk-LEHHSI6G.js";
|
|
26
|
+
import "./chunk-6MFHA555.js";
|
|
27
|
+
import "./chunk-FZK3EXYZ.js";
|
|
26
28
|
import "./chunk-K62RR4UQ.js";
|
|
27
29
|
import "./chunk-H46JUIHZ.js";
|
|
28
|
-
import "./chunk-
|
|
30
|
+
import "./chunk-Z3ZSCPG4.js";
|
|
29
31
|
import "./chunk-FUA5H6JE.js";
|
|
30
32
|
import {
|
|
31
33
|
BUILTIN_SECTION_SCHEMAS,
|
|
@@ -47,6 +49,7 @@ import {
|
|
|
47
49
|
ProcessSectionSchema,
|
|
48
50
|
RichTextSectionSchema,
|
|
49
51
|
SECTION_VARIANTS,
|
|
52
|
+
SITE_CONFIG_SCHEMA_VERSION,
|
|
50
53
|
SectionSchema,
|
|
51
54
|
ServicesSectionSchema,
|
|
52
55
|
SiteConfigSchema,
|
|
@@ -55,9 +58,11 @@ import {
|
|
|
55
58
|
TestimonialsSectionSchema,
|
|
56
59
|
TrustSectionSchema,
|
|
57
60
|
defineSiteConfig,
|
|
58
|
-
parseSiteConfig
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
parseSiteConfig,
|
|
62
|
+
resolveSiteConfigSchemaVersion
|
|
63
|
+
} from "./chunk-GUV5WHD5.js";
|
|
64
|
+
import "./chunk-OMXEU4LS.js";
|
|
65
|
+
import "./chunk-YLSQAT6B.js";
|
|
61
66
|
|
|
62
67
|
// src/templates/SiteRenderer.tsx
|
|
63
68
|
import {
|
|
@@ -243,6 +248,7 @@ export {
|
|
|
243
248
|
ProcessSectionSchema,
|
|
244
249
|
RichTextSectionSchema,
|
|
245
250
|
SECTION_VARIANTS,
|
|
251
|
+
SITE_CONFIG_SCHEMA_VERSION,
|
|
246
252
|
SectionSchema,
|
|
247
253
|
ServicesSectionSchema,
|
|
248
254
|
SiteConfigSchema,
|
|
@@ -270,6 +276,7 @@ export {
|
|
|
270
276
|
TrustSectionSchema,
|
|
271
277
|
defineSiteConfig,
|
|
272
278
|
parseSiteConfig,
|
|
279
|
+
resolveSiteConfigSchemaVersion,
|
|
273
280
|
sectionThemeStyle,
|
|
274
281
|
themeToCssVars
|
|
275
282
|
};
|
package/dist/templates.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/templates/SiteRenderer.tsx"],"sourcesContent":["/**\n * `SiteRenderer` — `SiteConfig.pages[path]` 섹션 배열을 registry 로 렌더.\n *\n * ADR-0040 P2 + P0.5 RFC §①:\n * - 빌트인 registry + 클라 주입 `customSections` 머지. **빌트인이 우선** —\n * 클라가 빌트인 type 을 가로채 계약이 갈라지는 것 방지 (고유 섹션은 고유\n * type 으로).\n * - **render-prop 금지**: 임의 JSX escape hatch 는 customSections registry 로만.\n * - **admin preview parity**: admin draft/preview 도 동일 `SiteRenderer` + 동일\n * 빌트인 registry 를 탄다. customSections 는 클라 repo 자산 — preview 에선\n * 미주입 → `unknownSection: \"placeholder\"` 로 skeleton 표시.\n * - cms-bound 섹션(blog-list/lead-form)은 `RootTaleBlogList`/`RootTaleLeadForm`\n * 위임 (단방향: templates → renderer 코어).\n */\nimport {\n Fragment,\n type CSSProperties,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport { RootTaleLeadForm } from \"../LeadForm.js\";\nimport { RootTaleBlogList } from \"../server.js\";\nimport {\n TemplateConcerns,\n TemplateExpertise,\n TemplateSpaces,\n} from \"./professional-sections.js\";\nimport {\n TemplateBeforeAfter,\n TemplateContact,\n TemplateCtaBanner,\n TemplateFaq,\n TemplateFooter,\n TemplateHero,\n TemplateHours,\n TemplatePricing,\n TemplateProcess,\n TemplateRichText,\n TemplateServices,\n TemplateTeam,\n TemplateTestimonials,\n TemplateTrust,\n sectionThemeStyle,\n} from \"./sections.js\";\nimport {\n type BeforeAfterSection,\n type BlogListSection,\n type ConcernsSection,\n type ContactSection,\n type CtaBannerSection,\n type ExpertiseSection,\n type FaqSection,\n type FooterSection,\n type HeroSection,\n type HoursSection,\n type LeadFormSection,\n type PricingSection,\n type ProcessSection,\n type RichTextSection,\n type Section,\n type ServicesSection,\n type SpacesSection,\n type SiteConfig,\n type SiteConfigInput,\n type TeamSection,\n type TestimonialsSection,\n type TrustSection,\n parseSiteConfig,\n} from \"./site-config.js\";\n\n/** customSections registry 컴포넌트 계약 (RFC §①). */\nexport type SectionComponent = (p: {\n id?: string;\n props: Record<string, unknown>;\n variant?: string;\n theme?: Record<string, string>;\n}) => ReactNode;\n\nexport interface SiteRendererProps {\n /** `defineSiteConfig()` 결과 또는 raw config (내부에서 검증). */\n config: SiteConfig | SiteConfigInput;\n /** 현재 페이지 경로 — `config.pages` 의 key (\"/\", \"/services\", …). */\n path: string;\n /** cms-bound 섹션(blog-list/lead-form 의 theme fetch) 위임용. 서버 전용. */\n apiKey: string;\n /** self-host 등 API base override (`ROOTTALE_API_BASE`). */\n baseUrl?: string;\n /** 클라 repo 고유 섹션 registry (escape hatch). 빌트인 type 은 가로챌 수 없음. */\n customSections?: Record<string, SectionComponent>;\n /**\n * registry 에 없는 type 처리. 기본 \"warn-dev\" = dev 에서 경고 박스, prod 에서\n * 생략. admin preview 는 \"placeholder\" (customSections 미주입 환경).\n */\n unknownSection?: \"warn-dev\" | \"placeholder\" | \"ignore\";\n}\n\nfunction isDev(): boolean {\n // dts 빌드는 node types 없이 돈다 — process 는 globalThis 경유로 안전 접근.\n const env =\n (globalThis as { process?: { env?: Record<string, string | undefined> } })\n .process?.env ?? {};\n return env.NODE_ENV !== \"production\";\n}\n\nfunction UnknownSection({\n type,\n mode,\n}: {\n type: string;\n mode: \"warn-dev\" | \"placeholder\" | \"ignore\";\n}): ReactElement | null {\n if (mode === \"ignore\") return null;\n if (mode === \"placeholder\") {\n return (\n <section\n data-roottale-tpl=\"placeholder\"\n className=\"rt-tpl-section rt-tpl-placeholder\"\n aria-hidden\n >\n <div className=\"rt-tpl-container\">\n <div className=\"rt-tpl-placeholder-box\">{type}</div>\n </div>\n </section>\n );\n }\n if (!isDev()) return null;\n const style: CSSProperties = {\n padding: \"1rem\",\n border: \"1px dashed #c00\",\n color: \"#c00\",\n };\n return (\n <div style={style}>\n 알 수 없는 섹션 type: <code>{type}</code> — SiteRenderer 의 customSections\n 에 등록하세요.\n </div>\n );\n}\n\nfunction renderBuiltin(\n section: Section,\n ctx: { apiKey: string; baseUrl?: string },\n): ReactNode | undefined {\n switch (section.type) {\n case \"hero\":\n return <TemplateHero {...(section as HeroSection)} />;\n case \"rich-text\":\n return <TemplateRichText {...(section as RichTextSection)} />;\n case \"services\":\n return <TemplateServices {...(section as ServicesSection)} />;\n case \"faq\":\n return <TemplateFaq {...(section as FaqSection)} />;\n case \"footer\":\n return <TemplateFooter {...(section as FooterSection)} />;\n case \"cta-banner\":\n return <TemplateCtaBanner {...(section as CtaBannerSection)} />;\n case \"blog-list\": {\n const s = section as BlogListSection;\n const base = s.props.blogBasePath ?? \"/blog\";\n return (\n <section\n data-roottale-tpl=\"blog-list\"\n data-roottale-cms=\"list\"\n id={s.id}\n className=\"rt-tpl-section rt-tpl-blog-list\"\n style={sectionThemeStyle(s.theme)}\n >\n <div className=\"rt-tpl-container\">\n {s.props.heading ? (\n <h2 className=\"rt-tpl-heading\">{s.props.heading}</h2>\n ) : null}\n <RootTaleBlogList\n apiKey={ctx.apiKey}\n baseUrl={ctx.baseUrl}\n limit={s.props.limit}\n emptyMessage={s.props.emptyMessage}\n postHref={(post) => `${base}/${post.slug}`}\n />\n </div>\n </section>\n );\n }\n case \"lead-form\": {\n const s = section as LeadFormSection;\n return (\n <section\n data-roottale-tpl=\"lead-form\"\n data-roottale-cms=\"lead-form\"\n id={s.id}\n className=\"rt-tpl-section rt-tpl-lead-form\"\n style={sectionThemeStyle(s.theme)}\n >\n <div className=\"rt-tpl-container\">\n <RootTaleLeadForm\n action={s.props.action}\n vertical={s.props.vertical}\n heading={s.props.heading}\n description={s.props.description}\n submitLabel={s.props.submitLabel}\n />\n </div>\n </section>\n );\n }\n case \"trust\":\n return <TemplateTrust {...(section as TrustSection)} />;\n case \"contact\":\n return <TemplateContact {...(section as ContactSection)} />;\n case \"hours\":\n return <TemplateHours {...(section as HoursSection)} />;\n case \"pricing\":\n return <TemplatePricing {...(section as PricingSection)} />;\n case \"process\":\n return <TemplateProcess {...(section as ProcessSection)} />;\n case \"before-after\":\n return <TemplateBeforeAfter {...(section as BeforeAfterSection)} />;\n case \"testimonials\":\n return <TemplateTestimonials {...(section as TestimonialsSection)} />;\n case \"expertise\":\n return <TemplateExpertise {...(section as ExpertiseSection)} />;\n case \"spaces\":\n return <TemplateSpaces {...(section as SpacesSection)} />;\n case \"concerns\":\n return <TemplateConcerns {...(section as ConcernsSection)} />;\n case \"team\":\n return <TemplateTeam {...(section as TeamSection)} />;\n default:\n return undefined;\n }\n}\n\n/**\n * 한 페이지의 섹션 배열을 순서대로 렌더.\n *\n * ```tsx\n * // app/services/page.tsx\n * import config from \"@/site.config\";\n * import { SiteRenderer } from \"@roottale/cms-renderer-next/templates\";\n *\n * export default function ServicesPage() {\n * return (\n * <SiteRenderer config={config} path=\"/services\"\n * apiKey={process.env.ROOTTALE_API_KEY!} />\n * );\n * }\n * ```\n */\nexport function SiteRenderer(props: SiteRendererProps): ReactElement {\n const {\n path,\n apiKey,\n baseUrl,\n customSections = {},\n unknownSection = \"warn-dev\",\n } = props;\n const config = parseSiteConfig(props.config);\n const sections = config.pages[path] ?? [];\n return (\n <>\n {sections.length === 0 ? (\n <UnknownSection\n type={`pages[\"${path}\"] (섹션 0개)`}\n mode={unknownSection}\n />\n ) : null}\n {sections.map((section, i) => {\n const key = section.id ?? `${section.type}-${i}`;\n const builtin = renderBuiltin(section, { apiKey, baseUrl });\n if (builtin !== undefined) {\n return <Fragment key={key}>{builtin}</Fragment>;\n }\n const Custom = customSections[section.type];\n if (Custom) {\n return (\n <Fragment key={key}>\n {Custom({\n id: section.id,\n props: section.props as Record<string, unknown>,\n variant: section.variant,\n theme: section.theme,\n })}\n </Fragment>\n );\n }\n return (\n <UnknownSection key={key} type={section.type} mode={unknownSection} />\n );\n })}\n </>\n );\n}\n"],"mappings":"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","names":["Fragment"]}
|
|
1
|
+
{"version":3,"sources":["../src/templates/SiteRenderer.tsx"],"sourcesContent":["/**\n * `SiteRenderer` — `SiteConfig.pages[path]` 섹션 배열을 registry 로 렌더.\n *\n * ADR-0040 P2 + P0.5 RFC §①:\n * - 빌트인 registry + 클라 주입 `customSections` 머지. **빌트인이 우선** —\n * 클라가 빌트인 type 을 가로채 계약이 갈라지는 것 방지 (고유 섹션은 고유\n * type 으로).\n * - **render-prop 금지**: 임의 JSX escape hatch 는 customSections registry 로만.\n * - **admin preview parity**: admin draft/preview 도 동일 `SiteRenderer` + 동일\n * 빌트인 registry 를 탄다. customSections 는 클라 repo 자산 — preview 에선\n * 미주입 → `unknownSection: \"placeholder\"` 로 skeleton 표시.\n * - cms-bound 섹션(blog-list/lead-form)은 `RootTaleBlogList`/`RootTaleLeadForm`\n * 위임 (단방향: templates → renderer 코어).\n */\nimport {\n Fragment,\n type CSSProperties,\n type ReactElement,\n type ReactNode,\n} from \"react\";\n\nimport { RootTaleLeadForm } from \"../LeadForm.js\";\nimport { RootTaleBlogList } from \"../server.js\";\nimport {\n TemplateConcerns,\n TemplateExpertise,\n TemplateSpaces,\n} from \"./professional-sections.js\";\nimport {\n TemplateBeforeAfter,\n TemplateContact,\n TemplateCtaBanner,\n TemplateFaq,\n TemplateFooter,\n TemplateHero,\n TemplateHours,\n TemplatePricing,\n TemplateProcess,\n TemplateRichText,\n TemplateServices,\n TemplateTeam,\n TemplateTestimonials,\n TemplateTrust,\n sectionThemeStyle,\n} from \"./sections.js\";\nimport {\n type BeforeAfterSection,\n type BlogListSection,\n type ConcernsSection,\n type ContactSection,\n type CtaBannerSection,\n type ExpertiseSection,\n type FaqSection,\n type FooterSection,\n type HeroSection,\n type HoursSection,\n type LeadFormSection,\n type PricingSection,\n type ProcessSection,\n type RichTextSection,\n type Section,\n type ServicesSection,\n type SpacesSection,\n type SiteConfig,\n type SiteConfigInput,\n type TeamSection,\n type TestimonialsSection,\n type TrustSection,\n parseSiteConfig,\n} from \"./site-config.js\";\n\n/** customSections registry 컴포넌트 계약 (RFC §①). */\nexport type SectionComponent = (p: {\n id?: string;\n props: Record<string, unknown>;\n variant?: string;\n theme?: Record<string, string>;\n}) => ReactNode;\n\nexport interface SiteRendererProps {\n /** `defineSiteConfig()` 결과 또는 raw config (내부에서 검증). */\n config: SiteConfig | SiteConfigInput;\n /** 현재 페이지 경로 — `config.pages` 의 key (\"/\", \"/services\", …). */\n path: string;\n /** cms-bound 섹션(blog-list/lead-form 의 theme fetch) 위임용. 서버 전용. */\n apiKey: string;\n /** self-host 등 API base override (`ROOTTALE_API_BASE`). */\n baseUrl?: string;\n /** 클라 repo 고유 섹션 registry (escape hatch). 빌트인 type 은 가로챌 수 없음. */\n customSections?: Record<string, SectionComponent>;\n /**\n * registry 에 없는 type 처리. 기본 \"warn-dev\" = dev 에서 경고 박스, prod 에서\n * 생략. admin preview 는 \"placeholder\" (customSections 미주입 환경).\n */\n unknownSection?: \"warn-dev\" | \"placeholder\" | \"ignore\";\n}\n\nfunction isDev(): boolean {\n // dts 빌드는 node types 없이 돈다 — process 는 globalThis 경유로 안전 접근.\n const env =\n (globalThis as { process?: { env?: Record<string, string | undefined> } })\n .process?.env ?? {};\n return env.NODE_ENV !== \"production\";\n}\n\nfunction UnknownSection({\n type,\n mode,\n}: {\n type: string;\n mode: \"warn-dev\" | \"placeholder\" | \"ignore\";\n}): ReactElement | null {\n if (mode === \"ignore\") return null;\n if (mode === \"placeholder\") {\n return (\n <section\n data-roottale-tpl=\"placeholder\"\n className=\"rt-tpl-section rt-tpl-placeholder\"\n aria-hidden\n >\n <div className=\"rt-tpl-container\">\n <div className=\"rt-tpl-placeholder-box\">{type}</div>\n </div>\n </section>\n );\n }\n if (!isDev()) return null;\n const style: CSSProperties = {\n padding: \"1rem\",\n border: \"1px dashed #c00\",\n color: \"#c00\",\n };\n return (\n <div style={style}>\n 알 수 없는 섹션 type: <code>{type}</code> — SiteRenderer 의 customSections\n 에 등록하세요.\n </div>\n );\n}\n\nfunction renderBuiltin(\n section: Section,\n ctx: { apiKey: string; baseUrl?: string },\n): ReactNode | undefined {\n switch (section.type) {\n case \"hero\":\n return <TemplateHero {...(section as HeroSection)} />;\n case \"rich-text\":\n return <TemplateRichText {...(section as RichTextSection)} />;\n case \"services\":\n return <TemplateServices {...(section as ServicesSection)} />;\n case \"faq\":\n return <TemplateFaq {...(section as FaqSection)} />;\n case \"footer\":\n return <TemplateFooter {...(section as FooterSection)} />;\n case \"cta-banner\":\n return <TemplateCtaBanner {...(section as CtaBannerSection)} />;\n case \"blog-list\": {\n const s = section as BlogListSection;\n const base = s.props.blogBasePath ?? \"/blog\";\n return (\n <section\n data-roottale-tpl=\"blog-list\"\n data-roottale-cms=\"list\"\n id={s.id}\n className=\"rt-tpl-section rt-tpl-blog-list\"\n style={sectionThemeStyle(s.theme)}\n >\n <div className=\"rt-tpl-container\">\n {s.props.heading ? (\n <h2 className=\"rt-tpl-heading\">{s.props.heading}</h2>\n ) : null}\n <RootTaleBlogList\n apiKey={ctx.apiKey}\n baseUrl={ctx.baseUrl}\n limit={s.props.limit}\n emptyMessage={s.props.emptyMessage}\n postHref={(post) => `${base}/${post.slug}`}\n />\n </div>\n </section>\n );\n }\n case \"lead-form\": {\n const s = section as LeadFormSection;\n return (\n <section\n data-roottale-tpl=\"lead-form\"\n data-roottale-cms=\"lead-form\"\n id={s.id}\n className=\"rt-tpl-section rt-tpl-lead-form\"\n style={sectionThemeStyle(s.theme)}\n >\n <div className=\"rt-tpl-container\">\n <RootTaleLeadForm\n action={s.props.action}\n vertical={s.props.vertical}\n heading={s.props.heading}\n description={s.props.description}\n submitLabel={s.props.submitLabel}\n />\n </div>\n </section>\n );\n }\n case \"trust\":\n return <TemplateTrust {...(section as TrustSection)} />;\n case \"contact\":\n return <TemplateContact {...(section as ContactSection)} />;\n case \"hours\":\n return <TemplateHours {...(section as HoursSection)} />;\n case \"pricing\":\n return <TemplatePricing {...(section as PricingSection)} />;\n case \"process\":\n return <TemplateProcess {...(section as ProcessSection)} />;\n case \"before-after\":\n return <TemplateBeforeAfter {...(section as BeforeAfterSection)} />;\n case \"testimonials\":\n return <TemplateTestimonials {...(section as TestimonialsSection)} />;\n case \"expertise\":\n return <TemplateExpertise {...(section as ExpertiseSection)} />;\n case \"spaces\":\n return <TemplateSpaces {...(section as SpacesSection)} />;\n case \"concerns\":\n return <TemplateConcerns {...(section as ConcernsSection)} />;\n case \"team\":\n return <TemplateTeam {...(section as TeamSection)} />;\n default:\n return undefined;\n }\n}\n\n/**\n * 한 페이지의 섹션 배열을 순서대로 렌더.\n *\n * ```tsx\n * // app/services/page.tsx\n * import config from \"@/site.config\";\n * import { SiteRenderer } from \"@roottale/cms-renderer-next/templates\";\n *\n * export default function ServicesPage() {\n * return (\n * <SiteRenderer config={config} path=\"/services\"\n * apiKey={process.env.ROOTTALE_API_KEY!} />\n * );\n * }\n * ```\n */\nexport function SiteRenderer(props: SiteRendererProps): ReactElement {\n const {\n path,\n apiKey,\n baseUrl,\n customSections = {},\n unknownSection = \"warn-dev\",\n } = props;\n const config = parseSiteConfig(props.config);\n const sections = config.pages[path] ?? [];\n return (\n <>\n {sections.length === 0 ? (\n <UnknownSection\n type={`pages[\"${path}\"] (섹션 0개)`}\n mode={unknownSection}\n />\n ) : null}\n {sections.map((section, i) => {\n const key = section.id ?? `${section.type}-${i}`;\n const builtin = renderBuiltin(section, { apiKey, baseUrl });\n if (builtin !== undefined) {\n return <Fragment key={key}>{builtin}</Fragment>;\n }\n const Custom = customSections[section.type];\n if (Custom) {\n return (\n <Fragment key={key}>\n {Custom({\n id: section.id,\n props: section.props as Record<string, unknown>,\n variant: section.variant,\n theme: section.theme,\n })}\n </Fragment>\n );\n }\n return (\n <UnknownSection key={key} type={section.type} mode={unknownSection} />\n );\n })}\n </>\n );\n}\n"],"mappings":"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","names":["Fragment"]}
|