@create-flow/common-ui 0.3.6 → 0.3.8

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/dist/index.cjs CHANGED
@@ -3,66 +3,12 @@
3
3
 
4
4
  var jsxRuntime = require('react/jsx-runtime');
5
5
  var react = require('react');
6
- var Link = require('next/link');
7
- var navigation = require('next/navigation');
8
-
9
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
-
11
- var Link__default = /*#__PURE__*/_interopDefault(Link);
6
+ var authUi = require('@create-flow/auth-ui');
12
7
 
13
8
  // src/components/Hello.tsx
14
9
  function Hello() {
15
10
  return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Hello world" });
16
11
  }
17
-
18
- // src/utils/authApi.ts
19
- var DEFAULT_AUTH_HOST = (() => {
20
- if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_AUTH_API_HOST) {
21
- const envHost = process.env.NEXT_PUBLIC_AUTH_API_HOST.trim();
22
- if (envHost.length > 0) return envHost;
23
- }
24
- return "https://auth.create-flow.ai";
25
- })();
26
- var DEFAULT_APP_ID = typeof process !== "undefined" ? process.env?.NEXT_PUBLIC_AUTH_APP_ID?.trim() ?? "" : "";
27
- function normalizeHost(host) {
28
- const value = (host ?? DEFAULT_AUTH_HOST).trim();
29
- if (!value) throw new Error("Auth host is not configured");
30
- if (/^https?:\/\//i.test(value)) return value.replace(/\/+$/g, "");
31
- return `https://${value}`.replace(/\/+$/g, "");
32
- }
33
- function buildAuthUrl(path, host, query) {
34
- const normalizedHost = normalizeHost(host);
35
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
36
- const url = new URL(normalizedPath, normalizedHost);
37
- if (query) {
38
- for (const [key, value] of Object.entries(query)) {
39
- if (value !== void 0 && value !== null) {
40
- url.searchParams.set(key, value);
41
- }
42
- }
43
- }
44
- return url;
45
- }
46
- async function fetchWithCredentials(url, init = {}) {
47
- const response = await fetch(url.toString(), {
48
- credentials: "include",
49
- cache: "no-store",
50
- ...init
51
- });
52
- let data = null;
53
- try {
54
- data = await response.json();
55
- } catch {
56
- }
57
- return { response, data };
58
- }
59
- async function getAuthJson(path, host, query) {
60
- const url = buildAuthUrl(path, host, query);
61
- return fetchWithCredentials(url, { method: "GET" });
62
- }
63
- function getResolvedAppId(appId) {
64
- return (appId ?? DEFAULT_APP_ID).trim();
65
- }
66
12
  function HomeIcon({ className }) {
67
13
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: [
68
14
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z" }),
@@ -72,57 +18,25 @@ function HomeIcon({ className }) {
72
18
  function FolderIcon({ className }) {
73
19
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z" }) });
74
20
  }
75
- function UserIcon({ className }) {
76
- return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: [
77
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "8", r: "4" }),
78
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 20c0-4 3.6-7 8-7s8 3 8 7" })
79
- ] });
80
- }
81
21
  function SettingsIcon({ className }) {
82
22
  return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: [
83
23
  /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "3" }),
84
24
  /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z" })
85
25
  ] });
86
26
  }
87
- function LogOutIcon({ className }) {
88
- return /* @__PURE__ */ jsxRuntime.jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: [
89
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4" }),
90
- /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "16,17 21,12 16,7" }),
91
- /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
92
- ] });
93
- }
94
27
  function ChevronLeftIcon({ className }) {
95
28
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 18l-6-6 6-6" }) });
96
29
  }
97
30
  function ChevronRightIcon({ className }) {
98
31
  return /* @__PURE__ */ jsxRuntime.jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9 18l6-6-6-6" }) });
99
32
  }
100
- function ChevronsUpDownIcon({ className }) {
101
- return /* @__PURE__ */ jsxRuntime.jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M7 15l5 5 5-5M7 9l5-5 5 5" }) });
102
- }
103
33
  var defaultNavItems = [
104
34
  { href: "/dashboard", label: "Dashboard", icon: HomeIcon, exact: true },
105
35
  { href: "/dashboard/projects", label: "Projects", icon: FolderIcon, exact: false },
106
36
  { href: "/dashboard/settings", label: "Settings", icon: SettingsIcon, exact: false }
107
37
  ];
108
- var AVATAR_COLORS = [
109
- "bg-violet-600",
110
- "bg-indigo-600",
111
- "bg-sky-600",
112
- "bg-emerald-600",
113
- "bg-amber-600",
114
- "bg-rose-600"
115
- ];
116
- function getAvatarColor(name) {
117
- let hash = 0;
118
- for (let i = 0; i < name.length; i++) hash = name.charCodeAt(i) + ((hash << 5) - hash);
119
- return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];
120
- }
121
- function getInitials(name) {
122
- return name.split(" ").filter(Boolean).map((w) => w[0]).join("").toUpperCase().slice(0, 2);
123
- }
124
38
  function Sidebar({
125
- user: userProp,
39
+ user,
126
40
  appId,
127
41
  authHost,
128
42
  navItems = defaultNavItems,
@@ -133,63 +47,13 @@ function Sidebar({
133
47
  onLogout
134
48
  }) {
135
49
  const [isCollapsed, setIsCollapsed] = react.useState(false);
136
- const [isUserMenuOpen, setIsUserMenuOpen] = react.useState(false);
137
- const [fetchedUser, setFetchedUser] = react.useState(null);
138
- const [isLoading, setIsLoading] = react.useState(!userProp);
139
- const pathname = navigation.usePathname();
140
- const router = navigation.useRouter();
141
- const menuRef = react.useRef(null);
142
- react.useEffect(() => {
143
- if (userProp) return;
144
- let cancelled = false;
145
- async function fetchSession() {
146
- try {
147
- const { response, data } = await getAuthJson("api/auth/session", authHost);
148
- if (!cancelled && response.ok && data?.user) {
149
- setFetchedUser(data.user);
150
- }
151
- } catch (err) {
152
- console.error("Failed to fetch session:", err);
153
- } finally {
154
- if (!cancelled) setIsLoading(false);
155
- }
156
- }
157
- fetchSession();
158
- return () => {
159
- cancelled = true;
160
- };
161
- }, [authHost, userProp]);
50
+ const [pathname, setPathname] = react.useState(typeof window !== "undefined" ? window.location.pathname : "/");
162
51
  react.useEffect(() => {
163
- function handleClickOutside(e) {
164
- if (menuRef.current && !menuRef.current.contains(e.target)) {
165
- setIsUserMenuOpen(false);
166
- }
167
- }
168
- document.addEventListener("mousedown", handleClickOutside);
169
- return () => document.removeEventListener("mousedown", handleClickOutside);
52
+ setPathname(window.location.pathname);
170
53
  }, []);
171
- const user = userProp || fetchedUser;
172
- if (isLoading || !user) return null;
173
- const displayName = user.name || user.email?.split("@")[0] || "User";
174
- const initials = getInitials(displayName);
175
- const avatarColor = getAvatarColor(displayName);
176
54
  function isActive(href, exact) {
177
55
  return exact ? pathname === href : pathname.startsWith(href);
178
56
  }
179
- async function handleLogout() {
180
- const resolvedAppId = getResolvedAppId(appId);
181
- try {
182
- await getAuthJson("api/auth/logout", authHost, resolvedAppId ? { appId: resolvedAppId } : void 0);
183
- } catch (err) {
184
- console.error("Logout error:", err);
185
- }
186
- if (onLogout) {
187
- onLogout();
188
- } else {
189
- router.push(logoutRedirectTo);
190
- router.refresh();
191
- }
192
- }
193
57
  return /* @__PURE__ */ jsxRuntime.jsxs(
194
58
  "aside",
195
59
  {
@@ -216,7 +80,7 @@ function Sidebar({
216
80
  /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "flex-1 overflow-y-auto py-2 px-2 space-y-0.5", children: navItems.map(({ href, label, icon: Icon, exact }) => {
217
81
  const active = isActive(href, exact ?? false);
218
82
  return /* @__PURE__ */ jsxRuntime.jsxs(
219
- Link__default.default,
83
+ "a",
220
84
  {
221
85
  href,
222
86
  title: isCollapsed ? label : void 0,
@@ -229,85 +93,18 @@ function Sidebar({
229
93
  href
230
94
  );
231
95
  }) }),
232
- /* @__PURE__ */ jsxRuntime.jsxs(
233
- "div",
96
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 p-2 border-t border-zinc-200", children: /* @__PURE__ */ jsxRuntime.jsx(
97
+ authUi.UserMenu,
234
98
  {
235
- ref: menuRef,
236
- className: "relative flex-shrink-0 p-2 border-t border-zinc-200",
237
- children: [
238
- isUserMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(
239
- "div",
240
- {
241
- className: "absolute bottom-full mb-1 z-50 bg-white border border-zinc-200 rounded-xl shadow-lg shadow-zinc-200/50 overflow-hidden " + (isCollapsed ? "left-full ml-2 w-52" : "left-2 right-2"),
242
- children: [
243
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3.5 py-3 border-b border-zinc-100", children: [
244
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-zinc-900 truncate", children: displayName }),
245
- user.email && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-zinc-500 truncate mt-0.5", children: user.email })
246
- ] }),
247
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-1", children: [
248
- /* @__PURE__ */ jsxRuntime.jsxs(
249
- Link__default.default,
250
- {
251
- href: profileHref,
252
- onClick: () => setIsUserMenuOpen(false),
253
- className: "flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors",
254
- children: [
255
- /* @__PURE__ */ jsxRuntime.jsx(UserIcon, { className: "w-4 h-4 text-zinc-400" }),
256
- "Profile"
257
- ]
258
- }
259
- ),
260
- /* @__PURE__ */ jsxRuntime.jsxs(
261
- Link__default.default,
262
- {
263
- href: settingsHref,
264
- onClick: () => setIsUserMenuOpen(false),
265
- className: "flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors",
266
- children: [
267
- /* @__PURE__ */ jsxRuntime.jsx(SettingsIcon, { className: "w-4 h-4 text-zinc-400" }),
268
- "Settings"
269
- ]
270
- }
271
- ),
272
- /* @__PURE__ */ jsxRuntime.jsxs(
273
- "button",
274
- {
275
- onClick: handleLogout,
276
- className: "flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors text-left",
277
- children: [
278
- /* @__PURE__ */ jsxRuntime.jsx(LogOutIcon, { className: "w-4 h-4 text-zinc-400" }),
279
- "Log out"
280
- ]
281
- }
282
- )
283
- ] })
284
- ]
285
- }
286
- ),
287
- /* @__PURE__ */ jsxRuntime.jsxs(
288
- "button",
289
- {
290
- onClick: () => setIsUserMenuOpen((o) => !o),
291
- title: isCollapsed ? displayName : void 0,
292
- className: "w-full flex items-center gap-2.5 p-2 rounded-lg hover:bg-zinc-50 transition-colors text-left " + (isCollapsed ? "justify-center" : ""),
293
- children: [
294
- /* @__PURE__ */ jsxRuntime.jsx(
295
- "div",
296
- {
297
- className: "w-7 h-7 rounded-full flex items-center justify-center flex-shrink-0 " + avatarColor,
298
- children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-white leading-none", children: initials })
299
- }
300
- ),
301
- !isCollapsed && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
302
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-zinc-900 truncate leading-tight", children: displayName }) }),
303
- /* @__PURE__ */ jsxRuntime.jsx(ChevronsUpDownIcon, { className: "w-3.5 h-3.5 text-zinc-400 flex-shrink-0" })
304
- ] })
305
- ]
306
- }
307
- )
308
- ]
99
+ user,
100
+ appId,
101
+ authHost,
102
+ logoutRedirectTo,
103
+ profileHref,
104
+ settingsHref,
105
+ onLogout
309
106
  }
