@sparkstudio/common-ui 1.0.22 → 1.0.23
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 +5 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +20 -24
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -117,7 +117,7 @@ function Body({ icon, title, description, children }) {
|
|
|
117
117
|
var import_react = require("react");
|
|
118
118
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
119
119
|
function Button({
|
|
120
|
-
buttonClassName = "btn btn-primary
|
|
120
|
+
buttonClassName = "btn btn-primary",
|
|
121
121
|
type = "button",
|
|
122
122
|
disabled = false,
|
|
123
123
|
variant,
|
|
@@ -281,19 +281,15 @@ function NavigationItem({ icon, title, type, active, onClick }) {
|
|
|
281
281
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
282
282
|
var NavToggleButton = ({
|
|
283
283
|
onClick,
|
|
284
|
-
|
|
285
|
-
color = "secondary"
|
|
284
|
+
color = "dark"
|
|
286
285
|
}) => {
|
|
287
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "
|
|
286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "ms-auto pe-2 d-md-none", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
288
287
|
Button,
|
|
289
288
|
{
|
|
290
289
|
variant: color,
|
|
291
290
|
buttonClassName: "btn btn-secondary",
|
|
292
291
|
onClick: () => onClick(),
|
|
293
|
-
children:
|
|
294
|
-
"\u2630 ",
|
|
295
|
-
label
|
|
296
|
-
]
|
|
292
|
+
children: "\u2630"
|
|
297
293
|
}
|
|
298
294
|
) });
|
|
299
295
|
};
|
|
@@ -416,7 +412,7 @@ var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
|
416
412
|
var AppsView = ({ apps, title, onAppClick }) => {
|
|
417
413
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
418
414
|
title && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h5", { className: "mb-3", children: title }),
|
|
419
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "row", children: apps.map((app) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AppTile, { app, onClick: onAppClick }, app.id)) })
|
|
415
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "row justify-content-center justify-content-md-start", children: apps.map((app) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(AppTile, { app, onClick: onAppClick }, app.id)) })
|
|
420
416
|
] });
|
|
421
417
|
};
|
|
422
418
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/components/Alert.tsx","../src/components/AppTile.tsx","../src/components/Body.tsx","../src/components/Button.tsx","../src/components/Footer.tsx","../src/components/Header.tsx","../src/components/HeaderText.tsx","../src/components/Icon.tsx","../src/components/NpmBadge.tsx","../src/components/navigation/Navigation.tsx","../src/components/navigation/NavigationItem.tsx","../src/components/navigation/NavToggleButton.tsx","../src/components/notifications/Notifications.tsx","../src/components/notifications/NotificationsProvider.tsx","../src/components/views/AppsView.tsx","../src/components/wrappers/ContentContainer.tsx","../src/components/wrappers/ContentRow.tsx","../src/components/wrappers/LayoutWrapper.tsx","../src/modal/Modal.tsx","../src/modal/ModalProvider.tsx"],"sourcesContent":["/**\n * @file Automatically generated by barrelsby.\n */\n\nexport * from \"./components/Alert\";\nexport * from \"./components/AppTile\";\nexport * from \"./components/Body\";\nexport * from \"./components/Button\";\nexport * from \"./components/Footer\";\nexport * from \"./components/Header\";\nexport * from \"./components/HeaderText\";\nexport * from \"./components/Icon\";\nexport * from \"./components/NpmBadge\";\nexport * from \"./components/navigation/Navigation\";\nexport * from \"./components/navigation/NavigationItem\";\nexport * from \"./components/navigation/NavToggleButton\";\nexport * from \"./components/notifications/Notifications\";\nexport * from \"./components/notifications/NotificationsProvider\";\nexport * from \"./components/views/AppsView\";\nexport * from \"./components/wrappers/ContentContainer\";\nexport * from \"./components/wrappers/ContentRow\";\nexport * from \"./components/wrappers/LayoutWrapper\";\nexport * from \"./modal/Modal\";\nexport * from \"./modal/ModalProvider\";\nexport * from \"./models/AppItem\";\n","// components/Alert.tsx\r\nimport React from \"react\";\r\n\r\nexport type AlertVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\";\r\n\r\ninterface AlertProps {\r\n variant?: AlertVariant;\r\n title?: string;\r\n dismissible?: boolean;\r\n className?: string;\r\n children: React.ReactNode;\r\n onClose?: () => void;\r\n}\r\n\r\nexport const Alert: React.FC<AlertProps> = ({\r\n variant = \"info\",\r\n title,\r\n dismissible = false,\r\n className = \"\",\r\n children,\r\n onClose,\r\n}) => {\r\n const classes = [\r\n \"alert\",\r\n `alert-${variant}`,\r\n dismissible ? \"alert-dismissible fade show\" : \"\",\r\n className,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \");\r\n\r\n return (\r\n <div role=\"alert\" className={classes}>\r\n {title && <strong className=\"d-block mb-1\">{title}</strong>}\r\n {children}\r\n\r\n {dismissible && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport type { AppItem } from \"../models/AppItem\";\r\n\r\ninterface AppTileProps {\r\n app: AppItem;\r\n onClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppTile: React.FC<AppTileProps> = ({ app, onClick }) => {\r\n return (\r\n <div className=\"col-auto\">\r\n <button\r\n type=\"button\"\r\n className=\"btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn\"\r\n onClick={() => onClick?.(app)}\r\n >\r\n <div className=\"app-icon-tile d-flex align-items-center justify-content-center mb-1\">\r\n <span style={{fontSize:\"32px\"}}>{app.icon}</span>\r\n </div>\r\n\r\n <span className=\"w-100 small text-truncate\">\r\n {app.name}\r\n {app.version && <small className=\"text-muted ms-1\">v{app.version}</small>}\r\n </span>\r\n </button>\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface BodyProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n description?: ReactNode;\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Body({ icon, title, description, children }: BodyProps) {\r\n return (\r\n\r\n <main className=\"col p-4\">\r\n <h2>{icon} {title}</h2>\r\n\r\n {description && <p>{description}</p>}\r\n {children}\r\n </main>\r\n );\r\n}\r\n","import { useState, type ReactNode, type MouseEvent } from \"react\";\r\n\r\nexport type ButtonVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\"\r\n | \"link\";\r\n\r\nexport interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\r\n\r\n variant?: ButtonVariant; // 👈 NEW — Bootstrap color support\r\n\r\n onAction?: () => Promise<unknown>;\r\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\r\n onDone?: (result: unknown) => void;\r\n onError?: (error: unknown) => void;\r\n onFinally?: () => void;\r\n\r\n children?: ReactNode;\r\n loadingChildren?: ReactNode;\r\n\r\n renderContent?: () => ReactNode;\r\n renderLoading?: () => ReactNode;\r\n\r\n loadingText?: string;\r\n showSpinner?: boolean;\r\n}\r\n\r\nexport function Button({\r\n buttonClassName = \"btn btn-primary btn-lg\",\r\n type = \"button\",\r\n disabled = false,\r\n\r\n variant,\r\n\r\n onAction,\r\n onClick,\r\n onDone,\r\n onError,\r\n onFinally,\r\n\r\n children = \"Click me\",\r\n\r\n loadingChildren,\r\n renderContent,\r\n renderLoading,\r\n\r\n loadingText = \"Loading...\",\r\n showSpinner = true,\r\n}: ButtonProps) {\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleClick = async (event: MouseEvent<HTMLButtonElement>) => {\r\n if (loading) return;\r\n\r\n onClick?.(event);\r\n if (event.defaultPrevented) return;\r\n if (!onAction) return;\r\n\r\n try {\r\n setLoading(true);\r\n const result = await onAction();\r\n onDone?.(result);\r\n } catch (error) {\r\n onError?.(error);\r\n } finally {\r\n setLoading(false);\r\n onFinally?.();\r\n }\r\n };\r\n\r\n // 👇 Decide which CSS to use:\r\n // - if variant is provided, use Bootstrap \"btn btn-X\"\r\n // - otherwise fall back to user-supplied buttonClassName\r\n const baseClass = variant\r\n ? `btn btn-${variant}`\r\n : buttonClassName;\r\n\r\n return (\r\n <button\r\n type={type}\r\n className={`${baseClass} ${loading ? \"async-btn--loading\" : \"\"}`}\r\n onClick={handleClick}\r\n disabled={disabled || loading}\r\n >\r\n {loading ? (\r\n renderLoading?.() ??\r\n loadingChildren ?? (\r\n <>\r\n {showSpinner && (\r\n <span\r\n className=\"spinner-border spinner-border-sm me-2 async-btn__spinner\"\r\n role=\"status\"\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n {loadingText}\r\n </>\r\n )\r\n ) : (\r\n renderContent?.() ?? children\r\n )}\r\n </button>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface FooterProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Footer({ children }: FooterProps) {\r\n return (\r\n <footer className=\"bg-dark text-white text-center py-2 mt-auto\">\r\n {children ?? \"© 2025 Your Site — All rights reserved\"}\r\n </footer>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Header({ children }: HeaderProps) {\r\n return (\r\n <nav className=\"navbar navbar-dark bg-dark px-3 sticky-top\">\r\n {children ?? (\r\n <span className=\"navbar-brand mb-0 h4\">My Website</span>\r\n )}\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderBrandProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function HeaderText({ children }: HeaderBrandProps) {\r\n return (\r\n <span className=\"navbar-brand mb-0 h4\">\r\n {children}\r\n </span>\r\n );\r\n}\r\n","// ImageCard.tsx\r\nimport React from \"react\";\r\n\r\ninterface ImageCardProps {\r\n src: string;\r\n alt: string;\r\n width?: string | number;\r\n height?: string | number;\r\n}\r\n\r\nexport const ImageCard: React.FC<ImageCardProps> = ({\r\n src,\r\n alt,\r\n}) => {\r\n return (\r\n <img\r\n src={src}\r\n alt={alt}\r\n className={\"w-100\"}\r\n style={{\r\n display: \"block\",\r\n objectFit: \"cover\",\r\n }}\r\n />\r\n );\r\n};\r\n","// components/NpmBadge.tsx\r\ninterface NpmBadgeProps {\r\n packageLabel: string;\r\n packageName: string;\r\n packageUrl: string; // e.g. \"@sparkstudio/authentication-ui\"\r\n color?: string; // optional (default black)\r\n height?: number; // optional (default 22)\r\n}\r\n\r\nexport function NpmBadge({ packageName, packageLabel, packageUrl, color = \"black\", height = 22 }: NpmBadgeProps) {\r\n const encodedLabel = encodeURIComponent(packageLabel);\r\n const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;\r\n const npmUrl = packageUrl;\r\n\r\n return (\r\n <a href={npmUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n <img src={badgeUrl} alt={`${packageName} version`} style={{ height }} />\r\n </a>\r\n );\r\n}\r\n","// components/Navigation.tsx\r\nimport type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n}\r\n\r\nexport function Navigation({\r\n title = \"Navigation\",\r\n children,\r\n isOpen,\r\n onClose,\r\n}: NavigationProps) {\r\n return (\r\n <>\r\n {/* Desktop sidebar */}\r\n <nav className=\"col-auto p-3 h-100 d-none d-md-flex flex-column\">\r\n <h6 className=\"text-muted text-uppercase\">{title}</h6>\r\n\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-3\">\r\n {children}\r\n </ul>\r\n </nav>\r\n\r\n {/* Mobile drawer */}\r\n <div\r\n className={`offcanvas offcanvas-start d-md-none ${isOpen ? \"show\" : \"\"}`}\r\n style={{ visibility: isOpen ? \"visible\" : \"hidden\" }}\r\n tabIndex={-1}\r\n aria-hidden={isOpen ? \"false\" : \"true\"}\r\n >\r\n <div className=\"offcanvas-header\">\r\n <h5 className=\"offcanvas-title\">{title}</h5>\r\n <button className=\"btn-close\" onClick={onClose} />\r\n </div>\r\n\r\n <div className=\"offcanvas-body\">\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-2\">\r\n {children}\r\n </ul>\r\n </div>\r\n </div>\r\n\r\n {/* Backdrop */}\r\n {isOpen && (\r\n <div\r\n className=\"offcanvas-backdrop fade show d-md-none\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationItemProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n type: string;\r\n active?: boolean;\r\n onClick?: (type: string) => void;\r\n}\r\n\r\nexport function NavigationItem({icon, title, type, active, onClick }: NavigationItemProps) {\r\n return (\r\n <li className=\"nav-item\">\r\n <button\r\n type=\"button\"\r\n className={`nav-link text-start w-100 ${active ? \"active\" : \"\"}`}\r\n onClick={() => onClick?.(type)}\r\n >\r\n {icon} {title}\r\n </button>\r\n </li>\r\n );\r\n}\r\n","// components/NavToggleButton.tsx\r\nimport React from \"react\";\r\nimport { Button } from \"../Button\";\r\n\r\ninterface NavToggleButtonProps {\r\n onClick: () => void;\r\n label?: string;\r\n color?: \"primary\" | \"secondary\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"light\" | \"dark\";\r\n}\r\n\r\nexport const NavToggleButton: React.FC<NavToggleButtonProps> = ({\r\n onClick,\r\n label = \"Menu\",\r\n color = \"secondary\",\r\n}) => {\r\n return (\r\n <div className=\"d-md-none position-absolute top-0 end-0 m-2\">\r\n <Button\r\n variant={color}\r\n buttonClassName=\"btn btn-secondary\"\r\n onClick={() => onClick()}\r\n >\r\n ☰ {label}\r\n </Button>\r\n </div>\r\n );\r\n};\r\n","import { useEffect } from \"react\";\r\n\r\nexport type NotificationType = \"success\" | \"info\" | \"warning\" | \"danger\";\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsProps {\r\n notifications: Notification[];\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Notifications({ notifications, onClose }: NotificationsProps) {\r\n useEffect(() => {\r\n notifications.forEach((n) => {\r\n if (!n.autoCloseMs) return;\r\n\r\n const timer = setTimeout(() => onClose(n.id), n.autoCloseMs);\r\n return () => clearTimeout(timer);\r\n });\r\n }, [notifications, onClose]);\r\n\r\n return (\r\n <div\r\n className=\"position-fixed top-0 end-0\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => onClose(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport type { NotificationType } from \"./Notifications\";\r\n\r\n// Rename to avoid conflict with browser Notification type\r\nexport interface AppNotification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsContextValue {\r\n push: (message: string, type?: NotificationType, autoCloseMs?: number) => void;\r\n}\r\n\r\nconst NotificationsContext = createContext<NotificationsContextValue | undefined>(\r\n undefined\r\n);\r\n\r\ninterface NotificationsProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function NotificationsProvider({ children }: NotificationsProviderProps) {\r\n const [notifications, setNotifications] = useState<AppNotification[]>([]);\r\n\r\n const push = useCallback(\r\n (message: string, type: NotificationType = \"info\", autoCloseMs = 4000) => {\r\n setNotifications((prev) => [\r\n ...prev,\r\n {\r\n id: crypto.randomUUID(),\r\n message,\r\n type,\r\n autoCloseMs,\r\n },\r\n ]);\r\n },\r\n []\r\n );\r\n\r\n const close = useCallback((id: string) => {\r\n setNotifications((list) => list.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n // Handle auto close timers\r\n useEffect(() => {\r\n const timers = notifications.map((n) => {\r\n if (!n.autoCloseMs) return null;\r\n return setTimeout(() => close(n.id), n.autoCloseMs);\r\n });\r\n\r\n return () => {\r\n timers.forEach((t) => t && clearTimeout(t));\r\n };\r\n }, [notifications, close]);\r\n\r\n return (\r\n <NotificationsContext.Provider value={{ push }}>\r\n {/* overlay renderer */}\r\n <div\r\n className=\"position-fixed top-0 end-0 p-3\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => close(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {children}\r\n </NotificationsContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseNotifications(): NotificationsContextValue {\r\n const ctx = useContext(NotificationsContext);\r\n if (!ctx) {\r\n throw new Error(\"useNotifications must be used within a NotificationsProvider\");\r\n }\r\n return ctx;\r\n}\r\n","// ./views/AppsView.tsx (or ./components/AppsView.tsx)\r\nimport React from \"react\";\r\nimport type { AppItem } from \"../../models/AppItem\";\r\nimport { AppTile } from \"../AppTile\";\r\n\r\ninterface AppsViewProps {\r\n apps: AppItem[];\r\n title?: string;\r\n onAppClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppsView: React.FC<AppsViewProps> = ({ apps, title, onAppClick }) => {\r\n return (\r\n <>\r\n {title && <h5 className=\"mb-3\">{title}</h5>}\r\n\r\n <div className=\"row\">\r\n {apps.map((app) => (\r\n <AppTile key={app.id} app={app} onClick={onAppClick} />\r\n ))}\r\n </div>\r\n </>\r\n );\r\n};\r\n","export function ContentContainer({ children }: React.PropsWithChildren) {\r\n return <div className=\"container-fluid flex-grow-1\">{children}</div>;\r\n}\r\n","export function ContentRow({ children }: React.PropsWithChildren) {\r\n return <div className=\"row h-100 flex-nowrap\">{children}</div>;\r\n}\r\n","\r\nexport function LayoutWrapper({ children }: React.PropsWithChildren) {\r\n return (\r\n\r\n <div className=\"d-flex flex-column min-vh-100\">{children}</div>\r\n );\r\n}\r\n","// components/Modal.tsx\r\nimport React from \"react\";\r\n\r\nexport interface ModalProps {\r\n title?: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onConfirm?: () => void;\r\n confirmText?: string;\r\n\r\n disableBackdropClose?: boolean;\r\n disableAllButtons?: boolean;\r\n\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport const Modal: React.FC<ModalProps> = ({\r\n title,\r\n isOpen,\r\n onClose,\r\n onConfirm,\r\n confirmText = \"OK\",\r\n\r\n disableBackdropClose = false,\r\n disableAllButtons = false,\r\n\r\n showHeaderClose = true,\r\n showCloseButton = true,\r\n showConfirmButton = true,\r\n\r\n children,\r\n}) => {\r\n if (!isOpen) return null;\r\n\r\n const handleBackdropClick = () => {\r\n if (disableBackdropClose || disableAllButtons) return;\r\n onClose();\r\n };\r\n\r\n const handleContentClick: React.MouseEventHandler<HTMLDivElement> = (e) => {\r\n e.stopPropagation();\r\n };\r\n\r\n // 👇 NEW: decide if footer should exist at all\r\n const hasFooterButtons =\r\n (showCloseButton || (onConfirm && showConfirmButton)) &&\r\n !disableAllButtons;\r\n\r\n return (\r\n <>\r\n <div\r\n className=\"modal-backdrop fade show\"\r\n style={{ zIndex: 1040 }}\r\n onClick={handleBackdropClick}\r\n />\r\n\r\n <div\r\n className=\"modal fade show d-block\"\r\n tabIndex={-1}\r\n role=\"dialog\"\r\n style={{ zIndex: 1050 }}\r\n onClick={handleBackdropClick}\r\n >\r\n <div\r\n className=\"modal-dialog modal-dialog-centered\"\r\n role=\"document\"\r\n onClick={handleContentClick}\r\n >\r\n <div className=\"modal-content shadow\">\r\n {/* Header */}\r\n <div className=\"modal-header\">\r\n {title && <h5 className=\"modal-title\">{title}</h5>}\r\n\r\n {showHeaderClose && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"modal-body\">{children}</div>\r\n\r\n {/* Footer — only if buttons are visible */}\r\n {hasFooterButtons && (\r\n <div className=\"modal-footer\">\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-secondary\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n >\r\n Close\r\n </button>\r\n )}\r\n\r\n {onConfirm && showConfirmButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-primary\"\r\n onClick={onConfirm}\r\n disabled={disableAllButtons}\r\n >\r\n {confirmText}\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { Modal } from \"./Modal\";\r\n\r\nexport interface ModalOptions {\r\n title?: string;\r\n confirmText?: string;\r\n disableBackdropClose?: boolean;\r\n onConfirm?: () => void;\r\n\r\n /** extra control flags matching Modal.tsx */\r\n disableAllButtons?: boolean;\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n}\r\n\r\ninterface ModalContextValue {\r\n openModal: (content: ReactNode, options?: ModalOptions) => void;\r\n closeModal: () => void;\r\n}\r\n\r\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\r\n\r\nexport function ModalProvider({ children }: { children: ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [content, setContent] = useState<ReactNode>(null);\r\n const [options, setOptions] = useState<ModalOptions>({});\r\n\r\n const openModal = useCallback((content: ReactNode, options?: ModalOptions) => {\r\n setContent(content);\r\n setOptions(options ?? {});\r\n setIsOpen(true);\r\n }, []);\r\n\r\n const closeModal = useCallback(() => {\r\n setIsOpen(false);\r\n }, []);\r\n\r\n return (\r\n <ModalContext.Provider value={{ openModal, closeModal }}>\r\n {children}\r\n\r\n <Modal\r\n isOpen={isOpen}\r\n title={options.title}\r\n confirmText={options.confirmText}\r\n disableBackdropClose={options.disableBackdropClose}\r\n disableAllButtons={options.disableAllButtons}\r\n showHeaderClose={options.showHeaderClose}\r\n showCloseButton={options.showCloseButton}\r\n showConfirmButton={options.showConfirmButton}\r\n onClose={closeModal}\r\n onConfirm={options.onConfirm}\r\n >\r\n {content}\r\n </Modal>\r\n </ModalContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseModal() {\r\n const ctx = useContext(ModalContext);\r\n if (!ctx) throw new Error(\"UseModal must be used within ModalProvider\");\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","content","options"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/components/Alert.tsx","../src/components/AppTile.tsx","../src/components/Body.tsx","../src/components/Button.tsx","../src/components/Footer.tsx","../src/components/Header.tsx","../src/components/HeaderText.tsx","../src/components/Icon.tsx","../src/components/NpmBadge.tsx","../src/components/navigation/Navigation.tsx","../src/components/navigation/NavigationItem.tsx","../src/components/navigation/NavToggleButton.tsx","../src/components/notifications/Notifications.tsx","../src/components/notifications/NotificationsProvider.tsx","../src/components/views/AppsView.tsx","../src/components/wrappers/ContentContainer.tsx","../src/components/wrappers/ContentRow.tsx","../src/components/wrappers/LayoutWrapper.tsx","../src/modal/Modal.tsx","../src/modal/ModalProvider.tsx"],"sourcesContent":["/**\n * @file Automatically generated by barrelsby.\n */\n\nexport * from \"./components/Alert\";\nexport * from \"./components/AppTile\";\nexport * from \"./components/Body\";\nexport * from \"./components/Button\";\nexport * from \"./components/Footer\";\nexport * from \"./components/Header\";\nexport * from \"./components/HeaderText\";\nexport * from \"./components/Icon\";\nexport * from \"./components/NpmBadge\";\nexport * from \"./components/navigation/Navigation\";\nexport * from \"./components/navigation/NavigationItem\";\nexport * from \"./components/navigation/NavToggleButton\";\nexport * from \"./components/notifications/Notifications\";\nexport * from \"./components/notifications/NotificationsProvider\";\nexport * from \"./components/views/AppsView\";\nexport * from \"./components/wrappers/ContentContainer\";\nexport * from \"./components/wrappers/ContentRow\";\nexport * from \"./components/wrappers/LayoutWrapper\";\nexport * from \"./modal/Modal\";\nexport * from \"./modal/ModalProvider\";\nexport * from \"./models/AppItem\";\n","// components/Alert.tsx\r\nimport React from \"react\";\r\n\r\nexport type AlertVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\";\r\n\r\ninterface AlertProps {\r\n variant?: AlertVariant;\r\n title?: string;\r\n dismissible?: boolean;\r\n className?: string;\r\n children: React.ReactNode;\r\n onClose?: () => void;\r\n}\r\n\r\nexport const Alert: React.FC<AlertProps> = ({\r\n variant = \"info\",\r\n title,\r\n dismissible = false,\r\n className = \"\",\r\n children,\r\n onClose,\r\n}) => {\r\n const classes = [\r\n \"alert\",\r\n `alert-${variant}`,\r\n dismissible ? \"alert-dismissible fade show\" : \"\",\r\n className,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \");\r\n\r\n return (\r\n <div role=\"alert\" className={classes}>\r\n {title && <strong className=\"d-block mb-1\">{title}</strong>}\r\n {children}\r\n\r\n {dismissible && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport type { AppItem } from \"../models/AppItem\";\r\n\r\ninterface AppTileProps {\r\n app: AppItem;\r\n onClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppTile: React.FC<AppTileProps> = ({ app, onClick }) => {\r\n return (\r\n <div className=\"col-auto\">\r\n <button\r\n type=\"button\"\r\n className=\"btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn\"\r\n onClick={() => onClick?.(app)}\r\n >\r\n <div className=\"app-icon-tile d-flex align-items-center justify-content-center mb-1\">\r\n <span style={{fontSize:\"32px\"}}>{app.icon}</span>\r\n </div>\r\n\r\n <span className=\"w-100 small text-truncate\">\r\n {app.name}\r\n {app.version && <small className=\"text-muted ms-1\">v{app.version}</small>}\r\n </span>\r\n </button>\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface BodyProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n description?: ReactNode;\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Body({ icon, title, description, children }: BodyProps) {\r\n return (\r\n\r\n <main className=\"col p-4\">\r\n <h2>{icon} {title}</h2>\r\n\r\n {description && <p>{description}</p>}\r\n {children}\r\n </main>\r\n );\r\n}\r\n","import { useState, type ReactNode, type MouseEvent } from \"react\";\r\n\r\nexport type ButtonVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\"\r\n | \"link\";\r\n\r\nexport interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\r\n\r\n variant?: ButtonVariant; // 👈 NEW — Bootstrap color support\r\n\r\n onAction?: () => Promise<unknown>;\r\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\r\n onDone?: (result: unknown) => void;\r\n onError?: (error: unknown) => void;\r\n onFinally?: () => void;\r\n\r\n children?: ReactNode;\r\n loadingChildren?: ReactNode;\r\n\r\n renderContent?: () => ReactNode;\r\n renderLoading?: () => ReactNode;\r\n\r\n loadingText?: string;\r\n showSpinner?: boolean;\r\n}\r\n\r\nexport function Button({\r\n buttonClassName = \"btn btn-primary\",\r\n type = \"button\",\r\n disabled = false,\r\n\r\n variant,\r\n\r\n onAction,\r\n onClick,\r\n onDone,\r\n onError,\r\n onFinally,\r\n\r\n children = \"Click me\",\r\n\r\n loadingChildren,\r\n renderContent,\r\n renderLoading,\r\n\r\n loadingText = \"Loading...\",\r\n showSpinner = true,\r\n}: ButtonProps) {\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleClick = async (event: MouseEvent<HTMLButtonElement>) => {\r\n if (loading) return;\r\n\r\n onClick?.(event);\r\n if (event.defaultPrevented) return;\r\n if (!onAction) return;\r\n\r\n try {\r\n setLoading(true);\r\n const result = await onAction();\r\n onDone?.(result);\r\n } catch (error) {\r\n onError?.(error);\r\n } finally {\r\n setLoading(false);\r\n onFinally?.();\r\n }\r\n };\r\n\r\n // 👇 Decide which CSS to use:\r\n // - if variant is provided, use Bootstrap \"btn btn-X\"\r\n // - otherwise fall back to user-supplied buttonClassName\r\n const baseClass = variant\r\n ? `btn btn-${variant}`\r\n : buttonClassName;\r\n\r\n return (\r\n <button\r\n type={type}\r\n className={`${baseClass} ${loading ? \"async-btn--loading\" : \"\"}`}\r\n onClick={handleClick}\r\n disabled={disabled || loading}\r\n >\r\n {loading ? (\r\n renderLoading?.() ??\r\n loadingChildren ?? (\r\n <>\r\n {showSpinner && (\r\n <span\r\n className=\"spinner-border spinner-border-sm me-2 async-btn__spinner\"\r\n role=\"status\"\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n {loadingText}\r\n </>\r\n )\r\n ) : (\r\n renderContent?.() ?? children\r\n )}\r\n </button>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface FooterProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Footer({ children }: FooterProps) {\r\n return (\r\n <footer className=\"bg-dark text-white text-center py-2 mt-auto\">\r\n {children ?? \"© 2025 Your Site — All rights reserved\"}\r\n </footer>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Header({ children }: HeaderProps) {\r\n return (\r\n <nav className=\"navbar navbar-dark bg-dark px-3 sticky-top\">\r\n {children ?? (\r\n <span className=\"navbar-brand mb-0 h4\">My Website</span>\r\n )}\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderBrandProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function HeaderText({ children }: HeaderBrandProps) {\r\n return (\r\n <span className=\"navbar-brand mb-0 h4\">\r\n {children}\r\n </span>\r\n );\r\n}\r\n","// ImageCard.tsx\r\nimport React from \"react\";\r\n\r\ninterface ImageCardProps {\r\n src: string;\r\n alt: string;\r\n width?: string | number;\r\n height?: string | number;\r\n}\r\n\r\nexport const ImageCard: React.FC<ImageCardProps> = ({\r\n src,\r\n alt,\r\n}) => {\r\n return (\r\n <img\r\n src={src}\r\n alt={alt}\r\n className={\"w-100\"}\r\n style={{\r\n display: \"block\",\r\n objectFit: \"cover\",\r\n }}\r\n />\r\n );\r\n};\r\n","// components/NpmBadge.tsx\r\ninterface NpmBadgeProps {\r\n packageLabel: string;\r\n packageName: string;\r\n packageUrl: string; // e.g. \"@sparkstudio/authentication-ui\"\r\n color?: string; // optional (default black)\r\n height?: number; // optional (default 22)\r\n}\r\n\r\nexport function NpmBadge({ packageName, packageLabel, packageUrl, color = \"black\", height = 22 }: NpmBadgeProps) {\r\n const encodedLabel = encodeURIComponent(packageLabel);\r\n const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;\r\n const npmUrl = packageUrl;\r\n\r\n return (\r\n <a href={npmUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n <img src={badgeUrl} alt={`${packageName} version`} style={{ height }} />\r\n </a>\r\n );\r\n}\r\n","// components/Navigation.tsx\r\nimport type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n}\r\n\r\nexport function Navigation({\r\n title = \"Navigation\",\r\n children,\r\n isOpen,\r\n onClose,\r\n}: NavigationProps) {\r\n return (\r\n <>\r\n {/* Desktop sidebar */}\r\n <nav className=\"col-auto p-3 h-100 d-none d-md-flex flex-column\">\r\n <h6 className=\"text-muted text-uppercase\">{title}</h6>\r\n\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-3\">\r\n {children}\r\n </ul>\r\n </nav>\r\n\r\n {/* Mobile drawer */}\r\n <div\r\n className={`offcanvas offcanvas-start d-md-none ${isOpen ? \"show\" : \"\"}`}\r\n style={{ visibility: isOpen ? \"visible\" : \"hidden\" }}\r\n tabIndex={-1}\r\n aria-hidden={isOpen ? \"false\" : \"true\"}\r\n >\r\n <div className=\"offcanvas-header\">\r\n <h5 className=\"offcanvas-title\">{title}</h5>\r\n <button className=\"btn-close\" onClick={onClose} />\r\n </div>\r\n\r\n <div className=\"offcanvas-body\">\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-2\">\r\n {children}\r\n </ul>\r\n </div>\r\n </div>\r\n\r\n {/* Backdrop */}\r\n {isOpen && (\r\n <div\r\n className=\"offcanvas-backdrop fade show d-md-none\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationItemProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n type: string;\r\n active?: boolean;\r\n onClick?: (type: string) => void;\r\n}\r\n\r\nexport function NavigationItem({icon, title, type, active, onClick }: NavigationItemProps) {\r\n return (\r\n <li className=\"nav-item\">\r\n <button\r\n type=\"button\"\r\n className={`nav-link text-start w-100 ${active ? \"active\" : \"\"}`}\r\n onClick={() => onClick?.(type)}\r\n >\r\n {icon} {title}\r\n </button>\r\n </li>\r\n );\r\n}\r\n","// components/NavToggleButton.tsx\r\nimport React from \"react\";\r\nimport { Button } from \"../Button\";\r\n\r\ninterface NavToggleButtonProps {\r\n onClick: () => void;\r\n label?: string;\r\n color?: \"primary\" | \"secondary\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"light\" | \"dark\";\r\n}\r\n\r\nexport const NavToggleButton: React.FC<NavToggleButtonProps> = ({\r\n onClick,\r\n color = \"dark\",\r\n}) => {\r\n return (\r\n <div className=\"ms-auto pe-2 d-md-none\">\r\n <Button\r\n variant={color}\r\n buttonClassName=\"btn btn-secondary\"\r\n onClick={() => onClick()}\r\n >\r\n ☰\r\n </Button>\r\n </div>\r\n );\r\n};\r\n","import { useEffect } from \"react\";\r\n\r\nexport type NotificationType = \"success\" | \"info\" | \"warning\" | \"danger\";\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsProps {\r\n notifications: Notification[];\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Notifications({ notifications, onClose }: NotificationsProps) {\r\n useEffect(() => {\r\n notifications.forEach((n) => {\r\n if (!n.autoCloseMs) return;\r\n\r\n const timer = setTimeout(() => onClose(n.id), n.autoCloseMs);\r\n return () => clearTimeout(timer);\r\n });\r\n }, [notifications, onClose]);\r\n\r\n return (\r\n <div\r\n className=\"position-fixed top-0 end-0\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => onClose(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport type { NotificationType } from \"./Notifications\";\r\n\r\n// Rename to avoid conflict with browser Notification type\r\nexport interface AppNotification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsContextValue {\r\n push: (message: string, type?: NotificationType, autoCloseMs?: number) => void;\r\n}\r\n\r\nconst NotificationsContext = createContext<NotificationsContextValue | undefined>(\r\n undefined\r\n);\r\n\r\ninterface NotificationsProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function NotificationsProvider({ children }: NotificationsProviderProps) {\r\n const [notifications, setNotifications] = useState<AppNotification[]>([]);\r\n\r\n const push = useCallback(\r\n (message: string, type: NotificationType = \"info\", autoCloseMs = 4000) => {\r\n setNotifications((prev) => [\r\n ...prev,\r\n {\r\n id: crypto.randomUUID(),\r\n message,\r\n type,\r\n autoCloseMs,\r\n },\r\n ]);\r\n },\r\n []\r\n );\r\n\r\n const close = useCallback((id: string) => {\r\n setNotifications((list) => list.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n // Handle auto close timers\r\n useEffect(() => {\r\n const timers = notifications.map((n) => {\r\n if (!n.autoCloseMs) return null;\r\n return setTimeout(() => close(n.id), n.autoCloseMs);\r\n });\r\n\r\n return () => {\r\n timers.forEach((t) => t && clearTimeout(t));\r\n };\r\n }, [notifications, close]);\r\n\r\n return (\r\n <NotificationsContext.Provider value={{ push }}>\r\n {/* overlay renderer */}\r\n <div\r\n className=\"position-fixed top-0 end-0 p-3\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => close(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {children}\r\n </NotificationsContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseNotifications(): NotificationsContextValue {\r\n const ctx = useContext(NotificationsContext);\r\n if (!ctx) {\r\n throw new Error(\"useNotifications must be used within a NotificationsProvider\");\r\n }\r\n return ctx;\r\n}\r\n","// ./views/AppsView.tsx (or ./components/AppsView.tsx)\r\nimport React from \"react\";\r\nimport type { AppItem } from \"../../models/AppItem\";\r\nimport { AppTile } from \"../AppTile\";\r\n\r\ninterface AppsViewProps {\r\n apps: AppItem[];\r\n title?: string;\r\n onAppClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppsView: React.FC<AppsViewProps> = ({ apps, title, onAppClick }) => {\r\n return (\r\n <>\r\n {title && <h5 className=\"mb-3\">{title}</h5>}\r\n\r\n <div className=\"row justify-content-center justify-content-md-start\">\r\n {apps.map((app) => (\r\n <AppTile key={app.id} app={app} onClick={onAppClick} />\r\n ))}\r\n </div>\r\n </>\r\n );\r\n};\r\n","export function ContentContainer({ children }: React.PropsWithChildren) {\r\n return <div className=\"container-fluid flex-grow-1\">{children}</div>;\r\n}\r\n","export function ContentRow({ children }: React.PropsWithChildren) {\r\n return <div className=\"row h-100 flex-nowrap\">{children}</div>;\r\n}\r\n","\r\nexport function LayoutWrapper({ children }: React.PropsWithChildren) {\r\n return (\r\n\r\n <div className=\"d-flex flex-column min-vh-100\">{children}</div>\r\n );\r\n}\r\n","// components/Modal.tsx\r\nimport React from \"react\";\r\n\r\nexport interface ModalProps {\r\n title?: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onConfirm?: () => void;\r\n confirmText?: string;\r\n\r\n disableBackdropClose?: boolean;\r\n disableAllButtons?: boolean;\r\n\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport const Modal: React.FC<ModalProps> = ({\r\n title,\r\n isOpen,\r\n onClose,\r\n onConfirm,\r\n confirmText = \"OK\",\r\n\r\n disableBackdropClose = false,\r\n disableAllButtons = false,\r\n\r\n showHeaderClose = true,\r\n showCloseButton = true,\r\n showConfirmButton = true,\r\n\r\n children,\r\n}) => {\r\n if (!isOpen) return null;\r\n\r\n const handleBackdropClick = () => {\r\n if (disableBackdropClose || disableAllButtons) return;\r\n onClose();\r\n };\r\n\r\n const handleContentClick: React.MouseEventHandler<HTMLDivElement> = (e) => {\r\n e.stopPropagation();\r\n };\r\n\r\n // 👇 NEW: decide if footer should exist at all\r\n const hasFooterButtons =\r\n (showCloseButton || (onConfirm && showConfirmButton)) &&\r\n !disableAllButtons;\r\n\r\n return (\r\n <>\r\n <div\r\n className=\"modal-backdrop fade show\"\r\n style={{ zIndex: 1040 }}\r\n onClick={handleBackdropClick}\r\n />\r\n\r\n <div\r\n className=\"modal fade show d-block\"\r\n tabIndex={-1}\r\n role=\"dialog\"\r\n style={{ zIndex: 1050 }}\r\n onClick={handleBackdropClick}\r\n >\r\n <div\r\n className=\"modal-dialog modal-dialog-centered\"\r\n role=\"document\"\r\n onClick={handleContentClick}\r\n >\r\n <div className=\"modal-content shadow\">\r\n {/* Header */}\r\n <div className=\"modal-header\">\r\n {title && <h5 className=\"modal-title\">{title}</h5>}\r\n\r\n {showHeaderClose && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"modal-body\">{children}</div>\r\n\r\n {/* Footer — only if buttons are visible */}\r\n {hasFooterButtons && (\r\n <div className=\"modal-footer\">\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-secondary\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n >\r\n Close\r\n </button>\r\n )}\r\n\r\n {onConfirm && showConfirmButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-primary\"\r\n onClick={onConfirm}\r\n disabled={disableAllButtons}\r\n >\r\n {confirmText}\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { Modal } from \"./Modal\";\r\n\r\nexport interface ModalOptions {\r\n title?: string;\r\n confirmText?: string;\r\n disableBackdropClose?: boolean;\r\n onConfirm?: () => void;\r\n\r\n /** extra control flags matching Modal.tsx */\r\n disableAllButtons?: boolean;\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n}\r\n\r\ninterface ModalContextValue {\r\n openModal: (content: ReactNode, options?: ModalOptions) => void;\r\n closeModal: () => void;\r\n}\r\n\r\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\r\n\r\nexport function ModalProvider({ children }: { children: ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [content, setContent] = useState<ReactNode>(null);\r\n const [options, setOptions] = useState<ModalOptions>({});\r\n\r\n const openModal = useCallback((content: ReactNode, options?: ModalOptions) => {\r\n setContent(content);\r\n setOptions(options ?? {});\r\n setIsOpen(true);\r\n }, []);\r\n\r\n const closeModal = useCallback(() => {\r\n setIsOpen(false);\r\n }, []);\r\n\r\n return (\r\n <ModalContext.Provider value={{ openModal, closeModal }}>\r\n {children}\r\n\r\n <Modal\r\n isOpen={isOpen}\r\n title={options.title}\r\n confirmText={options.confirmText}\r\n disableBackdropClose={options.disableBackdropClose}\r\n disableAllButtons={options.disableAllButtons}\r\n showHeaderClose={options.showHeaderClose}\r\n showCloseButton={options.showCloseButton}\r\n showConfirmButton={options.showConfirmButton}\r\n onClose={closeModal}\r\n onConfirm={options.onConfirm}\r\n >\r\n {content}\r\n </Modal>\r\n </ModalContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseModal() {\r\n const ctx = useContext(ModalContext);\r\n if (!ctx) throw new Error(\"UseModal must be used within ModalProvider\");\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","import_react","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_react","import_jsx_runtime","content","options"]}
|
package/dist/index.js
CHANGED
|
@@ -70,7 +70,7 @@ function Body({ icon, title, description, children }) {
|
|
|
70
70
|
import { useState } from "react";
|
|
71
71
|
import { Fragment, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
72
72
|
function Button({
|
|
73
|
-
buttonClassName = "btn btn-primary
|
|
73
|
+
buttonClassName = "btn btn-primary",
|
|
74
74
|
type = "button",
|
|
75
75
|
disabled = false,
|
|
76
76
|
variant,
|
|
@@ -231,29 +231,25 @@ function NavigationItem({ icon, title, type, active, onClick }) {
|
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
// src/components/navigation/NavToggleButton.tsx
|
|
234
|
-
import { jsx as jsx12
|
|
234
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
235
235
|
var NavToggleButton = ({
|
|
236
236
|
onClick,
|
|
237
|
-
|
|
238
|
-
color = "secondary"
|
|
237
|
+
color = "dark"
|
|
239
238
|
}) => {
|
|
240
|
-
return /* @__PURE__ */ jsx12("div", { className: "
|
|
239
|
+
return /* @__PURE__ */ jsx12("div", { className: "ms-auto pe-2 d-md-none", children: /* @__PURE__ */ jsx12(
|
|
241
240
|
Button,
|
|
242
241
|
{
|
|
243
242
|
variant: color,
|
|
244
243
|
buttonClassName: "btn btn-secondary",
|
|
245
244
|
onClick: () => onClick(),
|
|
246
|
-
children:
|
|
247
|
-
"\u2630 ",
|
|
248
|
-
label
|
|
249
|
-
]
|
|
245
|
+
children: "\u2630"
|
|
250
246
|
}
|
|
251
247
|
) });
|
|
252
248
|
};
|
|
253
249
|
|
|
254
250
|
// src/components/notifications/Notifications.tsx
|
|
255
251
|
import { useEffect } from "react";
|
|
256
|
-
import { jsx as jsx13, jsxs as
|
|
252
|
+
import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
257
253
|
function Notifications({ notifications, onClose }) {
|
|
258
254
|
useEffect(() => {
|
|
259
255
|
notifications.forEach((n) => {
|
|
@@ -267,7 +263,7 @@ function Notifications({ notifications, onClose }) {
|
|
|
267
263
|
{
|
|
268
264
|
className: "position-fixed top-0 end-0",
|
|
269
265
|
style: { zIndex: 1080, width: 340 },
|
|
270
|
-
children: notifications.map((n) => /* @__PURE__ */
|
|
266
|
+
children: notifications.map((n) => /* @__PURE__ */ jsxs7(
|
|
271
267
|
"div",
|
|
272
268
|
{
|
|
273
269
|
className: `alert alert-${n.type ?? "info"} alert-dismissible fade show shadow-sm mb-2`,
|
|
@@ -299,7 +295,7 @@ import {
|
|
|
299
295
|
useEffect as useEffect2,
|
|
300
296
|
useState as useState2
|
|
301
297
|
} from "react";
|
|
302
|
-
import { jsx as jsx14, jsxs as
|
|
298
|
+
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
303
299
|
var NotificationsContext = createContext(
|
|
304
300
|
void 0
|
|
305
301
|
);
|
|
@@ -331,13 +327,13 @@ function NotificationsProvider({ children }) {
|
|
|
331
327
|
timers.forEach((t) => t && clearTimeout(t));
|
|
332
328
|
};
|
|
333
329
|
}, [notifications, close]);
|
|
334
|
-
return /* @__PURE__ */
|
|
330
|
+
return /* @__PURE__ */ jsxs8(NotificationsContext.Provider, { value: { push }, children: [
|
|
335
331
|
/* @__PURE__ */ jsx14(
|
|
336
332
|
"div",
|
|
337
333
|
{
|
|
338
334
|
className: "position-fixed top-0 end-0 p-3",
|
|
339
335
|
style: { zIndex: 1080, width: 340 },
|
|
340
|
-
children: notifications.map((n) => /* @__PURE__ */
|
|
336
|
+
children: notifications.map((n) => /* @__PURE__ */ jsxs8(
|
|
341
337
|
"div",
|
|
342
338
|
{
|
|
343
339
|
className: `alert alert-${n.type ?? "info"} alert-dismissible fade show shadow-sm mb-2`,
|
|
@@ -371,11 +367,11 @@ function UseNotifications() {
|
|
|
371
367
|
}
|
|
372
368
|
|
|
373
369
|
// src/components/views/AppsView.tsx
|
|
374
|
-
import { Fragment as Fragment3, jsx as jsx15, jsxs as
|
|
370
|
+
import { Fragment as Fragment3, jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
375
371
|
var AppsView = ({ apps, title, onAppClick }) => {
|
|
376
|
-
return /* @__PURE__ */
|
|
372
|
+
return /* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
377
373
|
title && /* @__PURE__ */ jsx15("h5", { className: "mb-3", children: title }),
|
|
378
|
-
/* @__PURE__ */ jsx15("div", { className: "row", children: apps.map((app) => /* @__PURE__ */ jsx15(AppTile, { app, onClick: onAppClick }, app.id)) })
|
|
374
|
+
/* @__PURE__ */ jsx15("div", { className: "row justify-content-center justify-content-md-start", children: apps.map((app) => /* @__PURE__ */ jsx15(AppTile, { app, onClick: onAppClick }, app.id)) })
|
|
379
375
|
] });
|
|
380
376
|
};
|
|
381
377
|
|
|
@@ -398,7 +394,7 @@ function LayoutWrapper({ children }) {
|
|
|
398
394
|
}
|
|
399
395
|
|
|
400
396
|
// src/modal/Modal.tsx
|
|
401
|
-
import { Fragment as Fragment4, jsx as jsx19, jsxs as
|
|
397
|
+
import { Fragment as Fragment4, jsx as jsx19, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
402
398
|
var Modal = ({
|
|
403
399
|
title,
|
|
404
400
|
isOpen,
|
|
@@ -421,7 +417,7 @@ var Modal = ({
|
|
|
421
417
|
e.stopPropagation();
|
|
422
418
|
};
|
|
423
419
|
const hasFooterButtons = (showCloseButton || onConfirm && showConfirmButton) && !disableAllButtons;
|
|
424
|
-
return /* @__PURE__ */
|
|
420
|
+
return /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
425
421
|
/* @__PURE__ */ jsx19(
|
|
426
422
|
"div",
|
|
427
423
|
{
|
|
@@ -444,8 +440,8 @@ var Modal = ({
|
|
|
444
440
|
className: "modal-dialog modal-dialog-centered",
|
|
445
441
|
role: "document",
|
|
446
442
|
onClick: handleContentClick,
|
|
447
|
-
children: /* @__PURE__ */
|
|
448
|
-
/* @__PURE__ */
|
|
443
|
+
children: /* @__PURE__ */ jsxs10("div", { className: "modal-content shadow", children: [
|
|
444
|
+
/* @__PURE__ */ jsxs10("div", { className: "modal-header", children: [
|
|
449
445
|
title && /* @__PURE__ */ jsx19("h5", { className: "modal-title", children: title }),
|
|
450
446
|
showHeaderClose && /* @__PURE__ */ jsx19(
|
|
451
447
|
"button",
|
|
@@ -459,7 +455,7 @@ var Modal = ({
|
|
|
459
455
|
)
|
|
460
456
|
] }),
|
|
461
457
|
/* @__PURE__ */ jsx19("div", { className: "modal-body", children }),
|
|
462
|
-
hasFooterButtons && /* @__PURE__ */
|
|
458
|
+
hasFooterButtons && /* @__PURE__ */ jsxs10("div", { className: "modal-footer", children: [
|
|
463
459
|
showCloseButton && /* @__PURE__ */ jsx19(
|
|
464
460
|
"button",
|
|
465
461
|
{
|
|
@@ -496,7 +492,7 @@ import {
|
|
|
496
492
|
useContext as useContext2,
|
|
497
493
|
useState as useState3
|
|
498
494
|
} from "react";
|
|
499
|
-
import { jsx as jsx20, jsxs as
|
|
495
|
+
import { jsx as jsx20, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
500
496
|
var ModalContext = createContext2(void 0);
|
|
501
497
|
function ModalProvider({ children }) {
|
|
502
498
|
const [isOpen, setIsOpen] = useState3(false);
|
|
@@ -510,7 +506,7 @@ function ModalProvider({ children }) {
|
|
|
510
506
|
const closeModal = useCallback2(() => {
|
|
511
507
|
setIsOpen(false);
|
|
512
508
|
}, []);
|
|
513
|
-
return /* @__PURE__ */
|
|
509
|
+
return /* @__PURE__ */ jsxs11(ModalContext.Provider, { value: { openModal, closeModal }, children: [
|
|
514
510
|
children,
|
|
515
511
|
/* @__PURE__ */ jsx20(
|
|
516
512
|
Modal,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/Alert.tsx","../src/components/AppTile.tsx","../src/components/Body.tsx","../src/components/Button.tsx","../src/components/Footer.tsx","../src/components/Header.tsx","../src/components/HeaderText.tsx","../src/components/Icon.tsx","../src/components/NpmBadge.tsx","../src/components/navigation/Navigation.tsx","../src/components/navigation/NavigationItem.tsx","../src/components/navigation/NavToggleButton.tsx","../src/components/notifications/Notifications.tsx","../src/components/notifications/NotificationsProvider.tsx","../src/components/views/AppsView.tsx","../src/components/wrappers/ContentContainer.tsx","../src/components/wrappers/ContentRow.tsx","../src/components/wrappers/LayoutWrapper.tsx","../src/modal/Modal.tsx","../src/modal/ModalProvider.tsx"],"sourcesContent":["// components/Alert.tsx\r\nimport React from \"react\";\r\n\r\nexport type AlertVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\";\r\n\r\ninterface AlertProps {\r\n variant?: AlertVariant;\r\n title?: string;\r\n dismissible?: boolean;\r\n className?: string;\r\n children: React.ReactNode;\r\n onClose?: () => void;\r\n}\r\n\r\nexport const Alert: React.FC<AlertProps> = ({\r\n variant = \"info\",\r\n title,\r\n dismissible = false,\r\n className = \"\",\r\n children,\r\n onClose,\r\n}) => {\r\n const classes = [\r\n \"alert\",\r\n `alert-${variant}`,\r\n dismissible ? \"alert-dismissible fade show\" : \"\",\r\n className,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \");\r\n\r\n return (\r\n <div role=\"alert\" className={classes}>\r\n {title && <strong className=\"d-block mb-1\">{title}</strong>}\r\n {children}\r\n\r\n {dismissible && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport type { AppItem } from \"../models/AppItem\";\r\n\r\ninterface AppTileProps {\r\n app: AppItem;\r\n onClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppTile: React.FC<AppTileProps> = ({ app, onClick }) => {\r\n return (\r\n <div className=\"col-auto\">\r\n <button\r\n type=\"button\"\r\n className=\"btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn\"\r\n onClick={() => onClick?.(app)}\r\n >\r\n <div className=\"app-icon-tile d-flex align-items-center justify-content-center mb-1\">\r\n <span style={{fontSize:\"32px\"}}>{app.icon}</span>\r\n </div>\r\n\r\n <span className=\"w-100 small text-truncate\">\r\n {app.name}\r\n {app.version && <small className=\"text-muted ms-1\">v{app.version}</small>}\r\n </span>\r\n </button>\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface BodyProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n description?: ReactNode;\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Body({ icon, title, description, children }: BodyProps) {\r\n return (\r\n\r\n <main className=\"col p-4\">\r\n <h2>{icon} {title}</h2>\r\n\r\n {description && <p>{description}</p>}\r\n {children}\r\n </main>\r\n );\r\n}\r\n","import { useState, type ReactNode, type MouseEvent } from \"react\";\r\n\r\nexport type ButtonVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\"\r\n | \"link\";\r\n\r\nexport interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\r\n\r\n variant?: ButtonVariant; // 👈 NEW — Bootstrap color support\r\n\r\n onAction?: () => Promise<unknown>;\r\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\r\n onDone?: (result: unknown) => void;\r\n onError?: (error: unknown) => void;\r\n onFinally?: () => void;\r\n\r\n children?: ReactNode;\r\n loadingChildren?: ReactNode;\r\n\r\n renderContent?: () => ReactNode;\r\n renderLoading?: () => ReactNode;\r\n\r\n loadingText?: string;\r\n showSpinner?: boolean;\r\n}\r\n\r\nexport function Button({\r\n buttonClassName = \"btn btn-primary btn-lg\",\r\n type = \"button\",\r\n disabled = false,\r\n\r\n variant,\r\n\r\n onAction,\r\n onClick,\r\n onDone,\r\n onError,\r\n onFinally,\r\n\r\n children = \"Click me\",\r\n\r\n loadingChildren,\r\n renderContent,\r\n renderLoading,\r\n\r\n loadingText = \"Loading...\",\r\n showSpinner = true,\r\n}: ButtonProps) {\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleClick = async (event: MouseEvent<HTMLButtonElement>) => {\r\n if (loading) return;\r\n\r\n onClick?.(event);\r\n if (event.defaultPrevented) return;\r\n if (!onAction) return;\r\n\r\n try {\r\n setLoading(true);\r\n const result = await onAction();\r\n onDone?.(result);\r\n } catch (error) {\r\n onError?.(error);\r\n } finally {\r\n setLoading(false);\r\n onFinally?.();\r\n }\r\n };\r\n\r\n // 👇 Decide which CSS to use:\r\n // - if variant is provided, use Bootstrap \"btn btn-X\"\r\n // - otherwise fall back to user-supplied buttonClassName\r\n const baseClass = variant\r\n ? `btn btn-${variant}`\r\n : buttonClassName;\r\n\r\n return (\r\n <button\r\n type={type}\r\n className={`${baseClass} ${loading ? \"async-btn--loading\" : \"\"}`}\r\n onClick={handleClick}\r\n disabled={disabled || loading}\r\n >\r\n {loading ? (\r\n renderLoading?.() ??\r\n loadingChildren ?? (\r\n <>\r\n {showSpinner && (\r\n <span\r\n className=\"spinner-border spinner-border-sm me-2 async-btn__spinner\"\r\n role=\"status\"\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n {loadingText}\r\n </>\r\n )\r\n ) : (\r\n renderContent?.() ?? children\r\n )}\r\n </button>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface FooterProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Footer({ children }: FooterProps) {\r\n return (\r\n <footer className=\"bg-dark text-white text-center py-2 mt-auto\">\r\n {children ?? \"© 2025 Your Site — All rights reserved\"}\r\n </footer>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Header({ children }: HeaderProps) {\r\n return (\r\n <nav className=\"navbar navbar-dark bg-dark px-3 sticky-top\">\r\n {children ?? (\r\n <span className=\"navbar-brand mb-0 h4\">My Website</span>\r\n )}\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderBrandProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function HeaderText({ children }: HeaderBrandProps) {\r\n return (\r\n <span className=\"navbar-brand mb-0 h4\">\r\n {children}\r\n </span>\r\n );\r\n}\r\n","// ImageCard.tsx\r\nimport React from \"react\";\r\n\r\ninterface ImageCardProps {\r\n src: string;\r\n alt: string;\r\n width?: string | number;\r\n height?: string | number;\r\n}\r\n\r\nexport const ImageCard: React.FC<ImageCardProps> = ({\r\n src,\r\n alt,\r\n}) => {\r\n return (\r\n <img\r\n src={src}\r\n alt={alt}\r\n className={\"w-100\"}\r\n style={{\r\n display: \"block\",\r\n objectFit: \"cover\",\r\n }}\r\n />\r\n );\r\n};\r\n","// components/NpmBadge.tsx\r\ninterface NpmBadgeProps {\r\n packageLabel: string;\r\n packageName: string;\r\n packageUrl: string; // e.g. \"@sparkstudio/authentication-ui\"\r\n color?: string; // optional (default black)\r\n height?: number; // optional (default 22)\r\n}\r\n\r\nexport function NpmBadge({ packageName, packageLabel, packageUrl, color = \"black\", height = 22 }: NpmBadgeProps) {\r\n const encodedLabel = encodeURIComponent(packageLabel);\r\n const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;\r\n const npmUrl = packageUrl;\r\n\r\n return (\r\n <a href={npmUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n <img src={badgeUrl} alt={`${packageName} version`} style={{ height }} />\r\n </a>\r\n );\r\n}\r\n","// components/Navigation.tsx\r\nimport type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n}\r\n\r\nexport function Navigation({\r\n title = \"Navigation\",\r\n children,\r\n isOpen,\r\n onClose,\r\n}: NavigationProps) {\r\n return (\r\n <>\r\n {/* Desktop sidebar */}\r\n <nav className=\"col-auto p-3 h-100 d-none d-md-flex flex-column\">\r\n <h6 className=\"text-muted text-uppercase\">{title}</h6>\r\n\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-3\">\r\n {children}\r\n </ul>\r\n </nav>\r\n\r\n {/* Mobile drawer */}\r\n <div\r\n className={`offcanvas offcanvas-start d-md-none ${isOpen ? \"show\" : \"\"}`}\r\n style={{ visibility: isOpen ? \"visible\" : \"hidden\" }}\r\n tabIndex={-1}\r\n aria-hidden={isOpen ? \"false\" : \"true\"}\r\n >\r\n <div className=\"offcanvas-header\">\r\n <h5 className=\"offcanvas-title\">{title}</h5>\r\n <button className=\"btn-close\" onClick={onClose} />\r\n </div>\r\n\r\n <div className=\"offcanvas-body\">\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-2\">\r\n {children}\r\n </ul>\r\n </div>\r\n </div>\r\n\r\n {/* Backdrop */}\r\n {isOpen && (\r\n <div\r\n className=\"offcanvas-backdrop fade show d-md-none\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationItemProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n type: string;\r\n active?: boolean;\r\n onClick?: (type: string) => void;\r\n}\r\n\r\nexport function NavigationItem({icon, title, type, active, onClick }: NavigationItemProps) {\r\n return (\r\n <li className=\"nav-item\">\r\n <button\r\n type=\"button\"\r\n className={`nav-link text-start w-100 ${active ? \"active\" : \"\"}`}\r\n onClick={() => onClick?.(type)}\r\n >\r\n {icon} {title}\r\n </button>\r\n </li>\r\n );\r\n}\r\n","// components/NavToggleButton.tsx\r\nimport React from \"react\";\r\nimport { Button } from \"../Button\";\r\n\r\ninterface NavToggleButtonProps {\r\n onClick: () => void;\r\n label?: string;\r\n color?: \"primary\" | \"secondary\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"light\" | \"dark\";\r\n}\r\n\r\nexport const NavToggleButton: React.FC<NavToggleButtonProps> = ({\r\n onClick,\r\n label = \"Menu\",\r\n color = \"secondary\",\r\n}) => {\r\n return (\r\n <div className=\"d-md-none position-absolute top-0 end-0 m-2\">\r\n <Button\r\n variant={color}\r\n buttonClassName=\"btn btn-secondary\"\r\n onClick={() => onClick()}\r\n >\r\n ☰ {label}\r\n </Button>\r\n </div>\r\n );\r\n};\r\n","import { useEffect } from \"react\";\r\n\r\nexport type NotificationType = \"success\" | \"info\" | \"warning\" | \"danger\";\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsProps {\r\n notifications: Notification[];\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Notifications({ notifications, onClose }: NotificationsProps) {\r\n useEffect(() => {\r\n notifications.forEach((n) => {\r\n if (!n.autoCloseMs) return;\r\n\r\n const timer = setTimeout(() => onClose(n.id), n.autoCloseMs);\r\n return () => clearTimeout(timer);\r\n });\r\n }, [notifications, onClose]);\r\n\r\n return (\r\n <div\r\n className=\"position-fixed top-0 end-0\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => onClose(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport type { NotificationType } from \"./Notifications\";\r\n\r\n// Rename to avoid conflict with browser Notification type\r\nexport interface AppNotification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsContextValue {\r\n push: (message: string, type?: NotificationType, autoCloseMs?: number) => void;\r\n}\r\n\r\nconst NotificationsContext = createContext<NotificationsContextValue | undefined>(\r\n undefined\r\n);\r\n\r\ninterface NotificationsProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function NotificationsProvider({ children }: NotificationsProviderProps) {\r\n const [notifications, setNotifications] = useState<AppNotification[]>([]);\r\n\r\n const push = useCallback(\r\n (message: string, type: NotificationType = \"info\", autoCloseMs = 4000) => {\r\n setNotifications((prev) => [\r\n ...prev,\r\n {\r\n id: crypto.randomUUID(),\r\n message,\r\n type,\r\n autoCloseMs,\r\n },\r\n ]);\r\n },\r\n []\r\n );\r\n\r\n const close = useCallback((id: string) => {\r\n setNotifications((list) => list.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n // Handle auto close timers\r\n useEffect(() => {\r\n const timers = notifications.map((n) => {\r\n if (!n.autoCloseMs) return null;\r\n return setTimeout(() => close(n.id), n.autoCloseMs);\r\n });\r\n\r\n return () => {\r\n timers.forEach((t) => t && clearTimeout(t));\r\n };\r\n }, [notifications, close]);\r\n\r\n return (\r\n <NotificationsContext.Provider value={{ push }}>\r\n {/* overlay renderer */}\r\n <div\r\n className=\"position-fixed top-0 end-0 p-3\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => close(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {children}\r\n </NotificationsContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseNotifications(): NotificationsContextValue {\r\n const ctx = useContext(NotificationsContext);\r\n if (!ctx) {\r\n throw new Error(\"useNotifications must be used within a NotificationsProvider\");\r\n }\r\n return ctx;\r\n}\r\n","// ./views/AppsView.tsx (or ./components/AppsView.tsx)\r\nimport React from \"react\";\r\nimport type { AppItem } from \"../../models/AppItem\";\r\nimport { AppTile } from \"../AppTile\";\r\n\r\ninterface AppsViewProps {\r\n apps: AppItem[];\r\n title?: string;\r\n onAppClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppsView: React.FC<AppsViewProps> = ({ apps, title, onAppClick }) => {\r\n return (\r\n <>\r\n {title && <h5 className=\"mb-3\">{title}</h5>}\r\n\r\n <div className=\"row\">\r\n {apps.map((app) => (\r\n <AppTile key={app.id} app={app} onClick={onAppClick} />\r\n ))}\r\n </div>\r\n </>\r\n );\r\n};\r\n","export function ContentContainer({ children }: React.PropsWithChildren) {\r\n return <div className=\"container-fluid flex-grow-1\">{children}</div>;\r\n}\r\n","export function ContentRow({ children }: React.PropsWithChildren) {\r\n return <div className=\"row h-100 flex-nowrap\">{children}</div>;\r\n}\r\n","\r\nexport function LayoutWrapper({ children }: React.PropsWithChildren) {\r\n return (\r\n\r\n <div className=\"d-flex flex-column min-vh-100\">{children}</div>\r\n );\r\n}\r\n","// components/Modal.tsx\r\nimport React from \"react\";\r\n\r\nexport interface ModalProps {\r\n title?: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onConfirm?: () => void;\r\n confirmText?: string;\r\n\r\n disableBackdropClose?: boolean;\r\n disableAllButtons?: boolean;\r\n\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport const Modal: React.FC<ModalProps> = ({\r\n title,\r\n isOpen,\r\n onClose,\r\n onConfirm,\r\n confirmText = \"OK\",\r\n\r\n disableBackdropClose = false,\r\n disableAllButtons = false,\r\n\r\n showHeaderClose = true,\r\n showCloseButton = true,\r\n showConfirmButton = true,\r\n\r\n children,\r\n}) => {\r\n if (!isOpen) return null;\r\n\r\n const handleBackdropClick = () => {\r\n if (disableBackdropClose || disableAllButtons) return;\r\n onClose();\r\n };\r\n\r\n const handleContentClick: React.MouseEventHandler<HTMLDivElement> = (e) => {\r\n e.stopPropagation();\r\n };\r\n\r\n // 👇 NEW: decide if footer should exist at all\r\n const hasFooterButtons =\r\n (showCloseButton || (onConfirm && showConfirmButton)) &&\r\n !disableAllButtons;\r\n\r\n return (\r\n <>\r\n <div\r\n className=\"modal-backdrop fade show\"\r\n style={{ zIndex: 1040 }}\r\n onClick={handleBackdropClick}\r\n />\r\n\r\n <div\r\n className=\"modal fade show d-block\"\r\n tabIndex={-1}\r\n role=\"dialog\"\r\n style={{ zIndex: 1050 }}\r\n onClick={handleBackdropClick}\r\n >\r\n <div\r\n className=\"modal-dialog modal-dialog-centered\"\r\n role=\"document\"\r\n onClick={handleContentClick}\r\n >\r\n <div className=\"modal-content shadow\">\r\n {/* Header */}\r\n <div className=\"modal-header\">\r\n {title && <h5 className=\"modal-title\">{title}</h5>}\r\n\r\n {showHeaderClose && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"modal-body\">{children}</div>\r\n\r\n {/* Footer — only if buttons are visible */}\r\n {hasFooterButtons && (\r\n <div className=\"modal-footer\">\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-secondary\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n >\r\n Close\r\n </button>\r\n )}\r\n\r\n {onConfirm && showConfirmButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-primary\"\r\n onClick={onConfirm}\r\n disabled={disableAllButtons}\r\n >\r\n {confirmText}\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { Modal } from \"./Modal\";\r\n\r\nexport interface ModalOptions {\r\n title?: string;\r\n confirmText?: string;\r\n disableBackdropClose?: boolean;\r\n onConfirm?: () => void;\r\n\r\n /** extra control flags matching Modal.tsx */\r\n disableAllButtons?: boolean;\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n}\r\n\r\ninterface ModalContextValue {\r\n openModal: (content: ReactNode, options?: ModalOptions) => void;\r\n closeModal: () => void;\r\n}\r\n\r\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\r\n\r\nexport function ModalProvider({ children }: { children: ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [content, setContent] = useState<ReactNode>(null);\r\n const [options, setOptions] = useState<ModalOptions>({});\r\n\r\n const openModal = useCallback((content: ReactNode, options?: ModalOptions) => {\r\n setContent(content);\r\n setOptions(options ?? {});\r\n setIsOpen(true);\r\n }, []);\r\n\r\n const closeModal = useCallback(() => {\r\n setIsOpen(false);\r\n }, []);\r\n\r\n return (\r\n <ModalContext.Provider value={{ openModal, closeModal }}>\r\n {children}\r\n\r\n <Modal\r\n isOpen={isOpen}\r\n title={options.title}\r\n confirmText={options.confirmText}\r\n disableBackdropClose={options.disableBackdropClose}\r\n disableAllButtons={options.disableAllButtons}\r\n showHeaderClose={options.showHeaderClose}\r\n showCloseButton={options.showCloseButton}\r\n showConfirmButton={options.showConfirmButton}\r\n onClose={closeModal}\r\n onConfirm={options.onConfirm}\r\n >\r\n {content}\r\n </Modal>\r\n </ModalContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseModal() {\r\n const ctx = useContext(ModalContext);\r\n if (!ctx) throw new Error(\"UseModal must be used within ModalProvider\");\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsx","jsx","jsx","jsx","Fragment","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","useEffect","useState","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsx","jsx","Fragment","jsx","jsxs","createContext","useCallback","useContext","useState","jsx","jsxs","createContext","useState","useCallback","content","options","useContext"]}
|
|
1
|
+
{"version":3,"sources":["../src/components/Alert.tsx","../src/components/AppTile.tsx","../src/components/Body.tsx","../src/components/Button.tsx","../src/components/Footer.tsx","../src/components/Header.tsx","../src/components/HeaderText.tsx","../src/components/Icon.tsx","../src/components/NpmBadge.tsx","../src/components/navigation/Navigation.tsx","../src/components/navigation/NavigationItem.tsx","../src/components/navigation/NavToggleButton.tsx","../src/components/notifications/Notifications.tsx","../src/components/notifications/NotificationsProvider.tsx","../src/components/views/AppsView.tsx","../src/components/wrappers/ContentContainer.tsx","../src/components/wrappers/ContentRow.tsx","../src/components/wrappers/LayoutWrapper.tsx","../src/modal/Modal.tsx","../src/modal/ModalProvider.tsx"],"sourcesContent":["// components/Alert.tsx\r\nimport React from \"react\";\r\n\r\nexport type AlertVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\";\r\n\r\ninterface AlertProps {\r\n variant?: AlertVariant;\r\n title?: string;\r\n dismissible?: boolean;\r\n className?: string;\r\n children: React.ReactNode;\r\n onClose?: () => void;\r\n}\r\n\r\nexport const Alert: React.FC<AlertProps> = ({\r\n variant = \"info\",\r\n title,\r\n dismissible = false,\r\n className = \"\",\r\n children,\r\n onClose,\r\n}) => {\r\n const classes = [\r\n \"alert\",\r\n `alert-${variant}`,\r\n dismissible ? \"alert-dismissible fade show\" : \"\",\r\n className,\r\n ]\r\n .filter(Boolean)\r\n .join(\" \");\r\n\r\n return (\r\n <div role=\"alert\" className={classes}>\r\n {title && <strong className=\"d-block mb-1\">{title}</strong>}\r\n {children}\r\n\r\n {dismissible && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </div>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport type { AppItem } from \"../models/AppItem\";\r\n\r\ninterface AppTileProps {\r\n app: AppItem;\r\n onClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppTile: React.FC<AppTileProps> = ({ app, onClick }) => {\r\n return (\r\n <div className=\"col-auto\">\r\n <button\r\n type=\"button\"\r\n className=\"btn p-2 d-flex flex-column align-items-center border-0 bg-transparent app-icon-btn\"\r\n onClick={() => onClick?.(app)}\r\n >\r\n <div className=\"app-icon-tile d-flex align-items-center justify-content-center mb-1\">\r\n <span style={{fontSize:\"32px\"}}>{app.icon}</span>\r\n </div>\r\n\r\n <span className=\"w-100 small text-truncate\">\r\n {app.name}\r\n {app.version && <small className=\"text-muted ms-1\">v{app.version}</small>}\r\n </span>\r\n </button>\r\n </div>\r\n );\r\n};\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface BodyProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n description?: ReactNode;\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Body({ icon, title, description, children }: BodyProps) {\r\n return (\r\n\r\n <main className=\"col p-4\">\r\n <h2>{icon} {title}</h2>\r\n\r\n {description && <p>{description}</p>}\r\n {children}\r\n </main>\r\n );\r\n}\r\n","import { useState, type ReactNode, type MouseEvent } from \"react\";\r\n\r\nexport type ButtonVariant =\r\n | \"primary\"\r\n | \"secondary\"\r\n | \"success\"\r\n | \"danger\"\r\n | \"warning\"\r\n | \"info\"\r\n | \"light\"\r\n | \"dark\"\r\n | \"link\";\r\n\r\nexport interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\r\n\r\n variant?: ButtonVariant; // 👈 NEW — Bootstrap color support\r\n\r\n onAction?: () => Promise<unknown>;\r\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void;\r\n onDone?: (result: unknown) => void;\r\n onError?: (error: unknown) => void;\r\n onFinally?: () => void;\r\n\r\n children?: ReactNode;\r\n loadingChildren?: ReactNode;\r\n\r\n renderContent?: () => ReactNode;\r\n renderLoading?: () => ReactNode;\r\n\r\n loadingText?: string;\r\n showSpinner?: boolean;\r\n}\r\n\r\nexport function Button({\r\n buttonClassName = \"btn btn-primary\",\r\n type = \"button\",\r\n disabled = false,\r\n\r\n variant,\r\n\r\n onAction,\r\n onClick,\r\n onDone,\r\n onError,\r\n onFinally,\r\n\r\n children = \"Click me\",\r\n\r\n loadingChildren,\r\n renderContent,\r\n renderLoading,\r\n\r\n loadingText = \"Loading...\",\r\n showSpinner = true,\r\n}: ButtonProps) {\r\n const [loading, setLoading] = useState(false);\r\n\r\n const handleClick = async (event: MouseEvent<HTMLButtonElement>) => {\r\n if (loading) return;\r\n\r\n onClick?.(event);\r\n if (event.defaultPrevented) return;\r\n if (!onAction) return;\r\n\r\n try {\r\n setLoading(true);\r\n const result = await onAction();\r\n onDone?.(result);\r\n } catch (error) {\r\n onError?.(error);\r\n } finally {\r\n setLoading(false);\r\n onFinally?.();\r\n }\r\n };\r\n\r\n // 👇 Decide which CSS to use:\r\n // - if variant is provided, use Bootstrap \"btn btn-X\"\r\n // - otherwise fall back to user-supplied buttonClassName\r\n const baseClass = variant\r\n ? `btn btn-${variant}`\r\n : buttonClassName;\r\n\r\n return (\r\n <button\r\n type={type}\r\n className={`${baseClass} ${loading ? \"async-btn--loading\" : \"\"}`}\r\n onClick={handleClick}\r\n disabled={disabled || loading}\r\n >\r\n {loading ? (\r\n renderLoading?.() ??\r\n loadingChildren ?? (\r\n <>\r\n {showSpinner && (\r\n <span\r\n className=\"spinner-border spinner-border-sm me-2 async-btn__spinner\"\r\n role=\"status\"\r\n aria-hidden=\"true\"\r\n />\r\n )}\r\n {loadingText}\r\n </>\r\n )\r\n ) : (\r\n renderContent?.() ?? children\r\n )}\r\n </button>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface FooterProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Footer({ children }: FooterProps) {\r\n return (\r\n <footer className=\"bg-dark text-white text-center py-2 mt-auto\">\r\n {children ?? \"© 2025 Your Site — All rights reserved\"}\r\n </footer>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderProps {\r\n children?: ReactNode;\r\n}\r\n\r\nexport function Header({ children }: HeaderProps) {\r\n return (\r\n <nav className=\"navbar navbar-dark bg-dark px-3 sticky-top\">\r\n {children ?? (\r\n <span className=\"navbar-brand mb-0 h4\">My Website</span>\r\n )}\r\n </nav>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface HeaderBrandProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function HeaderText({ children }: HeaderBrandProps) {\r\n return (\r\n <span className=\"navbar-brand mb-0 h4\">\r\n {children}\r\n </span>\r\n );\r\n}\r\n","// ImageCard.tsx\r\nimport React from \"react\";\r\n\r\ninterface ImageCardProps {\r\n src: string;\r\n alt: string;\r\n width?: string | number;\r\n height?: string | number;\r\n}\r\n\r\nexport const ImageCard: React.FC<ImageCardProps> = ({\r\n src,\r\n alt,\r\n}) => {\r\n return (\r\n <img\r\n src={src}\r\n alt={alt}\r\n className={\"w-100\"}\r\n style={{\r\n display: \"block\",\r\n objectFit: \"cover\",\r\n }}\r\n />\r\n );\r\n};\r\n","// components/NpmBadge.tsx\r\ninterface NpmBadgeProps {\r\n packageLabel: string;\r\n packageName: string;\r\n packageUrl: string; // e.g. \"@sparkstudio/authentication-ui\"\r\n color?: string; // optional (default black)\r\n height?: number; // optional (default 22)\r\n}\r\n\r\nexport function NpmBadge({ packageName, packageLabel, packageUrl, color = \"black\", height = 22 }: NpmBadgeProps) {\r\n const encodedLabel = encodeURIComponent(packageLabel);\r\n const badgeUrl = `https://img.shields.io/npm/v/${packageName}?logo=npm&label=${encodedLabel}&color=${color}`;\r\n const npmUrl = packageUrl;\r\n\r\n return (\r\n <a href={npmUrl} target=\"_blank\" rel=\"noopener noreferrer\">\r\n <img src={badgeUrl} alt={`${packageName} version`} style={{ height }} />\r\n </a>\r\n );\r\n}\r\n","// components/Navigation.tsx\r\nimport type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n}\r\n\r\nexport function Navigation({\r\n title = \"Navigation\",\r\n children,\r\n isOpen,\r\n onClose,\r\n}: NavigationProps) {\r\n return (\r\n <>\r\n {/* Desktop sidebar */}\r\n <nav className=\"col-auto p-3 h-100 d-none d-md-flex flex-column\">\r\n <h6 className=\"text-muted text-uppercase\">{title}</h6>\r\n\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-3\">\r\n {children}\r\n </ul>\r\n </nav>\r\n\r\n {/* Mobile drawer */}\r\n <div\r\n className={`offcanvas offcanvas-start d-md-none ${isOpen ? \"show\" : \"\"}`}\r\n style={{ visibility: isOpen ? \"visible\" : \"hidden\" }}\r\n tabIndex={-1}\r\n aria-hidden={isOpen ? \"false\" : \"true\"}\r\n >\r\n <div className=\"offcanvas-header\">\r\n <h5 className=\"offcanvas-title\">{title}</h5>\r\n <button className=\"btn-close\" onClick={onClose} />\r\n </div>\r\n\r\n <div className=\"offcanvas-body\">\r\n <ul className=\"nav nav-pills flex-column gap-2 mt-2\">\r\n {children}\r\n </ul>\r\n </div>\r\n </div>\r\n\r\n {/* Backdrop */}\r\n {isOpen && (\r\n <div\r\n className=\"offcanvas-backdrop fade show d-md-none\"\r\n onClick={onClose}\r\n />\r\n )}\r\n </>\r\n );\r\n}\r\n","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationItemProps {\r\n icon: ReactNode;\r\n title: ReactNode;\r\n type: string;\r\n active?: boolean;\r\n onClick?: (type: string) => void;\r\n}\r\n\r\nexport function NavigationItem({icon, title, type, active, onClick }: NavigationItemProps) {\r\n return (\r\n <li className=\"nav-item\">\r\n <button\r\n type=\"button\"\r\n className={`nav-link text-start w-100 ${active ? \"active\" : \"\"}`}\r\n onClick={() => onClick?.(type)}\r\n >\r\n {icon} {title}\r\n </button>\r\n </li>\r\n );\r\n}\r\n","// components/NavToggleButton.tsx\r\nimport React from \"react\";\r\nimport { Button } from \"../Button\";\r\n\r\ninterface NavToggleButtonProps {\r\n onClick: () => void;\r\n label?: string;\r\n color?: \"primary\" | \"secondary\" | \"success\" | \"danger\" | \"warning\" | \"info\" | \"light\" | \"dark\";\r\n}\r\n\r\nexport const NavToggleButton: React.FC<NavToggleButtonProps> = ({\r\n onClick,\r\n color = \"dark\",\r\n}) => {\r\n return (\r\n <div className=\"ms-auto pe-2 d-md-none\">\r\n <Button\r\n variant={color}\r\n buttonClassName=\"btn btn-secondary\"\r\n onClick={() => onClick()}\r\n >\r\n ☰\r\n </Button>\r\n </div>\r\n );\r\n};\r\n","import { useEffect } from \"react\";\r\n\r\nexport type NotificationType = \"success\" | \"info\" | \"warning\" | \"danger\";\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsProps {\r\n notifications: Notification[];\r\n onClose: (id: string) => void;\r\n}\r\n\r\nexport function Notifications({ notifications, onClose }: NotificationsProps) {\r\n useEffect(() => {\r\n notifications.forEach((n) => {\r\n if (!n.autoCloseMs) return;\r\n\r\n const timer = setTimeout(() => onClose(n.id), n.autoCloseMs);\r\n return () => clearTimeout(timer);\r\n });\r\n }, [notifications, onClose]);\r\n\r\n return (\r\n <div\r\n className=\"position-fixed top-0 end-0\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => onClose(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useEffect,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport type { NotificationType } from \"./Notifications\";\r\n\r\n// Rename to avoid conflict with browser Notification type\r\nexport interface AppNotification {\r\n id: string;\r\n message: string;\r\n type?: NotificationType;\r\n autoCloseMs?: number;\r\n}\r\n\r\ninterface NotificationsContextValue {\r\n push: (message: string, type?: NotificationType, autoCloseMs?: number) => void;\r\n}\r\n\r\nconst NotificationsContext = createContext<NotificationsContextValue | undefined>(\r\n undefined\r\n);\r\n\r\ninterface NotificationsProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\nexport function NotificationsProvider({ children }: NotificationsProviderProps) {\r\n const [notifications, setNotifications] = useState<AppNotification[]>([]);\r\n\r\n const push = useCallback(\r\n (message: string, type: NotificationType = \"info\", autoCloseMs = 4000) => {\r\n setNotifications((prev) => [\r\n ...prev,\r\n {\r\n id: crypto.randomUUID(),\r\n message,\r\n type,\r\n autoCloseMs,\r\n },\r\n ]);\r\n },\r\n []\r\n );\r\n\r\n const close = useCallback((id: string) => {\r\n setNotifications((list) => list.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n // Handle auto close timers\r\n useEffect(() => {\r\n const timers = notifications.map((n) => {\r\n if (!n.autoCloseMs) return null;\r\n return setTimeout(() => close(n.id), n.autoCloseMs);\r\n });\r\n\r\n return () => {\r\n timers.forEach((t) => t && clearTimeout(t));\r\n };\r\n }, [notifications, close]);\r\n\r\n return (\r\n <NotificationsContext.Provider value={{ push }}>\r\n {/* overlay renderer */}\r\n <div\r\n className=\"position-fixed top-0 end-0 p-3\"\r\n style={{ zIndex: 1080, width: 340 }}\r\n >\r\n {notifications.map((n) => (\r\n <div\r\n key={n.id}\r\n className={`alert alert-${n.type ?? \"info\"} alert-dismissible fade show shadow-sm mb-2`}\r\n role=\"alert\"\r\n >\r\n {n.message}\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={() => close(n.id)}\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n\r\n {children}\r\n </NotificationsContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseNotifications(): NotificationsContextValue {\r\n const ctx = useContext(NotificationsContext);\r\n if (!ctx) {\r\n throw new Error(\"useNotifications must be used within a NotificationsProvider\");\r\n }\r\n return ctx;\r\n}\r\n","// ./views/AppsView.tsx (or ./components/AppsView.tsx)\r\nimport React from \"react\";\r\nimport type { AppItem } from \"../../models/AppItem\";\r\nimport { AppTile } from \"../AppTile\";\r\n\r\ninterface AppsViewProps {\r\n apps: AppItem[];\r\n title?: string;\r\n onAppClick?: (app: AppItem) => void;\r\n}\r\n\r\nexport const AppsView: React.FC<AppsViewProps> = ({ apps, title, onAppClick }) => {\r\n return (\r\n <>\r\n {title && <h5 className=\"mb-3\">{title}</h5>}\r\n\r\n <div className=\"row justify-content-center justify-content-md-start\">\r\n {apps.map((app) => (\r\n <AppTile key={app.id} app={app} onClick={onAppClick} />\r\n ))}\r\n </div>\r\n </>\r\n );\r\n};\r\n","export function ContentContainer({ children }: React.PropsWithChildren) {\r\n return <div className=\"container-fluid flex-grow-1\">{children}</div>;\r\n}\r\n","export function ContentRow({ children }: React.PropsWithChildren) {\r\n return <div className=\"row h-100 flex-nowrap\">{children}</div>;\r\n}\r\n","\r\nexport function LayoutWrapper({ children }: React.PropsWithChildren) {\r\n return (\r\n\r\n <div className=\"d-flex flex-column min-vh-100\">{children}</div>\r\n );\r\n}\r\n","// components/Modal.tsx\r\nimport React from \"react\";\r\n\r\nexport interface ModalProps {\r\n title?: string;\r\n isOpen: boolean;\r\n onClose: () => void;\r\n onConfirm?: () => void;\r\n confirmText?: string;\r\n\r\n disableBackdropClose?: boolean;\r\n disableAllButtons?: boolean;\r\n\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n\r\n children?: React.ReactNode;\r\n}\r\n\r\nexport const Modal: React.FC<ModalProps> = ({\r\n title,\r\n isOpen,\r\n onClose,\r\n onConfirm,\r\n confirmText = \"OK\",\r\n\r\n disableBackdropClose = false,\r\n disableAllButtons = false,\r\n\r\n showHeaderClose = true,\r\n showCloseButton = true,\r\n showConfirmButton = true,\r\n\r\n children,\r\n}) => {\r\n if (!isOpen) return null;\r\n\r\n const handleBackdropClick = () => {\r\n if (disableBackdropClose || disableAllButtons) return;\r\n onClose();\r\n };\r\n\r\n const handleContentClick: React.MouseEventHandler<HTMLDivElement> = (e) => {\r\n e.stopPropagation();\r\n };\r\n\r\n // 👇 NEW: decide if footer should exist at all\r\n const hasFooterButtons =\r\n (showCloseButton || (onConfirm && showConfirmButton)) &&\r\n !disableAllButtons;\r\n\r\n return (\r\n <>\r\n <div\r\n className=\"modal-backdrop fade show\"\r\n style={{ zIndex: 1040 }}\r\n onClick={handleBackdropClick}\r\n />\r\n\r\n <div\r\n className=\"modal fade show d-block\"\r\n tabIndex={-1}\r\n role=\"dialog\"\r\n style={{ zIndex: 1050 }}\r\n onClick={handleBackdropClick}\r\n >\r\n <div\r\n className=\"modal-dialog modal-dialog-centered\"\r\n role=\"document\"\r\n onClick={handleContentClick}\r\n >\r\n <div className=\"modal-content shadow\">\r\n {/* Header */}\r\n <div className=\"modal-header\">\r\n {title && <h5 className=\"modal-title\">{title}</h5>}\r\n\r\n {showHeaderClose && (\r\n <button\r\n type=\"button\"\r\n className=\"btn-close\"\r\n aria-label=\"Close\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n />\r\n )}\r\n </div>\r\n\r\n {/* Body */}\r\n <div className=\"modal-body\">{children}</div>\r\n\r\n {/* Footer — only if buttons are visible */}\r\n {hasFooterButtons && (\r\n <div className=\"modal-footer\">\r\n {showCloseButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-secondary\"\r\n onClick={onClose}\r\n disabled={disableAllButtons}\r\n >\r\n Close\r\n </button>\r\n )}\r\n\r\n {onConfirm && showConfirmButton && (\r\n <button\r\n type=\"button\"\r\n className=\"btn btn-primary\"\r\n onClick={onConfirm}\r\n disabled={disableAllButtons}\r\n >\r\n {confirmText}\r\n </button>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n );\r\n};\r\n","import {\r\n createContext,\r\n useCallback,\r\n useContext,\r\n useState,\r\n type ReactNode,\r\n} from \"react\";\r\nimport { Modal } from \"./Modal\";\r\n\r\nexport interface ModalOptions {\r\n title?: string;\r\n confirmText?: string;\r\n disableBackdropClose?: boolean;\r\n onConfirm?: () => void;\r\n\r\n /** extra control flags matching Modal.tsx */\r\n disableAllButtons?: boolean;\r\n showHeaderClose?: boolean;\r\n showCloseButton?: boolean;\r\n showConfirmButton?: boolean;\r\n}\r\n\r\ninterface ModalContextValue {\r\n openModal: (content: ReactNode, options?: ModalOptions) => void;\r\n closeModal: () => void;\r\n}\r\n\r\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\r\n\r\nexport function ModalProvider({ children }: { children: ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [content, setContent] = useState<ReactNode>(null);\r\n const [options, setOptions] = useState<ModalOptions>({});\r\n\r\n const openModal = useCallback((content: ReactNode, options?: ModalOptions) => {\r\n setContent(content);\r\n setOptions(options ?? {});\r\n setIsOpen(true);\r\n }, []);\r\n\r\n const closeModal = useCallback(() => {\r\n setIsOpen(false);\r\n }, []);\r\n\r\n return (\r\n <ModalContext.Provider value={{ openModal, closeModal }}>\r\n {children}\r\n\r\n <Modal\r\n isOpen={isOpen}\r\n title={options.title}\r\n confirmText={options.confirmText}\r\n disableBackdropClose={options.disableBackdropClose}\r\n disableAllButtons={options.disableAllButtons}\r\n showHeaderClose={options.showHeaderClose}\r\n showCloseButton={options.showCloseButton}\r\n showConfirmButton={options.showConfirmButton}\r\n onClose={closeModal}\r\n onConfirm={options.onConfirm}\r\n >\r\n {content}\r\n </Modal>\r\n </ModalContext.Provider>\r\n );\r\n}\r\n\r\nexport function UseModal() {\r\n const ctx = useContext(ModalContext);\r\n if (!ctx) throw new Error(\"UseModal must be used within ModalProvider\");\r\n return ctx;\r\n}\r\n"],"mappings":"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","names":["jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsx","jsx","jsx","jsx","Fragment","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs","useEffect","useState","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsx","jsx","Fragment","jsx","jsxs","createContext","useCallback","useContext","useState","jsx","jsxs","createContext","useState","useCallback","content","options","useContext"]}
|