@sparkstudio/common-ui 1.0.20 → 1.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -407,6 +407,7 @@ var Modal = ({
407
407
  const handleContentClick = (e) => {
408
408
  e.stopPropagation();
409
409
  };
410
+ const hasFooterButtons = (showCloseButton || onConfirm && showConfirmButton) && !disableAllButtons;
410
411
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
411
412
  /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
412
413
  "div",
@@ -424,44 +425,52 @@ var Modal = ({
424
425
  role: "dialog",
425
426
  style: { zIndex: 1050 },
426
427
  onClick: handleBackdropClick,
427
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "modal-dialog modal-dialog-centered", role: "document", onClick: handleContentClick, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "modal-content shadow", children: [
428
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "modal-header", children: [
429
- title && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h5", { className: "modal-title", children: title }),
430
- showHeaderClose && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
431
- "button",
432
- {
433
- type: "button",
434
- className: "btn-close",
435
- "aria-label": "Close",
436
- onClick: onClose,
437
- disabled: disableAllButtons
438
- }
439
- )
440
- ] }),
441
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "modal-body", children }),
442
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "modal-footer", children: [
443
- showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
444
- "button",
445
- {
446
- type: "button",
447
- className: "btn btn-secondary",
448
- onClick: onClose,
449
- disabled: disableAllButtons,
450
- children: "Close"
451
- }
452
- ),
453
- onConfirm && showConfirmButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
454
- "button",
455
- {
456
- type: "button",
457
- className: "btn btn-primary",
458
- onClick: onConfirm,
459
- disabled: disableAllButtons,
460
- children: confirmText
461
- }
462
- )
463
- ] })
464
- ] }) })
428
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
429
+ "div",
430
+ {
431
+ className: "modal-dialog modal-dialog-centered",
432
+ role: "document",
433
+ onClick: handleContentClick,
434
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "modal-content shadow", children: [
435
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "modal-header", children: [
436
+ title && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h5", { className: "modal-title", children: title }),
437
+ showHeaderClose && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
438
+ "button",
439
+ {
440
+ type: "button",
441
+ className: "btn-close",
442
+ "aria-label": "Close",
443
+ onClick: onClose,
444
+ disabled: disableAllButtons
445
+ }
446
+ )
447
+ ] }),
448
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "modal-body", children }),
449
+ hasFooterButtons && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "modal-footer", children: [
450
+ showCloseButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
451
+ "button",
452
+ {
453
+ type: "button",
454
+ className: "btn btn-secondary",
455
+ onClick: onClose,
456
+ disabled: disableAllButtons,
457
+ children: "Close"
458
+ }
459
+ ),
460
+ onConfirm && showConfirmButton && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
461
+ "button",
462
+ {
463
+ type: "button",
464
+ className: "btn btn-primary",
465
+ onClick: onConfirm,
466
+ disabled: disableAllButtons,
467
+ children: confirmText
468
+ }
469
+ )
470
+ ] })
471
+ ] })
472
+ }
473
+ )
465
474
  }
466
475
  )
467
476
  ] });