310
- )
107
+ ) })
311
108
  ]
312
109
  }
313
110
  );
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Hello.tsx","../src/utils/authApi.ts","../src/components/Sidebar.tsx"],"names":["jsx","jsxs","useState","usePathname","useRouter","useRef","useEffect","Link","Fragment"],"mappings":";;;;;;;;;;;;AAAO,SAAS,KAAA,GAAQ;AACtB,EAAA,uBAAOA,cAAA,CAAC,SAAI,QAAA,EAAA,aAAA,EAAW,CAAA;AACzB;;;ACFA,IAAM,qBAAqB,MAAM;AAC/B,EAAA,IAAI,OAAO,OAAA,KAAY,WAAA,IAAe,OAAA,CAAQ,KAAK,yBAAA,EAA2B;AAC5E,IAAA,MAAM,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,yBAAA,CAA0B,IAAA,EAAK;AAC3D,IAAA,IAAI,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG,OAAO,OAAA;AAAA,EACjC;AACA,EAAA,OAAO,6BAAA;AACT,CAAA,GAAG;AAEH,IAAM,cAAA,GACJ,OAAO,OAAA,KAAY,WAAA,GACf,QAAQ,GAAA,EAAK,uBAAA,EAAyB,IAAA,EAAK,IAAK,EAAA,GAChD,EAAA;AAEN,SAAS,cAAc,IAAA,EAAe;AACpC,EAAA,MAAM,KAAA,GAAA,CAAS,IAAA,IAAQ,iBAAA,EAAmB,IAAA,EAAK;AAC/C,EAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,MAAM,6BAA6B,CAAA;AACzD,EAAA,IAAI,eAAA,CAAgB,KAAK,KAAK,CAAA,SAAU,KAAA,CAAM,OAAA,CAAQ,SAAS,EAAE,CAAA;AACjE,EAAA,OAAO,CAAA,QAAA,EAAW,KAAK,CAAA,CAAA,CAAG,OAAA,CAAQ,SAAS,EAAE,CAAA;AAC/C;AAEA,SAAS,YAAA,CACP,IAAA,EACA,IAAA,EACA,KAAA,EACA;AACA,EAAA,MAAM,cAAA,GAAiB,cAAc,IAAI,CAAA;AACzC,EAAA,MAAM,iBAAiB,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,GAAI,IAAA,GAAO,IAAI,IAAI,CAAA,CAAA;AAC7D,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,cAAA,EAAgB,cAAc,CAAA;AAElD,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAChD,MAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,IAAA,EAAM;AACzC,QAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,GAAA,EAAK,KAAK,CAAA;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,GAAA;AACT;AAEA,eAAe,oBAAA,CAAqB,GAAA,EAAU,IAAA,GAAoB,EAAC,EAAG;AACpE,EAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,CAAI,UAAS,EAAG;AAAA,IAC3C,WAAA,EAAa,SAAA;AAAA,IACb,KAAA,EAAO,UAAA;AAAA,IACP,GAAG;AAAA,GACJ,CAAA;AACD,EAAA,IAAI,IAAA,GAAY,IAAA;AAChB,EAAA,IAAI;AACF,IAAA,IAAA,GAAO,MAAM,SAAS,IAAA,EAAK;AAAA,EAC7B,CAAA,CAAA,MAAQ;AAAA,EAER;AACA,EAAA,OAAO,EAAE,UAAU,IAAA,EAAK;AAC1B;AAEA,eAAsB,WAAA,CACpB,IAAA,EACA,IAAA,EACA,KAAA,EACA;AACA,EAAA,MAAM,GAAA,GAAM,YAAA,CAAa,IAAA,EAAM,IAAA,EAAM,KAAK,CAAA;AAC1C,EAAA,OAAO,oBAAA,CAAqB,GAAA,EAAK,EAAE,MAAA,EAAQ,OAAO,CAAA;AACpD;AAEO,SAAS,iBAAiB,KAAA,EAAgB;AAC/C,EAAA,OAAA,CAAQ,KAAA,IAAS,gBAAgB,IAAA,EAAK;AACxC;ACvBA,SAAS,QAAA,CAAS,EAAE,SAAA,EAAU,EAA2B;AACvD,EAAA,uBACEC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,OAAA,EAAQ,aAAY,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,cAAA,EAAe,WAAA,EAAY,MAAA,EAAO,aAAA,EAAc,OAAA,EAAQ,gBAAe,OAAA,EACvI,QAAA,EAAA;AAAA,oBAAAD,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,8CAAA,EAA+C,CAAA;AAAA,oBACvDA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,eAAA,EAAgB;AAAA,GAAA,EAC1B,CAAA;AAEJ;AAEA,SAAS,UAAA,CAAW,EAAE,SAAA,EAAU,EAA2B;AACzD,EAAA,uBACEA,eAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,SAAQ,WAAA,EAAY,IAAA,EAAK,QAAO,MAAA,EAAO,cAAA,EAAe,aAAY,MAAA,EAAO,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EACvI,0BAAAA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,uEAAA,EAAwE,CAAA,EAClF,CAAA;AAEJ;AAEA,SAAS,QAAA,CAAS,EAAE,SAAA,EAAU,EAA2B;AACvD,EAAA,uBACEC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,OAAA,EAAQ,aAAY,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,cAAA,EAAe,WAAA,EAAY,MAAA,EAAO,aAAA,EAAc,OAAA,EAAQ,gBAAe,OAAA,EACvI,QAAA,EAAA;AAAA,oBAAAD,eAAC,QAAA,EAAA,EAAO,EAAA,EAAG,MAAK,EAAA,EAAG,GAAA,EAAI,GAAE,GAAA,EAAI,CAAA;AAAA,oBAC7BA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,6BAAA,EAA8B;AAAA,GAAA,EACxC,CAAA;AAEJ;AAEA,SAAS,YAAA,CAAa,EAAE,SAAA,EAAU,EAA2B;AAC3D,EAAA,uBACEC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,OAAA,EAAQ,aAAY,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,cAAA,EAAe,WAAA,EAAY,MAAA,EAAO,aAAA,EAAc,OAAA,EAAQ,gBAAe,OAAA,EACvI,QAAA,EAAA;AAAA,oBAAAD,eAAC,QAAA,EAAA,EAAO,EAAA,EAAG,MAAK,EAAA,EAAG,IAAA,EAAK,GAAE,GAAA,EAAI,CAAA;AAAA,oBAC9BA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,6kBAAA,EAA8kB;AAAA,GAAA,EACxlB,CAAA;AAEJ;AAEA,SAAS,UAAA,CAAW,EAAE,SAAA,EAAU,EAA2B;AACzD,EAAA,uBACEC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,OAAA,EAAQ,aAAY,IAAA,EAAK,MAAA,EAAO,MAAA,EAAO,cAAA,EAAe,WAAA,EAAY,MAAA,EAAO,aAAA,EAAc,OAAA,EAAQ,gBAAe,OAAA,EACvI,QAAA,EAAA;AAAA,oBAAAD,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,sCAAA,EAAuC,CAAA;AAAA,oBAC/CA,cAAAA,CAAC,UAAA,EAAA,EAAS,MAAA,EAAO,kBAAA,EAAmB,CAAA;AAAA,oBACpCA,cAAAA,CAAC,MAAA,EAAA,EAAK,EAAA,EAAG,IAAA,EAAK,IAAG,IAAA,EAAK,EAAA,EAAG,GAAA,EAAI,EAAA,EAAG,IAAA,EAAK;AAAA,GAAA,EACvC,CAAA;AAEJ;AAEA,SAAS,eAAA,CAAgB,EAAE,SAAA,EAAU,EAA2B;AAC9D,EAAA,uBACEA,eAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,SAAQ,WAAA,EAAY,IAAA,EAAK,QAAO,MAAA,EAAO,cAAA,EAAe,aAAY,GAAA,EAAI,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EACpI,0BAAAA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,iBAAA,EAAkB,CAAA,EAC5B,CAAA;AAEJ;AAEA,SAAS,gBAAA,CAAiB,EAAE,SAAA,EAAU,EAA2B;AAC/D,EAAA,uBACEA,eAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,SAAQ,WAAA,EAAY,IAAA,EAAK,QAAO,MAAA,EAAO,cAAA,EAAe,aAAY,GAAA,EAAI,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EACpI,0BAAAA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,eAAA,EAAgB,CAAA,EAC1B,CAAA;AAEJ;AAEA,SAAS,kBAAA,CAAmB,EAAE,SAAA,EAAU,EAA2B;AACjE,EAAA,uBACEA,eAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,SAAQ,WAAA,EAAY,IAAA,EAAK,QAAO,MAAA,EAAO,cAAA,EAAe,aAAY,GAAA,EAAI,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EACpI,0BAAAA,cAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,2BAAA,EAA4B,CAAA,EACtC,CAAA;AAEJ;AAIA,IAAM,eAAA,GAA6B;AAAA,EACjC,EAAE,MAAM,YAAA,EAAc,KAAA,EAAO,aAAa,IAAA,EAAM,QAAA,EAAU,OAAO,IAAA,EAAK;AAAA,EACtE,EAAE,MAAM,qBAAA,EAAuB,KAAA,EAAO,YAAY,IAAA,EAAM,UAAA,EAAY,OAAO,KAAA,EAAM;AAAA,EACjF,EAAE,MAAM,qBAAA,EAAuB,KAAA,EAAO,YAAY,IAAA,EAAM,YAAA,EAAc,OAAO,KAAA;AAC/E,CAAA;AAIA,IAAM,aAAA,GAAgB;AAAA,EACpB,eAAA;AAAA,EACA,eAAA;AAAA,EACA,YAAA;AAAA,EACA,gBAAA;AAAA,EACA,cAAA;AAAA,EACA;AACF,CAAA;AAEA,SAAS,eAAe,IAAA,EAAsB;AAC5C,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAA,EAAK,IAAA,GAAO,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA,IAAA,CAAM,IAAA,IAAQ,CAAA,IAAK,IAAA,CAAA;AACjF,EAAA,OAAO,cAAc,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,GAAI,cAAc,MAAM,CAAA;AAC5D;AAEA,SAAS,YAAY,IAAA,EAAsB;AACzC,EAAA,OAAO,IAAA,CACJ,MAAM,GAAG,CAAA,CACT,OAAO,OAAO,CAAA,CACd,IAAI,CAAC,CAAA,KAAM,EAAE,CAAC,CAAC,EACf,IAAA,CAAK,EAAE,EACP,WAAA,EAAY,CACZ,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AACf;AAIO,SAAS,OAAA,CAAQ;AAAA,EACtB,IAAA,EAAM,QAAA;AAAA,EACN,KAAA;AAAA,EACA,QAAA;AAAA,EACA,QAAA,GAAW,eAAA;AAAA,EACX,KAAA,GAAQ,WAAA;AAAA,EACR,gBAAA,GAAmB,GAAA;AAAA,EACnB,WAAA,GAAc,UAAA;AAAA,EACd,YAAA,GAAe,WAAA;AAAA,EACf;AACF,CAAA,EAAiB;AACf,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIE,eAAS,KAAK,CAAA;AACpD,EAAA,MAAM,CAAC,cAAA,EAAgB,iBAAiB,CAAA,GAAIA,eAAS,KAAK,CAAA;AAC1D,EAAA,MAAM,CAAC,WAAA,EAAa,cAAc,CAAA,GAAIA,eAA0B,IAAI,CAAA;AACpE,EAAA,MAAM,CAAC,SAAA,EAAW,YAAY,CAAA,GAAIA,cAAA,CAAS,CAAC,QAAQ,CAAA;AACpD,EAAA,MAAM,WAAWC,sBAAA,EAAY;AAC7B,EAAA,MAAM,SAASC,oBAAA,EAAU;AACzB,EAAA,MAAM,OAAA,GAAUC,aAAuB,IAAI,CAAA;AAE3C,EAAAC,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,QAAA,EAAU;AAEd,IAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,IAAA,eAAe,YAAA,GAAe;AAC5B,MAAA,IAAI;AACF,QAAA,MAAM,EAAE,QAAA,EAAU,IAAA,KAAS,MAAM,WAAA,CAAY,oBAAoB,QAAQ,CAAA;AACzE,QAAA,IAAI,CAAC,SAAA,IAAa,QAAA,CAAS,EAAA,IAAM,MAAM,IAAA,EAAM;AAC3C,UAAA,cAAA,CAAe,KAAK,IAAI,CAAA;AAAA,QAC1B;AAAA,MACF,SAAS,GAAA,EAAK;AACZ,QAAA,OAAA,CAAQ,KAAA,CAAM,4BAA4B,GAAG,CAAA;AAAA,MAC/C,CAAA,SAAE;AACA,QAAA,IAAI,CAAC,SAAA,EAAW,YAAA,CAAa,KAAK,CAAA;AAAA,MACpC;AAAA,IACF;AAEA,IAAA,YAAA,EAAa;AACb,IAAA,OAAO,MAAM;AAAE,MAAA,SAAA,GAAY,IAAA;AAAA,IAAM,CAAA;AAAA,EACnC,CAAA,EAAG,CAAC,QAAA,EAAU,QAAQ,CAAC,CAAA;AAEvB,EAAAA,eAAA,CAAU,MAAM;AACd,IAAA,SAAS,mBAAmB,CAAA,EAAe;AACzC,MAAA,IAAI,OAAA,CAAQ,WAAW,CAAC,OAAA,CAAQ,QAAQ,QAAA,CAAS,CAAA,CAAE,MAAc,CAAA,EAAG;AAClE,QAAA,iBAAA,CAAkB,KAAK,CAAA;AAAA,MACzB;AAAA,IACF;AACA,IAAA,QAAA,CAAS,gBAAA,CAAiB,aAAa,kBAAkB,CAAA;AACzD,IAAA,OAAO,MAAM,QAAA,CAAS,mBAAA,CAAoB,WAAA,EAAa,kBAAkB,CAAA;AAAA,EAC3E,CAAA,EAAG,EAAE,CAAA;AAEL,EAAA,MAAM,OAAO,QAAA,IAAY,WAAA;AAEzB,EAAA,IAAI,SAAA,IAAa,CAAC,IAAA,EAAM,OAAO,IAAA;AAE/B,EAAA,MAAM,WAAA,GAAc,KAAK,IAAA,IAAQ,IAAA,CAAK,OAAO,KAAA,CAAM,GAAG,CAAA,CAAE,CAAC,CAAA,IAAK,MAAA;AAC9D,EAAA,MAAM,QAAA,GAAW,YAAY,WAAW,CAAA;AACxC,EAAA,MAAM,WAAA,GAAc,eAAe,WAAW,CAAA;AAE9C,EAAA,SAAS,QAAA,CAAS,MAAc,KAAA,EAAgB;AAC9C,IAAA,OAAO,KAAA,GAAQ,QAAA,KAAa,IAAA,GAAO,QAAA,CAAS,WAAW,IAAI,CAAA;AAAA,EAC7D;AAEA,EAAA,eAAe,YAAA,GAAe;AAC5B,IAAA,MAAM,aAAA,GAAgB,iBAAiB,KAAK,CAAA;AAE5C,IAAA,IAAI;AACF,MAAA,MAAM,WAAA,CAAY,mBAAmB,QAAA,EAAU,aAAA,GAAgB,EAAE,KAAA,EAAO,aAAA,KAAkB,KAAA,CAAS,CAAA;AAAA,IACrG,SAAS,GAAA,EAAK;AACZ,MAAA,OAAA,CAAQ,KAAA,CAAM,iBAAiB,GAAG,CAAA;AAAA,IACpC;AAEA,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,QAAA,EAAS;AAAA,IACX,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,KAAK,gBAAgB,CAAA;AAC5B,MAAA,MAAA,CAAO,OAAA,EAAQ;AAAA,IACjB;AAAA,EACF;AAEA,EAAA,uBACEL,eAAA;AAAA,IAAC,OAAA;AAAA,IAAA;AAAA,MACC,SAAA,EACE,0HAAA,IACC,WAAA,GAAc,UAAA,GAAa,WAAA,CAAA;AAAA,MAI9B,QAAA,EAAA;AAAA,wBAAAA,eAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,SAAA,EACE,qEAAA,IACC,WAAA,GAAc,gBAAA,GAAmB,iBAAA,CAAA;AAAA,YAGnC,QAAA,EAAA;AAAA,cAAA,CAAC,+BACAD,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,2EACb,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,8BAEFA,cAAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,SAAS,MAAM,cAAA,CAAe,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,kBACvC,KAAA,EAAO,cAAc,gBAAA,GAAmB,kBAAA;AAAA,kBACxC,SAAA,EAAU,sGAAA;AAAA,kBAET,QAAA,EAAA,WAAA,mBACCA,cAAAA,CAAC,gBAAA,EAAA,EAAiB,SAAA,EAAU,SAAA,EAAU,CAAA,mBAEtCA,cAAAA,CAAC,eAAA,EAAA,EAAgB,SAAA,EAAU,SAAA,EAAU;AAAA;AAAA;AAEzC;AAAA;AAAA,SACF;AAAA,wBAGAA,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gDACZ,QAAA,EAAA,QAAA,CAAS,GAAA,CAAI,CAAC,EAAE,IAAA,EAAM,KAAA,EAAO,IAAA,EAAM,IAAA,EAAM,OAAM,KAAM;AACpD,UAAA,MAAM,MAAA,GAAS,QAAA,CAAS,IAAA,EAAM,KAAA,IAAS,KAAK,CAAA;AAC5C,UAAA,uBACEC,eAAA;AAAA,YAACM,qBAAA;AAAA,YAAA;AAAA,cAEC,IAAA;AAAA,cACA,KAAA,EAAO,cAAc,KAAA,GAAQ,MAAA;AAAA,cAC7B,WACE,6EAAA,IACC,WAAA,GAAc,iBAAA,GAAoB,EAAA,CAAA,IAClC,SACG,uCAAA,GACA,oDAAA,CAAA;AAAA,cAGN,QAAA,EAAA;AAAA,gCAAAP,cAAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAU,uBAAA,EAAwB,CAAA;AAAA,gBACvC,CAAC,WAAA,oBAAeA,eAAC,MAAA,EAAA,EAAK,SAAA,EAAU,YAAY,QAAA,EAAA,KAAA,EAAM;AAAA;AAAA,aAAA;AAAA,YAZ9C;AAAA,WAaP;AAAA,QAEJ,CAAC,CAAA,EACH,CAAA;AAAA,wBAGAC,eAAA;AAAA,UAAC,KAAA;AAAA,UAAA;AAAA,YACC,GAAA,EAAK,OAAA;AAAA,YACL,SAAA,EAAU,qDAAA;AAAA,YAGT,QAAA,EAAA;AAAA,cAAA,cAAA,oBACCA,eAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,SAAA,EACE,yHAAA,IACC,WAAA,GAAc,qBAAA,GAAwB,gBAAA,CAAA;AAAA,kBAIzC,QAAA,EAAA;AAAA,oCAAAA,eAAA,CAAC,KAAA,EAAA,EAAI,WAAU,sCAAA,EACb,QAAA,EAAA;AAAA,sCAAAD,cAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,4CAAA,EACV,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,sBACC,IAAA,CAAK,yBACJA,cAAAA,CAAC,OAAE,SAAA,EAAU,uCAAA,EACV,eAAK,KAAA,EACR;AAAA,qBAAA,EAEJ,CAAA;AAAA,oCAEAC,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,KAAA,EACb,QAAA,EAAA;AAAA,sCAAAA,eAAA;AAAA,wBAACM,qBAAA;AAAA,wBAAA;AAAA,0BACC,IAAA,EAAM,WAAA;AAAA,0BACN,OAAA,EAAS,MAAM,iBAAA,CAAkB,KAAK,CAAA;AAAA,0BACtC,SAAA,EAAU,gHAAA;AAAA,0BAEV,QAAA,EAAA;AAAA,4CAAAP,cAAAA,CAAC,QAAA,EAAA,EAAS,SAAA,EAAU,uBAAA,EAAwB,CAAA;AAAA,4BAAE;AAAA;AAAA;AAAA,uBAEhD;AAAA,sCACAC,eAAA;AAAA,wBAACM,qBAAA;AAAA,wBAAA;AAAA,0BACC,IAAA,EAAM,YAAA;AAAA,0BACN,OAAA,EAAS,MAAM,iBAAA,CAAkB,KAAK,CAAA;AAAA,0BACtC,SAAA,EAAU,gHAAA;AAAA,0BAEV,QAAA,EAAA;AAAA,4CAAAP,cAAAA,CAAC,YAAA,EAAA,EAAa,SAAA,EAAU,uBAAA,EAAwB,CAAA;AAAA,4BAAE;AAAA;AAAA;AAAA,uBAEpD;AAAA,sCACAC,eAAA;AAAA,wBAAC,QAAA;AAAA,wBAAA;AAAA,0BACC,OAAA,EAAS,YAAA;AAAA,0BACT,SAAA,EAAU,0HAAA;AAAA,0BAEV,QAAA,EAAA;AAAA,4CAAAD,cAAAA,CAAC,UAAA,EAAA,EAAW,SAAA,EAAU,uBAAA,EAAwB,CAAA;AAAA,4BAAE;AAAA;AAAA;AAAA;AAElD,qBAAA,EACF;AAAA;AAAA;AAAA,eACF;AAAA,8BAIFC,eAAA;AAAA,gBAAC,QAAA;AAAA,gBAAA;AAAA,kBACC,SAAS,MAAM,iBAAA,CAAkB,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,kBAC1C,KAAA,EAAO,cAAc,WAAA,GAAc,MAAA;AAAA,kBACnC,SAAA,EACE,+FAAA,IACC,WAAA,GAAc,gBAAA,GAAmB,EAAA,CAAA;AAAA,kBAGpC,QAAA,EAAA;AAAA,oCAAAD,cAAAA;AAAA,sBAAC,KAAA;AAAA,sBAAA;AAAA,wBACC,WAAW,sEAAA,GAAyE,WAAA;AAAA,wBAEpF,QAAA,kBAAAA,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,iDACb,QAAA,EAAA,QAAA,EACH;AAAA;AAAA,qBACF;AAAA,oBACC,CAAC,+BACAC,eAAA,CAAAO,mBAAA,EAAA,EACE,QAAA,EAAA;AAAA,sCAAAR,cAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,kBAAAA,eAAC,GAAA,EAAA,EAAE,SAAA,EAAU,0DAAA,EACV,QAAA,EAAA,WAAA,EACH,CAAA,EACF,CAAA;AAAA,sCACAA,cAAAA,CAAC,kBAAA,EAAA,EAAmB,SAAA,EAAU,yCAAA,EAA0C;AAAA,qBAAA,EAC1E;AAAA;AAAA;AAAA;AAEJ;AAAA;AAAA;AACF;AAAA;AAAA,GACF;AAEJ","file":"index.cjs","sourcesContent":["export function Hello() {\n return <div>Hello world</div>;\n}\n","const DEFAULT_AUTH_HOST = (() => {\n if (typeof process !== \"undefined\" && process.env?.NEXT_PUBLIC_AUTH_API_HOST) {\n const envHost = process.env.NEXT_PUBLIC_AUTH_API_HOST.trim();\n if (envHost.length > 0) return envHost;\n }\n return \"https://auth.create-flow.ai\";\n})();\n\nconst DEFAULT_APP_ID =\n typeof process !== \"undefined\"\n ? process.env?.NEXT_PUBLIC_AUTH_APP_ID?.trim() ?? \"\"\n : \"\";\n\nfunction normalizeHost(host?: string) {\n const value = (host ?? DEFAULT_AUTH_HOST).trim();\n if (!value) throw new Error(\"Auth host is not configured\");\n if (/^https?:\\/\\//i.test(value)) return value.replace(/\\/+$/g, \"\");\n return `https://${value}`.replace(/\\/+$/g, \"\");\n}\n\nfunction buildAuthUrl(\n path: string,\n host?: string,\n query?: Record<string, string | undefined>\n) {\n const normalizedHost = normalizeHost(host);\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n const url = new URL(normalizedPath, normalizedHost);\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, value);\n }\n }\n }\n\n return url;\n}\n\nasync function fetchWithCredentials(url: URL, init: RequestInit = {}) {\n const response = await fetch(url.toString(), {\n credentials: \"include\",\n cache: \"no-store\",\n ...init,\n });\n let data: any = null;\n try {\n data = await response.json();\n } catch {\n // Ignore JSON parse errors\n }\n return { response, data };\n}\n\nexport async function getAuthJson(\n path: string,\n host?: string,\n query?: Record<string, string | undefined>\n) {\n const url = buildAuthUrl(path, host, query);\n return fetchWithCredentials(url, { method: \"GET\" });\n}\n\nexport function getResolvedAppId(appId?: string) {\n return (appId ?? DEFAULT_APP_ID).trim();\n}\n","\"use client\";\n\nimport { useState, useRef, useEffect, type ComponentType } from \"react\";\nimport Link from \"next/link\";\nimport { usePathname, useRouter } from \"next/navigation\";\n\nimport { getResolvedAppId, getAuthJson } from \"../utils/authApi\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type UserType = \"guest\" | \"regular\";\n\nexport interface AuthUser {\n id: string;\n name?: string | null;\n email?: string | null;\n image?: string | null;\n type: UserType;\n appId: string;\n isGuest: boolean;\n}\n\nexport interface NavItem {\n href: string;\n label: string;\n icon: ComponentType<{ className?: string }>;\n exact?: boolean;\n}\n\nexport interface SidebarProps {\n user?: AuthUser;\n appId?: string;\n authHost?: string;\n navItems?: NavItem[];\n title?: string;\n logoutRedirectTo?: string;\n profileHref?: string;\n settingsHref?: string;\n onLogout?: () => void;\n}\n\n// ── Icons ─────────────────────────────────────────────────────────────────────\n\nfunction HomeIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z\" />\n <path d=\"M9 22V12h6v10\" />\n </svg>\n );\n}\n\nfunction FolderIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z\" />\n </svg>\n );\n}\n\nfunction UserIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"8\" r=\"4\" />\n <path d=\"M4 20c0-4 3.6-7 8-7s8 3 8 7\" />\n </svg>\n );\n}\n\nfunction SettingsIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n <path d=\"M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z\" />\n </svg>\n );\n}\n\nfunction LogOutIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4\" />\n <polyline points=\"16,17 21,12 16,7\" />\n <line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\" />\n </svg>\n );\n}\n\nfunction ChevronLeftIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n );\n}\n\nfunction ChevronRightIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n );\n}\n\nfunction ChevronsUpDownIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M7 15l5 5 5-5M7 9l5-5 5 5\" />\n </svg>\n );\n}\n\n// ── Default nav items ─────────────────────────────────────────────────────────\n\nconst defaultNavItems: NavItem[] = [\n { href: \"/dashboard\", label: \"Dashboard\", icon: HomeIcon, exact: true },\n { href: \"/dashboard/projects\", label: \"Projects\", icon: FolderIcon, exact: false },\n { href: \"/dashboard/settings\", label: \"Settings\", icon: SettingsIcon, exact: false },\n];\n\n// ── Avatar ────────────────────────────────────────────────────────────────────\n\nconst AVATAR_COLORS = [\n \"bg-violet-600\",\n \"bg-indigo-600\",\n \"bg-sky-600\",\n \"bg-emerald-600\",\n \"bg-amber-600\",\n \"bg-rose-600\",\n];\n\nfunction getAvatarColor(name: string): string {\n let hash = 0;\n for (let i = 0; i < name.length; i++) hash = name.charCodeAt(i) + ((hash << 5) - hash);\n return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];\n}\n\nfunction getInitials(name: string): string {\n return name\n .split(\" \")\n .filter(Boolean)\n .map((w) => w[0])\n .join(\"\")\n .toUpperCase()\n .slice(0, 2);\n}\n\n// ── Sidebar ───────────────────────────────────────────────────────────────────\n\nexport function Sidebar({\n user: userProp,\n appId,\n authHost,\n navItems = defaultNavItems,\n title = \"Workspace\",\n logoutRedirectTo = \"/\",\n profileHref = \"/profile\",\n settingsHref = \"/settings\",\n onLogout,\n}: SidebarProps) {\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);\n const [fetchedUser, setFetchedUser] = useState<AuthUser | null>(null);\n const [isLoading, setIsLoading] = useState(!userProp);\n const pathname = usePathname();\n const router = useRouter();\n const menuRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (userProp) return;\n\n let cancelled = false;\n\n async function fetchSession() {\n try {\n const { response, data } = await getAuthJson(\"api/auth/session\", authHost);\n if (!cancelled && response.ok && data?.user) {\n setFetchedUser(data.user);\n }\n } catch (err) {\n console.error(\"Failed to fetch session:\", err);\n } finally {\n if (!cancelled) setIsLoading(false);\n }\n }\n\n fetchSession();\n return () => { cancelled = true; };\n }, [authHost, userProp]);\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setIsUserMenuOpen(false);\n }\n }\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, []);\n\n const user = userProp || fetchedUser;\n\n if (isLoading || !user) return null;\n\n const displayName = user.name || user.email?.split(\"@\")[0] || \"User\";\n const initials = getInitials(displayName);\n const avatarColor = getAvatarColor(displayName);\n\n function isActive(href: string, exact: boolean) {\n return exact ? pathname === href : pathname.startsWith(href);\n }\n\n async function handleLogout() {\n const resolvedAppId = getResolvedAppId(appId);\n\n try {\n await getAuthJson(\"api/auth/logout\", authHost, resolvedAppId ? { appId: resolvedAppId } : undefined);\n } catch (err) {\n console.error(\"Logout error:\", err);\n }\n\n if (onLogout) {\n onLogout();\n } else {\n router.push(logoutRedirectTo);\n router.refresh();\n }\n }\n\n return (\n <aside\n className={\n \"relative flex flex-col h-screen bg-white border-r border-zinc-200 transition-all duration-200 ease-in-out flex-shrink-0 \" +\n (isCollapsed ? \"w-[60px]\" : \"w-[220px]\")\n }\n >\n {/* ── Header ─────────────────────────────────────────────────────────── */}\n <div\n className={\n \"flex items-center h-14 px-3 flex-shrink-0 border-b border-zinc-200 \" +\n (isCollapsed ? \"justify-center\" : \"justify-between\")\n }\n >\n {!isCollapsed && (\n <span className=\"text-sm font-semibold text-zinc-900 tracking-tight truncate select-none\">\n {title}\n </span>\n )}\n <button\n onClick={() => setIsCollapsed((c) => !c)}\n title={isCollapsed ? \"Expand sidebar\" : \"Collapse sidebar\"}\n className=\"p-1.5 rounded-md text-zinc-400 hover:text-zinc-700 hover:bg-zinc-100 transition-colors flex-shrink-0\"\n >\n {isCollapsed ? (\n <ChevronRightIcon className=\"w-4 h-4\" />\n ) : (\n <ChevronLeftIcon className=\"w-4 h-4\" />\n )}\n </button>\n </div>\n\n {/* ── Nav ────────────────────────────────────────────────────────────── */}\n <nav className=\"flex-1 overflow-y-auto py-2 px-2 space-y-0.5\">\n {navItems.map(({ href, label, icon: Icon, exact }) => {\n const active = isActive(href, exact ?? false);\n return (\n <Link\n key={href}\n href={href}\n title={isCollapsed ? label : undefined}\n className={\n \"flex items-center gap-2.5 px-2.5 py-2 rounded-lg text-sm transition-colors \" +\n (isCollapsed ? \"justify-center \" : \"\") +\n (active\n ? \"bg-zinc-100 text-zinc-900 font-medium\"\n : \"text-zinc-500 hover:bg-zinc-50 hover:text-zinc-900\")\n }\n >\n <Icon className=\"w-4 h-4 flex-shrink-0\" />\n {!isCollapsed && <span className=\"truncate\">{label}</span>}\n </Link>\n );\n })}\n </nav>\n\n {/* ── User area ──────────────────────────────────────────────────────── */}\n <div\n ref={menuRef}\n className=\"relative flex-shrink-0 p-2 border-t border-zinc-200\"\n >\n {/* Dropdown menu */}\n {isUserMenuOpen && (\n <div\n className={\n \"absolute bottom-full mb-1 z-50 bg-white border border-zinc-200 rounded-xl shadow-lg shadow-zinc-200/50 overflow-hidden \" +\n (isCollapsed ? \"left-full ml-2 w-52\" : \"left-2 right-2\")\n }\n >\n {/* User info */}\n <div className=\"px-3.5 py-3 border-b border-zinc-100\">\n <p className=\"text-sm font-medium text-zinc-900 truncate\">\n {displayName}\n </p>\n {user.email && (\n <p className=\"text-xs text-zinc-500 truncate mt-0.5\">\n {user.email}\n </p>\n )}\n </div>\n {/* Menu items */}\n <div className=\"p-1\">\n <Link\n href={profileHref}\n onClick={() => setIsUserMenuOpen(false)}\n className=\"flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors\"\n >\n <UserIcon className=\"w-4 h-4 text-zinc-400\" />\n Profile\n </Link>\n <Link\n href={settingsHref}\n onClick={() => setIsUserMenuOpen(false)}\n className=\"flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors\"\n >\n <SettingsIcon className=\"w-4 h-4 text-zinc-400\" />\n Settings\n </Link>\n <button\n onClick={handleLogout}\n className=\"flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors text-left\"\n >\n <LogOutIcon className=\"w-4 h-4 text-zinc-400\" />\n Log out\n </button>\n </div>\n </div>\n )}\n\n {/* User trigger button */}\n <button\n onClick={() => setIsUserMenuOpen((o) => !o)}\n title={isCollapsed ? displayName : undefined}\n className={\n \"w-full flex items-center gap-2.5 p-2 rounded-lg hover:bg-zinc-50 transition-colors text-left \" +\n (isCollapsed ? \"justify-center\" : \"\")\n }\n >\n <div\n className={\"w-7 h-7 rounded-full flex items-center justify-center flex-shrink-0 \" + avatarColor}\n >\n <span className=\"text-xs font-semibold text-white leading-none\">\n {initials}\n </span>\n </div>\n {!isCollapsed && (\n <>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-zinc-900 truncate leading-tight\">\n {displayName}\n </p>\n </div>\n <ChevronsUpDownIcon className=\"w-3.5 h-3.5 text-zinc-400 flex-shrink-0\" />\n </>\n )}\n </button>\n </div>\n </aside>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/Hello.tsx","../src/components/Sidebar.tsx"],"names":["jsx","jsxs","useState","useEffect","UserMenu"],"mappings":"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","file":"index.cjs","sourcesContent":["export function Hello() {\n return <div>Hello world</div>;\n}\n","\"use client\";\n\nimport { useState, useEffect, type ComponentType } from \"react\";\nimport { UserMenu } from \"@create-flow/auth-ui\";\nimport type { AuthUser } from \"@create-flow/auth-ui\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type { AuthUser, UserType } from \"@create-flow/auth-ui\";\n\nexport interface NavItem {\n href: string;\n label: string;\n icon: ComponentType<{ className?: string }>;\n exact?: boolean;\n}\n\nexport interface SidebarProps {\n user?: AuthUser;\n appId?: string;\n authHost?: string;\n navItems?: NavItem[];\n title?: string;\n logoutRedirectTo?: string;\n profileHref?: string;\n settingsHref?: string;\n onLogout?: () => void;\n}\n\n// ── Icons ─────────────────────────────────────────────────────────────────────\n\nfunction HomeIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z\" />\n <path d=\"M9 22V12h6v10\" />\n </svg>\n );\n}\n\nfunction FolderIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z\" />\n </svg>\n );\n}\n\nfunction SettingsIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n <path d=\"M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z\" />\n </svg>\n );\n}\n\nfunction ChevronLeftIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n );\n}\n\nfunction ChevronRightIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n );\n}\n\n// ── Default nav items ─────────────────────────────────────────────────────────\n\nconst defaultNavItems: NavItem[] = [\n { href: \"/dashboard\", label: \"Dashboard\", icon: HomeIcon, exact: true },\n { href: \"/dashboard/projects\", label: \"Projects\", icon: FolderIcon, exact: false },\n { href: \"/dashboard/settings\", label: \"Settings\", icon: SettingsIcon, exact: false },\n];\n\n// ── Sidebar ───────────────────────────────────────────────────────────────────\n\nexport function Sidebar({\n user,\n appId,\n authHost,\n navItems = defaultNavItems,\n title = \"Workspace\",\n logoutRedirectTo = \"/\",\n profileHref = \"/profile\",\n settingsHref = \"/settings\",\n onLogout,\n}: SidebarProps) {\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [pathname, setPathname] = useState(typeof window !== \"undefined\" ? window.location.pathname : \"/\");\n\n useEffect(() => {\n setPathname(window.location.pathname);\n }, []);\n\n function isActive(href: string, exact: boolean) {\n return exact ? pathname === href : pathname.startsWith(href);\n }\n\n return (\n <aside\n className={\n \"relative flex flex-col h-screen bg-white border-r border-zinc-200 transition-all duration-200 ease-in-out flex-shrink-0 \" +\n (isCollapsed ? \"w-[60px]\" : \"w-[220px]\")\n }\n >\n {/* ── Header ─────────────────────────────────────────────────────────── */}\n <div\n className={\n \"flex items-center h-14 px-3 flex-shrink-0 border-b border-zinc-200 \" +\n (isCollapsed ? \"justify-center\" : \"justify-between\")\n }\n >\n {!isCollapsed && (\n <span className=\"text-sm font-semibold text-zinc-900 tracking-tight truncate select-none\">\n {title}\n </span>\n )}\n <button\n onClick={() => setIsCollapsed((c) => !c)}\n title={isCollapsed ? \"Expand sidebar\" : \"Collapse sidebar\"}\n className=\"p-1.5 rounded-md text-zinc-400 hover:text-zinc-700 hover:bg-zinc-100 transition-colors flex-shrink-0\"\n >\n {isCollapsed ? (\n <ChevronRightIcon className=\"w-4 h-4\" />\n ) : (\n <ChevronLeftIcon className=\"w-4 h-4\" />\n )}\n </button>\n </div>\n\n {/* ── Nav ────────────────────────────────────────────────────────────── */}\n <nav className=\"flex-1 overflow-y-auto py-2 px-2 space-y-0.5\">\n {navItems.map(({ href, label, icon: Icon, exact }) => {\n const active = isActive(href, exact ?? false);\n return (\n <a\n key={href}\n href={href}\n title={isCollapsed ? label : undefined}\n className={\n \"flex items-center gap-2.5 px-2.5 py-2 rounded-lg text-sm transition-colors \" +\n (isCollapsed ? \"justify-center \" : \"\") +\n (active\n ? \"bg-zinc-100 text-zinc-900 font-medium\"\n : \"text-zinc-500 hover:bg-zinc-50 hover:text-zinc-900\")\n }\n >\n <Icon className=\"w-4 h-4 flex-shrink-0\" />\n {!isCollapsed && <span className=\"truncate\">{label}</span>}\n </a>\n );\n })}\n </nav>\n\n {/* ── User area ──────────────────────────────────────────────────────── */}\n <div className=\"flex-shrink-0 p-2 border-t border-zinc-200\">\n <UserMenu\n user={user}\n appId={appId}\n authHost={authHost}\n logoutRedirectTo={logoutRedirectTo}\n profileHref={profileHref}\n settingsHref={settingsHref}\n onLogout={onLogout}\n />\n </div>\n </aside>\n );\n}\n"]}
package/dist/index.css ADDED
@@ -0,0 +1 @@
1
+ *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,0.5);--tw-ring-offset-shadow:0 0 transparent;--tw-ring-shadow:0 0 transparent;--tw-shadow:0 0 transparent;--tw-shadow-colored:0 0 transparent;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder, textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.relative{position:relative}.flex{display:flex}.h-14{height:3.5rem}.h-4{height:1rem}.h-screen{height:100vh}.w-4{width:1rem}.w-\[220px\]{width:220px}.w-\[60px\]{width:60px}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-2\.5{gap:.625rem}.space-y-0\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(0.125rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(0.125rem*var(--tw-space-y-reverse))}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border-b{border-bottom-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-zinc-200{--tw-border-opacity:1;border-color:rgb(228 228 231/var(--tw-border-opacity,1))}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-zinc-100{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.text-sm{font-size:.875rem;line-height:1.25rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.tracking-tight{letter-spacing:-.025em}.text-zinc-400{--tw-text-opacity:1;color:rgb(161 161 170/var(--tw-text-opacity,1))}.text-zinc-500{--tw-text-opacity:1;color:rgb(113 113 122/var(--tw-text-opacity,1))}.text-zinc-900{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200{transition-duration:.2s}.ease-in-out{transition-timing-function:cubic-bezier(.4,0,.2,1)}.hover\:bg-zinc-100:hover{--tw-bg-opacity:1;background-color:rgb(244 244 245/var(--tw-bg-opacity,1))}.hover\:bg-zinc-50:hover{--tw-bg-opacity:1;background-color:rgb(250 250 250/var(--tw-bg-opacity,1))}.hover\:text-zinc-700:hover{--tw-text-opacity:1;color:rgb(63 63 70/var(--tw-text-opacity,1))}.hover\:text-zinc-900:hover{--tw-text-opacity:1;color:rgb(24 24 27/var(--tw-text-opacity,1))}
package/dist/index.d.cts CHANGED
@@ -1,18 +1,10 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ComponentType } from 'react';
3
+ import { AuthUser } from '@create-flow/auth-ui';
4
+ export { AuthUser, UserType } from '@create-flow/auth-ui';
3
5
 
4
6
  declare function Hello(): react_jsx_runtime.JSX.Element;
5
7
 
6
- type UserType = "guest" | "regular";
7
- interface AuthUser {
8
- id: string;
9
- name?: string | null;
10
- email?: string | null;
11
- image?: string | null;
12
- type: UserType;
13
- appId: string;
14
- isGuest: boolean;
15
- }
16
8
  interface NavItem {
17
9
  href: string;
18
10
  label: string;
@@ -32,6 +24,6 @@ interface SidebarProps {
32
24
  settingsHref?: string;
33
25
  onLogout?: () => void;
34
26
  }
35
- declare function Sidebar({ user: userProp, appId, authHost, navItems, title, logoutRedirectTo, profileHref, settingsHref, onLogout, }: SidebarProps): react_jsx_runtime.JSX.Element | null;
27
+ declare function Sidebar({ user, appId, authHost, navItems, title, logoutRedirectTo, profileHref, settingsHref, onLogout, }: SidebarProps): react_jsx_runtime.JSX.Element;
36
28
 
37
- export { type AuthUser, Hello, type NavItem, Sidebar, type SidebarProps, type UserType };
29
+ export { Hello, type NavItem, Sidebar, type SidebarProps };
package/dist/index.d.ts CHANGED
@@ -1,18 +1,10 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ComponentType } from 'react';
3
+ import { AuthUser } from '@create-flow/auth-ui';
4
+ export { AuthUser, UserType } from '@create-flow/auth-ui';
3
5
 
4
6
  declare function Hello(): react_jsx_runtime.JSX.Element;
5
7
 
6
- type UserType = "guest" | "regular";
7
- interface AuthUser {
8
- id: string;
9
- name?: string | null;
10
- email?: string | null;
11
- image?: string | null;
12
- type: UserType;
13
- appId: string;
14
- isGuest: boolean;
15
- }
16
8
  interface NavItem {
17
9
  href: string;
18
10
  label: string;
@@ -32,6 +24,6 @@ interface SidebarProps {
32
24
  settingsHref?: string;
33
25
  onLogout?: () => void;
34
26
  }
35
- declare function Sidebar({ user: userProp, appId, authHost, navItems, title, logoutRedirectTo, profileHref, settingsHref, onLogout, }: SidebarProps): react_jsx_runtime.JSX.Element | null;
27
+ declare function Sidebar({ user, appId, authHost, navItems, title, logoutRedirectTo, profileHref, settingsHref, onLogout, }: SidebarProps): react_jsx_runtime.JSX.Element;
36
28
 
37
- export { type AuthUser, Hello, type NavItem, Sidebar, type SidebarProps, type UserType };
29
+ export { Hello, type NavItem, Sidebar, type SidebarProps };
package/dist/index.js CHANGED
@@ -1,62 +1,12 @@
1
1
  "use client";
2
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
- import { useState, useRef, useEffect } from 'react';
4
- import Link from 'next/link';
5
- import { usePathname, useRouter } from 'next/navigation';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { useState, useEffect } from 'react';
4
+ import { UserMenu } from '@create-flow/auth-ui';
6
5
 
7
6
  // src/components/Hello.tsx
8
7
  function Hello() {
9
8
  return /* @__PURE__ */ jsx("div", { children: "Hello world" });
10
9
  }
11
-
12
- // src/utils/authApi.ts
13
- var DEFAULT_AUTH_HOST = (() => {
14
- if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_AUTH_API_HOST) {
15
- const envHost = process.env.NEXT_PUBLIC_AUTH_API_HOST.trim();
16
- if (envHost.length > 0) return envHost;
17
- }
18
- return "https://auth.create-flow.ai";
19
- })();
20
- var DEFAULT_APP_ID = typeof process !== "undefined" ? process.env?.NEXT_PUBLIC_AUTH_APP_ID?.trim() ?? "" : "";
21
- function normalizeHost(host) {
22
- const value = (host ?? DEFAULT_AUTH_HOST).trim();
23
- if (!value) throw new Error("Auth host is not configured");
24
- if (/^https?:\/\//i.test(value)) return value.replace(/\/+$/g, "");
25
- return `https://${value}`.replace(/\/+$/g, "");
26
- }
27
- function buildAuthUrl(path, host, query) {
28
- const normalizedHost = normalizeHost(host);
29
- const normalizedPath = path.startsWith("/") ? path : `/${path}`;
30
- const url = new URL(normalizedPath, normalizedHost);
31
- if (query) {
32
- for (const [key, value] of Object.entries(query)) {
33
- if (value !== void 0 && value !== null) {
34
- url.searchParams.set(key, value);
35
- }
36
- }
37
- }
38
- return url;
39
- }
40
- async function fetchWithCredentials(url, init = {}) {
41
- const response = await fetch(url.toString(), {
42
- credentials: "include",
43
- cache: "no-store",
44
- ...init
45
- });
46
- let data = null;
47
- try {
48
- data = await response.json();
49
- } catch {
50
- }
51
- return { response, data };
52
- }
53
- async function getAuthJson(path, host, query) {
54
- const url = buildAuthUrl(path, host, query);
55
- return fetchWithCredentials(url, { method: "GET" });
56
- }
57
- function getResolvedAppId(appId) {
58
- return (appId ?? DEFAULT_APP_ID).trim();
59
- }
60
10
  function HomeIcon({ className }) {
61
11
  return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: [
62
12
  /* @__PURE__ */ jsx("path", { d: "M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z" }),
@@ -66,57 +16,25 @@ function HomeIcon({ className }) {
66
16
  function FolderIcon({ className }) {
67
17
  return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z" }) });
68
18
  }
69
- function UserIcon({ className }) {
70
- return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: [
71
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "8", r: "4" }),
72
- /* @__PURE__ */ jsx("path", { d: "M4 20c0-4 3.6-7 8-7s8 3 8 7" })
73
- ] });
74
- }
75
19
  function SettingsIcon({ className }) {
76
20
  return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: [
77
21
  /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" }),
78
22
  /* @__PURE__ */ jsx("path", { d: "M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z" })
79
23
  ] });
80
24
  }
81
- function LogOutIcon({ className }) {
82
- return /* @__PURE__ */ jsxs("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round", children: [
83
- /* @__PURE__ */ jsx("path", { d: "M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4" }),
84
- /* @__PURE__ */ jsx("polyline", { points: "16,17 21,12 16,7" }),
85
- /* @__PURE__ */ jsx("line", { x1: "21", y1: "12", x2: "9", y2: "12" })
86
- ] });
87
- }
88
25
  function ChevronLeftIcon({ className }) {
89
26
  return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M15 18l-6-6 6-6" }) });
90
27
  }
