@jmruthers/pace-core 0.5.135 → 0.5.137
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/{DataTable-A36PJG6N.js → DataTable-6M4L6BI2.js} +26 -13
- package/dist/{DataTable-C7GaRZye.d.ts → DataTable-CWAZZcXC.d.ts} +1 -1
- package/dist/{PublicLoadingSpinner-CUAnTvcg.d.ts → EventLogo-rFL_kRjk.d.ts} +123 -135
- package/dist/{UnifiedAuthProvider-BVKmQd9u.d.ts → UnifiedAuthProvider-DJxGTftH.d.ts} +1 -1
- package/dist/{UnifiedAuthProvider-CQDZRJIS.js → UnifiedAuthProvider-XIQQ7LVU.js} +5 -5
- package/dist/{api-TNIBJWLM.js → api-45XYYO2A.js} +4 -3
- package/dist/{audit-T36HM7IM.js → audit-64X3VJXB.js} +3 -2
- package/dist/{chunk-F64FFPOZ.js → chunk-22WKWKRX.js} +26 -20
- package/dist/chunk-22WKWKRX.js.map +1 -0
- package/dist/{chunk-VZ5OR6HD.js → chunk-4C7EXCAR.js} +62 -150
- package/dist/chunk-4C7EXCAR.js.map +1 -0
- package/dist/{chunk-PYUXFQJ3.js → chunk-56XJ3TU6.js} +2 -2
- package/dist/chunk-56XJ3TU6.js.map +1 -0
- package/dist/{chunk-CTJRBUX2.js → chunk-6LAAY47Q.js} +2 -2
- package/dist/{chunk-UJI6WSMD.js → chunk-7QCC6MCP.js} +90 -3
- package/dist/chunk-7QCC6MCP.js.map +1 -0
- package/dist/{chunk-66C4BSAY.js → chunk-ANBQRTPX.js} +9 -2
- package/dist/chunk-ANBQRTPX.js.map +1 -0
- package/dist/{chunk-CQZU6TFE.js → chunk-BCIBECNB.js} +100 -62
- package/dist/chunk-BCIBECNB.js.map +1 -0
- package/dist/{chunk-GKHF54DI.js → chunk-BESYRHQM.js} +10 -4
- package/dist/chunk-BESYRHQM.js.map +1 -0
- package/dist/chunk-BJPBT3CU.js +21 -0
- package/dist/chunk-BJPBT3CU.js.map +1 -0
- package/dist/{chunk-BYXRHAIF.js → chunk-BLCXZEYF.js} +23 -14
- package/dist/chunk-BLCXZEYF.js.map +1 -0
- package/dist/{chunk-WP5I5GLN.js → chunk-BVYWGZVV.js} +112 -97
- package/dist/chunk-BVYWGZVV.js.map +1 -0
- package/dist/{chunk-GEVIB2UB.js → chunk-ERISIBYU.js} +14 -5
- package/dist/chunk-ERISIBYU.js.map +1 -0
- package/dist/{chunk-O3NWNXDY.js → chunk-FMUCXFII.js} +2 -2
- package/dist/chunk-FMUCXFII.js.map +1 -0
- package/dist/{chunk-GVDR7WNV.js → chunk-HAWZXGR2.js} +334 -614
- package/dist/chunk-HAWZXGR2.js.map +1 -0
- package/dist/{chunk-ZV77RZMU.js → chunk-INQLMHPF.js} +2 -2
- package/dist/chunk-JISYG63F.js +70 -0
- package/dist/chunk-JISYG63F.js.map +1 -0
- package/dist/{chunk-HMNOSGVA.js → chunk-KYRHUBIU.js} +576 -767
- package/dist/chunk-KYRHUBIU.js.map +1 -0
- package/dist/{chunk-M6DDYFUD.js → chunk-LS353YLY.js} +19 -16
- package/dist/chunk-LS353YLY.js.map +1 -0
- package/dist/{chunk-TGIY2AR2.js → chunk-MA6EPSGZ.js} +4 -3
- package/dist/{chunk-TGIY2AR2.js.map → chunk-MA6EPSGZ.js.map} +1 -1
- package/dist/chunk-OWAG3GSU.js +58 -0
- package/dist/chunk-OWAG3GSU.js.map +1 -0
- package/dist/{chunk-JCQZ6LA7.js → chunk-Q5QRDWKI.js} +9 -3
- package/dist/chunk-Q5QRDWKI.js.map +1 -0
- package/dist/chunk-S5OFRT4M.js +94 -0
- package/dist/chunk-S5OFRT4M.js.map +1 -0
- package/dist/{chunk-3DBFLLLU.js → chunk-SBVILCCA.js} +14 -9
- package/dist/chunk-SBVILCCA.js.map +1 -0
- package/dist/{chunk-ZYZCRSBD.js → chunk-T6JN6LH6.js} +16 -11
- package/dist/chunk-T6JN6LH6.js.map +1 -0
- package/dist/chunk-XDNLUEXI.js +138 -0
- package/dist/chunk-XDNLUEXI.js.map +1 -0
- package/dist/{chunk-3CG5L6RN.js → chunk-YCWDTTUK.js} +90 -75
- package/dist/chunk-YCWDTTUK.js.map +1 -0
- package/dist/{chunk-5F3NDPJV.js → chunk-ZZ2SS7NI.js} +10 -5
- package/dist/chunk-ZZ2SS7NI.js.map +1 -0
- package/dist/components.d.ts +7 -287
- package/dist/components.js +27 -157
- package/dist/components.js.map +1 -1
- package/dist/{file-reference-C9isKNPn.d.ts → file-reference-C6Gkn77H.d.ts} +1 -1
- package/dist/{formatting-DFcCxUEk.d.ts → formatting-CvUXy2mF.d.ts} +1 -1
- package/dist/hooks.d.ts +3 -3
- package/dist/hooks.js +21 -16
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +101 -9
- package/dist/index.js +44 -31
- package/dist/index.js.map +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +4 -4
- package/dist/rbac/index.js +12 -12
- package/dist/schema-DTDZQe2u.d.ts +28 -0
- package/dist/styles/index.js +2 -1
- package/dist/theming/runtime.d.ts +2 -19
- package/dist/theming/runtime.js +2 -1
- package/dist/{types-D5rqZQXk.d.ts → types-Dfz9dmVH.d.ts} +12 -1
- package/dist/types.d.ts +153 -4
- package/dist/types.js +51 -16
- package/dist/types.js.map +1 -1
- package/dist/{useInactivityTracker-MRUU55XI.js → useInactivityTracker-TO6ZOF35.js} +3 -2
- package/dist/{usePublicRouteParams-Dyt1tzI9.d.ts → usePublicRouteParams-B7PabvuH.d.ts} +1 -1
- package/dist/utils.d.ts +221 -173
- package/dist/utils.js +185 -225
- package/dist/utils.js.map +1 -1
- package/dist/validation.d.ts +24 -115
- package/dist/validation.js +19 -474
- package/dist/validation.js.map +1 -1
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +6 -6
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +6 -6
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +7 -7
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +4 -4
- package/docs/api/interfaces/BadgeProps.md +27 -0
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +29 -4
- package/docs/api/interfaces/DataAccessRecord.md +9 -9
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +18 -18
- package/docs/api/interfaces/DataTableColumn.md +61 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +7 -7
- package/docs/api/interfaces/EmptyStateConfig.md +5 -5
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +14 -14
- package/docs/api/interfaces/EventAppRoleData.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +152 -0
- package/docs/api/interfaces/ExportColumn.md +1 -1
- package/docs/api/interfaces/ExportOptions.md +8 -8
- package/docs/api/interfaces/FileDisplayProps.md +15 -15
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +10 -10
- package/docs/api/interfaces/NavigationContextType.md +9 -9
- package/docs/api/interfaces/NavigationGuardProps.md +10 -10
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +7 -7
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +27 -27
- package/docs/api/interfaces/PaceLoginPageProps.md +4 -4
- package/docs/api/interfaces/PageAccessRecord.md +8 -8
- package/docs/api/interfaces/PagePermissionContextType.md +8 -8
- package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
- package/docs/api/interfaces/PagePermissionProviderProps.md +7 -7
- package/docs/api/interfaces/PaletteData.md +4 -4
- package/docs/api/interfaces/PermissionEnforcerProps.md +11 -11
- package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +8 -8
- package/docs/api/interfaces/RoleBasedRouterProps.md +10 -10
- package/docs/api/interfaces/RoleManagementResult.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +10 -10
- package/docs/api/interfaces/RouteConfig.md +10 -10
- package/docs/api/interfaces/SecureDataContextType.md +9 -9
- package/docs/api/interfaces/SecureDataProviderProps.md +8 -8
- package/docs/api/interfaces/SessionRestorationLoaderProps.md +21 -0
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +53 -53
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +9 -9
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +8 -8
- package/docs/api/interfaces/UsePublicEventOptions.md +3 -3
- package/docs/api/interfaces/UsePublicEventReturn.md +5 -5
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +4 -4
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +9 -9
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +4 -4
- package/docs/api/interfaces/UseResolvedScopeReturn.md +4 -4
- package/docs/api/interfaces/UserEventAccess.md +11 -11
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +591 -220
- package/docs/api-reference/components.md +106 -26
- package/docs/architecture/README.md +0 -3
- package/docs/implementation-guides/data-tables.md +277 -13
- package/docs/implementation-guides/forms.md +1 -16
- package/docs/implementation-guides/permission-enforcement.md +8 -2
- package/docs/styles/README.md +0 -2
- package/examples/README.md +30 -14
- package/examples/STRUCTURE.md +125 -0
- package/examples/components 2/DataTable/HierarchicalActionsExample.tsx +421 -0
- package/examples/components 2/DataTable/HierarchicalExample.tsx +475 -0
- package/examples/components 2/DataTable/InitialPageSizeExample.tsx +177 -0
- package/examples/components 2/DataTable/PerformanceExample.tsx +506 -0
- package/examples/components 2/DataTable/index.ts +13 -0
- package/examples/components 2/Dialog/BasicHtmlTest.tsx +55 -0
- package/examples/components 2/Dialog/DebugHtmlExample.tsx +68 -0
- package/examples/components 2/Dialog/HtmlDialogExample.tsx +202 -0
- package/examples/components 2/Dialog/ScrollableDialogExample.tsx +290 -0
- package/examples/components 2/Dialog/SimpleHtmlTest.tsx +61 -0
- package/examples/components 2/Dialog/SmartDialogExample.tsx +322 -0
- package/examples/components 2/Dialog/index.ts +15 -0
- package/examples/components 2/index.ts +11 -0
- package/examples/features/index.ts +12 -0
- package/{src/examples → examples/features/public-pages}/CorrectPublicPageImplementation.tsx +14 -17
- package/{src/examples → examples/features/public-pages}/PublicEventPage.tsx +14 -27
- package/{src/examples → examples/features/public-pages}/PublicPageApp.tsx +15 -28
- package/{src/examples → examples/features/public-pages}/PublicPageUsageExample.tsx +8 -10
- package/examples/features/public-pages/index.ts +14 -0
- package/examples/features/rbac/CompleteRBACExample.tsx +324 -0
- package/examples/features/rbac/EventBasedApp.tsx +239 -0
- package/examples/features/rbac/PermissionExample.tsx +151 -0
- package/examples/features/rbac/index.ts +13 -0
- package/examples/index.ts +11 -3
- package/package.json +30 -19
- package/src/__tests__/TEST_STANDARD.md +92 -0
- package/src/components/Alert/Alert.tsx +1 -1
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Badge/Badge.test.tsx +314 -0
- package/src/components/Badge/Badge.tsx +304 -0
- package/src/components/Badge/index.ts +3 -0
- package/src/components/Button/Button.tsx +1 -1
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Checkbox/Checkbox.tsx +1 -1
- package/src/components/DataTable/DataTable.test.tsx +1 -1
- package/src/components/DataTable/DataTable.tsx +1 -30
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +562 -0
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +217 -0
- package/src/components/DataTable/__tests__/styles.test.ts +3 -3
- package/src/components/DataTable/components/ActionButtons.tsx +0 -15
- package/src/components/DataTable/components/ColumnFilter.tsx +8 -4
- package/src/components/DataTable/components/DataTableBody.tsx +461 -0
- package/src/components/DataTable/components/DataTableCore.tsx +4 -185
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +1 -1
- package/src/components/DataTable/components/DataTableModals.tsx +1 -27
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +144 -0
- package/src/components/DataTable/components/EditableRow.tsx +1 -1
- package/src/components/DataTable/components/FilterRow.tsx +9 -3
- package/src/components/DataTable/components/ImportModal.tsx +2 -14
- package/src/components/DataTable/components/PaginationControls.tsx +2 -1
- package/src/components/DataTable/components/UnifiedTableBody.tsx +109 -82
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +513 -0
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +14 -68
- package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +62 -0
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +1 -1
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +43 -0
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +1 -1
- package/src/components/DataTable/core/ActionManager.ts +235 -0
- package/src/components/DataTable/core/ColumnManager.ts +205 -0
- package/src/components/DataTable/core/DataManager.ts +188 -0
- package/src/components/DataTable/core/DataTableContext.tsx +181 -0
- package/src/components/DataTable/core/LocalDataAdapter.ts +273 -0
- package/src/components/DataTable/core/PluginRegistry.ts +229 -0
- package/src/components/DataTable/core/StateManager.ts +311 -0
- package/src/components/DataTable/core/interfaces.ts +338 -0
- package/src/components/DataTable/examples/GroupingAggregationExample.tsx +273 -0
- package/src/components/DataTable/examples/HierarchicalActionsExample.tsx +1 -1
- package/src/components/DataTable/examples/__tests__/HierarchicalActionsExample.test.tsx +1 -1
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +1 -1
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +1 -1
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +2 -23
- package/src/components/DataTable/index.ts +4 -0
- package/src/components/DataTable/styles.ts +28 -7
- package/src/components/DataTable/types.ts +13 -0
- package/src/components/DataTable/utils/__tests__/columnUtils.test.ts +94 -0
- package/src/components/DataTable/utils/__tests__/exportUtils.test.ts +1 -1
- package/src/components/DataTable/utils/aggregationUtils.ts +161 -0
- package/src/components/DataTable/utils/columnUtils.ts +40 -0
- package/src/components/DataTable/utils/debugTools.ts +609 -0
- package/src/components/DataTable/utils/exportUtils.ts +1 -1
- package/src/components/DataTable/utils/flexibleImport.ts +1 -11
- package/src/components/DataTable/utils/index.ts +2 -0
- package/src/components/DataTable/utils/paginationUtils.ts +1 -1
- package/src/components/Dialog/Dialog.tsx +2 -2
- package/src/components/Dialog/utils/__tests__/safeHtml.unit.test.ts +8 -1
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +35 -7
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +5 -4
- package/src/components/EventSelector/EventSelector.tsx +3 -2
- package/src/components/FileDisplay/FileDisplay.tsx +2 -36
- package/src/components/FileUpload/FileUpload.test.tsx +2 -2
- package/src/components/FileUpload/FileUpload.tsx +2 -2
- package/src/components/Footer/Footer.test.tsx +1 -1
- package/src/components/Footer/Footer.tsx +1 -1
- package/src/components/Form/Form.test.tsx +5 -510
- package/src/components/Form/Form.tsx +1 -1
- package/src/components/Form/FormField.tsx +1 -1
- package/src/components/Form/index.ts +0 -12
- package/src/components/Header/Header.tsx +1 -1
- package/src/components/Input/Input.tsx +1 -1
- package/src/components/Label/Label.tsx +1 -1
- package/src/components/LoginForm/LoginForm.test.tsx +1 -1
- package/src/components/LoginForm/LoginForm.tsx +1 -1
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +19 -3
- package/src/components/NavigationMenu/NavigationMenu.tsx +9 -8
- package/src/components/OrganisationSelector/OrganisationSelector.tsx +4 -3
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -12
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.integration.test.tsx +0 -16
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.performance.test.tsx +76 -10
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +0 -1
- package/src/components/PaceAppLayout/__tests__/PaceAppLayout.unit.test.tsx +0 -9
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +35 -3
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +14 -13
- package/src/components/PasswordReset/PasswordChangeForm.tsx +1 -1
- package/src/components/PasswordReset/index.ts +0 -2
- package/src/components/Progress/Progress.tsx +1 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +35 -8
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +3 -2
- package/src/components/PublicLayout/PublicErrorBoundary.tsx +1 -1
- package/src/components/PublicLayout/PublicLoadingSpinner.tsx +1 -1
- package/src/components/PublicLayout/PublicPageContextChecker.tsx +44 -43
- package/src/components/PublicLayout/PublicPageFooter.tsx +1 -1
- package/src/components/PublicLayout/PublicPageHeader.tsx +1 -15
- package/src/components/PublicLayout/PublicPageProvider.tsx +3 -2
- package/src/components/PublicLayout/__tests__/PublicPageContextChecker.test.tsx +2 -0
- package/src/components/PublicLayout/__tests__/PublicPageFooter.test.tsx +1 -1
- package/src/components/PublicLayout/index.ts +4 -2
- package/src/components/Select/Select.test.tsx +1 -1
- package/src/components/Select/Select.tsx +21 -9
- package/src/components/{SessionRestorationLoader.tsx → SessionRestorationLoader/SessionRestorationLoader.tsx} +3 -2
- package/src/components/SessionRestorationLoader/index.ts +3 -0
- package/src/components/Switch/Switch.tsx +1 -1
- package/src/components/Table/Table.tsx +1 -1
- package/src/components/Table/__tests__/Table.test.tsx +1 -1
- package/src/components/Toast/Toast.tsx +1 -1
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/components/index.ts +7 -10
- package/src/hooks/__tests__/hooks.integration.test.tsx +37 -22
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +33 -17
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +28 -3
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +36 -9
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +83 -85
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +26 -2
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +19 -6
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +17 -4
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +17 -4
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +26 -6
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +16 -6
- package/src/hooks/__tests__/useSecureDataAccess.unit.test.tsx +3 -3
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +17 -3
- package/src/hooks/public/usePublicEvent.ts +7 -6
- package/src/hooks/public/usePublicEventLogo.ts +7 -4
- package/src/hooks/public/usePublicFileDisplay.ts +6 -150
- package/src/hooks/useComponentPerformance.ts +4 -1
- package/src/hooks/useDataTablePerformance.ts +4 -3
- package/src/hooks/useEventTheme.test.ts +18 -5
- package/src/hooks/useEventTheme.ts +4 -1
- package/src/hooks/useEvents.ts +2 -0
- package/src/hooks/useFileDisplay.ts +9 -8
- package/src/hooks/useFileReference.ts +4 -1
- package/src/hooks/useFileUrl.ts +4 -1
- package/src/hooks/useInactivityTracker.ts +5 -4
- package/src/hooks/useOrganisationSecurity.test.ts +33 -12
- package/src/hooks/useOrganisationSecurity.ts +8 -7
- package/src/hooks/usePerformanceMonitor.ts +6 -3
- package/src/hooks/usePermissionCache.ts +13 -6
- package/src/hooks/useSecureDataAccess.test.ts +2 -2
- package/src/hooks/useSecureDataAccess.ts +9 -8
- package/src/hooks/useSessionRestoration.ts +4 -1
- package/src/hooks/useStorage.ts +4 -1
- package/src/index.ts +20 -7
- package/src/providers/services/AuthServiceProvider.tsx +3 -2
- package/src/providers/services/EventServiceProvider.tsx +2 -1
- package/src/providers/services/InactivityServiceProvider.tsx +2 -1
- package/src/providers/services/OrganisationServiceProvider.tsx +2 -1
- package/src/providers/services/UnifiedAuthProvider.tsx +4 -3
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +22 -2
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +24 -2
- package/src/rbac/__tests__/cache-invalidation.test.ts +20 -6
- package/src/rbac/api.ts +5 -2
- package/src/rbac/audit-enhanced.ts +6 -6
- package/src/rbac/audit.test.ts +60 -38
- package/src/rbac/audit.ts +8 -8
- package/src/rbac/cache-invalidation.ts +7 -4
- package/src/rbac/components/EnhancedNavigationMenu.tsx +11 -5
- package/src/rbac/components/NavigationGuard.tsx +7 -3
- package/src/rbac/components/NavigationProvider.tsx +6 -3
- package/src/rbac/components/PagePermissionGuard.tsx +28 -16
- package/src/rbac/components/PagePermissionProvider.tsx +4 -1
- package/src/rbac/components/PermissionEnforcer.tsx +9 -3
- package/src/rbac/components/RoleBasedRouter.tsx +3 -1
- package/src/rbac/components/SecureDataProvider.tsx +7 -3
- package/src/rbac/components/__tests__/EnhancedNavigationMenu.test.tsx +87 -61
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +83 -33
- package/src/rbac/components/__tests__/NavigationProvider.test.tsx +36 -13
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +2 -2
- package/src/rbac/components/__tests__/PagePermissionProvider.test.tsx +22 -8
- package/src/rbac/components/__tests__/PermissionEnforcer.test.tsx +19 -6
- package/src/rbac/components/__tests__/SecureDataProvider.fixed.test.tsx +43 -17
- package/src/rbac/components/__tests__/SecureDataProvider.test.tsx +42 -17
- package/src/rbac/engine.ts +15 -7
- package/src/rbac/hooks/usePermissions.ts +7 -3
- package/src/rbac/hooks/useResolvedScope.test.ts +2 -2
- package/src/rbac/hooks/useResolvedScope.ts +10 -7
- package/src/rbac/permissions.ts +5 -2
- package/src/rbac/security.test.ts +27 -16
- package/src/rbac/security.ts +5 -4
- package/src/services/AuthService.ts +22 -21
- package/src/services/EventService.ts +12 -12
- package/src/services/InactivityService.ts +5 -4
- package/src/services/OrganisationService.ts +26 -25
- package/src/services/__tests__/AuthService.test.ts +51 -19
- package/src/services/__tests__/EventService.test.ts +37 -5
- package/src/services/__tests__/InactivityService.test.ts +38 -4
- package/src/services/__tests__/OrganisationService.test.ts +3 -8
- package/src/services/base/BaseService.ts +3 -1
- package/src/styles/core.css +3 -0
- package/src/theming/__tests__/runtime.test.ts +21 -12
- package/src/theming/parseEventColours.ts +5 -19
- package/src/theming/runtime.ts +8 -4
- package/src/types/validation.ts +2 -29
- package/src/utils/__tests__/appConfig.unit.test.ts +1 -1
- package/src/utils/__tests__/audit.unit.test.ts +1 -1
- package/src/utils/__tests__/auth-utils.unit.test.ts +1 -1
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +19 -19
- package/src/utils/__tests__/cn.unit.test.ts +1 -1
- package/src/utils/__tests__/debugLogger.test.ts +1 -1
- package/src/utils/__tests__/deviceFingerprint.unit.test.ts +1 -1
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/formatting.unit.test.ts +1 -1
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +1 -1
- package/src/utils/__tests__/logger.unit.test.ts +1 -1
- package/src/utils/__tests__/organisationContext.unit.test.ts +1 -1
- package/src/utils/__tests__/performanceBenchmark.test.ts +1 -1
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +1 -1
- package/src/utils/__tests__/permissionTypes.unit.test.ts +1 -1
- package/src/utils/__tests__/permissionUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/sanitization.unit.test.ts +1 -1
- package/src/utils/__tests__/schemaUtils.unit.test.ts +1 -1
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +1 -1
- package/src/utils/__tests__/secureErrors.unit.test.ts +33 -15
- package/src/utils/__tests__/secureStorage.unit.test.ts +1 -1
- package/src/utils/__tests__/security.unit.test.ts +40 -18
- package/src/utils/__tests__/securityMonitor.unit.test.ts +1 -1
- package/src/utils/__tests__/sessionTracking.unit.test.ts +40 -29
- package/src/utils/__tests__/validationUtils.unit.test.ts +19 -6
- package/src/utils/app/appConfig.ts +47 -0
- package/src/utils/app/appIdResolver.test.ts +497 -0
- package/src/utils/app/appIdResolver.ts +133 -0
- package/src/utils/app/appNameResolver.simple.test.ts +212 -0
- package/src/utils/app/appNameResolver.test.ts +121 -0
- package/src/utils/app/appNameResolver.ts +195 -0
- package/src/utils/audit/audit.ts +127 -0
- package/src/utils/context/organisationContext.test.ts +322 -0
- package/src/utils/context/organisationContext.ts +156 -0
- package/src/utils/context/sessionTracking.ts +125 -0
- package/src/utils/core/cn.ts +7 -0
- package/src/utils/core/debugLogger.ts +67 -0
- package/src/utils/core/logger.ts +181 -0
- package/src/utils/device/deviceFingerprint.ts +215 -0
- package/src/utils/dynamic/dynamicUtils.ts +105 -0
- package/src/utils/dynamic/lazyLoad.tsx +44 -0
- package/src/utils/file-reference/__tests__/file-reference.test.ts +788 -0
- package/src/utils/file-reference/index.ts +501 -0
- package/src/utils/formatting/formatDate.test.ts +237 -0
- package/src/utils/formatting/formatting.ts +133 -0
- package/src/utils/index.ts +39 -54
- package/src/utils/performance/bundleAnalysis.ts +129 -0
- package/src/utils/performance/performanceBenchmark.ts +64 -0
- package/src/utils/performance/performanceBudgets.ts +110 -0
- package/src/utils/permissions/permissionTypes.ts +37 -0
- package/src/utils/permissions/permissionUtils.test.ts +393 -0
- package/src/utils/permissions/permissionUtils.ts +34 -0
- package/src/utils/security/auth-utils.ts +96 -0
- package/src/utils/security/secureDataAccess.test.ts +711 -0
- package/src/utils/security/secureDataAccess.ts +377 -0
- package/src/utils/security/secureErrors.ts +82 -0
- package/src/utils/security/secureStorage.ts +244 -0
- package/src/utils/security/security.ts +159 -0
- package/src/utils/security/securityMonitor.ts +45 -0
- package/src/utils/storage/__tests__/helpers.unit.test.ts +1 -4
- package/src/utils/storage/helpers.ts +15 -8
- package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +598 -0
- package/src/{validation → utils/validation}/csrf.ts +1 -1
- package/src/utils/validation/htmlSanitization.ts +184 -0
- package/src/utils/validation/index.ts +79 -0
- package/src/utils/validation/sanitization.ts +333 -0
- package/src/{validation/schemaUtils.ts → utils/validation/schema.ts} +11 -6
- package/src/{validation → utils/validation}/sqlInjectionProtection.ts +2 -0
- package/src/utils/validation/validation.ts +111 -0
- package/src/utils/validation/validationUtils.ts +123 -0
- package/src/validation/index.ts +3 -34
- package/dist/chunk-24MKLB7U.js +0 -81
- package/dist/chunk-24MKLB7U.js.map +0 -1
- package/dist/chunk-3CG5L6RN.js.map +0 -1
- package/dist/chunk-3DBFLLLU.js.map +0 -1
- package/dist/chunk-5F3NDPJV.js.map +0 -1
- package/dist/chunk-66C4BSAY.js.map +0 -1
- package/dist/chunk-BDZUMRBD.js +0 -87
- package/dist/chunk-BDZUMRBD.js.map +0 -1
- package/dist/chunk-BYXRHAIF.js.map +0 -1
- package/dist/chunk-CDQ3PX7L.js +0 -18
- package/dist/chunk-CDQ3PX7L.js.map +0 -1
- package/dist/chunk-CQZU6TFE.js.map +0 -1
- package/dist/chunk-F64FFPOZ.js.map +0 -1
- package/dist/chunk-GEVIB2UB.js.map +0 -1
- package/dist/chunk-GKHF54DI.js.map +0 -1
- package/dist/chunk-GVDR7WNV.js.map +0 -1
- package/dist/chunk-HMNOSGVA.js.map +0 -1
- package/dist/chunk-JCQZ6LA7.js.map +0 -1
- package/dist/chunk-M6DDYFUD.js.map +0 -1
- package/dist/chunk-O3NWNXDY.js.map +0 -1
- package/dist/chunk-PYUXFQJ3.js.map +0 -1
- package/dist/chunk-UJI6WSMD.js.map +0 -1
- package/dist/chunk-VZ5OR6HD.js.map +0 -1
- package/dist/chunk-WP5I5GLN.js.map +0 -1
- package/dist/chunk-ZYZCRSBD.js.map +0 -1
- package/dist/validation-DnhrNMju.d.ts +0 -159
- package/src/components/PublicLayout/__tests__/PublicPageDebugger.test.tsx +0 -185
- package/src/validation/__tests__/common.unit.test.ts +0 -101
- package/src/validation/__tests__/csrf.unit.test.ts +0 -365
- package/src/validation/__tests__/passwordSchema.unit.test.ts +0 -203
- package/src/validation/__tests__/sanitization.unit.test.ts +0 -250
- package/src/validation/__tests__/schemaUtils.unit.test.ts +0 -451
- package/src/validation/__tests__/sqlInjectionProtection.unit.test.ts +0 -462
- package/src/validation/__tests__/user.unit.test.ts +0 -440
- package/src/validation/sanitization.ts +0 -96
- /package/dist/{DataTable-A36PJG6N.js.map → DataTable-6M4L6BI2.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-CQDZRJIS.js.map → UnifiedAuthProvider-XIQQ7LVU.js.map} +0 -0
- /package/dist/{api-TNIBJWLM.js.map → api-45XYYO2A.js.map} +0 -0
- /package/dist/{audit-T36HM7IM.js.map → audit-64X3VJXB.js.map} +0 -0
- /package/dist/{chunk-CTJRBUX2.js.map → chunk-6LAAY47Q.js.map} +0 -0
- /package/dist/{chunk-ZV77RZMU.js.map → chunk-INQLMHPF.js.map} +0 -0
- /package/dist/{useInactivityTracker-MRUU55XI.js.map → useInactivityTracker-TO6ZOF35.js.map} +0 -0
- /package/src/{validation → utils/validation}/common.ts +0 -0
- /package/src/{validation → utils/validation}/passwordSchema.ts +0 -0
- /package/src/{validation → utils/validation}/user.ts +0 -0
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Badge Component Tests
|
|
3
|
+
* @description Comprehensive test suite for Badge component
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { screen } from '@testing-library/react';
|
|
8
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
9
|
+
import { Badge } from './Badge';
|
|
10
|
+
import { renderWithProviders } from '../../__tests__/helpers/test-utils';
|
|
11
|
+
import type { BadgeVariant } from './Badge';
|
|
12
|
+
|
|
13
|
+
describe('Badge Component', () => {
|
|
14
|
+
describe('Rendering', () => {
|
|
15
|
+
it('renders with text content', () => {
|
|
16
|
+
renderWithProviders(<Badge>New</Badge>);
|
|
17
|
+
expect(screen.getByText('New')).toBeInTheDocument();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('renders as span element', () => {
|
|
21
|
+
const { container } = renderWithProviders(<Badge>Test</Badge>);
|
|
22
|
+
const badge = container.querySelector('span');
|
|
23
|
+
expect(badge).toBeInTheDocument();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('renders with custom className', () => {
|
|
27
|
+
renderWithProviders(<Badge className="custom-class">Styled badge</Badge>);
|
|
28
|
+
const badge = screen.getByText('Styled badge');
|
|
29
|
+
expect(badge).toHaveClass('custom-class');
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('renders with data-testid', () => {
|
|
33
|
+
renderWithProviders(<Badge data-testid="test-badge">Test</Badge>);
|
|
34
|
+
expect(screen.getByTestId('test-badge')).toBeInTheDocument();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('renders with children elements', () => {
|
|
38
|
+
renderWithProviders(
|
|
39
|
+
<Badge>
|
|
40
|
+
<span>Icon</span> Text
|
|
41
|
+
</Badge>
|
|
42
|
+
);
|
|
43
|
+
expect(screen.getByText('Icon')).toBeInTheDocument();
|
|
44
|
+
expect(screen.getByText('Text')).toBeInTheDocument();
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
describe('Variants', () => {
|
|
49
|
+
const allVariants: BadgeVariant[] = [
|
|
50
|
+
// Solid variants
|
|
51
|
+
'solid-main-muted',
|
|
52
|
+
'solid-main-normal',
|
|
53
|
+
'solid-main-strong',
|
|
54
|
+
'solid-sec-muted',
|
|
55
|
+
'solid-sec-normal',
|
|
56
|
+
'solid-sec-strong',
|
|
57
|
+
'solid-acc-muted',
|
|
58
|
+
'solid-acc-normal',
|
|
59
|
+
'solid-acc-strong',
|
|
60
|
+
// Outline variants
|
|
61
|
+
'outline-main-muted',
|
|
62
|
+
'outline-main-normal',
|
|
63
|
+
'outline-main-strong',
|
|
64
|
+
'outline-sec-muted',
|
|
65
|
+
'outline-sec-normal',
|
|
66
|
+
'outline-sec-strong',
|
|
67
|
+
'outline-acc-muted',
|
|
68
|
+
'outline-acc-normal',
|
|
69
|
+
'outline-acc-strong',
|
|
70
|
+
// Soft variants
|
|
71
|
+
'soft-main-muted',
|
|
72
|
+
'soft-main-normal',
|
|
73
|
+
'soft-main-strong',
|
|
74
|
+
'soft-sec-muted',
|
|
75
|
+
'soft-sec-normal',
|
|
76
|
+
'soft-sec-strong',
|
|
77
|
+
'soft-acc-muted',
|
|
78
|
+
'soft-acc-normal',
|
|
79
|
+
'soft-acc-strong',
|
|
80
|
+
];
|
|
81
|
+
|
|
82
|
+
allVariants.forEach((variant) => {
|
|
83
|
+
it(`renders ${variant} variant correctly`, () => {
|
|
84
|
+
renderWithProviders(<Badge variant={variant}>Test {variant}</Badge>);
|
|
85
|
+
const badge = screen.getByText(`Test ${variant}`);
|
|
86
|
+
expect(badge).toBeInTheDocument();
|
|
87
|
+
expect(badge).toHaveClass('inline-flex', 'items-center', 'rounded-2xl');
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('uses default variant when not specified', () => {
|
|
92
|
+
renderWithProviders(<Badge>Default</Badge>);
|
|
93
|
+
const badge = screen.getByText('Default');
|
|
94
|
+
expect(badge).toHaveClass('bg-main-500', 'text-main-50');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('applies solid variant classes correctly', () => {
|
|
98
|
+
renderWithProviders(<Badge variant="solid-main-normal">Solid</Badge>);
|
|
99
|
+
const badge = screen.getByText('Solid');
|
|
100
|
+
expect(badge).toHaveClass('bg-main-500', 'text-main-50');
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('applies outline variant classes correctly', () => {
|
|
104
|
+
renderWithProviders(<Badge variant="outline-sec-muted">Outline</Badge>);
|
|
105
|
+
const badge = screen.getByText('Outline');
|
|
106
|
+
expect(badge).toHaveClass('outline', 'outline-1');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('applies soft variant classes correctly', () => {
|
|
110
|
+
renderWithProviders(<Badge variant="soft-acc-strong">Soft</Badge>);
|
|
111
|
+
const badge = screen.getByText('Soft');
|
|
112
|
+
expect(badge).toHaveClass('shadow-badge-soft');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('Color System', () => {
|
|
117
|
+
it('uses main color palette for main variants', () => {
|
|
118
|
+
renderWithProviders(<Badge variant="solid-main-normal">Main</Badge>);
|
|
119
|
+
const badge = screen.getByText('Main');
|
|
120
|
+
expect(badge).toHaveClass('bg-main-500', 'text-main-50');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('uses sec color palette for sec variants', () => {
|
|
124
|
+
renderWithProviders(<Badge variant="solid-sec-normal">Sec</Badge>);
|
|
125
|
+
const badge = screen.getByText('Sec');
|
|
126
|
+
expect(badge).toHaveClass('bg-sec-500', 'text-sec-50');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('uses acc color palette for acc variants', () => {
|
|
130
|
+
renderWithProviders(<Badge variant="solid-acc-normal">Acc</Badge>);
|
|
131
|
+
const badge = screen.getByText('Acc');
|
|
132
|
+
expect(badge).toHaveClass('bg-acc-500', 'text-acc-50');
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('does not use standard Tailwind colors', () => {
|
|
136
|
+
renderWithProviders(<Badge variant="solid-main-normal">Test</Badge>);
|
|
137
|
+
const badge = screen.getByText('Test');
|
|
138
|
+
// Should not have standard Tailwind color classes
|
|
139
|
+
expect(badge).not.toHaveClass('bg-blue-', 'text-red-', 'bg-gray-', 'bg-white', 'bg-black');
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
describe('Shade Variants', () => {
|
|
144
|
+
it('applies muted shade correctly (dark text on light)', () => {
|
|
145
|
+
renderWithProviders(<Badge variant="solid-main-muted">Muted</Badge>);
|
|
146
|
+
const badge = screen.getByText('Muted');
|
|
147
|
+
expect(badge).toHaveClass('bg-main-200', 'text-main-600');
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('applies normal shade correctly (light text on medium)', () => {
|
|
151
|
+
renderWithProviders(<Badge variant="solid-main-normal">Normal</Badge>);
|
|
152
|
+
const badge = screen.getByText('Normal');
|
|
153
|
+
expect(badge).toHaveClass('bg-main-500', 'text-main-50');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('applies strong shade correctly (light text on dark)', () => {
|
|
157
|
+
renderWithProviders(<Badge variant="solid-main-strong">Strong</Badge>);
|
|
158
|
+
const badge = screen.getByText('Strong');
|
|
159
|
+
expect(badge).toHaveClass('bg-main-700', 'text-main-50');
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
describe('Props Forwarding', () => {
|
|
164
|
+
it('forwards HTML attributes', () => {
|
|
165
|
+
renderWithProviders(
|
|
166
|
+
<Badge id="test-id" data-custom="value" aria-label="Test badge">
|
|
167
|
+
Test
|
|
168
|
+
</Badge>
|
|
169
|
+
);
|
|
170
|
+
const badge = screen.getByText('Test');
|
|
171
|
+
expect(badge).toHaveAttribute('id', 'test-id');
|
|
172
|
+
expect(badge).toHaveAttribute('data-custom', 'value');
|
|
173
|
+
expect(badge).toHaveAttribute('aria-label', 'Test badge');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
it('forwards ref correctly', () => {
|
|
177
|
+
const ref = React.createRef<HTMLSpanElement>();
|
|
178
|
+
renderWithProviders(<Badge ref={ref}>Ref badge</Badge>);
|
|
179
|
+
expect(ref.current).toBeInstanceOf(HTMLSpanElement);
|
|
180
|
+
expect(ref.current).toHaveTextContent('Ref badge');
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('merges custom className with variant classes', () => {
|
|
184
|
+
renderWithProviders(
|
|
185
|
+
<Badge variant="solid-main-normal" className="custom-class px-4">
|
|
186
|
+
Custom
|
|
187
|
+
</Badge>
|
|
188
|
+
);
|
|
189
|
+
const badge = screen.getByText('Custom');
|
|
190
|
+
expect(badge).toHaveClass('custom-class', 'px-4', 'bg-main-500');
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
describe('Accessibility', () => {
|
|
195
|
+
it('renders as non-interactive span element', () => {
|
|
196
|
+
const { container } = renderWithProviders(<Badge>Test</Badge>);
|
|
197
|
+
const badge = container.querySelector('span');
|
|
198
|
+
expect(badge).toBeInTheDocument();
|
|
199
|
+
// Should not be a button or have button role
|
|
200
|
+
expect(badge).not.toHaveAttribute('role', 'button');
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it('does not have focus styles by default', () => {
|
|
204
|
+
renderWithProviders(<Badge>Test</Badge>);
|
|
205
|
+
const badge = screen.getByText('Test');
|
|
206
|
+
// Badge should not have focus-visible classes since it's non-interactive
|
|
207
|
+
expect(badge).not.toHaveClass('focus-visible:outline-none');
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('supports aria-label for screen readers', () => {
|
|
211
|
+
renderWithProviders(<Badge aria-label="Status: Active">Active</Badge>);
|
|
212
|
+
const badge = screen.getByText('Active');
|
|
213
|
+
expect(badge).toHaveAttribute('aria-label', 'Status: Active');
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('supports aria-describedby', () => {
|
|
217
|
+
renderWithProviders(
|
|
218
|
+
<Badge aria-describedby="badge-description">Test</Badge>
|
|
219
|
+
);
|
|
220
|
+
const badge = screen.getByText('Test');
|
|
221
|
+
expect(badge).toHaveAttribute('aria-describedby', 'badge-description');
|
|
222
|
+
});
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
describe('Integration', () => {
|
|
226
|
+
it('works with React.forwardRef', () => {
|
|
227
|
+
const ref = React.createRef<HTMLSpanElement>();
|
|
228
|
+
renderWithProviders(<Badge ref={ref}>Ref badge</Badge>);
|
|
229
|
+
expect(ref.current).toBeInstanceOf(HTMLSpanElement);
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('can be wrapped in interactive elements', () => {
|
|
233
|
+
const handleClick = vi.fn();
|
|
234
|
+
renderWithProviders(
|
|
235
|
+
<button onClick={handleClick}>
|
|
236
|
+
<Badge>Clickable badge</Badge>
|
|
237
|
+
</button>
|
|
238
|
+
);
|
|
239
|
+
const button = screen.getByRole('button');
|
|
240
|
+
expect(button).toBeInTheDocument();
|
|
241
|
+
expect(button).toHaveTextContent('Clickable badge');
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('works in complex layouts', () => {
|
|
245
|
+
renderWithProviders(
|
|
246
|
+
<div>
|
|
247
|
+
<h2>Status</h2>
|
|
248
|
+
<Badge variant="solid-main-normal">Active</Badge>
|
|
249
|
+
<Badge variant="outline-sec-muted">Pending</Badge>
|
|
250
|
+
<Badge variant="soft-acc-strong">Featured</Badge>
|
|
251
|
+
</div>
|
|
252
|
+
);
|
|
253
|
+
expect(screen.getByText('Active')).toBeInTheDocument();
|
|
254
|
+
expect(screen.getByText('Pending')).toBeInTheDocument();
|
|
255
|
+
expect(screen.getByText('Featured')).toBeInTheDocument();
|
|
256
|
+
});
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
describe('Edge Cases', () => {
|
|
260
|
+
it('handles empty children gracefully', () => {
|
|
261
|
+
const { container } = renderWithProviders(<Badge></Badge>);
|
|
262
|
+
const badge = container.querySelector('span');
|
|
263
|
+
expect(badge).toBeInTheDocument();
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it('handles very long text content', () => {
|
|
267
|
+
const longText = 'This is a very long badge text that might cause layout issues but should be handled gracefully';
|
|
268
|
+
renderWithProviders(<Badge>{longText}</Badge>);
|
|
269
|
+
expect(screen.getByText(longText)).toBeInTheDocument();
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('handles special characters in text', () => {
|
|
273
|
+
const specialText = 'Badge with special chars: !@#$%^&*()_+-=[]{}|;:,.<>?';
|
|
274
|
+
renderWithProviders(<Badge>{specialText}</Badge>);
|
|
275
|
+
expect(screen.getByText(specialText)).toBeInTheDocument();
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
it('handles numeric content', () => {
|
|
279
|
+
renderWithProviders(<Badge>123</Badge>);
|
|
280
|
+
expect(screen.getByText('123')).toBeInTheDocument();
|
|
281
|
+
});
|
|
282
|
+
|
|
283
|
+
it('handles multiple className overrides', () => {
|
|
284
|
+
renderWithProviders(
|
|
285
|
+
<Badge variant="solid-main-normal" className="px-8 py-2 text-sm">
|
|
286
|
+
Override
|
|
287
|
+
</Badge>
|
|
288
|
+
);
|
|
289
|
+
const badge = screen.getByText('Override');
|
|
290
|
+
expect(badge).toHaveClass('px-8', 'py-2', 'text-sm');
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
describe('Style Variants', () => {
|
|
295
|
+
it('solid variant has no border or blur', () => {
|
|
296
|
+
renderWithProviders(<Badge variant="solid-main-normal">Solid</Badge>);
|
|
297
|
+
const badge = screen.getByText('Solid');
|
|
298
|
+
expect(badge).not.toHaveClass('border', 'backdrop-blur');
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it('outline variant has outline', () => {
|
|
302
|
+
renderWithProviders(<Badge variant="outline-main-muted">Outline</Badge>);
|
|
303
|
+
const badge = screen.getByText('Outline');
|
|
304
|
+
expect(badge).toHaveClass('outline', 'outline-1');
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it('soft variant has shadow', () => {
|
|
308
|
+
renderWithProviders(<Badge variant="soft-main-normal">Soft</Badge>);
|
|
309
|
+
const badge = screen.getByText('Soft');
|
|
310
|
+
expect(badge).toHaveClass('shadow-badge-soft');
|
|
311
|
+
});
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Badge Component
|
|
3
|
+
* @package @jmruthers/pace-core
|
|
4
|
+
* @module Components
|
|
5
|
+
* @since 0.1.0
|
|
6
|
+
*
|
|
7
|
+
* A small, non-interactive visual label component for displaying concise information
|
|
8
|
+
* such as status indicators, tags, or labels. Acts as a visual alternative to buttons
|
|
9
|
+
* for non-interactive content.
|
|
10
|
+
*
|
|
11
|
+
* Features:
|
|
12
|
+
* - 27 combined variants (3 styles × 3 colors × 3 shades)
|
|
13
|
+
* - Non-interactive by default (renders as <span>)
|
|
14
|
+
* - Supports all pace-core color palettes (main, sec, acc)
|
|
15
|
+
* - Customizable styling via className prop
|
|
16
|
+
* - Accessible and screen reader friendly
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* // Basic badge with default variant
|
|
21
|
+
* <Badge>New</Badge>
|
|
22
|
+
*
|
|
23
|
+
* // Badge with specific variant
|
|
24
|
+
* <Badge variant="solid-main-normal">Active</Badge>
|
|
25
|
+
*
|
|
26
|
+
* // Outline variant
|
|
27
|
+
* <Badge variant="outline-sec-muted">Pending</Badge>
|
|
28
|
+
*
|
|
29
|
+
* // Soft variant with accent color
|
|
30
|
+
* <Badge variant="soft-acc-strong">Featured</Badge>
|
|
31
|
+
*
|
|
32
|
+
* // Custom styling
|
|
33
|
+
* <Badge variant="solid-main-normal" className="px-4">
|
|
34
|
+
* Custom Badge
|
|
35
|
+
* </Badge>
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* @accessibility
|
|
39
|
+
* - Renders as semantic <span> element
|
|
40
|
+
* - No focus styles (non-interactive by default)
|
|
41
|
+
* - Screen reader friendly through semantic HTML
|
|
42
|
+
* - Can be wrapped in interactive elements if needed
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
import * as React from 'react';
|
|
46
|
+
import { cn } from '../../utils/core/cn';
|
|
47
|
+
|
|
48
|
+
// ============================================================================
|
|
49
|
+
// TYPE DEFINITIONS
|
|
50
|
+
// ============================================================================
|
|
51
|
+
|
|
52
|
+
export type BadgeVariant =
|
|
53
|
+
| 'solid-main-muted' | 'solid-main-normal' | 'solid-main-strong'
|
|
54
|
+
| 'solid-sec-muted' | 'solid-sec-normal' | 'solid-sec-strong'
|
|
55
|
+
| 'solid-acc-muted' | 'solid-acc-normal' | 'solid-acc-strong'
|
|
56
|
+
| 'outline-main-muted' | 'outline-main-normal' | 'outline-main-strong'
|
|
57
|
+
| 'outline-sec-muted' | 'outline-sec-normal' | 'outline-sec-strong'
|
|
58
|
+
| 'outline-acc-muted' | 'outline-acc-normal' | 'outline-acc-strong'
|
|
59
|
+
| 'soft-main-muted' | 'soft-main-normal' | 'soft-main-strong'
|
|
60
|
+
| 'soft-sec-muted' | 'soft-sec-normal' | 'soft-sec-strong'
|
|
61
|
+
| 'soft-acc-muted' | 'soft-acc-normal' | 'soft-acc-strong';
|
|
62
|
+
|
|
63
|
+
export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
64
|
+
/** Visual variant of the badge (style-color-shade) */
|
|
65
|
+
variant?: BadgeVariant;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// VARIANT CONFIGURATION
|
|
70
|
+
// ============================================================================
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Shade configuration mapping
|
|
74
|
+
* Maps shade names to background, text, border, and outline text color shades
|
|
75
|
+
*/
|
|
76
|
+
const shadeConfig = {
|
|
77
|
+
muted: {
|
|
78
|
+
bg: 200,
|
|
79
|
+
text: 600,
|
|
80
|
+
border: 400,
|
|
81
|
+
outlineText: 600,
|
|
82
|
+
outlineBg: 100,
|
|
83
|
+
},
|
|
84
|
+
normal: {
|
|
85
|
+
bg: 500,
|
|
86
|
+
text: 50,
|
|
87
|
+
border: 700,
|
|
88
|
+
outlineText: 700,
|
|
89
|
+
outlineBg: 200,
|
|
90
|
+
},
|
|
91
|
+
strong: {
|
|
92
|
+
bg: 700,
|
|
93
|
+
text: 50,
|
|
94
|
+
border: 800,
|
|
95
|
+
outlineText: 900,
|
|
96
|
+
outlineBg: 400,
|
|
97
|
+
},
|
|
98
|
+
} as const;
|
|
99
|
+
|
|
100
|
+
type Shade = keyof typeof shadeConfig;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Color palette options
|
|
104
|
+
*/
|
|
105
|
+
const colors = ['main', 'sec', 'acc'] as const;
|
|
106
|
+
type Color = typeof colors[number];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Style options
|
|
110
|
+
*/
|
|
111
|
+
const styles = ['solid', 'outline', 'soft'] as const;
|
|
112
|
+
type Style = typeof styles[number];
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Build variant class string for a given style, color, and shade
|
|
116
|
+
* Generates classes programmatically from configuration
|
|
117
|
+
*/
|
|
118
|
+
function buildVariantClasses(style: Style, color: Color, shade: Shade): string {
|
|
119
|
+
const cfg = shadeConfig[shade];
|
|
120
|
+
const parts: string[] = [];
|
|
121
|
+
|
|
122
|
+
if (style === 'solid') {
|
|
123
|
+
// Solid: flat background colors
|
|
124
|
+
parts.push(`bg-${color}-${cfg.bg}`, `text-${color}-${cfg.text}`);
|
|
125
|
+
} else if (style === 'outline') {
|
|
126
|
+
// Outline: outlined with light background
|
|
127
|
+
parts.push('outline outline-1 -outline-offset-1', `outline-${color}-${cfg.border}`, `bg-${color}-${cfg.outlineBg}`, `text-${color}-${cfg.outlineText}`);
|
|
128
|
+
} else if (style === 'soft') {
|
|
129
|
+
// Soft: uses shadow-badge-soft utility with colored shadows
|
|
130
|
+
parts.push(
|
|
131
|
+
`bg-${color}-${cfg.bg}`,
|
|
132
|
+
'shadow-badge-soft',
|
|
133
|
+
`shadow-${color}-${cfg.bg}`,
|
|
134
|
+
`text-${color}-${cfg.text}`,
|
|
135
|
+
'my-1', 'mx-1', 'py-0', 'px-2'
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return parts.join(' ');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Generate all class name patterns for Tailwind scanning
|
|
144
|
+
* This ensures Tailwind can detect all dynamically generated classes
|
|
145
|
+
*
|
|
146
|
+
* Tailwind v4 content scanning: These classes are listed here so Tailwind
|
|
147
|
+
* can detect them during content scanning, even when built dynamically.
|
|
148
|
+
*
|
|
149
|
+
* Classes used: shadow-badge-soft shadow-main-200 shadow-main-500 shadow-main-700
|
|
150
|
+
* shadow-sec-200 shadow-sec-500 shadow-sec-700 shadow-acc-200 shadow-acc-500 shadow-acc-700
|
|
151
|
+
*/
|
|
152
|
+
const tailwindClassScan = [
|
|
153
|
+
// Solid background classes
|
|
154
|
+
'bg-main-100', 'bg-main-600', 'bg-main-900',
|
|
155
|
+
'bg-sec-100', 'bg-sec-600', 'bg-sec-900',
|
|
156
|
+
'bg-acc-100', 'bg-acc-600', 'bg-acc-900',
|
|
157
|
+
// Solid text classes
|
|
158
|
+
'text-main-50', 'text-main-900',
|
|
159
|
+
'text-sec-50', 'text-sec-900',
|
|
160
|
+
'text-acc-50', 'text-acc-900',
|
|
161
|
+
// Outline classes
|
|
162
|
+
'outline outline-1',
|
|
163
|
+
'outline-main-400', 'outline-main-700', 'outline-main-800',
|
|
164
|
+
'outline-sec-400', 'outline-sec-700', 'outline-sec-800',
|
|
165
|
+
'outline-acc-400', 'outline-acc-700', 'outline-acc-800',
|
|
166
|
+
// Outline background classes
|
|
167
|
+
'bg-main-100', 'bg-main-200', 'bg-main-300',
|
|
168
|
+
'bg-sec-100', 'bg-sec-200', 'bg-sec-300',
|
|
169
|
+
'bg-acc-100', 'bg-acc-200', 'bg-acc-300',
|
|
170
|
+
// Outline text classes
|
|
171
|
+
'text-main-500', 'text-main-600', 'text-main-800',
|
|
172
|
+
'text-sec-500', 'text-sec-600', 'text-sec-800',
|
|
173
|
+
'text-acc-500', 'text-acc-600', 'text-acc-800',
|
|
174
|
+
// Soft background classes (solid, no opacity)
|
|
175
|
+
'bg-main-200', 'bg-main-500', 'bg-main-700',
|
|
176
|
+
'bg-sec-200', 'bg-sec-500', 'bg-sec-700',
|
|
177
|
+
'bg-acc-200', 'bg-acc-500', 'bg-acc-700',
|
|
178
|
+
// Soft shadow utility classes - CRITICAL: These must be detected by Tailwind
|
|
179
|
+
'shadow-badge-soft',
|
|
180
|
+
'shadow-main-200', 'shadow-main-500', 'shadow-main-700',
|
|
181
|
+
'shadow-sec-200', 'shadow-sec-500', 'shadow-sec-700',
|
|
182
|
+
'shadow-acc-200', 'shadow-acc-500', 'shadow-acc-700',
|
|
183
|
+
// Soft margin/padding classes
|
|
184
|
+
'my-3', 'mx-3', 'py-0', 'px-2',
|
|
185
|
+
] as const;
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Generate all variant class combinations programmatically
|
|
189
|
+
* Uses the configuration to build the lookup map dynamically
|
|
190
|
+
*/
|
|
191
|
+
function generateVariantClasses(): Record<BadgeVariant, string> {
|
|
192
|
+
const variantClasses = {} as Record<BadgeVariant, string>;
|
|
193
|
+
|
|
194
|
+
for (const style of styles) {
|
|
195
|
+
for (const color of colors) {
|
|
196
|
+
for (const shade of Object.keys(shadeConfig) as Shade[]) {
|
|
197
|
+
const variant = `${style}-${color}-${shade}` as BadgeVariant;
|
|
198
|
+
variantClasses[variant] = buildVariantClasses(style, color, shade);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return variantClasses;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Pre-generate all variant classes
|
|
207
|
+
const variantClassesMap = generateVariantClasses();
|
|
208
|
+
|
|
209
|
+
// Ensure Tailwind detects shadow-badge-soft class
|
|
210
|
+
// This string literal ensures Tailwind v4 content scanning includes the class
|
|
211
|
+
const _tailwindShadowDetection = 'shadow-badge-soft';
|
|
212
|
+
|
|
213
|
+
// ============================================================================
|
|
214
|
+
// CLASS GENERATION FUNCTION
|
|
215
|
+
// ============================================================================
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get badge classes based on variant
|
|
219
|
+
*
|
|
220
|
+
* Variant format: {style}-{color}-{shade}
|
|
221
|
+
* - style: solid (flat), outline (bordered), soft (blurred)
|
|
222
|
+
* - color: main, sec, acc
|
|
223
|
+
* - shade: muted (dark on light), normal (light on medium), strong (light on dark)
|
|
224
|
+
*/
|
|
225
|
+
function getBadgeClasses(variant: BadgeVariant = 'solid-main-normal'): string {
|
|
226
|
+
const baseClasses = 'inline-flex text-balance items-center rounded-2xl px-3 py-1 text-xs font-medium transition-colors box-border';
|
|
227
|
+
return `${baseClasses} ${variantClassesMap[variant]}`;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// ============================================================================
|
|
231
|
+
// BADGE COMPONENT
|
|
232
|
+
// ============================================================================
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Badge Component
|
|
236
|
+
* A small, non-interactive visual label for displaying concise information.
|
|
237
|
+
*
|
|
238
|
+
* @component
|
|
239
|
+
* @example
|
|
240
|
+
* ```tsx
|
|
241
|
+
* // Default variant
|
|
242
|
+
* <Badge>New</Badge>
|
|
243
|
+
*
|
|
244
|
+
* // Specific variant
|
|
245
|
+
* <Badge variant="solid-main-normal">Active</Badge>
|
|
246
|
+
*
|
|
247
|
+
* // Outline variant
|
|
248
|
+
* <Badge variant="outline-sec-muted">Pending</Badge>
|
|
249
|
+
*
|
|
250
|
+
* // Soft variant
|
|
251
|
+
* <Badge variant="soft-acc-strong">Featured</Badge>
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
const Badge = React.forwardRef<HTMLSpanElement, BadgeProps>(
|
|
255
|
+
({ className, variant = 'solid-main-normal', ...props }, ref) => {
|
|
256
|
+
const isSoftVariant = variant.startsWith('soft-');
|
|
257
|
+
|
|
258
|
+
if (isSoftVariant) {
|
|
259
|
+
// For soft variants, we need both shadow-badge-soft and shadow color class
|
|
260
|
+
// twMerge treats all shadow-* classes as conflicting, so we need to add them after merging
|
|
261
|
+
const variantClasses = getBadgeClasses(variant);
|
|
262
|
+
// Extract the shadow color class from variantClasses (e.g., shadow-main-200)
|
|
263
|
+
const shadowColorMatch = variantClasses.match(/\bshadow-(\w+)-(\d+)\b/);
|
|
264
|
+
const shadowColorClass = shadowColorMatch ? shadowColorMatch[0] : '';
|
|
265
|
+
|
|
266
|
+
// Remove shadow classes from variantClasses to avoid twMerge conflicts
|
|
267
|
+
const classesWithoutShadows = variantClasses
|
|
268
|
+
.replace(/\bshadow-badge-soft\b/g, '')
|
|
269
|
+
.replace(/\bshadow-\w+-\d+\b/g, '')
|
|
270
|
+
.replace(/\s+/g, ' ')
|
|
271
|
+
.trim();
|
|
272
|
+
|
|
273
|
+
// Merge non-shadow classes first, then append shadow classes to ensure both are present
|
|
274
|
+
// shadow-badge-soft first (defines shape), then shadow color (defines color)
|
|
275
|
+
const mergedClasses = cn(classesWithoutShadows, className);
|
|
276
|
+
const finalClasses = `${mergedClasses} shadow-badge-soft ${shadowColorClass}`.trim();
|
|
277
|
+
|
|
278
|
+
return (
|
|
279
|
+
<span
|
|
280
|
+
ref={ref}
|
|
281
|
+
className={finalClasses}
|
|
282
|
+
{...props}
|
|
283
|
+
/>
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return (
|
|
288
|
+
<span
|
|
289
|
+
ref={ref}
|
|
290
|
+
className={cn(getBadgeClasses(variant), className)}
|
|
291
|
+
{...props}
|
|
292
|
+
/>
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
Badge.displayName = 'Badge';
|
|
298
|
+
|
|
299
|
+
// ============================================================================
|
|
300
|
+
// EXPORTS
|
|
301
|
+
// ============================================================================
|
|
302
|
+
|
|
303
|
+
export { Badge };
|
|
304
|
+
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
|
|
47
47
|
import * as React from 'react';
|
|
48
48
|
import { Slot } from '@radix-ui/react-slot';
|
|
49
|
-
import { cn } from '../../utils/cn';
|
|
49
|
+
import { cn } from '../../utils/core/cn';
|
|
50
50
|
import { Tooltip } from '../Tooltip';
|
|
51
51
|
|
|
52
52
|
// ============================================================================
|
|
@@ -49,7 +49,7 @@ import * as React from "react"
|
|
|
49
49
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
|
|
50
50
|
import { Check } from "lucide-react"
|
|
51
51
|
|
|
52
|
-
import { cn } from "../../utils/cn"
|
|
52
|
+
import { cn } from "../../utils/core/cn"
|
|
53
53
|
|
|
54
54
|
const Checkbox = React.forwardRef<
|
|
55
55
|
React.ElementRef<typeof CheckboxPrimitive.Root>,
|