@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.
Files changed (61) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +5 -5
  3. package/dist/{chunk-XRO3NJAB.js → chunk-KWEWR46R.js} +40 -154
  4. package/dist/{chunk-JDHGKM25.js → chunk-U3IZCFM4.js} +267 -2
  5. package/dist/components/index.js +12 -3
  6. package/dist/components/naeil-footer.d.ts +3 -3
  7. package/dist/components/naeil-footer.js +14 -11
  8. package/dist/components/naeil-header.d.ts +7 -9
  9. package/dist/components/naeil-header.js +2 -2
  10. package/dist/lib/ui-release.d.ts +1 -1
  11. package/dist/lib/ui-release.js +1 -1
  12. package/dist/naeil-locale/checker.d.ts +16 -0
  13. package/dist/naeil-locale/checker.js +91 -0
  14. package/dist/naeil-locale/chrome.d.ts +150 -0
  15. package/dist/naeil-locale/chrome.js +2385 -0
  16. package/dist/naeil-locale/chunk-4U64K4J3.js +56 -0
  17. package/dist/naeil-locale/chunk-N3ETBM74.js +24 -0
  18. package/dist/naeil-locale/chunk-U65OQHZY.js +167 -0
  19. package/dist/naeil-locale/chunk-YQ5OJWBF.js +53 -0
  20. package/dist/naeil-locale/client.d.ts +70 -0
  21. package/dist/naeil-locale/client.js +388 -0
  22. package/dist/naeil-locale/en-ZC66VDHP.js +86 -0
  23. package/dist/naeil-locale/index.d.ts +40 -0
  24. package/dist/naeil-locale/index.js +111 -0
  25. package/dist/naeil-locale/ja-DKIEQUG7.js +86 -0
  26. package/dist/naeil-locale/ko-CY6663RZ.js +86 -0
  27. package/dist/naeil-locale/messages-BuQvB-u2.d.ts +167 -0
  28. package/dist/naeil-locale/messages.d.ts +1 -0
  29. package/dist/naeil-locale/messages.js +14 -0
  30. package/dist/naeil-locale/server.d.ts +75 -0
  31. package/dist/naeil-locale/server.js +172 -0
  32. package/dist/source/components/naeil-footer-core.d.ts +16 -0
  33. package/dist/source/components/naeil-footer-core.js +93 -0
  34. package/dist/source/components/naeil-footer.d.ts +6 -11
  35. package/dist/source/components/naeil-footer.js +4 -75
  36. package/dist/source/components/naeil-header-account-core.d.ts +26 -0
  37. package/dist/source/components/naeil-header-account-core.js +98 -0
  38. package/dist/source/components/naeil-header-account.d.ts +6 -22
  39. package/dist/source/components/naeil-header-account.js +5 -81
  40. package/dist/source/components/naeil-header-content.d.ts +102 -109
  41. package/dist/source/components/naeil-header-content.js +6 -142
  42. package/dist/source/components/naeil-header-core.d.ts +59 -0
  43. package/dist/source/components/naeil-header-core.js +231 -0
  44. package/dist/source/components/naeil-header-data.d.ts +11 -0
  45. package/dist/source/components/naeil-header-data.js +14 -0
  46. package/dist/source/components/naeil-header.d.ts +10 -51
  47. package/dist/source/components/naeil-header.js +9 -200
  48. package/dist/source/components/naeil-messages-context.d.ts +94 -0
  49. package/dist/source/components/naeil-messages-context.js +16 -0
  50. package/dist/source/components/naeil-standalone-messages.d.ts +11 -0
  51. package/dist/source/components/naeil-standalone-messages.js +13 -0
  52. package/dist/source/i18n/routing.d.ts +22 -20
  53. package/dist/source/lib/ui-release.d.ts +1 -1
  54. package/dist/source/lib/ui-release.js +1 -1
  55. package/dist/source/naeil-locale/messages/en.json +78 -0
  56. package/dist/source/naeil-locale/messages/ja.json +78 -0
  57. package/dist/source/naeil-locale/messages/ko.json +78 -0
  58. package/docs/components/naeil-locale.md +52 -0
  59. package/docs/package-release.md +31 -6
  60. package/package.json +35 -7
  61. /package/dist/{naeil-header-content-BvISJ4RV.d.ts → naeil-header-data-BvISJ4RV.d.ts} +0 -0
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { S as SiteFooterProps } from '../site-footer-s113FZgC.js';
3
- import { N as NaeilHeaderLocale } from '../naeil-header-content-BvISJ4RV.js';
3
+ import { N as NaeilHeaderLocale } from '../naeil-header-data-BvISJ4RV.js';
4
4
  import 'react';