91
28
  function ChevronRightIcon({ className }) {
92
29
  return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M9 18l6-6-6-6" }) });
93
30
  }
94
- function ChevronsUpDownIcon({ className }) {
95
- return /* @__PURE__ */ jsx("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M7 15l5 5 5-5M7 9l5-5 5 5" }) });
96
- }
97
31
  var defaultNavItems = [
98
32
  { href: "/dashboard", label: "Dashboard", icon: HomeIcon, exact: true },
99
33
  { href: "/dashboard/projects", label: "Projects", icon: FolderIcon, exact: false },
100
34
  { href: "/dashboard/settings", label: "Settings", icon: SettingsIcon, exact: false }
101
35
  ];
102
- var AVATAR_COLORS = [
103
- "bg-violet-600",
104
- "bg-indigo-600",
105
- "bg-sky-600",
106
- "bg-emerald-600",
107
- "bg-amber-600",
108
- "bg-rose-600"
109
- ];
110
- function getAvatarColor(name) {
111
- let hash = 0;
112
- for (let i = 0; i < name.length; i++) hash = name.charCodeAt(i) + ((hash << 5) - hash);
113
- return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];
114
- }
115
- function getInitials(name) {
116
- return name.split(" ").filter(Boolean).map((w) => w[0]).join("").toUpperCase().slice(0, 2);
117
- }
118
36
  function Sidebar({
119
- user: userProp,
37
+ user,
120
38
  appId,
121
39
  authHost,
122
40
  navItems = defaultNavItems,
@@ -127,63 +45,13 @@ function Sidebar({
127
45
  onLogout
128
46
  }) {
129
47
  const [isCollapsed, setIsCollapsed] = useState(false);
130
- const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);
131
- const [fetchedUser, setFetchedUser] = useState(null);
132
- const [isLoading, setIsLoading] = useState(!userProp);
133
- const pathname = usePathname();
134
- const router = useRouter();
135
- const menuRef = useRef(null);
48
+ const [pathname, setPathname] = useState(typeof window !== "undefined" ? window.location.pathname : "/");
136
49
  useEffect(() => {
137
- if (userProp) return;
138
- let cancelled = false;
139
- async function fetchSession() {
140
- try {
141
- const { response, data } = await getAuthJson("api/auth/session", authHost);
142
- if (!cancelled && response.ok && data?.user) {
143
- setFetchedUser(data.user);
144
- }
145
- } catch (err) {
146
- console.error("Failed to fetch session:", err);
147
- } finally {
148
- if (!cancelled) setIsLoading(false);
149
- }
150
- }
151
- fetchSession();
152
- return () => {
153
- cancelled = true;
154
- };
155
- }, [authHost, userProp]);
156
- useEffect(() => {
157
- function handleClickOutside(e) {
158
- if (menuRef.current && !menuRef.current.contains(e.target)) {
159
- setIsUserMenuOpen(false);
160
- }
161
- }
162
- document.addEventListener("mousedown", handleClickOutside);
163
- return () => document.removeEventListener("mousedown", handleClickOutside);
50
+ setPathname(window.location.pathname);
164
51
  }, []);
165
- const user = userProp || fetchedUser;
166
- if (isLoading || !user) return null;
167
- const displayName = user.name || user.email?.split("@")[0] || "User";
168
- const initials = getInitials(displayName);
169
- const avatarColor = getAvatarColor(displayName);
170
52
  function isActive(href, exact) {
171
53
  return exact ? pathname === href : pathname.startsWith(href);
172
54
  }
173
- async function handleLogout() {
174
- const resolvedAppId = getResolvedAppId(appId);
175
- try {
176
- await getAuthJson("api/auth/logout", authHost, resolvedAppId ? { appId: resolvedAppId } : void 0);
177
- } catch (err) {
178
- console.error("Logout error:", err);
179
- }
180
- if (onLogout) {
181
- onLogout();
182
- } else {
183
- router.push(logoutRedirectTo);
184
- router.refresh();
185
- }
186
- }
187
55
  return /* @__PURE__ */ jsxs(
188
56
  "aside",
189
57
  {
@@ -210,7 +78,7 @@ function Sidebar({
210
78
  /* @__PURE__ */ jsx("nav", { className: "flex-1 overflow-y-auto py-2 px-2 space-y-0.5", children: navItems.map(({ href, label, icon: Icon, exact }) => {
211
79
  const active = isActive(href, exact ?? false);
212
80
  return /* @__PURE__ */ jsxs(
213
- Link,
81
+ "a",
214
82
  {
215
83
  href,
216
84
  title: isCollapsed ? label : void 0,
@@ -223,85 +91,18 @@ function Sidebar({
223
91
  href
224
92
  );
225
93
  }) }),
226
- /* @__PURE__ */ jsxs(
227
- "div",
94
+ /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 p-2 border-t border-zinc-200", children: /* @__PURE__ */ jsx(
95
+ UserMenu,
228
96
  {
229
- ref: menuRef,
230
- className: "relative flex-shrink-0 p-2 border-t border-zinc-200",
231
- children: [
232
- isUserMenuOpen && /* @__PURE__ */ jsxs(
233
- "div",
234
- {
235
- className: "absolute bottom-full mb-1 z-50 bg-white border border-zinc-200 rounded-xl shadow-lg shadow-zinc-200/50 overflow-hidden " + (isCollapsed ? "left-full ml-2 w-52" : "left-2 right-2"),
236
- children: [
237
- /* @__PURE__ */ jsxs("div", { className: "px-3.5 py-3 border-b border-zinc-100", children: [
238
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-zinc-900 truncate", children: displayName }),
239
- user.email && /* @__PURE__ */ jsx("p", { className: "text-xs text-zinc-500 truncate mt-0.5", children: user.email })
240
- ] }),
241
- /* @__PURE__ */ jsxs("div", { className: "p-1", children: [
242
- /* @__PURE__ */ jsxs(
243
- Link,
244
- {
245
- href: profileHref,
246
- onClick: () => setIsUserMenuOpen(false),
247
- className: "flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors",
248
- children: [
249
- /* @__PURE__ */ jsx(UserIcon, { className: "w-4 h-4 text-zinc-400" }),
250
- "Profile"
251
- ]
252
- }
253
- ),
254
- /* @__PURE__ */ jsxs(
255
- Link,
256
- {
257
- href: settingsHref,
258
- onClick: () => setIsUserMenuOpen(false),
259
- className: "flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors",
260
- children: [
261
- /* @__PURE__ */ jsx(SettingsIcon, { className: "w-4 h-4 text-zinc-400" }),
262
- "Settings"
263
- ]
264
- }
265
- ),
266
- /* @__PURE__ */ jsxs(
267
- "button",
268
- {
269
- onClick: handleLogout,
270
- className: "flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors text-left",
271
- children: [
272
- /* @__PURE__ */ jsx(LogOutIcon, { className: "w-4 h-4 text-zinc-400" }),
273
- "Log out"
274
- ]
275
- }
276
- )
277
- ] })
278
- ]
279
- }
280
- ),
281
- /* @__PURE__ */ jsxs(
282
- "button",
283
- {
284
- onClick: () => setIsUserMenuOpen((o) => !o),
285
- title: isCollapsed ? displayName : void 0,
286
- className: "w-full flex items-center gap-2.5 p-2 rounded-lg hover:bg-zinc-50 transition-colors text-left " + (isCollapsed ? "justify-center" : ""),
287
- children: [
288
- /* @__PURE__ */ jsx(
289
- "div",
290
- {
291
- className: "w-7 h-7 rounded-full flex items-center justify-center flex-shrink-0 " + avatarColor,
292
- children: /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-white leading-none", children: initials })
293
- }
294
- ),
295
- !isCollapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
296
- /* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-zinc-900 truncate leading-tight", children: displayName }) }),
297
- /* @__PURE__ */ jsx(ChevronsUpDownIcon, { className: "w-3.5 h-3.5 text-zinc-400 flex-shrink-0" })
298
- ] })
299
- ]
300
- }
301
- )
302
- ]
97
+ user,
98
+ appId,
99
+ authHost,
100
+ logoutRedirectTo,
101
+ profileHref,
102
+ settingsHref,
103
+ onLogout
303
104
  }
304
- )
105
+ ) })
305
106
  ]
306
107
  }
307
108
  );
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Hello.tsx","../src/utils/authApi.ts","../src/components/Sidebar.tsx"],"names":["jsx"],"mappings":"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","file":"index.js","sourcesContent":["export function Hello() {\n return <div>Hello world</div>;\n}\n","const DEFAULT_AUTH_HOST = (() => {\n if (typeof process !== \"undefined\" && process.env?.NEXT_PUBLIC_AUTH_API_HOST) {\n const envHost = process.env.NEXT_PUBLIC_AUTH_API_HOST.trim();\n if (envHost.length > 0) return envHost;\n }\n return \"https://auth.create-flow.ai\";\n})();\n\nconst DEFAULT_APP_ID =\n typeof process !== \"undefined\"\n ? process.env?.NEXT_PUBLIC_AUTH_APP_ID?.trim() ?? \"\"\n : \"\";\n\nfunction normalizeHost(host?: string) {\n const value = (host ?? DEFAULT_AUTH_HOST).trim();\n if (!value) throw new Error(\"Auth host is not configured\");\n if (/^https?:\\/\\//i.test(value)) return value.replace(/\\/+$/g, \"\");\n return `https://${value}`.replace(/\\/+$/g, \"\");\n}\n\nfunction buildAuthUrl(\n path: string,\n host?: string,\n query?: Record<string, string | undefined>\n) {\n const normalizedHost = normalizeHost(host);\n const normalizedPath = path.startsWith(\"/\") ? path : `/${path}`;\n const url = new URL(normalizedPath, normalizedHost);\n\n if (query) {\n for (const [key, value] of Object.entries(query)) {\n if (value !== undefined && value !== null) {\n url.searchParams.set(key, value);\n }\n }\n }\n\n return url;\n}\n\nasync function fetchWithCredentials(url: URL, init: RequestInit = {}) {\n const response = await fetch(url.toString(), {\n credentials: \"include\",\n cache: \"no-store\",\n ...init,\n });\n let data: any = null;\n try {\n data = await response.json();\n } catch {\n // Ignore JSON parse errors\n }\n return { response, data };\n}\n\nexport async function getAuthJson(\n path: string,\n host?: string,\n query?: Record<string, string | undefined>\n) {\n const url = buildAuthUrl(path, host, query);\n return fetchWithCredentials(url, { method: \"GET\" });\n}\n\nexport function getResolvedAppId(appId?: string) {\n return (appId ?? DEFAULT_APP_ID).trim();\n}\n","\"use client\";\n\nimport { useState, useRef, useEffect, type ComponentType } from \"react\";\nimport Link from \"next/link\";\nimport { usePathname, useRouter } from \"next/navigation\";\n\nimport { getResolvedAppId, getAuthJson } from \"../utils/authApi\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type UserType = \"guest\" | \"regular\";\n\nexport interface AuthUser {\n id: string;\n name?: string | null;\n email?: string | null;\n image?: string | null;\n type: UserType;\n appId: string;\n isGuest: boolean;\n}\n\nexport interface NavItem {\n href: string;\n label: string;\n icon: ComponentType<{ className?: string }>;\n exact?: boolean;\n}\n\nexport interface SidebarProps {\n user?: AuthUser;\n appId?: string;\n authHost?: string;\n navItems?: NavItem[];\n title?: string;\n logoutRedirectTo?: string;\n profileHref?: string;\n settingsHref?: string;\n onLogout?: () => void;\n}\n\n// ── Icons ─────────────────────────────────────────────────────────────────────\n\nfunction HomeIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z\" />\n <path d=\"M9 22V12h6v10\" />\n </svg>\n );\n}\n\nfunction FolderIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z\" />\n </svg>\n );\n}\n\nfunction UserIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"8\" r=\"4\" />\n <path d=\"M4 20c0-4 3.6-7 8-7s8 3 8 7\" />\n </svg>\n );\n}\n\nfunction SettingsIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n <path d=\"M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z\" />\n </svg>\n );\n}\n\nfunction LogOutIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M9 21H5a2 2 0 01-2-2V5a2 2 0 012-2h4\" />\n <polyline points=\"16,17 21,12 16,7\" />\n <line x1=\"21\" y1=\"12\" x2=\"9\" y2=\"12\" />\n </svg>\n );\n}\n\nfunction ChevronLeftIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n );\n}\n\nfunction ChevronRightIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n );\n}\n\nfunction ChevronsUpDownIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M7 15l5 5 5-5M7 9l5-5 5 5\" />\n </svg>\n );\n}\n\n// ── Default nav items ─────────────────────────────────────────────────────────\n\nconst defaultNavItems: NavItem[] = [\n { href: \"/dashboard\", label: \"Dashboard\", icon: HomeIcon, exact: true },\n { href: \"/dashboard/projects\", label: \"Projects\", icon: FolderIcon, exact: false },\n { href: \"/dashboard/settings\", label: \"Settings\", icon: SettingsIcon, exact: false },\n];\n\n// ── Avatar ────────────────────────────────────────────────────────────────────\n\nconst AVATAR_COLORS = [\n \"bg-violet-600\",\n \"bg-indigo-600\",\n \"bg-sky-600\",\n \"bg-emerald-600\",\n \"bg-amber-600\",\n \"bg-rose-600\",\n];\n\nfunction getAvatarColor(name: string): string {\n let hash = 0;\n for (let i = 0; i < name.length; i++) hash = name.charCodeAt(i) + ((hash << 5) - hash);\n return AVATAR_COLORS[Math.abs(hash) % AVATAR_COLORS.length];\n}\n\nfunction getInitials(name: string): string {\n return name\n .split(\" \")\n .filter(Boolean)\n .map((w) => w[0])\n .join(\"\")\n .toUpperCase()\n .slice(0, 2);\n}\n\n// ── Sidebar ───────────────────────────────────────────────────────────────────\n\nexport function Sidebar({\n user: userProp,\n appId,\n authHost,\n navItems = defaultNavItems,\n title = \"Workspace\",\n logoutRedirectTo = \"/\",\n profileHref = \"/profile\",\n settingsHref = \"/settings\",\n onLogout,\n}: SidebarProps) {\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [isUserMenuOpen, setIsUserMenuOpen] = useState(false);\n const [fetchedUser, setFetchedUser] = useState<AuthUser | null>(null);\n const [isLoading, setIsLoading] = useState(!userProp);\n const pathname = usePathname();\n const router = useRouter();\n const menuRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (userProp) return;\n\n let cancelled = false;\n\n async function fetchSession() {\n try {\n const { response, data } = await getAuthJson(\"api/auth/session\", authHost);\n if (!cancelled && response.ok && data?.user) {\n setFetchedUser(data.user);\n }\n } catch (err) {\n console.error(\"Failed to fetch session:\", err);\n } finally {\n if (!cancelled) setIsLoading(false);\n }\n }\n\n fetchSession();\n return () => { cancelled = true; };\n }, [authHost, userProp]);\n\n useEffect(() => {\n function handleClickOutside(e: MouseEvent) {\n if (menuRef.current && !menuRef.current.contains(e.target as Node)) {\n setIsUserMenuOpen(false);\n }\n }\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => document.removeEventListener(\"mousedown\", handleClickOutside);\n }, []);\n\n const user = userProp || fetchedUser;\n\n if (isLoading || !user) return null;\n\n const displayName = user.name || user.email?.split(\"@\")[0] || \"User\";\n const initials = getInitials(displayName);\n const avatarColor = getAvatarColor(displayName);\n\n function isActive(href: string, exact: boolean) {\n return exact ? pathname === href : pathname.startsWith(href);\n }\n\n async function handleLogout() {\n const resolvedAppId = getResolvedAppId(appId);\n\n try {\n await getAuthJson(\"api/auth/logout\", authHost, resolvedAppId ? { appId: resolvedAppId } : undefined);\n } catch (err) {\n console.error(\"Logout error:\", err);\n }\n\n if (onLogout) {\n onLogout();\n } else {\n router.push(logoutRedirectTo);\n router.refresh();\n }\n }\n\n return (\n <aside\n className={\n \"relative flex flex-col h-screen bg-white border-r border-zinc-200 transition-all duration-200 ease-in-out flex-shrink-0 \" +\n (isCollapsed ? \"w-[60px]\" : \"w-[220px]\")\n }\n >\n {/* ── Header ─────────────────────────────────────────────────────────── */}\n <div\n className={\n \"flex items-center h-14 px-3 flex-shrink-0 border-b border-zinc-200 \" +\n (isCollapsed ? \"justify-center\" : \"justify-between\")\n }\n >\n {!isCollapsed && (\n <span className=\"text-sm font-semibold text-zinc-900 tracking-tight truncate select-none\">\n {title}\n </span>\n )}\n <button\n onClick={() => setIsCollapsed((c) => !c)}\n title={isCollapsed ? \"Expand sidebar\" : \"Collapse sidebar\"}\n className=\"p-1.5 rounded-md text-zinc-400 hover:text-zinc-700 hover:bg-zinc-100 transition-colors flex-shrink-0\"\n >\n {isCollapsed ? (\n <ChevronRightIcon className=\"w-4 h-4\" />\n ) : (\n <ChevronLeftIcon className=\"w-4 h-4\" />\n )}\n </button>\n </div>\n\n {/* ── Nav ────────────────────────────────────────────────────────────── */}\n <nav className=\"flex-1 overflow-y-auto py-2 px-2 space-y-0.5\">\n {navItems.map(({ href, label, icon: Icon, exact }) => {\n const active = isActive(href, exact ?? false);\n return (\n <Link\n key={href}\n href={href}\n title={isCollapsed ? label : undefined}\n className={\n \"flex items-center gap-2.5 px-2.5 py-2 rounded-lg text-sm transition-colors \" +\n (isCollapsed ? \"justify-center \" : \"\") +\n (active\n ? \"bg-zinc-100 text-zinc-900 font-medium\"\n : \"text-zinc-500 hover:bg-zinc-50 hover:text-zinc-900\")\n }\n >\n <Icon className=\"w-4 h-4 flex-shrink-0\" />\n {!isCollapsed && <span className=\"truncate\">{label}</span>}\n </Link>\n );\n })}\n </nav>\n\n {/* ── User area ──────────────────────────────────────────────────────── */}\n <div\n ref={menuRef}\n className=\"relative flex-shrink-0 p-2 border-t border-zinc-200\"\n >\n {/* Dropdown menu */}\n {isUserMenuOpen && (\n <div\n className={\n \"absolute bottom-full mb-1 z-50 bg-white border border-zinc-200 rounded-xl shadow-lg shadow-zinc-200/50 overflow-hidden \" +\n (isCollapsed ? \"left-full ml-2 w-52\" : \"left-2 right-2\")\n }\n >\n {/* User info */}\n <div className=\"px-3.5 py-3 border-b border-zinc-100\">\n <p className=\"text-sm font-medium text-zinc-900 truncate\">\n {displayName}\n </p>\n {user.email && (\n <p className=\"text-xs text-zinc-500 truncate mt-0.5\">\n {user.email}\n </p>\n )}\n </div>\n {/* Menu items */}\n <div className=\"p-1\">\n <Link\n href={profileHref}\n onClick={() => setIsUserMenuOpen(false)}\n className=\"flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors\"\n >\n <UserIcon className=\"w-4 h-4 text-zinc-400\" />\n Profile\n </Link>\n <Link\n href={settingsHref}\n onClick={() => setIsUserMenuOpen(false)}\n className=\"flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors\"\n >\n <SettingsIcon className=\"w-4 h-4 text-zinc-400\" />\n Settings\n </Link>\n <button\n onClick={handleLogout}\n className=\"flex items-center gap-2.5 w-full px-3 py-2 text-sm text-zinc-700 hover:bg-zinc-50 rounded-lg transition-colors text-left\"\n >\n <LogOutIcon className=\"w-4 h-4 text-zinc-400\" />\n Log out\n </button>\n </div>\n </div>\n )}\n\n {/* User trigger button */}\n <button\n onClick={() => setIsUserMenuOpen((o) => !o)}\n title={isCollapsed ? displayName : undefined}\n className={\n \"w-full flex items-center gap-2.5 p-2 rounded-lg hover:bg-zinc-50 transition-colors text-left \" +\n (isCollapsed ? \"justify-center\" : \"\")\n }\n >\n <div\n className={\"w-7 h-7 rounded-full flex items-center justify-center flex-shrink-0 \" + avatarColor}\n >\n <span className=\"text-xs font-semibold text-white leading-none\">\n {initials}\n </span>\n </div>\n {!isCollapsed && (\n <>\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium text-zinc-900 truncate leading-tight\">\n {displayName}\n </p>\n </div>\n <ChevronsUpDownIcon className=\"w-3.5 h-3.5 text-zinc-400 flex-shrink-0\" />\n </>\n )}\n </button>\n </div>\n </aside>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/components/Hello.tsx","../src/components/Sidebar.tsx"],"names":["jsx"],"mappings":"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","file":"index.js","sourcesContent":["export function Hello() {\n return <div>Hello world</div>;\n}\n","\"use client\";\n\nimport { useState, useEffect, type ComponentType } from \"react\";\nimport { UserMenu } from \"@create-flow/auth-ui\";\nimport type { AuthUser } from \"@create-flow/auth-ui\";\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type { AuthUser, UserType } from \"@create-flow/auth-ui\";\n\nexport interface NavItem {\n href: string;\n label: string;\n icon: ComponentType<{ className?: string }>;\n exact?: boolean;\n}\n\nexport interface SidebarProps {\n user?: AuthUser;\n appId?: string;\n authHost?: string;\n navItems?: NavItem[];\n title?: string;\n logoutRedirectTo?: string;\n profileHref?: string;\n settingsHref?: string;\n onLogout?: () => void;\n}\n\n// ── Icons ─────────────────────────────────────────────────────────────────────\n\nfunction HomeIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z\" />\n <path d=\"M9 22V12h6v10\" />\n </svg>\n );\n}\n\nfunction FolderIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M22 19a2 2 0 01-2 2H4a2 2 0 01-2-2V5a2 2 0 012-2h5l2 3h9a2 2 0 012 2z\" />\n </svg>\n );\n}\n\nfunction SettingsIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.75\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\n <path d=\"M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z\" />\n </svg>\n );\n}\n\nfunction ChevronLeftIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M15 18l-6-6 6-6\" />\n </svg>\n );\n}\n\nfunction ChevronRightIcon({ className }: { className?: string }) {\n return (\n <svg className={className} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M9 18l6-6-6-6\" />\n </svg>\n );\n}\n\n// ── Default nav items ─────────────────────────────────────────────────────────\n\nconst defaultNavItems: NavItem[] = [\n { href: \"/dashboard\", label: \"Dashboard\", icon: HomeIcon, exact: true },\n { href: \"/dashboard/projects\", label: \"Projects\", icon: FolderIcon, exact: false },\n { href: \"/dashboard/settings\", label: \"Settings\", icon: SettingsIcon, exact: false },\n];\n\n// ── Sidebar ───────────────────────────────────────────────────────────────────\n\nexport function Sidebar({\n user,\n appId,\n authHost,\n navItems = defaultNavItems,\n title = \"Workspace\",\n logoutRedirectTo = \"/\",\n profileHref = \"/profile\",\n settingsHref = \"/settings\",\n onLogout,\n}: SidebarProps) {\n const [isCollapsed, setIsCollapsed] = useState(false);\n const [pathname, setPathname] = useState(typeof window !== \"undefined\" ? window.location.pathname : \"/\");\n\n useEffect(() => {\n setPathname(window.location.pathname);\n }, []);\n\n function isActive(href: string, exact: boolean) {\n return exact ? pathname === href : pathname.startsWith(href);\n }\n\n return (\n <aside\n className={\n \"relative flex flex-col h-screen bg-white border-r border-zinc-200 transition-all duration-200 ease-in-out flex-shrink-0 \" +\n (isCollapsed ? \"w-[60px]\" : \"w-[220px]\")\n }\n >\n {/* ── Header ─────────────────────────────────────────────────────────── */}\n <div\n className={\n \"flex items-center h-14 px-3 flex-shrink-0 border-b border-zinc-200 \" +\n (isCollapsed ? \"justify-center\" : \"justify-between\")\n }\n >\n {!isCollapsed && (\n <span className=\"text-sm font-semibold text-zinc-900 tracking-tight truncate select-none\">\n {title}\n </span>\n )}\n <button\n onClick={() => setIsCollapsed((c) => !c)}\n title={isCollapsed ? \"Expand sidebar\" : \"Collapse sidebar\"}\n className=\"p-1.5 rounded-md text-zinc-400 hover:text-zinc-700 hover:bg-zinc-100 transition-colors flex-shrink-0\"\n >\n {isCollapsed ? (\n <ChevronRightIcon className=\"w-4 h-4\" />\n ) : (\n <ChevronLeftIcon className=\"w-4 h-4\" />\n )}\n </button>\n </div>\n\n {/* ── Nav ────────────────────────────────────────────────────────────── */}\n <nav className=\"flex-1 overflow-y-auto py-2 px-2 space-y-0.5\">\n {navItems.map(({ href, label, icon: Icon, exact }) => {\n const active = isActive(href, exact ?? false);\n return (\n <a\n key={href}\n href={href}\n title={isCollapsed ? label : undefined}\n className={\n \"flex items-center gap-2.5 px-2.5 py-2 rounded-lg text-sm transition-colors \" +\n (isCollapsed ? \"justify-center \" : \"\") +\n (active\n ? \"bg-zinc-100 text-zinc-900 font-medium\"\n : \"text-zinc-500 hover:bg-zinc-50 hover:text-zinc-900\")\n }\n >\n <Icon className=\"w-4 h-4 flex-shrink-0\" />\n {!isCollapsed && <span className=\"truncate\">{label}</span>}\n </a>\n );\n })}\n </nav>\n\n {/* ── User area ──────────────────────────────────────────────────────── */}\n <div className=\"flex-shrink-0 p-2 border-t border-zinc-200\">\n <UserMenu\n user={user}\n appId={appId}\n authHost={authHost}\n logoutRedirectTo={logoutRedirectTo}\n profileHref={profileHref}\n settingsHref={settingsHref}\n onLogout={onLogout}\n />\n </div>\n </aside>\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@create-flow/common-ui",
3
- "version": "0.3.6",
3
+ "version": "0.3.8",
4
4
  "description": "Shared UI components for Flow apps",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -11,7 +11,8 @@
11
11
  "types": "./dist/index.d.ts",
12
12
  "import": "./dist/index.js",
13
13
  "require": "./dist/index.cjs"
14
- }
14
+ },
15
+ "./styles": "./dist/index.css"
15
16
  },
