@ethisyscore/plugin-ui 1.52.0 → 1.54.0
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/components/shared/index.cjs +26 -0
- package/dist/components/shared/index.cjs.map +1 -1
- package/dist/components/shared/index.d.cts +34 -1
- package/dist/components/shared/index.d.ts +34 -1
- package/dist/components/shared/index.js +24 -1
- package/dist/components/shared/index.js.map +1 -1
- package/dist/index.cjs +28 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +28 -4
- package/dist/index.js.map +1 -1
- package/dist/platform-react/index.cjs +79 -5
- package/dist/platform-react/index.cjs.map +1 -1
- package/dist/platform-react/index.d.cts +60 -4
- package/dist/platform-react/index.d.ts +60 -4
- package/dist/platform-react/index.js +78 -6
- package/dist/platform-react/index.js.map +1 -1
- package/dist/{useHostSidebarActions-CyNYWKiv.d.cts → useHostSidebarActions-Bt2U-EuA.d.cts} +31 -3
- package/dist/{useHostSidebarActions-CyNYWKiv.d.ts → useHostSidebarActions-Bt2U-EuA.d.ts} +31 -3
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/ui/Dialog.tsx","../../../src/components/shared/ConfirmActionDialog.tsx","../../../src/icons/nexture/ni-bin-empty.tsx","../../../src/icons/nexture-icons.tsx","../../../src/components/shared/ConfirmDeleteDialog.tsx","../../../src/components/shared/toast.ts"],"names":["MuiDialog","jsx","jsxs","Fragment"],"mappings":"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","file":"index.js","sourcesContent":["import { Dialog as MuiDialog, type DialogProps } from \"@mui/material\";\n\n/**\n * MUI `Dialog` with the scroll-lock + focus-restore overrides plugin surfaces\n * need (AB#4808): MUI's defaults reset the page to top when a dialog opened from\n * below the fold closes. Everything else is the stock `Dialog` — this is the one\n * `components/ui` wrapper that isn't a pure re-export.\n */\nexport function Dialog(props: DialogProps) {\n return <MuiDialog disableScrollLock disableRestoreFocus {...props} />;\n}\n","import type { ReactNode } from \"react\";\nimport {\n Button,\n CircularProgress,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n} from \"../ui\";\n\nexport interface ConfirmActionLabels {\n title: string;\n description?: ReactNode;\n btnCancel?: string;\n btnConfirm?: string;\n btnLoading?: string;\n}\n\ninterface ConfirmActionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void;\n isLoading?: boolean;\n labels: ConfirmActionLabels;\n icon?: ReactNode;\n confirmVariant?: \"default\" | \"destructive\";\n className?: string;\n /** Optional body content rendered between the description and footer (e.g. a Textarea). */\n children?: ReactNode;\n /** Additional disable condition for the confirm button (e.g. empty required field). */\n disableConfirm?: boolean;\n}\n\n/**\n * Generic action confirmation dialog.\n * Use `labels` to customise title, description and button text.\n * `labels.description` accepts a string or any ReactNode (e.g. JSX with <strong>).\n *\n * Pass `children` to render additional body content (e.g. a Textarea) between the\n * description and the footer. Use `disableConfirm` to conditionally disable the confirm\n * button (e.g. when a required field is empty).\n *\n * For delete confirmations, prefer `ConfirmDeleteDialog` instead.\n */\nexport function ConfirmActionDialog({\n open,\n onOpenChange,\n onConfirm,\n isLoading = false,\n labels,\n icon,\n confirmVariant = \"default\",\n children,\n disableConfirm,\n}: ConfirmActionDialogProps) {\n const description = labels.description ?? \"Are you sure you want to continue?\";\n const btnCancel = labels.btnCancel ?? \"Cancel\";\n const btnConfirm = labels.btnConfirm ?? \"Confirm\";\n const btnLoading = labels.btnLoading ?? \"Processing...\";\n\n const handleClose = () => {\n if (!isLoading) onOpenChange(false);\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"xs\" fullWidth role=\"alertdialog\">\n <DialogTitle className=\"flex items-center gap-2\">\n {icon}\n {labels.title}\n </DialogTitle>\n <DialogContent>\n {typeof description === \"string\" ? (\n <DialogContentText>{description}</DialogContentText>\n ) : (\n <DialogContentText component=\"div\">{description}</DialogContentText>\n )}\n {children}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={isLoading}>\n {btnCancel}\n </Button>\n <Button\n variant=\"contained\"\n color={confirmVariant === \"destructive\" ? \"error\" : \"primary\"}\n onClick={onConfirm}\n disabled={isLoading || disableConfirm}\n >\n {isLoading ? (\n <>\n <CircularProgress size={16} color=\"inherit\" className=\"mr-2\" />\n {btnLoading}\n </>\n ) : (\n btnConfirm\n )}\n </Button>\n </DialogActions>\n </Dialog>\n );\n}\n","import { NextureIconsProps, sizeHelper, strokeSizeHelper } from \"../nexture-icons\";\n\nexport default function NiBinEmpty({ className, variant = \"outlined\", size = \"medium\" }: NextureIconsProps) {\n const iconSize = sizeHelper(size);\n const iconStrokeWidth = strokeSizeHelper(iconSize);\n if (variant === \"outlined\") {\n return (\n <svg\n width={iconSize}\n height={iconSize}\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6 6L5.48806 9.58357C5.16413 11.8511 5.14395 14.1516 5.42806 16.4245L5.51601 17.1281C5.80316 19.4253 7.56538 21.2609 9.84894 21.6415V21.6415C11.2732 21.8789 12.7268 21.8789 14.1511 21.6415V21.6415C16.4346 21.2609 18.1968 19.4253 18.484 17.1281L18.5719 16.4245C18.856 14.1516 18.8359 11.8511 18.5119 9.58357L18 6\"\n stroke=\"currentColor\"\n strokeWidth={iconStrokeWidth}\n strokeLinecap=\"round\"\n />\n <path\n d=\"M15 5L14.9062 4.43717C14.7408 3.4451 14.6582 2.94906 14.3711 2.60286C14.2462 2.45218 14.0957 2.32469 13.9265 2.22623C13.5378 2 13.035 2 12.0292 2L11.9708 2C10.965 2 10.4622 2 10.0735 2.22623C9.90431 2.32469 9.75381 2.45219 9.62888 2.60286C9.34182 2.94906 9.25915 3.4451 9.09381 4.43717L9 5\"\n stroke=\"currentColor\"\n strokeWidth={iconStrokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M20 6L18.2017 5.77522C14.0833 5.26041 9.91673 5.26041 5.79826 5.77522L4 6\"\n stroke=\"currentColor\"\n strokeWidth={iconStrokeWidth}\n strokeLinecap=\"round\"\n />\n </svg>\n );\n } else {\n return (\n <svg\n width={iconSize}\n height={iconSize}\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M9.74018 5.12304C9.6721 5.53152 9.28536 5.80813 8.8769 5.74023C8.46843 5.67215 8.19181 5.28541 8.25971 4.87695L8.35444 4.31347C8.43472 3.83178 8.50246 3.41913 8.59077 3.08593C8.68246 2.74003 8.81179 2.41337 9.0517 2.12402C9.23282 1.90562 9.45102 1.72085 9.69623 1.57812C10.0211 1.38906 10.3644 1.31483 10.7206 1.28125C11.0639 1.24892 11.4822 1.25 11.9706 1.25L12.0292 1.25C12.5177 1.25 12.936 1.24892 13.2792 1.28125C13.6355 1.31483 13.9788 1.38906 14.3037 1.57812C14.5489 1.72085 14.7671 1.90562 14.9482 2.12402C15.1881 2.41337 15.3174 2.74003 15.4091 3.08593C15.4974 3.41913 15.5652 3.83177 15.6455 4.31347L15.7402 4.87695L15.749 4.95312C15.7732 5.33241 15.506 5.6764 15.123 5.74023C14.74 5.80389 14.3763 5.56494 14.2763 5.19824L14.2597 5.12304L14.166 4.56054C14.081 4.05049 14.025 3.71896 13.9589 3.46972C13.8964 3.23378 13.8409 3.13889 13.7939 3.08203C13.7252 2.99916 13.6418 2.92817 13.5488 2.87402C13.4849 2.83695 13.3818 2.79831 13.1386 2.77539C12.8819 2.75121 12.5462 2.75 12.0292 2.75L11.9706 2.75C11.4537 2.75 11.1179 2.75121 10.8613 2.77539C10.6181 2.79831 10.515 2.83695 10.4511 2.87402C10.3581 2.92817 10.2747 2.99916 10.206 3.08203C10.1589 3.13889 10.1035 3.23378 10.041 3.46972C9.97489 3.71896 9.91894 4.05049 9.83393 4.56054L9.74018 5.12304Z\"\n fill=\"currentColor\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M5.94819 5.00114C9.96612 4.51861 14.0279 4.51807 18.0459 5.00016C18.1288 5.01011 18.212 5.02008 18.2949 5.03043L20.0927 5.25504L20.1689 5.26872C20.5391 5.35382 20.792 5.70788 20.7441 6.09293C20.6958 6.47814 20.3633 6.75806 19.9834 6.74918L19.9072 6.7443L18.8447 6.61051L19.2548 9.4777C19.5881 11.8107 19.6086 14.1783 19.3164 16.5168L19.2285 17.2209C18.9001 19.8471 16.8851 21.9459 14.2744 22.381C12.7685 22.632 11.2314 22.632 9.72554 22.381C7.11486 21.9458 5.09978 19.8471 4.77144 17.2209L4.68355 16.5168C4.39132 14.1783 4.41185 11.8107 4.74507 9.4777L5.15425 6.61051L4.09273 6.7443L4.01655 6.74918C3.63657 6.75805 3.30414 6.47813 3.25581 6.09293C3.20471 5.68211 3.49633 5.30642 3.90718 5.25504L5.70503 5.03043C5.78598 5.02032 5.86721 5.01086 5.94819 5.00114Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n }\n}\n","import NiAI from \"./nexture/ni-ai\";\nimport NiAirBalloon from \"./nexture/ni-air-balloon\";\nimport NiAnchor from \"./nexture/ni-anchor\";\nimport NiAnnouncement from \"./nexture/ni-announcement\";\nimport NiAntenna from \"./nexture/ni-antenna\";\nimport NiArchive from \"./nexture/ni-archive\";\nimport NiArchiveCheck from \"./nexture/ni-archive-check\";\nimport NiArrowCircleLeft from \"./nexture/ni-arrow-circle-left\";\nimport NiArrowCircleRight from \"./nexture/ni-arrow-circle-right\";\nimport NiArrowDown from \"./nexture/ni-arrow-down\";\nimport NiArrowDownLeft from \"./nexture/ni-arrow-down-left\";\nimport NiArrowDownLeftSquare from \"./nexture/ni-arrow-down-left-square\";\nimport NiArrowDownRight from \"./nexture/ni-arrow-down-right\";\nimport NiArrowDownRightSquare from \"./nexture/ni-arrow-down-right-square\";\nimport NiArrowDownSquare from \"./nexture/ni-arrow-down-square\";\nimport NiArrowHistory from \"./nexture/ni-arrow-history\";\nimport NiArrowInDown from \"./nexture/ni-arrow-in-down\";\nimport NiArrowInLeft from \"./nexture/ni-arrow-in-left\";\nimport NiArrowInRight from \"./nexture/ni-arrow-in-right\";\nimport NiArrowInUp from \"./nexture/ni-arrow-in-up\";\nimport NiArrowLeft from \"./nexture/ni-arrow-left\";\nimport NiArrowLeftRight from \"./nexture/ni-arrow-left-right\";\nimport NiArrowLeftSquare from \"./nexture/ni-arrow-left-square\";\nimport NiArrowOutDown from \"./nexture/ni-arrow-out-down\";\nimport NiArrowOutLeft from \"./nexture/ni-arrow-out-left\";\nimport NiArrowOutRight from \"./nexture/ni-arrow-out-right\";\nimport NiArrowOutUp from \"./nexture/ni-arrow-out-up\";\nimport NiArrowRight from \"./nexture/ni-arrow-right\";\nimport NiArrowRightSquare from \"./nexture/ni-arrow-right-square\";\nimport NiArrowUp from \"./nexture/ni-arrow-up\";\nimport NiArrowUpDown from \"./nexture/ni-arrow-up-down\";\nimport NiArrowUpLeft from \"./nexture/ni-arrow-up-left\";\nimport NiArrowUpLeftSquare from \"./nexture/ni-arrow-up-left-square\";\nimport NiArrowUpRight from \"./nexture/ni-arrow-up-right\";\nimport NiArrowUpRightSquare from \"./nexture/ni-arrow-up-right-square\";\nimport NiArrowUpSquare from \"./nexture/ni-arrow-up-square\";\nimport NiAt from \"./nexture/ni-at\";\nimport NiBadge from \"./nexture/ni-badge\";\nimport NiBadgeCheck from \"./nexture/ni-badge-check\";\nimport NiBag from \"./nexture/ni-bag\";\nimport NiBandAid from \"./nexture/ni-band-aid\";\nimport NiBarcode from \"./nexture/ni-barcode\";\nimport NiBasket from \"./nexture/ni-basket\";\nimport NiBatteryCharging from \"./nexture/ni-battery-charging\";\nimport NiBatteryEmpty from \"./nexture/ni-battery-empty\";\nimport NiBatteryFull from \"./nexture/ni-battery-full\";\nimport NiBell from \"./nexture/ni-bell\";\nimport NiBellInactive from \"./nexture/ni-bell-inactive\";\nimport NiBinEmpty from \"./nexture/ni-bin-empty\";\nimport NiBinFull from \"./nexture/ni-bin-full\";\nimport NiBloodCells from \"./nexture/ni-blood-cells\";\nimport NiBluetooth from \"./nexture/ni-bluetooth\";\nimport NiBook from \"./nexture/ni-book\";\nimport NiBookmark from \"./nexture/ni-bookmark\";\nimport NiBookmarkSingle from \"./nexture/ni-bookmark-single\";\nimport NiBraces from \"./nexture/ni-braces\";\nimport NiBrackets from \"./nexture/ni-brackets\";\nimport NiBrain from \"./nexture/ni-brain\";\nimport NiBrainCircuit from \"./nexture/ni-brain-circuit\";\nimport NiBriefcase from \"./nexture/ni-briefcase\";\nimport NiBrush from \"./nexture/ni-brush\";\nimport NiBrushArt from \"./nexture/ni-brush-art\";\nimport NiBrushArtSquare from \"./nexture/ni-brush-art-square\";\nimport NiBug from \"./nexture/ni-bug\";\nimport NiBuilding from \"./nexture/ni-building\";\nimport NiBulbOff from \"./nexture/ni-bulb-off\";\nimport NiBulbOn from \"./nexture/ni-bulb-on\";\nimport NiButton from \"./nexture/ni-button\";\nimport NiButtonGroup from \"./nexture/ni-button-group\";\nimport NiButtonLarge from \"./nexture/ni-button-large\";\nimport NiCake from \"./nexture/ni-cake\";\nimport NiCalendar from \"./nexture/ni-calendar\";\nimport NiCalendarClock from \"./nexture/ni-calendar-clock\";\nimport NiCamera from \"./nexture/ni-camera\";\nimport NiCar from \"./nexture/ni-car\";\nimport NiCartArrow from \"./nexture/ni-cart-arrow\";\nimport NiCartCross from \"./nexture/ni-cart-cross\";\nimport NiCartEmpty from \"./nexture/ni-cart-empty\";\nimport NiCartMinus from \"./nexture/ni-cart-minus\";\nimport NiCartPlus from \"./nexture/ni-cart-plus\";\nimport NiCatalog from \"./nexture/ni-catalog\";\nimport NiCells from \"./nexture/ni-cells\";\nimport NiCellsPlus from \"./nexture/ni-cells-plus\";\nimport NiChange from \"./nexture/ni-change\";\nimport NiChartBar from \"./nexture/ni-chart-bar\";\nimport NiChartCandleSticks from \"./nexture/ni-chart-candle-sticks\";\nimport NiChartFunnel from \"./nexture/ni-chart-funnel\";\nimport NiChartHeatmap from \"./nexture/ni-chart-heatmap\";\nimport NiChartLine from \"./nexture/ni-chart-line\";\nimport NiChartLineBar from \"./nexture/ni-chart-line-bar\";\nimport NiChartPie from \"./nexture/ni-chart-pie\";\nimport NiChartPolar from \"./nexture/ni-chart-polar\";\nimport NiChartRadar from \"./nexture/ni-chart-radar\";\nimport NiChartScatter from \"./nexture/ni-chart-scatter\";\nimport NiCheck from \"./nexture/ni-check\";\nimport NiCheckFull from \"./nexture/ni-check-full\";\nimport NiCheckSquare from \"./nexture/ni-check-square\";\nimport NiChef from \"./nexture/ni-chef\";\nimport NiChevronDown from \"./nexture/ni-chevron-down\";\nimport NiChevronDownSmall from \"./nexture/ni-chevron-down-small\";\nimport NiChevronLeft from \"./nexture/ni-chevron-left\";\nimport NiChevronLeftRightReverseSmall from \"./nexture/ni-chevron-left-right-reverse-small\";\nimport NiChevronLeftRightSmall from \"./nexture/ni-chevron-left-right-small\";\nimport NiChevronLeftSmall from \"./nexture/ni-chevron-left-small\";\nimport NiChevronRight from \"./nexture/ni-chevron-right\";\nimport NiChevronRightSmall from \"./nexture/ni-chevron-right-small\";\nimport NiChevronUp from \"./nexture/ni-chevron-up\";\nimport NiChevronUpDownReverseSmall from \"./nexture/ni-chevron-up-down-reverse-small\";\nimport NiChevronUpDownSmall from \"./nexture/ni-chevron-up-down-small\";\nimport NiChevronUpSmall from \"./nexture/ni-chevron-up-small\";\nimport NiCholesterol from \"./nexture/ni-cholesterol\";\nimport NiCircle from \"./nexture/ni-circle\";\nimport NiClipboard from \"./nexture/ni-clipboard\";\nimport NiClock from \"./nexture/ni-clock\";\nimport NiCloud from \"./nexture/ni-cloud\";\nimport NiCloudPartly from \"./nexture/ni-cloud-partly\";\nimport NiCloudRain from \"./nexture/ni-cloud-rain\";\nimport NiCloudSnow from \"./nexture/ni-cloud-snow\";\nimport NiCloudThunder from \"./nexture/ni-cloud-thunder\";\nimport NiCode from \"./nexture/ni-code\";\nimport NiCoffee from \"./nexture/ni-coffee\";\nimport NiCoin from \"./nexture/ni-coin\";\nimport NiCollapse from \"./nexture/ni-collapse\";\nimport NiCollapseIn from \"./nexture/ni-collapse-in\";\nimport NiCols from \"./nexture/ni-cols\";\nimport NiCompass from \"./nexture/ni-compass\";\nimport NiController from \"./nexture/ni-controller\";\nimport NiCopyright from \"./nexture/ni-copyright\";\nimport NiCpu from \"./nexture/ni-cpu\";\nimport NiCreditCard from \"./nexture/ni-credit-card\";\nimport NiCrop from \"./nexture/ni-crop\";\nimport NiCross from \"./nexture/ni-cross\";\nimport NiCrossFull from \"./nexture/ni-cross-full\";\nimport NiCrossHexagon from \"./nexture/ni-cross-hexagon\";\nimport NiCrossSquare from \"./nexture/ni-cross-square\";\nimport NiCrosshair from \"./nexture/ni-crosshair\";\nimport NiCrown from \"./nexture/ni-crown\";\nimport NiCursor from \"./nexture/ni-cursor\";\nimport NiDashboard from \"./nexture/ni-dashboard\";\nimport NiDatabase from \"./nexture/ni-database\";\nimport NiDevops from \"./nexture/ni-devops\";\nimport NiDiagram from \"./nexture/ni-diagram\";\nimport NiDice from \"./nexture/ni-dice\";\nimport NiDirectory from \"./nexture/ni-directory\";\nimport NiDocumentArchive from \"./nexture/ni-document-archive\";\nimport NiDocumentChart from \"./nexture/ni-document-chart\";\nimport NiDocumentCheck from \"./nexture/ni-document-check\";\nimport NiDocumentCode from \"./nexture/ni-document-code\";\nimport NiDocumentCross from \"./nexture/ni-document-cross\";\nimport NiDocumentFull from \"./nexture/ni-document-full\";\nimport NiDocumentImage from \"./nexture/ni-document-image\";\nimport NiDocumentMinus from \"./nexture/ni-document-minus\";\nimport NiDocumentNumber from \"./nexture/ni-document-number\";\nimport NiDocumentPlus from \"./nexture/ni-document-plus\";\nimport NiDocumentVideo from \"./nexture/ni-document-video\";\nimport NiDollar from \"./nexture/ni-dollar\";\nimport NiDollarSquare from \"./nexture/ni-dollar-square\";\nimport NiDotsSquare from \"./nexture/ni-dots-square\";\nimport NiDownloadCloud from \"./nexture/ni-download-cloud\";\nimport NiDragHorizontal from \"./nexture/ni-drag-horizontal\";\nimport NiDragVertical from \"./nexture/ni-drag-vertical\";\nimport NiDrink from \"./nexture/ni-drink\";\nimport NiDrop from \"./nexture/ni-drop\";\nimport NiDuplicate from \"./nexture/ni-duplicate\";\nimport NiEllipsisHorizontal from \"./nexture/ni-ellipsis-horizontal\";\nimport NiEllipsisVertical from \"./nexture/ni-ellipsis-vertical\";\nimport NiEmail from \"./nexture/ni-email\";\nimport NiEmailOpen from \"./nexture/ni-email-open\";\nimport NiEndDownSmall from \"./nexture/ni-end-down-small\";\nimport NiEndLeftSmall from \"./nexture/ni-end-left-small\";\nimport NiEndRightSmall from \"./nexture/ni-end-right-small\";\nimport NiEndUpSmall from \"./nexture/ni-end-up-small\";\nimport NiEnterDown from \"./nexture/ni-enter-down\";\nimport NiEnterLeft from \"./nexture/ni-enter-left\";\nimport NiEnterReverseDown from \"./nexture/ni-enter-reverse-down\";\nimport NiEnterReverseLeft from \"./nexture/ni-enter-reverse-left\";\nimport NiEnterReverseRight from \"./nexture/ni-enter-reverse-right\";\nimport NiEnterReverseUp from \"./nexture/ni-enter-reverse-up\";\nimport NiEnterRight from \"./nexture/ni-enter-right\";\nimport NiEnterUp from \"./nexture/ni-enter-up\";\nimport NiEquals from \"./nexture/ni-equals\";\nimport NiEqualsFull from \"./nexture/ni-equals-full\";\nimport NiEraser from \"./nexture/ni-eraser\";\nimport NiEuro from \"./nexture/ni-euro\";\nimport NiEuroSquare from \"./nexture/ni-euro-square\";\nimport NiExclamationHexagon from \"./nexture/ni-exclamation-hexagon\";\nimport NiExclamationSquare from \"./nexture/ni-exclamation-square\";\nimport NiExpand from \"./nexture/ni-expand\";\nimport NiExpandFull from \"./nexture/ni-expand-full\";\nimport NiExpandOut from \"./nexture/ni-expand-out\";\nimport NiExpandSquare from \"./nexture/ni-expand-square\";\nimport NiExternal from \"./nexture/ni-external\";\nimport NiEyeClose from \"./nexture/ni-eye-close\";\nimport NiEyeInactive from \"./nexture/ni-eye-inactive\";\nimport NiEyeOpen from \"./nexture/ni-eye-open\";\nimport NiFaceFrown from \"./nexture/ni-face-frown\";\nimport NiFaceFrownMore from \"./nexture/ni-face-frown-more\";\nimport NiFaceNeutral from \"./nexture/ni-face-neutral\";\nimport NiFaceSmile from \"./nexture/ni-face-smile\";\nimport NiFaceSmileMore from \"./nexture/ni-face-smile-more\";\nimport NiFemale from \"./nexture/ni-female\";\nimport NiFilter from \"./nexture/ni-filter\";\nimport NiFilterCross from \"./nexture/ni-filter-cross\";\nimport NiFilterMinus from \"./nexture/ni-filter-minus\";\nimport NiFilterPlus from \"./nexture/ni-filter-plus\";\nimport NiFingerprint from \"./nexture/ni-fingerprint\";\nimport NiFire from \"./nexture/ni-fire\";\nimport NiFirstAid from \"./nexture/ni-first-aid\";\nimport NiFitness from \"./nexture/ni-fitness\";\nimport NiFlag from \"./nexture/ni-flag\";\nimport NiFlash from \"./nexture/ni-flash\";\nimport NiFlask from \"./nexture/ni-flask\";\nimport NiFloppyDisk from \"./nexture/ni-floppy-disk\";\nimport NiFolder from \"./nexture/ni-folder\";\nimport NiFolderCheck from \"./nexture/ni-folder-check\";\nimport NiFolderCross from \"./nexture/ni-folder-cross\";\nimport NiFolderMinus from \"./nexture/ni-folder-minus\";\nimport NiFolderPlus from \"./nexture/ni-folder-plus\";\nimport NiForwardDownSmall from \"./nexture/ni-forward-down-small\";\nimport NiForwardLeftSmall from \"./nexture/ni-forward-left-small\";\nimport NiForwardRightSmall from \"./nexture/ni-forward-right-small\";\nimport NiForwardUpSmall from \"./nexture/ni-forward-up-small\";\nimport NiGay from \"./nexture/ni-gay\";\nimport NiGerm from \"./nexture/ni-germ\";\nimport NiGogo from \"./nexture/ni-gogo\";\nimport NiGold from \"./nexture/ni-gold\";\nimport NiGpu from \"./nexture/ni-gpu\";\nimport NiGraduation from \"./nexture/ni-graduation\";\nimport NiGroup from \"./nexture/ni-group\";\nimport NiHeadphones from \"./nexture/ni-headphones\";\nimport NiHeadset from \"./nexture/ni-headset\";\nimport NiHeadsetMic from \"./nexture/ni-headset-mic\";\nimport NiHealth from \"./nexture/ni-health\";\nimport NiHeart from \"./nexture/ni-heart\";\nimport NiHeartRate from \"./nexture/ni-heart-rate\";\nimport NiHearts from \"./nexture/ni-hearts\";\nimport NiHome from \"./nexture/ni-home\";\nimport NiInbox from \"./nexture/ni-inbox\";\nimport NiInfoSquare from \"./nexture/ni-info-square\";\nimport NiInjection from \"./nexture/ni-injection\";\nimport NiInput from \"./nexture/ni-input\";\nimport NiIntegration from \"./nexture/ni-integration\";\nimport NiInternal from \"./nexture/ni-internal\";\nimport NiIv from \"./nexture/ni-iv\";\nimport NiJoin from \"./nexture/ni-join\";\nimport NiKey from \"./nexture/ni-key\";\nimport NiKeyboard from \"./nexture/ni-keyboard\";\nimport NiKnobs from \"./nexture/ni-knobs\";\nimport NiLaptop from \"./nexture/ni-laptop\";\nimport NiLaw from \"./nexture/ni-law\";\nimport NiLayout from \"./nexture/ni-layout\";\nimport NiLike from \"./nexture/ni-like\";\nimport NiLink from \"./nexture/ni-link\";\nimport NiLinkBroken from \"./nexture/ni-link-broken\";\nimport NiList from \"./nexture/ni-list\";\nimport NiListCheck from \"./nexture/ni-list-check\";\nimport NiListChevronDown from \"./nexture/ni-list-chevron-down\";\nimport NiListCircle from \"./nexture/ni-list-circle\";\nimport NiListCross from \"./nexture/ni-list-cross\";\nimport NiListNumber from \"./nexture/ni-list-number\";\nimport NiListSquare from \"./nexture/ni-list-square\";\nimport NiLoader from \"./nexture/ni-loader\";\nimport NiLock from \"./nexture/ni-lock\";\nimport NiLuggage from \"./nexture/ni-luggage\";\nimport NiLungs from \"./nexture/ni-lungs\";\nimport NiMagicWand from \"./nexture/ni-magic-wand\";\nimport NiMale from \"./nexture/ni-male\";\nimport NiMap from \"./nexture/ni-map\";\nimport NiMasonary from \"./nexture/ni-masonary\";\nimport NiMedal from \"./nexture/ni-medal\";\nimport NiMenu from \"./nexture/ni-menu\";\nimport NiMenuLeft from \"./nexture/ni-menu-left\";\nimport NiMenuRight from \"./nexture/ni-menu-right\";\nimport NiMenuSplit from \"./nexture/ni-menu-split\";\nimport NiMenuSplitDot from \"./nexture/ni-menu-split-dot\";\nimport NiMenuSplitDotReverse from \"./nexture/ni-menu-split-dot-reverse\";\nimport NiMenuSplitReverse from \"./nexture/ni-menu-split-reverse\";\nimport NiMessage from \"./nexture/ni-message\";\nimport NiMessageCheck from \"./nexture/ni-message-check\";\nimport NiMessageCross from \"./nexture/ni-message-cross\";\nimport NiMessageDots from \"./nexture/ni-message-dots\";\nimport NiMessageFilled from \"./nexture/ni-message-filled\";\nimport NiMessageGrammar from \"./nexture/ni-message-grammar\";\nimport NiMessagePlus from \"./nexture/ni-message-plus\";\nimport NiMessages from \"./nexture/ni-messages\";\nimport NiMicrophone from \"./nexture/ni-microphone\";\nimport NiMinus from \"./nexture/ni-minus\";\nimport NiMinusFull from \"./nexture/ni-minus-full\";\nimport NiMinusSquare from \"./nexture/ni-minus-square\";\nimport NiMoney from \"./nexture/ni-money\";\nimport NiMoneyBag from \"./nexture/ni-money-bag\";\nimport NiMoon from \"./nexture/ni-moon\";\nimport NiMountain from \"./nexture/ni-mountain\";\nimport NiMouse from \"./nexture/ni-mouse\";\nimport NiMove from \"./nexture/ni-move\";\nimport NiMusic from \"./nexture/ni-music\";\nimport NiNetwork from \"./nexture/ni-network\";\nimport NiNext from \"./nexture/ni-next\";\nimport NiOxygen from \"./nexture/ni-oxygen\";\nimport NiPaintBucket from \"./nexture/ni-paint-bucket\";\nimport NiPaintRoller from \"./nexture/ni-paint-roller\";\nimport NiPalette from \"./nexture/ni-palette\";\nimport NiPaperclip from \"./nexture/ni-paperclip\";\nimport NiParentheses from \"./nexture/ni-parentheses\";\nimport NiPath from \"./nexture/ni-path\";\nimport NiPause from \"./nexture/ni-pause\";\nimport NiPen from \"./nexture/ni-pen\";\nimport NiPenSquare from \"./nexture/ni-pen-square\";\nimport NiPercent from \"./nexture/ni-percent\";\nimport NiPhone from \"./nexture/ni-phone\";\nimport NiPhoneHandset from \"./nexture/ni-phone-handset\";\nimport NiPhoneHandsetCheck from \"./nexture/ni-phone-handset-check\";\nimport NiPhoneHandsetOff from \"./nexture/ni-phone-handset-off\";\nimport NiPhoneHandsetOn from \"./nexture/ni-phone-handset-on\";\nimport NiPin from \"./nexture/ni-pin\";\nimport NiPinCheck from \"./nexture/ni-pin-check\";\nimport NiPinCross from \"./nexture/ni-pin-cross\";\nimport NiPinPlus from \"./nexture/ni-pin-plus\";\nimport NiPine from \"./nexture/ni-pine\";\nimport NiPivot from \"./nexture/ni-pivot\";\nimport NiPlane from \"./nexture/ni-plane\";\nimport NiPlay from \"./nexture/ni-play\";\nimport NiPlug from \"./nexture/ni-plug\";\nimport NiPlus from \"./nexture/ni-plus\";\nimport NiPlusFull from \"./nexture/ni-plus-full\";\nimport NiPlusSquare from \"./nexture/ni-plus-square\";\nimport NiPolitics from \"./nexture/ni-politics\";\nimport NiPound from \"./nexture/ni-pound\";\nimport NiPoundSquare from \"./nexture/ni-pound-square\";\nimport NiPower from \"./nexture/ni-power\";\nimport NiPresentation from \"./nexture/ni-presentation\";\nimport NiPrevious from \"./nexture/ni-previous\";\nimport NiPrinter from \"./nexture/ni-printer\";\nimport NiProgress from \"./nexture/ni-progress\";\nimport NiPullRequestClosed from \"./nexture/ni-pull-request-closed\";\nimport NiPullRequestDraft from \"./nexture/ni-pull-request-draft\";\nimport NiPullRequestMerged from \"./nexture/ni-pull-request-merged\";\nimport NiPullRequestOpen from \"./nexture/ni-pull-request-open\";\nimport NiPulse from \"./nexture/ni-pulse\";\nimport NiPushPin from \"./nexture/ni-push-pin\";\nimport NiPushPinLeft from \"./nexture/ni-push-pin-left\";\nimport NiPushPinRight from \"./nexture/ni-push-pin-right\";\nimport NiPuzzle from \"./nexture/ni-puzzle\";\nimport NiQuestionHexagon from \"./nexture/ni-question-hexagon\";\nimport NiRadio from \"./nexture/ni-radio\";\nimport NiRankFour from \"./nexture/ni-rank-four\";\nimport NiRankOne from \"./nexture/ni-rank-one\";\nimport NiRankThree from \"./nexture/ni-rank-three\";\nimport NiRankTwo from \"./nexture/ni-rank-two\";\nimport NiReceipt from \"./nexture/ni-receipt\";\nimport NiRecord from \"./nexture/ni-record\";\nimport NiRefresh from \"./nexture/ni-refresh\";\nimport NiReligion from \"./nexture/ni-religion\";\nimport NiResearch from \"./nexture/ni-research\";\nimport NiRevenue from \"./nexture/ni-revenue\";\nimport NiReverseLeft from \"./nexture/ni-reverse-left\";\nimport NiReverseRight from \"./nexture/ni-reverse-right\";\nimport NiRobot from \"./nexture/ni-robot\";\nimport NiRocket from \"./nexture/ni-rocket\";\nimport NiRouter from \"./nexture/ni-router\";\nimport NiRows from \"./nexture/ni-rows\";\nimport NiSafe from \"./nexture/ni-safe\";\nimport NiScale from \"./nexture/ni-scale\";\nimport NiScalpel from \"./nexture/ni-scalpel\";\nimport NiScissors from \"./nexture/ni-scissors\";\nimport NiScreen from \"./nexture/ni-screen\";\nimport NiScriptSub from \"./nexture/ni-script-sub\";\nimport NiScriptSuper from \"./nexture/ni-script-super\";\nimport NiSdCard from \"./nexture/ni-sd-card\";\nimport NiSearch from \"./nexture/ni-search\";\nimport NiSelect from \"./nexture/ni-select\";\nimport NiSendDown from \"./nexture/ni-send-down\";\nimport NiSendDownLeft from \"./nexture/ni-send-down-left\";\nimport NiSendDownRight from \"./nexture/ni-send-down-right\";\nimport NiSendLeft from \"./nexture/ni-send-left\";\nimport NiSendRight from \"./nexture/ni-send-right\";\nimport NiSendUp from \"./nexture/ni-send-up\";\nimport NiSendUpLeft from \"./nexture/ni-send-up-left\";\nimport NiSendUpRight from \"./nexture/ni-send-up-right\";\nimport NiServer from \"./nexture/ni-server\";\nimport NiSettings from \"./nexture/ni-settings\";\nimport NiShare from \"./nexture/ni-share\";\nimport NiShield from \"./nexture/ni-shield\";\nimport NiShieldCheck from \"./nexture/ni-shield-check\";\nimport NiShieldCross from \"./nexture/ni-shield-cross\";\nimport NiShrinkFull from \"./nexture/ni-shrink-full\";\nimport NiShrinkSquare from \"./nexture/ni-shrink-square\";\nimport NiShuffle from \"./nexture/ni-shuffle\";\nimport NiSign from \"./nexture/ni-sign\";\nimport NiSignalLeftRight from \"./nexture/ni-signal-left-right\";\nimport NiSignalRight from \"./nexture/ni-signal-right\";\nimport NiSignalUp from \"./nexture/ni-signal-up\";\nimport NiSigns from \"./nexture/ni-signs\";\nimport NiSlashHexagon from \"./nexture/ni-slash-hexagon\";\nimport NiSlider from \"./nexture/ni-slider\";\nimport NiSnow from \"./nexture/ni-snow\";\nimport NiSoundCross from \"./nexture/ni-sound-cross\";\nimport NiSoundOff from \"./nexture/ni-sound-off\";\nimport NiSoundOn from \"./nexture/ni-sound-on\";\nimport NiSoundPlus from \"./nexture/ni-sound-plus\";\nimport NiSparkle from \"./nexture/ni-sparkle\";\nimport NiSpinner from \"./nexture/ni-spinner\";\nimport NiSquare from \"./nexture/ni-square\";\nimport NiSquircle from \"./nexture/ni-squircle\";\nimport NiStar from \"./nexture/ni-star\";\nimport NiStars from \"./nexture/ni-stars\";\nimport NiStomach from \"./nexture/ni-stomach\";\nimport NiStopwatch from \"./nexture/ni-stopwatch\";\nimport NiStore from \"./nexture/ni-store\";\nimport NiStructure from \"./nexture/ni-structure\";\nimport NiSum from \"./nexture/ni-sum\";\nimport NiSun from \"./nexture/ni-sun\";\nimport NiSwap from \"./nexture/ni-swap\";\nimport NiSwitch from \"./nexture/ni-switch\";\nimport NiTablet from \"./nexture/ni-tablet\";\nimport NiTag from \"./nexture/ni-tag\";\nimport NiTelescope from \"./nexture/ni-telescope\";\nimport NiTemperature from \"./nexture/ni-temperature\";\nimport NiTent from \"./nexture/ni-tent\";\nimport NiTerminal from \"./nexture/ni-terminal\";\nimport NiTextBold from \"./nexture/ni-text-bold\";\nimport NiTextCenter from \"./nexture/ni-text-center\";\nimport NiTextFont from \"./nexture/ni-text-font\";\nimport NiTextItalic from \"./nexture/ni-text-italic\";\nimport NiTextJustify from \"./nexture/ni-text-justify\";\nimport NiTextLeft from \"./nexture/ni-text-left\";\nimport NiTextQuote from \"./nexture/ni-text-quote\";\nimport NiTextRight from \"./nexture/ni-text-right\";\nimport NiTextStrikethrough from \"./nexture/ni-text-strikethrough\";\nimport NiTextUnderline from \"./nexture/ni-text-underline\";\nimport NiTextarea from \"./nexture/ni-textarea\";\nimport NiTicket from \"./nexture/ni-ticket\";\nimport NiTimeline from \"./nexture/ni-timeline\";\nimport NiTooth from \"./nexture/ni-tooth\";\nimport NiToyBoat from \"./nexture/ni-toy-boat\";\nimport NiToySky from \"./nexture/ni-toy-sky\";\nimport NiToyStacking from \"./nexture/ni-toy-stacking\";\nimport NiTrade from \"./nexture/ni-trade\";\nimport NiTree from \"./nexture/ni-tree\";\nimport NiTrendDown from \"./nexture/ni-trend-down\";\nimport NiTrendUp from \"./nexture/ni-trend-up\";\nimport NiTriangleDown from \"./nexture/ni-triangle-down\";\nimport NiTriangleLeft from \"./nexture/ni-triangle-left\";\nimport NiTriangleRight from \"./nexture/ni-triangle-right\";\nimport NiTriangleUp from \"./nexture/ni-triangle-up\";\nimport NiTrophy from \"./nexture/ni-trophy\";\nimport NiTruck from \"./nexture/ni-truck\";\nimport NiTubes from \"./nexture/ni-tubes\";\nimport NiUngroup from \"./nexture/ni-ungroup\";\nimport NiUnlike from \"./nexture/ni-unlike\";\nimport NiUnlock from \"./nexture/ni-unlock\";\nimport NiUploadCloud from \"./nexture/ni-upload-cloud\";\nimport NiUser from \"./nexture/ni-user\";\nimport NiUserCheck from \"./nexture/ni-user-check\";\nimport NiUserCross from \"./nexture/ni-user-cross\";\nimport NiUserMinus from \"./nexture/ni-user-minus\";\nimport NiUserPlus from \"./nexture/ni-user-plus\";\nimport NiUsers from \"./nexture/ni-users\";\nimport NiVerified from \"./nexture/ni-verified\";\nimport NiWallet from \"./nexture/ni-wallet\";\nimport NiWalletCrypto from \"./nexture/ni-wallet-crypto\";\nimport NiWatch from \"./nexture/ni-watch\";\nimport NiWeightScale from \"./nexture/ni-weight-scale\";\nimport NiWind from \"./nexture/ni-wind\";\nimport NiWorld from \"./nexture/ni-world\";\nimport NiZoomIn from \"./nexture/ni-zoom-in\";\nimport NiZoomOut from \"./nexture/ni-zoom-out\";\n\nexport const IconMap = {\n NiAI,\n NiAirBalloon,\n NiAnchor,\n NiAnnouncement,\n NiAntenna,\n NiArchiveCheck,\n NiArchive,\n NiArrowCircleLeft,\n NiArrowCircleRight,\n NiArrowDownLeftSquare,\n NiArrowDownLeft,\n NiArrowDownRightSquare,\n NiArrowDownRight,\n NiArrowDownSquare,\n NiArrowDown,\n NiArrowHistory,\n NiArrowInDown,\n NiArrowInLeft,\n NiArrowInRight,\n NiArrowInUp,\n NiArrowLeftRight,\n NiArrowLeftSquare,\n NiArrowLeft,\n NiArrowOutDown,\n NiArrowOutLeft,\n NiArrowOutRight,\n NiArrowOutUp,\n NiArrowRightSquare,\n NiArrowRight,\n NiArrowUpDown,\n NiArrowUpLeftSquare,\n NiArrowUpLeft,\n NiArrowUpRightSquare,\n NiArrowUpRight,\n NiArrowUpSquare,\n NiArrowUp,\n NiAt,\n NiBadgeCheck,\n NiBadge,\n NiBag,\n NiBandAid,\n NiBarcode,\n NiBasket,\n NiBatteryCharging,\n NiBatteryEmpty,\n NiBatteryFull,\n NiBellInactive,\n NiBell,\n NiBinEmpty,\n NiBinFull,\n NiBloodCells,\n NiBluetooth,\n NiBook,\n NiBookmarkSingle,\n NiBookmark,\n NiBraces,\n NiBrackets,\n NiBrain,\n NiBrainCircuit,\n NiBriefcase,\n NiBrushArtSquare,\n NiBrushArt,\n NiBrush,\n NiBug,\n NiBuilding,\n NiBulbOff,\n NiBulbOn,\n NiButton,\n NiButtonGroup,\n NiButtonLarge,\n NiCake,\n NiCalendar,\n NiCalendarClock,\n NiCamera,\n NiCar,\n NiCartArrow,\n NiCartCross,\n NiCartEmpty,\n NiCartMinus,\n NiCartPlus,\n NiCatalog,\n NiCellsPlus,\n NiCells,\n NiChange,\n NiChartBar,\n NiChartCandleSticks,\n NiChartFunnel,\n NiChartHeatmap,\n NiChartLineBar,\n NiChartLine,\n NiChartPie,\n NiChartPolar,\n NiChartRadar,\n NiChartScatter,\n NiCheckSquare,\n NiCheck,\n NiCheckFull,\n NiChef,\n NiChevronDownSmall,\n NiChevronDown,\n NiChevronLeftRightReverseSmall,\n NiChevronLeftRightSmall,\n NiChevronLeftSmall,\n NiChevronLeft,\n NiChevronRightSmall,\n NiChevronRight,\n NiChevronUpDownReverseSmall,\n NiChevronUpDownSmall,\n NiChevronUpSmall,\n NiChevronUp,\n NiCholesterol,\n NiCircle,\n NiClipboard,\n NiClock,\n NiCloudPartly,\n NiCloudRain,\n NiCloudSnow,\n NiCloudThunder,\n NiCloud,\n NiCode,\n NiCoffee,\n NiCoin,\n NiCollapse,\n NiCollapseIn,\n NiCols,\n NiCompass,\n NiController,\n NiCopyright,\n NiCpu,\n NiCreditCard,\n NiCrop,\n NiCrossHexagon,\n NiCrossSquare,\n NiCross,\n NiCrossFull,\n NiCrosshair,\n NiCrown,\n NiCursor,\n NiDashboard,\n NiDatabase,\n NiDevops,\n NiDiagram,\n NiDice,\n NiDirectory,\n NiDocumentArchive,\n NiDocumentChart,\n NiDocumentCheck,\n NiDocumentCode,\n NiDocumentCross,\n NiDocumentFull,\n NiDocumentImage,\n NiDocumentMinus,\n NiDocumentNumber,\n NiDocumentPlus,\n NiDocumentVideo,\n NiDollarSquare,\n NiDollar,\n NiDotsSquare,\n NiDownloadCloud,\n NiDragHorizontal,\n NiDragVertical,\n NiDrink,\n NiDrop,\n NiDuplicate,\n NiEllipsisHorizontal,\n NiEllipsisVertical,\n NiEmailOpen,\n NiEmail,\n NiEndDownSmall,\n NiEndLeftSmall,\n NiEndRightSmall,\n NiEndUpSmall,\n NiEnterDown,\n NiEnterLeft,\n NiEnterReverseDown,\n NiEnterReverseLeft,\n NiEnterReverseRight,\n NiEnterReverseUp,\n NiEnterRight,\n NiEnterUp,\n NiEquals,\n NiEqualsFull,\n NiEraser,\n NiEuroSquare,\n NiEuro,\n NiExclamationHexagon,\n NiExclamationSquare,\n NiExpandOut,\n NiExpandSquare,\n NiExpandFull,\n NiExpand,\n NiExternal,\n NiEyeClose,\n NiEyeInactive,\n NiEyeOpen,\n NiFaceFrownMore,\n NiFaceFrown,\n NiFaceNeutral,\n NiFaceSmileMore,\n NiFaceSmile,\n NiFemale,\n NiFilterCross,\n NiFilterMinus,\n NiFilterPlus,\n NiFilter,\n NiFingerprint,\n NiFire,\n NiFirstAid,\n NiFitness,\n NiFlag,\n NiFlash,\n NiFlask,\n NiFloppyDisk,\n NiFolderCheck,\n NiFolderCross,\n NiFolderMinus,\n NiFolderPlus,\n NiFolder,\n NiForwardDownSmall,\n NiForwardLeftSmall,\n NiForwardRightSmall,\n NiForwardUpSmall,\n NiGay,\n NiGerm,\n NiGogo,\n NiGold,\n NiGpu,\n NiGroup,\n NiGraduation,\n NiHeadphones,\n NiHeadset,\n NiHeadsetMic,\n NiHealth,\n NiHeart,\n NiHeartRate,\n NiHearts,\n NiHome,\n NiInbox,\n NiInfoSquare,\n NiInjection,\n NiInput,\n NiIntegration,\n NiInternal,\n NiIv,\n NiJoin,\n NiKey,\n NiKeyboard,\n NiKnobs,\n NiLaptop,\n NiLayout,\n NiLaw,\n NiLike,\n NiLinkBroken,\n NiLink,\n NiListCheck,\n NiListChevronDown,\n NiListCircle,\n NiListCross,\n NiListNumber,\n NiListSquare,\n NiList,\n NiLungs,\n NiLoader,\n NiLock,\n NiLuggage,\n NiMagicWand,\n NiMale,\n NiMap,\n NiMasonary,\n NiMedal,\n NiMenu,\n NiMenuLeft,\n NiMenuRight,\n NiMenuSplitDotReverse,\n NiMenuSplitDot,\n NiMenuSplitReverse,\n NiMenuSplit,\n NiMessageCheck,\n NiMessageCross,\n NiMessageDots,\n NiMessageFilled,\n NiMessageGrammar,\n NiMessagePlus,\n NiMessage,\n NiMessages,\n NiMicrophone,\n NiMinus,\n NiMinusFull,\n NiMinusSquare,\n NiMoneyBag,\n NiMoney,\n NiMoon,\n NiMountain,\n NiMouse,\n NiMove,\n NiMusic,\n NiNetwork,\n NiNext,\n NiOxygen,\n NiPaintBucket,\n NiPaintRoller,\n NiPalette,\n NiPaperclip,\n NiParentheses,\n NiPath,\n NiPause,\n NiPenSquare,\n NiPen,\n NiPercent,\n NiPhoneHandsetCheck,\n NiPhoneHandsetOff,\n NiPhoneHandsetOn,\n NiPhoneHandset,\n NiPhone,\n NiPinCheck,\n NiPinCross,\n NiPinPlus,\n NiPin,\n NiPine,\n NiPivot,\n NiPlane,\n NiPlay,\n NiPlug,\n NiPlusSquare,\n NiPlus,\n NiPlusFull,\n NiPolitics,\n NiPoundSquare,\n NiPound,\n NiPower,\n NiPresentation,\n NiPrevious,\n NiPrinter,\n NiProgress,\n NiPullRequestClosed,\n NiPullRequestDraft,\n NiPullRequestMerged,\n NiPullRequestOpen,\n NiPulse,\n NiPushPin,\n NiPushPinLeft,\n NiPushPinRight,\n NiPuzzle,\n NiQuestionHexagon,\n NiRankOne,\n NiRankTwo,\n NiRankThree,\n NiRankFour,\n NiRadio,\n NiReceipt,\n NiRecord,\n NiRefresh,\n NiReligion,\n NiResearch,\n NiRevenue,\n NiReverseLeft,\n NiReverseRight,\n NiRobot,\n NiRocket,\n NiRouter,\n NiRows,\n NiSafe,\n NiScale,\n NiScalpel,\n NiScissors,\n NiScreen,\n NiScriptSub,\n NiScriptSuper,\n NiSdCard,\n NiSearch,\n NiSelect,\n NiSendDownLeft,\n NiSendDownRight,\n NiSendDown,\n NiSendLeft,\n NiSendRight,\n NiSendUpLeft,\n NiSendUpRight,\n NiSendUp,\n NiServer,\n NiSettings,\n NiShare,\n NiShieldCheck,\n NiShieldCross,\n NiShield,\n NiShrinkSquare,\n NiShrinkFull,\n NiShuffle,\n NiSign,\n NiSignalLeftRight,\n NiSignalRight,\n NiSignalUp,\n NiSigns,\n NiSlashHexagon,\n NiSlider,\n NiSnow,\n NiSoundCross,\n NiSoundOff,\n NiSoundOn,\n NiSoundPlus,\n NiSparkle,\n NiSpinner,\n NiSquare,\n NiSquircle,\n NiStar,\n NiStars,\n NiStopwatch,\n NiStore,\n NiStomach,\n NiStructure,\n NiSum,\n NiSun,\n NiSwap,\n NiSwitch,\n NiTablet,\n NiTag,\n NiTelescope,\n NiTemperature,\n NiTent,\n NiTerminal,\n NiTextBold,\n NiTextCenter,\n NiTextFont,\n NiTextItalic,\n NiTextJustify,\n NiTextLeft,\n NiTextQuote,\n NiTextRight,\n NiTextStrikethrough,\n NiTextUnderline,\n NiTextarea,\n NiTicket,\n NiTimeline,\n NiTooth,\n NiToyBoat,\n NiToySky,\n NiToyStacking,\n NiTrade,\n NiTree,\n NiTrendDown,\n NiTrendUp,\n NiTriangleDown,\n NiTriangleLeft,\n NiTriangleRight,\n NiTriangleUp,\n NiTrophy,\n NiTruck,\n NiTubes,\n NiUngroup,\n NiUnlike,\n NiUnlock,\n NiUploadCloud,\n NiUserCheck,\n NiUserCross,\n NiUserMinus,\n NiUserPlus,\n NiUser,\n NiUsers,\n NiVerified,\n NiWalletCrypto,\n NiWallet,\n NiWatch,\n NiWeightScale,\n NiWind,\n NiWorld,\n NiZoomIn,\n NiZoomOut,\n};\n\nexport type IconName = keyof typeof IconMap;\nexport type IconSize = \"large\" | \"medium\" | \"small\" | \"tiny\" | number;\nexport type IconVariant = \"outlined\" | \"contained\";\n\nexport type NextureIconsProps = {\n variant?: IconVariant;\n className?: string;\n size?: IconSize;\n strokeWidth?: number;\n oneTone?: boolean;\n};\n\nexport type NextureIconsPropsComponent = NextureIconsProps & {\n icon: IconName;\n};\n\nconst NextureIcons: React.FC<NextureIconsPropsComponent> = ({\n icon,\n size = 20,\n variant = \"outlined\",\n className,\n strokeWidth = 1.5,\n oneTone = false,\n}) => {\n const IconComponent = IconMap[icon];\n if (!IconComponent) {\n console.warn(`Icon \"${icon}\" not found in IconMap.`);\n return null;\n }\n return (\n <IconComponent variant={variant} size={size} className={className} strokeWidth={strokeWidth} oneTone={oneTone} />\n );\n};\n\nexport const sizeHelper = (size: NextureIconsProps[\"size\"]) => {\n if (typeof size === \"number\") {\n return size;\n } else if (size === \"large\") {\n return 24;\n } else if (size === \"small\" || size === \"tiny\") {\n return 16;\n } else {\n return 20;\n }\n};\n\nexport const strokeSizeHelper = (size: number) => {\n if (size === 32) {\n return 1.15;\n } else if (size >= 20) {\n return 1.5;\n } else {\n return 1.75;\n }\n};\n\nexport default NextureIcons;\n","import type { ReactNode } from \"react\";\nimport {\n Box,\n Button,\n CircularProgress,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n} from \"../ui\";\nimport { NiBinEmpty } from \"../../icons\";\n\nexport interface ConfirmDeleteLabels {\n title?: string;\n description?: ReactNode;\n btnCancel?: string;\n btnConfirm?: string;\n btnDeleting?: string;\n}\n\ninterface ConfirmDeleteDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void;\n isDeleting: boolean;\n labels?: ConfirmDeleteLabels;\n className?: string;\n}\n\n/**\n * Generic delete confirmation dialog.\n * Use `labels` to customise title, description and button text.\n * `labels.description` accepts a string or any ReactNode (e.g. JSX with <strong>).\n */\nexport function ConfirmDeleteDialog({\n open,\n onOpenChange,\n onConfirm,\n isDeleting,\n labels,\n}: ConfirmDeleteDialogProps) {\n const title = labels?.title ?? \"Delete?\";\n const description = labels?.description ?? \"Are you sure? This action cannot be undone.\";\n const btnCancel = labels?.btnCancel ?? \"Cancel\";\n const btnConfirm = labels?.btnConfirm ?? \"Delete\";\n const btnDeleting = labels?.btnDeleting ?? \"Deleting...\";\n\n const handleClose = () => {\n if (!isDeleting) onOpenChange(false);\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"xs\" fullWidth role=\"alertdialog\">\n <DialogTitle className=\"flex items-center gap-2\">\n <Box component=\"span\" sx={{ color: \"error.main\", display: \"inline-flex\" }}>\n <NiBinEmpty size=\"medium\" />\n </Box>\n {title}\n </DialogTitle>\n <DialogContent>\n {typeof description === \"string\" ? (\n <DialogContentText>{description}</DialogContentText>\n ) : (\n <DialogContentText component=\"div\">{description}</DialogContentText>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={isDeleting}>\n {btnCancel}\n </Button>\n <Button variant=\"contained\" color=\"error\" onClick={onConfirm} disabled={isDeleting}>\n {isDeleting ? (\n <>\n <CircularProgress size={16} color=\"inherit\" className=\"mr-2\" />\n {btnDeleting}\n </>\n ) : (\n btnConfirm\n )}\n </Button>\n </DialogActions>\n </Dialog>\n );\n}\n","/**\n * Host toast bridge — the ergonomic surface a lifted monolith `useToast()`\n * expects, shipped alongside the other shared composites so a plugin's\n * `components/shared/*` (and its `use-toast` alias) resolve here.\n *\n * PlatformReact pages can't import the host's toaster (it's an app-global\n * singleton, not in the host module registry), so these dispatch the\n * `ethisys:toast` CustomEvent the host's toast listener (`useExtensionToast`)\n * forwards to its toaster — the same wire contract as the lower-level\n * `@ethisyscore/components-react` `showToast` primitive (kept self-contained\n * here to avoid a load-bearing cross-package import for a one-line dispatch).\n * Outside a host that wired the listener (mock/dev), every call is a harmless\n * no-op, so a plugin keeps its lifted `showSuccessToast(...)` call sites.\n */\ntype ToastVariant = \"default\" | \"success\" | \"error\" | \"warning\";\n\nfunction dispatchToast(title: string, description: string | undefined, variant: ToastVariant): void {\n if (typeof window === \"undefined\" || title.length === 0) {\n return;\n }\n window.dispatchEvent(new CustomEvent(\"ethisys:toast\", { detail: { title, description, variant } }));\n}\n\nexport function showSuccessToast(title: string, description?: string): void {\n dispatchToast(title, description, \"success\");\n}\n\nexport function showErrorToast(title: string, description?: string): void {\n dispatchToast(title, description, \"error\");\n}\n\nexport function showWarningToast(title: string, description?: string): void {\n dispatchToast(title, description, \"warning\");\n}\n\n/**\n * Options accepted by the `toast(...)` returned from {@link useToast}. Both `title`\n * and `description` are optional, but at least one must be set — `toast({ description })`\n * shows the description as the message (mirroring the monolith); `toast({})` is a no-op.\n */\nexport interface ToastOptions {\n /** Primary line. Falls back to {@link ToastOptions.description} when absent/empty. */\n title?: string;\n /** Secondary line — or the message itself when no `title` is given. */\n description?: string;\n /** `\"destructive\"`/`\"error\"` → error; `\"warning\"`/`\"success\"` map directly; else default. */\n variant?: string;\n}\n\n/**\n * Hook mirror of the monolith's `useToast()` surface, so a lifted\n * `const { toast } = useToast()` (and `showSuccessToast`/`showErrorToast`) keeps\n * working unchanged once `@/hooks/common/utility/use-toast` is aliased here.\n */\nexport function useToast() {\n return {\n toast: (opts: ToastOptions): void => {\n const variant: ToastVariant =\n opts.variant === \"destructive\" || opts.variant === \"error\"\n ? \"error\"\n : opts.variant === \"warning\"\n ? \"warning\"\n : opts.variant === \"success\"\n ? \"success\"\n : \"default\";\n // `title` is the primary line; fall back to `description` so `toast({ description })`\n // shows it (mirroring the monolith) instead of silently no-op'ing. Both absent → no-op.\n if (opts.title) {\n dispatchToast(opts.title, opts.description, variant);\n } else if (opts.description) {\n dispatchToast(opts.description, undefined, variant);\n }\n },\n showSuccessToast,\n showErrorToast,\n showWarningToast,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/ui/Dialog.tsx","../../../src/components/shared/ConfirmActionDialog.tsx","../../../src/icons/nexture/ni-bin-empty.tsx","../../../src/icons/nexture-icons.tsx","../../../src/components/shared/ConfirmDeleteDialog.tsx","../../../src/components/shared/useConfirmDialog.ts","../../../src/components/shared/toast.ts"],"names":["MuiDialog","jsx","jsxs","Fragment"],"mappings":"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","file":"index.js","sourcesContent":["import { Dialog as MuiDialog, type DialogProps } from \"@mui/material\";\n\n/**\n * MUI `Dialog` with the scroll-lock + focus-restore overrides plugin surfaces\n * need (AB#4808): MUI's defaults reset the page to top when a dialog opened from\n * below the fold closes. Everything else is the stock `Dialog` — this is the one\n * `components/ui` wrapper that isn't a pure re-export.\n */\nexport function Dialog(props: DialogProps) {\n return <MuiDialog disableScrollLock disableRestoreFocus {...props} />;\n}\n","import type { ReactNode } from \"react\";\nimport {\n Button,\n CircularProgress,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n} from \"../ui\";\n\nexport interface ConfirmActionLabels {\n title: string;\n description?: ReactNode;\n btnCancel?: string;\n btnConfirm?: string;\n btnLoading?: string;\n}\n\ninterface ConfirmActionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void;\n isLoading?: boolean;\n labels: ConfirmActionLabels;\n icon?: ReactNode;\n confirmVariant?: \"default\" | \"destructive\";\n className?: string;\n /** Optional body content rendered between the description and footer (e.g. a Textarea). */\n children?: ReactNode;\n /** Additional disable condition for the confirm button (e.g. empty required field). */\n disableConfirm?: boolean;\n}\n\n/**\n * Generic action confirmation dialog.\n * Use `labels` to customise title, description and button text.\n * `labels.description` accepts a string or any ReactNode (e.g. JSX with <strong>).\n *\n * Pass `children` to render additional body content (e.g. a Textarea) between the\n * description and the footer. Use `disableConfirm` to conditionally disable the confirm\n * button (e.g. when a required field is empty).\n *\n * For delete confirmations, prefer `ConfirmDeleteDialog` instead.\n */\nexport function ConfirmActionDialog({\n open,\n onOpenChange,\n onConfirm,\n isLoading = false,\n labels,\n icon,\n confirmVariant = \"default\",\n children,\n disableConfirm,\n}: ConfirmActionDialogProps) {\n const description = labels.description ?? \"Are you sure you want to continue?\";\n const btnCancel = labels.btnCancel ?? \"Cancel\";\n const btnConfirm = labels.btnConfirm ?? \"Confirm\";\n const btnLoading = labels.btnLoading ?? \"Processing...\";\n\n const handleClose = () => {\n if (!isLoading) onOpenChange(false);\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"xs\" fullWidth role=\"alertdialog\">\n <DialogTitle className=\"flex items-center gap-2\">\n {icon}\n {labels.title}\n </DialogTitle>\n <DialogContent>\n {typeof description === \"string\" ? (\n <DialogContentText>{description}</DialogContentText>\n ) : (\n <DialogContentText component=\"div\">{description}</DialogContentText>\n )}\n {children}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={isLoading}>\n {btnCancel}\n </Button>\n <Button\n variant=\"contained\"\n color={confirmVariant === \"destructive\" ? \"error\" : \"primary\"}\n onClick={onConfirm}\n disabled={isLoading || disableConfirm}\n >\n {isLoading ? (\n <>\n <CircularProgress size={16} color=\"inherit\" className=\"mr-2\" />\n {btnLoading}\n </>\n ) : (\n btnConfirm\n )}\n </Button>\n </DialogActions>\n </Dialog>\n );\n}\n","import { NextureIconsProps, sizeHelper, strokeSizeHelper } from \"../nexture-icons\";\n\nexport default function NiBinEmpty({ className, variant = \"outlined\", size = \"medium\" }: NextureIconsProps) {\n const iconSize = sizeHelper(size);\n const iconStrokeWidth = strokeSizeHelper(iconSize);\n if (variant === \"outlined\") {\n return (\n <svg\n width={iconSize}\n height={iconSize}\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M6 6L5.48806 9.58357C5.16413 11.8511 5.14395 14.1516 5.42806 16.4245L5.51601 17.1281C5.80316 19.4253 7.56538 21.2609 9.84894 21.6415V21.6415C11.2732 21.8789 12.7268 21.8789 14.1511 21.6415V21.6415C16.4346 21.2609 18.1968 19.4253 18.484 17.1281L18.5719 16.4245C18.856 14.1516 18.8359 11.8511 18.5119 9.58357L18 6\"\n stroke=\"currentColor\"\n strokeWidth={iconStrokeWidth}\n strokeLinecap=\"round\"\n />\n <path\n d=\"M15 5L14.9062 4.43717C14.7408 3.4451 14.6582 2.94906 14.3711 2.60286C14.2462 2.45218 14.0957 2.32469 13.9265 2.22623C13.5378 2 13.035 2 12.0292 2L11.9708 2C10.965 2 10.4622 2 10.0735 2.22623C9.90431 2.32469 9.75381 2.45219 9.62888 2.60286C9.34182 2.94906 9.25915 3.4451 9.09381 4.43717L9 5\"\n stroke=\"currentColor\"\n strokeWidth={iconStrokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <path\n d=\"M20 6L18.2017 5.77522C14.0833 5.26041 9.91673 5.26041 5.79826 5.77522L4 6\"\n stroke=\"currentColor\"\n strokeWidth={iconStrokeWidth}\n strokeLinecap=\"round\"\n />\n </svg>\n );\n } else {\n return (\n <svg\n width={iconSize}\n height={iconSize}\n className={className}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M9.74018 5.12304C9.6721 5.53152 9.28536 5.80813 8.8769 5.74023C8.46843 5.67215 8.19181 5.28541 8.25971 4.87695L8.35444 4.31347C8.43472 3.83178 8.50246 3.41913 8.59077 3.08593C8.68246 2.74003 8.81179 2.41337 9.0517 2.12402C9.23282 1.90562 9.45102 1.72085 9.69623 1.57812C10.0211 1.38906 10.3644 1.31483 10.7206 1.28125C11.0639 1.24892 11.4822 1.25 11.9706 1.25L12.0292 1.25C12.5177 1.25 12.936 1.24892 13.2792 1.28125C13.6355 1.31483 13.9788 1.38906 14.3037 1.57812C14.5489 1.72085 14.7671 1.90562 14.9482 2.12402C15.1881 2.41337 15.3174 2.74003 15.4091 3.08593C15.4974 3.41913 15.5652 3.83177 15.6455 4.31347L15.7402 4.87695L15.749 4.95312C15.7732 5.33241 15.506 5.6764 15.123 5.74023C14.74 5.80389 14.3763 5.56494 14.2763 5.19824L14.2597 5.12304L14.166 4.56054C14.081 4.05049 14.025 3.71896 13.9589 3.46972C13.8964 3.23378 13.8409 3.13889 13.7939 3.08203C13.7252 2.99916 13.6418 2.92817 13.5488 2.87402C13.4849 2.83695 13.3818 2.79831 13.1386 2.77539C12.8819 2.75121 12.5462 2.75 12.0292 2.75L11.9706 2.75C11.4537 2.75 11.1179 2.75121 10.8613 2.77539C10.6181 2.79831 10.515 2.83695 10.4511 2.87402C10.3581 2.92817 10.2747 2.99916 10.206 3.08203C10.1589 3.13889 10.1035 3.23378 10.041 3.46972C9.97489 3.71896 9.91894 4.05049 9.83393 4.56054L9.74018 5.12304Z\"\n fill=\"currentColor\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M5.94819 5.00114C9.96612 4.51861 14.0279 4.51807 18.0459 5.00016C18.1288 5.01011 18.212 5.02008 18.2949 5.03043L20.0927 5.25504L20.1689 5.26872C20.5391 5.35382 20.792 5.70788 20.7441 6.09293C20.6958 6.47814 20.3633 6.75806 19.9834 6.74918L19.9072 6.7443L18.8447 6.61051L19.2548 9.4777C19.5881 11.8107 19.6086 14.1783 19.3164 16.5168L19.2285 17.2209C18.9001 19.8471 16.8851 21.9459 14.2744 22.381C12.7685 22.632 11.2314 22.632 9.72554 22.381C7.11486 21.9458 5.09978 19.8471 4.77144 17.2209L4.68355 16.5168C4.39132 14.1783 4.41185 11.8107 4.74507 9.4777L5.15425 6.61051L4.09273 6.7443L4.01655 6.74918C3.63657 6.75805 3.30414 6.47813 3.25581 6.09293C3.20471 5.68211 3.49633 5.30642 3.90718 5.25504L5.70503 5.03043C5.78598 5.02032 5.86721 5.01086 5.94819 5.00114Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n }\n}\n","import NiAI from \"./nexture/ni-ai\";\nimport NiAirBalloon from \"./nexture/ni-air-balloon\";\nimport NiAnchor from \"./nexture/ni-anchor\";\nimport NiAnnouncement from \"./nexture/ni-announcement\";\nimport NiAntenna from \"./nexture/ni-antenna\";\nimport NiArchive from \"./nexture/ni-archive\";\nimport NiArchiveCheck from \"./nexture/ni-archive-check\";\nimport NiArrowCircleLeft from \"./nexture/ni-arrow-circle-left\";\nimport NiArrowCircleRight from \"./nexture/ni-arrow-circle-right\";\nimport NiArrowDown from \"./nexture/ni-arrow-down\";\nimport NiArrowDownLeft from \"./nexture/ni-arrow-down-left\";\nimport NiArrowDownLeftSquare from \"./nexture/ni-arrow-down-left-square\";\nimport NiArrowDownRight from \"./nexture/ni-arrow-down-right\";\nimport NiArrowDownRightSquare from \"./nexture/ni-arrow-down-right-square\";\nimport NiArrowDownSquare from \"./nexture/ni-arrow-down-square\";\nimport NiArrowHistory from \"./nexture/ni-arrow-history\";\nimport NiArrowInDown from \"./nexture/ni-arrow-in-down\";\nimport NiArrowInLeft from \"./nexture/ni-arrow-in-left\";\nimport NiArrowInRight from \"./nexture/ni-arrow-in-right\";\nimport NiArrowInUp from \"./nexture/ni-arrow-in-up\";\nimport NiArrowLeft from \"./nexture/ni-arrow-left\";\nimport NiArrowLeftRight from \"./nexture/ni-arrow-left-right\";\nimport NiArrowLeftSquare from \"./nexture/ni-arrow-left-square\";\nimport NiArrowOutDown from \"./nexture/ni-arrow-out-down\";\nimport NiArrowOutLeft from \"./nexture/ni-arrow-out-left\";\nimport NiArrowOutRight from \"./nexture/ni-arrow-out-right\";\nimport NiArrowOutUp from \"./nexture/ni-arrow-out-up\";\nimport NiArrowRight from \"./nexture/ni-arrow-right\";\nimport NiArrowRightSquare from \"./nexture/ni-arrow-right-square\";\nimport NiArrowUp from \"./nexture/ni-arrow-up\";\nimport NiArrowUpDown from \"./nexture/ni-arrow-up-down\";\nimport NiArrowUpLeft from \"./nexture/ni-arrow-up-left\";\nimport NiArrowUpLeftSquare from \"./nexture/ni-arrow-up-left-square\";\nimport NiArrowUpRight from \"./nexture/ni-arrow-up-right\";\nimport NiArrowUpRightSquare from \"./nexture/ni-arrow-up-right-square\";\nimport NiArrowUpSquare from \"./nexture/ni-arrow-up-square\";\nimport NiAt from \"./nexture/ni-at\";\nimport NiBadge from \"./nexture/ni-badge\";\nimport NiBadgeCheck from \"./nexture/ni-badge-check\";\nimport NiBag from \"./nexture/ni-bag\";\nimport NiBandAid from \"./nexture/ni-band-aid\";\nimport NiBarcode from \"./nexture/ni-barcode\";\nimport NiBasket from \"./nexture/ni-basket\";\nimport NiBatteryCharging from \"./nexture/ni-battery-charging\";\nimport NiBatteryEmpty from \"./nexture/ni-battery-empty\";\nimport NiBatteryFull from \"./nexture/ni-battery-full\";\nimport NiBell from \"./nexture/ni-bell\";\nimport NiBellInactive from \"./nexture/ni-bell-inactive\";\nimport NiBinEmpty from \"./nexture/ni-bin-empty\";\nimport NiBinFull from \"./nexture/ni-bin-full\";\nimport NiBloodCells from \"./nexture/ni-blood-cells\";\nimport NiBluetooth from \"./nexture/ni-bluetooth\";\nimport NiBook from \"./nexture/ni-book\";\nimport NiBookmark from \"./nexture/ni-bookmark\";\nimport NiBookmarkSingle from \"./nexture/ni-bookmark-single\";\nimport NiBraces from \"./nexture/ni-braces\";\nimport NiBrackets from \"./nexture/ni-brackets\";\nimport NiBrain from \"./nexture/ni-brain\";\nimport NiBrainCircuit from \"./nexture/ni-brain-circuit\";\nimport NiBriefcase from \"./nexture/ni-briefcase\";\nimport NiBrush from \"./nexture/ni-brush\";\nimport NiBrushArt from \"./nexture/ni-brush-art\";\nimport NiBrushArtSquare from \"./nexture/ni-brush-art-square\";\nimport NiBug from \"./nexture/ni-bug\";\nimport NiBuilding from \"./nexture/ni-building\";\nimport NiBulbOff from \"./nexture/ni-bulb-off\";\nimport NiBulbOn from \"./nexture/ni-bulb-on\";\nimport NiButton from \"./nexture/ni-button\";\nimport NiButtonGroup from \"./nexture/ni-button-group\";\nimport NiButtonLarge from \"./nexture/ni-button-large\";\nimport NiCake from \"./nexture/ni-cake\";\nimport NiCalendar from \"./nexture/ni-calendar\";\nimport NiCalendarClock from \"./nexture/ni-calendar-clock\";\nimport NiCamera from \"./nexture/ni-camera\";\nimport NiCar from \"./nexture/ni-car\";\nimport NiCartArrow from \"./nexture/ni-cart-arrow\";\nimport NiCartCross from \"./nexture/ni-cart-cross\";\nimport NiCartEmpty from \"./nexture/ni-cart-empty\";\nimport NiCartMinus from \"./nexture/ni-cart-minus\";\nimport NiCartPlus from \"./nexture/ni-cart-plus\";\nimport NiCatalog from \"./nexture/ni-catalog\";\nimport NiCells from \"./nexture/ni-cells\";\nimport NiCellsPlus from \"./nexture/ni-cells-plus\";\nimport NiChange from \"./nexture/ni-change\";\nimport NiChartBar from \"./nexture/ni-chart-bar\";\nimport NiChartCandleSticks from \"./nexture/ni-chart-candle-sticks\";\nimport NiChartFunnel from \"./nexture/ni-chart-funnel\";\nimport NiChartHeatmap from \"./nexture/ni-chart-heatmap\";\nimport NiChartLine from \"./nexture/ni-chart-line\";\nimport NiChartLineBar from \"./nexture/ni-chart-line-bar\";\nimport NiChartPie from \"./nexture/ni-chart-pie\";\nimport NiChartPolar from \"./nexture/ni-chart-polar\";\nimport NiChartRadar from \"./nexture/ni-chart-radar\";\nimport NiChartScatter from \"./nexture/ni-chart-scatter\";\nimport NiCheck from \"./nexture/ni-check\";\nimport NiCheckFull from \"./nexture/ni-check-full\";\nimport NiCheckSquare from \"./nexture/ni-check-square\";\nimport NiChef from \"./nexture/ni-chef\";\nimport NiChevronDown from \"./nexture/ni-chevron-down\";\nimport NiChevronDownSmall from \"./nexture/ni-chevron-down-small\";\nimport NiChevronLeft from \"./nexture/ni-chevron-left\";\nimport NiChevronLeftRightReverseSmall from \"./nexture/ni-chevron-left-right-reverse-small\";\nimport NiChevronLeftRightSmall from \"./nexture/ni-chevron-left-right-small\";\nimport NiChevronLeftSmall from \"./nexture/ni-chevron-left-small\";\nimport NiChevronRight from \"./nexture/ni-chevron-right\";\nimport NiChevronRightSmall from \"./nexture/ni-chevron-right-small\";\nimport NiChevronUp from \"./nexture/ni-chevron-up\";\nimport NiChevronUpDownReverseSmall from \"./nexture/ni-chevron-up-down-reverse-small\";\nimport NiChevronUpDownSmall from \"./nexture/ni-chevron-up-down-small\";\nimport NiChevronUpSmall from \"./nexture/ni-chevron-up-small\";\nimport NiCholesterol from \"./nexture/ni-cholesterol\";\nimport NiCircle from \"./nexture/ni-circle\";\nimport NiClipboard from \"./nexture/ni-clipboard\";\nimport NiClock from \"./nexture/ni-clock\";\nimport NiCloud from \"./nexture/ni-cloud\";\nimport NiCloudPartly from \"./nexture/ni-cloud-partly\";\nimport NiCloudRain from \"./nexture/ni-cloud-rain\";\nimport NiCloudSnow from \"./nexture/ni-cloud-snow\";\nimport NiCloudThunder from \"./nexture/ni-cloud-thunder\";\nimport NiCode from \"./nexture/ni-code\";\nimport NiCoffee from \"./nexture/ni-coffee\";\nimport NiCoin from \"./nexture/ni-coin\";\nimport NiCollapse from \"./nexture/ni-collapse\";\nimport NiCollapseIn from \"./nexture/ni-collapse-in\";\nimport NiCols from \"./nexture/ni-cols\";\nimport NiCompass from \"./nexture/ni-compass\";\nimport NiController from \"./nexture/ni-controller\";\nimport NiCopyright from \"./nexture/ni-copyright\";\nimport NiCpu from \"./nexture/ni-cpu\";\nimport NiCreditCard from \"./nexture/ni-credit-card\";\nimport NiCrop from \"./nexture/ni-crop\";\nimport NiCross from \"./nexture/ni-cross\";\nimport NiCrossFull from \"./nexture/ni-cross-full\";\nimport NiCrossHexagon from \"./nexture/ni-cross-hexagon\";\nimport NiCrossSquare from \"./nexture/ni-cross-square\";\nimport NiCrosshair from \"./nexture/ni-crosshair\";\nimport NiCrown from \"./nexture/ni-crown\";\nimport NiCursor from \"./nexture/ni-cursor\";\nimport NiDashboard from \"./nexture/ni-dashboard\";\nimport NiDatabase from \"./nexture/ni-database\";\nimport NiDevops from \"./nexture/ni-devops\";\nimport NiDiagram from \"./nexture/ni-diagram\";\nimport NiDice from \"./nexture/ni-dice\";\nimport NiDirectory from \"./nexture/ni-directory\";\nimport NiDocumentArchive from \"./nexture/ni-document-archive\";\nimport NiDocumentChart from \"./nexture/ni-document-chart\";\nimport NiDocumentCheck from \"./nexture/ni-document-check\";\nimport NiDocumentCode from \"./nexture/ni-document-code\";\nimport NiDocumentCross from \"./nexture/ni-document-cross\";\nimport NiDocumentFull from \"./nexture/ni-document-full\";\nimport NiDocumentImage from \"./nexture/ni-document-image\";\nimport NiDocumentMinus from \"./nexture/ni-document-minus\";\nimport NiDocumentNumber from \"./nexture/ni-document-number\";\nimport NiDocumentPlus from \"./nexture/ni-document-plus\";\nimport NiDocumentVideo from \"./nexture/ni-document-video\";\nimport NiDollar from \"./nexture/ni-dollar\";\nimport NiDollarSquare from \"./nexture/ni-dollar-square\";\nimport NiDotsSquare from \"./nexture/ni-dots-square\";\nimport NiDownloadCloud from \"./nexture/ni-download-cloud\";\nimport NiDragHorizontal from \"./nexture/ni-drag-horizontal\";\nimport NiDragVertical from \"./nexture/ni-drag-vertical\";\nimport NiDrink from \"./nexture/ni-drink\";\nimport NiDrop from \"./nexture/ni-drop\";\nimport NiDuplicate from \"./nexture/ni-duplicate\";\nimport NiEllipsisHorizontal from \"./nexture/ni-ellipsis-horizontal\";\nimport NiEllipsisVertical from \"./nexture/ni-ellipsis-vertical\";\nimport NiEmail from \"./nexture/ni-email\";\nimport NiEmailOpen from \"./nexture/ni-email-open\";\nimport NiEndDownSmall from \"./nexture/ni-end-down-small\";\nimport NiEndLeftSmall from \"./nexture/ni-end-left-small\";\nimport NiEndRightSmall from \"./nexture/ni-end-right-small\";\nimport NiEndUpSmall from \"./nexture/ni-end-up-small\";\nimport NiEnterDown from \"./nexture/ni-enter-down\";\nimport NiEnterLeft from \"./nexture/ni-enter-left\";\nimport NiEnterReverseDown from \"./nexture/ni-enter-reverse-down\";\nimport NiEnterReverseLeft from \"./nexture/ni-enter-reverse-left\";\nimport NiEnterReverseRight from \"./nexture/ni-enter-reverse-right\";\nimport NiEnterReverseUp from \"./nexture/ni-enter-reverse-up\";\nimport NiEnterRight from \"./nexture/ni-enter-right\";\nimport NiEnterUp from \"./nexture/ni-enter-up\";\nimport NiEquals from \"./nexture/ni-equals\";\nimport NiEqualsFull from \"./nexture/ni-equals-full\";\nimport NiEraser from \"./nexture/ni-eraser\";\nimport NiEuro from \"./nexture/ni-euro\";\nimport NiEuroSquare from \"./nexture/ni-euro-square\";\nimport NiExclamationHexagon from \"./nexture/ni-exclamation-hexagon\";\nimport NiExclamationSquare from \"./nexture/ni-exclamation-square\";\nimport NiExpand from \"./nexture/ni-expand\";\nimport NiExpandFull from \"./nexture/ni-expand-full\";\nimport NiExpandOut from \"./nexture/ni-expand-out\";\nimport NiExpandSquare from \"./nexture/ni-expand-square\";\nimport NiExternal from \"./nexture/ni-external\";\nimport NiEyeClose from \"./nexture/ni-eye-close\";\nimport NiEyeInactive from \"./nexture/ni-eye-inactive\";\nimport NiEyeOpen from \"./nexture/ni-eye-open\";\nimport NiFaceFrown from \"./nexture/ni-face-frown\";\nimport NiFaceFrownMore from \"./nexture/ni-face-frown-more\";\nimport NiFaceNeutral from \"./nexture/ni-face-neutral\";\nimport NiFaceSmile from \"./nexture/ni-face-smile\";\nimport NiFaceSmileMore from \"./nexture/ni-face-smile-more\";\nimport NiFemale from \"./nexture/ni-female\";\nimport NiFilter from \"./nexture/ni-filter\";\nimport NiFilterCross from \"./nexture/ni-filter-cross\";\nimport NiFilterMinus from \"./nexture/ni-filter-minus\";\nimport NiFilterPlus from \"./nexture/ni-filter-plus\";\nimport NiFingerprint from \"./nexture/ni-fingerprint\";\nimport NiFire from \"./nexture/ni-fire\";\nimport NiFirstAid from \"./nexture/ni-first-aid\";\nimport NiFitness from \"./nexture/ni-fitness\";\nimport NiFlag from \"./nexture/ni-flag\";\nimport NiFlash from \"./nexture/ni-flash\";\nimport NiFlask from \"./nexture/ni-flask\";\nimport NiFloppyDisk from \"./nexture/ni-floppy-disk\";\nimport NiFolder from \"./nexture/ni-folder\";\nimport NiFolderCheck from \"./nexture/ni-folder-check\";\nimport NiFolderCross from \"./nexture/ni-folder-cross\";\nimport NiFolderMinus from \"./nexture/ni-folder-minus\";\nimport NiFolderPlus from \"./nexture/ni-folder-plus\";\nimport NiForwardDownSmall from \"./nexture/ni-forward-down-small\";\nimport NiForwardLeftSmall from \"./nexture/ni-forward-left-small\";\nimport NiForwardRightSmall from \"./nexture/ni-forward-right-small\";\nimport NiForwardUpSmall from \"./nexture/ni-forward-up-small\";\nimport NiGay from \"./nexture/ni-gay\";\nimport NiGerm from \"./nexture/ni-germ\";\nimport NiGogo from \"./nexture/ni-gogo\";\nimport NiGold from \"./nexture/ni-gold\";\nimport NiGpu from \"./nexture/ni-gpu\";\nimport NiGraduation from \"./nexture/ni-graduation\";\nimport NiGroup from \"./nexture/ni-group\";\nimport NiHeadphones from \"./nexture/ni-headphones\";\nimport NiHeadset from \"./nexture/ni-headset\";\nimport NiHeadsetMic from \"./nexture/ni-headset-mic\";\nimport NiHealth from \"./nexture/ni-health\";\nimport NiHeart from \"./nexture/ni-heart\";\nimport NiHeartRate from \"./nexture/ni-heart-rate\";\nimport NiHearts from \"./nexture/ni-hearts\";\nimport NiHome from \"./nexture/ni-home\";\nimport NiInbox from \"./nexture/ni-inbox\";\nimport NiInfoSquare from \"./nexture/ni-info-square\";\nimport NiInjection from \"./nexture/ni-injection\";\nimport NiInput from \"./nexture/ni-input\";\nimport NiIntegration from \"./nexture/ni-integration\";\nimport NiInternal from \"./nexture/ni-internal\";\nimport NiIv from \"./nexture/ni-iv\";\nimport NiJoin from \"./nexture/ni-join\";\nimport NiKey from \"./nexture/ni-key\";\nimport NiKeyboard from \"./nexture/ni-keyboard\";\nimport NiKnobs from \"./nexture/ni-knobs\";\nimport NiLaptop from \"./nexture/ni-laptop\";\nimport NiLaw from \"./nexture/ni-law\";\nimport NiLayout from \"./nexture/ni-layout\";\nimport NiLike from \"./nexture/ni-like\";\nimport NiLink from \"./nexture/ni-link\";\nimport NiLinkBroken from \"./nexture/ni-link-broken\";\nimport NiList from \"./nexture/ni-list\";\nimport NiListCheck from \"./nexture/ni-list-check\";\nimport NiListChevronDown from \"./nexture/ni-list-chevron-down\";\nimport NiListCircle from \"./nexture/ni-list-circle\";\nimport NiListCross from \"./nexture/ni-list-cross\";\nimport NiListNumber from \"./nexture/ni-list-number\";\nimport NiListSquare from \"./nexture/ni-list-square\";\nimport NiLoader from \"./nexture/ni-loader\";\nimport NiLock from \"./nexture/ni-lock\";\nimport NiLuggage from \"./nexture/ni-luggage\";\nimport NiLungs from \"./nexture/ni-lungs\";\nimport NiMagicWand from \"./nexture/ni-magic-wand\";\nimport NiMale from \"./nexture/ni-male\";\nimport NiMap from \"./nexture/ni-map\";\nimport NiMasonary from \"./nexture/ni-masonary\";\nimport NiMedal from \"./nexture/ni-medal\";\nimport NiMenu from \"./nexture/ni-menu\";\nimport NiMenuLeft from \"./nexture/ni-menu-left\";\nimport NiMenuRight from \"./nexture/ni-menu-right\";\nimport NiMenuSplit from \"./nexture/ni-menu-split\";\nimport NiMenuSplitDot from \"./nexture/ni-menu-split-dot\";\nimport NiMenuSplitDotReverse from \"./nexture/ni-menu-split-dot-reverse\";\nimport NiMenuSplitReverse from \"./nexture/ni-menu-split-reverse\";\nimport NiMessage from \"./nexture/ni-message\";\nimport NiMessageCheck from \"./nexture/ni-message-check\";\nimport NiMessageCross from \"./nexture/ni-message-cross\";\nimport NiMessageDots from \"./nexture/ni-message-dots\";\nimport NiMessageFilled from \"./nexture/ni-message-filled\";\nimport NiMessageGrammar from \"./nexture/ni-message-grammar\";\nimport NiMessagePlus from \"./nexture/ni-message-plus\";\nimport NiMessages from \"./nexture/ni-messages\";\nimport NiMicrophone from \"./nexture/ni-microphone\";\nimport NiMinus from \"./nexture/ni-minus\";\nimport NiMinusFull from \"./nexture/ni-minus-full\";\nimport NiMinusSquare from \"./nexture/ni-minus-square\";\nimport NiMoney from \"./nexture/ni-money\";\nimport NiMoneyBag from \"./nexture/ni-money-bag\";\nimport NiMoon from \"./nexture/ni-moon\";\nimport NiMountain from \"./nexture/ni-mountain\";\nimport NiMouse from \"./nexture/ni-mouse\";\nimport NiMove from \"./nexture/ni-move\";\nimport NiMusic from \"./nexture/ni-music\";\nimport NiNetwork from \"./nexture/ni-network\";\nimport NiNext from \"./nexture/ni-next\";\nimport NiOxygen from \"./nexture/ni-oxygen\";\nimport NiPaintBucket from \"./nexture/ni-paint-bucket\";\nimport NiPaintRoller from \"./nexture/ni-paint-roller\";\nimport NiPalette from \"./nexture/ni-palette\";\nimport NiPaperclip from \"./nexture/ni-paperclip\";\nimport NiParentheses from \"./nexture/ni-parentheses\";\nimport NiPath from \"./nexture/ni-path\";\nimport NiPause from \"./nexture/ni-pause\";\nimport NiPen from \"./nexture/ni-pen\";\nimport NiPenSquare from \"./nexture/ni-pen-square\";\nimport NiPercent from \"./nexture/ni-percent\";\nimport NiPhone from \"./nexture/ni-phone\";\nimport NiPhoneHandset from \"./nexture/ni-phone-handset\";\nimport NiPhoneHandsetCheck from \"./nexture/ni-phone-handset-check\";\nimport NiPhoneHandsetOff from \"./nexture/ni-phone-handset-off\";\nimport NiPhoneHandsetOn from \"./nexture/ni-phone-handset-on\";\nimport NiPin from \"./nexture/ni-pin\";\nimport NiPinCheck from \"./nexture/ni-pin-check\";\nimport NiPinCross from \"./nexture/ni-pin-cross\";\nimport NiPinPlus from \"./nexture/ni-pin-plus\";\nimport NiPine from \"./nexture/ni-pine\";\nimport NiPivot from \"./nexture/ni-pivot\";\nimport NiPlane from \"./nexture/ni-plane\";\nimport NiPlay from \"./nexture/ni-play\";\nimport NiPlug from \"./nexture/ni-plug\";\nimport NiPlus from \"./nexture/ni-plus\";\nimport NiPlusFull from \"./nexture/ni-plus-full\";\nimport NiPlusSquare from \"./nexture/ni-plus-square\";\nimport NiPolitics from \"./nexture/ni-politics\";\nimport NiPound from \"./nexture/ni-pound\";\nimport NiPoundSquare from \"./nexture/ni-pound-square\";\nimport NiPower from \"./nexture/ni-power\";\nimport NiPresentation from \"./nexture/ni-presentation\";\nimport NiPrevious from \"./nexture/ni-previous\";\nimport NiPrinter from \"./nexture/ni-printer\";\nimport NiProgress from \"./nexture/ni-progress\";\nimport NiPullRequestClosed from \"./nexture/ni-pull-request-closed\";\nimport NiPullRequestDraft from \"./nexture/ni-pull-request-draft\";\nimport NiPullRequestMerged from \"./nexture/ni-pull-request-merged\";\nimport NiPullRequestOpen from \"./nexture/ni-pull-request-open\";\nimport NiPulse from \"./nexture/ni-pulse\";\nimport NiPushPin from \"./nexture/ni-push-pin\";\nimport NiPushPinLeft from \"./nexture/ni-push-pin-left\";\nimport NiPushPinRight from \"./nexture/ni-push-pin-right\";\nimport NiPuzzle from \"./nexture/ni-puzzle\";\nimport NiQuestionHexagon from \"./nexture/ni-question-hexagon\";\nimport NiRadio from \"./nexture/ni-radio\";\nimport NiRankFour from \"./nexture/ni-rank-four\";\nimport NiRankOne from \"./nexture/ni-rank-one\";\nimport NiRankThree from \"./nexture/ni-rank-three\";\nimport NiRankTwo from \"./nexture/ni-rank-two\";\nimport NiReceipt from \"./nexture/ni-receipt\";\nimport NiRecord from \"./nexture/ni-record\";\nimport NiRefresh from \"./nexture/ni-refresh\";\nimport NiReligion from \"./nexture/ni-religion\";\nimport NiResearch from \"./nexture/ni-research\";\nimport NiRevenue from \"./nexture/ni-revenue\";\nimport NiReverseLeft from \"./nexture/ni-reverse-left\";\nimport NiReverseRight from \"./nexture/ni-reverse-right\";\nimport NiRobot from \"./nexture/ni-robot\";\nimport NiRocket from \"./nexture/ni-rocket\";\nimport NiRouter from \"./nexture/ni-router\";\nimport NiRows from \"./nexture/ni-rows\";\nimport NiSafe from \"./nexture/ni-safe\";\nimport NiScale from \"./nexture/ni-scale\";\nimport NiScalpel from \"./nexture/ni-scalpel\";\nimport NiScissors from \"./nexture/ni-scissors\";\nimport NiScreen from \"./nexture/ni-screen\";\nimport NiScriptSub from \"./nexture/ni-script-sub\";\nimport NiScriptSuper from \"./nexture/ni-script-super\";\nimport NiSdCard from \"./nexture/ni-sd-card\";\nimport NiSearch from \"./nexture/ni-search\";\nimport NiSelect from \"./nexture/ni-select\";\nimport NiSendDown from \"./nexture/ni-send-down\";\nimport NiSendDownLeft from \"./nexture/ni-send-down-left\";\nimport NiSendDownRight from \"./nexture/ni-send-down-right\";\nimport NiSendLeft from \"./nexture/ni-send-left\";\nimport NiSendRight from \"./nexture/ni-send-right\";\nimport NiSendUp from \"./nexture/ni-send-up\";\nimport NiSendUpLeft from \"./nexture/ni-send-up-left\";\nimport NiSendUpRight from \"./nexture/ni-send-up-right\";\nimport NiServer from \"./nexture/ni-server\";\nimport NiSettings from \"./nexture/ni-settings\";\nimport NiShare from \"./nexture/ni-share\";\nimport NiShield from \"./nexture/ni-shield\";\nimport NiShieldCheck from \"./nexture/ni-shield-check\";\nimport NiShieldCross from \"./nexture/ni-shield-cross\";\nimport NiShrinkFull from \"./nexture/ni-shrink-full\";\nimport NiShrinkSquare from \"./nexture/ni-shrink-square\";\nimport NiShuffle from \"./nexture/ni-shuffle\";\nimport NiSign from \"./nexture/ni-sign\";\nimport NiSignalLeftRight from \"./nexture/ni-signal-left-right\";\nimport NiSignalRight from \"./nexture/ni-signal-right\";\nimport NiSignalUp from \"./nexture/ni-signal-up\";\nimport NiSigns from \"./nexture/ni-signs\";\nimport NiSlashHexagon from \"./nexture/ni-slash-hexagon\";\nimport NiSlider from \"./nexture/ni-slider\";\nimport NiSnow from \"./nexture/ni-snow\";\nimport NiSoundCross from \"./nexture/ni-sound-cross\";\nimport NiSoundOff from \"./nexture/ni-sound-off\";\nimport NiSoundOn from \"./nexture/ni-sound-on\";\nimport NiSoundPlus from \"./nexture/ni-sound-plus\";\nimport NiSparkle from \"./nexture/ni-sparkle\";\nimport NiSpinner from \"./nexture/ni-spinner\";\nimport NiSquare from \"./nexture/ni-square\";\nimport NiSquircle from \"./nexture/ni-squircle\";\nimport NiStar from \"./nexture/ni-star\";\nimport NiStars from \"./nexture/ni-stars\";\nimport NiStomach from \"./nexture/ni-stomach\";\nimport NiStopwatch from \"./nexture/ni-stopwatch\";\nimport NiStore from \"./nexture/ni-store\";\nimport NiStructure from \"./nexture/ni-structure\";\nimport NiSum from \"./nexture/ni-sum\";\nimport NiSun from \"./nexture/ni-sun\";\nimport NiSwap from \"./nexture/ni-swap\";\nimport NiSwitch from \"./nexture/ni-switch\";\nimport NiTablet from \"./nexture/ni-tablet\";\nimport NiTag from \"./nexture/ni-tag\";\nimport NiTelescope from \"./nexture/ni-telescope\";\nimport NiTemperature from \"./nexture/ni-temperature\";\nimport NiTent from \"./nexture/ni-tent\";\nimport NiTerminal from \"./nexture/ni-terminal\";\nimport NiTextBold from \"./nexture/ni-text-bold\";\nimport NiTextCenter from \"./nexture/ni-text-center\";\nimport NiTextFont from \"./nexture/ni-text-font\";\nimport NiTextItalic from \"./nexture/ni-text-italic\";\nimport NiTextJustify from \"./nexture/ni-text-justify\";\nimport NiTextLeft from \"./nexture/ni-text-left\";\nimport NiTextQuote from \"./nexture/ni-text-quote\";\nimport NiTextRight from \"./nexture/ni-text-right\";\nimport NiTextStrikethrough from \"./nexture/ni-text-strikethrough\";\nimport NiTextUnderline from \"./nexture/ni-text-underline\";\nimport NiTextarea from \"./nexture/ni-textarea\";\nimport NiTicket from \"./nexture/ni-ticket\";\nimport NiTimeline from \"./nexture/ni-timeline\";\nimport NiTooth from \"./nexture/ni-tooth\";\nimport NiToyBoat from \"./nexture/ni-toy-boat\";\nimport NiToySky from \"./nexture/ni-toy-sky\";\nimport NiToyStacking from \"./nexture/ni-toy-stacking\";\nimport NiTrade from \"./nexture/ni-trade\";\nimport NiTree from \"./nexture/ni-tree\";\nimport NiTrendDown from \"./nexture/ni-trend-down\";\nimport NiTrendUp from \"./nexture/ni-trend-up\";\nimport NiTriangleDown from \"./nexture/ni-triangle-down\";\nimport NiTriangleLeft from \"./nexture/ni-triangle-left\";\nimport NiTriangleRight from \"./nexture/ni-triangle-right\";\nimport NiTriangleUp from \"./nexture/ni-triangle-up\";\nimport NiTrophy from \"./nexture/ni-trophy\";\nimport NiTruck from \"./nexture/ni-truck\";\nimport NiTubes from \"./nexture/ni-tubes\";\nimport NiUngroup from \"./nexture/ni-ungroup\";\nimport NiUnlike from \"./nexture/ni-unlike\";\nimport NiUnlock from \"./nexture/ni-unlock\";\nimport NiUploadCloud from \"./nexture/ni-upload-cloud\";\nimport NiUser from \"./nexture/ni-user\";\nimport NiUserCheck from \"./nexture/ni-user-check\";\nimport NiUserCross from \"./nexture/ni-user-cross\";\nimport NiUserMinus from \"./nexture/ni-user-minus\";\nimport NiUserPlus from \"./nexture/ni-user-plus\";\nimport NiUsers from \"./nexture/ni-users\";\nimport NiVerified from \"./nexture/ni-verified\";\nimport NiWallet from \"./nexture/ni-wallet\";\nimport NiWalletCrypto from \"./nexture/ni-wallet-crypto\";\nimport NiWatch from \"./nexture/ni-watch\";\nimport NiWeightScale from \"./nexture/ni-weight-scale\";\nimport NiWind from \"./nexture/ni-wind\";\nimport NiWorld from \"./nexture/ni-world\";\nimport NiZoomIn from \"./nexture/ni-zoom-in\";\nimport NiZoomOut from \"./nexture/ni-zoom-out\";\n\nexport const IconMap = {\n NiAI,\n NiAirBalloon,\n NiAnchor,\n NiAnnouncement,\n NiAntenna,\n NiArchiveCheck,\n NiArchive,\n NiArrowCircleLeft,\n NiArrowCircleRight,\n NiArrowDownLeftSquare,\n NiArrowDownLeft,\n NiArrowDownRightSquare,\n NiArrowDownRight,\n NiArrowDownSquare,\n NiArrowDown,\n NiArrowHistory,\n NiArrowInDown,\n NiArrowInLeft,\n NiArrowInRight,\n NiArrowInUp,\n NiArrowLeftRight,\n NiArrowLeftSquare,\n NiArrowLeft,\n NiArrowOutDown,\n NiArrowOutLeft,\n NiArrowOutRight,\n NiArrowOutUp,\n NiArrowRightSquare,\n NiArrowRight,\n NiArrowUpDown,\n NiArrowUpLeftSquare,\n NiArrowUpLeft,\n NiArrowUpRightSquare,\n NiArrowUpRight,\n NiArrowUpSquare,\n NiArrowUp,\n NiAt,\n NiBadgeCheck,\n NiBadge,\n NiBag,\n NiBandAid,\n NiBarcode,\n NiBasket,\n NiBatteryCharging,\n NiBatteryEmpty,\n NiBatteryFull,\n NiBellInactive,\n NiBell,\n NiBinEmpty,\n NiBinFull,\n NiBloodCells,\n NiBluetooth,\n NiBook,\n NiBookmarkSingle,\n NiBookmark,\n NiBraces,\n NiBrackets,\n NiBrain,\n NiBrainCircuit,\n NiBriefcase,\n NiBrushArtSquare,\n NiBrushArt,\n NiBrush,\n NiBug,\n NiBuilding,\n NiBulbOff,\n NiBulbOn,\n NiButton,\n NiButtonGroup,\n NiButtonLarge,\n NiCake,\n NiCalendar,\n NiCalendarClock,\n NiCamera,\n NiCar,\n NiCartArrow,\n NiCartCross,\n NiCartEmpty,\n NiCartMinus,\n NiCartPlus,\n NiCatalog,\n NiCellsPlus,\n NiCells,\n NiChange,\n NiChartBar,\n NiChartCandleSticks,\n NiChartFunnel,\n NiChartHeatmap,\n NiChartLineBar,\n NiChartLine,\n NiChartPie,\n NiChartPolar,\n NiChartRadar,\n NiChartScatter,\n NiCheckSquare,\n NiCheck,\n NiCheckFull,\n NiChef,\n NiChevronDownSmall,\n NiChevronDown,\n NiChevronLeftRightReverseSmall,\n NiChevronLeftRightSmall,\n NiChevronLeftSmall,\n NiChevronLeft,\n NiChevronRightSmall,\n NiChevronRight,\n NiChevronUpDownReverseSmall,\n NiChevronUpDownSmall,\n NiChevronUpSmall,\n NiChevronUp,\n NiCholesterol,\n NiCircle,\n NiClipboard,\n NiClock,\n NiCloudPartly,\n NiCloudRain,\n NiCloudSnow,\n NiCloudThunder,\n NiCloud,\n NiCode,\n NiCoffee,\n NiCoin,\n NiCollapse,\n NiCollapseIn,\n NiCols,\n NiCompass,\n NiController,\n NiCopyright,\n NiCpu,\n NiCreditCard,\n NiCrop,\n NiCrossHexagon,\n NiCrossSquare,\n NiCross,\n NiCrossFull,\n NiCrosshair,\n NiCrown,\n NiCursor,\n NiDashboard,\n NiDatabase,\n NiDevops,\n NiDiagram,\n NiDice,\n NiDirectory,\n NiDocumentArchive,\n NiDocumentChart,\n NiDocumentCheck,\n NiDocumentCode,\n NiDocumentCross,\n NiDocumentFull,\n NiDocumentImage,\n NiDocumentMinus,\n NiDocumentNumber,\n NiDocumentPlus,\n NiDocumentVideo,\n NiDollarSquare,\n NiDollar,\n NiDotsSquare,\n NiDownloadCloud,\n NiDragHorizontal,\n NiDragVertical,\n NiDrink,\n NiDrop,\n NiDuplicate,\n NiEllipsisHorizontal,\n NiEllipsisVertical,\n NiEmailOpen,\n NiEmail,\n NiEndDownSmall,\n NiEndLeftSmall,\n NiEndRightSmall,\n NiEndUpSmall,\n NiEnterDown,\n NiEnterLeft,\n NiEnterReverseDown,\n NiEnterReverseLeft,\n NiEnterReverseRight,\n NiEnterReverseUp,\n NiEnterRight,\n NiEnterUp,\n NiEquals,\n NiEqualsFull,\n NiEraser,\n NiEuroSquare,\n NiEuro,\n NiExclamationHexagon,\n NiExclamationSquare,\n NiExpandOut,\n NiExpandSquare,\n NiExpandFull,\n NiExpand,\n NiExternal,\n NiEyeClose,\n NiEyeInactive,\n NiEyeOpen,\n NiFaceFrownMore,\n NiFaceFrown,\n NiFaceNeutral,\n NiFaceSmileMore,\n NiFaceSmile,\n NiFemale,\n NiFilterCross,\n NiFilterMinus,\n NiFilterPlus,\n NiFilter,\n NiFingerprint,\n NiFire,\n NiFirstAid,\n NiFitness,\n NiFlag,\n NiFlash,\n NiFlask,\n NiFloppyDisk,\n NiFolderCheck,\n NiFolderCross,\n NiFolderMinus,\n NiFolderPlus,\n NiFolder,\n NiForwardDownSmall,\n NiForwardLeftSmall,\n NiForwardRightSmall,\n NiForwardUpSmall,\n NiGay,\n NiGerm,\n NiGogo,\n NiGold,\n NiGpu,\n NiGroup,\n NiGraduation,\n NiHeadphones,\n NiHeadset,\n NiHeadsetMic,\n NiHealth,\n NiHeart,\n NiHeartRate,\n NiHearts,\n NiHome,\n NiInbox,\n NiInfoSquare,\n NiInjection,\n NiInput,\n NiIntegration,\n NiInternal,\n NiIv,\n NiJoin,\n NiKey,\n NiKeyboard,\n NiKnobs,\n NiLaptop,\n NiLayout,\n NiLaw,\n NiLike,\n NiLinkBroken,\n NiLink,\n NiListCheck,\n NiListChevronDown,\n NiListCircle,\n NiListCross,\n NiListNumber,\n NiListSquare,\n NiList,\n NiLungs,\n NiLoader,\n NiLock,\n NiLuggage,\n NiMagicWand,\n NiMale,\n NiMap,\n NiMasonary,\n NiMedal,\n NiMenu,\n NiMenuLeft,\n NiMenuRight,\n NiMenuSplitDotReverse,\n NiMenuSplitDot,\n NiMenuSplitReverse,\n NiMenuSplit,\n NiMessageCheck,\n NiMessageCross,\n NiMessageDots,\n NiMessageFilled,\n NiMessageGrammar,\n NiMessagePlus,\n NiMessage,\n NiMessages,\n NiMicrophone,\n NiMinus,\n NiMinusFull,\n NiMinusSquare,\n NiMoneyBag,\n NiMoney,\n NiMoon,\n NiMountain,\n NiMouse,\n NiMove,\n NiMusic,\n NiNetwork,\n NiNext,\n NiOxygen,\n NiPaintBucket,\n NiPaintRoller,\n NiPalette,\n NiPaperclip,\n NiParentheses,\n NiPath,\n NiPause,\n NiPenSquare,\n NiPen,\n NiPercent,\n NiPhoneHandsetCheck,\n NiPhoneHandsetOff,\n NiPhoneHandsetOn,\n NiPhoneHandset,\n NiPhone,\n NiPinCheck,\n NiPinCross,\n NiPinPlus,\n NiPin,\n NiPine,\n NiPivot,\n NiPlane,\n NiPlay,\n NiPlug,\n NiPlusSquare,\n NiPlus,\n NiPlusFull,\n NiPolitics,\n NiPoundSquare,\n NiPound,\n NiPower,\n NiPresentation,\n NiPrevious,\n NiPrinter,\n NiProgress,\n NiPullRequestClosed,\n NiPullRequestDraft,\n NiPullRequestMerged,\n NiPullRequestOpen,\n NiPulse,\n NiPushPin,\n NiPushPinLeft,\n NiPushPinRight,\n NiPuzzle,\n NiQuestionHexagon,\n NiRankOne,\n NiRankTwo,\n NiRankThree,\n NiRankFour,\n NiRadio,\n NiReceipt,\n NiRecord,\n NiRefresh,\n NiReligion,\n NiResearch,\n NiRevenue,\n NiReverseLeft,\n NiReverseRight,\n NiRobot,\n NiRocket,\n NiRouter,\n NiRows,\n NiSafe,\n NiScale,\n NiScalpel,\n NiScissors,\n NiScreen,\n NiScriptSub,\n NiScriptSuper,\n NiSdCard,\n NiSearch,\n NiSelect,\n NiSendDownLeft,\n NiSendDownRight,\n NiSendDown,\n NiSendLeft,\n NiSendRight,\n NiSendUpLeft,\n NiSendUpRight,\n NiSendUp,\n NiServer,\n NiSettings,\n NiShare,\n NiShieldCheck,\n NiShieldCross,\n NiShield,\n NiShrinkSquare,\n NiShrinkFull,\n NiShuffle,\n NiSign,\n NiSignalLeftRight,\n NiSignalRight,\n NiSignalUp,\n NiSigns,\n NiSlashHexagon,\n NiSlider,\n NiSnow,\n NiSoundCross,\n NiSoundOff,\n NiSoundOn,\n NiSoundPlus,\n NiSparkle,\n NiSpinner,\n NiSquare,\n NiSquircle,\n NiStar,\n NiStars,\n NiStopwatch,\n NiStore,\n NiStomach,\n NiStructure,\n NiSum,\n NiSun,\n NiSwap,\n NiSwitch,\n NiTablet,\n NiTag,\n NiTelescope,\n NiTemperature,\n NiTent,\n NiTerminal,\n NiTextBold,\n NiTextCenter,\n NiTextFont,\n NiTextItalic,\n NiTextJustify,\n NiTextLeft,\n NiTextQuote,\n NiTextRight,\n NiTextStrikethrough,\n NiTextUnderline,\n NiTextarea,\n NiTicket,\n NiTimeline,\n NiTooth,\n NiToyBoat,\n NiToySky,\n NiToyStacking,\n NiTrade,\n NiTree,\n NiTrendDown,\n NiTrendUp,\n NiTriangleDown,\n NiTriangleLeft,\n NiTriangleRight,\n NiTriangleUp,\n NiTrophy,\n NiTruck,\n NiTubes,\n NiUngroup,\n NiUnlike,\n NiUnlock,\n NiUploadCloud,\n NiUserCheck,\n NiUserCross,\n NiUserMinus,\n NiUserPlus,\n NiUser,\n NiUsers,\n NiVerified,\n NiWalletCrypto,\n NiWallet,\n NiWatch,\n NiWeightScale,\n NiWind,\n NiWorld,\n NiZoomIn,\n NiZoomOut,\n};\n\nexport type IconName = keyof typeof IconMap;\nexport type IconSize = \"large\" | \"medium\" | \"small\" | \"tiny\" | number;\nexport type IconVariant = \"outlined\" | \"contained\";\n\nexport type NextureIconsProps = {\n variant?: IconVariant;\n className?: string;\n size?: IconSize;\n strokeWidth?: number;\n oneTone?: boolean;\n};\n\nexport type NextureIconsPropsComponent = NextureIconsProps & {\n icon: IconName;\n};\n\nconst NextureIcons: React.FC<NextureIconsPropsComponent> = ({\n icon,\n size = 20,\n variant = \"outlined\",\n className,\n strokeWidth = 1.5,\n oneTone = false,\n}) => {\n const IconComponent = IconMap[icon];\n if (!IconComponent) {\n console.warn(`Icon \"${icon}\" not found in IconMap.`);\n return null;\n }\n return (\n <IconComponent variant={variant} size={size} className={className} strokeWidth={strokeWidth} oneTone={oneTone} />\n );\n};\n\nexport const sizeHelper = (size: NextureIconsProps[\"size\"]) => {\n if (typeof size === \"number\") {\n return size;\n } else if (size === \"large\") {\n return 24;\n } else if (size === \"small\" || size === \"tiny\") {\n return 16;\n } else {\n return 20;\n }\n};\n\nexport const strokeSizeHelper = (size: number) => {\n if (size === 32) {\n return 1.15;\n } else if (size >= 20) {\n return 1.5;\n } else {\n return 1.75;\n }\n};\n\nexport default NextureIcons;\n","import type { ReactNode } from \"react\";\nimport {\n Box,\n Button,\n CircularProgress,\n Dialog,\n DialogActions,\n DialogContent,\n DialogContentText,\n DialogTitle,\n} from \"../ui\";\nimport { NiBinEmpty } from \"../../icons\";\n\nexport interface ConfirmDeleteLabels {\n title?: string;\n description?: ReactNode;\n btnCancel?: string;\n btnConfirm?: string;\n btnDeleting?: string;\n}\n\ninterface ConfirmDeleteDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n onConfirm: () => void;\n isDeleting: boolean;\n labels?: ConfirmDeleteLabels;\n className?: string;\n}\n\n/**\n * Generic delete confirmation dialog.\n * Use `labels` to customise title, description and button text.\n * `labels.description` accepts a string or any ReactNode (e.g. JSX with <strong>).\n */\nexport function ConfirmDeleteDialog({\n open,\n onOpenChange,\n onConfirm,\n isDeleting,\n labels,\n}: ConfirmDeleteDialogProps) {\n const title = labels?.title ?? \"Delete?\";\n const description = labels?.description ?? \"Are you sure? This action cannot be undone.\";\n const btnCancel = labels?.btnCancel ?? \"Cancel\";\n const btnConfirm = labels?.btnConfirm ?? \"Delete\";\n const btnDeleting = labels?.btnDeleting ?? \"Deleting...\";\n\n const handleClose = () => {\n if (!isDeleting) onOpenChange(false);\n };\n\n return (\n <Dialog open={open} onClose={handleClose} maxWidth=\"xs\" fullWidth role=\"alertdialog\">\n <DialogTitle className=\"flex items-center gap-2\">\n <Box component=\"span\" sx={{ color: \"error.main\", display: \"inline-flex\" }}>\n <NiBinEmpty size=\"medium\" />\n </Box>\n {title}\n </DialogTitle>\n <DialogContent>\n {typeof description === \"string\" ? (\n <DialogContentText>{description}</DialogContentText>\n ) : (\n <DialogContentText component=\"div\">{description}</DialogContentText>\n )}\n </DialogContent>\n <DialogActions>\n <Button onClick={handleClose} disabled={isDeleting}>\n {btnCancel}\n </Button>\n <Button variant=\"contained\" color=\"error\" onClick={onConfirm} disabled={isDeleting}>\n {isDeleting ? (\n <>\n <CircularProgress size={16} color=\"inherit\" className=\"mr-2\" />\n {btnDeleting}\n </>\n ) : (\n btnConfirm\n )}\n </Button>\n </DialogActions>\n </Dialog>\n );\n}\n","/**\n * Dialog-state hooks shipped alongside the shared confirmation dialogs\n * (`ConfirmActionDialog` / `ConfirmDeleteDialog`), so a plugin's lifted\n * `hooks/common/utility/useConfirmDialog` alias resolves here instead of each\n * plugin re-porting the same open/close/reason boilerplate from the monolith.\n *\n * Pure React state — no host bridge needed; safe in mock/dev and inside the host.\n */\nimport { useCallback, useState } from \"react\";\n\n/**\n * Boolean open/close state for a confirm dialog. Replaces the\n * `const [xOpen, setXOpen] = useState(false)` + inline open/close arrows that detail pages\n * repeated per dialog.\n */\nexport function useConfirmDialog() {\n const [isOpen, setIsOpen] = useState(false);\n const open = useCallback(() => setIsOpen(true), []);\n const close = useCallback(() => setIsOpen(false), []);\n return { isOpen, open, close };\n}\n\n/**\n * Confirm dialog carrying a target payload (e.g. the row being acted on). `isOpen` is derived\n * from whether a target is set; `close()` clears it. Replaces the\n * `const [xTarget, setXTarget] = useState<T | null>(null)` pattern in the list pages.\n */\nexport function useTargetDialog<T>() {\n const [target, setTarget] = useState<T | null>(null);\n const open = useCallback((value: T) => setTarget(value), []);\n const close = useCallback(() => setTarget(null), []);\n return { target, isOpen: target !== null, open, close };\n}\n\n/**\n * Confirm dialog with a free-text reason (e.g. reject/dispute). `close()` resets the reason so\n * the next open starts blank. Replaces the per-page `xOpen` + `reason` state + reset handler.\n */\nexport function useReasonDialog() {\n const [isOpen, setIsOpen] = useState(false);\n const [reason, setReason] = useState(\"\");\n const open = useCallback(() => setIsOpen(true), []);\n const close = useCallback(() => {\n setIsOpen(false);\n setReason(\"\");\n }, []);\n return { isOpen, reason, setReason, open, close };\n}\n","/**\n * Host toast bridge — the ergonomic surface a lifted monolith `useToast()`\n * expects, shipped alongside the other shared composites so a plugin's\n * `components/shared/*` (and its `use-toast` alias) resolve here.\n *\n * PlatformReact pages can't import the host's toaster (it's an app-global\n * singleton, not in the host module registry), so these dispatch the\n * `ethisys:toast` CustomEvent the host's toast listener (`useExtensionToast`)\n * forwards to its toaster — the same wire contract as the lower-level\n * `@ethisyscore/components-react` `showToast` primitive (kept self-contained\n * here to avoid a load-bearing cross-package import for a one-line dispatch).\n * Outside a host that wired the listener (mock/dev), every call is a harmless\n * no-op, so a plugin keeps its lifted `showSuccessToast(...)` call sites.\n */\ntype ToastVariant = \"default\" | \"success\" | \"error\" | \"warning\";\n\nfunction dispatchToast(title: string, description: string | undefined, variant: ToastVariant): void {\n if (typeof window === \"undefined\" || title.length === 0) {\n return;\n }\n window.dispatchEvent(new CustomEvent(\"ethisys:toast\", { detail: { title, description, variant } }));\n}\n\nexport function showSuccessToast(title: string, description?: string): void {\n dispatchToast(title, description, \"success\");\n}\n\nexport function showErrorToast(title: string, description?: string): void {\n dispatchToast(title, description, \"error\");\n}\n\nexport function showWarningToast(title: string, description?: string): void {\n dispatchToast(title, description, \"warning\");\n}\n\n/**\n * Options accepted by the `toast(...)` returned from {@link useToast}. Both `title`\n * and `description` are optional, but at least one must be set — `toast({ description })`\n * shows the description as the message (mirroring the monolith); `toast({})` is a no-op.\n */\nexport interface ToastOptions {\n /** Primary line. Falls back to {@link ToastOptions.description} when absent/empty. */\n title?: string;\n /** Secondary line — or the message itself when no `title` is given. */\n description?: string;\n /** `\"destructive\"`/`\"error\"` → error; `\"warning\"`/`\"success\"` map directly; else default. */\n variant?: string;\n}\n\n/**\n * Hook mirror of the monolith's `useToast()` surface, so a lifted\n * `const { toast } = useToast()` (and `showSuccessToast`/`showErrorToast`) keeps\n * working unchanged once `@/hooks/common/utility/use-toast` is aliased here.\n */\nexport function useToast() {\n return {\n toast: (opts: ToastOptions): void => {\n const variant: ToastVariant =\n opts.variant === \"destructive\" || opts.variant === \"error\"\n ? \"error\"\n : opts.variant === \"warning\"\n ? \"warning\"\n : opts.variant === \"success\"\n ? \"success\"\n : \"default\";\n // `title` is the primary line; fall back to `description` so `toast({ description })`\n // shows it (mirroring the monolith) instead of silently no-op'ing. Both absent → no-op.\n if (opts.title) {\n dispatchToast(opts.title, opts.description, variant);\n } else if (opts.description) {\n dispatchToast(opts.description, undefined, variant);\n }\n },\n showSuccessToast,\n showErrorToast,\n showWarningToast,\n };\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -45,6 +45,22 @@ function isHostChromeCompatible(hostVersion) {
|
|
|
45
45
|
return hostMajor === sdkMajor;
|
|
46
46
|
}
|
|
47
47
|
var SurfaceBaseContext = react.createContext(void 0);
|
|
48
|
+
function stripTrailingSlash(p) {
|
|
49
|
+
return p.length > 1 && p.endsWith("/") ? p.slice(0, -1) : p;
|
|
50
|
+
}
|
|
51
|
+
function deriveHostEntityToken(pathname, basePath) {
|
|
52
|
+
if (!basePath) {
|
|
53
|
+
return pathname;
|
|
54
|
+
}
|
|
55
|
+
const base = stripTrailingSlash(basePath);
|
|
56
|
+
if (pathname === base) {
|
|
57
|
+
return "/";
|
|
58
|
+
}
|
|
59
|
+
if (pathname.startsWith(`${base}/`)) {
|
|
60
|
+
return pathname.slice(base.length);
|
|
61
|
+
}
|
|
62
|
+
return pathname;
|
|
63
|
+
}
|
|
48
64
|
|
|
49
65
|
// src/platform-react/useHostSidebarActions.ts
|
|
50
66
|
var SIDEBAR_MODE = { none: "none", actions: "actions", detail: "detail" };
|
|
@@ -133,9 +149,17 @@ function reportNoHost(pageId) {
|
|
|
133
149
|
}
|
|
134
150
|
function useHostSidebarActions(input) {
|
|
135
151
|
const api = react.useContext(HostSidebarActionsContext);
|
|
136
|
-
const
|
|
152
|
+
const surfaceBase = react.useContext(SurfaceBaseContext);
|
|
153
|
+
const pageId = surfaceBase?.pageId;
|
|
137
154
|
const compatible = api && isHostChromeCompatible(api.capabilities?.contractVersion) ? api : null;
|
|
138
|
-
const
|
|
155
|
+
const resolved = input.mode === SIDEBAR_MODE.none ? input : typeof input.entityToken === "string" ? input : "entityToken" in input ? { mode: SIDEBAR_MODE.none } : {
|
|
156
|
+
...input,
|
|
157
|
+
entityToken: deriveHostEntityToken(
|
|
158
|
+
typeof window !== "undefined" ? window.location.pathname : "",
|
|
159
|
+
surfaceBase?.basePath
|
|
160
|
+
)
|
|
161
|
+
};
|
|
162
|
+
const actions = resolved.mode === SIDEBAR_MODE.none ? [] : resolved.actions;
|
|
139
163
|
const handlers = react.useRef(/* @__PURE__ */ new Map());
|
|
140
164
|
handlers.current = new Map(collectDispatchHandlers(actions));
|
|
141
165
|
react.useEffect(() => {
|
|
@@ -151,10 +175,10 @@ function useHostSidebarActions(input) {
|
|
|
151
175
|
unsub();
|
|
152
176
|
};
|
|
153
177
|
}, [compatible, pageId]);
|
|
154
|
-
const key = contributionKey(
|
|
178
|
+
const key = contributionKey(resolved);
|
|
155
179
|
react.useEffect(() => {
|
|
156
180
|
if (!compatible) return;
|
|
157
|
-
compatible.publish(toContribution(
|
|
181
|
+
compatible.publish(toContribution(resolved));
|
|
158
182
|
}, [compatible, key]);
|
|
159
183
|
}
|
|
160
184
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/currentUser.ts","../src/platform-react/hostSidebarActionsContext.ts","../src/platform-react/surfaceUrl.ts","../src/platform-react/useHostSidebarActions.ts"],"names":["useHostIdentity","createContext","useContext","useRef","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * `useCurrentUser` — the display-only current-user hook for plugin frontends\n * (WI 5154 follow-up #2, plugin-ui host-identity).\n *\n * A plugin page often needs the signed-in user for UX bits — a \"you are signed\n * in as …\" hint, pre-selecting the caller in a sign-off panel, or a\n * \"my acknowledgements\" heading. This hook surfaces that identity from the\n * host without the plugin importing the lower-level {@link useHostIdentity}\n * seam directly.\n *\n * It is a thin adapter over the host-provided {@link HostIdentity} context\n * (bound by the host through `ExtensionRuntimeProvider`'s `identity` prop):\n * it projects the host's richer {@link HostIdentityUser} down to the minimal\n * `{ id, displayName }` shape a plugin page needs for display.\n *\n * ⚠️ SECURITY — DISPLAY ONLY. This is presentation/UX data, NOT an\n * authorization source. Authorization is enforced HOST-SIDE at the MCP\n * boundary: the plugin backend re-authorises every tool/resource call from the\n * trusted server session. Never gate a mutation or a data read on this value.\n *\n * Returns `null` when the host has not provided an identity — standalone / mock\n * hosts, a host that predates the identity seam, or while host auth is still\n * loading or the caller is unauthenticated. Callers MUST handle `null`\n * (this matches the pre-existing plugin `useAuth().user` shim, which returned\n * `undefined`, so adopting this hook is a no-regression change).\n */\nimport { useHostIdentity } from \"@ethisyscore/extension-runtime/plugin\";\n\n/**\n * Minimal current-user shape a plugin page reads for display. Mirrors the\n * identity the host authenticates: a stable `id` and a human-readable\n * `displayName`. (No email — the host identity seam does not currently\n * forward one; if that changes, extend {@link HostIdentityUser} first and\n * project it here.)\n */\nexport interface CurrentUser {\n /** Stable user id (matches the host's authenticated caller id). */\n id: string;\n /** Human-readable display name (the host's full name). */\n displayName: string;\n}\n\n/**\n * Returns the host-authenticated current user projected to the display-only\n * {@link CurrentUser} shape, or `null` when no host identity is available.\n *\n * Display-only — see the module doc: authorization stays host-enforced at the\n * MCP boundary. Do NOT use the returned value as an authorization decision.\n */\nexport function useCurrentUser(): CurrentUser | null {\n const identity = useHostIdentity();\n const user = identity?.user ?? null;\n if (!user) {\n return null;\n }\n return {\n id: user.id,\n // The host binds `fullName`; fall back to composing first + last so a host\n // that only sets the parts still yields a usable display name.\n displayName:\n user.fullName?.trim() || `${user.firstName ?? \"\"} ${user.lastName ?? \"\"}`.trim(),\n };\n}\n","import { createContext } from \"react\";\nimport type { Context } from \"react\";\nimport type { HostSidebarActionsApiShape } from \"@ethisyscore/components-react\";\n\n// ── Cross-bundle singleton keys ───────────────────────────────────────────────\n// tsup may inline this module into BOTH the package-root entry and the subpath\n// entry, producing two distinct module copies. Storing shared state on globalThis\n// under Symbol.for(…) keys guarantees that every copy resolves the SAME object.\nconst CONTEXT_KEY = Symbol.for(\"ethisyscore.plugin-ui.hostSidebarActionsContext\");\nconst SINK_KEY = Symbol.for(\"ethisyscore.plugin-ui.hostChromeDiagnosticSink\");\n\n/** Host-chrome / sidebar-actions contract version (semver). Host MAJOR must equal the SDK\n * MAJOR before any publish/subscribe; otherwise the plugin hook fails closed (WI 5188 batch 2).\n * 2.1.0 added the additive `kind:\"group\"` action variant (collapsible Lifecycle/Share); the\n * major-equality gate keeps 2.0 and 2.1 mutually compatible (older hosts ignore group children). */\nexport const HOST_CHROME_CONTRACT_VERSION = \"2.1.0\";\n\nexport type HostSidebarActionSlot = \"primary\" | \"overflow\" | \"sidebar-only\";\nexport type HostSidebarActionVariant = \"default\" | \"danger\";\n\n/** Fields common to every action. */\ninterface HostSidebarActionBase {\n id: string;\n label: string;\n icon?: string;\n slot?: HostSidebarActionSlot;\n variant?: HostSidebarActionVariant;\n disabled?: boolean;\n active?: boolean;\n /** Optional host-side double-gate: the mask is resolved against the surface extension groupCode. */\n requiredPermission?: number;\n}\n\n/** Strictly serializable action the plugin publishes to the host sidebar — NO functions cross\n * the boundary. Discriminated union so `href` is REQUIRED at the type level for a navigate\n * action and FORBIDDEN for a dispatch action (spec-gate MEDIUM R1-M1 — a navigate with a\n * missing href fails typecheck at authoring time rather than being silently dropped by the host).\n * `kind:\"dispatch\"` is clicked back to the plugin by `id` via the action-emit subscription. */\nexport type HostSidebarActionDescriptor =\n | (HostSidebarActionBase & { kind: \"dispatch\" })\n | (HostSidebarActionBase & { kind: \"navigate\"; href: string }) // extension-relative; host normalizes/validates\n // A collapsible parent (e.g. Lifecycle / Share). It carries no behaviour of its own — the host\n // renders it as an accordion and its `children` as the collapsed rows. `children` is recursive:\n // each child is a navigate/dispatch action OR a nested group.\n | (HostSidebarActionBase & { kind: \"group\"; children: HostSidebarActionDescriptor[] });\n\n/** A navigation leaf the plugin drives into the host detail sidebar. `href` is extension-relative;\n * the host canonicalises + confines it to `/extensions/<slug>/…` (host-owned, never trusted). */\nexport interface HostSidebarNavItem {\n id: string;\n label: string;\n icon?: string;\n href: string;\n}\n\n/** The single publish payload. `none` = contribute nothing (do NOT clobber the static manifest\n * actions); `actions` = batch-2 Quick Actions for a detail entity; `detail` = full detail-nav\n * REPLACEMENT (title + nav items + back-arrow + Quick Actions). `identityEpoch` is host-stamped\n * (plan D-1), so it is not part of this plugin-published shape. */\nexport type HostSidebarContribution =\n | { mode: \"none\" }\n | { mode: \"actions\"; entityToken: string; actions: HostSidebarActionDescriptor[] }\n | {\n mode: \"detail\";\n entityToken: string;\n title: string;\n navSectionLabel: string;\n navItems: HostSidebarNavItem[];\n backHref: string;\n backLabel: string;\n actions: HostSidebarActionDescriptor[];\n };\n\nexport interface HostSidebarActionsCapabilities {\n readonly contractVersion: string; // HOST_CHROME_CONTRACT_VERSION the host implements\n}\n\n/** Host-provided API, passed to a PlatformReact page as the `hostSidebar` prop and read via\n * the plugin-bundled context. Additive-only. */\nexport interface HostSidebarActionsApi {\n /** Replace the surface's sidebar contribution. The host rejects a publish whose entityToken ≠\n * its current location-derived token, rejects duplicate action ids, and — for mode:\"detail\" —\n * rejects/atomically-drops an invalid or href-unsafe context (falls back to main nav). */\n publish(contribution: HostSidebarContribution): void;\n /** Revert to the static-manifest fallback (publication state = unpublished). */\n clear(): void;\n /** Subscribe to click dispatch for `kind:\"dispatch\"` actions. The host emits the clicked\n * action id. Returns an unsubscribe. The plugin bridge subscribes exactly once. */\n subscribe(onAction: (actionId: string) => void): () => void;\n readonly capabilities: HostSidebarActionsCapabilities;\n}\n\n/** Props the host injects into a page for the sidebar-actions seam (merged into PlatformReactPageProps).\n * Typed against the dependency-neutral `HostSidebarActionsApiShape` — the SAME type\n * `PlatformReactPageProps.hostSidebar` uses in `@ethisyscore/components-react` — so this\n * convenience alias never diverges from the canonical page-props declaration. The concrete\n * `HostSidebarActionsApi` is structurally assignable to the shape; the page bridge narrows to\n * it internally. */\nexport interface HostSidebarActionsPageProps {\n hostSidebar?: HostSidebarActionsApiShape;\n}\n\ntype GlobalWithCtx = typeof globalThis & {\n [CONTEXT_KEY]?: Context<HostSidebarActionsApi | null>;\n};\nconst _g = globalThis as GlobalWithCtx;\nexport const HostSidebarActionsContext: Context<HostSidebarActionsApi | null> =\n _g[CONTEXT_KEY] ?? (_g[CONTEXT_KEY] = createContext<HostSidebarActionsApi | null>(null));\n\n// ── Diagnostics adapter (concrete, testable — spec-gate HIGH R1-H3) ─────────────\n// A single injectable sink so degradation is OBSERVABLE in all environments without inventing a\n// `globalThis` global. The host runtime calls `setHostChromeDiagnosticSink` once to route these to\n// its real telemetry; absent a sink it is a safe no-op. Every emission carries the page id tag.\n//\n// The sink is stored on the SINK_KEY globalThis slot so that setHostChromeDiagnosticSink and\n// reportHostChromeDiagnostic in any duplicate module copy read/write the SAME slot.\nexport interface HostChromeDiagnostic {\n event: string;\n pageId?: string;\n detail?: unknown;\n}\ntype DiagnosticSinkFn = (d: HostChromeDiagnostic) => void;\ntype GlobalWithSink = typeof globalThis & { [SINK_KEY]?: DiagnosticSinkFn };\nconst _gs = globalThis as GlobalWithSink;\nif (_gs[SINK_KEY] === undefined) {\n _gs[SINK_KEY] = () => {};\n}\nexport function setHostChromeDiagnosticSink(sink: DiagnosticSinkFn): void {\n _gs[SINK_KEY] = sink;\n}\nexport function reportHostChromeDiagnostic(d: HostChromeDiagnostic): void {\n try {\n _gs[SINK_KEY]!(d);\n } catch {\n /* diagnostics are best-effort — never throw into the plugin */\n }\n}\n\n/** Major-equality compatibility check; fail-closed on absent/unparseable input. */\nexport function isHostChromeCompatible(hostVersion: string | undefined): boolean {\n if (hostVersion === undefined) return false;\n const hostMajor = Number.parseInt(hostVersion.split(\".\")[0] ?? \"\", 10);\n const sdkMajor = Number.parseInt(HOST_CHROME_CONTRACT_VERSION.split(\".\")[0] ?? \"\", 10);\n if (Number.isNaN(hostMajor) || Number.isNaN(sdkMajor)) return false;\n return hostMajor === sdkMajor;\n}\n","import { createContext, useContext } from \"react\";\nimport { useHostIdentity } from \"@ethisyscore/extension-runtime/plugin\";\n\n/** The surface's mount context, provided by definePlatformReactPluginPage. */\nexport interface SurfaceBaseValue {\n /** Host-provided mount path `/extensions/<slug>/<pageId>` (authoritative). */\n basePath?: string;\n /** The page id (from PlatformReactPageProps), used for the derived fallback. */\n pageId?: string;\n}\n\nexport const SurfaceBaseContext = createContext<SurfaceBaseValue | undefined>(undefined);\n\n/** Match the host's slug normalisation (useExtensionSurfaceShellPage `normaliseSlug`). */\nexport function normaliseSlug(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction stripTrailingSlash(p: string): string {\n return p.length > 1 && p.endsWith(\"/\") ? p.slice(0, -1) : p;\n}\n\n/**\n * Resolve the surface base. Precedence: host-provided basePath → derived from\n * normaliseSlug(extensionGroupCode) + pageId → null (caller decides how to fail).\n * Pure — callers read context + identity and pass the pieces in.\n */\nexport function resolveSurfaceBase(input: {\n basePath?: string;\n pageId?: string;\n extensionGroupCode?: string | null;\n}): { base: string; groupRoot: string } | null {\n if (input.basePath) {\n const base = stripTrailingSlash(input.basePath);\n const cut = base.lastIndexOf(\"/\");\n const groupRoot = cut > 0 ? base.slice(0, cut) : base;\n return { base, groupRoot };\n }\n const slug = input.extensionGroupCode ? normaliseSlug(input.extensionGroupCode) : \"\";\n const pageId = input.pageId ?? \"\";\n if (slug && pageId) {\n const groupRoot = `/extensions/${slug}`;\n return { base: `${groupRoot}/${pageId}`, groupRoot };\n }\n return null;\n}\n\n/** Join base + sub (leading slash stripped) + optional ?query/#hash suffix. */\nexport function buildSurfaceUrl(base: string, sub = \"\", suffix = \"\"): string {\n const b = stripTrailingSlash(base);\n const s = sub.replace(/^\\/+/, \"\");\n const path = s ? `${b}/${s}` : b;\n return suffix ? `${path}${suffix}` : path;\n}\n\n/**\n * Hook: build a URL relative to the CURRENT surface. Precedence per\n * resolveSurfaceBase; throws in dev when unresolved (never returns app-root).\n */\nexport function useSurfaceUrl(): (sub?: string, suffix?: string) => string {\n const ctx = useContext(SurfaceBaseContext);\n const identity = useHostIdentity();\n return (sub = \"\", suffix = \"\") => {\n const resolved = resolveSurfaceBase({\n basePath: ctx?.basePath,\n pageId: ctx?.pageId,\n extensionGroupCode: identity?.extensionGroupCode ?? null,\n });\n if (!resolved) {\n const msg =\n \"useSurfaceUrl: no surface base — SurfaceBaseContext (basePath/pageId) and \" +\n \"extensionGroupCode are both unavailable. Ensure the page is wrapped by \" +\n \"definePlatformReactPluginPage inside the host runtime.\";\n // Dev: fail loud. Prod: never navigate to app-root (that recreates the 404\n // class) — stay on the current path (a no-op) so a transient unresolved\n // state (e.g. identity still loading on a pre-basePath host) can't crash the\n // surface. Callers invoke this in event handlers, by which time identity has\n // loaded and the base resolves normally.\n // Guard `process` access: in a browser/ESM consumer where `process` is\n // undefined, reading `process.env.NODE_ENV` directly would throw a\n // ReferenceError before the prod fallback runs. `typeof` never throws on an\n // undeclared identifier. Fail SAFE — throw ONLY when we can positively\n // confirm a non-production env; an unknown env (no `process`) is treated as\n // production so a bundled surface never crashes here.\n const isDevEnv =\n typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\";\n if (isDevEnv) throw new Error(msg);\n if (typeof console !== \"undefined\") console.error(msg);\n // Prod no-op: stay on the FULL current URL (path + query + hash) — a true\n // no-op, and never app-root.\n return typeof window !== \"undefined\"\n ? window.location.pathname + window.location.search + window.location.hash\n : \"\";\n }\n return buildSurfaceUrl(resolved.base, sub, suffix);\n };\n}\n\n/** Pure: build a URL for ANOTHER surface (cross-surface, e.g. an overlay opening a page). */\nexport function surfacePathFor(opts: {\n slug: string;\n pageId: string;\n sub?: string;\n suffix?: string;\n}): string {\n const base = `/extensions/${normaliseSlug(opts.slug)}/${opts.pageId}`;\n return buildSurfaceUrl(base, opts.sub ?? \"\", opts.suffix ?? \"\");\n}\n","import { useContext, useEffect, useRef } from \"react\";\nimport {\n HostSidebarActionsContext,\n isHostChromeCompatible,\n reportHostChromeDiagnostic,\n type HostSidebarActionDescriptor,\n type HostSidebarActionsApi,\n type HostSidebarContribution,\n type HostSidebarNavItem,\n} from \"./hostSidebarActionsContext\";\nimport { SurfaceBaseContext } from \"./surfaceUrl\";\n\n/** Authoring shape: a descriptor plus — ONLY for `kind:\"dispatch\"` — an inline handler.\n * A distributive union (not a blanket intersection over the whole descriptor union): `onSelect`\n * is permitted only on a dispatch action. A navigate action carries no handler (the host performs\n * the navigation from `href`), so supplying `onSelect` on a navigate action is a typecheck error\n * rather than a silently-ignored footgun. The hook strips `onSelect` before publishing (only\n * serializable descriptors cross to the host). */\nexport type HostSidebarAction =\n | (Extract<HostSidebarActionDescriptor, { kind: \"dispatch\" }> & { onSelect?: () => void })\n | Extract<HostSidebarActionDescriptor, { kind: \"navigate\" }>\n // A collapsible group whose `children` are themselves authoring actions (so a dispatch child can\n // still carry its inline `onSelect`). `children` overrides the descriptor's serializable children.\n | (Omit<Extract<HostSidebarActionDescriptor, { kind: \"group\" }>, \"children\"> & { children: HostSidebarAction[] });\n\n/** Single source for the discriminant values used across the mode checks, `toContribution`, and\n * the content key — so the \"none\"/\"actions\"/\"detail\" strings live in one place. The union type\n * below intentionally keeps its literal members (they ARE the discriminant + drive IntelliSense);\n * `SIDEBAR_MODE.*` is `as const`, so it is type-identical to those literals. */\nexport const SIDEBAR_MODE = { none: \"none\", actions: \"actions\", detail: \"detail\" } as const;\n\n/** Discriminated input to `useHostSidebarActions`. `mode:\"none\"` suppresses all plugin-side\n * contributions without clobbering the static manifest actions. `mode:\"actions\"` is the\n * batch-2 Quick Actions shape. `mode:\"detail\"` is the full detail-nav replacement with title,\n * navigation items, back-arrow, and Quick Actions. */\nexport type HostSidebarInput =\n | { mode: \"none\" }\n | { mode: \"actions\"; entityToken: string; actions: HostSidebarAction[] }\n | {\n mode: \"detail\";\n entityToken: string;\n title: string;\n navSectionLabel: string;\n navItems: HostSidebarNavItem[];\n backHref: string;\n backLabel: string;\n actions: HostSidebarAction[];\n };\n\nfunction toDescriptor(a: HostSidebarAction): HostSidebarActionDescriptor {\n if (a.kind === \"dispatch\") {\n const { onSelect: _drop, ...rest } = a;\n return rest; // rest is the serializable dispatch descriptor\n }\n if (a.kind === \"group\") {\n // Recurse: strip the children's `onSelect` handlers so only serializable descriptors cross.\n const { children, ...rest } = a;\n return { ...rest, children: children.map(toDescriptor) };\n }\n return a; // navigate descriptor is already serializable (no handler)\n}\n\n/** Flatten a (possibly nested) action tree to its `kind:\"dispatch\"` handler entries — a group's\n * child dispatch clicks must reach their `onSelect` just like a top-level dispatch action. */\nfunction collectDispatchHandlers(actions: HostSidebarAction[]): Array<readonly [string, () => void]> {\n return actions.flatMap((a) =>\n a.kind === \"dispatch\" && a.onSelect\n ? [[a.id, a.onSelect] as const]\n : a.kind === \"group\"\n ? collectDispatchHandlers(a.children)\n : [],\n );\n}\n\n/** Map a plugin-authoring input to the serializable contribution published to the host.\n * `onSelect` handlers are stripped via `toDescriptor`; nav/back/title pass through for `detail`. */\nfunction toContribution(input: HostSidebarInput): HostSidebarContribution {\n if (input.mode === SIDEBAR_MODE.none) {\n return { mode: SIDEBAR_MODE.none };\n }\n if (input.mode === SIDEBAR_MODE.actions) {\n return {\n mode: SIDEBAR_MODE.actions,\n entityToken: input.entityToken,\n actions: input.actions.map(toDescriptor),\n };\n }\n // mode === \"detail\"\n return {\n mode: SIDEBAR_MODE.detail,\n entityToken: input.entityToken,\n title: input.title,\n navSectionLabel: input.navSectionLabel,\n navItems: input.navItems,\n backHref: input.backHref,\n backLabel: input.backLabel,\n actions: input.actions.map(toDescriptor),\n };\n}\n\n/** Content key so we republish only when the visible descriptor set changes. JSON-encodes an\n * ARRAY of ORDERED-tuple arrays: element order is stable (unlike object property insertion order,\n * which is why we avoid `JSON.stringify` over the raw descriptor objects — spec-gate MEDIUM R1-M2),\n * and JSON string-escaping makes the key delimiter-collision-proof, so a `label`/`href` that\n * happens to contain a separator character can no longer alias two distinct action sets to the\n * same key (which would skip a needed republish and leave the host sidebar stale). */\nfunction contributionKey(input: HostSidebarInput): string {\n if (input.mode === SIDEBAR_MODE.none) {\n return JSON.stringify([SIDEBAR_MODE.none]);\n }\n const actionTuple = (a: HostSidebarAction): unknown[] => [\n a.id,\n a.label,\n a.icon ?? \"\",\n a.slot ?? \"\",\n a.variant ?? \"\",\n a.disabled ? 1 : 0,\n a.active ? 1 : 0,\n a.requiredPermission ?? \"\",\n a.kind,\n a.kind === \"navigate\" ? a.href : \"\",\n // Group children fold into the key so a change to any collapsed leaf forces a republish.\n a.kind === \"group\" ? a.children.map(actionTuple) : \"\",\n ];\n const actionTuples = input.actions.map(actionTuple);\n if (input.mode === SIDEBAR_MODE.actions) {\n return JSON.stringify([SIDEBAR_MODE.actions, input.entityToken, actionTuples]);\n }\n // mode === \"detail\"\n const navTuples = input.navItems.map((n) => [n.id, n.label, n.icon ?? \"\", n.href]);\n return JSON.stringify([\n SIDEBAR_MODE.detail,\n input.entityToken,\n input.title,\n input.navSectionLabel,\n input.backHref,\n input.backLabel,\n navTuples,\n actionTuples,\n ]);\n}\n\n/** Per-page dev-warn throttle (NOT a global boolean — a module singleton would suppress warnings\n * for every later surface in a shared bundle; spec-gate HIGH R1-H2). Telemetry fires every time. */\nconst devWarnedPages = new Set<string>();\nfunction reportNoHost(pageId: string | undefined): void {\n // Observable in ALL environments via the injected diagnostic sink, tagged by page id (R1-H3).\n reportHostChromeDiagnostic({ event: \"host_sidebar_actions_unavailable\", pageId });\n const key = pageId ?? \"*\";\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((import.meta as any).env?.DEV && !devWarnedPages.has(key)) {\n devWarnedPages.add(key);\n // eslint-disable-next-line no-console\n console.warn(\n `[plugin-ui] useHostSidebarActions (${key}): no compatible host sidebar-actions API — ` +\n \"the host predates the seam or its contract major differs. Quick Actions will not render.\",\n );\n }\n}\n\n/**\n * Publish contextual sidebar contributions from a PlatformReact page to the host sidebar, and\n * receive click dispatch by id. Accepts a discriminated `HostSidebarInput`:\n * - `mode:\"none\"` — suppress all plugin contributions without clobbering the static manifest.\n * - `mode:\"actions\"` — batch-2 Quick Actions for a detail entity (entity token + action list).\n * - `mode:\"detail\"` — full detail-nav replacement (title, nav items, back-arrow, Quick Actions).\n *\n * Serializable descriptors only cross to the host; the inline `onSelect` handlers stay in a\n * ref-map here and are always the latest closure. Fails closed (no publish/subscribe, no throw)\n * when the host predates or is incompatible with the seam. */\nexport function useHostSidebarActions(input: HostSidebarInput): void {\n const api = useContext(HostSidebarActionsContext);\n const pageId = useContext(SurfaceBaseContext)?.pageId; // diagnostic tag (per-surface)\n const compatible: HostSidebarActionsApi | null =\n api && isHostChromeCompatible(api.capabilities?.contractVersion) ? api : null;\n\n // Ref-map refreshed every render → dispatch always hits the latest handler (recursing groups).\n const actions = input.mode === SIDEBAR_MODE.none ? [] : input.actions;\n const handlers = useRef<Map<string, () => void>>(new Map());\n handlers.current = new Map(collectDispatchHandlers(actions));\n\n useEffect(() => {\n if (!compatible) {\n reportNoHost(pageId);\n return;\n }\n const unsub = compatible.subscribe((id) => {\n handlers.current.get(id)?.();\n });\n return () => {\n compatible.clear();\n unsub();\n };\n }, [compatible, pageId]);\n\n // Content key: mode + entityToken + descriptor tuples + (detail) nav/back/title.\n const key = contributionKey(input);\n useEffect(() => {\n if (!compatible) return;\n compatible.publish(toContribution(input));\n // key encodes all content that affects the published contribution; changes force republish.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [compatible, key]);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/currentUser.ts","../src/platform-react/hostSidebarActionsContext.ts","../src/platform-react/surfaceUrl.ts","../src/platform-react/useHostSidebarActions.ts"],"names":["useHostIdentity","createContext","useContext","useRef","useEffect"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * `useCurrentUser` — the display-only current-user hook for plugin frontends\n * (WI 5154 follow-up #2, plugin-ui host-identity).\n *\n * A plugin page often needs the signed-in user for UX bits — a \"you are signed\n * in as …\" hint, pre-selecting the caller in a sign-off panel, or a\n * \"my acknowledgements\" heading. This hook surfaces that identity from the\n * host without the plugin importing the lower-level {@link useHostIdentity}\n * seam directly.\n *\n * It is a thin adapter over the host-provided {@link HostIdentity} context\n * (bound by the host through `ExtensionRuntimeProvider`'s `identity` prop):\n * it projects the host's richer {@link HostIdentityUser} down to the minimal\n * `{ id, displayName }` shape a plugin page needs for display.\n *\n * ⚠️ SECURITY — DISPLAY ONLY. This is presentation/UX data, NOT an\n * authorization source. Authorization is enforced HOST-SIDE at the MCP\n * boundary: the plugin backend re-authorises every tool/resource call from the\n * trusted server session. Never gate a mutation or a data read on this value.\n *\n * Returns `null` when the host has not provided an identity — standalone / mock\n * hosts, a host that predates the identity seam, or while host auth is still\n * loading or the caller is unauthenticated. Callers MUST handle `null`\n * (this matches the pre-existing plugin `useAuth().user` shim, which returned\n * `undefined`, so adopting this hook is a no-regression change).\n */\nimport { useHostIdentity } from \"@ethisyscore/extension-runtime/plugin\";\n\n/**\n * Minimal current-user shape a plugin page reads for display. Mirrors the\n * identity the host authenticates: a stable `id` and a human-readable\n * `displayName`. (No email — the host identity seam does not currently\n * forward one; if that changes, extend {@link HostIdentityUser} first and\n * project it here.)\n */\nexport interface CurrentUser {\n /** Stable user id (matches the host's authenticated caller id). */\n id: string;\n /** Human-readable display name (the host's full name). */\n displayName: string;\n}\n\n/**\n * Returns the host-authenticated current user projected to the display-only\n * {@link CurrentUser} shape, or `null` when no host identity is available.\n *\n * Display-only — see the module doc: authorization stays host-enforced at the\n * MCP boundary. Do NOT use the returned value as an authorization decision.\n */\nexport function useCurrentUser(): CurrentUser | null {\n const identity = useHostIdentity();\n const user = identity?.user ?? null;\n if (!user) {\n return null;\n }\n return {\n id: user.id,\n // The host binds `fullName`; fall back to composing first + last so a host\n // that only sets the parts still yields a usable display name.\n displayName:\n user.fullName?.trim() || `${user.firstName ?? \"\"} ${user.lastName ?? \"\"}`.trim(),\n };\n}\n","import { createContext } from \"react\";\nimport type { Context } from \"react\";\nimport type { HostSidebarActionsApiShape } from \"@ethisyscore/components-react\";\n\n// ── Cross-bundle singleton keys ───────────────────────────────────────────────\n// tsup may inline this module into BOTH the package-root entry and the subpath\n// entry, producing two distinct module copies. Storing shared state on globalThis\n// under Symbol.for(…) keys guarantees that every copy resolves the SAME object.\nconst CONTEXT_KEY = Symbol.for(\"ethisyscore.plugin-ui.hostSidebarActionsContext\");\nconst SINK_KEY = Symbol.for(\"ethisyscore.plugin-ui.hostChromeDiagnosticSink\");\n\n/** Host-chrome / sidebar-actions contract version (semver). Host MAJOR must equal the SDK\n * MAJOR before any publish/subscribe; otherwise the plugin hook fails closed (WI 5188 batch 2).\n * 2.1.0 added the additive `kind:\"group\"` action variant (collapsible Lifecycle/Share); the\n * major-equality gate keeps 2.0 and 2.1 mutually compatible (older hosts ignore group children). */\nexport const HOST_CHROME_CONTRACT_VERSION = \"2.1.0\";\n\nexport type HostSidebarActionSlot = \"primary\" | \"overflow\" | \"sidebar-only\";\nexport type HostSidebarActionVariant = \"default\" | \"danger\";\n\n/** Fields common to every action. */\ninterface HostSidebarActionBase {\n id: string;\n label: string;\n icon?: string;\n slot?: HostSidebarActionSlot;\n variant?: HostSidebarActionVariant;\n disabled?: boolean;\n active?: boolean;\n /** Optional host-side double-gate: the mask is resolved against the surface extension groupCode. */\n requiredPermission?: number;\n}\n\n/** Strictly serializable action the plugin publishes to the host sidebar — NO functions cross\n * the boundary. Discriminated union so `href` is REQUIRED at the type level for a navigate\n * action and FORBIDDEN for a dispatch action (spec-gate MEDIUM R1-M1 — a navigate with a\n * missing href fails typecheck at authoring time rather than being silently dropped by the host).\n * `kind:\"dispatch\"` is clicked back to the plugin by `id` via the action-emit subscription. */\nexport type HostSidebarActionDescriptor =\n | (HostSidebarActionBase & { kind: \"dispatch\" })\n | (HostSidebarActionBase & { kind: \"navigate\"; href: string }) // extension-relative; host normalizes/validates\n // A collapsible parent (e.g. Lifecycle / Share). It carries no behaviour of its own — the host\n // renders it as an accordion and its `children` as the collapsed rows. `children` is recursive:\n // each child is a navigate/dispatch action OR a nested group.\n | (HostSidebarActionBase & { kind: \"group\"; children: HostSidebarActionDescriptor[] });\n\n/** A navigation leaf the plugin drives into the host detail sidebar. `href` is extension-relative;\n * the host canonicalises + confines it to `/extensions/<slug>/…` (host-owned, never trusted). */\nexport interface HostSidebarNavItem {\n id: string;\n label: string;\n icon?: string;\n href: string;\n}\n\n/** The single publish payload. `none` = contribute nothing (do NOT clobber the static manifest\n * actions); `actions` = batch-2 Quick Actions for a detail entity; `detail` = full detail-nav\n * REPLACEMENT (title + nav items + back-arrow + Quick Actions). `identityEpoch` is host-stamped\n * (plan D-1), so it is not part of this plugin-published shape. */\nexport type HostSidebarContribution =\n | { mode: \"none\" }\n | { mode: \"actions\"; entityToken: string; actions: HostSidebarActionDescriptor[] }\n | {\n mode: \"detail\";\n entityToken: string;\n title: string;\n navSectionLabel: string;\n navItems: HostSidebarNavItem[];\n backHref: string;\n backLabel: string;\n actions: HostSidebarActionDescriptor[];\n };\n\nexport interface HostSidebarActionsCapabilities {\n readonly contractVersion: string; // HOST_CHROME_CONTRACT_VERSION the host implements\n}\n\n/** Host-provided API, passed to a PlatformReact page as the `hostSidebar` prop and read via\n * the plugin-bundled context. Additive-only. */\nexport interface HostSidebarActionsApi {\n /** Replace the surface's sidebar contribution. The host rejects a publish whose entityToken ≠\n * its current location-derived token, rejects duplicate action ids, and — for mode:\"detail\" —\n * rejects/atomically-drops an invalid or href-unsafe context (falls back to main nav). */\n publish(contribution: HostSidebarContribution): void;\n /** Revert to the static-manifest fallback (publication state = unpublished). */\n clear(): void;\n /** Subscribe to click dispatch for `kind:\"dispatch\"` actions. The host emits the clicked\n * action id. Returns an unsubscribe. The plugin bridge subscribes exactly once. */\n subscribe(onAction: (actionId: string) => void): () => void;\n readonly capabilities: HostSidebarActionsCapabilities;\n}\n\n/** Props the host injects into a page for the sidebar-actions seam (merged into PlatformReactPageProps).\n * Typed against the dependency-neutral `HostSidebarActionsApiShape` — the SAME type\n * `PlatformReactPageProps.hostSidebar` uses in `@ethisyscore/components-react` — so this\n * convenience alias never diverges from the canonical page-props declaration. The concrete\n * `HostSidebarActionsApi` is structurally assignable to the shape; the page bridge narrows to\n * it internally. */\nexport interface HostSidebarActionsPageProps {\n hostSidebar?: HostSidebarActionsApiShape;\n}\n\ntype GlobalWithCtx = typeof globalThis & {\n [CONTEXT_KEY]?: Context<HostSidebarActionsApi | null>;\n};\nconst _g = globalThis as GlobalWithCtx;\nexport const HostSidebarActionsContext: Context<HostSidebarActionsApi | null> =\n _g[CONTEXT_KEY] ?? (_g[CONTEXT_KEY] = createContext<HostSidebarActionsApi | null>(null));\n\n// ── Diagnostics adapter (concrete, testable — spec-gate HIGH R1-H3) ─────────────\n// A single injectable sink so degradation is OBSERVABLE in all environments without inventing a\n// `globalThis` global. The host runtime calls `setHostChromeDiagnosticSink` once to route these to\n// its real telemetry; absent a sink it is a safe no-op. Every emission carries the page id tag.\n//\n// The sink is stored on the SINK_KEY globalThis slot so that setHostChromeDiagnosticSink and\n// reportHostChromeDiagnostic in any duplicate module copy read/write the SAME slot.\nexport interface HostChromeDiagnostic {\n event: string;\n pageId?: string;\n detail?: unknown;\n}\ntype DiagnosticSinkFn = (d: HostChromeDiagnostic) => void;\ntype GlobalWithSink = typeof globalThis & { [SINK_KEY]?: DiagnosticSinkFn };\nconst _gs = globalThis as GlobalWithSink;\nif (_gs[SINK_KEY] === undefined) {\n _gs[SINK_KEY] = () => {};\n}\nexport function setHostChromeDiagnosticSink(sink: DiagnosticSinkFn): void {\n _gs[SINK_KEY] = sink;\n}\nexport function reportHostChromeDiagnostic(d: HostChromeDiagnostic): void {\n try {\n _gs[SINK_KEY]!(d);\n } catch {\n /* diagnostics are best-effort — never throw into the plugin */\n }\n}\n\n/** Major-equality compatibility check; fail-closed on absent/unparseable input. */\nexport function isHostChromeCompatible(hostVersion: string | undefined): boolean {\n if (hostVersion === undefined) return false;\n const hostMajor = Number.parseInt(hostVersion.split(\".\")[0] ?? \"\", 10);\n const sdkMajor = Number.parseInt(HOST_CHROME_CONTRACT_VERSION.split(\".\")[0] ?? \"\", 10);\n if (Number.isNaN(hostMajor) || Number.isNaN(sdkMajor)) return false;\n return hostMajor === sdkMajor;\n}\n","import { createContext, useContext } from \"react\";\nimport { useHostIdentity } from \"@ethisyscore/extension-runtime/plugin\";\n\n/** The surface's mount context, provided by definePlatformReactPluginPage. */\nexport interface SurfaceBaseValue {\n /** Host-provided mount path `/extensions/<slug>/<pageId>` (authoritative). */\n basePath?: string;\n /** The page id (from PlatformReactPageProps), used for the derived fallback. */\n pageId?: string;\n}\n\nexport const SurfaceBaseContext = createContext<SurfaceBaseValue | undefined>(undefined);\n\n/** Match the host's slug normalisation (useExtensionSurfaceShellPage `normaliseSlug`). */\nexport function normaliseSlug(value: string): string {\n return value.trim().toLowerCase();\n}\n\nfunction stripTrailingSlash(p: string): string {\n return p.length > 1 && p.endsWith(\"/\") ? p.slice(0, -1) : p;\n}\n\n/**\n * Resolve the surface base. Precedence: host-provided basePath → derived from\n * normaliseSlug(extensionGroupCode) + pageId → null (caller decides how to fail).\n * Pure — callers read context + identity and pass the pieces in.\n */\nexport function resolveSurfaceBase(input: {\n basePath?: string;\n pageId?: string;\n extensionGroupCode?: string | null;\n}): { base: string; groupRoot: string } | null {\n if (input.basePath) {\n const base = stripTrailingSlash(input.basePath);\n const cut = base.lastIndexOf(\"/\");\n const groupRoot = cut > 0 ? base.slice(0, cut) : base;\n return { base, groupRoot };\n }\n const slug = input.extensionGroupCode ? normaliseSlug(input.extensionGroupCode) : \"\";\n const pageId = input.pageId ?? \"\";\n if (slug && pageId) {\n const groupRoot = `/extensions/${slug}`;\n return { base: `${groupRoot}/${pageId}`, groupRoot };\n }\n return null;\n}\n\n/**\n * Mirror of the HOST mount's `deriveEntityToken` (PlatformReactSurfaceMount): the\n * route sub-path relative to the PAGE-surface `basePath` — which is the page\n * route's STATIC leading segments, so a fully-static page (list routes) yields\n * `\"/\"` because there the pathname IS the basePath. The host silently drops a\n * publish whose `entityToken` doesn't match its own derivation, so this must stay\n * bit-identical to the host helper. No basePath (legacy host) falls back to the\n * full pathname, exactly like the host does.\n */\nexport function deriveHostEntityToken(pathname: string, basePath: string | undefined): string {\n if (!basePath) {\n return pathname;\n }\n const base = stripTrailingSlash(basePath);\n if (pathname === base) {\n return \"/\";\n }\n if (pathname.startsWith(`${base}/`)) {\n return pathname.slice(base.length);\n }\n return pathname;\n}\n\n/** Join base + sub (leading slash stripped) + optional ?query/#hash suffix. */\nexport function buildSurfaceUrl(base: string, sub = \"\", suffix = \"\"): string {\n const b = stripTrailingSlash(base);\n const s = sub.replace(/^\\/+/, \"\");\n const path = s ? `${b}/${s}` : b;\n return suffix ? `${path}${suffix}` : path;\n}\n\n/**\n * Hook: build a URL relative to the CURRENT surface. Precedence per\n * resolveSurfaceBase; throws in dev when unresolved (never returns app-root).\n */\nexport function useSurfaceUrl(): (sub?: string, suffix?: string) => string {\n const ctx = useContext(SurfaceBaseContext);\n const identity = useHostIdentity();\n return (sub = \"\", suffix = \"\") => {\n const resolved = resolveSurfaceBase({\n basePath: ctx?.basePath,\n pageId: ctx?.pageId,\n extensionGroupCode: identity?.extensionGroupCode ?? null,\n });\n if (!resolved) {\n const msg =\n \"useSurfaceUrl: no surface base — SurfaceBaseContext (basePath/pageId) and \" +\n \"extensionGroupCode are both unavailable. Ensure the page is wrapped by \" +\n \"definePlatformReactPluginPage inside the host runtime.\";\n // Dev: fail loud. Prod: never navigate to app-root (that recreates the 404\n // class) — stay on the current path (a no-op) so a transient unresolved\n // state (e.g. identity still loading on a pre-basePath host) can't crash the\n // surface. Callers invoke this in event handlers, by which time identity has\n // loaded and the base resolves normally.\n // Guard `process` access: in a browser/ESM consumer where `process` is\n // undefined, reading `process.env.NODE_ENV` directly would throw a\n // ReferenceError before the prod fallback runs. `typeof` never throws on an\n // undeclared identifier. Fail SAFE — throw ONLY when we can positively\n // confirm a non-production env; an unknown env (no `process`) is treated as\n // production so a bundled surface never crashes here.\n const isDevEnv =\n typeof process !== \"undefined\" && process.env?.NODE_ENV !== \"production\";\n if (isDevEnv) throw new Error(msg);\n if (typeof console !== \"undefined\") console.error(msg);\n // Prod no-op: stay on the FULL current URL (path + query + hash) — a true\n // no-op, and never app-root.\n return typeof window !== \"undefined\"\n ? window.location.pathname + window.location.search + window.location.hash\n : \"\";\n }\n return buildSurfaceUrl(resolved.base, sub, suffix);\n };\n}\n\n/** Pure: build a URL for ANOTHER surface (cross-surface, e.g. an overlay opening a page). */\nexport function surfacePathFor(opts: {\n slug: string;\n pageId: string;\n sub?: string;\n suffix?: string;\n}): string {\n const base = `/extensions/${normaliseSlug(opts.slug)}/${opts.pageId}`;\n return buildSurfaceUrl(base, opts.sub ?? \"\", opts.suffix ?? \"\");\n}\n","import { useContext, useEffect, useRef } from \"react\";\nimport {\n HostSidebarActionsContext,\n isHostChromeCompatible,\n reportHostChromeDiagnostic,\n type HostSidebarActionDescriptor,\n type HostSidebarActionsApi,\n type HostSidebarContribution,\n type HostSidebarNavItem,\n} from \"./hostSidebarActionsContext\";\nimport { SurfaceBaseContext, deriveHostEntityToken } from \"./surfaceUrl\";\n\n/** Authoring shape: a descriptor plus — ONLY for `kind:\"dispatch\"` — an inline handler.\n * A distributive union (not a blanket intersection over the whole descriptor union): `onSelect`\n * is permitted only on a dispatch action. A navigate action carries no handler (the host performs\n * the navigation from `href`), so supplying `onSelect` on a navigate action is a typecheck error\n * rather than a silently-ignored footgun. The hook strips `onSelect` before publishing (only\n * serializable descriptors cross to the host). */\nexport type HostSidebarAction =\n | (Extract<HostSidebarActionDescriptor, { kind: \"dispatch\" }> & { onSelect?: () => void })\n | Extract<HostSidebarActionDescriptor, { kind: \"navigate\" }>\n // A collapsible group whose `children` are themselves authoring actions (so a dispatch child can\n // still carry its inline `onSelect`). `children` overrides the descriptor's serializable children.\n | (Omit<Extract<HostSidebarActionDescriptor, { kind: \"group\" }>, \"children\"> & { children: HostSidebarAction[] });\n\n/** Single source for the discriminant values used across the mode checks, `toContribution`, and\n * the content key — so the \"none\"/\"actions\"/\"detail\" strings live in one place. The union type\n * below intentionally keeps its literal members (they ARE the discriminant + drive IntelliSense);\n * `SIDEBAR_MODE.*` is `as const`, so it is type-identical to those literals. */\nexport const SIDEBAR_MODE = { none: \"none\", actions: \"actions\", detail: \"detail\" } as const;\n\n/** Discriminated input to `useHostSidebarActions`. `mode:\"none\"` suppresses all plugin-side\n * contributions without clobbering the static manifest actions. `mode:\"actions\"` is the\n * batch-2 Quick Actions shape. `mode:\"detail\"` is the full detail-nav replacement with title,\n * navigation items, back-arrow, and Quick Actions.\n *\n * `entityToken` is REQUIRED here — this is the published shape existing consumers narrow\n * against (`input.entityToken` is a `string` after a mode check), unchanged. To let the\n * hook derive the token instead, OMIT the property via {@link HostSidebarDerivedInput}. */\nexport type HostSidebarInput =\n | { mode: \"none\" }\n | { mode: \"actions\"; entityToken: string; actions: HostSidebarAction[] }\n | {\n mode: \"detail\";\n entityToken: string;\n title: string;\n navSectionLabel: string;\n navItems: HostSidebarNavItem[];\n backHref: string;\n backLabel: string;\n actions: HostSidebarAction[];\n };\n\n/** Token-less authoring variants: the hook derives the host-mirrored entity token from the\n * surface base + current location (`deriveHostEntityToken`) — correct by construction, since\n * the host's token guard silently drops a mismatching publish. Prefer these unless you need\n * the bare-entity-id form (which the host segment-matches across an entity's sub-pages).\n * `entityToken?: undefined` (not just absence) is deliberate: an EXPLICIT `undefined`\n * (e.g. `entityToken: maybeToken` with an unresolved token) keeps the long-standing\n * \"unresolved token → contribute nothing\" semantic and is treated as `mode:\"none\"`, NOT\n * derived — only a truly ABSENT property derives. */\nexport type HostSidebarDerivedInput =\n | { mode: \"actions\"; entityToken?: undefined; actions: HostSidebarAction[] }\n | {\n mode: \"detail\";\n entityToken?: undefined;\n title: string;\n navSectionLabel: string;\n navItems: HostSidebarNavItem[];\n backHref: string;\n backLabel: string;\n actions: HostSidebarAction[];\n };\n\n/** What `useHostSidebarActions` accepts: the classic explicit-token shape or a derived-token variant. */\nexport type HostSidebarHookInput = HostSidebarInput | HostSidebarDerivedInput;\n\n/** Input with the entity token resolved (supplied or derived) — the only shape that crosses\n * to the host, whose contribution contract requires the token. */\ntype ResolvedHostSidebarInput = HostSidebarInput;\n\nfunction toDescriptor(a: HostSidebarAction): HostSidebarActionDescriptor {\n if (a.kind === \"dispatch\") {\n const { onSelect: _drop, ...rest } = a;\n return rest; // rest is the serializable dispatch descriptor\n }\n if (a.kind === \"group\") {\n // Recurse: strip the children's `onSelect` handlers so only serializable descriptors cross.\n const { children, ...rest } = a;\n return { ...rest, children: children.map(toDescriptor) };\n }\n return a; // navigate descriptor is already serializable (no handler)\n}\n\n/** Flatten a (possibly nested) action tree to its `kind:\"dispatch\"` handler entries — a group's\n * child dispatch clicks must reach their `onSelect` just like a top-level dispatch action. */\nfunction collectDispatchHandlers(actions: HostSidebarAction[]): Array<readonly [string, () => void]> {\n return actions.flatMap((a) =>\n a.kind === \"dispatch\" && a.onSelect\n ? [[a.id, a.onSelect] as const]\n : a.kind === \"group\"\n ? collectDispatchHandlers(a.children)\n : [],\n );\n}\n\n/** Map a plugin-authoring input to the serializable contribution published to the host.\n * `onSelect` handlers are stripped via `toDescriptor`; nav/back/title pass through for `detail`. */\nfunction toContribution(input: ResolvedHostSidebarInput): HostSidebarContribution {\n if (input.mode === SIDEBAR_MODE.none) {\n return { mode: SIDEBAR_MODE.none };\n }\n if (input.mode === SIDEBAR_MODE.actions) {\n return {\n mode: SIDEBAR_MODE.actions,\n entityToken: input.entityToken,\n actions: input.actions.map(toDescriptor),\n };\n }\n // mode === \"detail\"\n return {\n mode: SIDEBAR_MODE.detail,\n entityToken: input.entityToken,\n title: input.title,\n navSectionLabel: input.navSectionLabel,\n navItems: input.navItems,\n backHref: input.backHref,\n backLabel: input.backLabel,\n actions: input.actions.map(toDescriptor),\n };\n}\n\n/** Content key so we republish only when the visible descriptor set changes. JSON-encodes an\n * ARRAY of ORDERED-tuple arrays: element order is stable (unlike object property insertion order,\n * which is why we avoid `JSON.stringify` over the raw descriptor objects — spec-gate MEDIUM R1-M2),\n * and JSON string-escaping makes the key delimiter-collision-proof, so a `label`/`href` that\n * happens to contain a separator character can no longer alias two distinct action sets to the\n * same key (which would skip a needed republish and leave the host sidebar stale). */\nfunction contributionKey(input: ResolvedHostSidebarInput): string {\n if (input.mode === SIDEBAR_MODE.none) {\n return JSON.stringify([SIDEBAR_MODE.none]);\n }\n const actionTuple = (a: HostSidebarAction): unknown[] => [\n a.id,\n a.label,\n a.icon ?? \"\",\n a.slot ?? \"\",\n a.variant ?? \"\",\n a.disabled ? 1 : 0,\n a.active ? 1 : 0,\n a.requiredPermission ?? \"\",\n a.kind,\n a.kind === \"navigate\" ? a.href : \"\",\n // Group children fold into the key so a change to any collapsed leaf forces a republish.\n a.kind === \"group\" ? a.children.map(actionTuple) : \"\",\n ];\n const actionTuples = input.actions.map(actionTuple);\n if (input.mode === SIDEBAR_MODE.actions) {\n return JSON.stringify([SIDEBAR_MODE.actions, input.entityToken, actionTuples]);\n }\n // mode === \"detail\"\n const navTuples = input.navItems.map((n) => [n.id, n.label, n.icon ?? \"\", n.href]);\n return JSON.stringify([\n SIDEBAR_MODE.detail,\n input.entityToken,\n input.title,\n input.navSectionLabel,\n input.backHref,\n input.backLabel,\n navTuples,\n actionTuples,\n ]);\n}\n\n/** Per-page dev-warn throttle (NOT a global boolean — a module singleton would suppress warnings\n * for every later surface in a shared bundle; spec-gate HIGH R1-H2). Telemetry fires every time. */\nconst devWarnedPages = new Set<string>();\nfunction reportNoHost(pageId: string | undefined): void {\n // Observable in ALL environments via the injected diagnostic sink, tagged by page id (R1-H3).\n reportHostChromeDiagnostic({ event: \"host_sidebar_actions_unavailable\", pageId });\n const key = pageId ?? \"*\";\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((import.meta as any).env?.DEV && !devWarnedPages.has(key)) {\n devWarnedPages.add(key);\n // eslint-disable-next-line no-console\n console.warn(\n `[plugin-ui] useHostSidebarActions (${key}): no compatible host sidebar-actions API — ` +\n \"the host predates the seam or its contract major differs. Quick Actions will not render.\",\n );\n }\n}\n\n/**\n * Publish contextual sidebar contributions from a PlatformReact page to the host sidebar, and\n * receive click dispatch by id. Accepts a discriminated `HostSidebarInput`:\n * - `mode:\"none\"` — suppress all plugin contributions without clobbering the static manifest.\n * - `mode:\"actions\"` — batch-2 Quick Actions for a detail entity (entity token + action list).\n * - `mode:\"detail\"` — full detail-nav replacement (title, nav items, back-arrow, Quick Actions).\n *\n * Serializable descriptors only cross to the host; the inline `onSelect` handlers stay in a\n * ref-map here and are always the latest closure. Fails closed (no publish/subscribe, no throw)\n * when the host predates or is incompatible with the seam. */\nexport function useHostSidebarActions(input: HostSidebarHookInput): void {\n const api = useContext(HostSidebarActionsContext);\n const surfaceBase = useContext(SurfaceBaseContext);\n const pageId = surfaceBase?.pageId; // diagnostic tag (per-surface)\n const compatible: HostSidebarActionsApi | null =\n api && isHostChromeCompatible(api.capabilities?.contractVersion) ? api : null;\n\n // Resolve the entity token. Three cases, in order:\n // 1. Explicit string token → publish as-is (the pre-existing behaviour, unchanged).\n // 2. Property PRESENT but undefined (`entityToken: maybeToken` with an unresolved\n // token) → mode:\"none\". This preserves the long-standing \"unresolved token →\n // contribute nothing\" gate (`toHostSidebarInput` has always mapped an undefined\n // token to none) — deriving here would surface actions for an entity the page\n // has not resolved yet.\n // 3. Property ABSENT → derive the host-mirrored token from the surface base +\n // current location, so the host's (silent) token guard can never drop the\n // publish over a token-shape mismatch. The derived token re-computes on every\n // render; the content key below re-publishes when it changes (a location change\n // also makes the HOST clear its state synchronously, so a republish is required\n // with explicit tokens too — this path is no less reactive than they are).\n const resolved: ResolvedHostSidebarInput =\n input.mode === SIDEBAR_MODE.none\n ? input\n : typeof input.entityToken === \"string\"\n ? (input as ResolvedHostSidebarInput)\n : \"entityToken\" in input\n ? { mode: SIDEBAR_MODE.none }\n : {\n ...input,\n entityToken: deriveHostEntityToken(\n typeof window !== \"undefined\" ? window.location.pathname : \"\",\n surfaceBase?.basePath,\n ),\n };\n\n // Ref-map refreshed every render → dispatch always hits the latest handler (recursing groups).\n // Built from RESOLVED (not raw input): when resolution collapses to mode:\"none\" (explicit\n // undefined token), the handlers must be empty too — a stale host dispatch arriving before\n // the none-publish clears the sidebar must not invoke an unresolved-entity action.\n const actions = resolved.mode === SIDEBAR_MODE.none ? [] : resolved.actions;\n const handlers = useRef<Map<string, () => void>>(new Map());\n handlers.current = new Map(collectDispatchHandlers(actions));\n\n useEffect(() => {\n if (!compatible) {\n reportNoHost(pageId);\n return;\n }\n const unsub = compatible.subscribe((id) => {\n handlers.current.get(id)?.();\n });\n return () => {\n compatible.clear();\n unsub();\n };\n }, [compatible, pageId]);\n\n // Content key: mode + entityToken + descriptor tuples + (detail) nav/back/title.\n const key = contributionKey(resolved);\n useEffect(() => {\n if (!compatible) return;\n compatible.publish(toContribution(resolved));\n // key encodes all content that affects the published contribution; changes force republish.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [compatible, key]);\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { A11yPayload, BridgeClientContext, BridgePortShim, DensityPayload, ExtensionRuntimeProvider, ExtensionRuntimeProviderProps, HostIdentity, HostIdentityContext, HostIdentityUser, HostPermission, ItemsResponse, LocalePayload, McpTransport, NavPayload, PortBridgeClient, SessionTokenPayload, ThemePayload, UseMcpQueryOptions, UseMcpQueryResult, UseMcpResourceOptions, UseMcpResourceResult, UseMcpToolOptions, UseMcpToolResult, createPortBridgeClient, unwrapItems, useBridgeClient, useBridgeLocale, useBridgeTheme, useHostIdentity, useMcpQuery, useMcpResource, useMcpTool } from '@ethisyscore/extension-runtime/plugin';
|
|
2
2
|
export { PlatformReactPageProps, definePlatformReactPage, emitNavigation } from '@ethisyscore/components-react';
|
|
3
|
-
export { H as HOST_CHROME_CONTRACT_VERSION, a as HostChromeDiagnostic, b as HostSidebarAction, c as HostSidebarActionDescriptor, d as HostSidebarActionSlot, e as HostSidebarActionVariant, f as HostSidebarActionsApi, g as HostSidebarActionsCapabilities, h as HostSidebarActionsContext, i as HostSidebarActionsPageProps, j as HostSidebarContribution, k as HostSidebarInput, l as HostSidebarNavItem, S as SIDEBAR_MODE, m as isHostChromeCompatible, r as reportHostChromeDiagnostic, s as setHostChromeDiagnosticSink, u as useHostSidebarActions } from './useHostSidebarActions-
|
|
3
|
+
export { H as HOST_CHROME_CONTRACT_VERSION, a as HostChromeDiagnostic, b as HostSidebarAction, c as HostSidebarActionDescriptor, d as HostSidebarActionSlot, e as HostSidebarActionVariant, f as HostSidebarActionsApi, g as HostSidebarActionsCapabilities, h as HostSidebarActionsContext, i as HostSidebarActionsPageProps, j as HostSidebarContribution, k as HostSidebarInput, l as HostSidebarNavItem, S as SIDEBAR_MODE, m as isHostChromeCompatible, r as reportHostChromeDiagnostic, s as setHostChromeDiagnosticSink, u as useHostSidebarActions } from './useHostSidebarActions-Bt2U-EuA.cjs';
|
|
4
4
|
import 'react';
|
|
5
5
|
|
|
6
6
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { A11yPayload, BridgeClientContext, BridgePortShim, DensityPayload, ExtensionRuntimeProvider, ExtensionRuntimeProviderProps, HostIdentity, HostIdentityContext, HostIdentityUser, HostPermission, ItemsResponse, LocalePayload, McpTransport, NavPayload, PortBridgeClient, SessionTokenPayload, ThemePayload, UseMcpQueryOptions, UseMcpQueryResult, UseMcpResourceOptions, UseMcpResourceResult, UseMcpToolOptions, UseMcpToolResult, createPortBridgeClient, unwrapItems, useBridgeClient, useBridgeLocale, useBridgeTheme, useHostIdentity, useMcpQuery, useMcpResource, useMcpTool } from '@ethisyscore/extension-runtime/plugin';
|
|
2
2
|
export { PlatformReactPageProps, definePlatformReactPage, emitNavigation } from '@ethisyscore/components-react';
|
|
3
|
-
export { H as HOST_CHROME_CONTRACT_VERSION, a as HostChromeDiagnostic, b as HostSidebarAction, c as HostSidebarActionDescriptor, d as HostSidebarActionSlot, e as HostSidebarActionVariant, f as HostSidebarActionsApi, g as HostSidebarActionsCapabilities, h as HostSidebarActionsContext, i as HostSidebarActionsPageProps, j as HostSidebarContribution, k as HostSidebarInput, l as HostSidebarNavItem, S as SIDEBAR_MODE, m as isHostChromeCompatible, r as reportHostChromeDiagnostic, s as setHostChromeDiagnosticSink, u as useHostSidebarActions } from './useHostSidebarActions-
|
|
3
|
+
export { H as HOST_CHROME_CONTRACT_VERSION, a as HostChromeDiagnostic, b as HostSidebarAction, c as HostSidebarActionDescriptor, d as HostSidebarActionSlot, e as HostSidebarActionVariant, f as HostSidebarActionsApi, g as HostSidebarActionsCapabilities, h as HostSidebarActionsContext, i as HostSidebarActionsPageProps, j as HostSidebarContribution, k as HostSidebarInput, l as HostSidebarNavItem, S as SIDEBAR_MODE, m as isHostChromeCompatible, r as reportHostChromeDiagnostic, s as setHostChromeDiagnosticSink, u as useHostSidebarActions } from './useHostSidebarActions-Bt2U-EuA.js';
|
|
4
4
|
import 'react';
|
|
5
5
|
|
|
6
6
|
/**
|