@naeil/ui 0.5.0 → 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/DESIGN.md +7 -3
- package/README.md +19 -10
- package/contracts/naeil-chrome.v1.json +12 -0
- package/dist/chunk-HSTDPY56.js +74 -0
- package/dist/chunk-OLKTEYLS.js +413 -0
- package/dist/{chunk-CE73AEJZ.js → chunk-QQQQZEPV.js} +249 -3
- package/dist/{chunk-S64H3OYQ.js → chunk-VWIUN35X.js} +4 -343
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.js +11 -9
- 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/footer.js +1 -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.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 -1
- package/docs/components/application-layout.md +103 -0
- package/docs/components/common.md +2 -2
- package/docs/components/naeil-footer.md +20 -0
- package/docs/components/naeil-header.md +22 -6
- package/docs/components/navigation.md +8 -8
- package/docs/design/v2-migration.md +24 -25
- package/docs/package-release.md +12 -6
- package/package.json +16 -4
- package/src/styles/components.css +39 -4
- package/src/styles/theme.css +3 -1
- package/dist/chunk-QSTGUEEI.js +0 -323
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { S as SiteFooterProps } from '../site-footer-vXDa_6yr.js';
|
|
3
|
+
import { N as NaeilHeaderLocale } from '../naeil-header-content-BvISJ4RV.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
import '../navigation-CgPeL9tF.js';
|
|
6
|
+
|
|
7
|
+
type NaeilFooterLocale = NaeilHeaderLocale;
|
|
8
|
+
interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description" | "groups"> {
|
|
9
|
+
locale: NaeilFooterLocale;
|
|
10
|
+
/** Only localize/route canonical paths; default destinations use the official origin. */
|
|
11
|
+
resolveHref?: (path: string) => string;
|
|
12
|
+
}
|
|
13
|
+
/** Canonical content in full/compact density. Product legal/status copy belongs in meta. */
|
|
14
|
+
declare function NaeilFooter({ locale, resolveHref, variant, Link, onNavigate, ...props }: NaeilFooterProps): react_jsx_runtime.JSX.Element;
|
|
15
|
+
|
|
16
|
+
export { NaeilFooter, type NaeilFooterLocale, type NaeilFooterProps };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
"use client";
|
|
3
|
+
import {
|
|
4
|
+
Logo,
|
|
5
|
+
uiRelease
|
|
6
|
+
} from "../chunk-VWIUN35X.js";
|
|
7
|
+
import {
|
|
8
|
+
SiteFooter
|
|
9
|
+
} from "../chunk-HSTDPY56.js";
|
|
10
|
+
import {
|
|
11
|
+
__objRest,
|
|
12
|
+
__spreadProps,
|
|
13
|
+
__spreadValues
|
|
14
|
+
} from "../chunk-JBTDRVZ7.js";
|
|
15
|
+
|
|
16
|
+
// src/components/naeil-footer.tsx
|
|
17
|
+
import { jsx } from "react/jsx-runtime";
|
|
18
|
+
var content = {
|
|
19
|
+
en: { navigation: "Navigation", projects: "Projects", blog: "Blog", social: "Social" },
|
|
20
|
+
ko: { navigation: "\uB124\uBE44\uAC8C\uC774\uC158", projects: "\uD504\uB85C\uC81D\uD2B8", blog: "\uBE14\uB85C\uADF8", social: "\uC18C\uC15C" },
|
|
21
|
+
ja: { navigation: "\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3", projects: "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8", blog: "\u30D6\u30ED\u30B0", social: "\u30BD\u30FC\u30B7\u30E3\u30EB" }
|
|
22
|
+
};
|
|
23
|
+
var NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
|
|
24
|
+
function NaeilFooter(_a) {
|
|
25
|
+
var _b = _a, {
|
|
26
|
+
locale,
|
|
27
|
+
resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
|
|
28
|
+
variant = "full",
|
|
29
|
+
Link = NativeLink,
|
|
30
|
+
onNavigate
|
|
31
|
+
} = _b, props = __objRest(_b, [
|
|
32
|
+
"locale",
|
|
33
|
+
"resolveHref",
|
|
34
|
+
"variant",
|
|
35
|
+
"Link",
|
|
36
|
+
"onNavigate"
|
|
37
|
+
]);
|
|
38
|
+
const copy = content[locale];
|
|
39
|
+
const home = { id: "brand", label: ".naeil", href: resolveHref("/") };
|
|
40
|
+
return /* @__PURE__ */ jsx(
|
|
41
|
+
SiteFooter,
|
|
42
|
+
__spreadProps(__spreadValues({}, props), {
|
|
43
|
+
variant,
|
|
44
|
+
Link,
|
|
45
|
+
onNavigate,
|
|
46
|
+
"data-naeil-footer": true,
|
|
47
|
+
"data-naeil-ui-version": uiRelease.version,
|
|
48
|
+
"data-naeil-ui-contract": uiRelease.contractVersion,
|
|
49
|
+
brand: /* @__PURE__ */ jsx(
|
|
50
|
+
Link,
|
|
51
|
+
{
|
|
52
|
+
href: home.href,
|
|
53
|
+
"aria-label": ".naeil",
|
|
54
|
+
"data-footer-brand": true,
|
|
55
|
+
className: "ui-focus inline-flex min-h-11 items-center",
|
|
56
|
+
onClick: (event) => onNavigate == null ? void 0 : onNavigate(event, home),
|
|
57
|
+
children: /* @__PURE__ */ jsx(Logo, { variant: "footer", size: 20, label: null })
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
description: variant === "full" ? "Tomorrow starts here." : void 0,
|
|
61
|
+
groups: [
|
|
62
|
+
{ id: "navigation", label: copy.navigation, links: [
|
|
63
|
+
{ id: "projects", label: copy.projects, href: resolveHref("/projects") },
|
|
64
|
+
{ id: "blog", label: copy.blog, href: resolveHref("/blog") }
|
|
65
|
+
] },
|
|
66
|
+
{ id: "social", label: copy.social, links: [
|
|
67
|
+
// All canonical destinations use the consumer Link, including this absolute URL.
|
|
68
|
+
{ id: "github", label: "GitHub", href: "https://github.com/naeil-dev", target: "_blank" }
|
|
69
|
+
] }
|
|
70
|
+
]
|
|
71
|
+
})
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
export {
|
|
75
|
+
NaeilFooter
|
|
76
|
+
};
|
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import { a as NavigationProps,
|
|
3
|
+
import { b as NavigationLinkComponent, a as NavigationProps, c as NavigationLinkProps, N as NavigationLink } from '../navigation-CgPeL9tF.js';
|
|
4
|
+
import { N as NaeilHeaderLocale } from '../naeil-header-content-BvISJ4RV.js';
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
type NaeilHeaderAccount = {
|
|
7
|
+
status: "signed-out";
|
|
8
|
+
loginHref: string;
|
|
9
|
+
} | {
|
|
10
|
+
status: "signed-in";
|
|
11
|
+
/** Consumer starts its guarded session action and owns failures/navigation. */
|
|
12
|
+
onLogout: () => void;
|
|
13
|
+
busy?: boolean;
|
|
14
|
+
displayName?: string;
|
|
15
|
+
email?: string;
|
|
16
|
+
};
|
|
17
|
+
interface NaeilHeaderAccountControlProps {
|
|
18
|
+
locale: NaeilHeaderLocale;
|
|
19
|
+
account: NaeilHeaderAccount;
|
|
20
|
+
/** The same route/save adapter used by the rest of the application header. */
|
|
21
|
+
Link?: NavigationLinkComponent;
|
|
22
|
+
}
|
|
23
|
+
/** Shared account presentation only: never reads sessions or calls an auth API. */
|
|
24
|
+
declare function NaeilHeaderAccountControl({ locale, account, Link }: NaeilHeaderAccountControlProps): react_jsx_runtime.JSX.Element;
|
|
7
25
|
|
|
8
26
|
interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
|
|
9
27
|
locale: NaeilHeaderLocale;
|
|
@@ -14,7 +32,7 @@ interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "to
|
|
|
14
32
|
brandLinkProps?: Omit<NavigationLinkProps, "href" | "children">;
|
|
15
33
|
/** Omit when the application does not support changing its UI language. */
|
|
16
34
|
onLocaleChange?: (locale: NaeilHeaderLocale) => void;
|
|
17
|
-
/**
|
|
35
|
+
/** Use NaeilHeaderAccountControl for canonical UI; the app owns auth state/I/O. */
|
|
18
36
|
authSlot?: ReactNode;
|
|
19
37
|
labels?: NavigationProps["labels"];
|
|
20
38
|
projects?: NavigationLink[];
|
|
@@ -51,4 +69,4 @@ declare function NaeilHeaderLocaleControl({ locale, onLocaleChange }: {
|
|
|
51
69
|
/** One complete, opt-in branded composition shared by naeil.dev and applications. */
|
|
52
70
|
declare function NaeilHeader({ locale, resolveHref, brandHref, brandSlot, brandLinkProps, brandLinkComponent, onLocaleChange, authSlot, toolbarSlot, projects, projectsExternal, translations, showProjects, showBlog, subNav, currentProjectKey, currentProjectHref, labels, Link, currentHref, onNavigate, className, containerClassName, ...props }: NaeilHeaderProps): react_jsx_runtime.JSX.Element;
|
|
53
71
|
|
|
54
|
-
export { NaeilHeader, type NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };
|
|
72
|
+
export { NaeilHeader, type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps, NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };
|
|
@@ -2,13 +2,16 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
import {
|
|
4
4
|
NaeilHeader,
|
|
5
|
+
NaeilHeaderAccountControl,
|
|
5
6
|
NaeilHeaderLocaleControl,
|
|
6
7
|
NaeilHeaderThemeControl
|
|
7
|
-
} from "../chunk-
|
|
8
|
-
import "../chunk-
|
|
8
|
+
} from "../chunk-OLKTEYLS.js";
|
|
9
|
+
import "../chunk-VWIUN35X.js";
|
|
10
|
+
import "../chunk-QQQQZEPV.js";
|
|
9
11
|
import "../chunk-JBTDRVZ7.js";
|
|
10
12
|
export {
|
|
11
13
|
NaeilHeader,
|
|
14
|
+
NaeilHeaderAccountControl,
|
|
12
15
|
NaeilHeaderLocaleControl,
|
|
13
16
|
NaeilHeaderThemeControl
|
|
14
17
|
};
|
|
@@ -4,8 +4,8 @@ import { Avatar as Avatar$1, Dialog as Dialog$1, DropdownMenu as DropdownMenu$1,
|
|
|
4
4
|
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
5
5
|
import { VariantProps } from 'class-variance-authority';
|
|
6
6
|
import { ToasterProps } from 'sonner';
|
|
7
|
-
export { d as Navigation, e as NavigationGroup, f as NavigationItem, N as NavigationLink,
|
|
8
|
-
export { a as SiteFooter, S as SiteFooterProps } from '../../site-footer-
|
|
7
|
+
export { d as Navigation, e as NavigationGroup, f as NavigationItem, N as NavigationLink, b as NavigationLinkComponent, c as NavigationLinkProps, a as NavigationProps } from '../../navigation-CgPeL9tF.js';
|
|
8
|
+
export { a as SiteFooter, S as SiteFooterProps } from '../../site-footer-vXDa_6yr.js';
|
|
9
9
|
|
|
10
10
|
declare function Avatar({ className, size, ...props }: React.ComponentProps<typeof Avatar$1.Root> & {
|
|
11
11
|
size?: "default" | "sm" | "lg";
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
|
+
SiteFooter
|
|
4
|
+
} from "../../chunk-HSTDPY56.js";
|
|
5
|
+
import {
|
|
6
|
+
Badge,
|
|
7
|
+
Button,
|
|
3
8
|
DropdownMenu,
|
|
4
9
|
DropdownMenuCheckboxItem,
|
|
5
10
|
DropdownMenuContent,
|
|
@@ -15,11 +20,6 @@ import {
|
|
|
15
20
|
DropdownMenuSubContent,
|
|
16
21
|
DropdownMenuSubTrigger,
|
|
17
22
|
DropdownMenuTrigger,
|
|
18
|
-
SiteFooter
|
|
19
|
-
} from "../../chunk-QSTGUEEI.js";
|
|
20
|
-
import {
|
|
21
|
-
Badge,
|
|
22
|
-
Button,
|
|
23
23
|
Navigation,
|
|
24
24
|
Select,
|
|
25
25
|
SelectContent,
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
SelectValue,
|
|
34
34
|
badgeVariants,
|
|
35
35
|
buttonVariants
|
|
36
|
-
} from "../../chunk-
|
|
36
|
+
} from "../../chunk-QQQQZEPV.js";
|
|
37
37
|
import {
|
|
38
38
|
__objRest,
|
|
39
39
|
__spreadProps,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const uiRelease: Readonly<{version: "0.7.1"; contractVersion: "1"}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const uiRelease = Object.freeze({"version":"0.7.1","contractVersion":"1"});
|
|
@@ -45,4 +45,4 @@ interface NavigationProps extends Omit<React.ComponentPropsWithoutRef<"header">,
|
|
|
45
45
|
}
|
|
46
46
|
declare function Navigation({ brand, items, labels, Link, currentHref, toolbar, mobileToolbar, mobileFooter, containerClassName, onNavigate, className, ...props }: NavigationProps): react_jsx_runtime.JSX.Element;
|
|
47
47
|
|
|
48
|
-
export { type NavigationLink as N, type NavigationProps as a, type
|
|
48
|
+
export { type NavigationLink as N, type NavigationProps as a, type NavigationLinkComponent as b, type NavigationLinkProps as c, Navigation as d, type NavigationGroup as e, type NavigationItem as f };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { N as NavigationLink,
|
|
3
|
+
import { N as NavigationLink, b as NavigationLinkComponent, a as NavigationProps } from './navigation-CgPeL9tF.js';
|
|
4
4
|
|
|
5
5
|
interface SiteFooterProps extends React.ComponentPropsWithoutRef<"footer"> {
|
|
6
6
|
brand?: React.ReactNode;
|
|
@@ -14,8 +14,10 @@ interface SiteFooterProps extends React.ComponentPropsWithoutRef<"footer"> {
|
|
|
14
14
|
meta?: React.ReactNode;
|
|
15
15
|
containerClassName?: string;
|
|
16
16
|
variant?: "full" | "compact";
|
|
17
|
+
/** Called for every group link, including native external anchors. Preserve modified clicks. */
|
|
18
|
+
onNavigate?: NavigationProps["onNavigate"];
|
|
17
19
|
}
|
|
18
20
|
/** Product content and translations belong to the consumer, including legal copy. */
|
|
19
|
-
declare function SiteFooter({ brand, description, groups, Link, meta, children, containerClassName, className, variant, ...props }: SiteFooterProps): react_jsx_runtime.JSX.Element;
|
|
21
|
+
declare function SiteFooter({ brand, description, groups, Link, meta, children, containerClassName, className, variant, onNavigate, ...props }: SiteFooterProps): react_jsx_runtime.JSX.Element;
|
|
20
22
|
|
|
21
23
|
export { type SiteFooterProps as S, SiteFooter as a };
|
|
@@ -22,7 +22,6 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
22
22
|
import { useTranslations } from "next-intl";
|
|
23
23
|
import { Logo } from "./logo.js";
|
|
24
24
|
import { SiteFooter } from "./ui/site-footer.js";
|
|
25
|
-
import { cn } from "../lib/utils.js";
|
|
26
25
|
function Footer({
|
|
27
26
|
Link,
|
|
28
27
|
linksExternal = false,
|
|
@@ -45,7 +44,7 @@ function Footer({
|
|
|
45
44
|
{
|
|
46
45
|
Link,
|
|
47
46
|
className,
|
|
48
|
-
containerClassName
|
|
47
|
+
containerClassName,
|
|
49
48
|
variant,
|
|
50
49
|
brand: brandSlot != null ? brandSlot : /* @__PURE__ */ jsx(Logo, { variant: "footer", size: 20, className: "block" }),
|
|
51
50
|
description: description === void 0 ? t("tagline") : description,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { SiteFooterProps } from './ui/site-footer.js';
|
|
3
|
+
import { NaeilHeaderLocale } from './naeil-header-content.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
import './ui/navigation.js';
|
|
6
|
+
|
|
7
|
+
type NaeilFooterLocale = NaeilHeaderLocale;
|
|
8
|
+
interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description" | "groups"> {
|
|
9
|
+
locale: NaeilFooterLocale;
|
|
10
|
+
/** Only localize/route canonical paths; default destinations use the official origin. */
|
|
11
|
+
resolveHref?: (path: string) => string;
|
|
12
|
+
}
|
|
13
|
+
/** Canonical content in full/compact density. Product legal/status copy belongs in meta. */
|
|
14
|
+
declare function NaeilFooter({ locale, resolveHref, variant, Link, onNavigate, ...props }: NaeilFooterProps): react_jsx_runtime.JSX.Element;
|
|
15
|
+
|
|
16
|
+
export { NaeilFooter, type NaeilFooterLocale, type NaeilFooterProps };
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
|
+
var __objRest = (source, exclude) => {
|
|
22
|
+
var target = {};
|
|
23
|
+
for (var prop in source)
|
|
24
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
25
|
+
target[prop] = source[prop];
|
|
26
|
+
if (source != null && __getOwnPropSymbols)
|
|
27
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
28
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
}
|
|
31
|
+
return target;
|
|
32
|
+
};
|
|
33
|
+
import { jsx } from "react/jsx-runtime";
|
|
34
|
+
import { Logo } from "./logo.js";
|
|
35
|
+
import { SiteFooter } from "./ui/site-footer.js";
|
|
36
|
+
import { uiRelease } from "../lib/ui-release.js";
|
|
37
|
+
const content = {
|
|
38
|
+
en: { navigation: "Navigation", projects: "Projects", blog: "Blog", social: "Social" },
|
|
39
|
+
ko: { navigation: "\uB124\uBE44\uAC8C\uC774\uC158", projects: "\uD504\uB85C\uC81D\uD2B8", blog: "\uBE14\uB85C\uADF8", social: "\uC18C\uC15C" },
|
|
40
|
+
ja: { navigation: "\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3", projects: "\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8", blog: "\u30D6\u30ED\u30B0", social: "\u30BD\u30FC\u30B7\u30E3\u30EB" }
|
|
41
|
+
};
|
|
42
|
+
const NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
|
|
43
|
+
function NaeilFooter(_a) {
|
|
44
|
+
var _b = _a, {
|
|
45
|
+
locale,
|
|
46
|
+
resolveHref = (path) => `https://naeil.dev/${locale}${path === "/" ? "" : path}`,
|
|
47
|
+
variant = "full",
|
|
48
|
+
Link = NativeLink,
|
|
49
|
+
onNavigate
|
|
50
|
+
} = _b, props = __objRest(_b, [
|
|
51
|
+
"locale",
|
|
52
|
+
"resolveHref",
|
|
53
|
+
"variant",
|
|
54
|
+
"Link",
|
|
55
|
+
"onNavigate"
|
|
56
|
+
]);
|
|
57
|
+
const copy = content[locale];
|
|
58
|
+
const home = { id: "brand", label: ".naeil", href: resolveHref("/") };
|
|
59
|
+
return /* @__PURE__ */ jsx(
|
|
60
|
+
SiteFooter,
|
|
61
|
+
__spreadProps(__spreadValues({}, props), {
|
|
62
|
+
variant,
|
|
63
|
+
Link,
|
|
64
|
+
onNavigate,
|
|
65
|
+
"data-naeil-footer": true,
|
|
66
|
+
"data-naeil-ui-version": uiRelease.version,
|
|
67
|
+
"data-naeil-ui-contract": uiRelease.contractVersion,
|
|
68
|
+
brand: /* @__PURE__ */ jsx(
|
|
69
|
+
Link,
|
|
70
|
+
{
|
|
71
|
+
href: home.href,
|
|
72
|
+
"aria-label": ".naeil",
|
|
73
|
+
"data-footer-brand": true,
|
|
74
|
+
className: "ui-focus inline-flex min-h-11 items-center",
|
|
75
|
+
onClick: (event) => onNavigate == null ? void 0 : onNavigate(event, home),
|
|
76
|
+
children: /* @__PURE__ */ jsx(Logo, { variant: "footer", size: 20, label: null })
|
|
77
|
+
}
|
|
78
|
+
),
|
|
79
|
+
description: variant === "full" ? "Tomorrow starts here." : void 0,
|
|
80
|
+
groups: [
|
|
81
|
+
{ id: "navigation", label: copy.navigation, links: [
|
|
82
|
+
{ id: "projects", label: copy.projects, href: resolveHref("/projects") },
|
|
83
|
+
{ id: "blog", label: copy.blog, href: resolveHref("/blog") }
|
|
84
|
+
] },
|
|
85
|
+
{ id: "social", label: copy.social, links: [
|
|
86
|
+
// All canonical destinations use the consumer Link, including this absolute URL.
|
|
87
|
+
{ id: "github", label: "GitHub", href: "https://github.com/naeil-dev", target: "_blank" }
|
|
88
|
+
] }
|
|
89
|
+
]
|
|
90
|
+
})
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
export {
|
|
94
|
+
NaeilFooter
|
|
95
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { NavigationLinkComponent } from './ui/navigation.js';
|
|
3
|
+
import { NaeilHeaderLocale } from './naeil-header-content.js';
|
|
4
|
+
import 'react';
|
|
5
|
+
|
|
6
|
+
type NaeilHeaderAccount = {
|
|
7
|
+
status: "signed-out";
|
|
8
|
+
loginHref: string;
|
|
9
|
+
} | {
|
|
10
|
+
status: "signed-in";
|
|
11
|
+
/** Consumer starts its guarded session action and owns failures/navigation. */
|
|
12
|
+
onLogout: () => void;
|
|
13
|
+
busy?: boolean;
|
|
14
|
+
displayName?: string;
|
|
15
|
+
email?: string;
|
|
16
|
+
};
|
|
17
|
+
interface NaeilHeaderAccountControlProps {
|
|
18
|
+
locale: NaeilHeaderLocale;
|
|
19
|
+
account: NaeilHeaderAccount;
|
|
20
|
+
/** The same route/save adapter used by the rest of the application header. */
|
|
21
|
+
Link?: NavigationLinkComponent;
|
|
22
|
+
}
|
|
23
|
+
/** Shared account presentation only: never reads sessions or calls an auth API. */
|
|
24
|
+
declare function NaeilHeaderAccountControl({ locale, account, Link }: NaeilHeaderAccountControlProps): react_jsx_runtime.JSX.Element;
|
|
25
|
+
|
|
26
|
+
export { type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps };
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
+
var __spreadValues = (a, b) => {
|
|
8
|
+
for (var prop in b || (b = {}))
|
|
9
|
+
if (__hasOwnProp.call(b, prop))
|
|
10
|
+
__defNormalProp(a, prop, b[prop]);
|
|
11
|
+
if (__getOwnPropSymbols)
|
|
12
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
13
|
+
if (__propIsEnum.call(b, prop))
|
|
14
|
+
__defNormalProp(a, prop, b[prop]);
|
|
15
|
+
}
|
|
16
|
+
return a;
|
|
17
|
+
};
|
|
18
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
19
|
+
import { UserRound } from "lucide-react";
|
|
20
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem } from "./ui/dropdown-menu.js";
|
|
21
|
+
const labels = {
|
|
22
|
+
en: { menu: "Account menu", account: "Account", login: "Log in", logout: "Log out", busy: "Logging out\u2026" },
|
|
23
|
+
ko: { menu: "\uACC4\uC815 \uBA54\uB274", account: "\uACC4\uC815", login: "\uB85C\uADF8\uC778", logout: "\uB85C\uADF8\uC544\uC6C3", busy: "\uB85C\uADF8\uC544\uC6C3 \uC911\u2026" },
|
|
24
|
+
ja: { menu: "\u30A2\u30AB\u30A6\u30F3\u30C8\u30E1\u30CB\u30E5\u30FC", account: "\u30A2\u30AB\u30A6\u30F3\u30C8", login: "\u30ED\u30B0\u30A4\u30F3", logout: "\u30ED\u30B0\u30A2\u30A6\u30C8", busy: "\u30ED\u30B0\u30A2\u30A6\u30C8\u4E2D\u2026" }
|
|
25
|
+
};
|
|
26
|
+
const NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
|
|
27
|
+
function NaeilHeaderAccountControl({ locale, account, Link = NativeLink }) {
|
|
28
|
+
const text = labels[locale];
|
|
29
|
+
if (account.status === "signed-out") {
|
|
30
|
+
return /* @__PURE__ */ jsx(Link, { href: account.loginHref, className: "ui-navigation-link ui-focus naeil-header-login", "data-naeil-account-state": "signed-out", children: text.login });
|
|
31
|
+
}
|
|
32
|
+
return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
|
|
33
|
+
/* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
34
|
+
"button",
|
|
35
|
+
{
|
|
36
|
+
type: "button",
|
|
37
|
+
className: "ui-focus naeil-header-account-trigger",
|
|
38
|
+
"data-naeil-account-trigger": true,
|
|
39
|
+
"data-naeil-account-state": "signed-in",
|
|
40
|
+
"aria-label": text.menu,
|
|
41
|
+
"aria-busy": account.busy || void 0,
|
|
42
|
+
children: /* @__PURE__ */ jsx("span", { className: "naeil-header-account-avatar", "aria-hidden": "true", children: /* @__PURE__ */ jsx(UserRound, {}) })
|
|
43
|
+
}
|
|
44
|
+
) }),
|
|
45
|
+
/* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-56 max-w-[calc(100vw-2rem)]", "data-naeil-account-menu": true, children: [
|
|
46
|
+
/* @__PURE__ */ jsxs(DropdownMenuLabel, { className: "flex min-w-0 flex-col font-normal", children: [
|
|
47
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-base font-medium", children: account.displayName || text.account }),
|
|
48
|
+
account.email && /* @__PURE__ */ jsx("span", { className: "truncate text-sm text-muted-foreground", children: account.email })
|
|
49
|
+
] }),
|
|
50
|
+
/* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
51
|
+
/* @__PURE__ */ jsx(
|
|
52
|
+
DropdownMenuItem,
|
|
53
|
+
{
|
|
54
|
+
className: "min-h-11",
|
|
55
|
+
disabled: account.busy,
|
|
56
|
+
onSelect: () => {
|
|
57
|
+
if (!account.busy) account.onLogout();
|
|
58
|
+
},
|
|
59
|
+
children: account.busy ? text.busy : text.logout
|
|
60
|
+
}
|
|
61
|
+
)
|
|
62
|
+
] })
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
export {
|
|
66
|
+
NaeilHeaderAccountControl
|
|
67
|
+
};
|
|
@@ -2,6 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { NavigationProps, NavigationLinkProps, NavigationLink, NavigationLinkComponent } from './ui/navigation.js';
|
|
4
4
|
import { NaeilHeaderLocale } from './naeil-header-content.js';
|
|
5
|
+
export { NaeilHeaderAccount, NaeilHeaderAccountControl, NaeilHeaderAccountControlProps } from './naeil-header-account.js';
|
|
5
6
|
|
|
6
7
|
interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
|
|
7
8
|
locale: NaeilHeaderLocale;
|
|
@@ -12,7 +13,7 @@ interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "to
|
|
|
12
13
|
brandLinkProps?: Omit<NavigationLinkProps, "href" | "children">;
|
|
13
14
|
/** Omit when the application does not support changing its UI language. */
|
|
14
15
|
onLocaleChange?: (locale: NaeilHeaderLocale) => void;
|
|
15
|
-
/**
|
|
16
|
+
/** Use NaeilHeaderAccountControl for canonical UI; the app owns auth state/I/O. */
|
|
16
17
|
authSlot?: ReactNode;
|
|
17
18
|
labels?: NavigationProps["labels"];
|
|
18
19
|
projects?: NavigationLink[];
|
|
@@ -40,7 +40,9 @@ import { Button } from "./ui/button.js";
|
|
|
40
40
|
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./ui/select.js";
|
|
41
41
|
import { Navigation } from "./ui/navigation.js";
|
|
42
42
|
import { cn } from "../lib/utils.js";
|
|
43
|
+
import { uiRelease } from "../lib/ui-release.js";
|
|
43
44
|
import { headerContent, headerLocales, headerLocaleNames, headerProjects } from "./naeil-header-content.js";
|
|
45
|
+
import { NaeilHeaderAccountControl } from "./naeil-header-account.js";
|
|
44
46
|
const subscribe = () => () => {
|
|
45
47
|
};
|
|
46
48
|
function NaeilHeaderThemeControl({ locale }) {
|
|
@@ -159,6 +161,8 @@ function NaeilHeader(_a) {
|
|
|
159
161
|
__spreadProps(__spreadValues({}, props), {
|
|
160
162
|
"data-global-header": true,
|
|
161
163
|
"data-naeil-header": true,
|
|
164
|
+
"data-naeil-ui-version": uiRelease.version,
|
|
165
|
+
"data-naeil-ui-contract": uiRelease.contractVersion,
|
|
162
166
|
Link,
|
|
163
167
|
currentHref,
|
|
164
168
|
onNavigate,
|
|
@@ -185,12 +189,13 @@ function NaeilHeader(_a) {
|
|
|
185
189
|
toolbar,
|
|
186
190
|
mobileToolbar: toolbar,
|
|
187
191
|
className: cn("naeil-header fixed top-0 w-full", className),
|
|
188
|
-
containerClassName: cn("naeil-header-frame
|
|
192
|
+
containerClassName: cn("naeil-header-frame", containerClassName)
|
|
189
193
|
})
|
|
190
194
|
);
|
|
191
195
|
}
|
|
192
196
|
export {
|
|
193
197
|
NaeilHeader,
|
|
198
|
+
NaeilHeaderAccountControl,
|
|
194
199
|
NaeilHeaderLocaleControl,
|
|
195
200
|
NaeilHeaderThemeControl
|
|
196
201
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as react from 'react';
|
|
3
|
-
import { NavigationLink, NavigationLinkComponent } from './navigation.js';
|
|
3
|
+
import { NavigationLink, NavigationLinkComponent, NavigationProps } from './navigation.js';
|
|
4
4
|
|
|
5
5
|
interface SiteFooterProps extends react.ComponentPropsWithoutRef<"footer"> {
|
|
6
6
|
brand?: react.ReactNode;
|
|
@@ -14,8 +14,10 @@ interface SiteFooterProps extends react.ComponentPropsWithoutRef<"footer"> {
|
|
|
14
14
|
meta?: react.ReactNode;
|
|
15
15
|
containerClassName?: string;
|
|
16
16
|
variant?: "full" | "compact";
|
|
17
|
+
/** Called for every group link, including native external anchors. Preserve modified clicks. */
|
|
18
|
+
onNavigate?: NavigationProps["onNavigate"];
|
|
17
19
|
}
|
|
18
20
|
/** Product content and translations belong to the consumer, including legal copy. */
|
|
19
|
-
declare function SiteFooter({ brand, description, groups, Link, meta, children, containerClassName, className, variant, ...props }: SiteFooterProps): react_jsx_runtime.JSX.Element;
|
|
21
|
+
declare function SiteFooter({ brand, description, groups, Link, meta, children, containerClassName, className, variant, onNavigate, ...props }: SiteFooterProps): react_jsx_runtime.JSX.Element;
|
|
20
22
|
|
|
21
23
|
export { SiteFooter, type SiteFooterProps };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
var __defProp = Object.defineProperty;
|
|
2
3
|
var __defProps = Object.defineProperties;
|
|
3
4
|
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
@@ -41,7 +42,8 @@ function SiteFooter(_a) {
|
|
|
41
42
|
children,
|
|
42
43
|
containerClassName,
|
|
43
44
|
className,
|
|
44
|
-
variant = "full"
|
|
45
|
+
variant = "full",
|
|
46
|
+
onNavigate
|
|
45
47
|
} = _b, props = __objRest(_b, [
|
|
46
48
|
"brand",
|
|
47
49
|
"description",
|
|
@@ -51,7 +53,8 @@ function SiteFooter(_a) {
|
|
|
51
53
|
"children",
|
|
52
54
|
"containerClassName",
|
|
53
55
|
"className",
|
|
54
|
-
"variant"
|
|
56
|
+
"variant",
|
|
57
|
+
"onNavigate"
|
|
55
58
|
]);
|
|
56
59
|
return /* @__PURE__ */ jsx(
|
|
57
60
|
"footer",
|
|
@@ -77,6 +80,7 @@ function SiteFooter(_a) {
|
|
|
77
80
|
target: item.target,
|
|
78
81
|
rel: item.target === "_blank" ? "noopener noreferrer" : void 0,
|
|
79
82
|
className: "ui-site-footer-link ui-focus",
|
|
83
|
+
onClick: (event) => onNavigate == null ? void 0 : onNavigate(event, item),
|
|
80
84
|
children: item.label
|
|
81
85
|
},
|
|
82
86
|
item.id
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Component usage guides
|
|
2
2
|
|
|
3
|
-
These guides
|
|
3
|
+
These guides include the unpublished **@naeil/ui 0.7.0 candidate**; the last published release is 0.6.0. release identities and publication evidence are recorded in the [release record](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.6.0). [Setup, themes, fonts and shared responsibilities](common.md). Run `pnpm storybook` for the current 17 Docs pages (15 UI and 2 Brand) and choose Docs or Usage. The [hosted Storybook](https://naeil-dev.github.io/naeil-ui/) was last verified for [0.5.0 on 2026-10-15](https://github.com/naeil-dev/naeil-ui/releases/tag/v0.5.0); each subsequent deployment is recorded separately. Select chooses a value; DropdownMenu chooses an action.
|
|
4
|
+
|
|
5
|
+
Start application layouts with the [shared navigation/footer selection and frame guide](application-layout.md). It includes a starter, the 1600px frame contract and instructions to place in consumer repositories so agents reuse the shared implementation.
|
|
4
6
|
|
|
5
7
|
| Family | Guide | Runnable story |
|
|
6
8
|
| --- | --- | --- |
|
|
@@ -19,6 +21,7 @@ These guides target the **@naeil/ui 0.5.0 release candidate**; final archive ver
|
|
|
19
21
|
| Textarea | [Textarea](./textarea.md) | UI / Textarea / Usage |
|
|
20
22
|
| Navigation | [Navigation](./navigation.md) | UI / Navigation / Usage |
|
|
21
23
|
| SiteFooter | [SiteFooter](./navigation.md) | UI / SiteFooter / Usage |
|
|
24
|
+
| NaeilFooter | [NaeilFooter](./naeil-footer.md) | Brand / NaeilHeader / ReferenceFull, ReferenceCompact |
|
|
22
25
|
| NaeilHeader | [NaeilHeader](./naeil-header.md) | Brand / NaeilHeader / Usage, JapaneseApplication |
|
|
23
26
|
|
|
24
27
|
[Field, native radio, Select and action composition](./composition.md) explains consumer state and semantic choices. [Demand decision](../design/component-demand.md) records why these two families were added.
|