16
17
  "files": [
17
18
  "dist"
@@ -21,7 +22,8 @@
21
22
  },
22
23
  "sideEffects": false,
23
24
  "scripts": {
24
- "build": "tsup",
25
+ "build": "tsup && bun run build:css",
26
+ "build:css": "tailwindcss -i ./src/index.css -o ./dist/index.css --minify",
25
27
  "lint": "eslint src",
26
28
  "prepublishOnly": "bun run build",
27
29
  "publish:dry": "npm pack --dry-run",
@@ -33,11 +35,12 @@
33
35
  "publish:major": "bun run version:major && bun publish"
34
36
  },
35
37
  "peerDependencies": {
36
- "next": ">=14",
38
+ "@create-flow/auth-ui": ">=0.0.2",
37
39
  "react": ">=18",
38
40
  "react-dom": ">=18"
39
41
  },
40
42
  "devDependencies": {
43
+ "@create-flow/auth-ui": "0.0.2",
41
44
  "@eslint/js": "^9",
42
45
  "@types/react": "^19",
43
46
  "@types/react-dom": "^19",
@@ -45,6 +48,7 @@
45
48
  "typescript-eslint": "^8",
46
49
  "react": "19.2.3",
47
50
  "react-dom": "19.2.3",
51
+ "tailwindcss": "^3.3.5",
48
52
  "tsup": "^8",
49
53
  "typescript": "^5"
50
54
  }