@naeil/ui 0.6.0 → 0.7.2
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 +22 -0
- package/README.md +15 -10
- package/contracts/naeil-chrome.v1.json +12 -0
- package/dist/{chunk-VL7FS4QM.js → chunk-7JBLPGZ4.js} +4 -343
- package/dist/chunk-HSTDPY56.js +74 -0
- package/dist/chunk-MGCCKOGU.js +385 -0
- package/dist/{chunk-CE73AEJZ.js → chunk-QQQQZEPV.js} +249 -3
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.js +10 -8
- package/dist/components/naeil-footer.d.ts +16 -0
- package/dist/components/naeil-footer.js +76 -0
- package/dist/components/naeil-header.d.ts +23 -5
- package/dist/components/naeil-header.js +5 -2
- package/dist/components/ui/index.d.ts +2 -2
- package/dist/components/ui/index.js +6 -6
- package/dist/lib/ui-release.d.ts +1 -0
- package/dist/lib/ui-release.js +1 -0
- package/dist/naeil-header-content-BvISJ4RV.d.ts +4 -0
- package/dist/{navigation-CL10a6Eb.d.ts → navigation-CgPeL9tF.d.ts} +1 -1
- package/dist/{site-footer-B67meCDv.d.ts → site-footer-vXDa_6yr.d.ts} +4 -2
- package/dist/source/components/naeil-footer.d.ts +16 -0
- package/dist/source/components/naeil-footer.js +95 -0
- package/dist/source/components/naeil-header-account.d.ts +26 -0
- package/dist/source/components/naeil-header-account.js +67 -0
- package/dist/source/components/naeil-header-content.d.ts +1 -25
- package/dist/source/components/naeil-header-content.js +0 -28
- package/dist/source/components/naeil-header.d.ts +2 -1
- package/dist/source/components/naeil-header.js +6 -1
- package/dist/source/components/ui/site-footer.d.ts +4 -2
- package/dist/source/components/ui/site-footer.js +6 -2
- package/dist/source/lib/ui-release.d.ts +6 -0
- package/dist/source/lib/ui-release.js +4 -0
- package/docs/components/README.md +4 -3
- package/docs/components/application-layout.md +48 -15
- package/docs/components/naeil-footer.md +20 -0
- package/docs/components/naeil-header.md +25 -7
- package/docs/components/navigation.md +3 -1
- package/docs/design/v2-migration.md +11 -10
- package/docs/package-release.md +33 -12
- package/package.json +16 -4
- package/src/styles/components.css +35 -0
- package/dist/chunk-QSTGUEEI.js +0 -323
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.2 — retired project catalog (candidate)
|
|
4
|
+
|
|
5
|
+
- Narrow the canonical `NaeilHeader` project catalog to naeil-ui. Content Collector, PKM, Sustainability Analyzer and Baby Agent are retired from naeil.dev; their site pages move to `src/app/_archive/` and old URLs temporarily redirect to the project list. The project menu uses one column for a single entry. `projects`, `translations` and `currentProjectKey` overrides are unchanged.
|
|
6
|
+
- Release class `dom`: the standing worker adopts it only through an owner-approved `reviewedMigration` of this exact release; ordinary fix-only patches are unaffected.
|
|
7
|
+
|
|
8
|
+
## 0.7.1 — canonical service chrome (published 2026-10-23)
|
|
9
|
+
|
|
10
|
+
Published to npm at `2026-10-23T01:14:11.387Z`; `latest` was verified as `0.7.1`. This first published 0.7.x release includes the unpublished 0.7.0 scope below. Frozen package source and tag `v0.7.1`: `32108fd8e1cb1db6dae24a09f3ca72ac9a91f618`; archive SHA-256: `ecd656c595fd63516417eef58a5e2624d1f1bf928ba0465761292d05502ab3f8`. Independent download and fresh React/Next registry consumers matched the archive and all 139 files, with types, production builds and browser checks passing. Hosted Docs and standing activation require separate receipts; see the [release policy](docs/package-release.md#publication-and-deployment).
|
|
11
|
+
|
|
12
|
+
- Add canonical `NaeilHeaderAccountControl` for shared login/account/logout presentation while consumers retain session and save guards.
|
|
13
|
+
- Include React-only `NaeilFooter`, canonical full/compact destinations, save-navigation interception and server-safe `/release` package/contract identity from the unpublished 0.7.0 candidate.
|
|
14
|
+
- Preserve existing header slots and imports; include authenticated menu/busy/failure coverage and packed consumer checks.
|
|
15
|
+
- Preserve the approved 1600px/clamp frame, generic Navigation/SiteFooter and legacy Nav/Footer APIs. Bundled guides retain their frozen preparation snapshot; maintained guides and hosted Docs use a separately reviewed source.
|
|
16
|
+
|
|
17
|
+
## 0.7.0 — unpublished candidate
|
|
18
|
+
|
|
19
|
+
- Add React-only canonical NaeilFooter with full/compact content, localized destinations and save-navigation adapters. Preserve generic and Next Footer overrides.
|
|
20
|
+
- Add SiteFooter onNavigate for every group link including native external anchors.
|
|
21
|
+
- Add package/chrome-contract identity, independent rendered release references and fail-closed service rollout verification.
|
|
22
|
+
- Keep approved 1600px/clamp frame and purpose-specific content widths unchanged.
|
|
23
|
+
|
|
24
|
+
|
|
3
25
|
## 0.6.0 — shared application frame (2026-10-16)
|
|
4
26
|
|
|
5
27
|
- Align Navigation, SiteFooter, NaeilHeader and preserved Nav/Footer adapters with a shared 1600px maximum outer frame and responsive `clamp(16px, 2.4vw, 40px)` gutters. Add `ui-app-frame` for main composition; retain explicit classes and product token overrides.
|
package/README.md
CHANGED
|
@@ -2,24 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
React components, semantic design tokens, and shared styles for naeil products. The approved system uses a neutral light/dark palette, Pretendard, 16px controls, comfortable or compact density, purpose-specific content widths, and restrained motion. Radix supplies interaction behavior.
|
|
4
4
|
|
|
5
|
+
**0.7.1 published and registry-verified — 2026-10-23.** The current published baseline is **0.7.1**. This first published 0.7.x release combines canonical `NaeilFooter`, server-safe `/release` identity and `NaeilHeaderAccountControl`; 0.7.0 remains an unpublished candidate. The frozen package source and `v0.7.1` tag are `32108fd8e1cb1db6dae24a09f3ca72ac9a91f618`. Fresh React/Next registry consumers matched all 139 frozen files and passed types, production builds and browser checks. Maintained guides use separately reviewed source; hosted Docs and standing activation require separate receipts. See the [release policy and receipts](docs/package-release.md#publication-and-deployment).
|
|
6
|
+
|
|
5
7
|
This repository also contains the **naeil.dev brand/example website** and an **optional agent reference workflow**. Choose the path you need:
|
|
6
8
|
|
|
7
9
|
| Path | Start here | Tools / keys |
|
|
8
10
|
| --- | --- | --- |
|
|
9
|
-
| Use the UI in an app | [Consumer guide](docs/design/v2-migration.md) | React 19, Tailwind 4; **no Next.js or API keys** for
|
|
11
|
+
| Use the UI in an app | [Consumer guide](docs/design/v2-migration.md) | React 19, Tailwind 4; **no Next.js or API keys** for shared React entries |
|
|
10
12
|
| Develop the shared UI | Commands below and [contributing](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/CONTRIBUTING.md) | Node.js 22+, pnpm; no Supabase or 21st key |
|
|
11
13
|
| Use frontend references with an agent | [Optional workflow setup](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/docs/design/frontend-tooling.md) | Supported agent; Python for bundled helpers; your own 21st key only for optional MCP |
|
|
12
14
|
| Develop the brand/example website | [Site setup](https://github.com/naeil-dev/naeil-ui/blob/81fd395031dc5b20074c4d915a8585360ce2d28a/docs/site-development.md) | Next.js and a separate Supabase project for site authentication |
|
|
13
15
|
|
|
14
16
|
## Use the UI
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
Use React 19 / ReactDOM 19 and Tailwind 4. UI v2 names the design generation independently of npm versioning. Install the verified registry release:
|
|
17
19
|
|
|
18
20
|
```sh
|
|
19
|
-
pnpm add --save-exact @naeil/ui@0.
|
|
21
|
+
pnpm add --save-exact @naeil/ui@0.7.1
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
For
|
|
24
|
+
The [npm 0.7.1 archive](https://registry.npmjs.org/@naeil/ui/-/ui-0.7.1.tgz) is byte-identical to the frozen release archive. Its bundled guides retain the preparation snapshot; use these maintained instructions for current installation. For local development, `pnpm build:pkg` and `npm pack --ignore-scripts --pack-destination /tmp` produce `/tmp/naeil-ui-0.7.1.tgz`. A fresh pack of maintained source differs from the frozen release archive; use the exact frozen file for release verification. The [0.6.0 release record](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.6.0) retains its archive, publication and deployment evidence.
|
|
23
25
|
|
|
24
26
|
The preceding [0.5.0 release](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.5.0) was published on 2026-10-15 and introduced the whole shared header. Version 0.6.0 adds the shared 1600px frame; existing applications must upgrade and adopt its layout composition.
|
|
25
27
|
|
|
@@ -30,11 +32,13 @@ Choose the shared application composition before building a header or footer:
|
|
|
30
32
|
| Application need | Shared component |
|
|
31
33
|
| --- | --- |
|
|
32
34
|
| Actual naeil.dev brand, project catalog and controls | `NaeilHeader` from `@naeil/ui/naeil-header` |
|
|
35
|
+
| Owned-service login, account and logout presentation (0.7.1) | `NaeilHeaderAccountControl` from `@naeil/ui/naeil-header`, passed in `authSlot` |
|
|
36
|
+
| Owned naeil service footer (0.7.1) | `NaeilFooter` from `@naeil/ui/naeil-footer` |
|
|
33
37
|
| A product's own menu | `Navigation` from `@naeil/ui/ui` |
|
|
34
|
-
|
|
|
38
|
+
| Different product footer or deliberate content override | `SiteFooter` from `@naeil/ui/ui` |
|
|
35
39
|
| Existing Next/next-intl integration | Preserve `Nav` / `Footer` compatibility adapters |
|
|
36
40
|
|
|
37
|
-
Supply application routing, guards, authentication and menu data through adapters and slots. Keep the shared menu, mobile sheet,
|
|
41
|
+
Pair `NaeilHeader` and `NaeilFooter` in owned services. Supply application routing, guards, authentication and menu data through adapters and slots. `NaeilHeaderAccountControl` receives session state, a busy flag and the guarded logout callback; keep pending state and its request lock above the header so desktop/mobile copies share them. Keep the shared menu, mobile sheet, account presentation and footer implementation in the package. The [application layout guide](docs/components/application-layout.md) provides a starter and consumer-agent instructions. Header, main and footer share a 1600px maximum frame with `clamp(16px, 2.4vw, 40px)` gutters; use `ui-app-frame` on main and keep 640px reading/settings or 480px short-form sections inside it.
|
|
38
42
|
|
|
39
43
|
Import primitives from the dedicated entrypoint:
|
|
40
44
|
|
|
@@ -73,9 +77,9 @@ Mark Japanese content with `lang="ja"`. Keep font OFL notices with redistributed
|
|
|
73
77
|
|
|
74
78
|
Shared CSS follows the OS theme unless the document root has `class="light"` or `class="dark"`. For compact spacing, set `data-ui-density="compact"` on that root; omit it for comfortable spacing. Density changes spacing while retaining 16px control text and minimum mobile touch sizes. React apps can also use `ThemeProvider` from `@naeil/ui/components/theme-provider` with `attribute="class"`.
|
|
75
79
|
|
|
76
|
-
The [component guides](docs/components/README.md) cover exact APIs, state composition and accessibility responsibilities
|
|
80
|
+
The [component guides](docs/components/README.md) cover exact APIs, state composition and accessibility responsibilities, with matching Storybook Docs and runnable examples. Canonical footer and account examples live in the existing NaeilHeader/SiteFooter stories. The [consumer guide](docs/design/v2-migration.md) covers peer dependencies, fonts, themes, density, Select versus DropdownMenu, overrides, and layout ownership. Fonts are delivered by the consumer; shared CSS does not fetch them automatically. `/ui`, `/utils`, `/naeil-header`, `/naeil-footer` and `/release` work without Next.js; the last two are included in 0.7.1. The legacy root remains a framework compatibility entry with static Next/next-intl imports; install those optional peers when using it, Nav, Footer or i18n/routing. ThemeProvider/controls and Toaster retain the React library next-themes. Shared deep imports use the exact [allowlist and migration](docs/design/v2-migration.md#03-package-boundary); website-only paths belong in your application.
|
|
77
81
|
|
|
78
|
-
For the actual naeil.dev branded header, import `NaeilHeader` from `@naeil/ui/naeil-header`; generic `Navigation` from `/ui` remains available for different product menus. The whole header owns its catalog, header translations, controls and responsive styles. Supply routing/dirty guards, an existing next-themes provider and real authentication through its props
|
|
82
|
+
For the actual naeil.dev branded header, import `NaeilHeader` and `NaeilHeaderAccountControl` from `@naeil/ui/naeil-header`; generic `Navigation` from `/ui` remains available for different product menus. The whole header owns its catalog, header translations, controls and responsive styles. Supply routing/dirty guards, an existing next-themes provider and real authentication state/actions through its props. Its five decorative project images reference official `naeil.dev` URLs and require network access; their bytes are excluded and unresolved redistribution provenance remains in [third-party notices](THIRD_PARTY_NOTICES.md). See [NaeilHeader](docs/components/naeil-header.md) for fixed positioning, the shared frame, supported locales and adapter contract, and [NaeilFooter](docs/components/naeil-footer.md) for canonical destinations and save interception.
|
|
79
83
|
|
|
80
84
|
## Develop the shared UI
|
|
81
85
|
|
|
@@ -92,7 +96,8 @@ Storybook uses the actual public components with simulated example data. It need
|
|
|
92
96
|
```sh
|
|
93
97
|
pnpm build:pkg
|
|
94
98
|
pnpm pack --pack-destination /tmp
|
|
95
|
-
# In your consumer app: pnpm add /tmp/naeil-ui-0.
|
|
99
|
+
# In your consumer app: pnpm add /tmp/naeil-ui-0.7.1.tgz
|
|
100
|
+
# This development pack does not replace the frozen release archive.
|
|
96
101
|
```
|
|
97
102
|
|
|
98
103
|
| Command | Purpose |
|
|
@@ -104,7 +109,7 @@ pnpm pack --pack-destination /tmp
|
|
|
104
109
|
| `pnpm build:pkg` / `pnpm check:package` | Build package / inspect package boundary and independently install/build packed React + Next consumers |
|
|
105
110
|
| `pnpm dev` / `pnpm build` | Brand/example website development / build |
|
|
106
111
|
|
|
107
|
-
A [reusable React consumer example](https://github.com/naeil-dev/naeil-ui/tree/main/examples/react) composes the packaged header, a settings form and footer. [Release policy](docs/package-release.md) and [changelog](CHANGELOG.md) distinguish implementation, publication and deployment. CI verifies the package and separate website/Storybook. Downloadable preview artifacts include notices and local fonts. The current
|
|
112
|
+
A [reusable React consumer example](https://github.com/naeil-dev/naeil-ui/tree/main/examples/react) composes the packaged header, a settings form and footer. [Release policy](docs/package-release.md) and [changelog](CHANGELOG.md) distinguish implementation, publication and deployment. CI verifies the package and separate website/Storybook. Downloadable preview artifacts include notices and local fonts. The current Storybook source defines 17 Docs pages (15 UI families and Brand / Logo plus NaeilHeader), including Usage, JapaneseApplication, ReferenceFull, ReferenceCompact and AccountStates examples. This does not establish a new hosted deployment. [Hosted Docs](https://naeil-dev.github.io/naeil-ui/) have recorded [0.5.0 verification](https://github.com/naeil-dev/naeil-ui/releases/download/v0.5.0/hosted-docs-verification.json); subsequent deployments require their own source and HTTP checks. The same approved brand is live on [naeil.dev](https://naeil.dev/). See [preview instructions](docs/package-release.md#storybook-preview-artifact) and [support limits](docs/design/public-ui-support.md). Native/manual platform acceptance retains its documented limits; service adoption and continuous rollout have separate [dated records](https://github.com/naeil-dev/naeil-ui/tree/main/docs/rollout).
|
|
108
113
|
|
|
109
114
|
Read [DESIGN.md](DESIGN.md) before shared UI changes. Numeric values live in `src/tokens/`; generated CSS is not edited by hand. Shared styles live in `src/styles/`, site-only styles in `src/app/`. Hero art, 3D scenes, cursor effects, and site content belong to the example website.
|
|
110
115
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"contractVersion": "1",
|
|
4
|
+
"authority": "DESIGN.md: approved 2026-10-16 frame; shared-ui-rollout spec: canonical footer and guard",
|
|
5
|
+
"frame": { "maxWidth": 1600, "gutterMin": 16, "gutterVw": 2.4, "gutterMax": 40 },
|
|
6
|
+
"header": { "height": 65, "brandHeight": 28, "desktopBrandReservation": 160 },
|
|
7
|
+
"footer": { "variants": ["full", "compact"], "brandHeight": 20, "requiredPaths": ["/", "/projects", "/blog"], "github": "https://github.com/naeil-dev" },
|
|
8
|
+
"viewports": [390, 768, 1440, 1920],
|
|
9
|
+
"themes": ["light", "dark"],
|
|
10
|
+
"locales": ["en", "ko", "ja"],
|
|
11
|
+
"tolerancePx": 1
|
|
12
|
+
}
|
|
@@ -1,26 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {
|
|
3
|
-
Badge,
|
|
4
|
-
Button,
|
|
5
|
-
Navigation,
|
|
6
|
-
Select,
|
|
7
|
-
SelectContent,
|
|
8
|
-
SelectItem,
|
|
9
|
-
SelectTrigger,
|
|
10
|
-
SelectValue
|
|
11
|
-
} from "./chunk-CE73AEJZ.js";
|
|
12
2
|
import {
|
|
13
3
|
__objRest,
|
|
14
4
|
__spreadProps,
|
|
15
|
-
__spreadValues
|
|
16
|
-
cn
|
|
5
|
+
__spreadValues
|
|
17
6
|
} from "./chunk-JBTDRVZ7.js";
|
|
18
7
|
|
|
19
|
-
// src/components/naeil-header.tsx
|
|
20
|
-
import { useSyncExternalStore } from "react";
|
|
21
|
-
import { useTheme } from "next-themes";
|
|
22
|
-
import { Moon, Sun } from "lucide-react";
|
|
23
|
-
|
|
24
8
|
// src/components/logo.tsx
|
|
25
9
|
import { useId } from "react";
|
|
26
10
|
|
|
@@ -1180,333 +1164,10 @@ function Logo(_a) {
|
|
|
1180
1164
|
);
|
|
1181
1165
|
}
|
|
1182
1166
|
|
|
1183
|
-
// src/
|
|
1184
|
-
var
|
|
1185
|
-
var headerLocaleNames = { en: "English", ko: "\uD55C\uAD6D\uC5B4", ja: "\u65E5\u672C\u8A9E" };
|
|
1186
|
-
var headerProjects = [
|
|
1187
|
-
{
|
|
1188
|
-
"key": "cc",
|
|
1189
|
-
"href": "/cc",
|
|
1190
|
-
"accent": "oklch(0.704 0.140 181)",
|
|
1191
|
-
"icon": "coral",
|
|
1192
|
-
"status": "active"
|
|
1193
|
-
},
|
|
1194
|
-
{
|
|
1195
|
-
"key": "pkm",
|
|
1196
|
-
"href": "/pkm",
|
|
1197
|
-
"accent": "oklch(0.702 0.183 293)",
|
|
1198
|
-
"icon": "jellyfish",
|
|
1199
|
-
"status": "coming"
|
|
1200
|
-
},
|
|
1201
|
-
{
|
|
1202
|
-
"key": "naeilUi",
|
|
1203
|
-
"href": "/design",
|
|
1204
|
-
"accent": "oklch(0.623 0.214 259)",
|
|
1205
|
-
"icon": "whale",
|
|
1206
|
-
"status": "active"
|
|
1207
|
-
},
|
|
1208
|
-
{
|
|
1209
|
-
"key": "sa",
|
|
1210
|
-
"href": "/sa",
|
|
1211
|
-
"accent": "oklch(0.723 0.219 149)",
|
|
1212
|
-
"icon": "fish",
|
|
1213
|
-
"status": "active"
|
|
1214
|
-
},
|
|
1215
|
-
{
|
|
1216
|
-
"key": "babyAgent",
|
|
1217
|
-
"href": "/baby-agent",
|
|
1218
|
-
"accent": "oklch(0.769 0.188 70.08)",
|
|
1219
|
-
"icon": "turtle",
|
|
1220
|
-
"status": "coming"
|
|
1221
|
-
}
|
|
1222
|
-
];
|
|
1223
|
-
var headerContent = {
|
|
1224
|
-
"en": {
|
|
1225
|
-
"nav": {
|
|
1226
|
-
"home": "Home",
|
|
1227
|
-
"projects": "Projects",
|
|
1228
|
-
"blog": "Blog",
|
|
1229
|
-
"navigation": "Main navigation",
|
|
1230
|
-
"menu": "Menu",
|
|
1231
|
-
"closeMenu": "Close menu"
|
|
1232
|
-
},
|
|
1233
|
-
"theme": {
|
|
1234
|
-
"switchToLight": "Switch to light theme",
|
|
1235
|
-
"switchToDark": "Switch to dark theme"
|
|
1236
|
-
},
|
|
1237
|
-
"locale": {
|
|
1238
|
-
"switchLabel": "Language"
|
|
1239
|
-
},
|
|
1240
|
-
"projects": {
|
|
1241
|
-
"cc": {
|
|
1242
|
-
"name": "Content Collector",
|
|
1243
|
-
"description": "Automated content collection from RSS, YouTube, Reddit + AI summarization"
|
|
1244
|
-
},
|
|
1245
|
-
"pkm": {
|
|
1246
|
-
"name": "PKM",
|
|
1247
|
-
"description": "Personal knowledge management \u2014 document parsing, embeddings, semantic search"
|
|
1248
|
-
},
|
|
1249
|
-
"naeilUi": {
|
|
1250
|
-
"name": "naeil-ui",
|
|
1251
|
-
"description": "Minimal design system \u2014 OKLCH tokens, Tailwind v4, shadcn"
|
|
1252
|
-
},
|
|
1253
|
-
"sa": {
|
|
1254
|
-
"name": "Sustainability Analyzer",
|
|
1255
|
-
"description": "AI-powered ESG report analysis \u2014 PDF parsing, qualitative assessment, comparison tables"
|
|
1256
|
-
},
|
|
1257
|
-
"babyAgent": {
|
|
1258
|
-
"name": "Baby Agent",
|
|
1259
|
-
"description": "Parenting AI agent \u2014 LINE-based Q&A, records, reminders"
|
|
1260
|
-
},
|
|
1261
|
-
"status": {
|
|
1262
|
-
"active": "Active",
|
|
1263
|
-
"coming": "Coming Soon"
|
|
1264
|
-
}
|
|
1265
|
-
}
|
|
1266
|
-
},
|
|
1267
|
-
"ko": {
|
|
1268
|
-
"nav": {
|
|
1269
|
-
"home": "\uD648",
|
|
1270
|
-
"projects": "\uD504\uB85C\uC81D\uD2B8",
|
|
1271
|
-
"blog": "\uBE14\uB85C\uADF8",
|
|
1272
|
-
"navigation": "\uC8FC\uC694 \uBA54\uB274",
|
|
1273
|
-
"menu": "\uBA54\uB274",
|
|
1274
|
-
"closeMenu": "\uBA54\uB274 \uB2EB\uAE30"
|
|
1275
|
-
},
|
|
1276
|
-
"theme": {
|
|
1277
|
-
"switchToLight": "\uBC1D\uC740 \uD14C\uB9C8\uB85C \uC804\uD658",
|
|
1278
|
-
"switchToDark": "\uC5B4\uB450\uC6B4 \uD14C\uB9C8\uB85C \uC804\uD658"
|
|
1279
|
-
},
|
|
1280
|
-
"locale": {
|
|
1281
|
-
"switchLabel": "\uC5B8\uC5B4"
|
|
1282
|
-
},
|
|
1283
|
-
"projects": {
|
|
1284
|
-
"cc": {
|
|
1285
|
-
"name": "Content Collector",
|
|
1286
|
-
"description": "RSS, YouTube, Reddit \uC790\uB3D9 \uC218\uC9D1 + AI \uC694\uC57D"
|
|
1287
|
-
},
|
|
1288
|
-
"pkm": {
|
|
1289
|
-
"name": "PKM",
|
|
1290
|
-
"description": "\uAC1C\uC778 \uC9C0\uC2DD \uAD00\uB9AC \u2014 \uBB38\uC11C \uD30C\uC2F1, \uC784\uBCA0\uB529, \uC2DC\uB9E8\uD2F1 \uAC80\uC0C9"
|
|
1291
|
-
},
|
|
1292
|
-
"naeilUi": {
|
|
1293
|
-
"name": "naeil-ui",
|
|
1294
|
-
"description": "\uBBF8\uB2C8\uBA40 \uB514\uC790\uC778 \uC2DC\uC2A4\uD15C \u2014 OKLCH \uD1A0\uD070, Tailwind v4, shadcn"
|
|
1295
|
-
},
|
|
1296
|
-
"sa": {
|
|
1297
|
-
"name": "Sustainability Analyzer",
|
|
1298
|
-
"description": "ESG \uB9AC\uD3EC\uD2B8 AI \uBD84\uC11D \u2014 PDF \uD30C\uC2F1, \uC815\uC131\uD3C9\uAC00, \uBE44\uAD50\uD45C \uC790\uB3D9 \uC0DD\uC131"
|
|
1299
|
-
},
|
|
1300
|
-
"babyAgent": {
|
|
1301
|
-
"name": "Baby Agent",
|
|
1302
|
-
"description": "\uC721\uC544 AI \uC5D0\uC774\uC804\uD2B8 \u2014 LINE \uAE30\uBC18 Q&A, \uAE30\uB85D, \uB9AC\uB9C8\uC778\uB354"
|
|
1303
|
-
},
|
|
1304
|
-
"status": {
|
|
1305
|
-
"active": "\uD65C\uC131",
|
|
1306
|
-
"coming": "\uC900\uBE44 \uC911"
|
|
1307
|
-
}
|
|
1308
|
-
}
|
|
1309
|
-
},
|
|
1310
|
-
"ja": {
|
|
1311
|
-
"nav": {
|
|
1312
|
-
"home": "\u30DB\u30FC\u30E0",
|
|
1313
|
-
"projects": "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8",
|
|
1314
|
-
"blog": "\u30D6\u30ED\u30B0",
|
|
1315
|
-
"navigation": "\u30E1\u30A4\u30F3\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3",
|
|
1316
|
-
"menu": "\u30E1\u30CB\u30E5\u30FC",
|
|
1317
|
-
"closeMenu": "\u30E1\u30CB\u30E5\u30FC\u3092\u9589\u3058\u308B"
|
|
1318
|
-
},
|
|
1319
|
-
"theme": {
|
|
1320
|
-
"switchToLight": "\u30E9\u30A4\u30C8\u30C6\u30FC\u30DE\u306B\u5207\u308A\u66FF\u3048\u308B",
|
|
1321
|
-
"switchToDark": "\u30C0\u30FC\u30AF\u30C6\u30FC\u30DE\u306B\u5207\u308A\u66FF\u3048\u308B"
|
|
1322
|
-
},
|
|
1323
|
-
"locale": {
|
|
1324
|
-
"switchLabel": "\u8A00\u8A9E"
|
|
1325
|
-
},
|
|
1326
|
-
"projects": {
|
|
1327
|
-
"cc": {
|
|
1328
|
-
"name": "Content Collector",
|
|
1329
|
-
"description": "RSS\u3001YouTube\u3001Reddit\u306E\u81EA\u52D5\u53CE\u96C6 + AI\u8981\u7D04"
|
|
1330
|
-
},
|
|
1331
|
-
"pkm": {
|
|
1332
|
-
"name": "PKM",
|
|
1333
|
-
"description": "\u500B\u4EBA\u30CA\u30EC\u30C3\u30B8\u7BA1\u7406 \u2014 \u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u89E3\u6790\u3001\u57CB\u3081\u8FBC\u307F\u3001\u30BB\u30DE\u30F3\u30C6\u30A3\u30C3\u30AF\u691C\u7D22"
|
|
1334
|
-
},
|
|
1335
|
-
"naeilUi": {
|
|
1336
|
-
"name": "naeil-ui",
|
|
1337
|
-
"description": "\u30DF\u30CB\u30DE\u30EB\u30C7\u30B6\u30A4\u30F3\u30B7\u30B9\u30C6\u30E0 \u2014 OKLCH\u30C8\u30FC\u30AF\u30F3\u3001Tailwind v4\u3001shadcn"
|
|
1338
|
-
},
|
|
1339
|
-
"sa": {
|
|
1340
|
-
"name": "Sustainability Analyzer",
|
|
1341
|
-
"description": "ESG\u30EC\u30DD\u30FC\u30C8AI\u5206\u6790 \u2014 PDF\u89E3\u6790\u3001\u5B9A\u6027\u8A55\u4FA1\u3001\u6BD4\u8F03\u8868\u306E\u81EA\u52D5\u751F\u6210"
|
|
1342
|
-
},
|
|
1343
|
-
"babyAgent": {
|
|
1344
|
-
"name": "Baby Agent",
|
|
1345
|
-
"description": "\u80B2\u5150AI\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8 \u2014 LINE Q&A\u3001\u8A18\u9332\u3001\u30EA\u30DE\u30A4\u30F3\u30C0\u30FC"
|
|
1346
|
-
},
|
|
1347
|
-
"status": {
|
|
1348
|
-
"active": "\u30A2\u30AF\u30C6\u30A3\u30D6",
|
|
1349
|
-
"coming": "\u6E96\u5099\u4E2D"
|
|
1350
|
-
}
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
};
|
|
1354
|
-
|
|
1355
|
-
// src/components/naeil-header.tsx
|
|
1356
|
-
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
1357
|
-
var subscribe = () => () => {
|
|
1358
|
-
};
|
|
1359
|
-
function NaeilHeaderThemeControl({ locale }) {
|
|
1360
|
-
const { resolvedTheme, setTheme } = useTheme();
|
|
1361
|
-
const mounted = useSyncExternalStore(subscribe, () => true, () => false);
|
|
1362
|
-
const dark = mounted && resolvedTheme === "dark";
|
|
1363
|
-
return /* @__PURE__ */ jsx3(
|
|
1364
|
-
Button,
|
|
1365
|
-
{
|
|
1366
|
-
variant: "ghost",
|
|
1367
|
-
size: "icon",
|
|
1368
|
-
className: "size-11 shrink-0",
|
|
1369
|
-
disabled: !mounted,
|
|
1370
|
-
"aria-label": headerContent[locale].theme[dark ? "switchToLight" : "switchToDark"],
|
|
1371
|
-
onClick: () => setTheme(dark ? "light" : "dark"),
|
|
1372
|
-
children: dark ? /* @__PURE__ */ jsx3(Sun, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx3(Moon, { "aria-hidden": "true" })
|
|
1373
|
-
}
|
|
1374
|
-
);
|
|
1375
|
-
}
|
|
1376
|
-
function NaeilHeaderLocaleControl({ locale, onLocaleChange }) {
|
|
1377
|
-
return /* @__PURE__ */ jsxs3(Select, { value: locale, onValueChange: (value) => onLocaleChange(value), children: [
|
|
1378
|
-
/* @__PURE__ */ jsx3(
|
|
1379
|
-
SelectTrigger,
|
|
1380
|
-
{
|
|
1381
|
-
className: "h-11 w-auto min-w-20 border-transparent bg-transparent px-2",
|
|
1382
|
-
"aria-label": headerContent[locale].locale.switchLabel,
|
|
1383
|
-
children: /* @__PURE__ */ jsx3(SelectValue, { children: locale.toUpperCase() })
|
|
1384
|
-
}
|
|
1385
|
-
),
|
|
1386
|
-
/* @__PURE__ */ jsx3(SelectContent, { align: "end", children: headerLocales.map((value) => /* @__PURE__ */ jsx3(SelectItem, { value, className: "min-h-11", lang: value, children: headerLocaleNames[value] }, value)) })
|
|
1387
|
-
] });
|
|
1388
|
-
}
|
|
1389
|
-
var NativeLink = (props) => /* @__PURE__ */ jsx3("a", __spreadValues({}, props));
|
|
1390
|
-
function NaeilHeader(_a) {
|
|
1391
|
-
var _b = _a, {
|
|
1392
|
-
locale,
|
|
1393
|
-
resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
|
|
1394
|
-
brandHref,
|
|
1395
|
-
brandSlot,
|
|
1396
|
-
brandLinkProps,
|
|
1397
|
-
brandLinkComponent,
|
|
1398
|
-
onLocaleChange,
|
|
1399
|
-
authSlot,
|
|
1400
|
-
toolbarSlot,
|
|
1401
|
-
projects,
|
|
1402
|
-
projectsExternal = false,
|
|
1403
|
-
translations,
|
|
1404
|
-
showProjects = true,
|
|
1405
|
-
showBlog = true,
|
|
1406
|
-
subNav,
|
|
1407
|
-
currentProjectKey,
|
|
1408
|
-
currentProjectHref,
|
|
1409
|
-
labels,
|
|
1410
|
-
Link = NativeLink,
|
|
1411
|
-
currentHref,
|
|
1412
|
-
onNavigate,
|
|
1413
|
-
className,
|
|
1414
|
-
containerClassName
|
|
1415
|
-
} = _b, props = __objRest(_b, [
|
|
1416
|
-
"locale",
|
|
1417
|
-
"resolveHref",
|
|
1418
|
-
"brandHref",
|
|
1419
|
-
"brandSlot",
|
|
1420
|
-
"brandLinkProps",
|
|
1421
|
-
"brandLinkComponent",
|
|
1422
|
-
"onLocaleChange",
|
|
1423
|
-
"authSlot",
|
|
1424
|
-
"toolbarSlot",
|
|
1425
|
-
"projects",
|
|
1426
|
-
"projectsExternal",
|
|
1427
|
-
"translations",
|
|
1428
|
-
"showProjects",
|
|
1429
|
-
"showBlog",
|
|
1430
|
-
"subNav",
|
|
1431
|
-
"currentProjectKey",
|
|
1432
|
-
"currentProjectHref",
|
|
1433
|
-
"labels",
|
|
1434
|
-
"Link",
|
|
1435
|
-
"currentHref",
|
|
1436
|
-
"onNavigate",
|
|
1437
|
-
"className",
|
|
1438
|
-
"containerClassName"
|
|
1439
|
-
]);
|
|
1440
|
-
var _b2, _c;
|
|
1441
|
-
const content = headerContent[locale];
|
|
1442
|
-
const projectLinks = !showProjects ? [] : projects != null ? projects : headerProjects.map((project) => {
|
|
1443
|
-
var _a3, _b3, _c2;
|
|
1444
|
-
const current = project.key === currentProjectKey;
|
|
1445
|
-
return {
|
|
1446
|
-
id: project.key,
|
|
1447
|
-
label: (_a3 = translations == null ? void 0 : translations.project(`${project.key}.name`)) != null ? _a3 : content.projects[project.key].name,
|
|
1448
|
-
description: (_b3 = translations == null ? void 0 : translations.project(`${project.key}.description`)) != null ? _b3 : content.projects[project.key].description,
|
|
1449
|
-
href: current ? currentProjectHref || "/" : resolveHref(project.href),
|
|
1450
|
-
external: !current && projectsExternal,
|
|
1451
|
-
active: current || currentHref === project.href || (currentHref == null ? void 0 : currentHref.startsWith(`${project.href}/`)) || currentHref === resolveHref(project.href),
|
|
1452
|
-
icon: /* @__PURE__ */ jsx3("span", { className: "naeil-header-project-icon", style: {
|
|
1453
|
-
borderColor: `color-mix(in oklch, ${project.accent} 30%, transparent)`,
|
|
1454
|
-
backgroundColor: `color-mix(in oklch, ${project.accent} 8%, transparent)`
|
|
1455
|
-
}, children: /* @__PURE__ */ jsx3("img", { src: `https://naeil.dev/images/${project.icon}.png`, alt: "", width: 24, height: 24 }) }),
|
|
1456
|
-
badge: project.status === "coming" ? /* @__PURE__ */ jsx3(Badge, { variant: "outline", children: (_c2 = translations == null ? void 0 : translations.project("status.coming")) != null ? _c2 : content.projects.status.coming }) : void 0
|
|
1457
|
-
};
|
|
1458
|
-
});
|
|
1459
|
-
const brandDestination = brandHref != null ? brandHref : resolveHref("/");
|
|
1460
|
-
const BrandLink = brandLinkComponent != null ? brandLinkComponent : Link;
|
|
1461
|
-
const _a2 = brandLinkProps != null ? brandLinkProps : {}, { onClick: onBrandClick } = _a2, brandProps = __objRest(_a2, ["onClick"]);
|
|
1462
|
-
const toolbar = /* @__PURE__ */ jsx3("div", { "data-app-toolbar": true, className: "naeil-header-controls", children: toolbarSlot !== void 0 ? toolbarSlot : /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
1463
|
-
/* @__PURE__ */ jsx3(NaeilHeaderThemeControl, { locale }),
|
|
1464
|
-
onLocaleChange && /* @__PURE__ */ jsx3(NaeilHeaderLocaleControl, { locale, onLocaleChange }),
|
|
1465
|
-
authSlot && /* @__PURE__ */ jsxs3(Fragment3, { children: [
|
|
1466
|
-
/* @__PURE__ */ jsx3("div", { "aria-hidden": "true", className: "naeil-header-separator" }),
|
|
1467
|
-
authSlot
|
|
1468
|
-
] })
|
|
1469
|
-
] }) });
|
|
1470
|
-
return /* @__PURE__ */ jsx3(
|
|
1471
|
-
Navigation,
|
|
1472
|
-
__spreadProps(__spreadValues({}, props), {
|
|
1473
|
-
"data-global-header": true,
|
|
1474
|
-
"data-naeil-header": true,
|
|
1475
|
-
Link,
|
|
1476
|
-
currentHref,
|
|
1477
|
-
onNavigate,
|
|
1478
|
-
brand: /* @__PURE__ */ jsx3(
|
|
1479
|
-
BrandLink,
|
|
1480
|
-
__spreadProps(__spreadValues({
|
|
1481
|
-
href: brandDestination,
|
|
1482
|
-
"data-app-brand": true,
|
|
1483
|
-
"aria-label": brandSlot == null ? ".naeil" : void 0
|
|
1484
|
-
}, brandProps), {
|
|
1485
|
-
onClick: (event) => {
|
|
1486
|
-
onBrandClick == null ? void 0 : onBrandClick(event);
|
|
1487
|
-
onNavigate == null ? void 0 : onNavigate(event, { id: "brand", href: brandDestination, label: ".naeil" });
|
|
1488
|
-
},
|
|
1489
|
-
children: brandSlot != null ? brandSlot : /* @__PURE__ */ jsx3(Logo, { variant: "horizontal", size: 28, className: "block", label: null })
|
|
1490
|
-
})
|
|
1491
|
-
),
|
|
1492
|
-
items: [
|
|
1493
|
-
...showProjects ? [{ id: "projects", label: (_b2 = translations == null ? void 0 : translations.projects) != null ? _b2 : content.nav.projects, items: projectLinks, columns: 2 }] : [],
|
|
1494
|
-
...showBlog ? [{ id: "blog", label: (_c = translations == null ? void 0 : translations.blog) != null ? _c : content.nav.blog, href: resolveHref("/blog"), external: projectsExternal }] : [],
|
|
1495
|
-
...(subNav != null ? subNav : []).map((item) => __spreadProps(__spreadValues({}, item), { id: item.href }))
|
|
1496
|
-
],
|
|
1497
|
-
labels: labels != null ? labels : { navigation: content.nav.navigation, menu: content.nav.menu, close: content.nav.closeMenu },
|
|
1498
|
-
toolbar,
|
|
1499
|
-
mobileToolbar: toolbar,
|
|
1500
|
-
className: cn("naeil-header fixed top-0 w-full", className),
|
|
1501
|
-
containerClassName: cn("naeil-header-frame", containerClassName)
|
|
1502
|
-
})
|
|
1503
|
-
);
|
|
1504
|
-
}
|
|
1167
|
+
// src/lib/ui-release.ts
|
|
1168
|
+
var uiRelease = { version: "0.7.2", contractVersion: "1" };
|
|
1505
1169
|
|
|
1506
1170
|
export {
|
|
1507
1171
|
Logo,
|
|
1508
|
-
|
|
1509
|
-
NaeilHeaderThemeControl,
|
|
1510
|
-
NaeilHeaderLocaleControl,
|
|
1511
|
-
NaeilHeader
|
|
1172
|
+
uiRelease
|
|
1512
1173
|
};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
__objRest,
|
|
4
|
+
__spreadProps,
|
|
5
|
+
__spreadValues,
|
|
6
|
+
cn
|
|
7
|
+
} from "./chunk-JBTDRVZ7.js";
|
|
8
|
+
|
|
9
|
+
// src/components/ui/site-footer.tsx
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
function SiteFooter(_a) {
|
|
12
|
+
var _b = _a, {
|
|
13
|
+
brand,
|
|
14
|
+
description,
|
|
15
|
+
groups = [],
|
|
16
|
+
Link,
|
|
17
|
+
meta,
|
|
18
|
+
children,
|
|
19
|
+
containerClassName,
|
|
20
|
+
className,
|
|
21
|
+
variant = "full",
|
|
22
|
+
onNavigate
|
|
23
|
+
} = _b, props = __objRest(_b, [
|
|
24
|
+
"brand",
|
|
25
|
+
"description",
|
|
26
|
+
"groups",
|
|
27
|
+
"Link",
|
|
28
|
+
"meta",
|
|
29
|
+
"children",
|
|
30
|
+
"containerClassName",
|
|
31
|
+
"className",
|
|
32
|
+
"variant",
|
|
33
|
+
"onNavigate"
|
|
34
|
+
]);
|
|
35
|
+
return /* @__PURE__ */ jsx(
|
|
36
|
+
"footer",
|
|
37
|
+
__spreadProps(__spreadValues({
|
|
38
|
+
"data-slot": "site-footer",
|
|
39
|
+
"data-variant": variant,
|
|
40
|
+
className: cn("ui-site-footer", className)
|
|
41
|
+
}, props), {
|
|
42
|
+
children: /* @__PURE__ */ jsxs("div", { className: cn("ui-site-footer-frame", containerClassName), children: [
|
|
43
|
+
/* @__PURE__ */ jsxs("div", { className: "ui-site-footer-brand", children: [
|
|
44
|
+
brand,
|
|
45
|
+
description && /* @__PURE__ */ jsx("div", { className: "ui-site-footer-description", children: description }),
|
|
46
|
+
children
|
|
47
|
+
] }),
|
|
48
|
+
groups.map((group) => /* @__PURE__ */ jsxs("nav", { "aria-label": group.label, children: [
|
|
49
|
+
/* @__PURE__ */ jsx("h2", { className: "ui-site-footer-label", children: group.label }),
|
|
50
|
+
group.links.map((item) => {
|
|
51
|
+
const Component = !item.external && Link ? Link : "a";
|
|
52
|
+
return /* @__PURE__ */ jsx(
|
|
53
|
+
Component,
|
|
54
|
+
{
|
|
55
|
+
href: item.href,
|
|
56
|
+
target: item.target,
|
|
57
|
+
rel: item.target === "_blank" ? "noopener noreferrer" : void 0,
|
|
58
|
+
className: "ui-site-footer-link ui-focus",
|
|
59
|
+
onClick: (event) => onNavigate == null ? void 0 : onNavigate(event, item),
|
|
60
|
+
children: item.label
|
|
61
|
+
},
|
|
62
|
+
item.id
|
|
63
|
+
);
|
|
64
|
+
})
|
|
65
|
+
] }, group.id)),
|
|
66
|
+
meta && /* @__PURE__ */ jsx("div", { className: "ui-site-footer-meta", children: meta })
|
|
67
|
+
] })
|
|
68
|
+
})
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export {
|
|
73
|
+
SiteFooter
|
|
74
|
+
};
|