@naeil/ui 0.9.0 → 0.11.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 +14 -0
- package/README.md +5 -5
- package/dist/{chunk-XRO3NJAB.js → chunk-KWEWR46R.js} +40 -154
- package/dist/{chunk-JDHGKM25.js → chunk-U3IZCFM4.js} +267 -2
- package/dist/components/index.js +12 -3
- package/dist/components/naeil-footer.d.ts +3 -3
- package/dist/components/naeil-footer.js +14 -11
- package/dist/components/naeil-header.d.ts +7 -9
- package/dist/components/naeil-header.js +2 -2
- package/dist/lib/ui-release.d.ts +1 -1
- package/dist/lib/ui-release.js +1 -1
- package/dist/naeil-locale/checker.d.ts +16 -0
- package/dist/naeil-locale/checker.js +91 -0
- package/dist/naeil-locale/chrome.d.ts +150 -0
- package/dist/naeil-locale/chrome.js +2385 -0
- package/dist/naeil-locale/chunk-4U64K4J3.js +56 -0
- package/dist/naeil-locale/chunk-N3ETBM74.js +24 -0
- package/dist/naeil-locale/chunk-U65OQHZY.js +167 -0
- package/dist/naeil-locale/chunk-YQ5OJWBF.js +53 -0
- package/dist/naeil-locale/client.d.ts +70 -0
- package/dist/naeil-locale/client.js +388 -0
- package/dist/naeil-locale/en-ZC66VDHP.js +86 -0
- package/dist/naeil-locale/index.d.ts +40 -0
- package/dist/naeil-locale/index.js +111 -0
- package/dist/naeil-locale/ja-DKIEQUG7.js +86 -0
- package/dist/naeil-locale/ko-CY6663RZ.js +86 -0
- package/dist/naeil-locale/messages-BuQvB-u2.d.ts +167 -0
- package/dist/naeil-locale/messages.d.ts +1 -0
- package/dist/naeil-locale/messages.js +14 -0
- package/dist/naeil-locale/server.d.ts +75 -0
- package/dist/naeil-locale/server.js +172 -0
- package/dist/source/components/naeil-footer-core.d.ts +16 -0
- package/dist/source/components/naeil-footer-core.js +93 -0
- package/dist/source/components/naeil-footer.d.ts +6 -11
- package/dist/source/components/naeil-footer.js +4 -75
- package/dist/source/components/naeil-header-account-core.d.ts +26 -0
- package/dist/source/components/naeil-header-account-core.js +98 -0
- package/dist/source/components/naeil-header-account.d.ts +6 -22
- package/dist/source/components/naeil-header-account.js +5 -81
- package/dist/source/components/naeil-header-content.d.ts +102 -109
- package/dist/source/components/naeil-header-content.js +6 -142
- package/dist/source/components/naeil-header-core.d.ts +59 -0
- package/dist/source/components/naeil-header-core.js +231 -0
- package/dist/source/components/naeil-header-data.d.ts +11 -0
- package/dist/source/components/naeil-header-data.js +14 -0
- package/dist/source/components/naeil-header.d.ts +10 -51
- package/dist/source/components/naeil-header.js +9 -200
- package/dist/source/components/naeil-messages-context.d.ts +94 -0
- package/dist/source/components/naeil-messages-context.js +16 -0
- package/dist/source/components/naeil-standalone-messages.d.ts +11 -0
- package/dist/source/components/naeil-standalone-messages.js +13 -0
- package/dist/source/i18n/routing.d.ts +22 -20
- package/dist/source/lib/ui-release.d.ts +1 -1
- package/dist/source/lib/ui-release.js +1 -1
- package/dist/source/naeil-locale/messages/en.json +78 -0
- package/dist/source/naeil-locale/messages/ja.json +78 -0
- package/dist/source/naeil-locale/messages/ko.json +78 -0
- package/docs/components/naeil-locale.md +52 -0
- package/docs/package-release.md +31 -6
- package/package.json +35 -7
- /package/dist/{naeil-header-content-BvISJ4RV.d.ts → naeil-header-data-BvISJ4RV.d.ts} +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { NaeilHeaderLocale } from './naeil-header-data.js';
|
|
4
|
+
|
|
5
|
+
/** Only the standalone compatibility entry includes all three small dictionaries. */
|
|
6
|
+
declare function NaeilStandaloneMessages({ locale, children }: {
|
|
7
|
+
locale: NaeilHeaderLocale;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}): react_jsx_runtime.JSX.Element;
|
|
10
|
+
|
|
11
|
+
export { NaeilStandaloneMessages };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import en from "../naeil-locale/messages/en.json";
|
|
4
|
+
import ko from "../naeil-locale/messages/ko.json";
|
|
5
|
+
import ja from "../naeil-locale/messages/ja.json";
|
|
6
|
+
import { NaeilMessagesProvider } from "./naeil-messages-context.js";
|
|
7
|
+
const messages = { en: en.naeil, ko: ko.naeil, ja: ja.naeil };
|
|
8
|
+
function NaeilStandaloneMessages({ locale, children }) {
|
|
9
|
+
return /* @__PURE__ */ jsx(NaeilMessagesProvider, { locale, messages: messages[locale], children });
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
NaeilStandaloneMessages
|
|
13
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as next_dist_shared_lib_app_router_context_shared_runtime from 'next/dist/shared/lib/app-router-context.shared-runtime';
|
|
2
|
-
import * as
|
|
2
|
+
import * as next_dist_client_components_redirect_error from 'next/dist/client/components/redirect-error';
|
|
3
3
|
import * as next_intl_navigation from 'next-intl/navigation';
|
|
4
4
|
import * as url from 'url';
|
|
5
5
|
import * as react from 'react';
|
|
@@ -31,8 +31,6 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
|
|
|
31
31
|
style?: react.CSSProperties | undefined;
|
|
32
32
|
title?: string | undefined | undefined;
|
|
33
33
|
locale?: string | undefined;
|
|
34
|
-
onError?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
35
|
-
children?: react.ReactNode;
|
|
36
34
|
ref?: react.Ref<HTMLAnchorElement> | undefined;
|
|
37
35
|
prefix?: string | undefined | undefined;
|
|
38
36
|
key?: react.Key | null | undefined;
|
|
@@ -42,12 +40,10 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
|
|
|
42
40
|
passHref?: boolean | undefined;
|
|
43
41
|
prefetch?: boolean | "auto" | null | undefined;
|
|
44
42
|
legacyBehavior?: boolean | undefined;
|
|
45
|
-
onMouseEnter?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
46
|
-
onTouchStart?: React.TouchEventHandler<HTMLAnchorElement> | undefined;
|
|
47
|
-
onClick?: React.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
48
43
|
onNavigate?: ((event: {
|
|
49
44
|
preventDefault: () => void;
|
|
50
45
|
}) => void) | undefined;
|
|
46
|
+
transitionTypes?: string[] | undefined;
|
|
51
47
|
download?: any;
|
|
52
48
|
hrefLang?: string | undefined | undefined;
|
|
53
49
|
media?: string | undefined | undefined;
|
|
@@ -104,7 +100,6 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
|
|
|
104
100
|
is?: string | undefined | undefined;
|
|
105
101
|
exportparts?: string | undefined | undefined;
|
|
106
102
|
part?: string | undefined | undefined;
|
|
107
|
-
tw?: string | undefined;
|
|
108
103
|
"aria-activedescendant"?: string | undefined | undefined;
|
|
109
104
|
"aria-atomic"?: (boolean | "true" | "false") | undefined;
|
|
110
105
|
"aria-autocomplete"?: "none" | "inline" | "list" | "both" | undefined | undefined;
|
|
@@ -158,6 +153,8 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
|
|
|
158
153
|
"aria-valuemin"?: number | undefined | undefined;
|
|
159
154
|
"aria-valuenow"?: number | undefined | undefined;
|
|
160
155
|
"aria-valuetext"?: string | undefined | undefined;
|
|
156
|
+
href: string | url.UrlObject;
|
|
157
|
+
children?: react.ReactNode;
|
|
161
158
|
dangerouslySetInnerHTML?: {
|
|
162
159
|
__html: string | TrustedHTML;
|
|
163
160
|
} | undefined | undefined;
|
|
@@ -177,20 +174,21 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
|
|
|
177
174
|
onFocusCapture?: react.FocusEventHandler<HTMLAnchorElement> | undefined;
|
|
178
175
|
onBlur?: react.FocusEventHandler<HTMLAnchorElement> | undefined;
|
|
179
176
|
onBlurCapture?: react.FocusEventHandler<HTMLAnchorElement> | undefined;
|
|
180
|
-
onChange?: react.
|
|
181
|
-
onChangeCapture?: react.
|
|
177
|
+
onChange?: react.ChangeEventHandler<HTMLAnchorElement, Element> | undefined;
|
|
178
|
+
onChangeCapture?: react.ChangeEventHandler<HTMLAnchorElement, Element> | undefined;
|
|
182
179
|
onBeforeInput?: react.InputEventHandler<HTMLAnchorElement> | undefined;
|
|
183
|
-
onBeforeInputCapture?: react.
|
|
184
|
-
onInput?: react.
|
|
185
|
-
onInputCapture?: react.
|
|
186
|
-
onReset?: react.
|
|
187
|
-
onResetCapture?: react.
|
|
188
|
-
onSubmit?: react.
|
|
189
|
-
onSubmitCapture?: react.
|
|
190
|
-
onInvalid?: react.
|
|
191
|
-
onInvalidCapture?: react.
|
|
180
|
+
onBeforeInputCapture?: react.InputEventHandler<HTMLAnchorElement> | undefined;
|
|
181
|
+
onInput?: react.InputEventHandler<HTMLAnchorElement> | undefined;
|
|
182
|
+
onInputCapture?: react.InputEventHandler<HTMLAnchorElement> | undefined;
|
|
183
|
+
onReset?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
184
|
+
onResetCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
185
|
+
onSubmit?: react.SubmitEventHandler<HTMLAnchorElement> | undefined;
|
|
186
|
+
onSubmitCapture?: react.SubmitEventHandler<HTMLAnchorElement> | undefined;
|
|
187
|
+
onInvalid?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
188
|
+
onInvalidCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
192
189
|
onLoad?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
193
190
|
onLoadCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
191
|
+
onError?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
194
192
|
onErrorCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
195
193
|
onKeyDown?: react.KeyboardEventHandler<HTMLAnchorElement> | undefined;
|
|
196
194
|
onKeyDownCapture?: react.KeyboardEventHandler<HTMLAnchorElement> | undefined;
|
|
@@ -244,6 +242,7 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
|
|
|
244
242
|
onWaitingCapture?: react.ReactEventHandler<HTMLAnchorElement> | undefined;
|
|
245
243
|
onAuxClick?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
246
244
|
onAuxClickCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
245
|
+
onClick?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
247
246
|
onClickCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
248
247
|
onContextMenu?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
249
248
|
onContextMenuCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
@@ -267,6 +266,7 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
|
|
|
267
266
|
onDropCapture?: react.DragEventHandler<HTMLAnchorElement> | undefined;
|
|
268
267
|
onMouseDown?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
269
268
|
onMouseDownCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
269
|
+
onMouseEnter?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
270
270
|
onMouseLeave?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
271
271
|
onMouseMove?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
272
272
|
onMouseMoveCapture?: react.MouseEventHandler<HTMLAnchorElement> | undefined;
|
|
@@ -284,6 +284,7 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
|
|
|
284
284
|
onTouchEndCapture?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
|
|
285
285
|
onTouchMove?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
|
|
286
286
|
onTouchMoveCapture?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
|
|
287
|
+
onTouchStart?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
|
|
287
288
|
onTouchStartCapture?: react.TouchEventHandler<HTMLAnchorElement> | undefined;
|
|
288
289
|
onPointerDown?: react.PointerEventHandler<HTMLAnchorElement> | undefined;
|
|
289
290
|
onPointerDownCapture?: react.PointerEventHandler<HTMLAnchorElement> | undefined;
|
|
@@ -325,7 +326,6 @@ declare const Link: react.ForwardRefExoticComponent<Omit<{
|
|
|
325
326
|
onTransitionRunCapture?: react.TransitionEventHandler<HTMLAnchorElement> | undefined;
|
|
326
327
|
onTransitionStart?: react.TransitionEventHandler<HTMLAnchorElement> | undefined;
|
|
327
328
|
onTransitionStartCapture?: react.TransitionEventHandler<HTMLAnchorElement> | undefined;
|
|
328
|
-
href: string | url.UrlObject;
|
|
329
329
|
}, "ref"> & react.RefAttributes<HTMLAnchorElement>>;
|
|
330
330
|
declare const redirect: (args: {
|
|
331
331
|
href: string | {
|
|
@@ -334,7 +334,7 @@ declare const redirect: (args: {
|
|
|
334
334
|
};
|
|
335
335
|
locale: string;
|
|
336
336
|
forcePrefix?: boolean;
|
|
337
|
-
}, type?:
|
|
337
|
+
}, type?: next_dist_client_components_redirect_error.RedirectType | undefined) => never;
|
|
338
338
|
declare const usePathname: () => string;
|
|
339
339
|
declare const useRouter: () => {
|
|
340
340
|
push: (href: string | {
|
|
@@ -358,6 +358,8 @@ declare const useRouter: () => {
|
|
|
358
358
|
back(): void;
|
|
359
359
|
forward(): void;
|
|
360
360
|
refresh(): void;
|
|
361
|
+
experimental_gesturePush?(href: string, options?: next_dist_shared_lib_app_router_context_shared_runtime.NavigateOptions): void;
|
|
362
|
+
bfcacheId: string;
|
|
361
363
|
};
|
|
362
364
|
declare const getPathname: (args: {
|
|
363
365
|
href: string | {
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"naeil": {
|
|
3
|
+
"header": {
|
|
4
|
+
"nav": {
|
|
5
|
+
"home": "Home",
|
|
6
|
+
"projects": "Projects",
|
|
7
|
+
"blog": "Blog",
|
|
8
|
+
"navigation": "Main navigation",
|
|
9
|
+
"menu": "Menu",
|
|
10
|
+
"closeMenu": "Close menu"
|
|
11
|
+
},
|
|
12
|
+
"theme": {
|
|
13
|
+
"switchToLight": "Switch to light theme",
|
|
14
|
+
"switchToDark": "Switch to dark theme"
|
|
15
|
+
},
|
|
16
|
+
"locale": {
|
|
17
|
+
"switchLabel": "Language"
|
|
18
|
+
},
|
|
19
|
+
"projects": {
|
|
20
|
+
"cc": {
|
|
21
|
+
"name": "Content Collector",
|
|
22
|
+
"description": "Automated content collection from RSS, YouTube, Reddit + AI summarization"
|
|
23
|
+
},
|
|
24
|
+
"pkm": {
|
|
25
|
+
"name": "PKM",
|
|
26
|
+
"description": "Personal knowledge management — document parsing, embeddings, semantic search"
|
|
27
|
+
},
|
|
28
|
+
"naeilUi": {
|
|
29
|
+
"name": "naeil-ui",
|
|
30
|
+
"description": "Minimal design system — OKLCH tokens, Tailwind v4, shadcn"
|
|
31
|
+
},
|
|
32
|
+
"sa": {
|
|
33
|
+
"name": "Sustainability Analyzer",
|
|
34
|
+
"description": "AI-powered ESG report analysis — PDF parsing, qualitative assessment, comparison tables"
|
|
35
|
+
},
|
|
36
|
+
"babyAgent": {
|
|
37
|
+
"name": "Baby Agent",
|
|
38
|
+
"description": "Parenting AI agent — LINE-based Q&A, records, reminders"
|
|
39
|
+
},
|
|
40
|
+
"status": {
|
|
41
|
+
"active": "Active",
|
|
42
|
+
"coming": "Coming Soon"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"account": {
|
|
47
|
+
"menu": "Account menu",
|
|
48
|
+
"account": "Account",
|
|
49
|
+
"login": "Log in",
|
|
50
|
+
"logout": "Log out",
|
|
51
|
+
"busy": "Logging out…"
|
|
52
|
+
},
|
|
53
|
+
"footer": {
|
|
54
|
+
"navigation": "Navigation",
|
|
55
|
+
"projects": "Projects",
|
|
56
|
+
"blog": "Blog",
|
|
57
|
+
"social": "Social",
|
|
58
|
+
"description": "Tomorrow starts here."
|
|
59
|
+
},
|
|
60
|
+
"locale": {
|
|
61
|
+
"names": {
|
|
62
|
+
"en": "English",
|
|
63
|
+
"ko": "한국어",
|
|
64
|
+
"ja": "日本語"
|
|
65
|
+
},
|
|
66
|
+
"pending": "Changing language…",
|
|
67
|
+
"failed": "The language could not be changed. Your work is still here.",
|
|
68
|
+
"retry": "Try again",
|
|
69
|
+
"errors": {
|
|
70
|
+
"badRequest": "This address is not valid.",
|
|
71
|
+
"notFound": "Page not found.",
|
|
72
|
+
"unauthenticated": "Sign in to continue.",
|
|
73
|
+
"forbidden": "You do not have access to this page.",
|
|
74
|
+
"unavailable": "The service is temporarily unavailable. Please try again."
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"naeil": {
|
|
3
|
+
"header": {
|
|
4
|
+
"nav": {
|
|
5
|
+
"home": "ホーム",
|
|
6
|
+
"projects": "プロジェクト",
|
|
7
|
+
"blog": "ブログ",
|
|
8
|
+
"navigation": "メインナビゲーション",
|
|
9
|
+
"menu": "メニュー",
|
|
10
|
+
"closeMenu": "メニューを閉じる"
|
|
11
|
+
},
|
|
12
|
+
"theme": {
|
|
13
|
+
"switchToLight": "ライトテーマに切り替える",
|
|
14
|
+
"switchToDark": "ダークテーマに切り替える"
|
|
15
|
+
},
|
|
16
|
+
"locale": {
|
|
17
|
+
"switchLabel": "言語"
|
|
18
|
+
},
|
|
19
|
+
"projects": {
|
|
20
|
+
"cc": {
|
|
21
|
+
"name": "Content Collector",
|
|
22
|
+
"description": "RSS、YouTube、Redditの自動収集 + AI要約"
|
|
23
|
+
},
|
|
24
|
+
"pkm": {
|
|
25
|
+
"name": "PKM",
|
|
26
|
+
"description": "個人ナレッジ管理 — ドキュメント解析、埋め込み、セマンティック検索"
|
|
27
|
+
},
|
|
28
|
+
"naeilUi": {
|
|
29
|
+
"name": "naeil-ui",
|
|
30
|
+
"description": "ミニマルデザインシステム — OKLCHトークン、Tailwind v4、shadcn"
|
|
31
|
+
},
|
|
32
|
+
"sa": {
|
|
33
|
+
"name": "Sustainability Analyzer",
|
|
34
|
+
"description": "ESGレポートAI分析 — PDF解析、定性評価、比較表の自動生成"
|
|
35
|
+
},
|
|
36
|
+
"babyAgent": {
|
|
37
|
+
"name": "Baby Agent",
|
|
38
|
+
"description": "育児AIエージェント — LINE Q&A、記録、リマインダー"
|
|
39
|
+
},
|
|
40
|
+
"status": {
|
|
41
|
+
"active": "アクティブ",
|
|
42
|
+
"coming": "準備中"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"account": {
|
|
47
|
+
"menu": "アカウントメニュー",
|
|
48
|
+
"account": "アカウント",
|
|
49
|
+
"login": "ログイン",
|
|
50
|
+
"logout": "ログアウト",
|
|
51
|
+
"busy": "ログアウト中…"
|
|
52
|
+
},
|
|
53
|
+
"footer": {
|
|
54
|
+
"navigation": "ナビゲーション",
|
|
55
|
+
"projects": "プロジェクト",
|
|
56
|
+
"blog": "ブログ",
|
|
57
|
+
"social": "ソーシャル",
|
|
58
|
+
"description": "Tomorrow starts here."
|
|
59
|
+
},
|
|
60
|
+
"locale": {
|
|
61
|
+
"names": {
|
|
62
|
+
"en": "English",
|
|
63
|
+
"ko": "한국어",
|
|
64
|
+
"ja": "日本語"
|
|
65
|
+
},
|
|
66
|
+
"pending": "言語を変更しています…",
|
|
67
|
+
"failed": "言語を変更できませんでした。作業内容は保持されています。",
|
|
68
|
+
"retry": "再試行",
|
|
69
|
+
"errors": {
|
|
70
|
+
"badRequest": "このアドレスは無効です。",
|
|
71
|
+
"notFound": "ページが見つかりません。",
|
|
72
|
+
"unauthenticated": "続けるにはログインしてください。",
|
|
73
|
+
"forbidden": "このページへのアクセス権限がありません。",
|
|
74
|
+
"unavailable": "サービスを一時的に利用できません。もう一度お試しください。"
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"naeil": {
|
|
3
|
+
"header": {
|
|
4
|
+
"nav": {
|
|
5
|
+
"home": "홈",
|
|
6
|
+
"projects": "프로젝트",
|
|
7
|
+
"blog": "블로그",
|
|
8
|
+
"navigation": "주요 메뉴",
|
|
9
|
+
"menu": "메뉴",
|
|
10
|
+
"closeMenu": "메뉴 닫기"
|
|
11
|
+
},
|
|
12
|
+
"theme": {
|
|
13
|
+
"switchToLight": "밝은 테마로 전환",
|
|
14
|
+
"switchToDark": "어두운 테마로 전환"
|
|
15
|
+
},
|
|
16
|
+
"locale": {
|
|
17
|
+
"switchLabel": "언어"
|
|
18
|
+
},
|
|
19
|
+
"projects": {
|
|
20
|
+
"cc": {
|
|
21
|
+
"name": "Content Collector",
|
|
22
|
+
"description": "RSS, YouTube, Reddit 자동 수집 + AI 요약"
|
|
23
|
+
},
|
|
24
|
+
"pkm": {
|
|
25
|
+
"name": "PKM",
|
|
26
|
+
"description": "개인 지식 관리 — 문서 파싱, 임베딩, 시맨틱 검색"
|
|
27
|
+
},
|
|
28
|
+
"naeilUi": {
|
|
29
|
+
"name": "naeil-ui",
|
|
30
|
+
"description": "미니멀 디자인 시스템 — OKLCH 토큰, Tailwind v4, shadcn"
|
|
31
|
+
},
|
|
32
|
+
"sa": {
|
|
33
|
+
"name": "Sustainability Analyzer",
|
|
34
|
+
"description": "ESG 리포트 AI 분석 — PDF 파싱, 정성평가, 비교표 자동 생성"
|
|
35
|
+
},
|
|
36
|
+
"babyAgent": {
|
|
37
|
+
"name": "Baby Agent",
|
|
38
|
+
"description": "육아 AI 에이전트 — LINE 기반 Q&A, 기록, 리마인더"
|
|
39
|
+
},
|
|
40
|
+
"status": {
|
|
41
|
+
"active": "활성",
|
|
42
|
+
"coming": "준비 중"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
"account": {
|
|
47
|
+
"menu": "계정 메뉴",
|
|
48
|
+
"account": "계정",
|
|
49
|
+
"login": "로그인",
|
|
50
|
+
"logout": "로그아웃",
|
|
51
|
+
"busy": "로그아웃 중…"
|
|
52
|
+
},
|
|
53
|
+
"footer": {
|
|
54
|
+
"navigation": "네비게이션",
|
|
55
|
+
"projects": "프로젝트",
|
|
56
|
+
"blog": "블로그",
|
|
57
|
+
"social": "소셜",
|
|
58
|
+
"description": "Tomorrow starts here."
|
|
59
|
+
},
|
|
60
|
+
"locale": {
|
|
61
|
+
"names": {
|
|
62
|
+
"en": "English",
|
|
63
|
+
"ko": "한국어",
|
|
64
|
+
"ja": "日本語"
|
|
65
|
+
},
|
|
66
|
+
"pending": "언어를 변경하는 중…",
|
|
67
|
+
"failed": "언어를 변경하지 못했습니다. 작업 내용은 유지됩니다.",
|
|
68
|
+
"retry": "다시 시도",
|
|
69
|
+
"errors": {
|
|
70
|
+
"badRequest": "올바르지 않은 주소입니다.",
|
|
71
|
+
"notFound": "페이지를 찾을 수 없습니다.",
|
|
72
|
+
"unauthenticated": "계속하려면 로그인하세요.",
|
|
73
|
+
"forbidden": "이 페이지에 접근할 권한이 없습니다.",
|
|
74
|
+
"unavailable": "일시적으로 서비스를 이용할 수 없습니다. 다시 시도하세요."
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Owned-service language runtime
|
|
2
|
+
|
|
3
|
+
The opt-in `@naeil/ui/naeil-locale` entries support the registered naeil Next applications. English uses `/`, Korean `/ko`, and Japanese `/ja`, including deep routes. The URL determines the language. Cookie and browser preferences never redirect or overwrite it. The existing public `i18n/routing`, `Nav` and `Footer` APIs retain their previous behavior.
|
|
4
|
+
|
|
5
|
+
Use exact `next-intl@4.14.8` with the shared server/client entries. Next and React remain external peers. Standalone header/footer imports do not require Next or next-intl.
|
|
6
|
+
|
|
7
|
+
## Entries and ownership
|
|
8
|
+
|
|
9
|
+
| Import | Responsibility |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| `@naeil/ui/naeil-locale` | Supported locales, strict service/route registry, `localePath`, `localeHref`, legacy receiving aliases and logical-route comparison |
|
|
12
|
+
| `/naeil-locale/server` | `createNaeilLocaleProxy`, `createNaeilRequestConfig`, request access markers and `localeMetadata` |
|
|
13
|
+
| `/naeil-locale/client` | Root `NaeilLocaleController`, locale `NaeilLocaleProvider`, `useLocaleController`, `useLocaleBeforeUnload` |
|
|
14
|
+
| `/naeil-locale/messages` | Selected common/application JSON loading and namespace merge |
|
|
15
|
+
| `/naeil-locale/checker` | Three-language key, nonempty value, ICU syntax and argument compatibility checks |
|
|
16
|
+
| `/naeil-locale/chrome` | Existing header/account/footer presentation using the provider's selected common dictionary |
|
|
17
|
+
|
|
18
|
+
Place the controller and app-owned session/business store in `app/layout.tsx`, above `[locale]`. Place the shared provider in `app/[locale]/layout.tsx` using the validated locale and server-loaded messages. Keep raw input, dialogs, undo, save/run controllers, stream readers and document-departure guards in the root lifetime. Locale remounts must not save, abort, reset, or seed a retained draft from older server props. Translate message keys at the rendering boundary, not inside persistent business state.
|
|
19
|
+
|
|
20
|
+
The shared config sets `localePrefix: "as-needed"`, `localeDetection: false`, `localeCookie: false`, and `alternateLinks: false`. Consumers set Next's `skipProxyUrlNormalize: true` and `skipTrailingSlashRedirect: true`; normalization follows the existing protocol/auth checks. A trusted ingress consumer may pass `requestOrigin: request => existingValidatedRequestUrl(request).origin` to the proxy. This keeps alias redirects and internal rewrites on the validated authority, including local127.0.0.1 deployments. Never derive it from an unvalidated forwarded host.
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
// app/layout.tsx — inside the existing html/body
|
|
24
|
+
<NaeilLocaleController service="estimate" preferenceWritesEnabled={false}>
|
|
25
|
+
<BusinessStateProvider>{children}</BusinessStateProvider>
|
|
26
|
+
</NaeilLocaleController>
|
|
27
|
+
|
|
28
|
+
// app/[locale]/layout.tsx — validate locale and setRequestLocale on the server
|
|
29
|
+
<NaeilLocaleProvider locale={locale} messages={await getMessages()}>
|
|
30
|
+
{children}
|
|
31
|
+
</NaeilLocaleProvider>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Use `createNaeilRequestConfig({namespace: "estimate", messages: {en: () => import("../../messages/en.json"), ko: () => import("../../messages/ko.json"), ja: () => import("../../messages/ja.json")}})` in the next-intl request config. Every app JSON has exactly its own namespace. The package owns `naeil`; do not copy it into an app. The shared checker is a required build gate. The loader imports only the selected app dictionary and shared dictionary; an observable English recovery handles unexpected runtime omissions. Such omissions still fail acceptance.
|
|
35
|
+
|
|
36
|
+
Render complete paths with `localePath` for same-service navigation and `localeHref` for owned service links. Pass those paths to base Next Link/router or anchors without another locale option. The controller performs `router.replace(href, {scroll: false})`, serializes requests and waits for the matching provider arrival. It restores a stable `data-naeil-focus-id`, input `name`, or `id`. Only a successful explicit selection may write preference; history, prefetch and direct visits do not. Storage failure cannot block a path change.
|
|
37
|
+
|
|
38
|
+
The canonical chrome can be imported from `/naeil-locale/chrome` under the shared provider. Existing `/naeil-header` and `/naeil-footer` remain standalone compatibility adapters and include the small three-language common dictionary. Consumer Link, auth, save guards, frame overrides, desktop/mobile account locks and project data remain consumer-owned.
|
|
39
|
+
|
|
40
|
+
## AB Storm registration (0.11.0 candidate)
|
|
41
|
+
|
|
42
|
+
`service="abstorm"` binds to exactly `https://abstorm.naeil.dev`. Its protected UI inventory is `/`, `/new`, `/runs/[id]`, `/runs/[id]/report` and `/experts`; `/new?copy=<id>` uses the same registered page. All support English, Korean and Japanese paths. `/auth/session`, `/auth/logout`, `/api/*` and `/health` remain unlocalized protocol endpoints, with no UI exceptions. Unknown UI paths are rejected instead of inheriting the app’s catch-all history fallback.
|
|
43
|
+
|
|
44
|
+
The inventory was checked against AB Storm source `087e67239db26506a73c51fde7a6d246e4a0d0d9`. Generic error documents use its existing `abstorm` title and no favicon. This registration does not add a default header/footer destination or application translations. Consumer provider, routing, authentication, message loading and upgrade remain app-owned; package registration alone does not establish production adoption.
|
|
45
|
+
|
|
46
|
+
## Security and rollout
|
|
47
|
+
|
|
48
|
+
The proxy runs exact existing protocol boundaries first, strips external private markers, strictly classifies UI paths, applies the existing app authorizer, and then runs next-intl. Protected entries without an authorizer fail closed. A marker is only a rendering hint: every protected server data read must independently authorize. RSC denial renders a valid localized access boundary and retains the root draft; it must not send login HTML or redirect an in-progress editor to another document. Keep the root beforeunload guard active during RSC failure and access recovery.
|
|
49
|
+
|
|
50
|
+
`localePath` is not an auth-return validator. Keep existing exact return/invite/callback/relay origin and envelope validation. Protocol paths stay outside `[locale]`; localized protocol aliases are rejected. Public metadata advertises only available translations. Protected/auth/error UI is noindex without SEO alternates.
|
|
51
|
+
|
|
52
|
+
Receiver deployment and sending are separate gates. `preferenceWritesEnabled` defaults to false. Before first exposure, validate a separate receiver-compatible fallback or the previous build's safe rejection of new paths. After all required receiver and auth receipts pass, enable the reviewed cross-service links and explicit preference writes. Keep package, source, hosted Docs, app identities, activation times and rollback receipts separate. Home and Baby are outside this migration.
|
package/docs/package-release.md
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
# Package verification and release policy
|
|
2
2
|
|
|
3
|
-
**Published exact baseline: 0.
|
|
3
|
+
**Published exact baseline: 0.10.0 — 2026-11-04.** Source/tag `455f2f9aedb108606af2f429c18281260eafd2dd`, frozen archive SHA-256 `a4a1e312f2f608358a10f9019c248af37a8172bb116d3bc506144442cb963fb4`, 175 regular files. Registry bytes matched; verified tags were `latest=0.7.2`, `next=0.10.0`. See the [publication and three-service acceptance receipts](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/shared-language-2026-11-04/implementation-progress.md). Historical releases, archives and receipts remain immutable; hosted Docs require their own receipt. The retained [local runner](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md) is a **0.7.x-only, contract 1** release/recovery tool, outside the current 0.10.0 deployment and recovery procedure. UI v2 names a design generation, not an npm major. Version-scoped installation is in the [README](../README.md#use-the-ui).
|
|
4
|
+
|
|
5
|
+
## 0.11.0 candidate — AB Storm locale registry
|
|
6
|
+
|
|
7
|
+
This additive API candidate registers AB Storm's five protected UI routes and error-document identity. Use the manual exact-archive procedure below, publish to `next` and preserve `latest`; the intended tag is `v0.11.0` at the frozen source. The historical 0.7.x runner transaction and chrome contract 1 remain unchanged. Package version, generated `/release` metadata and clean consumer fixture versions move together. Freeze only after all bundled documentation edits, and record source, digest, inventory and final checks outside the archive. Publication, registry verification, consumer adoption, GitHub Release and hosted Docs remain separate maintainer steps.
|
|
4
8
|
|
|
5
9
|
## Architecture
|
|
6
10
|
|
|
7
11
|
One repository contains the shared package and the separate Next.js brand/example website. `@naeil/ui/ui` provides React primitives and generic Navigation/SiteFooter. The opt-in React-only `@naeil/ui/naeil-header` provides the complete actual naeil.dev branded header and `NaeilHeaderAccountControl`; see [its consumer contract](components/naeil-header.md). Owned apps render that control in `authSlot` and supply session state, pending state and guarded callbacks above the header. The legacy root is a framework compatibility entry with static Next/next-intl imports, even when selecting only Logo or a heading; React-only consumers use the documented shared deep modules. Next and next-intl are optional peers, not optional behavior inside the root. Supply them when importing that entry, Nav, Footer, or i18n/routing. Theme controls and Toaster use the framework-independent React library next-themes, retained as a runtime dependency.
|
|
8
12
|
|
|
9
|
-
Owned services use `@naeil/ui/naeil-footer` for the canonical localized destinations in full/compact variants; generic SiteFooter and legacy Footer retain their APIs. Footer navigation adapters preserve application save/flush decisions and modified-click behavior. `@naeil/ui/release` is server-safe metadata; it contains no application artifact, credential or environment. Applications compile their own allowlisted artifact/source identity. See [the footer contract](components/naeil-footer.md).
|
|
13
|
+
Owned services use `@naeil/ui/naeil-footer` for the canonical localized destinations in full/compact variants; generic SiteFooter and legacy Footer retain their APIs. Footer navigation adapters preserve application save/flush decisions and modified-click behavior. `@naeil/ui/release` is server-safe metadata; it contains no application artifact, credential or environment. Applications compile their own allowlisted artifact/source identity. See [the footer contract](components/naeil-footer.md). Historical 0.7.x release plans and transaction recovery use the [local rollout runner](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md); the [rollout records](https://github.com/naeil-dev/naeil-ui/tree/main/docs/rollout) preserve dated evidence and historical policies. Publishing a package, creating an update PR or merging it never establishes complete consumer rollout. Home Console is outside the selected shared-UI rollout.
|
|
10
14
|
|
|
11
15
|
Website tools remain development dependencies so maintainers can develop both products. npm tarball consumers install only component runtime dependencies and their host React/ReactDOM. Build entries, package exports and packed checks constrain the public boundary. There is no bundled website action, Supabase helper, Three/hero/cursor module, blog engine or full application message catalog. The opt-in header includes only its three header dictionaries and canonical project catalog. Its 0.7.2 default catalog contains naeil-ui and references the official `https://naeil.dev/images/whale.png` URL and require network access; no image bytes are bundled, and unresolved artwork redistribution provenance remains in [third-party notices](../THIRD_PARTY_NOTICES.md).
|
|
12
16
|
|
|
@@ -31,6 +35,17 @@ pnpm exec playwright install chromium firefox webkit
|
|
|
31
35
|
pnpm test:browser
|
|
32
36
|
```
|
|
33
37
|
|
|
38
|
+
The chrome fixture server and standalone navigation sample use `NAEIL_UI_FIXTURE_PORT`, with the unchanged default defined in `scripts/chrome-fixture-config.ts` in the repository. The same module supplies every fixture URL. An explicit port also isolates generated fixtures, test results and HTML reports by port; leave it unset to retain the existing CI paths. Choose a free integer port from 1 to 65535.
|
|
39
|
+
|
|
40
|
+
For two concurrent fixture-only runs in one worktree, use separate terminals:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
NAEIL_UI_CHROME_ONLY=1 NAEIL_UI_FIXTURE_PORT=16081 pnpm test:browser e2e/page-frame.spec.ts --project=chromium
|
|
44
|
+
NAEIL_UI_CHROME_ONLY=1 NAEIL_UI_FIXTURE_PORT=16082 pnpm test:browser e2e/page-frame.spec.ts --project=chromium
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
`NAEIL_UI_CHROME_ONLY=1` skips the unrelated Storybook server. Full suites still use `NAEIL_UI_STORYBOOK_PORT` for Storybook. Do not overlap an unset-port run (which cleans the default `test-results` directory) with custom-port runs in the same worktree. The standalone sample uses the same port setting: `NAEIL_UI_FIXTURE_PORT=16083 pnpm exec tsx scripts/serve-navigation-sample.ts`. Stop standalone previews after use; Playwright stops its own fixture server.
|
|
48
|
+
|
|
34
49
|
`check:package:boundary` inspects an actual `npm pack --ignore-scripts` archive for every declared export, runtime dependencies, source aliases, relative imports, required CSS/tokens/documents/notices and forbidden website payload. `check:consumers` separately installs that tarball with npm into two temporary directories. It builds the reusable React example with Vite/Tailwind, type-checks with library checks enabled, imports shared deep modules, checks SSR and CSS, and asserts Next/Supabase/Three are absent. A separate Next production build exercises root exports and the deep paths observed in the reachable Next consumer, with consumer-owned messages and no auth backend. Neither fixture uses repository dependency symlinks. Network access is needed for uncached npm dependencies; temporary installs are removed on completion or failure.
|
|
35
50
|
|
|
36
51
|
For a frozen release candidate, both archive-producing checks can enforce the reviewed SHA-256 before extraction or consumer installation:
|
|
@@ -50,6 +65,14 @@ The explicit font-notice regression gate copies the real React fixture config in
|
|
|
50
65
|
|
|
51
66
|
## Publication and deployment
|
|
52
67
|
|
|
68
|
+
### Verified 0.10.0 publication and service acceptance — 2026-11-04
|
|
69
|
+
|
|
70
|
+
The [registry receipt](https://github.com/naeil-dev/naeil-ui/releases/download/v0.10.0/npm-registry-verification.json) verifies the exact frozen archive listed above, including all 175 regular members. [Release v0.10.0](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.10.0) retains its assets at the frozen source. [Implementation progress](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/shared-language-2026-11-04/implementation-progress.md) and [acceptance](https://github.com/naeil-dev/naeil-ui/blob/main/docs/design/shared-language-2026-11-04/acceptance.md) record Site, Jev and Estimate separately. Those service identities and recovery procedures are outside the old 0.7.x runner; its preserved approval and transaction must not be reused for this release.
|
|
71
|
+
|
|
72
|
+
### Historical 0.8.0 registry checkpoint — 2026-10-29
|
|
73
|
+
|
|
74
|
+
The published 0.8.0 archive matched frozen SHA-256 `6feb5a8cd50265ace584a0855432683b4127119377e08235282eaebd27081084` (139 files, source/tag `3f708e27d05212af7f7a5be769f13f871e8d10c7`). Registry tags at that dated checkpoint were `latest=0.7.2`, `next=0.8.0`. Its Home menu/brand/status/controlled-sheet APIs and package-owned chrome typography remain part of the current public API. This receipt remains historical and does not establish the current registry tags or hosted Docs source.
|
|
75
|
+
|
|
53
76
|
### Verified 0.7.1 registry publication and maintained Docs — 2026-10-23
|
|
54
77
|
|
|
55
78
|
The published release preserves these immutable identities:
|
|
@@ -66,7 +89,7 @@ The frozen archive was published directly with scripts disabled. npm records pub
|
|
|
66
89
|
|
|
67
90
|
The archive's bundled guides are an immutable preparation snapshot, including 0.6.0 installation copy. Release notes must point to maintained instructions. Deploy Docs from a separately reviewed commit containing current guidance, the `v0.7.1` link correction and the corrected manual workflow. Record that Docs SHA, workflow run, deployment and actual hosted checks separately; retain `v0.7.1` at the frozen package source.
|
|
68
91
|
|
|
69
|
-
Postpublication registry checks passed on 2026-10-23. Separate fresh React/Next fixtures installed exact `@naeil/ui@0.7.1` from npmjs with independent empty caches and no repository dependency symlinks; every installed file matched the frozen 139-file inventory in both fixtures. Types, production builds, public root/deep import boundaries, release/footer/account SSR and browser checks passed, including the React fixture's absence of Next/Supabase/Three. The retained `registry-receipt.json` and successful `npm-publication-verification.json` bind these checks to the frozen source/archive; the latter records `checkedAt: 2026-10-23T01:19:50.385Z`. At the 01:19 UTC registry checkpoint, the tag had been pushed and the Release draft prepared. GitHub Release publication, hosted Docs and
|
|
92
|
+
Postpublication registry checks passed on 2026-10-23. Separate fresh React/Next fixtures installed exact `@naeil/ui@0.7.1` from npmjs with independent empty caches and no repository dependency symlinks; every installed file matched the frozen 139-file inventory in both fixtures. Types, production builds, public root/deep import boundaries, release/footer/account SSR and browser checks passed, including the React fixture's absence of Next/Supabase/Three. The retained `registry-receipt.json` and successful `npm-publication-verification.json` bind these checks to the frozen source/archive; the latter records `checkedAt: 2026-10-23T01:19:50.385Z`. At the 01:19 UTC registry checkpoint, the tag had been pushed and the Release draft prepared. GitHub Release publication, hosted Docs and service rollout require separate receipts; see the release assets and [historical 0.7.x rollout runbook](https://github.com/naeil-dev/naeil-ui/blob/main/docs/rollout/local-runner.md). Native/manual, real OAuth and global service-discovery evidence retain their separate scopes and limits.
|
|
70
93
|
|
|
71
94
|
### 0.6.0 release scope — 2026-10-16
|
|
72
95
|
|
|
@@ -104,7 +127,7 @@ The immutable npm archive's bundled guides are the release-preparation snapshot.
|
|
|
104
127
|
|
|
105
128
|
### Release procedure
|
|
106
129
|
|
|
107
|
-
Maintained Storybook resolves relative Markdown guide links against the published `v0.7.2` source `40a3928e24cd2f0141be3e605eed0a75260938fd`.
|
|
130
|
+
Maintained Storybook resolves relative Markdown guide links against the published `v0.7.2` source `40a3928e24cd2f0141be3e605eed0a75260938fd`. Package releases keep that published guide-link target until a separately reviewed Docs release. That tag is independent of the reviewed Docs deployment SHA. Hosted verification checks that the pinned links resolve; the unpublished `v0.7.0` tag is not a valid target. Historical foundation/source-authority links remain at their original revisions. Freeze subsequent documentation changes separately from immutable release archives.
|
|
108
131
|
|
|
109
132
|
The authorized 0.3.0 release completed main merge, npm 0.3.0, a GitHub Release and hosted Docs as recorded above. The release maintainer performs external authentication and publication; documentation preparation does not itself execute those operations. The automatic verification workflow does not publish or deploy. Record native/manual observations with their actual scope and carry unrun checks as limitations; do not substitute automated WebKit/axe checks or publication authorization for human certification.
|
|
110
133
|
|
|
@@ -121,9 +144,11 @@ npm publication, GitHub Releases, main merge and hosted Docs are distinct operat
|
|
|
121
144
|
`vercel.json` disables Git deployments only for `feat/public-ui-readiness`. Other branches retain Vercel's default behavior, so merging or pushing another branch requires a separate deployment decision. The automatic GitHub Actions checks are verification-only; enabling repository workflows is not evidence of a hosted site or approved release.
|
|
122
145
|
|
|
123
146
|
|
|
124
|
-
###
|
|
147
|
+
### Historical manual exact-archive preparation for 0.9.0 (following 0.8.0)
|
|
148
|
+
|
|
149
|
+
The following preparation requirements and deployment hold describe the October 29 checkpoint. The November 4 release and accepted service state are recorded above; this historical section does not describe current service versions or pending approval.
|
|
125
150
|
|
|
126
|
-
The
|
|
151
|
+
The retained `scripts/rollout/prepare-release.mjs` accepts consecutive stable 0.7.x releases only. Do not change rollout policy, `release.json` or the chrome contract to admit 0.9.0. Use the manual release procedure above: complete G1–G7 from the [adopted root-frame contract](https://github.com/naeil-dev/naeil-ui/blob/434b7d07235316097ca3a55265ee02c1422b0cfd/docs/superpowers/specs/2026-10-29-page-root-scrollbar-gutter.md), including the retained 0.8.0 P1–P5 regressions, freeze the exact source SHA/archive, then run boundary and clean React/Next checks with `NAEIL_UI_EXPECTED_ARCHIVE_SHA256`. The paired browser gate accepts `NAEIL_UI_CHROME_PACKAGE=/absolute/extracted/package` to exercise that exact archive, alongside SHA-512-pinned 0.7.2 and SHA-256-pinned frozen 0.8.0. Reference-only root/lock CSS adjustments are separate hashed fixture files; immutable archives stay untouched. Both classic and overlay jobs require actual probes. Viewport captures have geometry guards; all acceptance measurement precedes any terminal fullPage capture. It retains numeric differences and screenshots for human review; new renders never replace expectations automatically.
|
|
127
152
|
|
|
128
153
|
Before npm publication, the separately approved source push must make the linked adopted contract at `434b7d07235316097ca3a55265ee02c1422b0cfd` public. Immediately after that push, verify an anonymous HTTP 200 for the exact guide URL and confirm its status says **rev 1, adopted 2026-10-29**. Local link/boundary checks do not establish public reachability. Source push may trigger Vercel deployment and retains its own approval boundary.
|
|
129
154
|
|