@jmruthers/pace-core 0.5.127 → 0.5.129

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.
Files changed (131) hide show
  1. package/dist/{DataTable-QZH6SEUM.js → DataTable-O2COE77K.js} +2 -2
  2. package/dist/{PublicLoadingSpinner-qqvM-NUe.d.ts → PublicLoadingSpinner-CUAnTvcg.d.ts} +7 -0
  3. package/dist/{chunk-JDBO5NCG.js → chunk-BJ7MCGY6.js} +66 -18
  4. package/dist/chunk-BJ7MCGY6.js.map +1 -0
  5. package/dist/{chunk-TMUNK34W.js → chunk-MOOJ2TK6.js} +37 -9
  6. package/dist/chunk-MOOJ2TK6.js.map +1 -0
  7. package/dist/components.d.ts +1 -1
  8. package/dist/components.js +2 -2
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.js +2 -2
  11. package/dist/utils.d.ts +1 -1
  12. package/dist/utils.js +1 -1
  13. package/docs/api/classes/ColumnFactory.md +1 -1
  14. package/docs/api/classes/ErrorBoundary.md +1 -1
  15. package/docs/api/classes/InvalidScopeError.md +1 -1
  16. package/docs/api/classes/MissingUserContextError.md +1 -1
  17. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  18. package/docs/api/classes/PermissionDeniedError.md +1 -1
  19. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  20. package/docs/api/classes/RBACAuditManager.md +1 -1
  21. package/docs/api/classes/RBACCache.md +1 -1
  22. package/docs/api/classes/RBACEngine.md +1 -1
  23. package/docs/api/classes/RBACError.md +1 -1
  24. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  25. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  26. package/docs/api/classes/StorageUtils.md +1 -1
  27. package/docs/api/enums/FileCategory.md +1 -1
  28. package/docs/api/interfaces/AggregateConfig.md +1 -1
  29. package/docs/api/interfaces/ButtonProps.md +1 -1
  30. package/docs/api/interfaces/CardProps.md +1 -1
  31. package/docs/api/interfaces/ColorPalette.md +1 -1
  32. package/docs/api/interfaces/ColorShade.md +1 -1
  33. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  34. package/docs/api/interfaces/DataRecord.md +1 -1
  35. package/docs/api/interfaces/DataTableAction.md +1 -1
  36. package/docs/api/interfaces/DataTableColumn.md +1 -1
  37. package/docs/api/interfaces/DataTableProps.md +1 -1
  38. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  39. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  40. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  41. package/docs/api/interfaces/EventAppRoleData.md +1 -1
  42. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  43. package/docs/api/interfaces/FileMetadata.md +1 -1
  44. package/docs/api/interfaces/FileReference.md +1 -1
  45. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  46. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  47. package/docs/api/interfaces/FileUploadProps.md +1 -1
  48. package/docs/api/interfaces/FooterProps.md +1 -1
  49. package/docs/api/interfaces/GrantEventAppRoleParams.md +1 -1
  50. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  51. package/docs/api/interfaces/InputProps.md +1 -1
  52. package/docs/api/interfaces/LabelProps.md +1 -1
  53. package/docs/api/interfaces/LoginFormProps.md +1 -1
  54. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  55. package/docs/api/interfaces/NavigationContextType.md +1 -1
  56. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  57. package/docs/api/interfaces/NavigationItem.md +1 -1
  58. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  59. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  60. package/docs/api/interfaces/Organisation.md +1 -1
  61. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  62. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  63. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  64. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  65. package/docs/api/interfaces/PaceAppLayoutProps.md +27 -27
  66. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  67. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  68. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  69. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  70. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  71. package/docs/api/interfaces/PaletteData.md +1 -1
  72. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  73. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  74. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  75. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  76. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  77. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  78. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  79. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  80. package/docs/api/interfaces/RBACConfig.md +1 -1
  81. package/docs/api/interfaces/RBACLogger.md +1 -1
  82. package/docs/api/interfaces/RevokeEventAppRoleParams.md +1 -1
  83. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  84. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  85. package/docs/api/interfaces/RoleManagementResult.md +1 -1
  86. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  87. package/docs/api/interfaces/RouteConfig.md +1 -1
  88. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  89. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  90. package/docs/api/interfaces/StorageConfig.md +1 -1
  91. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  92. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  93. package/docs/api/interfaces/StorageListOptions.md +1 -1
  94. package/docs/api/interfaces/StorageListResult.md +1 -1
  95. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  96. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  97. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  98. package/docs/api/interfaces/StyleImport.md +1 -1
  99. package/docs/api/interfaces/SwitchProps.md +1 -1
  100. package/docs/api/interfaces/ToastActionElement.md +1 -1
  101. package/docs/api/interfaces/ToastProps.md +1 -1
  102. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  103. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  104. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  105. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  106. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  107. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  108. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +1 -1
  109. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  110. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  111. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  112. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  113. package/docs/api/interfaces/UserEventAccess.md +1 -1
  114. package/docs/api/interfaces/UserMenuProps.md +1 -1
  115. package/docs/api/interfaces/UserProfile.md +1 -1
  116. package/docs/api/modules.md +10 -3
  117. package/docs/api-reference/components.md +24 -0
  118. package/docs/api-reference/types.md +28 -0
  119. package/docs/implementation-guides/data-tables.md +93 -10
  120. package/docs/implementation-guides/permission-enforcement.md +4 -0
  121. package/docs/rbac/super-admin-guide.md +43 -5
  122. package/package.json +1 -1
  123. package/src/components/DataTable/__tests__/DataTable.export.test.tsx +702 -0
  124. package/src/components/DataTable/components/DataTableCore.tsx +90 -39
  125. package/src/components/DataTable/index.ts +3 -1
  126. package/src/components/DataTable/types.ts +68 -0
  127. package/src/components/PaceAppLayout/PaceAppLayout.tsx +60 -11
  128. package/src/components/PaceAppLayout/__tests__/PaceAppLayout.security.test.tsx +81 -1
  129. package/dist/chunk-JDBO5NCG.js.map +0 -1
  130. package/dist/chunk-TMUNK34W.js.map +0 -1
  131. /package/dist/{DataTable-QZH6SEUM.js.map → DataTable-O2COE77K.js.map} +0 -0
