@yeongseoksong/framework 1.2.0 → 1.3.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/README.md +47 -0
- package/dist/ui/index.cjs +54 -30
- package/dist/ui/index.d.mts +3 -3
- package/dist/ui/index.d.ts +3 -3
- package/dist/ui/index.mjs +54 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -65,6 +65,53 @@ import './env.mjs'
|
|
|
65
65
|
|
|
66
66
|
`navItems` / `companyInfo`처럼 배열·객체인 값은 환경변수로 담을 수 없으므로 `MainLayout`에 prop으로 넘깁니다 (아래 MainLayout 항목 참고).
|
|
67
67
|
|
|
68
|
+
### 3. 색상 커스터마이즈
|
|
69
|
+
|
|
70
|
+
브랜드 색은 환경변수가 아니라 **테마 오버라이드**로 주입합니다. `theme`은 `createTheme()`이 만든 `MantineThemeOverride`라 Mantine 표준 `mergeThemeOverrides()`로 그대로 합칠 수 있습니다.
|
|
71
|
+
|
|
72
|
+
**반드시 `"use client"` 파일 안에서 합쳐야 합니다.** `ui` 번들 전체에 `"use client"`가 붙어 있어 서버 컴포넌트가 `theme`을 임포트하면 실제 객체가 아니라 client reference proxy를 받습니다. `<MantineProvider theme={theme}>`처럼 **넘기기만** 하는 건 되지만, `mergeThemeOverrides(theme, ...)`처럼 값을 **읽으면** 터집니다.
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
// app/theme.ts ← "use client" 필수
|
|
76
|
+
'use client'
|
|
77
|
+
import { mergeThemeOverrides } from '@mantine/core'
|
|
78
|
+
import { theme } from '@yeongseoksong/framework/ui'
|
|
79
|
+
|
|
80
|
+
export const appTheme = mergeThemeOverrides(theme, {
|
|
81
|
+
colors: {
|
|
82
|
+
// 10단계 전부 채워야 합니다. 부분 배열은 Mantine이 허용하지 않습니다.
|
|
83
|
+
primary: [
|
|
84
|
+
'#e7f0fb', '#c8dcf4', '#a3c3ec', '#7aa8e3', '#4f8ddb',
|
|
85
|
+
'#2374d4', '#0b5ed7', '#094db1', '#073d8c', '#052d68',
|
|
86
|
+
],
|
|
87
|
+
},
|
|
88
|
+
// 브랜드 앵커 shade를 바꾸려면 함께 지정
|
|
89
|
+
primaryShade: { light: 6, dark: 5 },
|
|
90
|
+
})
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
// app/layout.tsx — Server Component 그대로 둡니다
|
|
95
|
+
import { MantineProvider } from '@mantine/core'
|
|
96
|
+
import { appTheme } from './theme'
|
|
97
|
+
|
|
98
|
+
<MantineProvider theme={appTheme} defaultColorScheme="light">
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
오버라이드하지 않은 키(타이포·spacing·shadows·컴포넌트 기본값)는 프레임워크 값이 그대로 유지됩니다.
|
|
102
|
+
|
|
103
|
+
**컴포넌트가 의존하는 색상 키** — 아래 키를 바꾸면 해당 컴포넌트 전체가 따라 바뀝니다. 키를 **없애면** Mantine 기본 팔레트로 폴백하므로 톤이 어긋납니다.
|
|
104
|
+
|
|
105
|
+
| 키 | 쓰이는 곳 |
|
|
106
|
+
| ----------- | ---------------------------------------------------------------------- |
|
|
107
|
+
| `primary` | `primaryColor`. 버튼·링크 hover·`SdText.Eyebrow`·`SdBadge.Primary` 등 |
|
|
108
|
+
| `secondary` | 보조 강조 |
|
|
109
|
+
| `slate` | 중립 전반 — 모든 `SdText`/`SdTitle` 본문색, 보더, 표 헤더. `dark` 별칭 |
|
|
110
|
+
| `red` | `SdText.Error`, `SdButton.Delete` |
|
|
111
|
+
| `green` | `SdButton.Excel` |
|
|
112
|
+
|
|
113
|
+
10단계 램프를 손으로 만들기 번거로우면 [`@mantine/colors-generator`](https://mantine.dev/colors-generator/)의 `generateColors('#0b5ed7')`로 hex 하나에서 뽑을 수 있습니다(별도 설치 필요).
|
|
114
|
+
|
|
68
115
|
## 임포트 경로
|
|
69
116
|
|
|
70
117
|
| 경로 | 내용 |
|
package/dist/ui/index.cjs
CHANGED
|
@@ -1479,7 +1479,7 @@ var import_core28 = require("@mantine/core");
|
|
|
1479
1479
|
var import_hooks = require("@mantine/hooks");
|
|
1480
1480
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1481
1481
|
var BAR_HEIGHT = 60;
|
|
1482
|
-
function SdHeader({ navItems, loginFlag
|
|
1482
|
+
function SdHeader({ navItems, loginFlag }) {
|
|
1483
1483
|
const [opened, { toggle, close }] = (0, import_hooks.useDisclosure)();
|
|
1484
1484
|
const visibleItems = filterAndSort(navItems);
|
|
1485
1485
|
const topItems = visibleItems.filter((item) => !item.parentId);
|
|
@@ -1532,8 +1532,7 @@ function SdHeader({ navItems, loginFlag, children }) {
|
|
|
1532
1532
|
}) }),
|
|
1533
1533
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_core28.Group, { h: BAR_HEIGHT, align: "center", gap: "sm", wrap: "nowrap", children: [
|
|
1534
1534
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_core28.Burger, { hiddenFrom: "sm", opened, onClick: toggle }),
|
|
1535
|
-
loginFlag && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_core28.Group, { gap: "sm", visibleFrom: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(SdButton.Primary, { size: "xs", children: "\uB85C\uADF8\uC778" }) })
|
|
1536
|
-
children
|
|
1535
|
+
loginFlag && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_core28.Group, { gap: "sm", visibleFrom: "sm", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(SdButton.Primary, { size: "xs", children: "\uB85C\uADF8\uC778" }) })
|
|
1537
1536
|
] })
|
|
1538
1537
|
] }) })
|
|
1539
1538
|
}
|
|
@@ -1568,9 +1567,13 @@ var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
|
1568
1567
|
function FooterNavColumns({ items }) {
|
|
1569
1568
|
const topLevel = items.filter((item) => !item.parentId);
|
|
1570
1569
|
const getChildren = (parentId) => items.filter((item) => item.parentId === parentId);
|
|
1571
|
-
|
|
1570
|
+
const CHILD_THRESH = 4;
|
|
1571
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: topLevel.map((group) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_core29.Grid.Col, { span: { base: 6, sm: 4, md: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_core29.Stack, { gap: "xs", children: [
|
|
1572
1572
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SdText.Sub, { children: group.label }),
|
|
1573
|
-
getChildren(group.id).map((link) =>
|
|
1573
|
+
getChildren(group.id).map((link, id) => {
|
|
1574
|
+
if (id >= CHILD_THRESH) return;
|
|
1575
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(SdLink.Hint, { href: link.href, children: link.label }, link.id);
|
|
1576
|
+
})
|
|
1574
1577
|
] }) }, group.id)) });
|
|
1575
1578
|
}
|
|
1576
1579
|
var SOCIAL_ICONS = {
|
|
@@ -1796,10 +1799,11 @@ var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
|
1796
1799
|
function MainLayout({
|
|
1797
1800
|
children,
|
|
1798
1801
|
navItems,
|
|
1799
|
-
companyInfo
|
|
1802
|
+
companyInfo,
|
|
1803
|
+
loginFlag
|
|
1800
1804
|
}) {
|
|
1801
1805
|
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_core34.AppShell, { header: { height: 60 }, children: [
|
|
1802
|
-
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_core34.AppShell.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(SdHeader, { navItems, loginFlag
|
|
1806
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_core34.AppShell.Header, { children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(SdHeader, { navItems, loginFlag }) }),
|
|
1803
1807
|
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_core34.AppShell.Main, { children }),
|
|
1804
1808
|
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(SdFooter, { company: companyInfo, navItems })
|
|
1805
1809
|
] });
|
|
@@ -2010,33 +2014,53 @@ var slate = [
|
|
|
2010
2014
|
"#0f172a"
|
|
2011
2015
|
// 9 slate-900
|
|
2012
2016
|
];
|
|
2013
|
-
var
|
|
2014
|
-
"#
|
|
2015
|
-
|
|
2016
|
-
"#
|
|
2017
|
-
|
|
2018
|
-
"#
|
|
2019
|
-
|
|
2020
|
-
"#
|
|
2021
|
-
|
|
2022
|
-
"#
|
|
2023
|
-
|
|
2017
|
+
var red = [
|
|
2018
|
+
"#fef2f2",
|
|
2019
|
+
// 0 red-50
|
|
2020
|
+
"#fee2e2",
|
|
2021
|
+
// 1 red-100
|
|
2022
|
+
"#fecaca",
|
|
2023
|
+
// 2 red-200
|
|
2024
|
+
"#fca5a5",
|
|
2025
|
+
// 3 red-300
|
|
2026
|
+
"#f87171",
|
|
2027
|
+
// 4 red-400
|
|
2028
|
+
"#ef4444",
|
|
2029
|
+
// 5 red-500
|
|
2030
|
+
"#dc2626",
|
|
2031
|
+
// 6 red-600
|
|
2032
|
+
"#b91c1c",
|
|
2033
|
+
// 7 red-700
|
|
2034
|
+
"#991b1b",
|
|
2035
|
+
// 8 red-800
|
|
2036
|
+
"#7f1d1d"
|
|
2037
|
+
// 9 red-900
|
|
2024
2038
|
];
|
|
2025
|
-
var
|
|
2026
|
-
"#
|
|
2027
|
-
|
|
2028
|
-
"#
|
|
2029
|
-
|
|
2030
|
-
"#
|
|
2031
|
-
|
|
2032
|
-
"#
|
|
2033
|
-
|
|
2034
|
-
"#
|
|
2035
|
-
|
|
2039
|
+
var green = [
|
|
2040
|
+
"#f0fdf4",
|
|
2041
|
+
// 0 green-50
|
|
2042
|
+
"#dcfce7",
|
|
2043
|
+
// 1 green-100
|
|
2044
|
+
"#bbf7d0",
|
|
2045
|
+
// 2 green-200
|
|
2046
|
+
"#86efac",
|
|
2047
|
+
// 3 green-300
|
|
2048
|
+
"#4ade80",
|
|
2049
|
+
// 4 green-400
|
|
2050
|
+
"#22c55e",
|
|
2051
|
+
// 5 green-500
|
|
2052
|
+
"#16a34a",
|
|
2053
|
+
// 6 green-600
|
|
2054
|
+
"#15803d",
|
|
2055
|
+
// 7 green-700
|
|
2056
|
+
"#166534",
|
|
2057
|
+
// 8 green-800
|
|
2058
|
+
"#14532d"
|
|
2059
|
+
// 9 green-900
|
|
2036
2060
|
];
|
|
2037
2061
|
var theme = (0, import_core36.createTheme)({
|
|
2038
2062
|
/* ---- Color ---- */
|
|
2039
|
-
colors: { primary, secondary, slate,
|
|
2063
|
+
colors: { primary, secondary, slate, red, green, dark: slate },
|
|
2040
2064
|
primaryColor: "primary",
|
|
2041
2065
|
primaryShade: { light: 6, dark: 5 },
|
|
2042
2066
|
/* ---- Type ---- */
|
package/dist/ui/index.d.mts
CHANGED
|
@@ -770,9 +770,8 @@ declare function HeroCarousel({ slides, children }: HeroCarouselProps): react_js
|
|
|
770
770
|
interface HeaderProps {
|
|
771
771
|
navItems: NavItem[];
|
|
772
772
|
loginFlag?: boolean;
|
|
773
|
-
children?: ReactNode;
|
|
774
773
|
}
|
|
775
|
-
declare function SdHeader({ navItems, loginFlag
|
|
774
|
+
declare function SdHeader({ navItems, loginFlag }: HeaderProps): react_jsx_runtime.JSX.Element;
|
|
776
775
|
|
|
777
776
|
interface SdFooterProps {
|
|
778
777
|
company: CompanyInfo;
|
|
@@ -831,10 +830,11 @@ declare const SdErrorView: {
|
|
|
831
830
|
declare const SdErrorViewPage: typeof Page;
|
|
832
831
|
declare const SdErrorViewNotFound: typeof NotFound;
|
|
833
832
|
|
|
834
|
-
declare function MainLayout({ children, navItems, companyInfo, }: {
|
|
833
|
+
declare function MainLayout({ children, navItems, companyInfo, loginFlag, }: {
|
|
835
834
|
children: React.ReactNode;
|
|
836
835
|
navItems: NavItem[];
|
|
837
836
|
companyInfo: CompanyInfo;
|
|
837
|
+
loginFlag?: boolean;
|
|
838
838
|
}): react_jsx_runtime.JSX.Element;
|
|
839
839
|
|
|
840
840
|
interface PageHeroBaseProps {
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -770,9 +770,8 @@ declare function HeroCarousel({ slides, children }: HeroCarouselProps): react_js
|
|
|
770
770
|
interface HeaderProps {
|
|
771
771
|
navItems: NavItem[];
|
|
772
772
|
loginFlag?: boolean;
|
|
773
|
-
children?: ReactNode;
|
|
774
773
|
}
|
|
775
|
-
declare function SdHeader({ navItems, loginFlag
|
|
774
|
+
declare function SdHeader({ navItems, loginFlag }: HeaderProps): react_jsx_runtime.JSX.Element;
|
|
776
775
|
|
|
777
776
|
interface SdFooterProps {
|
|
778
777
|
company: CompanyInfo;
|
|
@@ -831,10 +830,11 @@ declare const SdErrorView: {
|
|
|
831
830
|
declare const SdErrorViewPage: typeof Page;
|
|
832
831
|
declare const SdErrorViewNotFound: typeof NotFound;
|
|
833
832
|
|
|
834
|
-
declare function MainLayout({ children, navItems, companyInfo, }: {
|
|
833
|
+
declare function MainLayout({ children, navItems, companyInfo, loginFlag, }: {
|
|
835
834
|
children: React.ReactNode;
|
|
836
835
|
navItems: NavItem[];
|
|
837
836
|
companyInfo: CompanyInfo;
|
|
837
|
+
loginFlag?: boolean;
|
|
838
838
|
}): react_jsx_runtime.JSX.Element;
|
|
839
839
|
|
|
840
840
|
interface PageHeroBaseProps {
|
package/dist/ui/index.mjs
CHANGED
|
@@ -1357,7 +1357,7 @@ import { Box as Box12, Burger, Drawer, Group as Group9, NavLink, Stack as Stack1
|
|
|
1357
1357
|
import { useDisclosure, useFocusWithin, useHover, useMergedRef } from "@mantine/hooks";
|
|
1358
1358
|
import { Fragment as Fragment4, jsx as jsx28, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1359
1359
|
var BAR_HEIGHT = 60;
|
|
1360
|
-
function SdHeader({ navItems, loginFlag
|
|
1360
|
+
function SdHeader({ navItems, loginFlag }) {
|
|
1361
1361
|
const [opened, { toggle, close }] = useDisclosure();
|
|
1362
1362
|
const visibleItems = filterAndSort(navItems);
|
|
1363
1363
|
const topItems = visibleItems.filter((item) => !item.parentId);
|
|
@@ -1410,8 +1410,7 @@ function SdHeader({ navItems, loginFlag, children }) {
|
|
|
1410
1410
|
}) }),
|
|
1411
1411
|
/* @__PURE__ */ jsxs16(Group9, { h: BAR_HEIGHT, align: "center", gap: "sm", wrap: "nowrap", children: [
|
|
1412
1412
|
/* @__PURE__ */ jsx28(Burger, { hiddenFrom: "sm", opened, onClick: toggle }),
|
|
1413
|
-
loginFlag && /* @__PURE__ */ jsx28(Group9, { gap: "sm", visibleFrom: "sm", children: /* @__PURE__ */ jsx28(SdButton.Primary, { size: "xs", children: "\uB85C\uADF8\uC778" }) })
|
|
1414
|
-
children
|
|
1413
|
+
loginFlag && /* @__PURE__ */ jsx28(Group9, { gap: "sm", visibleFrom: "sm", children: /* @__PURE__ */ jsx28(SdButton.Primary, { size: "xs", children: "\uB85C\uADF8\uC778" }) })
|
|
1415
1414
|
] })
|
|
1416
1415
|
] }) })
|
|
1417
1416
|
}
|
|
@@ -1454,9 +1453,13 @@ import { Fragment as Fragment5, jsx as jsx29, jsxs as jsxs17 } from "react/jsx-r
|
|
|
1454
1453
|
function FooterNavColumns({ items }) {
|
|
1455
1454
|
const topLevel = items.filter((item) => !item.parentId);
|
|
1456
1455
|
const getChildren = (parentId) => items.filter((item) => item.parentId === parentId);
|
|
1457
|
-
|
|
1456
|
+
const CHILD_THRESH = 4;
|
|
1457
|
+
return /* @__PURE__ */ jsx29(Fragment5, { children: topLevel.map((group) => /* @__PURE__ */ jsx29(Grid5.Col, { span: { base: 6, sm: 4, md: "auto" }, children: /* @__PURE__ */ jsxs17(Stack16, { gap: "xs", children: [
|
|
1458
1458
|
/* @__PURE__ */ jsx29(SdText.Sub, { children: group.label }),
|
|
1459
|
-
getChildren(group.id).map((link) =>
|
|
1459
|
+
getChildren(group.id).map((link, id) => {
|
|
1460
|
+
if (id >= CHILD_THRESH) return;
|
|
1461
|
+
return /* @__PURE__ */ jsx29(SdLink.Hint, { href: link.href, children: link.label }, link.id);
|
|
1462
|
+
})
|
|
1460
1463
|
] }) }, group.id)) });
|
|
1461
1464
|
}
|
|
1462
1465
|
var SOCIAL_ICONS = {
|
|
@@ -1682,10 +1685,11 @@ import { jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
|
1682
1685
|
function MainLayout({
|
|
1683
1686
|
children,
|
|
1684
1687
|
navItems,
|
|
1685
|
-
companyInfo
|
|
1688
|
+
companyInfo,
|
|
1689
|
+
loginFlag
|
|
1686
1690
|
}) {
|
|
1687
1691
|
return /* @__PURE__ */ jsxs22(AppShell, { header: { height: 60 }, children: [
|
|
1688
|
-
/* @__PURE__ */ jsx34(AppShell.Header, { children: /* @__PURE__ */ jsx34(SdHeader, { navItems, loginFlag
|
|
1692
|
+
/* @__PURE__ */ jsx34(AppShell.Header, { children: /* @__PURE__ */ jsx34(SdHeader, { navItems, loginFlag }) }),
|
|
1689
1693
|
/* @__PURE__ */ jsx34(AppShell.Main, { children }),
|
|
1690
1694
|
/* @__PURE__ */ jsx34(SdFooter, { company: companyInfo, navItems })
|
|
1691
1695
|
] });
|
|
@@ -1896,33 +1900,53 @@ var slate = [
|
|
|
1896
1900
|
"#0f172a"
|
|
1897
1901
|
// 9 slate-900
|
|
1898
1902
|
];
|
|
1899
|
-
var
|
|
1900
|
-
"#
|
|
1901
|
-
|
|
1902
|
-
"#
|
|
1903
|
-
|
|
1904
|
-
"#
|
|
1905
|
-
|
|
1906
|
-
"#
|
|
1907
|
-
|
|
1908
|
-
"#
|
|
1909
|
-
|
|
1903
|
+
var red = [
|
|
1904
|
+
"#fef2f2",
|
|
1905
|
+
// 0 red-50
|
|
1906
|
+
"#fee2e2",
|
|
1907
|
+
// 1 red-100
|
|
1908
|
+
"#fecaca",
|
|
1909
|
+
// 2 red-200
|
|
1910
|
+
"#fca5a5",
|
|
1911
|
+
// 3 red-300
|
|
1912
|
+
"#f87171",
|
|
1913
|
+
// 4 red-400
|
|
1914
|
+
"#ef4444",
|
|
1915
|
+
// 5 red-500
|
|
1916
|
+
"#dc2626",
|
|
1917
|
+
// 6 red-600
|
|
1918
|
+
"#b91c1c",
|
|
1919
|
+
// 7 red-700
|
|
1920
|
+
"#991b1b",
|
|
1921
|
+
// 8 red-800
|
|
1922
|
+
"#7f1d1d"
|
|
1923
|
+
// 9 red-900
|
|
1910
1924
|
];
|
|
1911
|
-
var
|
|
1912
|
-
"#
|
|
1913
|
-
|
|
1914
|
-
"#
|
|
1915
|
-
|
|
1916
|
-
"#
|
|
1917
|
-
|
|
1918
|
-
"#
|
|
1919
|
-
|
|
1920
|
-
"#
|
|
1921
|
-
|
|
1925
|
+
var green = [
|
|
1926
|
+
"#f0fdf4",
|
|
1927
|
+
// 0 green-50
|
|
1928
|
+
"#dcfce7",
|
|
1929
|
+
// 1 green-100
|
|
1930
|
+
"#bbf7d0",
|
|
1931
|
+
// 2 green-200
|
|
1932
|
+
"#86efac",
|
|
1933
|
+
// 3 green-300
|
|
1934
|
+
"#4ade80",
|
|
1935
|
+
// 4 green-400
|
|
1936
|
+
"#22c55e",
|
|
1937
|
+
// 5 green-500
|
|
1938
|
+
"#16a34a",
|
|
1939
|
+
// 6 green-600
|
|
1940
|
+
"#15803d",
|
|
1941
|
+
// 7 green-700
|
|
1942
|
+
"#166534",
|
|
1943
|
+
// 8 green-800
|
|
1944
|
+
"#14532d"
|
|
1945
|
+
// 9 green-900
|
|
1922
1946
|
];
|
|
1923
1947
|
var theme = createTheme({
|
|
1924
1948
|
/* ---- Color ---- */
|
|
1925
|
-
colors: { primary, secondary, slate,
|
|
1949
|
+
colors: { primary, secondary, slate, red, green, dark: slate },
|
|
1926
1950
|
primaryColor: "primary",
|
|
1927
1951
|
primaryShade: { light: 6, dark: 5 },
|
|
1928
1952
|
/* ---- Type ---- */
|