@campfire-interactive/shell-header 0.1.3 → 0.1.5
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.d.ts +6 -2
- package/dist/index.js +16 -13
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ interface AppDefinition {
|
|
|
6
6
|
icon: string;
|
|
7
7
|
/** Single letter shown in the branded badge */
|
|
8
8
|
letter: string;
|
|
9
|
+
/** Badge background color */
|
|
10
|
+
color: string;
|
|
9
11
|
/** Local dev port (e.g., 3000). Omit if the app doesn't run locally. */
|
|
10
12
|
localPort?: number;
|
|
11
13
|
}
|
|
@@ -27,11 +29,13 @@ interface ShellHeaderProps {
|
|
|
27
29
|
onNotificationClick?: () => void;
|
|
28
30
|
/** Called when logout is clicked */
|
|
29
31
|
onLogout?: () => void;
|
|
30
|
-
/**
|
|
32
|
+
/** Fixed width for the app brand area (e.g., to align with a sidebar below). */
|
|
33
|
+
brandWidth?: number;
|
|
34
|
+
/** Optional content in the left/center area (filters, search, breadcrumbs, etc.) */
|
|
31
35
|
children?: React.ReactNode;
|
|
32
36
|
}
|
|
33
37
|
|
|
34
|
-
declare function ShellHeader({ appId, user, authorizedApps, notificationCount, onNotificationClick, onLogout, children, }: ShellHeaderProps): react_jsx_runtime.JSX.Element;
|
|
38
|
+
declare function ShellHeader({ appId, user, authorizedApps, notificationCount, onNotificationClick, onLogout, brandWidth, children, }: ShellHeaderProps): react_jsx_runtime.JSX.Element;
|
|
35
39
|
|
|
36
40
|
declare const appCatalog: AppDefinition[];
|
|
37
41
|
/**
|
package/dist/index.js
CHANGED
|
@@ -24,17 +24,17 @@ function styleInject(css, { insertAt } = {}) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// src/styles.css
|
|
27
|
-
styleInject(".cfi-sh-header {\n display: flex;\n align-items: center;\n height: var(--cfi-shell-header-height, 48px);\n padding: 0 var(--cfi-spacing-md, 1rem);\n background: white;\n color: var(--cfi-color-gray-900, #111827);\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n position: relative;\n z-index: 1000;\n}\n.cfi-sh-left {\n display: flex;\n align-items: center;\n flex: 1;\n gap: var(--cfi-spacing-md, 1rem);\n overflow: hidden;\n}\n.cfi-sh-app-brand {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n
|
|
27
|
+
styleInject(".cfi-sh-header {\n display: flex;\n align-items: center;\n height: var(--cfi-shell-header-height, 48px);\n padding: 0 var(--cfi-spacing-md, 1rem);\n background: white;\n color: var(--cfi-color-gray-900, #111827);\n font-family: var(--cfi-font-family, system-ui, sans-serif);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n border-bottom: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n position: relative;\n z-index: 1000;\n}\n.cfi-sh-left {\n display: flex;\n align-items: center;\n flex: 1;\n gap: var(--cfi-spacing-md, 1rem);\n overflow: hidden;\n}\n.cfi-sh-app-brand {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-badge {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n color: white;\n font-size: 14px;\n font-weight: 700;\n font-family: inherit;\n border-radius: var(--cfi-radius-md, 0.375rem);\n flex-shrink: 0;\n}\n.cfi-sh-app-title {\n font-weight: 600;\n font-size: var(--cfi-font-size-base, 1rem);\n color: var(--cfi-color-gray-900, #111827);\n white-space: nowrap;\n}\n.cfi-sh-right {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n flex-shrink: 0;\n}\n.cfi-sh-icon-btn {\n position: relative;\n display: flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n background: transparent;\n border: none;\n border-radius: 50%;\n color: var(--cfi-color-gray-600, #4b5563);\n cursor: pointer;\n transition: background 150ms;\n}\n.cfi-sh-icon-btn:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-badge {\n position: absolute;\n top: 2px;\n right: 2px;\n min-width: 16px;\n height: 16px;\n padding: 0 4px;\n background: var(--cfi-color-error, #ef4444);\n color: white;\n font-size: 10px;\n font-weight: 600;\n line-height: 16px;\n text-align: center;\n border-radius: 99px;\n}\n.cfi-sh-app-switcher {\n position: relative;\n}\n.cfi-sh-app-grid {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n display: grid;\n grid-template-columns: repeat(3, 1fr);\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem);\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n min-width: 280px;\n}\n.cfi-sh-app-grid-item {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: var(--cfi-spacing-xs, 0.25rem);\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-xs, 0.25rem);\n border-radius: var(--cfi-radius-md, 0.375rem);\n color: var(--cfi-color-gray-700, #374151);\n text-decoration: none;\n cursor: pointer;\n transition: background 100ms;\n font-family: inherit;\n}\n.cfi-sh-app-grid-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n.cfi-sh-app-grid-item-active {\n background: var(--cfi-color-primary-50, #fff7ed);\n color: var(--cfi-color-primary-700, #c2410c);\n}\n.cfi-sh-app-grid-item-active:hover {\n background: var(--cfi-color-primary-100, #ffedd5);\n}\n.cfi-sh-app-grid-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 40px;\n height: 40px;\n border-radius: 50%;\n}\n.cfi-sh-app-grid-label {\n font-size: var(--cfi-font-size-xs, 0.75rem);\n text-align: center;\n line-height: 1.2;\n max-width: 80px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.cfi-sh-user-menu {\n position: relative;\n}\n.cfi-sh-avatar-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n padding: 0;\n background: var(--cfi-color-primary-600, #ea580c);\n border: none;\n border-radius: 50%;\n cursor: pointer;\n transition: opacity 150ms;\n}\n.cfi-sh-avatar-btn:hover {\n opacity: 0.85;\n}\n.cfi-sh-avatar-img {\n width: 32px;\n height: 32px;\n border-radius: 50%;\n object-fit: cover;\n}\n.cfi-sh-avatar-initials {\n color: white;\n font-size: var(--cfi-font-size-xs, 0.75rem);\n font-weight: 600;\n font-family: inherit;\n}\n.cfi-sh-user-dropdown {\n position: absolute;\n top: calc(100% + 8px);\n right: 0;\n min-width: 200px;\n background: white;\n border-radius: var(--cfi-radius-lg, 0.5rem);\n box-shadow: var(--cfi-shadow-lg, 0 10px 15px rgba(0, 0, 0, 0.1));\n border: 1px solid var(--cfi-color-gray-200, #e5e7eb);\n z-index: 1001;\n}\n.cfi-sh-user-header {\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n display: flex;\n flex-direction: column;\n}\n.cfi-sh-user-name {\n font-weight: 500;\n color: var(--cfi-color-gray-900, #111827);\n font-size: var(--cfi-font-size-sm, 0.875rem);\n}\n.cfi-sh-user-email {\n color: var(--cfi-color-gray-500, #6b7280);\n font-size: var(--cfi-font-size-xs, 0.75rem);\n}\n.cfi-sh-divider {\n height: 1px;\n background: var(--cfi-color-gray-200, #e5e7eb);\n}\n.cfi-sh-menu-item {\n display: flex;\n align-items: center;\n gap: var(--cfi-spacing-sm, 0.5rem);\n width: 100%;\n padding: var(--cfi-spacing-sm, 0.5rem) var(--cfi-spacing-md, 1rem);\n background: none;\n border: none;\n color: var(--cfi-color-gray-700, #374151);\n cursor: pointer;\n font-size: var(--cfi-font-size-sm, 0.875rem);\n font-family: inherit;\n transition: background 100ms;\n}\n.cfi-sh-menu-item:hover {\n background: var(--cfi-color-gray-100, #f3f4f6);\n}\n");
|
|
28
28
|
|
|
29
29
|
// src/appCatalog.ts
|
|
30
30
|
var appCatalog = [
|
|
31
|
-
{ id: "si", name: "Supplier Intelligence", icon: "Building2", letter: "S", localPort: 3e3 },
|
|
32
|
-
{ id: "masterdata", name: "Master Data", icon: "Database", letter: "M", localPort: 3100 },
|
|
33
|
-
{ id: "forecast", name: "Forecasting", icon: "TrendingUp", letter: "F", localPort: 3200 },
|
|
34
|
-
{ id: "pim", name: "Price Index", icon: "BarChart3", letter: "P", localPort: 3300 },
|
|
35
|
-
{ id: "cpq", name: "CPQ", icon: "Calculator", letter: "C", localPort: 3400 },
|
|
36
|
-
{ id: "omsf", name: "OMSF", icon: "FileText", letter: "O", localPort: 3500 },
|
|
37
|
-
{ id: "identity", name: "Identity", icon: "Shield", letter: "I", localPort: 3600 }
|
|
31
|
+
{ id: "si", name: "Supplier Intelligence", icon: "Building2", letter: "S", color: "#6366f1", localPort: 3e3 },
|
|
32
|
+
{ id: "masterdata", name: "Master Data", icon: "Database", letter: "M", color: "#f97316", localPort: 3100 },
|
|
33
|
+
{ id: "forecast", name: "Forecasting", icon: "TrendingUp", letter: "F", color: "#10b981", localPort: 3200 },
|
|
34
|
+
{ id: "pim", name: "Price Index", icon: "BarChart3", letter: "P", color: "#f97316", localPort: 3300 },
|
|
35
|
+
{ id: "cpq", name: "CPQ", icon: "Calculator", letter: "C", color: "#4f46e5", localPort: 3400 },
|
|
36
|
+
{ id: "omsf", name: "OMSF", icon: "FileText", letter: "O", color: "#0ea5e9", localPort: 3500 },
|
|
37
|
+
{ id: "identity", name: "Identity", icon: "Shield", letter: "I", color: "#8b5cf6", localPort: 3600 }
|
|
38
38
|
];
|
|
39
39
|
function getAppUrl(app) {
|
|
40
40
|
const host = typeof window !== "undefined" ? window.location.hostname : "";
|
|
@@ -131,7 +131,7 @@ function AppSwitcher({ currentAppId, authorizedApps }) {
|
|
|
131
131
|
setOpen(false);
|
|
132
132
|
} : void 0,
|
|
133
133
|
children: [
|
|
134
|
-
/* @__PURE__ */ jsx2("div", { className: "cfi-sh-app-grid-icon", children: /* @__PURE__ */ jsx2(Icon, { size: 22 }) }),
|
|
134
|
+
/* @__PURE__ */ jsx2("div", { className: "cfi-sh-app-grid-icon", style: { background: `${app.color}18`, color: app.color }, children: /* @__PURE__ */ jsx2(Icon, { size: 22 }) }),
|
|
135
135
|
/* @__PURE__ */ jsx2("span", { className: "cfi-sh-app-grid-label", children: app.name })
|
|
136
136
|
]
|
|
137
137
|
},
|
|
@@ -153,7 +153,7 @@ function NotificationBell({ count = 0, onClick }) {
|
|
|
153
153
|
// src/UserMenu.tsx
|
|
154
154
|
import { useState as useState2, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
155
155
|
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
156
|
-
function UserMenu({ user, onLogout }) {
|
|
156
|
+
function UserMenu({ user, onLogout, color }) {
|
|
157
157
|
const [open, setOpen] = useState2(false);
|
|
158
158
|
const ref = useRef2(null);
|
|
159
159
|
useEffect2(() => {
|
|
@@ -171,6 +171,7 @@ function UserMenu({ user, onLogout }) {
|
|
|
171
171
|
"button",
|
|
172
172
|
{
|
|
173
173
|
className: "cfi-sh-avatar-btn",
|
|
174
|
+
style: color ? { background: color } : void 0,
|
|
174
175
|
onClick: () => setOpen(!open),
|
|
175
176
|
"aria-expanded": open,
|
|
176
177
|
"aria-haspopup": "true",
|
|
@@ -210,13 +211,15 @@ function ShellHeader({
|
|
|
210
211
|
notificationCount,
|
|
211
212
|
onNotificationClick,
|
|
212
213
|
onLogout,
|
|
214
|
+
brandWidth,
|
|
213
215
|
children
|
|
214
216
|
}) {
|
|
215
217
|
const currentApp = appCatalog.find((a) => a.id === appId);
|
|
218
|
+
const brandStyle = brandWidth ? { width: `${brandWidth}px`, flexShrink: 0, boxSizing: "border-box" } : void 0;
|
|
216
219
|
return /* @__PURE__ */ jsxs5("header", { className: "cfi-sh-header", children: [
|
|
217
220
|
/* @__PURE__ */ jsxs5("div", { className: "cfi-sh-left", children: [
|
|
218
|
-
/* @__PURE__ */ jsxs5("div", { className: "cfi-sh-app-brand", children: [
|
|
219
|
-
currentApp && /* @__PURE__ */ jsx5("span", { className: "cfi-sh-app-badge", children: currentApp.letter }),
|
|
221
|
+
/* @__PURE__ */ jsxs5("div", { className: "cfi-sh-app-brand", style: brandStyle, children: [
|
|
222
|
+
currentApp && /* @__PURE__ */ jsx5("span", { className: "cfi-sh-app-badge", style: { background: currentApp.color }, children: currentApp.letter }),
|
|
220
223
|
/* @__PURE__ */ jsx5("span", { className: "cfi-sh-app-title", children: currentApp?.name || appId })
|
|
221
224
|
] }),
|
|
222
225
|
children
|
|
@@ -224,7 +227,7 @@ function ShellHeader({
|
|
|
224
227
|
/* @__PURE__ */ jsxs5("div", { className: "cfi-sh-right", children: [
|
|
225
228
|
/* @__PURE__ */ jsx5(NotificationBell, { count: notificationCount, onClick: onNotificationClick }),
|
|
226
229
|
/* @__PURE__ */ jsx5(AppSwitcher, { currentAppId: appId, authorizedApps }),
|
|
227
|
-
/* @__PURE__ */ jsx5(UserMenu, { user, onLogout })
|
|
230
|
+
/* @__PURE__ */ jsx5(UserMenu, { user, onLogout, color: currentApp?.color })
|
|
228
231
|
] })
|
|
229
232
|
] });
|
|
230
233
|
}
|