5
5
  import '../navigation-D8N1tMTu.js';
6
6
 
@@ -10,7 +10,7 @@ interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description"
10
10
  /** Only localize/route canonical paths; default destinations use the official origin. */
11
11
  resolveHref?: (path: string) => string;
12
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;
13
+
14
+ declare function NaeilFooter(props: NaeilFooterProps): react_jsx_runtime.JSX.Element;
15
15
 
16
16
  export { NaeilFooter, type NaeilFooterLocale, type NaeilFooterProps };
@@ -2,8 +2,10 @@
2
2
  "use client";
3
3
  import {
4
4
  Logo,
5
- uiRelease
6
- } from "../chunk-JDHGKM25.js";
5
+ NaeilStandaloneMessages,
6
+ uiRelease,
7
+ useNaeilMessages
8
+ } from "../chunk-U3IZCFM4.js";
7
9
  import {
8
10
  SiteFooter
9
11
  } from "../chunk-HSTDPY56.js";
@@ -13,13 +15,8 @@ import {
13
15
  __spreadValues
14
16
  } from "../chunk-JBTDRVZ7.js";
15
17
 
16
- // src/components/naeil-footer.tsx
18
+ // src/components/naeil-footer-core.tsx
17
19
  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
20
  var NativeLink = (props) => /* @__PURE__ */ jsx("a", __spreadValues({}, props));