@@ -1,6 +1,6 @@
1
- [@jmruthers/pace-core - v0.5.127](README.md) / Exports
1
+ [@jmruthers/pace-core - v0.5.129](README.md) / Exports
2
2
 
3
- # @jmruthers/pace-core - v0.5.127
3
+ # @jmruthers/pace-core - v0.5.129
4
4
 
5
5
  **`File`**
6
6
 
@@ -2309,6 +2309,12 @@ This component is designed to work with React Router's nested routing pattern us
2309
2309
  Outlet to render child routes. It provides integrated authentication, navigation,
2310
2310
  and user management functionality.
2311
2311
 
2312
+ **Super Admin Access:** When `enforcePermissions={true}`, PaceAppLayout automatically
2313
+ checks if the user is a super admin before enforcing permissions. Super admins bypass
2314
+ all permission checks and can access any route without violations. The component extracts
2315
+ base page names from route paths (e.g., `/organisation/scouts-victoria` → `"organisation"`)
2316
+ for permission checking, which can be overridden using `pageIdMapping`.
2317
+
2312
2318
  **Important:** The appName prop should use an APP_NAME constant declared in your App.tsx
2313
2319
  file. This ensures consistency with public pages (via PublicPageProvider) which should
2314
2320
  also receive the same APP_NAME constant. The logo URL is automatically constructed as
@@ -2325,6 +2331,7 @@ Features:
2325
2331
  - Layout-level permission enforcement
2326
2332
  - Permission-based navigation filtering
2327
2333
  - Automatic page permission validation
2334
+ - Super admin bypass (super admins automatically bypass all permission checks)
2328
2335
 
2329
2336
  #### Parameters
2330
2337
 
