@jmruthers/pace-core 0.6.6 → 0.6.7
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/{scripts/audit/audit-dependencies.cjs → audit-tool/00-dependencies.cjs} +12 -13
- package/audit-tool/audits/01-pace-core-compliance.cjs +556 -0
- package/audit-tool/audits/02-project-structure.cjs +255 -0
- package/audit-tool/audits/03-architecture.cjs +196 -0
- package/audit-tool/audits/04-code-quality.cjs +149 -0
- package/audit-tool/audits/05-styling.cjs +224 -0
- package/audit-tool/audits/06-security-rbac.cjs +544 -0
- package/audit-tool/audits/07-api-tech-stack.cjs +301 -0
- package/audit-tool/audits/08-testing-documentation.cjs +202 -0
- package/audit-tool/audits/09-operations.cjs +208 -0
- package/audit-tool/index.cjs +291 -0
- package/audit-tool/utils/code-utils.cjs +218 -0
- package/audit-tool/utils/file-utils.cjs +230 -0
- package/audit-tool/utils/report-utils.cjs +241 -0
- package/cursor-rules/00-standards-overview.mdc +156 -0
- package/cursor-rules/{00-pace-core-compliance.mdc → 01-pace-core-compliance.mdc} +187 -34
- package/cursor-rules/02-project-structure.mdc +37 -5
- package/cursor-rules/{03-solid-principles.mdc → 03-architecture.mdc} +125 -11
- package/cursor-rules/04-code-quality.mdc +419 -0
- package/cursor-rules/{08-markup-quality.mdc → 05-styling.mdc} +55 -10
- package/cursor-rules/{09-rbac-compliance.mdc → 06-security-rbac.mdc} +62 -6
- package/cursor-rules/07-api-tech-stack.mdc +377 -0
- package/cursor-rules/08-testing-documentation.mdc +324 -0
- package/cursor-rules/09-operations.mdc +365 -0
- package/dist/DataTable-7PMH7XN7.js +15 -0
- package/dist/{DataTable-2N_tqbfq.d.ts → DataTable-DRUIgtUH.d.ts} +1 -1
- package/dist/{PublicPageProvider-BBH6Vqg7.d.ts → PublicPageProvider-DlsCaR5v.d.ts} +26 -16
- package/dist/{chunk-FENMYN2U.js → chunk-5X4QLXRG.js} +1 -3
- package/dist/{chunk-4T7OBVTU.js → chunk-6F3IILHI.js} +1 -1
- package/dist/{chunk-SD6WQY43.js → chunk-7ILTDCL2.js} +9 -1
- package/dist/{chunk-3QC3KRHK.js → chunk-A3W6LW53.js} +16 -1
- package/dist/{chunk-7TYHROIV.js → chunk-BM4CQ5P3.js} +50 -8
- package/dist/{chunk-2HGJFNAH.js → chunk-FEJLJNWA.js} +1 -15
- package/dist/{chunk-OHIK3MIO.js → chunk-GHYHJTYV.js} +2 -2
- package/dist/{chunk-UIYSCEV7.js → chunk-IUBRCBSY.js} +1 -1
- package/dist/{chunk-LAZMKTTF.js → chunk-JGWDVX64.js} +281 -347
- package/dist/{chunk-MAGBIDNS.js → chunk-L4XMVJKY.js} +2 -2
- package/dist/{chunk-A55DK444.js → chunk-OJ4SKRSV.js} +1 -7
- package/dist/{chunk-ZS5VO5JB.js → chunk-Q7Q7V5NV.js} +406 -451
- package/dist/{chunk-3O3WHILE.js → chunk-VBCS3DUA.js} +236 -60
- package/dist/{chunk-BVP2BCJF.js → chunk-ZKAWKYT4.js} +8 -8
- package/dist/components.d.ts +5 -4
- package/dist/components.js +27 -32
- package/dist/eslint-rules/index.cjs +22 -9
- package/{src/eslint-rules/rules/compliance.cjs → dist/eslint-rules/rules/01-pace-core-compliance.cjs} +184 -23
- package/dist/eslint-rules/rules/04-code-quality.cjs +290 -0
- package/dist/eslint-rules/rules/05-styling.cjs +61 -0
- package/dist/eslint-rules/rules/{rbac.cjs → 06-security-rbac.cjs} +26 -10
- package/dist/eslint-rules/rules/07-api-tech-stack.cjs +263 -0
- package/dist/eslint-rules/rules/08-testing.cjs +94 -0
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +18 -17
- package/dist/rbac/index.js +6 -6
- package/dist/theming/runtime.d.ts +14 -1
- package/dist/theming/runtime.js +1 -1
- package/dist/{types-B-K_5VnO.d.ts → types-DXstZpNI.d.ts} +0 -17
- package/dist/{usePublicRouteParams-COZ28Mvq.d.ts → usePublicRouteParams-MamNgwqe.d.ts} +19 -19
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +8 -8
- package/docs/README.md +1 -1
- package/docs/api/modules.md +47 -31
- package/docs/api-reference/components.md +18 -20
- package/docs/api-reference/hooks.md +80 -80
- package/docs/api-reference/types.md +1 -1
- package/docs/api-reference/utilities.md +1 -1
- package/docs/architecture/README.md +1 -1
- package/docs/core-concepts/events.md +3 -3
- package/docs/core-concepts/organisations.md +6 -6
- package/docs/core-concepts/permissions.md +6 -6
- package/docs/documentation-index.md +12 -18
- package/docs/getting-started/documentation-index.md +1 -1
- package/docs/getting-started/examples/README.md +4 -4
- package/docs/getting-started/examples/full-featured-app.md +1 -1
- package/docs/getting-started/faq.md +2 -2
- package/docs/getting-started/quick-reference.md +4 -4
- package/docs/implementation-guides/authentication.md +15 -15
- package/docs/implementation-guides/component-styling.md +1 -1
- package/docs/implementation-guides/data-tables.md +126 -33
- package/docs/implementation-guides/datatable-rbac-usage.md +1 -1
- package/docs/implementation-guides/dynamic-colors.md +3 -3
- package/docs/implementation-guides/file-upload-storage.md +2 -2
- package/docs/implementation-guides/hierarchical-datatable.md +40 -60
- package/docs/implementation-guides/inactivity-tracking.md +3 -3
- package/docs/implementation-guides/large-datasets.md +3 -2
- package/docs/implementation-guides/organisation-security.md +2 -2
- package/docs/implementation-guides/performance.md +2 -2
- package/docs/implementation-guides/permission-enforcement.md +1 -1
- package/docs/migration/V0.3.44_organisation-context-timing-fix.md +1 -1
- package/docs/migration/V0.4.0_rbac-migration.md +6 -6
- package/docs/rbac/README.md +5 -5
- package/docs/rbac/advanced-patterns.md +6 -6
- package/docs/rbac/api-reference.md +20 -20
- package/docs/rbac/event-based-apps.md +3 -3
- package/docs/rbac/examples.md +41 -41
- package/docs/rbac/getting-started.md +37 -37
- package/docs/rbac/performance.md +1 -1
- package/docs/rbac/quick-start.md +52 -52
- package/docs/rbac/secure-client-protection.md +1 -1
- package/docs/rbac/troubleshooting.md +1 -1
- package/docs/security/README.md +5 -5
- package/docs/standards/0-standards-overview.md +220 -0
- package/docs/standards/{00-pace-core-compliance.md → 1-pace-core-compliance-standards.md} +204 -185
- package/docs/standards/{02-project-structure.md → 2-project-structure-standards.md} +11 -47
- package/docs/standards/3-architecture-standards.md +606 -0
- package/docs/standards/4-code-quality-standards.md +728 -0
- package/docs/standards/{08-markup-quality.md → 5-styling-standards.md} +12 -9
- package/docs/standards/{09-rbac-compliance.md → 6-security-rbac-standards.md} +126 -18
- package/docs/standards/7-api-tech-stack-standards.md +662 -0
- package/docs/standards/8-testing-documentation-standards.md +401 -0
- package/docs/standards/9-operations-standards.md +1102 -0
- package/docs/standards/README.md +203 -104
- package/docs/troubleshooting/README.md +4 -4
- package/docs/troubleshooting/common-issues.md +2 -2
- package/docs/troubleshooting/debugging.md +9 -9
- package/docs/troubleshooting/migration.md +4 -4
- package/eslint-config-pace-core.cjs +21 -10
- package/package.json +6 -5
- package/scripts/install-cursor-rules.cjs +11 -243
- package/scripts/install-eslint-config.cjs +284 -0
- package/src/__tests__/helpers/__tests__/component-test-utils.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-providers.test.tsx +2 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +10 -10
- package/src/__tests__/integration/UserProfile.test.tsx +14 -14
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +6 -6
- package/src/__tests__/templates/accessibility.test.template.tsx +9 -9
- package/src/__tests__/templates/component.test.template.tsx +18 -15
- package/src/components/Calendar/Calendar.tsx +201 -47
- package/src/components/ContextSelector/ContextSelector.tsx +137 -153
- package/src/components/DataTable/AUDIT_REPORT.md +293 -0
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +10 -2
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +10 -4
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +9 -9
- package/src/components/DataTable/components/ColumnFilter.tsx +63 -74
- package/src/components/DataTable/components/ColumnVisibilityDropdown.tsx +43 -41
- package/src/components/DataTable/components/DataTableErrorBoundary.tsx +9 -11
- package/src/components/DataTable/components/DataTableLayout.tsx +5 -16
- package/src/components/DataTable/components/EditableRow.tsx +5 -7
- package/src/components/DataTable/components/EmptyState.tsx +10 -9
- package/src/components/DataTable/components/FilterRow.tsx +2 -4
- package/src/components/DataTable/components/ImportModal.tsx +124 -126
- package/src/components/DataTable/components/LoadingState.tsx +5 -6
- package/src/components/DataTable/components/SortIndicator.tsx +50 -0
- package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +4 -4
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +23 -82
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +37 -9
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +7 -4
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +12 -4
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +41 -27
- package/src/components/DataTable/components/index.ts +2 -1
- package/src/components/DataTable/types.ts +0 -18
- package/src/components/DataTable/utils/a11yUtils.ts +17 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +2 -1
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +11 -15
- package/src/components/DateTimeField/DateTimeField.tsx +7 -8
- package/src/components/Dialog/Dialog.test.tsx +1 -0
- package/src/components/Dialog/Dialog.tsx +25 -8
- package/src/components/ErrorBoundary/ErrorBoundary.tsx +77 -79
- package/src/components/FileUpload/FileUpload.test.tsx +52 -14
- package/src/components/FileUpload/FileUpload.tsx +112 -130
- package/src/components/Progress/Progress.tsx +2 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +8 -8
- package/src/components/Select/Select.tsx +86 -77
- package/src/components/Select/types.ts +3 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +16 -16
- package/src/hooks/__tests__/hooks.integration.test.tsx +49 -49
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +97 -97
- package/src/hooks/public/usePublicEvent.ts +5 -5
- package/src/hooks/public/usePublicEventLogo.ts +5 -5
- package/src/hooks/public/usePublicFileDisplay.ts +2 -2
- package/src/hooks/public/usePublicRouteParams.ts +5 -5
- package/src/hooks/useAppConfig.ts +2 -2
- package/src/hooks/useEventTheme.test.ts +7 -7
- package/src/hooks/useEventTheme.ts +1 -4
- package/src/hooks/useFileDisplay.ts +2 -2
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +21 -21
- package/src/providers/__tests__/AuthProvider.test.tsx +21 -21
- package/src/providers/__tests__/EventProvider.test.tsx +61 -61
- package/src/providers/__tests__/InactivityProvider.test.tsx +56 -56
- package/src/providers/__tests__/OrganisationProvider.test.tsx +75 -75
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +37 -37
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +103 -103
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +7 -7
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +10 -10
- package/src/styles/core.css +7 -0
- package/src/theming/__tests__/parseEventColours.test.ts +9 -3
- package/src/theming/parseEventColours.ts +22 -10
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +42 -39
- package/src/utils/storage/README.md +1 -1
- package/cursor-rules/01-standards-compliance.mdc +0 -285
- package/cursor-rules/04-testing-standards.mdc +0 -270
- package/cursor-rules/05-bug-reports-and-features.mdc +0 -248
- package/cursor-rules/06-code-quality.mdc +0 -311
- package/cursor-rules/07-tech-stack-compliance.mdc +0 -216
- package/cursor-rules/10-error-handling-patterns.mdc +0 -179
- package/cursor-rules/11-performance-optimization.mdc +0 -169
- package/cursor-rules/12-ci-cd-integration.mdc +0 -150
- package/dist/DataTable-LRJL4IRV.js +0 -15
- package/dist/eslint-rules/rules/compliance.cjs +0 -348
- package/dist/eslint-rules/rules/components.cjs +0 -113
- package/dist/eslint-rules/rules/imports.cjs +0 -102
- package/docs/best-practices/README.md +0 -472
- package/docs/best-practices/accessibility.md +0 -604
- package/docs/best-practices/common-patterns.md +0 -516
- package/docs/best-practices/deployment.md +0 -1103
- package/docs/best-practices/performance.md +0 -1328
- package/docs/best-practices/security.md +0 -940
- package/docs/best-practices/testing.md +0 -1034
- package/docs/rbac/compliance/compliance-guide.md +0 -544
- package/docs/standards/01-standards-compliance.md +0 -188
- package/docs/standards/03-solid-principles.md +0 -39
- package/docs/standards/04-testing-standards.md +0 -36
- package/docs/standards/05-bug-reports-and-features.md +0 -27
- package/docs/standards/06-code-quality.md +0 -34
- package/docs/standards/07-tech-stack-compliance.md +0 -30
- package/docs/standards/10-error-handling-patterns.md +0 -401
- package/docs/standards/11-performance-optimization.md +0 -348
- package/docs/standards/12-ci-cd-integration.md +0 -370
- package/docs/standards/ALIGNMENT_REVIEW_SUMMARY.md +0 -192
- package/scripts/audit/audit-compliance.cjs +0 -1295
- package/scripts/audit/audit-components.cjs +0 -260
- package/scripts/audit/audit-rbac.cjs +0 -954
- package/scripts/audit/audit-standards.cjs +0 -1268
- package/scripts/audit/index.cjs +0 -1927
- package/src/components/DataTable/components/DataTableBody.tsx +0 -478
- package/src/components/DataTable/components/DraggableColumnHeader.tsx +0 -156
- package/src/components/DataTable/components/ExpandButton.tsx +0 -113
- package/src/components/DataTable/components/GroupHeader.tsx +0 -54
- package/src/components/DataTable/components/ViewRowModal.tsx +0 -68
- package/src/components/DataTable/components/VirtualizedDataTable.tsx +0 -525
- package/src/components/DataTable/components/__tests__/ExpandButton.test.tsx +0 -462
- package/src/components/DataTable/components/__tests__/GroupHeader.test.tsx +0 -393
- package/src/components/DataTable/components/__tests__/ViewRowModal.test.tsx +0 -476
- package/src/components/DataTable/components/__tests__/VirtualizedDataTable.test.tsx +0 -128
- package/src/components/DataTable/core/DataTableContext.tsx +0 -216
- package/src/components/DataTable/core/__tests__/DataTableContext.test.tsx +0 -136
- package/src/components/DataTable/hooks/__tests__/useColumnReordering.test.ts +0 -570
- package/src/components/DataTable/hooks/useColumnReordering.ts +0 -123
- package/src/components/DataTable/utils/debugTools.ts +0 -514
- package/src/eslint-rules/index.cjs +0 -22
- package/src/eslint-rules/rules/components.cjs +0 -113
- package/src/eslint-rules/rules/imports.cjs +0 -102
- package/src/eslint-rules/rules/rbac.cjs +0 -790
- package/src/eslint-rules/utils/helpers.cjs +0 -42
- package/src/eslint-rules/utils/manifest-loader.cjs +0 -75
|
@@ -92,7 +92,7 @@ import { useUnifiedAuth } from '@jmruthers/pace-core';
|
|
|
92
92
|
function MyComponent() {
|
|
93
93
|
const { user, loading, signIn, signOut } = useUnifiedAuth();
|
|
94
94
|
|
|
95
|
-
if (loading) return <
|
|
95
|
+
if (loading) return <p>Loading...</p>;
|
|
96
96
|
if (!user) return <button onClick={signIn}>Sign In</button>;
|
|
97
97
|
|
|
98
98
|
return (
|
|
@@ -184,7 +184,7 @@ function SuperAdminPanel() {
|
|
|
184
184
|
|
|
185
185
|
if (!isSuperAdmin) return null;
|
|
186
186
|
|
|
187
|
-
return <
|
|
187
|
+
return <section>Super admin panel</section>;
|
|
188
188
|
}
|
|
189
189
|
```
|
|
190
190
|
|
|
@@ -510,7 +510,7 @@ function MyComponent() {
|
|
|
510
510
|
const { user, loading, error } = useUnifiedAuth();
|
|
511
511
|
|
|
512
512
|
if (error) {
|
|
513
|
-
return <
|
|
513
|
+
return <p>Error: {error.message}</p>;
|
|
514
514
|
}
|
|
515
515
|
|
|
516
516
|
// ... rest of component
|
|
@@ -611,4 +611,4 @@ function AdminPanel() {
|
|
|
611
611
|
- **Common Issues**: [Troubleshooting Guide](./troubleshooting/common-issues.md)
|
|
612
612
|
- **Debugging**: [Debugging Guide](./troubleshooting/debugging.md)
|
|
613
613
|
- **Migration**: [Migration Guide](./migration/)
|
|
614
|
-
- **Security**: [Security
|
|
614
|
+
- **Security**: [Security & RBAC Standards](../standards/6-security-rbac-standards.md)
|
|
@@ -326,9 +326,9 @@ function UserDashboard() {
|
|
|
326
326
|
hasEventAccess, // Check event access
|
|
327
327
|
} = useUnifiedAuth();
|
|
328
328
|
|
|
329
|
-
if (loading) return <
|
|
330
|
-
if (error) return <
|
|
331
|
-
if (!user) return <
|
|
329
|
+
if (loading) return <p>Loading...</p>;
|
|
330
|
+
if (error) return <p>Error: {error.message}</p>;
|
|
331
|
+
if (!user) return <p>Please log in</p>;
|
|
332
332
|
|
|
333
333
|
return (
|
|
334
334
|
<div>
|
|
@@ -441,14 +441,14 @@ function EventContent() {
|
|
|
441
441
|
const { selectedEvent, hasEventAccess } = useUnifiedAuth();
|
|
442
442
|
|
|
443
443
|
if (!selectedEvent) {
|
|
444
|
-
return <
|
|
444
|
+
return <p>Please select an event</p>;
|
|
445
445
|
}
|
|
446
446
|
|
|
447
447
|
if (!hasEventAccess(selectedEvent.id)) {
|
|
448
|
-
return <
|
|
448
|
+
return <p>You don't have access to this event</p>;
|
|
449
449
|
}
|
|
450
450
|
|
|
451
|
-
return <
|
|
451
|
+
return <section>Event content for {selectedEvent.name}</section>;
|
|
452
452
|
}
|
|
453
453
|
```
|
|
454
454
|
|
|
@@ -703,14 +703,14 @@ function ConditionalContent() {
|
|
|
703
703
|
const { user, loading } = useUnifiedAuth();
|
|
704
704
|
|
|
705
705
|
if (loading) {
|
|
706
|
-
return <
|
|
706
|
+
return <p>Loading...</p>;
|
|
707
707
|
}
|
|
708
708
|
|
|
709
709
|
if (!user) {
|
|
710
|
-
return <
|
|
710
|
+
return <p>Please log in to continue</p>;
|
|
711
711
|
}
|
|
712
712
|
|
|
713
|
-
return <
|
|
713
|
+
return <p>Welcome, {user.email}!</p>;
|
|
714
714
|
}
|
|
715
715
|
```
|
|
716
716
|
|
|
@@ -850,11 +850,11 @@ function App() {
|
|
|
850
850
|
function AuthTest() {
|
|
851
851
|
const { user, loading, error } = useUnifiedAuth();
|
|
852
852
|
|
|
853
|
-
if (loading) return <
|
|
854
|
-
if (error) return <
|
|
855
|
-
if (!user) return <
|
|
856
|
-
|
|
857
|
-
return <
|
|
853
|
+
if (loading) return <p>Loading...</p>;
|
|
854
|
+
if (error) return <p>Error: {error.message}</p>;
|
|
855
|
+
if (!user) return <p>Not logged in</p>;
|
|
856
|
+
|
|
857
|
+
return <p>Welcome {user.email}</p>;
|
|
858
858
|
}
|
|
859
859
|
```
|
|
860
860
|
|
|
@@ -1105,7 +1105,7 @@ See the [Authentication Implementation Guide](./authentication.md) for a complet
|
|
|
1105
1105
|
|
|
1106
1106
|
### Advanced Patterns
|
|
1107
1107
|
|
|
1108
|
-
See the [
|
|
1108
|
+
See the [Authentication Implementation Guide](./authentication.md) for advanced authentication patterns and the [Standards Overview](../standards/0-standards-overview.md) for compliance requirements.
|
|
1109
1109
|
|
|
1110
1110
|
## Related Documentation
|
|
1111
1111
|
|
|
@@ -408,7 +408,7 @@ function DashboardCard({ title, children }) {
|
|
|
408
408
|
## Related Documentation
|
|
409
409
|
|
|
410
410
|
- [Styling Overview](../styles/README.md) - Complete styling system
|
|
411
|
-
- [Performance
|
|
411
|
+
- [Performance Optimization](../standards/9-operations-standards.md#performance-optimization) - Performance optimization
|
|
412
412
|
- [Component API Reference](../api-reference/components.md) - Component props
|
|
413
413
|
|
|
414
414
|
---
|
|
@@ -408,11 +408,11 @@ const columns: DataTableColumn<Dish>[] = [
|
|
|
408
408
|
const indentLevel = isParent ? 0 : 1;
|
|
409
409
|
|
|
410
410
|
return (
|
|
411
|
-
<
|
|
412
|
-
<
|
|
411
|
+
<section className={`flex items-center ${isParent ? 'font-semibold' : ''}`}>
|
|
412
|
+
<section style={{ marginLeft: `${indentLevel * 20}px` }}>
|
|
413
413
|
{isParent ? '🍽️' : '🥬'} {row.original.name}
|
|
414
|
-
</
|
|
415
|
-
</
|
|
414
|
+
</section>
|
|
415
|
+
</section>
|
|
416
416
|
);
|
|
417
417
|
}
|
|
418
418
|
},
|
|
@@ -478,26 +478,26 @@ const columns: DataTableColumn<Dish>[] = [
|
|
|
478
478
|
if (isParent) {
|
|
479
479
|
// Parent row actions
|
|
480
480
|
return (
|
|
481
|
-
<
|
|
481
|
+
<section className="flex gap-2">
|
|
482
482
|
<Button size="sm" variant="outline">
|
|
483
483
|
Edit Dish
|
|
484
484
|
</Button>
|
|
485
485
|
<Button size="sm" variant="outline">
|
|
486
486
|
Add Ingredient
|
|
487
487
|
</Button>
|
|
488
|
-
</
|
|
488
|
+
</section>
|
|
489
489
|
);
|
|
490
490
|
} else {
|
|
491
491
|
// Child row actions
|
|
492
492
|
return (
|
|
493
|
-
<
|
|
493
|
+
<section className="flex gap-2">
|
|
494
494
|
<Button size="sm" variant="ghost">
|
|
495
495
|
Edit Ingredient
|
|
496
496
|
</Button>
|
|
497
497
|
<Button size="sm" variant="ghost">
|
|
498
498
|
Remove
|
|
499
499
|
</Button>
|
|
500
|
-
</
|
|
500
|
+
</section>
|
|
501
501
|
);
|
|
502
502
|
}
|
|
503
503
|
}
|
|
@@ -1197,7 +1197,7 @@ import { DataTable } from '@jmruthers/pace-core';
|
|
|
1197
1197
|
|
|
1198
1198
|
**✅ Column Alignment in Virtualized Tables**
|
|
1199
1199
|
- **Problem**: Header and body columns were misaligned in virtualized mode due to separate table layouts.
|
|
1200
|
-
- **Solution**:
|
|
1200
|
+
- **Solution**: `UnifiedTableBody` component handles virtualization automatically with synchronized column sizing between header and body tables, `table-fixed` layout for consistent column widths, dynamic column width calculation and synchronization, proper virtualization handling for large datasets.
|
|
1201
1201
|
|
|
1202
1202
|
**✅ Pagination State Synchronization**
|
|
1203
1203
|
- **Problem**: Page size dropdown showed 50 but displayed 20 rows due to hardcoded values and virtualization conflicts.
|
|
@@ -2167,7 +2167,7 @@ function UserForm({ user, onSubmit, onCancel }) {
|
|
|
2167
2167
|
|
|
2168
2168
|
return (
|
|
2169
2169
|
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
|
|
2170
|
-
<
|
|
2170
|
+
<section>
|
|
2171
2171
|
<label htmlFor="name">Name</label>
|
|
2172
2172
|
<input
|
|
2173
2173
|
id="name"
|
|
@@ -2177,9 +2177,9 @@ function UserForm({ user, onSubmit, onCancel }) {
|
|
|
2177
2177
|
{errors.name && (
|
|
2178
2178
|
<p className="text-acc-600 text-sm">{errors.name.message}</p>
|
|
2179
2179
|
)}
|
|
2180
|
-
</
|
|
2180
|
+
</section>
|
|
2181
2181
|
|
|
2182
|
-
<
|
|
2182
|
+
<section>
|
|
2183
2183
|
<label htmlFor="email">Email</label>
|
|
2184
2184
|
<input
|
|
2185
2185
|
id="email"
|
|
@@ -2190,9 +2190,9 @@ function UserForm({ user, onSubmit, onCancel }) {
|
|
|
2190
2190
|
{errors.email && (
|
|
2191
2191
|
<p className="text-acc-600 text-sm">{errors.email.message}</p>
|
|
2192
2192
|
)}
|
|
2193
|
-
</
|
|
2193
|
+
</section>
|
|
2194
2194
|
|
|
2195
|
-
<
|
|
2195
|
+
<section>
|
|
2196
2196
|
<label htmlFor="role">Role</label>
|
|
2197
2197
|
<select
|
|
2198
2198
|
id="role"
|
|
@@ -2206,9 +2206,9 @@ function UserForm({ user, onSubmit, onCancel }) {
|
|
|
2206
2206
|
{errors.role && (
|
|
2207
2207
|
<p className="text-acc-600 text-sm">{errors.role.message}</p>
|
|
2208
2208
|
)}
|
|
2209
|
-
</
|
|
2209
|
+
</section>
|
|
2210
2210
|
|
|
2211
|
-
<
|
|
2211
|
+
<section className="flex gap-2">
|
|
2212
2212
|
<button
|
|
2213
2213
|
type="submit"
|
|
2214
2214
|
disabled={isSubmitting}
|
|
@@ -2223,7 +2223,7 @@ function UserForm({ user, onSubmit, onCancel }) {
|
|
|
2223
2223
|
>
|
|
2224
2224
|
Cancel
|
|
2225
2225
|
</button>
|
|
2226
|
-
</
|
|
2226
|
+
</section>
|
|
2227
2227
|
</form>
|
|
2228
2228
|
);
|
|
2229
2229
|
}
|
|
@@ -2496,25 +2496,118 @@ If you're upgrading from a previous version:
|
|
|
2496
2496
|
|
|
2497
2497
|
### Component Structure
|
|
2498
2498
|
|
|
2499
|
+
The DataTable component is built with a modular architecture that separates concerns and provides clear component boundaries. The structure is organized into main components, sub-components, hooks, utilities, and core architecture classes.
|
|
2500
|
+
|
|
2499
2501
|
```
|
|
2500
|
-
DataTable
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
│ ├──
|
|
2504
|
-
│ ├──
|
|
2505
|
-
│
|
|
2506
|
-
|
|
2507
|
-
│
|
|
2508
|
-
│
|
|
2509
|
-
├──
|
|
2510
|
-
│ ├──
|
|
2511
|
-
│ └──
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2502
|
+
DataTable (Main Entry Point)
|
|
2503
|
+
│
|
|
2504
|
+
├── DataTableCore (Internal Orchestrator)
|
|
2505
|
+
│ ├── DataTableErrorBoundary
|
|
2506
|
+
│ ├── LoadingState
|
|
2507
|
+
│ ├── AccessDeniedPage
|
|
2508
|
+
│ └── DataTableLayout
|
|
2509
|
+
│ │
|
|
2510
|
+
│ ├── DataTableToolbar
|
|
2511
|
+
│ │ ├── GroupingDropdown
|
|
2512
|
+
│ │ ├── ColumnVisibilityDropdown
|
|
2513
|
+
│ │ └── BulkOperationsDropdown
|
|
2514
|
+
│ │
|
|
2515
|
+
│ ├── UnifiedTableBody
|
|
2516
|
+
│ │ ├── FilterRow
|
|
2517
|
+
│ │ │ └── ColumnFilter
|
|
2518
|
+
│ │ ├── MemoizedRow (RowComponent)
|
|
2519
|
+
│ │ │ ├── EditableRow
|
|
2520
|
+
│ │ │ │ └── EditFields
|
|
2521
|
+
│ │ │ ├── ActionButtons
|
|
2522
|
+
│ │ │ └── RowComponent (handles grouped rows inline and hierarchical expand/collapse)
|
|
2523
|
+
│ │ └── EmptyState
|
|
2524
|
+
│ │
|
|
2525
|
+
│ ├── PaginationControls
|
|
2526
|
+
│ │ └── EnhancedPaginationControls (when enabled)
|
|
2527
|
+
│ │
|
|
2528
|
+
│ └── DataTableModals
|
|
2529
|
+
│ └── ImportModal
|
|
2530
|
+
│
|
|
2531
|
+
├── Hooks (State & Logic Management)
|
|
2532
|
+
│ ├── useDataTableState
|
|
2533
|
+
│ ├── useDataTableDataPipeline
|
|
2534
|
+
│ ├── useDataTableConfiguration
|
|
2535
|
+
│ ├── useDataTablePermissions
|
|
2536
|
+
│ ├── useTableColumns
|
|
2537
|
+
│ ├── useTableHandlers
|
|
2538
|
+
│ ├── useColumnOrderPersistence
|
|
2539
|
+
│ ├── useColumnVisibilityPersistence
|
|
2540
|
+
│ ├── useEffectiveColumnOrder
|
|
2541
|
+
│ ├── useHierarchicalState
|
|
2542
|
+
│ ├── useServerSideDataEffect
|
|
2543
|
+
│ ├── useKeyboardNavigation
|
|
2544
|
+
│ └── useDataTablePerformance (from core hooks)
|
|
2545
|
+
│ ├── DataChunkManager
|
|
2546
|
+
│ ├── SearchIndex
|
|
2547
|
+
│ ├── PerformanceMonitor
|
|
2548
|
+
│ └── VisibilityTracker
|
|
2549
|
+
│
|
|
2550
|
+
├── Core Architecture Classes
|
|
2551
|
+
│ ├── ColumnFactory
|
|
2552
|
+
│ ├── ColumnManager
|
|
2553
|
+
│ ├── DataManager
|
|
2554
|
+
│ ├── StateManager
|
|
2555
|
+
│ ├── ActionManager
|
|
2556
|
+
│ ├── LocalDataAdapter
|
|
2557
|
+
│ └── PluginRegistry
|
|
2558
|
+
│
|
|
2559
|
+
└── Utilities
|
|
2560
|
+
├── aggregationUtils (sum, average, count, min, max)
|
|
2561
|
+
├── columnUtils
|
|
2562
|
+
├── exportUtils
|
|
2563
|
+
├── hierarchicalUtils
|
|
2564
|
+
├── hierarchicalSorting
|
|
2565
|
+
├── paginationUtils
|
|
2566
|
+
├── performanceUtils
|
|
2567
|
+
├── rowUtils
|
|
2568
|
+
├── a11yUtils
|
|
2569
|
+
├── errorHandling
|
|
2570
|
+
└── flexibleImport
|
|
2516
2571
|
```
|
|
2517
2572
|
|
|
2573
|
+
#### Component Descriptions
|
|
2574
|
+
|
|
2575
|
+
**Main Components:**
|
|
2576
|
+
- **`DataTable`**: Public API component that wraps `DataTableCore` with feature normalization
|
|
2577
|
+
- **`DataTableCore`**: Internal orchestrator that manages all hooks, state, and sub-components
|
|
2578
|
+
- **`DataTableLayout`**: Main layout component that arranges toolbar, body, pagination, and modals
|
|
2579
|
+
|
|
2580
|
+
**Toolbar Components:**
|
|
2581
|
+
- **`DataTableToolbar`**: Top toolbar with search, grouping, column visibility, and action buttons
|
|
2582
|
+
- **`GroupingDropdown`**: Dropdown for selecting columns to group by
|
|
2583
|
+
- **`ColumnVisibilityDropdown`**: Dropdown for showing/hiding columns
|
|
2584
|
+
- **`BulkOperationsDropdown`**: Menu for bulk operations (delete selected, etc.)
|
|
2585
|
+
|
|
2586
|
+
**Table Body Components:**
|
|
2587
|
+
- **`UnifiedTableBody`**: Unified component that handles both standard and virtualized rendering
|
|
2588
|
+
- **`FilterRow`**: Row of filter inputs below column headers
|
|
2589
|
+
- **`ColumnFilter`**: Individual column filter component
|
|
2590
|
+
- **`MemoizedRow`** (RowComponent): Individual table row with memoization
|
|
2591
|
+
- **`EditableRow`**: Inline editable row with form fields
|
|
2592
|
+
- **`EditFields`**: Field renderers for editable columns (text, select, date, number, boolean)
|
|
2593
|
+
- **`ActionButtons`**: Row action buttons (edit, delete, custom actions)
|
|
2594
|
+
- **Hierarchical expand/collapse**: Handled inline by `RowComponent` for hierarchical rows
|
|
2595
|
+
- **Grouped rows**: Handled inline by `RowComponent` when `row.getIsGrouped()` returns true
|
|
2596
|
+
- **`EmptyState`**: Component displayed when table has no data
|
|
2597
|
+
|
|
2598
|
+
**Pagination Components:**
|
|
2599
|
+
- **`PaginationControls`**: Standard pagination controls
|
|
2600
|
+
- **`EnhancedPaginationControls`**: Enhanced version with performance metrics and jump-to-page
|
|
2601
|
+
|
|
2602
|
+
**Modal Components:**
|
|
2603
|
+
- **`DataTableModals`**: Container for all modal dialogs
|
|
2604
|
+
- **`ImportModal`**: CSV import modal with column mapping
|
|
2605
|
+
|
|
2606
|
+
**Supporting Components:**
|
|
2607
|
+
- **`DataTableErrorBoundary`**: Error boundary for graceful error handling
|
|
2608
|
+
- **`LoadingState`**: Loading indicator component
|
|
2609
|
+
- **`AccessDeniedPage`**: Component shown when user lacks permissions
|
|
2610
|
+
|
|
2518
2611
|
### Performance Utilities
|
|
2519
2612
|
|
|
2520
2613
|
- **`determinePaginationMode`**: Automatically selects optimal pagination strategy
|
|
@@ -93,7 +93,7 @@ function MyApp() {
|
|
|
93
93
|
// Automatically applies event colors when an event is selected
|
|
94
94
|
useEventTheme();
|
|
95
95
|
|
|
96
|
-
return <
|
|
96
|
+
return <main>Your app content</main>;
|
|
97
97
|
}
|
|
98
98
|
```
|
|
99
99
|
|
|
@@ -268,7 +268,7 @@ import { useEventTheme } from '@jmruthers/pace-core';
|
|
|
268
268
|
function MyApp() {
|
|
269
269
|
useEventTheme(); // Automatically applies event colors
|
|
270
270
|
|
|
271
|
-
return <
|
|
271
|
+
return <main>Your app content</main>;
|
|
272
272
|
}
|
|
273
273
|
```
|
|
274
274
|
|
|
@@ -319,7 +319,7 @@ function App() {
|
|
|
319
319
|
function App() {
|
|
320
320
|
useEventTheme(); // Replaces the above useEffect
|
|
321
321
|
|
|
322
|
-
return <
|
|
322
|
+
return <main>Your app</main>;
|
|
323
323
|
}
|
|
324
324
|
```
|
|
325
325
|
|
|
@@ -388,7 +388,7 @@ function FileManager() {
|
|
|
388
388
|
<div>
|
|
389
389
|
{/* Upload UI */}
|
|
390
390
|
{isLoading && <div>Uploading...</div>}
|
|
391
|
-
{error && <
|
|
391
|
+
{error && <p>Error: {error.message}</p>}
|
|
392
392
|
</div>
|
|
393
393
|
);
|
|
394
394
|
}
|
|
@@ -941,6 +941,6 @@ When network is interrupted during upload:
|
|
|
941
941
|
## Next Steps
|
|
942
942
|
|
|
943
943
|
- **[Storage Utilities](../api-reference/utilities.md#storage)** - Additional storage utilities
|
|
944
|
-
- **[Security
|
|
944
|
+
- **[Security & RBAC Standards](../standards/6-security-rbac-standards.md)** - Security guidelines
|
|
945
945
|
- **[RBAC Integration](./permission-enforcement.md)** - Permission-based file access
|
|
946
946
|
- **[Performance Optimization](./performance.md)** - Large file handling
|
|
@@ -112,20 +112,20 @@ const columns: DataTableColumn<Dish>[] = [
|
|
|
112
112
|
header: 'Name',
|
|
113
113
|
// Different rendering for parent vs child rows
|
|
114
114
|
renderForParent: (row) => (
|
|
115
|
-
<
|
|
115
|
+
<section className="flex items-center gap-2">
|
|
116
116
|
<span className="font-semibold text-main-800">{row.name}</span>
|
|
117
117
|
<span className="text-xs bg-main-100 text-main-700 px-2 py-1 rounded">
|
|
118
118
|
{row.type}
|
|
119
119
|
</span>
|
|
120
|
-
</
|
|
120
|
+
</section>
|
|
121
121
|
),
|
|
122
122
|
renderForChild: (row) => (
|
|
123
|
-
<
|
|
123
|
+
<section className="flex items-center gap-2 ml-4">
|
|
124
124
|
<span className="text-sec-700">{row.name}</span>
|
|
125
125
|
<span className="text-xs bg-sec-100 text-sec-600 px-2 py-1 rounded">
|
|
126
126
|
{row.type}
|
|
127
127
|
</span>
|
|
128
|
-
</
|
|
128
|
+
</section>
|
|
129
129
|
),
|
|
130
130
|
},
|
|
131
131
|
{
|
|
@@ -133,14 +133,14 @@ const columns: DataTableColumn<Dish>[] = [
|
|
|
133
133
|
accessorKey: 'cost',
|
|
134
134
|
header: 'Cost',
|
|
135
135
|
renderForParent: (row) => (
|
|
136
|
-
<
|
|
136
|
+
<p className="text-right font-semibold text-main-800">
|
|
137
137
|
${row.cost?.toFixed(2)}
|
|
138
|
-
</
|
|
138
|
+
</p>
|
|
139
139
|
),
|
|
140
140
|
renderForChild: (row) => (
|
|
141
|
-
<
|
|
141
|
+
<p className="text-right text-sec-600 ml-4">
|
|
142
142
|
${row.cost?.toFixed(2)}
|
|
143
|
-
</
|
|
143
|
+
</p>
|
|
144
144
|
),
|
|
145
145
|
},
|
|
146
146
|
{
|
|
@@ -150,10 +150,10 @@ const columns: DataTableColumn<Dish>[] = [
|
|
|
150
150
|
// Only show for child rows
|
|
151
151
|
renderForParent: () => null,
|
|
152
152
|
renderForChild: (row) => (
|
|
153
|
-
<
|
|
153
|
+
<p className="text-sm ml-4">
|
|
154
154
|
<span className="font-medium">{row.quantity}</span>
|
|
155
155
|
{row.unit && <span className="text-sec-500 ml-1">{row.unit}</span>}
|
|
156
|
-
</
|
|
156
|
+
</p>
|
|
157
157
|
),
|
|
158
158
|
hideForParent: true, // Hide this column for parent rows
|
|
159
159
|
}
|
|
@@ -193,7 +193,7 @@ hierarchical={{
|
|
|
193
193
|
onExpandedChange: (expandedIds) => {
|
|
194
194
|
console.log('Expanded rows:', expandedIds);
|
|
195
195
|
},
|
|
196
|
-
|
|
196
|
+
// Note: Custom expand button functionality has been removed. Expand/collapse is handled inline by RowComponent.
|
|
197
197
|
indentSize: 24, // Indentation for child rows in pixels
|
|
198
198
|
parentRowClassName: 'bg-main-50 font-medium', // CSS classes for parent rows
|
|
199
199
|
childRowClassName: 'bg-sec-25', // CSS classes for child rows
|
|
@@ -207,7 +207,7 @@ hierarchical={{
|
|
|
207
207
|
| `enabled` | `boolean` | `false` | Enable/disable hierarchical functionality |
|
|
208
208
|
| `defaultExpanded` | `boolean \| string[]` | `false` | Initial expansion state |
|
|
209
209
|
| `onExpandedChange` | `(expandedIds: string[]) => void` | `undefined` | Callback when expansion changes |
|
|
210
|
-
| `expandButton` |
|
|
210
|
+
| `expandButton` | ~~`React.ComponentType`~~ | ~~`ExpandButton`~~ | ~~Custom expand/collapse button~~ **DEPRECATED - Removed** |
|
|
211
211
|
| `indentSize` | `number` | `24` | Indentation for child rows in pixels |
|
|
212
212
|
| `parentRowClassName` | `string` | `''` | CSS classes for parent rows |
|
|
213
213
|
| `childRowClassName` | `string` | `''` | CSS classes for child rows |
|
|
@@ -240,16 +240,16 @@ const column: DataTableColumn<YourType> = {
|
|
|
240
240
|
id: 'actions',
|
|
241
241
|
header: 'Actions',
|
|
242
242
|
renderForParent: (row) => (
|
|
243
|
-
<
|
|
243
|
+
<section className="flex gap-2">
|
|
244
244
|
<Button size="sm">Edit Recipe</Button>
|
|
245
245
|
<Button size="sm" variant="outline">Add Ingredient</Button>
|
|
246
|
-
</
|
|
246
|
+
</section>
|
|
247
247
|
),
|
|
248
248
|
renderForChild: (row) => (
|
|
249
|
-
<
|
|
249
|
+
<section className="flex gap-2">
|
|
250
250
|
<Button size="sm" variant="ghost">Edit</Button>
|
|
251
251
|
<Button size="sm" variant="destructive">Remove</Button>
|
|
252
|
-
</
|
|
252
|
+
</section>
|
|
253
253
|
),
|
|
254
254
|
}
|
|
255
255
|
```
|
|
@@ -277,29 +277,9 @@ The DataTable automatically adds an expand/collapse all button in the header whe
|
|
|
277
277
|
You can provide a custom expand button component:
|
|
278
278
|
|
|
279
279
|
```tsx
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
<button
|
|
284
|
-
onClick={onClick}
|
|
285
|
-
className="p-1 hover:bg-sec-100 rounded"
|
|
286
|
-
{...props}
|
|
287
|
-
>
|
|
288
|
-
{isExpanded ? (
|
|
289
|
-
<ChevronDown className="h-4 w-4" />
|
|
290
|
-
) : (
|
|
291
|
-
<ChevronRight className="h-4 w-4" />
|
|
292
|
-
)}
|
|
293
|
-
</button>
|
|
294
|
-
);
|
|
295
|
-
|
|
296
|
-
// Use in DataTable
|
|
297
|
-
<DataTable
|
|
298
|
-
hierarchical={{
|
|
299
|
-
enabled: true,
|
|
300
|
-
expandButton: CustomExpandButton,
|
|
301
|
-
}}
|
|
302
|
-
/>
|
|
280
|
+
// Note: Custom expand button functionality has been removed.
|
|
281
|
+
// Expand/collapse buttons are now handled inline by RowComponent.
|
|
282
|
+
// The expandButton prop is no longer available in HierarchicalConfig.
|
|
303
283
|
```
|
|
304
284
|
|
|
305
285
|
## Hierarchical Actions
|
|
@@ -510,20 +490,20 @@ function HierarchicalDishTable() {
|
|
|
510
490
|
enableSorting: true,
|
|
511
491
|
size: 200,
|
|
512
492
|
renderForParent: (row) => (
|
|
513
|
-
<
|
|
493
|
+
<section className="flex items-center gap-2">
|
|
514
494
|
<span className="font-semibold text-main-800">{row.name}</span>
|
|
515
495
|
<span className="text-xs bg-main-100 text-main-700 px-2 py-1 rounded">
|
|
516
496
|
{row.type}
|
|
517
497
|
</span>
|
|
518
|
-
</
|
|
498
|
+
</section>
|
|
519
499
|
),
|
|
520
500
|
renderForChild: (row) => (
|
|
521
|
-
<
|
|
501
|
+
<section className="flex items-center gap-2 ml-4">
|
|
522
502
|
<span className="text-sec-700">{row.name}</span>
|
|
523
503
|
<span className="text-xs bg-sec-100 text-sec-600 px-2 py-1 rounded">
|
|
524
504
|
{row.type}
|
|
525
505
|
</span>
|
|
526
|
-
</
|
|
506
|
+
</section>
|
|
527
507
|
),
|
|
528
508
|
},
|
|
529
509
|
{
|
|
@@ -533,14 +513,14 @@ function HierarchicalDishTable() {
|
|
|
533
513
|
enableSorting: true,
|
|
534
514
|
size: 250,
|
|
535
515
|
renderForParent: (row) => (
|
|
536
|
-
<
|
|
516
|
+
<p className="text-sm text-sec-600">
|
|
537
517
|
{row.description}
|
|
538
|
-
</
|
|
518
|
+
</p>
|
|
539
519
|
),
|
|
540
520
|
renderForChild: (row) => (
|
|
541
|
-
<
|
|
521
|
+
<p className="text-sm text-sec-500 ml-4">
|
|
542
522
|
{row.description}
|
|
543
|
-
</
|
|
523
|
+
</p>
|
|
544
524
|
),
|
|
545
525
|
},
|
|
546
526
|
{
|
|
@@ -551,10 +531,10 @@ function HierarchicalDishTable() {
|
|
|
551
531
|
size: 120,
|
|
552
532
|
renderForParent: () => null,
|
|
553
533
|
renderForChild: (row) => (
|
|
554
|
-
<
|
|
534
|
+
<p className="text-sm ml-4">
|
|
555
535
|
<span className="font-medium">{row.quantity}</span>
|
|
556
536
|
{row.unit && <span className="text-sec-500 ml-1">{row.unit}</span>}
|
|
557
|
-
</
|
|
537
|
+
</p>
|
|
558
538
|
),
|
|
559
539
|
hideForParent: true,
|
|
560
540
|
},
|
|
@@ -565,14 +545,14 @@ function HierarchicalDishTable() {
|
|
|
565
545
|
enableSorting: true,
|
|
566
546
|
size: 100,
|
|
567
547
|
renderForParent: (row) => (
|
|
568
|
-
<
|
|
548
|
+
<p className="text-right font-semibold text-main-800">
|
|
569
549
|
${row.cost?.toFixed(2)}
|
|
570
|
-
</
|
|
550
|
+
</p>
|
|
571
551
|
),
|
|
572
552
|
renderForChild: (row) => (
|
|
573
|
-
<
|
|
553
|
+
<p className="text-right text-sec-600 ml-4">
|
|
574
554
|
${row.cost?.toFixed(2)}
|
|
575
|
-
</
|
|
555
|
+
</p>
|
|
576
556
|
),
|
|
577
557
|
},
|
|
578
558
|
{
|
|
@@ -583,9 +563,9 @@ function HierarchicalDishTable() {
|
|
|
583
563
|
size: 150,
|
|
584
564
|
renderForParent: () => null,
|
|
585
565
|
renderForChild: (row) => (
|
|
586
|
-
<
|
|
566
|
+
<p className="text-sm text-sec-600 ml-4">
|
|
587
567
|
{row.supplier}
|
|
588
|
-
</
|
|
568
|
+
</p>
|
|
589
569
|
),
|
|
590
570
|
hideForParent: true,
|
|
591
571
|
},
|
|
@@ -596,11 +576,11 @@ function HierarchicalDishTable() {
|
|
|
596
576
|
enableSorting: true,
|
|
597
577
|
size: 100,
|
|
598
578
|
renderForParent: (row) => (
|
|
599
|
-
<
|
|
579
|
+
<section className="text-center">
|
|
600
580
|
<span className="inline-flex items-center px-2 py-1 rounded text-xs font-medium bg-sec-100 text-sec-800">
|
|
601
581
|
{row.prepTime} min
|
|
602
582
|
</span>
|
|
603
|
-
</
|
|
583
|
+
</section>
|
|
604
584
|
),
|
|
605
585
|
renderForChild: () => null,
|
|
606
586
|
hideForChild: true,
|
|
@@ -618,11 +598,11 @@ function HierarchicalDishTable() {
|
|
|
618
598
|
Hard: 'bg-acc-100 text-acc-800'
|
|
619
599
|
};
|
|
620
600
|
return (
|
|
621
|
-
<
|
|
601
|
+
<section className="text-center">
|
|
622
602
|
<span className={`inline-flex items-center px-2 py-1 rounded text-xs font-medium ${colors[row.difficulty as keyof typeof colors] || 'bg-sec-100 text-sec-800'}`}>
|
|
623
603
|
{row.difficulty}
|
|
624
604
|
</span>
|
|
625
|
-
</
|
|
605
|
+
</section>
|
|
626
606
|
);
|
|
627
607
|
},
|
|
628
608
|
renderForChild: () => null,
|
|
@@ -812,7 +792,7 @@ interface HierarchicalConfig {
|
|
|
812
792
|
enabled: boolean;
|
|
813
793
|
defaultExpanded?: boolean | string[];
|
|
814
794
|
onExpandedChange?: (expandedIds: string[]) => void;
|
|
815
|
-
expandButton
|
|
795
|
+
// expandButton prop has been removed - expand/collapse is handled inline by RowComponent
|
|
816
796
|
indentSize?: number;
|
|
817
797
|
parentRowClassName?: string;
|
|
818
798
|
childRowClassName?: string;
|