24
21
  function NaeilFooter(_a) {
25
22
  var _b = _a, {
@@ -35,7 +32,7 @@ function NaeilFooter(_a) {
35
32
  "Link",
36
33
  "onNavigate"
37
34
  ]);
38
- const copy = content[locale];
35
+ const copy = useNaeilMessages(locale).footer;
39
36
  const home = { id: "brand", label: ".naeil", href: resolveHref("/") };
40
37
  return /* @__PURE__ */ jsx(
41
38
  SiteFooter,
@@ -59,7 +56,7 @@ function NaeilFooter(_a) {
59
56
  children: /* @__PURE__ */ jsx(Logo, { variant: "footer", size: 20, label: null })
60
57
  }
61
58
  ),
62
- description: variant === "full" ? "Tomorrow starts here." : void 0,
59
+ description: variant === "full" ? copy.description : void 0,
63
60
  groups: [
64
61
  { id: "navigation", label: copy.navigation, links: [
65
62
  { id: "projects", label: copy.projects, href: resolveHref("/projects") },
@@ -73,6 +70,12 @@ function NaeilFooter(_a) {
73
70
  })
74
71
  );
75
72
  }
73
+
74
+ // src/components/naeil-footer.tsx
75
+ import { jsx as jsx2 } from "react/jsx-runtime";
76
+ function NaeilFooter2(props) {
77
+ return /* @__PURE__ */ jsx2(NaeilStandaloneMessages, { locale: props.locale, children: /* @__PURE__ */ jsx2(NaeilFooter, __spreadValues({}, props)) });
78
+ }
76
79
  export {
77
- NaeilFooter
80
+ NaeilFooter2 as NaeilFooter
78
81
  };
@@ -1,7 +1,7 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
  import { b as NavigationLinkComponent, a as NavigationProps, c as NavigationItem, d as NavigationLinkProps, N as NavigationLink } from '../navigation-D8N1tMTu.js';
4
- import { N as NaeilHeaderLocale } from '../naeil-header-content-BvISJ4RV.js';
4
+ import { N as NaeilHeaderLocale } from '../naeil-header-data-BvISJ4RV.js';
5
5
 
6
6
  type NaeilHeaderAccount = {
7
7
  status: "signed-out";
@@ -20,8 +20,6 @@ interface NaeilHeaderAccountControlProps {
20
20
  /** The same route/save adapter used by the rest of the application header. */
21
21
  Link?: NavigationLinkComponent;
22
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
23
 
26
24
  interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
27
25
  locale: NaeilHeaderLocale;
@@ -63,16 +61,16 @@ interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "to
63
61
  /** Compatibility escape hatch for the legacy native external brand link. */
64
62
  brandLinkComponent?: NavigationLinkComponent;
65
63
  }
66
- /** The actual header theme control; reads only the consumer's theme provider. */
67
- declare function NaeilHeaderThemeControl({ locale }: {
64
+
65
+ declare function NaeilHeaderAccountControl(props: NaeilHeaderAccountControlProps): react_jsx_runtime.JSX.Element;
66
+
67
+ declare function NaeilHeader(props: NaeilHeaderProps): react_jsx_runtime.JSX.Element;
68
+ declare function NaeilHeaderThemeControl(props: {
68
69
  locale: NaeilHeaderLocale;
69
70
  }): react_jsx_runtime.JSX.Element;
70
- /** Shared rendering used by the whole header and legacy site control adapters. */
71
- declare function NaeilHeaderLocaleControl({ locale, onLocaleChange }: {
71
+ declare function NaeilHeaderLocaleControl(props: {
72
72
  locale: NaeilHeaderLocale;
73
73
  onLocaleChange: (locale: NaeilHeaderLocale) => void;
74
74
  }): react_jsx_runtime.JSX.Element;
75
- /** One complete, opt-in branded composition shared by naeil.dev and applications. */
76
- declare function NaeilHeader({ locale, resolveHref, brandHref, brandSlot, brandSuffix, statusSlot, appNavigation, 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;
77
75
 
78
76
  export { NaeilHeader, type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps, NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };
@@ -5,8 +5,8 @@ import {
5
5
  NaeilHeaderAccountControl,
6
6
  NaeilHeaderLocaleControl,
7
7
  NaeilHeaderThemeControl
8
- } from "../chunk-XRO3NJAB.js";
9
- import "../chunk-JDHGKM25.js";
8
+ } from "../chunk-KWEWR46R.js";
9
+ import "../chunk-U3IZCFM4.js";
10
10
  import "../chunk-KPE4KKYM.js";
11
11
  import "../chunk-JBTDRVZ7.js";
12
12
  export {
@@ -1 +1 @@
1
- export declare const uiRelease: Readonly<{version: "0.9.0"; contractVersion: "1"}>;
1
+ export declare const uiRelease: Readonly<{version: "0.11.0"; contractVersion: "1"}>;
@@ -1 +1 @@
1
- export const uiRelease = Object.freeze({"version":"0.9.0","contractVersion":"1"});
1
+ export const uiRelease = Object.freeze({"version":"0.11.0","contractVersion":"1"});
@@ -0,0 +1,16 @@
1
+ import { N as NaeilLocale, L as LocaleMessages } from './messages-BuQvB-u2.js';
2
+
3
+ interface MessageIssue {
4
+ locale: NaeilLocale;
5
+ key: string;
6
+ reason: string;
7
+ }
8
+ /** ICU categories may differ by language; variables, types and keys may not. */
9
+ declare function checkLocaleMessages(dictionaries: Record<NaeilLocale, LocaleMessages>, options: {
10
+ namespace: string;
11
+ }): MessageIssue[];
12
+ declare function assertLocaleMessages(dictionaries: Record<NaeilLocale, LocaleMessages>, options: {
13
+ namespace: string;
14
+ }): void;
15
+
16
+ export { type MessageIssue, assertLocaleMessages, checkLocaleMessages };
@@ -0,0 +1,91 @@
1
+ import {
2
+ naeilLocales
3
+ } from "./chunk-U65OQHZY.js";
4
+ import "./chunk-N3ETBM74.js";
5
+
6
+ // src/naeil-locale/checker.ts
7
+ import { parse, TYPE } from "@formatjs/icu-messageformat-parser";
8
+ function leaves(value, locale, issues, prefix = "") {
9
+ const found = /* @__PURE__ */ new Map();
10
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
11
+ issues.push({ locale, key: prefix, reason: "Dictionary must be a JSON object" });
12
+ return found;
13
+ }
14
+ for (const [key, child] of Object.entries(value)) {
15
+ const path = prefix ? `${prefix}.${key}` : key;
16
+ if (!key || key.includes(".") || ["__proto__", "constructor", "prototype"].includes(key)) issues.push({ locale, key: path, reason: "Unsafe or dotted message key" });
17
+ if (typeof child === "string") {
18
+ found.set(path, child);
19
+ if (!child.trim()) issues.push({ locale, key: path, reason: "Empty message" });
20
+ } else if (!child || typeof child !== "object" || Array.isArray(child)) issues.push({ locale, key: path, reason: "Message must be a string or nested object" });
21
+ else {
22
+ if (!Object.keys(child).length) issues.push({ locale, key: path, reason: "Empty namespace" });
23
+ for (const [nested, text] of leaves(child, locale, issues, path)) found.set(nested, text);
24
+ }
25
+ }
26
+ return found;
27
+ }
28
+ function argumentsOf(nodes) {
29
+ const args = /* @__PURE__ */ new Map();
30
+ const add = (name, type) => {
31
+ var _a;
32
+ const types = (_a = args.get(name)) != null ? _a : /* @__PURE__ */ new Set();
33
+ types.add(type);
34
+ args.set(name, types);
35
+ };
36
+ const visit = (items) => {
37
+ for (const item of items) {
38
+ if (item.type === TYPE.argument) add(item.value, "argument");
39
+ if (item.type === TYPE.number || item.type === TYPE.plural) add(item.value, "number");
40
+ if (item.type === TYPE.date || item.type === TYPE.time) add(item.value, "date");
41
+ if (item.type === TYPE.select) add(item.value, "select");
42
+ if (item.type === TYPE.tag) {
43
+ add(item.value, "tag");
44
+ visit(item.children);
45
+ }
46
+ if (item.type === TYPE.select || item.type === TYPE.plural) {
47
+ if (!item.options.other) throw new Error("Missing other branch");
48
+ for (const option of Object.values(item.options)) visit(option.value);
49
+ }
50
+ }
51
+ };
52
+ visit(nodes);
53
+ return JSON.stringify([...args].sort(([a], [b]) => a.localeCompare(b)).map(([name, types]) => [name, [...types].sort()]));
54
+ }
55
+ function checkLocaleMessages(dictionaries, options) {
56
+ const issues = [];
57
+ const keys = /* @__PURE__ */ new Map();
58
+ const signatures = /* @__PURE__ */ new Map();
59
+ for (const locale of naeilLocales) {
60
+ const dictionary = dictionaries[locale];
61
+ if (!dictionary || Object.keys(dictionary).length !== 1 || !Object.hasOwn(dictionary, options.namespace)) issues.push({ locale, key: "", reason: `Expected only ${options.namespace} namespace` });
62
+ const all = leaves(dictionary, locale, issues);
63
+ keys.set(locale, all);
64
+ const shapes = /* @__PURE__ */ new Map();
65
+ signatures.set(locale, shapes);
66
+ for (const [key, value] of all) {
67
+ try {
68
+ shapes.set(key, argumentsOf(parse(value, { requiresOtherClause: true })));
69
+ } catch (error) {
70
+ issues.push({ locale, key, reason: `Invalid ICU: ${error instanceof Error ? error.message : "parse failed"}` });
71
+ }
72
+ }
73
+ }
74
+ const reference = keys.get("en");
75
+ for (const locale of naeilLocales) {
76
+ for (const key of /* @__PURE__ */ new Set([...reference.keys(), ...keys.get(locale).keys()])) {
77
+ if (!keys.get(locale).has(key)) issues.push({ locale, key, reason: "Missing key" });
78
+ else if (!reference.has(key)) issues.push({ locale, key, reason: "Unexpected key" });
79
+ else if (signatures.get(locale).has(key) && signatures.get("en").has(key) && signatures.get(locale).get(key) !== signatures.get("en").get(key)) issues.push({ locale, key, reason: "ICU variable names or types differ from English" });
80
+ }
81
+ }
82
+ return issues;
83
+ }
84
+ function assertLocaleMessages(dictionaries, options) {
85
+ const issues = checkLocaleMessages(dictionaries, options);
86
+ if (issues.length) throw new Error(issues.map((issue) => `${issue.locale}:${issue.key}: ${issue.reason}`).join("\n"));
87
+ }
88
+ export {
89
+ assertLocaleMessages,
90
+ checkLocaleMessages
91
+ };
@@ -0,0 +1,150 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as React from 'react';
3
+ import { ReactNode } from 'react';
4
+
5
+ type NavigationLinkProps = React.ComponentPropsWithoutRef<"a"> & {
6
+ href: string;
7
+ };
8
+ type NavigationLinkComponent = React.ComponentType<NavigationLinkProps>;
9
+ interface NavigationLink {
10
+ id: string;
11
+ label: string;
12
+ href: string;
13
+ description?: string;
14
+ icon?: React.ReactNode;
15
+ badge?: React.ReactNode;
16
+ external?: boolean;
17
+ target?: React.HTMLAttributeAnchorTarget;
18
+ active?: boolean;
19
+ }
20
+ interface NavigationGroup {
21
+ id: string;
22
+ label: string;
23
+ items: NavigationLink[];
24
+ /** Desktop menu layout; the mobile sheet always uses one column. */
25
+ columns?: 1 | 2;
26
+ }
27
+ type NavigationItem = NavigationLink | NavigationGroup;
28
+ interface NavigationProps extends Omit<React.ComponentPropsWithoutRef<"header">, "children" | "onSelect"> {
29
+ brand: React.ReactNode;
30
+ items: NavigationItem[];
31
+ /** Translated landmark/dialog/close labels are supplied by the application. */
32
+ labels: {
33
+ navigation: string;
34
+ menu: string;
35
+ close: string;
36
+ };
37
+ Link?: NavigationLinkComponent;
38
+ currentHref?: string;
39
+ toolbar?: React.ReactNode;
40
+ mobileToolbar?: React.ReactNode;
41
+ mobileFooter?: React.ReactNode;
42
+ mobileOpen?: boolean;
43
+ onMobileOpenChange?: (open: boolean) => void;
44
+ /** Use the same product-owned frame class on header, footer and main. */
45
+ containerClassName?: string;
46
+ /** Preserve modified clicks; applications may preventDefault for client routing/guards. */
47
+ onNavigate?: (event: React.MouseEvent<HTMLAnchorElement>, item: NavigationLink) => void;
48
+ }
49
+
50
+ declare const headerLocales: readonly ["en", "ko", "ja"];
51
+ type NaeilHeaderLocale = (typeof headerLocales)[number];
52
+
53
+ type NaeilHeaderAccount = {
54
+ status: "signed-out";
55
+ loginHref: string;
56
+ } | {
57
+ status: "signed-in";
58
+ /** Consumer starts its guarded session action and owns failures/navigation. */
59
+ onLogout: () => void;
60
+ busy?: boolean;
61
+ displayName?: string;
62
+ email?: string;
63
+ };
64
+ interface NaeilHeaderAccountControlProps {
65
+ locale: NaeilHeaderLocale;
66
+ account: NaeilHeaderAccount;
67
+ /** The same route/save adapter used by the rest of the application header. */
68
+ Link?: NavigationLinkComponent;
69
+ }
70
+ /** Shared account presentation only: never reads sessions or calls an auth API. */
71
+ declare function NaeilHeaderAccountControl({ locale, account, Link }: NaeilHeaderAccountControlProps): react_jsx_runtime.JSX.Element;
72
+
73
+ interface NaeilHeaderProps extends Omit<NavigationProps, "brand" | "items" | "toolbar" | "mobileToolbar" | "labels"> {
74
+ locale: NaeilHeaderLocale;
75
+ /** Resolve canonical unlocalized paths. Defaults to the official localized site. */
76
+ resolveHref?: (path: string) => string;
77
+ brandHref?: string;
78
+ brandSlot?: ReactNode;
79
+ /** Ignored when brandSlot replaces the complete brand content. */
80
+ brandSuffix?: string;
81
+ /** After the brand link, outside it; rendered once at every width. */
82
+ statusSlot?: ReactNode;
83
+ /** Product menu data, after catalog/blog and before flat subNav links. */
84
+ appNavigation?: NavigationItem[];
85
+ brandLinkProps?: Omit<NavigationLinkProps, "href" | "children">;
86
+ /** Omit when the application does not support changing its UI language. */
87
+ onLocaleChange?: (locale: NaeilHeaderLocale) => void;
88
+ /** Use NaeilHeaderAccountControl for canonical UI; the app owns auth state/I/O. */
89
+ authSlot?: ReactNode;
90
+ labels?: NavigationProps["labels"];
91
+ projects?: NavigationLink[];
92
+ /** Legacy remote-catalog mode: generated noncurrent project/blog links use native anchors. */
93
+ projectsExternal?: boolean;
94
+ /** Legacy next-intl copy overrides; catalog/artwork/layout remain shared. */
95
+ translations?: {
96
+ projects: string;
97
+ blog: string;
98
+ project: (key: string) => string;
99
+ };
100
+ showProjects?: boolean;
101
+ showBlog?: boolean;
102
+ subNav?: Array<{
103
+ label: string;
104
+ href: string;
105
+ }>;
106
+ currentProjectKey?: string;
107
+ currentProjectHref?: string;
108
+ /** Compatibility escape hatch replacing the default theme/locale/auth toolbar. */
109
+ toolbarSlot?: ReactNode;
110
+ /** Compatibility escape hatch for the legacy native external brand link. */
111
+ brandLinkComponent?: NavigationLinkComponent;
112
+ }
113
+ /** The actual header theme control; reads only the consumer's theme provider. */
114
+ declare function NaeilHeaderThemeControl({ locale }: {
115
+ locale: NaeilHeaderLocale;
116
+ }): react_jsx_runtime.JSX.Element;
117
+ /** Shared rendering used by the whole header and legacy site control adapters. */
118
+ declare function NaeilHeaderLocaleControl({ locale, onLocaleChange }: {
119
+ locale: NaeilHeaderLocale;
120
+ onLocaleChange: (locale: NaeilHeaderLocale) => void;
121
+ }): react_jsx_runtime.JSX.Element;
122
+ /** One complete, opt-in branded composition shared by naeil.dev and applications. */
123
+ declare function NaeilHeader({ locale, resolveHref, brandHref, brandSlot, brandSuffix, statusSlot, appNavigation, 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;
124
+
125
+ interface SiteFooterProps extends React.ComponentPropsWithoutRef<"footer"> {
126
+ brand?: React.ReactNode;
127
+ description?: React.ReactNode;
128
+ groups?: Array<{
129
+ id: string;
130
+ label: string;
131
+ links: NavigationLink[];
132
+ }>;
133
+ Link?: NavigationLinkComponent;
134
+ meta?: React.ReactNode;
135
+ containerClassName?: string;
136
+ variant?: "full" | "compact";
137
+ /** Called for every group link, including native external anchors. Preserve modified clicks. */
138
+ onNavigate?: NavigationProps["onNavigate"];
139
+ }
140
+
141
+ type NaeilFooterLocale = NaeilHeaderLocale;
142
+ interface NaeilFooterProps extends Omit<SiteFooterProps, "brand" | "description" | "groups"> {
143
+ locale: NaeilFooterLocale;
144
+ /** Only localize/route canonical paths; default destinations use the official origin. */
145
+ resolveHref?: (path: string) => string;
146
+ }
147
+ /** Canonical content in full/compact density. Product legal/status copy belongs in meta. */
148
+ declare function NaeilFooter({ locale, resolveHref, variant, Link, onNavigate, ...props }: NaeilFooterProps): react_jsx_runtime.JSX.Element;
149
+
150
+ export { NaeilFooter, type NaeilFooterLocale, type NaeilFooterProps, NaeilHeader, type NaeilHeaderAccount, NaeilHeaderAccountControl, type NaeilHeaderAccountControlProps, type NaeilHeaderLocale, NaeilHeaderLocaleControl, type NaeilHeaderProps, NaeilHeaderThemeControl };