@m1kapp/ui 0.1.1 → 0.1.3
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 +4 -4
- package/dist/index.d.mts +73 -1
- package/dist/index.d.ts +73 -1
- package/dist/index.js +4 -193
- package/dist/index.mjs +4 -157
- package/package.json +1 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# @
|
|
1
|
+
# @m1kapp/ui
|
|
2
2
|
|
|
3
3
|
> Mobile-first app shell for side projects.
|
|
4
4
|
> Build apps that feel like native — in minutes.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
## Install
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
npm install @
|
|
23
|
+
npm install @m1kapp/ui
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## Quick Start
|
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
Divider,
|
|
39
39
|
StatChip,
|
|
40
40
|
EmptyState,
|
|
41
|
-
} from "@
|
|
41
|
+
} from "@m1kapp/ui";
|
|
42
42
|
|
|
43
43
|
export default function App() {
|
|
44
44
|
const [tab, setTab] = useState("home");
|
|
@@ -144,7 +144,7 @@ export default function App() {
|
|
|
144
144
|
In the AI era, building a side project takes a day.
|
|
145
145
|
But making it *feel* like an app still takes effort.
|
|
146
146
|
|
|
147
|
-
`@
|
|
147
|
+
`@m1kapp/ui` gives you the mobile app shell — header, scrollable content, bottom tabs, floating on a colored background — so you can focus on what matters: your idea.
|
|
148
148
|
|
|
149
149
|
Built and battle-tested in [m1k](https://m1k.app).
|
|
150
150
|
|
package/dist/index.d.mts
CHANGED
|
@@ -110,4 +110,76 @@ interface WatermarkProps {
|
|
|
110
110
|
*/
|
|
111
111
|
declare function Watermark({ children, color, text, maxWidth, padding, }: WatermarkProps): react_jsx_runtime.JSX.Element;
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
declare const colors: {
|
|
114
|
+
readonly blue: "#3b82f6";
|
|
115
|
+
readonly purple: "#8b5cf6";
|
|
116
|
+
readonly green: "#10b981";
|
|
117
|
+
readonly orange: "#f97316";
|
|
118
|
+
readonly pink: "#ec4899";
|
|
119
|
+
readonly red: "#ef4444";
|
|
120
|
+
readonly yellow: "#eab308";
|
|
121
|
+
readonly cyan: "#06b6d4";
|
|
122
|
+
readonly slate: "#0f172a";
|
|
123
|
+
readonly zinc: "#27272a";
|
|
124
|
+
};
|
|
125
|
+
type ColorName = keyof typeof colors;
|
|
126
|
+
|
|
127
|
+
interface ThemeButtonProps {
|
|
128
|
+
color: string;
|
|
129
|
+
onClick: () => void;
|
|
130
|
+
className?: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Small circular button showing the current theme color.
|
|
134
|
+
* Designed for the AppShellHeader top-right slot.
|
|
135
|
+
*/
|
|
136
|
+
declare function ThemeButton({ color, onClick, className }: ThemeButtonProps): react_jsx_runtime.JSX.Element;
|
|
137
|
+
interface ThemeDialogProps {
|
|
138
|
+
open: boolean;
|
|
139
|
+
onClose: () => void;
|
|
140
|
+
current: string;
|
|
141
|
+
onSelect: (color: string) => void;
|
|
142
|
+
/** Override the color palette. Defaults to built-in colors. */
|
|
143
|
+
palette?: Record<string, string>;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Bottom-sheet style color picker dialog.
|
|
147
|
+
* Shows a 5-column grid of color circles with check on the active one.
|
|
148
|
+
*/
|
|
149
|
+
declare function ThemeDialog({ open, onClose, current, onSelect, palette, }: ThemeDialogProps): react_jsx_runtime.JSX.Element | null;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Font presets for @m1kapp/ui.
|
|
153
|
+
* These return CSS @import strings to load fonts from official CDNs.
|
|
154
|
+
* No font files are bundled — only references to the original sources.
|
|
155
|
+
*/
|
|
156
|
+
declare const fonts: {
|
|
157
|
+
/** Toss Product Sans — from toss.im (free for commercial use) */
|
|
158
|
+
readonly toss: "https://static.toss.im/dist/tps.css";
|
|
159
|
+
/** Pretendard — popular Korean web font */
|
|
160
|
+
readonly pretendard: "https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css";
|
|
161
|
+
/** Inter — clean Latin sans-serif */
|
|
162
|
+
readonly inter: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&display=swap";
|
|
163
|
+
};
|
|
164
|
+
type FontName = keyof typeof fonts;
|
|
165
|
+
/**
|
|
166
|
+
* Returns a <link> href for the given font preset.
|
|
167
|
+
* Usage in your HTML head or via a <link> tag:
|
|
168
|
+
*
|
|
169
|
+
* ```tsx
|
|
170
|
+
* <link rel="stylesheet" href={fonts.toss} />
|
|
171
|
+
* ```
|
|
172
|
+
*
|
|
173
|
+
* Or in CSS:
|
|
174
|
+
* ```css
|
|
175
|
+
* @import url("https://static.toss.im/dist/tps.css");
|
|
176
|
+
* body { font-family: "Toss Product Sans", sans-serif; }
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
declare const fontFamily: {
|
|
180
|
+
readonly toss: "\"Toss Product Sans\", \"Pretendard\", system-ui, sans-serif";
|
|
181
|
+
readonly pretendard: "\"Pretendard Variable\", \"Pretendard\", system-ui, sans-serif";
|
|
182
|
+
readonly inter: "\"Inter\", system-ui, sans-serif";
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export { AppShell, AppShellContent, type AppShellContentProps, AppShellHeader, type AppShellHeaderProps, type AppShellProps, type ColorName, Divider, EmptyState, type EmptyStateProps, type FontName, Section, SectionHeader, type SectionHeaderProps, type SectionProps, StatChip, type StatChipProps, Tab, TabBar, type TabBarProps, type TabProps, ThemeButton, type ThemeButtonProps, ThemeDialog, type ThemeDialogProps, Watermark, type WatermarkProps, colors, fontFamily, fonts };
|
package/dist/index.d.ts
CHANGED
|
@@ -110,4 +110,76 @@ interface WatermarkProps {
|
|
|
110
110
|
*/
|
|
111
111
|
declare function Watermark({ children, color, text, maxWidth, padding, }: WatermarkProps): react_jsx_runtime.JSX.Element;
|
|
112
112
|
|
|
113
|
-
|
|
113
|
+
declare const colors: {
|
|
114
|
+
readonly blue: "#3b82f6";
|
|
115
|
+
readonly purple: "#8b5cf6";
|
|
116
|
+
readonly green: "#10b981";
|
|
117
|
+
readonly orange: "#f97316";
|
|
118
|
+
readonly pink: "#ec4899";
|
|
119
|
+
readonly red: "#ef4444";
|
|
120
|
+
readonly yellow: "#eab308";
|
|
121
|
+
readonly cyan: "#06b6d4";
|
|
122
|
+
readonly slate: "#0f172a";
|
|
123
|
+
readonly zinc: "#27272a";
|
|
124
|
+
};
|
|
125
|
+
type ColorName = keyof typeof colors;
|
|
126
|
+
|
|
127
|
+
interface ThemeButtonProps {
|
|
128
|
+
color: string;
|
|
129
|
+
onClick: () => void;
|
|
130
|
+
className?: string;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Small circular button showing the current theme color.
|
|
134
|
+
* Designed for the AppShellHeader top-right slot.
|
|
135
|
+
*/
|
|
136
|
+
declare function ThemeButton({ color, onClick, className }: ThemeButtonProps): react_jsx_runtime.JSX.Element;
|
|
137
|
+
interface ThemeDialogProps {
|
|
138
|
+
open: boolean;
|
|
139
|
+
onClose: () => void;
|
|
140
|
+
current: string;
|
|
141
|
+
onSelect: (color: string) => void;
|
|
142
|
+
/** Override the color palette. Defaults to built-in colors. */
|
|
143
|
+
palette?: Record<string, string>;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Bottom-sheet style color picker dialog.
|
|
147
|
+
* Shows a 5-column grid of color circles with check on the active one.
|
|
148
|
+
*/
|
|
149
|
+
declare function ThemeDialog({ open, onClose, current, onSelect, palette, }: ThemeDialogProps): react_jsx_runtime.JSX.Element | null;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Font presets for @m1kapp/ui.
|
|
153
|
+
* These return CSS @import strings to load fonts from official CDNs.
|
|
154
|
+
* No font files are bundled — only references to the original sources.
|
|
155
|
+
*/
|
|
156
|
+
declare const fonts: {
|
|
157
|
+
/** Toss Product Sans — from toss.im (free for commercial use) */
|
|
158
|
+
readonly toss: "https://static.toss.im/dist/tps.css";
|
|
159
|
+
/** Pretendard — popular Korean web font */
|
|
160
|
+
readonly pretendard: "https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css";
|
|
161
|
+
/** Inter — clean Latin sans-serif */
|
|
162
|
+
readonly inter: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&display=swap";
|
|
163
|
+
};
|
|
164
|
+
type FontName = keyof typeof fonts;
|
|
165
|
+
/**
|
|
166
|
+
* Returns a <link> href for the given font preset.
|
|
167
|
+
* Usage in your HTML head or via a <link> tag:
|
|
168
|
+
*
|
|
169
|
+
* ```tsx
|
|
170
|
+
* <link rel="stylesheet" href={fonts.toss} />
|
|
171
|
+
* ```
|
|
172
|
+
*
|
|
173
|
+
* Or in CSS:
|
|
174
|
+
* ```css
|
|
175
|
+
* @import url("https://static.toss.im/dist/tps.css");
|
|
176
|
+
* body { font-family: "Toss Product Sans", sans-serif; }
|
|
177
|
+
* ```
|
|
178
|
+
*/
|
|
179
|
+
declare const fontFamily: {
|
|
180
|
+
readonly toss: "\"Toss Product Sans\", \"Pretendard\", system-ui, sans-serif";
|
|
181
|
+
readonly pretendard: "\"Pretendard Variable\", \"Pretendard\", system-ui, sans-serif";
|
|
182
|
+
readonly inter: "\"Inter\", system-ui, sans-serif";
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export { AppShell, AppShellContent, type AppShellContentProps, AppShellHeader, type AppShellHeaderProps, type AppShellProps, type ColorName, Divider, EmptyState, type EmptyStateProps, type FontName, Section, SectionHeader, type SectionHeaderProps, type SectionProps, StatChip, type StatChipProps, Tab, TabBar, type TabBarProps, type TabProps, ThemeButton, type ThemeButtonProps, ThemeDialog, type ThemeDialogProps, Watermark, type WatermarkProps, colors, fontFamily, fonts };
|
package/dist/index.js
CHANGED
|
@@ -1,194 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
"use strict";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
-
};
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
-
for (let key of __getOwnPropNames(from))
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
-
}
|
|
17
|
-
return to;
|
|
18
|
-
};
|
|
19
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
-
|
|
21
|
-
// src/index.ts
|
|
22
|
-
var index_exports = {};
|
|
23
|
-
__export(index_exports, {
|
|
24
|
-
AppShell: () => AppShell,
|
|
25
|
-
AppShellContent: () => AppShellContent,
|
|
26
|
-
AppShellHeader: () => AppShellHeader,
|
|
27
|
-
Divider: () => Divider,
|
|
28
|
-
EmptyState: () => EmptyState,
|
|
29
|
-
Section: () => Section,
|
|
30
|
-
SectionHeader: () => SectionHeader,
|
|
31
|
-
StatChip: () => StatChip,
|
|
32
|
-
Tab: () => Tab,
|
|
33
|
-
TabBar: () => TabBar,
|
|
34
|
-
Watermark: () => Watermark
|
|
35
|
-
});
|
|
36
|
-
module.exports = __toCommonJS(index_exports);
|
|
37
|
-
|
|
38
|
-
// src/components/app-shell.tsx
|
|
39
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
40
|
-
function AppShell({
|
|
41
|
-
children,
|
|
42
|
-
className = "",
|
|
43
|
-
maxWidth = 430,
|
|
44
|
-
style
|
|
45
|
-
}) {
|
|
46
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
47
|
-
"div",
|
|
48
|
-
{
|
|
49
|
-
className: `w-full h-full flex flex-col bg-white dark:bg-zinc-950 shadow-2xl ring-1 ring-black/5 dark:ring-white/10 rounded-2xl overflow-hidden ${className}`,
|
|
50
|
-
style: { maxWidth, ...style },
|
|
51
|
-
children
|
|
52
|
-
}
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
function AppShellHeader({ children, className = "" }) {
|
|
56
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
57
|
-
"header",
|
|
58
|
-
{
|
|
59
|
-
className: `sticky top-0 z-20 px-4 py-3 flex items-center justify-between border-b border-zinc-100 dark:border-zinc-800 bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-t-2xl ${className}`,
|
|
60
|
-
children
|
|
61
|
-
}
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
function AppShellContent({ children, className = "" }) {
|
|
65
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: `flex-1 overflow-y-auto ${className}`, children });
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/components/tab-bar.tsx
|
|
69
|
-
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
70
|
-
function TabBar({ children, className = "" }) {
|
|
71
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
72
|
-
"nav",
|
|
73
|
-
{
|
|
74
|
-
className: `sticky bottom-0 z-20 border-t border-zinc-200 dark:border-zinc-800 flex bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-b-2xl ${className}`,
|
|
75
|
-
children
|
|
76
|
-
}
|
|
77
|
-
);
|
|
78
|
-
}
|
|
79
|
-
function Tab({ active, onClick, icon, label, activeColor }) {
|
|
80
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
81
|
-
"button",
|
|
82
|
-
{
|
|
83
|
-
onClick,
|
|
84
|
-
className: `flex-1 flex flex-col items-center gap-0.5 py-2.5 transition-colors ${!active ? "text-zinc-300 dark:text-zinc-600" : ""}`,
|
|
85
|
-
style: active ? { color: activeColor } : void 0,
|
|
86
|
-
children: [
|
|
87
|
-
icon,
|
|
88
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[10px] font-medium", children: label })
|
|
89
|
-
]
|
|
90
|
-
}
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// src/components/section.tsx
|
|
95
|
-
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
96
|
-
function Section({ children, className = "" }) {
|
|
97
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("section", { className: `px-4 ${className}`, children });
|
|
98
|
-
}
|
|
99
|
-
function SectionHeader({ children }) {
|
|
100
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "text-[11px] font-semibold text-zinc-400 dark:text-zinc-500 uppercase tracking-wider mb-3", children });
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// src/components/divider.tsx
|
|
104
|
-
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
105
|
-
function Divider({ className = "" }) {
|
|
106
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: `mx-4 my-6 h-px bg-zinc-200 dark:bg-zinc-800 ${className}` });
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
// src/components/stat-chip.tsx
|
|
110
|
-
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
111
|
-
function StatChip({ label, value, className = "" }) {
|
|
112
|
-
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `flex-1 rounded-xl bg-zinc-100 dark:bg-zinc-900 px-3 py-3 text-center ${className}`, children: [
|
|
113
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[10px] text-zinc-500 dark:text-zinc-400 font-medium mb-0.5", children: label }),
|
|
114
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-lg font-bold tabular-nums text-zinc-900 dark:text-white", children: value.toLocaleString() })
|
|
115
|
-
] });
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// src/components/empty-state.tsx
|
|
119
|
-
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
120
|
-
function EmptyState({ message, icon }) {
|
|
121
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 gap-2", children: [
|
|
122
|
-
icon || /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: "text-zinc-200 dark:text-zinc-700", children: [
|
|
123
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
124
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M8 15h8" }),
|
|
125
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "9", cy: "9", r: "1", fill: "currentColor", stroke: "none" }),
|
|
126
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "15", cy: "9", r: "1", fill: "currentColor", stroke: "none" })
|
|
127
|
-
] }),
|
|
128
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-sm text-zinc-400 dark:text-zinc-500", children: message })
|
|
129
|
-
] });
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// src/components/watermark.tsx
|
|
133
|
-
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
134
|
-
function buildSvgPattern(text, opacity = 0.08) {
|
|
135
|
-
const w = 220;
|
|
136
|
-
const h = 120;
|
|
137
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}">
|
|
138
|
-
<text x="10" y="45" font-family="system-ui,sans-serif" font-size="44" font-weight="900" fill="white" opacity="${opacity}">${text}</text>
|
|
139
|
-
<text x="120" y="100" font-family="system-ui,sans-serif" font-size="44" font-weight="900" fill="white" opacity="${opacity}">${text}</text>
|
|
140
|
-
</svg>`;
|
|
141
|
-
return `url("data:image/svg+xml,${encodeURIComponent(svg)}")`;
|
|
142
|
-
}
|
|
143
|
-
function Watermark({
|
|
144
|
-
children,
|
|
145
|
-
color = "#0f172a",
|
|
146
|
-
text = "m1k",
|
|
147
|
-
maxWidth = 430,
|
|
148
|
-
padding = 12
|
|
149
|
-
}) {
|
|
150
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
151
|
-
"div",
|
|
152
|
-
{
|
|
153
|
-
className: "h-dvh w-full relative overflow-hidden",
|
|
154
|
-
style: { backgroundColor: color, transition: "background-color 0.5s ease" },
|
|
155
|
-
children: [
|
|
156
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
157
|
-
"div",
|
|
158
|
-
{
|
|
159
|
-
className: "absolute inset-0 pointer-events-none select-none",
|
|
160
|
-
style: {
|
|
161
|
-
backgroundImage: buildSvgPattern(text),
|
|
162
|
-
backgroundRepeat: "repeat",
|
|
163
|
-
transform: "rotate(-12deg) scale(1.5)",
|
|
164
|
-
transformOrigin: "center center"
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
),
|
|
168
|
-
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
169
|
-
"div",
|
|
170
|
-
{
|
|
171
|
-
className: "relative z-10 h-full flex items-center justify-center mx-auto",
|
|
172
|
-
style: { maxWidth, padding },
|
|
173
|
-
children
|
|
174
|
-
}
|
|
175
|
-
)
|
|
176
|
-
]
|
|
177
|
-
}
|
|
178
|
-
);
|
|
179
|
-
}
|
|
180
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
181
|
-
0 && (module.exports = {
|
|
182
|
-
AppShell,
|
|
183
|
-
AppShellContent,
|
|
184
|
-
AppShellHeader,
|
|
185
|
-
Divider,
|
|
186
|
-
EmptyState,
|
|
187
|
-
Section,
|
|
188
|
-
SectionHeader,
|
|
189
|
-
StatChip,
|
|
190
|
-
Tab,
|
|
191
|
-
TabBar,
|
|
192
|
-
Watermark
|
|
193
|
-
});
|
|
194
|
-
//# sourceMappingURL=index.js.map
|
|
2
|
+
"use strict";var x=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var W=Object.getOwnPropertyNames;var D=Object.prototype.hasOwnProperty;var L=(e,t)=>{for(var r in t)x(e,r,{get:t[r],enumerable:!0})},F=(e,t,r,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of W(t))!D.call(e,n)&&n!==r&&x(e,n,{get:()=>t[n],enumerable:!(s=H(t,n))||s.enumerable});return e};var I=e=>F(x({},"__esModule",{value:!0}),e);var O={};L(O,{AppShell:()=>b,AppShellContent:()=>g,AppShellHeader:()=>u,Divider:()=>w,EmptyState:()=>S,Section:()=>v,SectionHeader:()=>N,StatChip:()=>P,Tab:()=>k,TabBar:()=>y,ThemeButton:()=>R,ThemeDialog:()=>$,Watermark:()=>C,colors:()=>f,fontFamily:()=>B,fonts:()=>A});module.exports=I(O);var m=require("react/jsx-runtime");function b({children:e,className:t="",maxWidth:r=430,style:s}){return(0,m.jsx)("div",{className:`w-full h-full flex flex-col bg-white dark:bg-zinc-950 shadow-2xl ring-1 ring-black/5 dark:ring-white/10 rounded-2xl overflow-hidden ${t}`,style:{maxWidth:r,...s},children:e})}function u({children:e,className:t=""}){return(0,m.jsx)("header",{className:`sticky top-0 z-20 px-4 py-3 flex items-center justify-between border-b border-zinc-100 dark:border-zinc-800 bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-t-2xl ${t}`,children:e})}function g({children:e,className:t=""}){return(0,m.jsx)("div",{className:`flex-1 overflow-y-auto scrollbar-hide ${t}`,children:e})}var p=require("react/jsx-runtime");function y({children:e,className:t=""}){return(0,p.jsx)("nav",{className:`sticky bottom-0 z-20 border-t border-zinc-200 dark:border-zinc-800 flex bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-b-2xl ${t}`,children:e})}function k({active:e,onClick:t,icon:r,label:s,activeColor:n}){return(0,p.jsxs)("button",{onClick:t,className:`flex-1 flex flex-col items-center gap-0.5 py-2.5 transition-colors ${e?"":"text-zinc-300 dark:text-zinc-600"}`,style:e?{color:n}:void 0,children:[r,(0,p.jsx)("span",{className:"text-[10px] font-medium",children:s})]})}var h=require("react/jsx-runtime");function v({children:e,className:t=""}){return(0,h.jsx)("section",{className:`px-4 ${t}`,children:e})}function N({children:e}){return(0,h.jsx)("h2",{className:"text-[11px] font-semibold text-zinc-400 dark:text-zinc-500 uppercase tracking-wider mb-3",children:e})}var z=require("react/jsx-runtime");function w({className:e=""}){return(0,z.jsx)("div",{className:`mx-4 my-6 h-px bg-zinc-200 dark:bg-zinc-800 ${e}`})}var l=require("react/jsx-runtime");function P({label:e,value:t,className:r=""}){return(0,l.jsxs)("div",{className:`flex-1 rounded-xl bg-zinc-100 dark:bg-zinc-900 px-3 py-3 text-center ${r}`,children:[(0,l.jsx)("p",{className:"text-[10px] text-zinc-500 dark:text-zinc-400 font-medium mb-0.5",children:e}),(0,l.jsx)("p",{className:"text-lg font-bold tabular-nums text-zinc-900 dark:text-white",children:t.toLocaleString()})]})}var a=require("react/jsx-runtime");function S({message:e,icon:t}){return(0,a.jsxs)("div",{className:"flex flex-col items-center justify-center py-12 gap-2",children:[t||(0,a.jsxs)("svg",{width:"32",height:"32",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",className:"text-zinc-200 dark:text-zinc-700",children:[(0,a.jsx)("circle",{cx:"12",cy:"12",r:"10"}),(0,a.jsx)("path",{d:"M8 15h8"}),(0,a.jsx)("circle",{cx:"9",cy:"9",r:"1",fill:"currentColor",stroke:"none"}),(0,a.jsx)("circle",{cx:"15",cy:"9",r:"1",fill:"currentColor",stroke:"none"})]}),(0,a.jsx)("p",{className:"text-sm text-zinc-400 dark:text-zinc-500",children:e})]})}var d=require("react/jsx-runtime");function j(e,t=.08){let n=`<svg xmlns="http://www.w3.org/2000/svg" width="220" height="120">
|
|
3
|
+
<text x="10" y="45" font-family="system-ui,sans-serif" font-size="44" font-weight="900" fill="white" opacity="${t}">${e}</text>
|
|
4
|
+
<text x="120" y="100" font-family="system-ui,sans-serif" font-size="44" font-weight="900" fill="white" opacity="${t}">${e}</text>
|
|
5
|
+
</svg>`;return`url("data:image/svg+xml,${encodeURIComponent(n)}")`}function C({children:e,color:t="#0f172a",text:r="m1k",maxWidth:s=430,padding:n=12}){return(0,d.jsxs)("div",{className:"h-dvh w-full relative overflow-hidden",style:{backgroundColor:t,transition:"background-color 0.5s ease"},children:[(0,d.jsx)("div",{className:"absolute inset-0 pointer-events-none select-none",style:{backgroundImage:j(r),backgroundRepeat:"repeat",transform:"rotate(-12deg) scale(1.5)",transformOrigin:"center center"}}),(0,d.jsx)("div",{className:"relative z-10 h-full flex items-center justify-center mx-auto",style:{maxWidth:s,padding:n},children:e})]})}var f={blue:"#3b82f6",purple:"#8b5cf6",green:"#10b981",orange:"#f97316",pink:"#ec4899",red:"#ef4444",yellow:"#eab308",cyan:"#06b6d4",slate:"#0f172a",zinc:"#27272a"};var T=require("react");var o=require("react/jsx-runtime");function R({color:e,onClick:t,className:r=""}){return(0,o.jsx)("button",{onClick:t,className:`w-7 h-7 rounded-full border-2 border-white dark:border-zinc-700 shadow-sm transition-transform hover:scale-110 ${r}`,style:{backgroundColor:e},title:"Change theme"})}function $({open:e,onClose:t,current:r,onSelect:s,palette:n=f}){if((0,T.useEffect)(()=>{if(!e)return;let c=i=>{i.key==="Escape"&&t()};return window.addEventListener("keydown",c),()=>window.removeEventListener("keydown",c)},[e,t]),!e)return null;let E=Object.entries(n);return(0,o.jsxs)("div",{className:"fixed inset-0 z-50 flex items-end justify-center",onClick:t,children:[(0,o.jsx)("div",{className:"absolute inset-0 bg-black/40 backdrop-blur-sm"}),(0,o.jsxs)("div",{className:"relative z-10 w-full max-w-[406px] mb-3 mx-3 rounded-2xl bg-white dark:bg-zinc-900 shadow-2xl overflow-hidden",onClick:c=>c.stopPropagation(),children:[(0,o.jsxs)("div",{className:"px-4 pt-4 pb-2",children:[(0,o.jsx)("p",{className:"text-sm font-bold text-zinc-900 dark:text-white",children:"Theme Color"}),(0,o.jsx)("p",{className:"text-xs text-zinc-400 dark:text-zinc-500 mt-0.5",children:"Change the Watermark background"})]}),(0,o.jsx)("div",{className:"px-4 pb-3 grid grid-cols-5 gap-3 justify-items-center",children:E.map(([c,i])=>(0,o.jsx)("button",{onClick:()=>{s(i),t()},className:`relative w-11 h-11 rounded-full transition-all hover:scale-110 ${r===i?"ring-2 ring-offset-2 ring-offset-white dark:ring-offset-zinc-900":""}`,style:{backgroundColor:i,...r===i?{"--tw-ring-color":i}:{}},children:r===i&&(0,o.jsx)("div",{className:"absolute inset-0 flex items-center justify-center",children:(0,o.jsx)("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"white",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round",children:(0,o.jsx)("polyline",{points:"20 6 9 17 4 12"})})})},i))}),(0,o.jsx)("div",{className:"px-4 py-3 border-t border-zinc-100 dark:border-zinc-800",children:(0,o.jsx)("button",{onClick:t,className:"w-full py-2.5 rounded-xl bg-zinc-100 dark:bg-zinc-800 text-sm font-medium text-zinc-600 dark:text-zinc-400 hover:bg-zinc-200 dark:hover:bg-zinc-700 transition-colors",children:"Close"})})]})]})}var A={toss:"https://static.toss.im/dist/tps.css",pretendard:"https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css",inter:"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&display=swap"},B={toss:'"Toss Product Sans", "Pretendard", system-ui, sans-serif',pretendard:'"Pretendard Variable", "Pretendard", system-ui, sans-serif',inter:'"Inter", system-ui, sans-serif'};0&&(module.exports={AppShell,AppShellContent,AppShellHeader,Divider,EmptyState,Section,SectionHeader,StatChip,Tab,TabBar,ThemeButton,ThemeDialog,Watermark,colors,fontFamily,fonts});
|
package/dist/index.mjs
CHANGED
|
@@ -1,158 +1,5 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
function
|
|
6
|
-
children,
|
|
7
|
-
className = "",
|
|
8
|
-
maxWidth = 430,
|
|
9
|
-
style
|
|
10
|
-
}) {
|
|
11
|
-
return /* @__PURE__ */ jsx(
|
|
12
|
-
"div",
|
|
13
|
-
{
|
|
14
|
-
className: `w-full h-full flex flex-col bg-white dark:bg-zinc-950 shadow-2xl ring-1 ring-black/5 dark:ring-white/10 rounded-2xl overflow-hidden ${className}`,
|
|
15
|
-
style: { maxWidth, ...style },
|
|
16
|
-
children
|
|
17
|
-
}
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
function AppShellHeader({ children, className = "" }) {
|
|
21
|
-
return /* @__PURE__ */ jsx(
|
|
22
|
-
"header",
|
|
23
|
-
{
|
|
24
|
-
className: `sticky top-0 z-20 px-4 py-3 flex items-center justify-between border-b border-zinc-100 dark:border-zinc-800 bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-t-2xl ${className}`,
|
|
25
|
-
children
|
|
26
|
-
}
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
function AppShellContent({ children, className = "" }) {
|
|
30
|
-
return /* @__PURE__ */ jsx("div", { className: `flex-1 overflow-y-auto ${className}`, children });
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// src/components/tab-bar.tsx
|
|
34
|
-
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
35
|
-
function TabBar({ children, className = "" }) {
|
|
36
|
-
return /* @__PURE__ */ jsx2(
|
|
37
|
-
"nav",
|
|
38
|
-
{
|
|
39
|
-
className: `sticky bottom-0 z-20 border-t border-zinc-200 dark:border-zinc-800 flex bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-b-2xl ${className}`,
|
|
40
|
-
children
|
|
41
|
-
}
|
|
42
|
-
);
|
|
43
|
-
}
|
|
44
|
-
function Tab({ active, onClick, icon, label, activeColor }) {
|
|
45
|
-
return /* @__PURE__ */ jsxs(
|
|
46
|
-
"button",
|
|
47
|
-
{
|
|
48
|
-
onClick,
|
|
49
|
-
className: `flex-1 flex flex-col items-center gap-0.5 py-2.5 transition-colors ${!active ? "text-zinc-300 dark:text-zinc-600" : ""}`,
|
|
50
|
-
style: active ? { color: activeColor } : void 0,
|
|
51
|
-
children: [
|
|
52
|
-
icon,
|
|
53
|
-
/* @__PURE__ */ jsx2("span", { className: "text-[10px] font-medium", children: label })
|
|
54
|
-
]
|
|
55
|
-
}
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// src/components/section.tsx
|
|
60
|
-
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
61
|
-
function Section({ children, className = "" }) {
|
|
62
|
-
return /* @__PURE__ */ jsx3("section", { className: `px-4 ${className}`, children });
|
|
63
|
-
}
|
|
64
|
-
function SectionHeader({ children }) {
|
|
65
|
-
return /* @__PURE__ */ jsx3("h2", { className: "text-[11px] font-semibold text-zinc-400 dark:text-zinc-500 uppercase tracking-wider mb-3", children });
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// src/components/divider.tsx
|
|
69
|
-
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
70
|
-
function Divider({ className = "" }) {
|
|
71
|
-
return /* @__PURE__ */ jsx4("div", { className: `mx-4 my-6 h-px bg-zinc-200 dark:bg-zinc-800 ${className}` });
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// src/components/stat-chip.tsx
|
|
75
|
-
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
76
|
-
function StatChip({ label, value, className = "" }) {
|
|
77
|
-
return /* @__PURE__ */ jsxs2("div", { className: `flex-1 rounded-xl bg-zinc-100 dark:bg-zinc-900 px-3 py-3 text-center ${className}`, children: [
|
|
78
|
-
/* @__PURE__ */ jsx5("p", { className: "text-[10px] text-zinc-500 dark:text-zinc-400 font-medium mb-0.5", children: label }),
|
|
79
|
-
/* @__PURE__ */ jsx5("p", { className: "text-lg font-bold tabular-nums text-zinc-900 dark:text-white", children: value.toLocaleString() })
|
|
80
|
-
] });
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// src/components/empty-state.tsx
|
|
84
|
-
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
85
|
-
function EmptyState({ message, icon }) {
|
|
86
|
-
return /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center py-12 gap-2", children: [
|
|
87
|
-
icon || /* @__PURE__ */ jsxs3("svg", { width: "32", height: "32", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: "text-zinc-200 dark:text-zinc-700", children: [
|
|
88
|
-
/* @__PURE__ */ jsx6("circle", { cx: "12", cy: "12", r: "10" }),
|
|
89
|
-
/* @__PURE__ */ jsx6("path", { d: "M8 15h8" }),
|
|
90
|
-
/* @__PURE__ */ jsx6("circle", { cx: "9", cy: "9", r: "1", fill: "currentColor", stroke: "none" }),
|
|
91
|
-
/* @__PURE__ */ jsx6("circle", { cx: "15", cy: "9", r: "1", fill: "currentColor", stroke: "none" })
|
|
92
|
-
] }),
|
|
93
|
-
/* @__PURE__ */ jsx6("p", { className: "text-sm text-zinc-400 dark:text-zinc-500", children: message })
|
|
94
|
-
] });
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// src/components/watermark.tsx
|
|
98
|
-
import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
99
|
-
function buildSvgPattern(text, opacity = 0.08) {
|
|
100
|
-
const w = 220;
|
|
101
|
-
const h = 120;
|
|
102
|
-
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}">
|
|
103
|
-
<text x="10" y="45" font-family="system-ui,sans-serif" font-size="44" font-weight="900" fill="white" opacity="${opacity}">${text}</text>
|
|
104
|
-
<text x="120" y="100" font-family="system-ui,sans-serif" font-size="44" font-weight="900" fill="white" opacity="${opacity}">${text}</text>
|
|
105
|
-
</svg>`;
|
|
106
|
-
return `url("data:image/svg+xml,${encodeURIComponent(svg)}")`;
|
|
107
|
-
}
|
|
108
|
-
function Watermark({
|
|
109
|
-
children,
|
|
110
|
-
color = "#0f172a",
|
|
111
|
-
text = "m1k",
|
|
112
|
-
maxWidth = 430,
|
|
113
|
-
padding = 12
|
|
114
|
-
}) {
|
|
115
|
-
return /* @__PURE__ */ jsxs4(
|
|
116
|
-
"div",
|
|
117
|
-
{
|
|
118
|
-
className: "h-dvh w-full relative overflow-hidden",
|
|
119
|
-
style: { backgroundColor: color, transition: "background-color 0.5s ease" },
|
|
120
|
-
children: [
|
|
121
|
-
/* @__PURE__ */ jsx7(
|
|
122
|
-
"div",
|
|
123
|
-
{
|
|
124
|
-
className: "absolute inset-0 pointer-events-none select-none",
|
|
125
|
-
style: {
|
|
126
|
-
backgroundImage: buildSvgPattern(text),
|
|
127
|
-
backgroundRepeat: "repeat",
|
|
128
|
-
transform: "rotate(-12deg) scale(1.5)",
|
|
129
|
-
transformOrigin: "center center"
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
),
|
|
133
|
-
/* @__PURE__ */ jsx7(
|
|
134
|
-
"div",
|
|
135
|
-
{
|
|
136
|
-
className: "relative z-10 h-full flex items-center justify-center mx-auto",
|
|
137
|
-
style: { maxWidth, padding },
|
|
138
|
-
children
|
|
139
|
-
}
|
|
140
|
-
)
|
|
141
|
-
]
|
|
142
|
-
}
|
|
143
|
-
);
|
|
144
|
-
}
|
|
145
|
-
export {
|
|
146
|
-
AppShell,
|
|
147
|
-
AppShellContent,
|
|
148
|
-
AppShellHeader,
|
|
149
|
-
Divider,
|
|
150
|
-
EmptyState,
|
|
151
|
-
Section,
|
|
152
|
-
SectionHeader,
|
|
153
|
-
StatChip,
|
|
154
|
-
Tab,
|
|
155
|
-
TabBar,
|
|
156
|
-
Watermark
|
|
157
|
-
};
|
|
158
|
-
//# sourceMappingURL=index.mjs.map
|
|
2
|
+
import{jsx as p}from"react/jsx-runtime";function g({children:e,className:t="",maxWidth:r=430,style:s}){return p("div",{className:`w-full h-full flex flex-col bg-white dark:bg-zinc-950 shadow-2xl ring-1 ring-black/5 dark:ring-white/10 rounded-2xl overflow-hidden ${t}`,style:{maxWidth:r,...s},children:e})}function y({children:e,className:t=""}){return p("header",{className:`sticky top-0 z-20 px-4 py-3 flex items-center justify-between border-b border-zinc-100 dark:border-zinc-800 bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-t-2xl ${t}`,children:e})}function k({children:e,className:t=""}){return p("div",{className:`flex-1 overflow-y-auto scrollbar-hide ${t}`,children:e})}import{jsx as m,jsxs as w}from"react/jsx-runtime";function v({children:e,className:t=""}){return m("nav",{className:`sticky bottom-0 z-20 border-t border-zinc-200 dark:border-zinc-800 flex bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-b-2xl ${t}`,children:e})}function N({active:e,onClick:t,icon:r,label:s,activeColor:i}){return w("button",{onClick:t,className:`flex-1 flex flex-col items-center gap-0.5 py-2.5 transition-colors ${e?"":"text-zinc-300 dark:text-zinc-600"}`,style:e?{color:i}:void 0,children:[r,m("span",{className:"text-[10px] font-medium",children:s})]})}import{jsx as f}from"react/jsx-runtime";function z({children:e,className:t=""}){return f("section",{className:`px-4 ${t}`,children:e})}function P({children:e}){return f("h2",{className:"text-[11px] font-semibold text-zinc-400 dark:text-zinc-500 uppercase tracking-wider mb-3",children:e})}import{jsx as C}from"react/jsx-runtime";function S({className:e=""}){return C("div",{className:`mx-4 my-6 h-px bg-zinc-200 dark:bg-zinc-800 ${e}`})}import{jsx as x,jsxs as R}from"react/jsx-runtime";function T({label:e,value:t,className:r=""}){return R("div",{className:`flex-1 rounded-xl bg-zinc-100 dark:bg-zinc-900 px-3 py-3 text-center ${r}`,children:[x("p",{className:"text-[10px] text-zinc-500 dark:text-zinc-400 font-medium mb-0.5",children:e}),x("p",{className:"text-lg font-bold tabular-nums text-zinc-900 dark:text-white",children:t.toLocaleString()})]})}import{jsx as c,jsxs as h}from"react/jsx-runtime";function $({message:e,icon:t}){return h("div",{className:"flex flex-col items-center justify-center py-12 gap-2",children:[t||h("svg",{width:"32",height:"32",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round",className:"text-zinc-200 dark:text-zinc-700",children:[c("circle",{cx:"12",cy:"12",r:"10"}),c("path",{d:"M8 15h8"}),c("circle",{cx:"9",cy:"9",r:"1",fill:"currentColor",stroke:"none"}),c("circle",{cx:"15",cy:"9",r:"1",fill:"currentColor",stroke:"none"})]}),c("p",{className:"text-sm text-zinc-400 dark:text-zinc-500",children:e})]})}import{jsx as b,jsxs as E}from"react/jsx-runtime";function A(e,t=.08){let i=`<svg xmlns="http://www.w3.org/2000/svg" width="220" height="120">
|
|
3
|
+
<text x="10" y="45" font-family="system-ui,sans-serif" font-size="44" font-weight="900" fill="white" opacity="${t}">${e}</text>
|
|
4
|
+
<text x="120" y="100" font-family="system-ui,sans-serif" font-size="44" font-weight="900" fill="white" opacity="${t}">${e}</text>
|
|
5
|
+
</svg>`;return`url("data:image/svg+xml,${encodeURIComponent(i)}")`}function B({children:e,color:t="#0f172a",text:r="m1k",maxWidth:s=430,padding:i=12}){return E("div",{className:"h-dvh w-full relative overflow-hidden",style:{backgroundColor:t,transition:"background-color 0.5s ease"},children:[b("div",{className:"absolute inset-0 pointer-events-none select-none",style:{backgroundImage:A(r),backgroundRepeat:"repeat",transform:"rotate(-12deg) scale(1.5)",transformOrigin:"center center"}}),b("div",{className:"relative z-10 h-full flex items-center justify-center mx-auto",style:{maxWidth:s,padding:i},children:e})]})}var l={blue:"#3b82f6",purple:"#8b5cf6",green:"#10b981",orange:"#f97316",pink:"#ec4899",red:"#ef4444",yellow:"#eab308",cyan:"#06b6d4",slate:"#0f172a",zinc:"#27272a"};import{useEffect as H}from"react";import{jsx as o,jsxs as d}from"react/jsx-runtime";function W({color:e,onClick:t,className:r=""}){return o("button",{onClick:t,className:`w-7 h-7 rounded-full border-2 border-white dark:border-zinc-700 shadow-sm transition-transform hover:scale-110 ${r}`,style:{backgroundColor:e},title:"Change theme"})}function D({open:e,onClose:t,current:r,onSelect:s,palette:i=l}){if(H(()=>{if(!e)return;let a=n=>{n.key==="Escape"&&t()};return window.addEventListener("keydown",a),()=>window.removeEventListener("keydown",a)},[e,t]),!e)return null;let u=Object.entries(i);return d("div",{className:"fixed inset-0 z-50 flex items-end justify-center",onClick:t,children:[o("div",{className:"absolute inset-0 bg-black/40 backdrop-blur-sm"}),d("div",{className:"relative z-10 w-full max-w-[406px] mb-3 mx-3 rounded-2xl bg-white dark:bg-zinc-900 shadow-2xl overflow-hidden",onClick:a=>a.stopPropagation(),children:[d("div",{className:"px-4 pt-4 pb-2",children:[o("p",{className:"text-sm font-bold text-zinc-900 dark:text-white",children:"Theme Color"}),o("p",{className:"text-xs text-zinc-400 dark:text-zinc-500 mt-0.5",children:"Change the Watermark background"})]}),o("div",{className:"px-4 pb-3 grid grid-cols-5 gap-3 justify-items-center",children:u.map(([a,n])=>o("button",{onClick:()=>{s(n),t()},className:`relative w-11 h-11 rounded-full transition-all hover:scale-110 ${r===n?"ring-2 ring-offset-2 ring-offset-white dark:ring-offset-zinc-900":""}`,style:{backgroundColor:n,...r===n?{"--tw-ring-color":n}:{}},children:r===n&&o("div",{className:"absolute inset-0 flex items-center justify-center",children:o("svg",{width:"16",height:"16",viewBox:"0 0 24 24",fill:"none",stroke:"white",strokeWidth:"3",strokeLinecap:"round",strokeLinejoin:"round",children:o("polyline",{points:"20 6 9 17 4 12"})})})},n))}),o("div",{className:"px-4 py-3 border-t border-zinc-100 dark:border-zinc-800",children:o("button",{onClick:t,className:"w-full py-2.5 rounded-xl bg-zinc-100 dark:bg-zinc-800 text-sm font-medium text-zinc-600 dark:text-zinc-400 hover:bg-zinc-200 dark:hover:bg-zinc-700 transition-colors",children:"Close"})})]})]})}var L={toss:"https://static.toss.im/dist/tps.css",pretendard:"https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css",inter:"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&display=swap"},F={toss:'"Toss Product Sans", "Pretendard", system-ui, sans-serif',pretendard:'"Pretendard Variable", "Pretendard", system-ui, sans-serif',inter:'"Inter", system-ui, sans-serif'};export{g as AppShell,k as AppShellContent,y as AppShellHeader,S as Divider,$ as EmptyState,z as Section,P as SectionHeader,T as StatChip,N as Tab,v as TabBar,W as ThemeButton,D as ThemeDialog,B as Watermark,l as colors,F as fontFamily,L as fonts};
|
package/package.json
CHANGED
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/components/app-shell.tsx","../src/components/tab-bar.tsx","../src/components/section.tsx","../src/components/divider.tsx","../src/components/stat-chip.tsx","../src/components/empty-state.tsx","../src/components/watermark.tsx"],"sourcesContent":["export { AppShell, AppShellHeader, AppShellContent } from \"./components/app-shell\";\nexport type { AppShellProps, AppShellHeaderProps, AppShellContentProps } from \"./components/app-shell\";\n\nexport { TabBar, Tab } from \"./components/tab-bar\";\nexport type { TabBarProps, TabProps } from \"./components/tab-bar\";\n\nexport { Section, SectionHeader } from \"./components/section\";\nexport type { SectionProps, SectionHeaderProps } from \"./components/section\";\n\nexport { Divider } from \"./components/divider\";\n\nexport { StatChip } from \"./components/stat-chip\";\nexport type { StatChipProps } from \"./components/stat-chip\";\n\nexport { EmptyState } from \"./components/empty-state\";\nexport type { EmptyStateProps } from \"./components/empty-state\";\n\nexport { Watermark } from \"./components/watermark\";\nexport type { WatermarkProps } from \"./components/watermark\";\n","import { type ReactNode, type CSSProperties } from \"react\";\n\nexport interface AppShellProps {\n children: ReactNode;\n className?: string;\n /** Max width of the shell. Default: 430px */\n maxWidth?: number;\n style?: CSSProperties;\n}\n\n/**\n * Mobile app-like container with rounded corners, shadow, and ring.\n * Centers content and constrains width for a phone-like viewport.\n */\nexport function AppShell({\n children,\n className = \"\",\n maxWidth = 430,\n style,\n}: AppShellProps) {\n return (\n <div\n className={`w-full h-full flex flex-col bg-white dark:bg-zinc-950 shadow-2xl ring-1 ring-black/5 dark:ring-white/10 rounded-2xl overflow-hidden ${className}`}\n style={{ maxWidth, ...style }}\n >\n {children}\n </div>\n );\n}\n\nexport interface AppShellHeaderProps {\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Sticky top header with blur backdrop.\n */\nexport function AppShellHeader({ children, className = \"\" }: AppShellHeaderProps) {\n return (\n <header\n className={`sticky top-0 z-20 px-4 py-3 flex items-center justify-between border-b border-zinc-100 dark:border-zinc-800 bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-t-2xl ${className}`}\n >\n {children}\n </header>\n );\n}\n\nexport interface AppShellContentProps {\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Scrollable main content area.\n */\nexport function AppShellContent({ children, className = \"\" }: AppShellContentProps) {\n return (\n <div className={`flex-1 overflow-y-auto ${className}`}>\n {children}\n </div>\n );\n}\n","import { type ReactNode } from \"react\";\n\nexport interface TabBarProps {\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Sticky bottom navigation tab bar.\n */\nexport function TabBar({ children, className = \"\" }: TabBarProps) {\n return (\n <nav\n className={`sticky bottom-0 z-20 border-t border-zinc-200 dark:border-zinc-800 flex bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-b-2xl ${className}`}\n >\n {children}\n </nav>\n );\n}\n\nexport interface TabProps {\n active: boolean;\n onClick: () => void;\n icon: ReactNode;\n label: string;\n /** Active tab color. Default: current text color */\n activeColor?: string;\n}\n\n/**\n * Individual tab button for the TabBar.\n */\nexport function Tab({ active, onClick, icon, label, activeColor }: TabProps) {\n return (\n <button\n onClick={onClick}\n className={`flex-1 flex flex-col items-center gap-0.5 py-2.5 transition-colors ${\n !active ? \"text-zinc-300 dark:text-zinc-600\" : \"\"\n }`}\n style={active ? { color: activeColor } : undefined}\n >\n {icon}\n <span className=\"text-[10px] font-medium\">{label}</span>\n </button>\n );\n}\n","import { type ReactNode } from \"react\";\n\nexport interface SectionProps {\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Padded section wrapper (px-4).\n */\nexport function Section({ children, className = \"\" }: SectionProps) {\n return <section className={`px-4 ${className}`}>{children}</section>;\n}\n\nexport interface SectionHeaderProps {\n children: ReactNode;\n}\n\n/**\n * Small uppercase section title.\n */\nexport function SectionHeader({ children }: SectionHeaderProps) {\n return (\n <h2 className=\"text-[11px] font-semibold text-zinc-400 dark:text-zinc-500 uppercase tracking-wider mb-3\">\n {children}\n </h2>\n );\n}\n","/**\n * Horizontal divider line with margin.\n */\nexport function Divider({ className = \"\" }: { className?: string }) {\n return <div className={`mx-4 my-6 h-px bg-zinc-200 dark:bg-zinc-800 ${className}`} />;\n}\n","export interface StatChipProps {\n label: string;\n value: number;\n className?: string;\n}\n\n/**\n * Compact stat display chip with label and number.\n */\nexport function StatChip({ label, value, className = \"\" }: StatChipProps) {\n return (\n <div className={`flex-1 rounded-xl bg-zinc-100 dark:bg-zinc-900 px-3 py-3 text-center ${className}`}>\n <p className=\"text-[10px] text-zinc-500 dark:text-zinc-400 font-medium mb-0.5\">\n {label}\n </p>\n <p className=\"text-lg font-bold tabular-nums text-zinc-900 dark:text-white\">\n {value.toLocaleString()}\n </p>\n </div>\n );\n}\n","import { type ReactNode } from \"react\";\n\nexport interface EmptyStateProps {\n message: string;\n icon?: ReactNode;\n}\n\n/**\n * Empty state placeholder with icon and message.\n */\nexport function EmptyState({ message, icon }: EmptyStateProps) {\n return (\n <div className=\"flex flex-col items-center justify-center py-12 gap-2\">\n {icon || (\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className=\"text-zinc-200 dark:text-zinc-700\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M8 15h8\" />\n <circle cx=\"9\" cy=\"9\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"15\" cy=\"9\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n )}\n <p className=\"text-sm text-zinc-400 dark:text-zinc-500\">{message}</p>\n </div>\n );\n}\n","import { type ReactNode } from \"react\";\n\nexport interface WatermarkProps {\n children: ReactNode;\n /** Background color */\n color?: string;\n /** Watermark text. Default: \"m1k\" */\n text?: string;\n /** Max width of content area. Default: 430 */\n maxWidth?: number;\n /** Padding around the app shell. Default: 12px */\n padding?: number;\n}\n\nfunction buildSvgPattern(text: string, opacity: number = 0.08): string {\n const w = 220;\n const h = 120;\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${w}\" height=\"${h}\">\n <text x=\"10\" y=\"45\" font-family=\"system-ui,sans-serif\" font-size=\"44\" font-weight=\"900\" fill=\"white\" opacity=\"${opacity}\">${text}</text>\n <text x=\"120\" y=\"100\" font-family=\"system-ui,sans-serif\" font-size=\"44\" font-weight=\"900\" fill=\"white\" opacity=\"${opacity}\">${text}</text>\n </svg>`;\n return `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`;\n}\n\n/**\n * Full-screen colored background with repeating text watermark pattern.\n * Wraps the AppShell and provides the \"floating app\" look.\n */\nexport function Watermark({\n children,\n color = \"#0f172a\",\n text = \"m1k\",\n maxWidth = 430,\n padding = 12,\n}: WatermarkProps) {\n return (\n <div\n className=\"h-dvh w-full relative overflow-hidden\"\n style={{ backgroundColor: color, transition: \"background-color 0.5s ease\" }}\n >\n <div\n className=\"absolute inset-0 pointer-events-none select-none\"\n style={{\n backgroundImage: buildSvgPattern(text),\n backgroundRepeat: \"repeat\",\n transform: \"rotate(-12deg) scale(1.5)\",\n transformOrigin: \"center center\",\n }}\n />\n <div\n className=\"relative z-10 h-full flex items-center justify-center mx-auto\"\n style={{ maxWidth, padding }}\n >\n {children}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
|
package/dist/index.mjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/app-shell.tsx","../src/components/tab-bar.tsx","../src/components/section.tsx","../src/components/divider.tsx","../src/components/stat-chip.tsx","../src/components/empty-state.tsx","../src/components/watermark.tsx"],"sourcesContent":["import { type ReactNode, type CSSProperties } from \"react\";\n\nexport interface AppShellProps {\n children: ReactNode;\n className?: string;\n /** Max width of the shell. Default: 430px */\n maxWidth?: number;\n style?: CSSProperties;\n}\n\n/**\n * Mobile app-like container with rounded corners, shadow, and ring.\n * Centers content and constrains width for a phone-like viewport.\n */\nexport function AppShell({\n children,\n className = \"\",\n maxWidth = 430,\n style,\n}: AppShellProps) {\n return (\n <div\n className={`w-full h-full flex flex-col bg-white dark:bg-zinc-950 shadow-2xl ring-1 ring-black/5 dark:ring-white/10 rounded-2xl overflow-hidden ${className}`}\n style={{ maxWidth, ...style }}\n >\n {children}\n </div>\n );\n}\n\nexport interface AppShellHeaderProps {\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Sticky top header with blur backdrop.\n */\nexport function AppShellHeader({ children, className = \"\" }: AppShellHeaderProps) {\n return (\n <header\n className={`sticky top-0 z-20 px-4 py-3 flex items-center justify-between border-b border-zinc-100 dark:border-zinc-800 bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-t-2xl ${className}`}\n >\n {children}\n </header>\n );\n}\n\nexport interface AppShellContentProps {\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Scrollable main content area.\n */\nexport function AppShellContent({ children, className = \"\" }: AppShellContentProps) {\n return (\n <div className={`flex-1 overflow-y-auto ${className}`}>\n {children}\n </div>\n );\n}\n","import { type ReactNode } from \"react\";\n\nexport interface TabBarProps {\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Sticky bottom navigation tab bar.\n */\nexport function TabBar({ children, className = \"\" }: TabBarProps) {\n return (\n <nav\n className={`sticky bottom-0 z-20 border-t border-zinc-200 dark:border-zinc-800 flex bg-white/90 dark:bg-zinc-950/90 backdrop-blur-md rounded-b-2xl ${className}`}\n >\n {children}\n </nav>\n );\n}\n\nexport interface TabProps {\n active: boolean;\n onClick: () => void;\n icon: ReactNode;\n label: string;\n /** Active tab color. Default: current text color */\n activeColor?: string;\n}\n\n/**\n * Individual tab button for the TabBar.\n */\nexport function Tab({ active, onClick, icon, label, activeColor }: TabProps) {\n return (\n <button\n onClick={onClick}\n className={`flex-1 flex flex-col items-center gap-0.5 py-2.5 transition-colors ${\n !active ? \"text-zinc-300 dark:text-zinc-600\" : \"\"\n }`}\n style={active ? { color: activeColor } : undefined}\n >\n {icon}\n <span className=\"text-[10px] font-medium\">{label}</span>\n </button>\n );\n}\n","import { type ReactNode } from \"react\";\n\nexport interface SectionProps {\n children: ReactNode;\n className?: string;\n}\n\n/**\n * Padded section wrapper (px-4).\n */\nexport function Section({ children, className = \"\" }: SectionProps) {\n return <section className={`px-4 ${className}`}>{children}</section>;\n}\n\nexport interface SectionHeaderProps {\n children: ReactNode;\n}\n\n/**\n * Small uppercase section title.\n */\nexport function SectionHeader({ children }: SectionHeaderProps) {\n return (\n <h2 className=\"text-[11px] font-semibold text-zinc-400 dark:text-zinc-500 uppercase tracking-wider mb-3\">\n {children}\n </h2>\n );\n}\n","/**\n * Horizontal divider line with margin.\n */\nexport function Divider({ className = \"\" }: { className?: string }) {\n return <div className={`mx-4 my-6 h-px bg-zinc-200 dark:bg-zinc-800 ${className}`} />;\n}\n","export interface StatChipProps {\n label: string;\n value: number;\n className?: string;\n}\n\n/**\n * Compact stat display chip with label and number.\n */\nexport function StatChip({ label, value, className = \"\" }: StatChipProps) {\n return (\n <div className={`flex-1 rounded-xl bg-zinc-100 dark:bg-zinc-900 px-3 py-3 text-center ${className}`}>\n <p className=\"text-[10px] text-zinc-500 dark:text-zinc-400 font-medium mb-0.5\">\n {label}\n </p>\n <p className=\"text-lg font-bold tabular-nums text-zinc-900 dark:text-white\">\n {value.toLocaleString()}\n </p>\n </div>\n );\n}\n","import { type ReactNode } from \"react\";\n\nexport interface EmptyStateProps {\n message: string;\n icon?: ReactNode;\n}\n\n/**\n * Empty state placeholder with icon and message.\n */\nexport function EmptyState({ message, icon }: EmptyStateProps) {\n return (\n <div className=\"flex flex-col items-center justify-center py-12 gap-2\">\n {icon || (\n <svg width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" className=\"text-zinc-200 dark:text-zinc-700\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M8 15h8\" />\n <circle cx=\"9\" cy=\"9\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n <circle cx=\"15\" cy=\"9\" r=\"1\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n )}\n <p className=\"text-sm text-zinc-400 dark:text-zinc-500\">{message}</p>\n </div>\n );\n}\n","import { type ReactNode } from \"react\";\n\nexport interface WatermarkProps {\n children: ReactNode;\n /** Background color */\n color?: string;\n /** Watermark text. Default: \"m1k\" */\n text?: string;\n /** Max width of content area. Default: 430 */\n maxWidth?: number;\n /** Padding around the app shell. Default: 12px */\n padding?: number;\n}\n\nfunction buildSvgPattern(text: string, opacity: number = 0.08): string {\n const w = 220;\n const h = 120;\n const svg = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${w}\" height=\"${h}\">\n <text x=\"10\" y=\"45\" font-family=\"system-ui,sans-serif\" font-size=\"44\" font-weight=\"900\" fill=\"white\" opacity=\"${opacity}\">${text}</text>\n <text x=\"120\" y=\"100\" font-family=\"system-ui,sans-serif\" font-size=\"44\" font-weight=\"900\" fill=\"white\" opacity=\"${opacity}\">${text}</text>\n </svg>`;\n return `url(\"data:image/svg+xml,${encodeURIComponent(svg)}\")`;\n}\n\n/**\n * Full-screen colored background with repeating text watermark pattern.\n * Wraps the AppShell and provides the \"floating app\" look.\n */\nexport function Watermark({\n children,\n color = \"#0f172a\",\n text = \"m1k\",\n maxWidth = 430,\n padding = 12,\n}: WatermarkProps) {\n return (\n <div\n className=\"h-dvh w-full relative overflow-hidden\"\n style={{ backgroundColor: color, transition: \"background-color 0.5s ease\" }}\n >\n <div\n className=\"absolute inset-0 pointer-events-none select-none\"\n style={{\n backgroundImage: buildSvgPattern(text),\n backgroundRepeat: \"repeat\",\n transform: \"rotate(-12deg) scale(1.5)\",\n transformOrigin: \"center center\",\n }}\n />\n <div\n className=\"relative z-10 h-full flex items-center justify-center mx-auto\"\n style={{ maxWidth, padding }}\n >\n {children}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","jsx","jsxs","jsx","jsxs","jsx","jsxs"]}
|