@@ -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/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/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 interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\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 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 return (\r\n <button\r\n type={type}\r\n className={`${buttonClassName} ${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","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n}\r\n\r\nexport function Navigation({ title = \"Navigation\", children }: NavigationProps) {\r\n return (\r\n <nav className=\"col-auto p-3 h-100 d-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}\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","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 /** NEW: toggle visibility */\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 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 className=\"modal-dialog modal-dialog-centered\" role=\"document\" onClick={handleContentClick}>\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 */}\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 </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_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/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/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 interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\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 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 return (\r\n <button\r\n type={type}\r\n className={`${buttonClassName} ${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","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n}\r\n\r\nexport function Navigation({ title = \"Navigation\", children }: NavigationProps) {\r\n return (\r\n <nav className=\"col-auto p-3 h-100 d-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}\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","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_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.d.cts CHANGED
@@ -148,7 +148,6 @@ interface ModalProps {
148
148
  confirmText?: string;
149
149
  disableBackdropClose?: boolean;
150
150
  disableAllButtons?: boolean;
151
- /** NEW: toggle visibility */
152
151
  showHeaderClose?: boolean;
153
152
  showCloseButton?: boolean;
154
153
  showConfirmButton?: boolean;
package/dist/index.d.ts CHANGED
@@ -148,7 +148,6 @@ interface ModalProps {
148
148
  confirmText?: string;
149
149
  disableBackdropClose?: boolean;
150
150
  disableAllButtons?: boolean;
151
- /** NEW: toggle visibility */
152
151
  showHeaderClose?: boolean;
153
152
  showCloseButton?: boolean;
154
153
  showConfirmButton?: boolean;
package/dist/index.js CHANGED
@@ -367,6 +367,7 @@ var Modal = ({
367
367
  const handleContentClick = (e) => {
368
368
  e.stopPropagation();
369
369
  };
370
+ const hasFooterButtons = (showCloseButton || onConfirm && showConfirmButton) && !disableAllButtons;
370
371
  return /* @__PURE__ */ jsxs10(Fragment3, { children: [
371
372
  /* @__PURE__ */ jsx18(
372
373
  "div",
@@ -384,44 +385,52 @@ var Modal = ({
384
385
  role: "dialog",
385
386
  style: { zIndex: 1050 },
386
387
  onClick: handleBackdropClick,
387
- children: /* @__PURE__ */ jsx18("div", { className: "modal-dialog modal-dialog-centered", role: "document", onClick: handleContentClick, children: /* @__PURE__ */ jsxs10("div", { className: "modal-content shadow", children: [
388
- /* @__PURE__ */ jsxs10("div", { className: "modal-header", children: [
389
- title && /* @__PURE__ */ jsx18("h5", { className: "modal-title", children: title }),
390
- showHeaderClose && /* @__PURE__ */ jsx18(
391
- "button",
392
- {
393
- type: "button",
394
- className: "btn-close",
395
- "aria-label": "Close",
396
- onClick: onClose,
397
- disabled: disableAllButtons
398
- }
399
- )
400
- ] }),
401
- /* @__PURE__ */ jsx18("div", { className: "modal-body", children }),
402
- /* @__PURE__ */ jsxs10("div", { className: "modal-footer", children: [
403
- showCloseButton && /* @__PURE__ */ jsx18(
404
- "button",
405
- {
406
- type: "button",
407
- className: "btn btn-secondary",
408
- onClick: onClose,
409
- disabled: disableAllButtons,
410
- children: "Close"
411
- }
412
- ),
413
- onConfirm && showConfirmButton && /* @__PURE__ */ jsx18(
414
- "button",
415
- {
416
- type: "button",
417
- className: "btn btn-primary",
418
- onClick: onConfirm,
419
- disabled: disableAllButtons,
420
- children: confirmText
421
- }
422
- )
423
- ] })
424
- ] }) })
388
+ children: /* @__PURE__ */ jsx18(
389
+ "div",
390
+ {
391
+ className: "modal-dialog modal-dialog-centered",
392
+ role: "document",
393
+ onClick: handleContentClick,
394
+ children: /* @__PURE__ */ jsxs10("div", { className: "modal-content shadow", children: [
395
+ /* @__PURE__ */ jsxs10("div", { className: "modal-header", children: [
396
+ title && /* @__PURE__ */ jsx18("h5", { className: "modal-title", children: title }),
397
+ showHeaderClose && /* @__PURE__ */ jsx18(
398
+ "button",
399
+ {
400
+ type: "button",
401
+ className: "btn-close",
402
+ "aria-label": "Close",
403
+ onClick: onClose,
404
+ disabled: disableAllButtons
405
+ }
406
+ )
407
+ ] }),
408
+ /* @__PURE__ */ jsx18("div", { className: "modal-body", children }),
409
+ hasFooterButtons && /* @__PURE__ */ jsxs10("div", { className: "modal-footer", children: [
410
+ showCloseButton && /* @__PURE__ */ jsx18(
411
+ "button",
412
+ {
413
+ type: "button",
414
+ className: "btn btn-secondary",
415
+ onClick: onClose,
416
+ disabled: disableAllButtons,
417
+ children: "Close"
418
+ }
419
+ ),
420
+ onConfirm && showConfirmButton && /* @__PURE__ */ jsx18(
421
+ "button",
422
+ {
423
+ type: "button",
424
+ className: "btn btn-primary",
425
+ onClick: onConfirm,
426
+ disabled: disableAllButtons,
427
+ children: confirmText
428
+ }
429
+ )
430
+ ] })
431
+ ] })
432
+ }
433
+ )
425
434
  }
426
435
  )
427
436
  ] });
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/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 interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\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 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 return (\r\n <button\r\n type={type}\r\n className={`${buttonClassName} ${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","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n}\r\n\r\nexport function Navigation({ title = \"Navigation\", children }: NavigationProps) {\r\n return (\r\n <nav className=\"col-auto p-3 h-100 d-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}\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","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 /** NEW: toggle visibility */\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 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 className=\"modal-dialog modal-dialog-centered\" role=\"document\" onClick={handleContentClick}>\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 */}\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 </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","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/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 interface ButtonProps {\r\n buttonClassName?: string;\r\n type?: \"button\" | \"submit\" | \"reset\";\r\n disabled?: boolean;\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 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 return (\r\n <button\r\n type={type}\r\n className={`${buttonClassName} ${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","import type { ReactNode } from \"react\";\r\n\r\ninterface NavigationProps {\r\n title?: ReactNode;\r\n children: ReactNode;\r\n}\r\n\r\nexport function Navigation({ title = \"Navigation\", children }: NavigationProps) {\r\n return (\r\n <nav className=\"col-auto p-3 h-100 d-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}\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","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","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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sparkstudio/common-ui",
3
- "version": "1.0.20",
3
+ "version": "1.0.21",
4
4
  "type": "module",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",