@@ -2455,7 +2462,7 @@ function AdminApp() {
2455
2462
 
2456
2463
  #### Defined in
2457
2464
 
2458
- [packages/core/src/components/PaceAppLayout/PaceAppLayout.tsx:336](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/PaceAppLayout/PaceAppLayout.tsx#L336)
2465
+ [packages/core/src/components/PaceAppLayout/PaceAppLayout.tsx:344](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/PaceAppLayout/PaceAppLayout.tsx#L344)
2459
2466
 
2460
2467
  ___
2461
2468
 
@@ -123,6 +123,12 @@ interface DataTableProps<TData extends DataRecord> {
123
123
  onDeleteRow?: (row: TData) => void;
124
124
  onCreateRow?: (data: Partial<TData>) => void;
125
125
  onImport?: (data: TData[]) => void | Promise<void>;
126
+ /**
127
+ * Custom export handler - allows full control over export columns and filename
128
+ * Receives ExportOptions with tableRows, allColumns, visibleColumns, and more
129
+ * If not provided, defaults to exporting all visible columns
130
+ */
131
+ onExport?: (options: ExportOptions<TData>) => void | Promise<void>;
126
132
  onDeleteSelected?: (selectedRows: Record<string, boolean>) => void;
127
133
 
128
134
  // Performance
@@ -276,6 +282,24 @@ const columns: DataTableColumn<User>[] = [
276
282
  onEditRow={handleEdit}
277
283
  onDeleteRow={handleDelete}
278
284
  onCreateRow={handleCreate}
285
+ onExport={async (options) => {
286
+ // Custom export with specific columns
287
+ const exportColumns = options.allColumns
288
+ .filter(col => ['name', 'email'].includes(col.accessorKey || ''))
289
+ .map(col => ({
290
+ header: col.header || col.accessorKey,
291
+ id: col.id || col.accessorKey,
292
+ accessorKey: col.accessorKey,
293
+ accessorFn: 'accessorFn' in col ? col.accessorFn : undefined,
294
+ }));
295
+
296
+ await exportToCSVWithTableRows(
297
+ options.tableRows,
298
+ exportColumns,
299
+ options.columnIdToTableColumn,
300
+ 'users-export.csv'
301
+ );
302
+ }}
279
303
  />
280
304
  ```
281
305
 
@@ -334,6 +334,33 @@ interface ButtonProps {
334
334
  }
335
335
  ```
336
336
 
337
+ ### ExportOptions
338
+
339
+ Options provided to the `onExport` handler for custom export functionality.
340
+
341
+ ```typescript
342
+ interface ExportOptions<TData extends DataRecord> {
343
+ /** Filtered table rows with getValue() method for proper accessorFn evaluation */
344
+ tableRows: Array<{
345
+ original: TData;
346
+ getValue: (columnId: string) => any;
347
+ id: string;
348
+ }>;
349
+ /** All column definitions passed to the DataTable */
350
+ allColumns: DataTableColumn<TData>[];
351
+ /** Currently visible columns in the table */
352
+ visibleColumns: DataTableColumn<TData>[];
353
+ /** Mapping of column IDs to TanStack table column instances (for getValue() calls) */
354
+ columnIdToTableColumn: Map<string, any>;
355
+ /** Raw data array (unfiltered) */
356
+ data: TData[];
357
+ /** Default filename generated from table title */
358
+ filename: string;
359
+ /** TanStack table instance for advanced operations */
360
+ table: any;
361
+ }
362
+ ```
363
+
337
364
  ### DataTableProps
338
365
 
339
366
  Props for the DataTable component.
@@ -948,6 +975,7 @@ export type {
948
975
  // UI Components
949
976
  ButtonProps,
950
977
  DataTableProps,
978
+ ExportOptions,
951
979
  ColumnDef,
952
980
  PaginationConfig,
953
981
  SortingConfig,
@@ -1746,35 +1746,118 @@ The import automatically recognizes and maps:
1746
1746
  />
1747
1747
  ```
1748
1748
 
1749
- ### Custom Export Filename
1749
+ ### Custom Export
1750
1750
 
1751
1751
  The export filename is automatically generated from the table `title` prop:
1752
1752
 
1753
1753
  - If `title` is provided: `{title}_{date}.csv` (e.g., `meals_2024-04-11.csv`)
1754
1754
  - If no `title`: `data_export_{date}.csv`
1755
1755
 
1756
- To customize the filename, you can provide a custom `onExport` handler:
1756
+ By default, the DataTable exports all **visible columns**. To customize the export (different columns, custom filename, etc.), you can provide a custom `onExport` handler:
1757
1757
 
1758
1758
  ```tsx
1759
+ import { DataTable, type ExportOptions, exportToCSVWithTableRows, type ExportColumn } from '@jmruthers/pace-core';
1760
+
1759
1761
  <DataTable
1760
1762
  title="Meals"
1761
1763
  columns={columns}
1762
1764
  features={{ export: true }}
1763
- onExport={async () => {
1764
- // Custom export logic
1765
- const data = getFilteredData();
1766
- await exportToCSV(data, columns, 'custom-export-name.csv');
1765
+ onExport={async (options: ExportOptions<Meal>) => {
1766
+ // Export only specific columns (different from visible columns)
1767
+ const exportColumnIds = ['name', 'email', 'role'];
1768
+
1769
+ const exportColumns: ExportColumn[] = exportColumnIds
1770
+ .map(columnId => {
1771
+ // Find the column definition
1772
+ const column = options.allColumns.find(col =>
1773
+ col.id === columnId || col.accessorKey === columnId
1774
+ );
1775
+ if (!column) return null;
1776
+
1777
+ // CRITICAL: The id must match the key in columnIdToTableColumn
1778
+ // TanStack Table uses String(column.id || column.accessorKey) as the column ID
1779
+ const tableColumnId = String(column.id || column.accessorKey);
1780
+
1781
+ // Verify this column ID exists in the mapping (for getValue() to work)
1782
+ if (!options.columnIdToTableColumn.has(tableColumnId)) {
1783
+ console.warn(`Column ID ${tableColumnId} not found in columnIdToTableColumn map`);
1784
+ return null;
1785
+ }
1786
+
1787
+ return {
1788
+ header: column.header || column.accessorKey,
1789
+ id: tableColumnId, // Must be string and match columnIdToTableColumn key
1790
+ accessorKey: column.accessorKey,
1791
+ accessorFn: 'accessorFn' in column ? column.accessorFn : undefined,
1792
+ };
1793
+ })
1794
+ .filter((col): col is ExportColumn => col !== null);
1795
+
1796
+ // Use the provided table rows and column mapping for proper accessorFn evaluation
1797
+ await exportToCSVWithTableRows(
1798
+ options.tableRows,
1799
+ exportColumns,
1800
+ options.columnIdToTableColumn,
1801
+ 'custom-export-name.csv'
1802
+ );
1767
1803
  }}
1768
1804
  />
1769
1805
  ```
1770
1806
 
1807
+ ### Export Options
1808
+
1809
+ The `onExport` handler receives an `ExportOptions` object with:
1810
+
1811
+ - `tableRows` - Filtered table rows with `getValue()` method for proper `accessorFn` evaluation
1812
+ - `allColumns` - All column definitions passed to the DataTable
1813
+ - `visibleColumns` - Currently visible columns in the table
1814
+ - `columnIdToTableColumn` - Mapping of column IDs to TanStack table column instances (for `getValue()` calls)
1815
+ - `data` - Raw data array (unfiltered)
1816
+ - `filename` - Default filename generated from table title
1817
+ - `table` - TanStack table instance for advanced operations
1818
+
1771
1819
  ### Export Column Selection
1772
1820
 
1773
- **Important**: Only **visible columns** are exported. If a column is hidden (via column visibility controls), it will not be included in the export.
1821
+ **Default Behavior**: Only **visible columns** are exported. If a column is hidden (via column visibility controls), it will not be included in the export.
1822
+
1823
+ **Custom Export**: Use the `onExport` handler to export different columns than what's visible in the table:
1824
+
1825
+ ```tsx
1826
+ onExport={async (options) => {
1827
+ // Export all columns (including hidden ones)
1828
+ const allExportColumns: ExportColumn[] = options.allColumns
1829
+ .map(col => {
1830
+ // Get the table column ID (must match columnIdToTableColumn key)
1831
+ const tableColumnId = String(col.id || col.accessorKey);
1832
+
1833
+ // Only include columns that exist in the table mapping
1834
+ if (!options.columnIdToTableColumn.has(tableColumnId)) {
1835
+ return null;
1836
+ }
1837
+
1838
+ return {
1839
+ header: col.header || col.accessorKey,
1840
+ id: tableColumnId, // Must be string and match columnIdToTableColumn key
1841
+ accessorKey: col.accessorKey,
1842
+ accessorFn: 'accessorFn' in col ? col.accessorFn : undefined,
1843
+ };
1844
+ })
1845
+ .filter((col): col is ExportColumn => col !== null);
1846
+
1847
+ await exportToCSVWithTableRows(
1848
+ options.tableRows,
1849
+ allExportColumns,
1850
+ options.columnIdToTableColumn,
1851
+ 'all-columns-export.csv'
1852
+ );
1853
+ }}
1854
+ ```
1774
1855
 
1775
- To ensure all columns are exported:
1776
- - Make sure all desired columns are visible before exporting
1777
- - Or use a custom `onExport` handler to export specific columns
1856
+ **Important Notes:**
1857
+ - The `id` field in `ExportColumn` **must** be a string and must exactly match a key in `columnIdToTableColumn`
1858
+ - Use `String(column.id || column.accessorKey)` to get the correct table column ID
1859
+ - Always verify the column ID exists in `columnIdToTableColumn` before using it
1860
+ - This ensures `getValue()` works correctly for columns with `accessorFn`
1778
1861
 
1779
1862
  ### Import Column Mapping
1780
1863
 
@@ -53,6 +53,8 @@ setupRBAC(supabase);
53
53
 
54
54
  Layout-level enforcement provides a safety net that prevents consuming apps from forgetting to implement permission checks. It ensures that every route is automatically validated for permissions.
55
55
 
56
+ **Note:** Super admins automatically bypass all permission checks in PaceAppLayout. The component checks super admin status before enforcing permissions, ensuring super admins can access any route without violations.
57
+
56
58
  ### Basic Implementation
57
59
 
58
60
  ```tsx
@@ -107,6 +109,8 @@ Configure different permissions for different routes:
107
109
  />
108
110
  ```
109
111
 
112
+ **Page Name Mapping:** PaceAppLayout automatically extracts the base page name from route paths. For nested routes like `/organisation/scouts-victoria`, it uses `"organisation"` (the first path segment) as the page name. You can override this using `pageIdMapping` to provide custom page IDs for specific routes.
113
+
110
114
  ### Navigation Filtering
111
115
 
112
116
  Filter navigation items based on user permissions:
@@ -260,7 +260,45 @@ function FilteredDataTable() {
260
260
  }
261
261
  ```
262
262
 
263
- ## 8. Navigation Guards
263
+ ## 8. PaceAppLayout Super Admin Bypass
264
+
265
+ When using `PaceAppLayout` with `enforcePermissions={true}`, super admins automatically bypass all permission checks:
266
+
267
+ ```tsx
268
+ import { PaceAppLayout } from '@jmruthers/pace-core';
269
+
270
+ function App() {
271
+ return (
272
+ <UnifiedAuthProvider supabaseClient={supabase} appName="My App">
273
+ <Router>
274
+ <Routes>
275
+ <Route path="/" element={
276
+ <PaceAppLayout
277
+ appName="My Application"
278
+ enforcePermissions={true}
279
+ defaultPermission="read"
280
+ />
281
+ }>
282
+ <Route index element={<HomePage />} />
283
+ <Route path="dashboard" element={<DashboardPage />} />
284
+ <Route path="organisation/:orgSlug" element={<OrganisationPage />} />
285
+ </Route>
286
+ </Routes>
287
+ </Router>
288
+ </UnifiedAuthProvider>
289
+ );
290
+ }
291
+ ```
292
+
293
+ **Key Features:**
294
+ - Super admins bypass all permission checks automatically
295
+ - No strict mode violations logged for super admins
296
+ - Page name extraction: nested routes like `/organisation/scouts-victoria` use `"organisation"` as the page name
297
+ - Custom page IDs can be provided via `pageIdMapping` prop
298
+
299
+ **Note:** PaceAppLayout checks super admin status before enforcing permissions, ensuring super admins can access any route without violations or access denied errors.
300
+
301
+ ## 9. Navigation Guards
264
302
 
265
303
  Protect entire routes for super admins:
266
304
 
@@ -303,7 +341,7 @@ function AdminRoutes() {
303
341
  }
304
342
  ```
305
343
 
306
- ## 9. Environment-Specific Configuration
344
+ ## 10. Environment-Specific Configuration
307
345
 
308
346
  You can also check for super admin access in your environment configuration:
309
347
 
@@ -321,7 +359,7 @@ const appConfig = {
321
359
  };
322
360
  ```
323
361
 
324
- ## 10. Best Practices
362
+ ## 11. Best Practices
325
363
 
326
364
  ### ✅ Do:
327
365
  - Always check `isSuperAdmin` first for performance
@@ -336,7 +374,7 @@ const appConfig = {
336
374
  - Skip permission checks assuming super admin status
337
375
  - Use anon key for super admin operations
338
376
 
339
- ## 11. Testing Super Admin Access
377
+ ## 12. Testing Super Admin Access
340
378
 
341
379
  ```tsx
342
380
  import { render, screen } from '@testing-library/react';
@@ -373,7 +411,7 @@ test('shows regular content for non-super admin users', () => {
373
411
  });
374
412
  ```
375
413
 
376
- ## 12. Practical Examples
414
+ ## 13. Practical Examples
377
415
 
378
416
  ### Basic Super Admin Check
379
417
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmruthers/pace-core",
3
- "version": "0.5.127",
3
+ "version": "0.5.129",
4
4
  "description": "Clean, modern React component library with Tailwind v4 styling and native utilities",
5
5
  "private": false,
6
6
  "publishConfig": {