@jmruthers/pace-core 0.6.7 → 0.6.8

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 (100) hide show
  1. package/audit-tool/00-dependencies.cjs +215 -9
  2. package/audit-tool/audits/02-project-structure.cjs +3 -18
  3. package/audit-tool/audits/03-architecture.cjs +34 -6
  4. package/audit-tool/audits/06-security-rbac.cjs +10 -0
  5. package/audit-tool/audits/07-api-tech-stack.cjs +55 -1
  6. package/audit-tool/index.cjs +23 -19
  7. package/audit-tool/utils/report-utils.cjs +141 -2
  8. package/dist/{DataTable-7PMH7XN7.js → DataTable-6RMSCQJ6.js} +5 -5
  9. package/dist/{PublicPageProvider-DlsCaR5v.d.ts → PublicPageProvider-CIGSujI2.d.ts} +14 -8
  10. package/dist/{UnifiedAuthProvider-ZT6TIGM7.js → UnifiedAuthProvider-7SNDOWYD.js} +2 -2
  11. package/dist/{api-Y4MQWOFW.js → api-7P7DI652.js} +1 -1
  12. package/dist/{chunk-L4XMVJKY.js → chunk-4DDCYDQ3.js} +8 -7
  13. package/dist/{chunk-ZKAWKYT4.js → chunk-5W2A3DRC.js} +2 -1
  14. package/dist/{chunk-VBCS3DUA.js → chunk-EF2UGZWY.js} +3 -3
  15. package/dist/{chunk-JGWDVX64.js → chunk-EURB7QFZ.js} +123 -53
  16. package/dist/{chunk-BM4CQ5P3.js → chunk-GS5672WG.js} +6 -6
  17. package/dist/{chunk-ZFYPMX46.js → chunk-LX6U42O3.js} +1 -1
  18. package/dist/{chunk-5X4QLXRG.js → chunk-MPBLMWVR.js} +5 -3
  19. package/dist/{chunk-Q7Q7V5NV.js → chunk-NKHKXPI4.js} +7 -7
  20. package/dist/{chunk-6F3IILHI.js → chunk-S6ZQKDY6.js} +1 -1
  21. package/dist/{chunk-FTCRZOG2.js → chunk-T5CVK4R3.js} +5 -5
  22. package/dist/{chunk-GHYHJTYV.js → chunk-Z2FNRKF3.js} +13 -13
  23. package/dist/components.d.ts +1 -1
  24. package/dist/components.js +12 -12
  25. package/dist/eslint-rules/rules/04-code-quality.cjs +66 -10
  26. package/dist/eslint-rules/rules/06-security-rbac.cjs +8 -3
  27. package/dist/eslint-rules/rules/07-api-tech-stack.cjs +190 -68
  28. package/dist/{functions-DHebl8-F.d.ts → functions-lBy5L2ry.d.ts} +1 -1
  29. package/dist/hooks.js +7 -7
  30. package/dist/index.d.ts +2 -2
  31. package/dist/index.js +15 -15
  32. package/dist/providers.js +2 -2
  33. package/dist/rbac/index.d.ts +1 -1
  34. package/dist/rbac/index.js +6 -6
  35. package/dist/theming/runtime.d.ts +48 -1
  36. package/dist/theming/runtime.js +1 -1
  37. package/dist/types.d.ts +2 -2
  38. package/dist/utils.js +1 -1
  39. package/docs/api/modules.md +63 -14
  40. package/docs/getting-started/dependencies.md +23 -0
  41. package/docs/implementation-guides/app-layout.md +1 -1
  42. package/docs/implementation-guides/data-tables.md +1 -1
  43. package/docs/standards/1-pace-core-compliance-standards.md +38 -1
  44. package/eslint-config-pace-core.cjs +30 -11
  45. package/package.json +45 -15
  46. package/scripts/eslint-audit.cjs +123 -0
  47. package/scripts/install-eslint-config.cjs +67 -2
  48. package/scripts/validate-dependencies.cjs +248 -0
  49. package/src/__tests__/helpers/__tests__/test-utils.test.tsx +20 -8
  50. package/src/__tests__/templates/accessibility.test.template.tsx +1 -0
  51. package/src/components/AddressField/AddressField.tsx +26 -1
  52. package/src/components/Alert/Alert.test.tsx +86 -22
  53. package/src/components/Alert/Alert.tsx +19 -11
  54. package/src/components/Badge/Badge.tsx +1 -1
  55. package/src/components/Checkbox/Checkbox.test.tsx +2 -1
  56. package/src/components/ContextSelector/ContextSelector.tsx +39 -41
  57. package/src/components/DataTable/DataTable.tsx +1 -19
  58. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +6 -10
  59. package/src/components/DataTable/__tests__/a11y.basic.test.tsx +18 -9
  60. package/src/components/DataTable/__tests__/pagination.modes.test.tsx +3 -2
  61. package/src/components/DataTable/components/EmptyState.tsx +1 -1
  62. package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +1 -1
  63. package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +3 -3
  64. package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +33 -29
  65. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +1 -2
  66. package/src/components/FileUpload/FileUpload.test.tsx +22 -31
  67. package/src/components/FileUpload/FileUpload.tsx +29 -0
  68. package/src/components/NavigationMenu/NavigationMenu.test.tsx +48 -12
  69. package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +9 -9
  70. package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +30 -30
  71. package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +4 -4
  72. package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +7 -1
  73. package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +8 -5
  74. package/src/hooks/__tests__/useFileUrl.unit.test.ts +4 -0
  75. package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +3 -3
  76. package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +45 -8
  77. package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +22 -2
  78. package/src/hooks/public/usePublicRouteParams.ts +8 -4
  79. package/src/hooks/useAddressAutocomplete.test.ts +18 -18
  80. package/src/hooks/useEventTheme.ts +5 -1
  81. package/src/hooks/useFileUrl.ts +52 -8
  82. package/src/hooks/useOrganisationSecurity.test.ts +2 -1
  83. package/src/providers/__tests__/ProviderLifecycle.test.tsx +1 -1
  84. package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +15 -6
  85. package/src/rbac/__tests__/rbac-functions.test.ts +3 -3
  86. package/src/rbac/api.test.ts +104 -0
  87. package/src/rbac/engine.ts +1 -1
  88. package/src/rbac/hooks/useCan.test.ts +2 -2
  89. package/src/rbac/secureClient.ts +1 -1
  90. package/src/rbac/types/functions.ts +1 -1
  91. package/src/theming/__tests__/parseEventColours.test.ts +117 -8
  92. package/src/theming/parseEventColours.ts +56 -2
  93. package/src/types/supabase.ts +2 -3
  94. package/src/utils/__tests__/bundleAnalysis.unit.test.ts +9 -9
  95. package/src/utils/file-reference/__tests__/file-reference.test.ts +4 -0
  96. package/src/utils/formatting/formatDate.test.ts +3 -2
  97. package/src/utils/formatting/formatDateTime.test.ts +2 -2
  98. package/src/utils/google-places/googlePlacesUtils.test.ts +36 -24
  99. package/src/utils/storage/__tests__/helpers.unit.test.ts +19 -12
  100. package/src/utils/storage/helpers.test.ts +69 -3
@@ -13,12 +13,21 @@
13
13
  * Supports input formats:
14
14
  * - Object with 'main', 'sec', 'acc' keys (standard format)
15
15
  * - Object with 'ev-main', 'ev-sec', 'ev-acc' keys (database format with prefix)
16
+ * - Shade names with 'ev-' prefix (e.g., 'ev-acc-500' -> 'acc-500', 'ev-main-raw' -> 'main-raw')
16
17
  * - JSON string that will be parsed
17
18
  *
18
19
  * Only includes explicitly defined color values. Does not fill
19
20
  * missing shades - only shades that are present in the input will
20
21
  * be included in the output.
21
22
  *
23
+ * The parser automatically strips 'ev-' prefixes from BOTH palette keys and shade names
24
+ * for future-proofing, allowing distinction between event colors and organization colors
25
+ * (org colors not yet implemented).
26
+ *
27
+ * Normalization rules:
28
+ * - Palette keys: 'ev-main' -> 'main', 'ev-sec' -> 'sec', 'ev-acc' -> 'acc'
29
+ * - Shade names: 'ev-main-raw' -> 'main-raw', 'ev-sec-200' -> 'sec-200', 'ev-acc-800' -> 'acc-800'
30
+ *
22
31
  * @param input - Event colours from database (JSONB field)
23
32
  * @returns Normalized palette data with main, sec, acc palettes, or null if invalid
24
33
  *
@@ -36,7 +45,7 @@
36
45
  *
37
46
  * @example
38
47
  * ```ts
39
- * // Database format with ev- prefix
48
+ * // Database format with ev- prefix on palette keys
40
49
  * const colours = {
41
50
  * 'ev-main': { 500: { L: 0.5, C: 0.2, H: 0 } },
42
51
  * 'ev-sec': { 500: { L: 0.5, C: 0.2, H: 120 } },
@@ -46,6 +55,44 @@
46
55
  * // Returns: { main: { 500: {...} }, sec: { 500: {...} }, acc: { 500: {...} } }
47
56
  * ```
48
57
  *
58
+ * @example
59
+ * ```ts
60
+ * // Future-proofing: ev- prefix on shade names
61
+ * const colours = {
62
+ * main: {
63
+ * 'ev-main-500': { L: 0.5, C: 0.2, H: 0 },
64
+ * 'ev-main-raw': { L: 0.55, C: 0.25, H: 5 }
65
+ * },
66
+ * sec: {
67
+ * 'ev-sec-200': { L: 0.8, C: 0.15, H: 120 }
68
+ * },
69
+ * acc: {
70
+ * 'ev-acc-800': { L: 0.3, C: 0.2, H: 240 }
71
+ * }
72
+ * };
73
+ * const palette = parseAndNormalizeEventColours(colours);
74
+ * // Returns: { main: { 'main-500': {...}, 'main-raw': {...} }, sec: { 'sec-200': {...} }, acc: { 'acc-800': {...} } }
75
+ * ```
76
+ *
77
+ * @example
78
+ * ```ts
79
+ * // Both palette keys and shade names with ev- prefix
80
+ * const colours = {
81
+ * 'ev-main': {
82
+ * 'ev-main-raw': { L: 0.55, C: 0.25, H: 5 },
83
+ * 'ev-main-200': { L: 0.8, C: 0.15, H: 0 }
84
+ * },
85
+ * 'ev-sec': {
86
+ * 'ev-sec-500': { L: 0.5, C: 0.2, H: 120 }
87
+ * },
88
+ * 'ev-acc': {
89
+ * 'ev-acc-800': { L: 0.3, C: 0.2, H: 240 }
90
+ * }
91
+ * };
92
+ * const palette = parseAndNormalizeEventColours(colours);
93
+ * // Returns: { main: { 'main-raw': {...}, 'main-200': {...} }, sec: { 'sec-500': {...} }, acc: { 'acc-800': {...} } }
94
+ * ```
95
+ *
49
96
  */
50
97
  declare function parseAndNormalizeEventColours(input: unknown): {
51
98
  main: any;
@@ -1,3 +1,3 @@
1
- export { applyPalette, clearPalette, generateSSRThemeCSS, getCurrentThemeData, isDynamicThemingActive, parseAndNormalizeEventColours } from '../chunk-ZKAWKYT4.js';
1
+ export { applyPalette, clearPalette, generateSSRThemeCSS, getCurrentThemeData, isDynamicThemingActive, parseAndNormalizeEventColours } from '../chunk-5W2A3DRC.js';
2
2
  import '../chunk-TTRFSOKR.js';
3
3
  import '../chunk-3RG5ZIWI.js';
package/dist/types.d.ts CHANGED
@@ -7,7 +7,7 @@ export { g as BucketInfo, B as BulkUploadResult, F as FileCategory, b as FileMet
7
7
  export { C as ChangePasswordFormValues, o as ContactFormData, F as FormData, k as LoginFormData, L as LoginFormValues, P as ProfileFormData, m as RegistrationFormData, R as RegistrationFormValues, S as SecureLoginFormValues, j as SecureRegistrationFormValues, U as UserProfileFormValues, V as ValidationError, a as ValidationResult, g as changePasswordSchema, t as combineSchemas, i as contactFormSchema, d as dateSchema, e as emailSchema, l as loginSchema, n as nameSchema, f as passwordResetSchema, b as passwordSchema, p as phoneSchema, q as pickSchema, r as registrationSchema, c as secureLoginSchema, s as securePasswordSchema, u as urlSchema, h as userProfileSchema } from './validation-643vUDZW.js';
8
8
  import { SupabaseClient } from '@supabase/supabase-js';
9
9
  export { D as Database, J as Json } from './database.generated-CcnC_DRc.js';
10
- export { A as AccessLevelContext, s as AuditEventType, P as PermissionSource, d as RBACAccessValidateParams, e as RBACAccessValidateResult, q as RBACAuditLogParams, r as RBACAuditLogResult, t as RBACContext, w as RBACErrorCode, v as RBACFunctionResponse, f as RBACPageAccessCheckParams, R as RBACPermissionCheckParams, a as RBACPermissionCheckResult, b as RBACPermissionsGetParams, c as RBACPermissionsGetResult, u as RBACResult, g as RBACRoleGrantParams, h as RBACRoleGrantResult, i as RBACRoleRevokeParams, j as RBACRoleRevokeResult, m as RBACRoleValidateParams, n as RBACRoleValidateResult, k as RBACRolesListParams, l as RBACRolesListResult, o as RBACSessionTrackParams, p as RBACSessionTrackResult, S as SessionType } from './functions-DHebl8-F.js';
10
+ export { A as AccessLevelContext, s as AuditEventType, P as PermissionSource, d as RBACAccessValidateParams, e as RBACAccessValidateResult, q as RBACAuditLogParams, r as RBACAuditLogResult, t as RBACContext, w as RBACErrorCode, v as RBACFunctionResponse, f as RBACPageAccessCheckParams, R as RBACPermissionCheckParams, a as RBACPermissionCheckResult, b as RBACPermissionsGetParams, c as RBACPermissionsGetResult, u as RBACResult, g as RBACRoleGrantParams, h as RBACRoleGrantResult, i as RBACRoleRevokeParams, j as RBACRoleRevokeResult, m as RBACRoleValidateParams, n as RBACRoleValidateResult, k as RBACRolesListParams, l as RBACRolesListResult, o as RBACSessionTrackParams, p as RBACSessionTrackResult, S as SessionType } from './functions-lBy5L2ry.js';
11
11
  import 'zod';
12
12
  import './types-BeoeWV5I.js';
13
13
 
@@ -185,7 +185,7 @@ type TableName = 'users' | 'rbac_global_roles' | 'rbac_organisation_roles' | 'rb
185
185
  * - Utility (3): Helper functions supporting RBAC operations
186
186
  * - Legacy (2): Deprecated functions to be removed
187
187
  */
188
- type RPCFunction = 'rbac_permission_check' | 'rbac_permissions_get' | 'rbac_access_validate' | 'rbac_page_access_check' | 'rbac_role_grant' | 'rbac_role_revoke' | 'rbac_roles_list' | 'rbac_role_validate' | 'rbac_session_track' | 'rbac_audit_log' | 'data_user_events_get' | 'data_user_organisation_roles_get' | 'data_user_organisations_get' | 'data_cake_meals_get' | 'util_app_resolve' | 'debug_auth_context' | 'handle_new_user' | 'get_pace_user_events';
188
+ type RPCFunction = 'rbac_permission_check' | 'rbac_permissions_get' | 'rbac_access_validate' | 'rbac_page_access_check' | 'rbac_role_grant' | 'rbac_role_revoke' | 'data_rbac_roles_list' | 'rbac_role_validate' | 'rbac_session_track' | 'rbac_audit_log' | 'data_user_events_get' | 'data_user_organisation_roles_get' | 'data_user_organisations_get' | 'data_cake_meals_get' | 'data_app_resolve' | 'debug_auth_context' | 'handle_new_user' | 'get_pace_user_events';
189
189
  /**
190
190
  * Helper type for Supabase filter operations
191
191
  */
package/dist/utils.js CHANGED
@@ -759,7 +759,7 @@ function createLazyComponent(importFn, componentName, options = {}) {
759
759
  return WrappedComponent;
760
760
  }
761
761
  var LazyDataTable = createLazyComponent(
762
- () => import('./DataTable-7PMH7XN7.js').then((module) => ({ default: module.DataTable })),
762
+ () => import('./DataTable-6RMSCQJ6.js').then((module) => ({ default: module.DataTable })),
763
763
  "DataTable"
764
764
  );
765
765
 
@@ -795,7 +795,7 @@ Props for the ContextSelector component.
795
795
 
796
796
  #### Defined in
797
797
 
798
- [packages/core/src/components/ContextSelector/ContextSelector.tsx:66](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/ContextSelector/ContextSelector.tsx#L66)
798
+ [packages/core/src/components/ContextSelector/ContextSelector.tsx:65](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/ContextSelector/ContextSelector.tsx#L65)
799
799
 
800
800
  ___
801
801
 
@@ -813,7 +813,7 @@ Enhanced DataTable props with performance features
813
813
 
814
814
  #### Defined in
815
815
 
816
- [packages/core/src/components/DataTable/DataTable.tsx:315](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/DataTable/DataTable.tsx#L315)
816
+ [packages/core/src/components/DataTable/DataTable.tsx:297](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/DataTable/DataTable.tsx#L297)
817
817
 
818
818
  ___
819
819
 
@@ -3134,7 +3134,7 @@ ___
3134
3134
 
3135
3135
  | Name | Type |
3136
3136
  | :------ | :------ |
3137
- | `props` | HTMLAttributes\<HTMLElement\> & Object & RefAttributes\<HTMLElement\> |
3137
+ | `props` | HTMLAttributes\<HTMLParagraphElement\> & Object & RefAttributes\<HTMLParagraphElement\> |
3138
3138
 
3139
3139
  #### Returns
3140
3140
 
@@ -3142,7 +3142,7 @@ ReactNode
3142
3142
 
3143
3143
  #### Defined in
3144
3144
 
3145
- [packages/core/src/components/Alert/Alert.tsx:67](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/Alert/Alert.tsx#L67)
3145
+ [packages/core/src/components/Alert/Alert.tsx:72](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/Alert/Alert.tsx#L72)
3146
3146
 
3147
3147
  ___
3148
3148
 
@@ -3162,7 +3162,7 @@ ReactNode
3162
3162
 
3163
3163
  #### Defined in
3164
3164
 
3165
- [packages/core/src/components/Alert/Alert.tsx:94](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/Alert/Alert.tsx#L94)
3165
+ [packages/core/src/components/Alert/Alert.tsx:102](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/Alert/Alert.tsx#L102)
3166
3166
 
3167
3167
  ___
3168
3168
 
@@ -3182,7 +3182,7 @@ ReactNode
3182
3182
 
3183
3183
  #### Defined in
3184
3184
 
3185
- [packages/core/src/components/Alert/Alert.tsx:114](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/Alert/Alert.tsx#L114)
3185
+ [packages/core/src/components/Alert/Alert.tsx:122](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/Alert/Alert.tsx#L122)
3186
3186
 
3187
3187
  ___
3188
3188
 
@@ -3487,7 +3487,7 @@ null \| Element
3487
3487
 
3488
3488
  #### Defined in
3489
3489
 
3490
- [packages/core/src/components/ContextSelector/ContextSelector.tsx:108](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/ContextSelector/ContextSelector.tsx#L108)
3490
+ [packages/core/src/components/ContextSelector/ContextSelector.tsx:107](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/ContextSelector/ContextSelector.tsx#L107)
3491
3491
 
3492
3492
  ___
3493
3493
 
@@ -3518,7 +3518,7 @@ The rendered DataTable component
3518
3518
 
3519
3519
  #### Defined in
3520
3520
 
3521
- [packages/core/src/components/DataTable/DataTable.tsx:497](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/DataTable/DataTable.tsx#L497)
3521
+ [packages/core/src/components/DataTable/DataTable.tsx:479](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/components/DataTable/DataTable.tsx#L479)
3522
3522
 
3523
3523
  ___
3524
3524
 
@@ -6011,7 +6011,7 @@ Object
6011
6011
 
6012
6012
  #### Defined in
6013
6013
 
6014
- [packages/core/src/hooks/public/usePublicRouteParams.ts:216](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicRouteParams.ts#L216)
6014
+ [packages/core/src/hooks/public/usePublicRouteParams.ts:220](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicRouteParams.ts#L220)
6015
6015
 
6016
6016
  ___
6017
6017
 
@@ -6034,7 +6034,7 @@ string
6034
6034
 
6035
6035
  #### Defined in
6036
6036
 
6037
- [packages/core/src/hooks/public/usePublicRouteParams.ts:252](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicRouteParams.ts#L252)
6037
+ [packages/core/src/hooks/public/usePublicRouteParams.ts:256](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicRouteParams.ts#L256)
6038
6038
 
6039
6039
  ___
6040
6040
 
@@ -6057,7 +6057,7 @@ string \| null
6057
6057
 
6058
6058
  #### Defined in
6059
6059
 
6060
- [packages/core/src/hooks/public/usePublicRouteParams.ts:267](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicRouteParams.ts#L267)
6060
+ [packages/core/src/hooks/public/usePublicRouteParams.ts:271](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/public/usePublicRouteParams.ts#L271)
6061
6061
 
6062
6062
  ___
6063
6063
 
@@ -6155,7 +6155,7 @@ void
6155
6155
 
6156
6156
  #### Defined in
6157
6157
 
6158
- [packages/core/src/hooks/useEventTheme.ts:98](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/useEventTheme.ts#L98)
6158
+ [packages/core/src/hooks/useEventTheme.ts:101](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/hooks/useEventTheme.ts#L101)
6159
6159
 
6160
6160
  ___
6161
6161
 
@@ -8611,12 +8611,21 @@ Parse and normalize event_colours to PaletteData
8611
8611
  Supports input formats:
8612
8612
  - Object with 'main', 'sec', 'acc' keys (standard format)
8613
8613
  - Object with 'ev-main', 'ev-sec', 'ev-acc' keys (database format with prefix)
8614
+ - Shade names with 'ev-' prefix (e.g., 'ev-acc-500' -> 'acc-500', 'ev-main-raw' -> 'main-raw')
8614
8615
  - JSON string that will be parsed
8615
8616
 
8616
8617
  Only includes explicitly defined color values. Does not fill
8617
8618
  missing shades - only shades that are present in the input will
8618
8619
  be included in the output.
8619
8620
 
8621
+ The parser automatically strips 'ev-' prefixes from BOTH palette keys and shade names
8622
+ for future-proofing, allowing distinction between event colors and organization colors
8623
+ (org colors not yet implemented).
8624
+
8625
+ Normalization rules:
8626
+ - Palette keys: 'ev-main' -> 'main', 'ev-sec' -> 'sec', 'ev-acc' -> 'acc'
8627
+ - Shade names: 'ev-main-raw' -> 'main-raw', 'ev-sec-200' -> 'sec-200', 'ev-acc-800' -> 'acc-800'
8628
+
8620
8629
  #### Parameters
8621
8630
 
8622
8631
  | Name | Type | Description |
@@ -8645,7 +8654,7 @@ const palette = parseAndNormalizeEventColours(colours);
8645
8654
  **`Example`**
8646
8655
 
8647
8656
  ```ts
8648
- // Database format with ev- prefix
8657
+ // Database format with ev- prefix on palette keys
8649
8658
  const colours = {
8650
8659
  'ev-main': { 500: { L: 0.5, C: 0.2, H: 0 } },
8651
8660
  'ev-sec': { 500: { L: 0.5, C: 0.2, H: 120 } },
@@ -8655,9 +8664,49 @@ const palette = parseAndNormalizeEventColours(colours);
8655
8664
  // Returns: { main: { 500: {...} }, sec: { 500: {...} }, acc: { 500: {...} } }
8656
8665
  ```
8657
8666
 
8667
+ **`Example`**
8668
+
8669
+ ```ts
8670
+ // Future-proofing: ev- prefix on shade names
8671
+ const colours = {
8672
+ main: {
8673
+ 'ev-main-500': { L: 0.5, C: 0.2, H: 0 },
8674
+ 'ev-main-raw': { L: 0.55, C: 0.25, H: 5 }
8675
+ },
8676
+ sec: {
8677
+ 'ev-sec-200': { L: 0.8, C: 0.15, H: 120 }
8678
+ },
8679
+ acc: {
8680
+ 'ev-acc-800': { L: 0.3, C: 0.2, H: 240 }
8681
+ }
8682
+ };
8683
+ const palette = parseAndNormalizeEventColours(colours);
8684
+ // Returns: { main: { 'main-500': {...}, 'main-raw': {...} }, sec: { 'sec-200': {...} }, acc: { 'acc-800': {...} } }
8685
+ ```
8686
+
8687
+ **`Example`**
8688
+
8689
+ ```ts
8690
+ // Both palette keys and shade names with ev- prefix
8691
+ const colours = {
8692
+ 'ev-main': {
8693
+ 'ev-main-raw': { L: 0.55, C: 0.25, H: 5 },
8694
+ 'ev-main-200': { L: 0.8, C: 0.15, H: 0 }
8695
+ },
8696
+ 'ev-sec': {
8697
+ 'ev-sec-500': { L: 0.5, C: 0.2, H: 120 }
8698
+ },
8699
+ 'ev-acc': {
8700
+ 'ev-acc-800': { L: 0.3, C: 0.2, H: 240 }
8701
+ }
8702
+ };
8703
+ const palette = parseAndNormalizeEventColours(colours);
8704
+ // Returns: { main: { 'main-raw': {...}, 'main-200': {...} }, sec: { 'sec-500': {...} }, acc: { 'acc-800': {...} } }
8705
+ ```
8706
+
8658
8707
  #### Defined in
8659
8708
 
8660
- [packages/core/src/theming/parseEventColours.ts:52](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/theming/parseEventColours.ts#L52)
8709
+ [packages/core/src/theming/parseEventColours.ts:99](https://github.com/jmruthers/pace-core/blob/main/packages/core/src/theming/parseEventColours.ts#L99)
8661
8710
 
8662
8711
  ___
8663
8712
 
@@ -31,6 +31,29 @@ reviewedBy: dependency-clarity-audit
31
31
 
32
32
  ---
33
33
 
34
+ ## 📋 Source of Truth: package.json
35
+
36
+ **IMPORTANT:** The `package.json` file in `@jmruthers/pace-core` is the **single source of truth** for all dependency information.
37
+
38
+ - **Peer dependencies** are defined in `package.json.peerDependencies`
39
+ - **Required vs optional** peers are marked in `package.json.peerDependenciesMeta`
40
+ - **Included dependencies** are listed in `package.json.dependencies`
41
+ - The **audit tool** reads directly from `package.json` - no hardcoded lists
42
+ - This **documentation** provides additional context and guidance, but version numbers and dependency lists come from `package.json`
43
+
44
+ **For pace-core maintainers:**
45
+ - Always update `package.json` when adding/removing dependencies
46
+ - Run `npm run validate:dependencies` to ensure consistency
47
+ - The validation script checks that `package.json`, audit tool, and documentation are in sync
48
+ - Validation runs automatically before publishing via `prepublishOnly` hook
49
+
50
+ **For consuming apps:**
51
+ - Use the audit tool (`npm run audit:pace-core`) to check your dependencies
52
+ - The audit tool reads the current `package.json` from the installed pace-core package
53
+ - Version requirements shown by the audit tool come directly from `package.json`
54
+
55
+ ---
56
+
34
57
  ## ⚠️ CRITICAL: pace-core Version Requirement
35
58
 
36
59
  **You MUST use `@jmruthers/pace-core@^0.6.5` or later.** Older versions may have incompatible dependencies or missing features.
@@ -963,7 +963,7 @@ test('renders mobile layout correctly', () => {
963
963
  ### 1. Layout Structure
964
964
 
965
965
  - Use semantic HTML elements (header, nav, main, aside, footer)
966
- - Implement proper heading hierarchy
966
+ - Implement proper heading hierarchy (heading levels can skip when semantically appropriate)
967
967
  - Provide clear navigation structure
968
968
  - Use consistent spacing and typography
969
969
 
@@ -2658,7 +2658,7 @@ The DataTable component is designed with accessibility in mind and meets WCAG 2.
2658
2658
  2. **Provide alt text for images** - Any images in cells should have alt text
2659
2659
  3. **Test with screen readers** - Verify table is navigable with screen readers
2660
2660
  4. **Maintain focus visibility** - Ensure focus indicators are visible
2661
- 5. **Use proper heading hierarchy** - Use appropriate heading levels for table context
2661
+ 5. **Use proper heading hierarchy** - Use appropriate heading levels for table context (heading levels can skip when semantically appropriate, e.g., h2 → h5)
2662
2662
 
2663
2663
  ## ⚠️ Edge Cases
2664
2664
 
@@ -131,6 +131,18 @@ export default [
131
131
  ];
132
132
  ```
133
133
 
134
+ **Example with `tseslint.config()` wrapper:**
135
+ ```javascript
136
+ // eslint.config.js
137
+ import tseslint from 'typescript-eslint';
138
+ import paceCoreConfig from '@jmruthers/pace-core/eslint-config';
139
+
140
+ export default tseslint.config(
141
+ ...paceCoreConfig, // Spread pace-core config as first arguments
142
+ // your other config objects
143
+ );
144
+ ```
145
+
134
146
  ### Step 3: Setup Cursor Rules (Optional but Recommended)
135
147
 
136
148
  **Automated Setup (Easiest)**
@@ -924,6 +936,31 @@ During audits, documented exceptions will be:
924
936
 
925
937
  ## Troubleshooting
926
938
 
939
+ ### ESLint Setup Issues
940
+
941
+ **Error: "Could not find 'no-restricted-imports' in plugin 'pace-core-compliance'"**
942
+ - **Cause**: This rule was removed from the plugin (it's now handled by standard ESLint `no-restricted-imports`)
943
+ - **Fix**: Update to the latest version of `@jmruthers/pace-core` and run `npm run setup:eslint --force`
944
+
945
+ **Error: "TypeError: Unexpected array" when using `tseslint.config()`**
946
+ - **Cause**: Incorrect spreading of `paceCoreConfig` in `tseslint.config()` wrapper
947
+ - **Fix**: Run `npm run setup:eslint --force` to fix the config structure, or manually ensure `paceCoreConfig` is spread correctly:
948
+ ```javascript
949
+ import paceCoreConfig from '@jmruthers/pace-core/eslint-config';
950
+
951
+ export default tseslint.config(
952
+ ...paceCoreConfig, // Spread here, not nested
953
+ // your other config
954
+ );
955
+ ```
956
+
957
+ **ESLint rules not loading**
958
+ - **Cause**: Path resolution issues or rules not copied to `dist/`
959
+ - **Fix**:
960
+ 1. Ensure `@jmruthers/pace-core` is built: `npm run build` in pace-core
961
+ 2. Check that `node_modules/@jmruthers/pace-core/dist/eslint-rules/` exists
962
+ 3. Run `npm run setup:eslint --force` to regenerate config
963
+
927
964
  ### ESLint Rules Not Working
928
965
 
929
966
  1. **Verify plugin is loaded**: Check that the config is imported correctly
@@ -931,7 +968,7 @@ During audits, documented exceptions will be:
931
968
  3. **Verify manifest exists**: Rules load from `core-usage-manifest.json` in the pace-core package
932
969
  4. **CommonJS/ES Module issues**: If you're using ES modules and rules aren't loading, ensure you're using the config preset which handles this automatically
933
970
  5. **Verify rules are available**: Check that the rules file exists
934
- 6. **Check rule count**: Verify all 15 rules are loaded
971
+ 6. **Check rule count**: Verify all rules are loaded
935
972
 
936
973
  ### Static Analysis Script Errors
937
974
 
@@ -33,38 +33,43 @@ try {
33
33
 
34
34
  // Load pace-core ESLint rules
35
35
  let paceCoreRules = {};
36
+ const sourceRulesPath = path.resolve(__dirname, 'eslint-rules/index.cjs');
37
+ const distRulesPath = path.resolve(__dirname, 'dist/eslint-rules/index.cjs');
38
+ const cwdRulesPath = path.resolve(process.cwd(), 'node_modules/@jmruthers/pace-core/dist/eslint-rules/index.cjs');
39
+
36
40
  try {
37
41
  // Try source path first (for development) - new location at package root
38
- const sourceRulesPath = path.resolve(__dirname, 'eslint-rules/index.cjs');
39
42
  if (fs.existsSync(sourceRulesPath)) {
40
43
  paceCoreRules = require(sourceRulesPath).rules;
41
44
  } else {
42
45
  // Try dist path (for published package)
43
- const distRulesPath = path.resolve(__dirname, 'dist/eslint-rules/index.cjs');
44
46
  if (fs.existsSync(distRulesPath)) {
45
47
  paceCoreRules = require(distRulesPath).rules;
46
48
  } else {
47
49
  // Try relative to current working directory (for consuming apps)
48
- const cwdRulesPath = path.resolve(process.cwd(), 'node_modules/@jmruthers/pace-core/dist/eslint-rules/index.cjs');
49
50
  if (fs.existsSync(cwdRulesPath)) {
50
51
  paceCoreRules = require(cwdRulesPath).rules;
51
52
  }
52
53
  }
53
54
  }
54
55
  } catch (error) {
55
- // Silently fail - rules will be empty, but config will still work
56
+ // Log warning in development but don't fail - rules will be empty, but config will still work
56
57
  // This allows the config to be used even if rules aren't available
58
+ if (process.env.NODE_ENV !== 'production') {
59
+ console.warn(`Warning: Could not load pace-core ESLint rules: ${error.message}`);
60
+ console.warn(` Tried paths: ${sourceRulesPath}, ${distRulesPath}, ${cwdRulesPath}`);
61
+ }
57
62
  }
58
63
 
59
64
  // Build restricted imports for no-restricted-imports rule (ESLint 9 flat config format)
60
- // ESLint 9 expects an array of objects with 'name' (string or regex) and 'message'
61
- const restrictedImportRules = restrictedImports.map(({ module, reason }) => ({
65
+ // ESLint 9 expects an object with 'paths' array - all restrictions use 'name' property
66
+ const restrictedPaths = restrictedImports.map(({ module, reason }) => ({
62
67
  name: module,
63
68
  message: reason || `Use pace-core alternative instead of direct import of '${module}'`
64
69
  }));
65
70
 
66
- // Also add pattern for @radix-ui/* (catch-all) - use string pattern format
67
- restrictedImportRules.push({
71
+ // Add @radix-ui/* pattern (also uses 'name' property, wildcards work with 'name')
72
+ restrictedPaths.push({
68
73
  name: '@radix-ui/*',
69
74
  message: 'Use pace-core components instead of direct Radix UI imports'
70
75
  });
@@ -78,7 +83,6 @@ module.exports = [
78
83
  },
79
84
  rules: {
80
85
  // Standard 1: pace-core Compliance
81
- 'pace-core-compliance/no-restricted-imports': 'error',
82
86
  'pace-core-compliance/prefer-pace-core-components': 'warn',
83
87
  'pace-core-compliance/prefer-pace-core-hooks': 'warn',
84
88
  'pace-core-compliance/prefer-pace-core-utils': 'warn',
@@ -112,8 +116,23 @@ module.exports = [
112
116
  'pace-core-compliance/test-file-naming': 'warn',
113
117
 
114
118
  // Also use standard no-restricted-imports (ESLint 9 flat config format)
115
- // Note: ESLint 9 uses a simpler array format
116
- 'no-restricted-imports': ['error', ...restrictedImportRules]
119
+ // ESLint 9 expects an object with 'paths' array containing objects with 'name' property
120
+ 'no-restricted-imports': ['error', {
121
+ paths: restrictedPaths
122
+ }]
123
+ }
124
+ },
125
+ // Override for Edge Functions (Deno runtime)
126
+ // Edge Functions run in Deno, not React, so they cannot use React hooks
127
+ // They need direct Supabase client access and console.log for debugging
128
+ {
129
+ files: ['**/supabase/functions/**/*.{ts,js}'],
130
+ rules: {
131
+ // Allow console.log in Edge Functions for debugging and monitoring
132
+ 'no-console': 'off',
133
+ // Edge Functions cannot use React hooks, so they must use createClient directly
134
+ // The rule already excludes Edge Functions, but we explicitly allow it here for clarity
135
+ 'pace-core-compliance/no-direct-supabase-client': 'off',
117
136
  }
118
137
  }
119
138
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jmruthers/pace-core",
3
- "version": "0.6.7",
3
+ "version": "0.6.8",
4
4
  "description": "React component library with Tailwind v4",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -166,7 +166,8 @@
166
166
  "link": "npm run build && npm link",
167
167
  "unlink": "npm unlink",
168
168
  "validate:theme": "node scripts/validate-theme.js",
169
- "prepublishOnly": "npm run build",
169
+ "prepublishOnly": "npm run validate:dependencies && npm run build",
170
+ "validate:dependencies": "node scripts/validate-dependencies.cjs",
170
171
  "clean": "rimraf dist",
171
172
  "_comment_test": "Test suite with various configurations",
172
173
  "test": "cross-env NODE_OPTIONS=\"--max-old-space-size=8192 --max-semi-space-size=128\" vitest run --config ../../vitest.config.ts",
@@ -218,38 +219,67 @@
218
219
  "clsx": "^2.0.0",
219
220
  "date-fns": "^3.0.0",
220
221
  "date-fns-tz": "^3.0.0",
221
- "react": "^19.0.0",
222
+ "react": "^19.2.3",
222
223
  "react-day-picker": "^9.0.0",
223
- "react-dom": "^19.0.0",
224
+ "react-dom": "^19.2.3",
224
225
  "react-hook-form": "^7.0.0",
225
226
  "react-router-dom": "^6.0.0",
226
227
  "tailwind-merge": "^2.0.0",
227
- "tailwindcss": "^4.0.0",
228
+ "tailwindcss": "^4.1.16",
228
229
  "zod": "^3.20.0"
229
230
  },
231
+ "peerDependenciesMeta": {
232
+ "@tanstack/react-query": {
233
+ "optional": true
234
+ },
235
+ "@tanstack/react-table": {
236
+ "optional": true
237
+ },
238
+ "clsx": {
239
+ "optional": true
240
+ },
241
+ "date-fns": {
242
+ "optional": true
243
+ },
244
+ "date-fns-tz": {
245
+ "optional": true
246
+ },
247
+ "react-hook-form": {
248
+ "optional": true
249
+ },
250
+ "react-day-picker": {
251
+ "optional": true
252
+ },
253
+ "zod": {
254
+ "optional": true
255
+ },
256
+ "tailwind-merge": {
257
+ "optional": true
258
+ }
259
+ },
230
260
  "devDependencies": {
231
261
  "@testing-library/jest-dom": "^6.6.3",
232
- "@testing-library/react": "^16.1.0",
233
- "@testing-library/user-event": "^14.5.2",
262
+ "@testing-library/react": "^16.3.0",
263
+ "@testing-library/user-event": "^14.6.1",
234
264
  "@types/papaparse": "^5.3.16",
235
- "@types/react": "^19.0.0",
236
- "@types/react-dom": "^19.0.0",
265
+ "@types/react": "^19.2.7",
266
+ "@types/react-dom": "^19.2.3",
237
267
  "@types/react-window": "^1.8.8",
238
- "@vitejs/plugin-react": "^4.5.1",
239
- "@vitest/coverage-v8": "^3.2.3",
268
+ "@vitejs/plugin-react": "^5.1.2",
269
+ "@vitest/coverage-v8": "^4.0.16",
240
270
  "esbuild": "^0.20.0",
241
271
  "eslint-plugin-react-hooks": "^5.2.0",
242
272
  "eslint-plugin-react-refresh": "^0.4.20",
243
273
  "globals": "^16.3.0",
244
274
  "jsdom": "^25.0.1",
245
275
  "react-router-dom": "^6.26.2",
246
- "tsup": "^8.5.0",
247
- "typedoc": "^0.26.11",
276
+ "tsup": "^8.5.1",
277
+ "typedoc": "^0.27.0",
248
278
  "typedoc-plugin-markdown": "^3.17.1",
249
279
  "typedoc-plugin-merge-modules": "^5.1.0",
250
- "typescript": "^5.4.0",
280
+ "typescript": "^5.9.3",
251
281
  "typescript-eslint": "^8.39.0",
252
- "vite": "^6.0.3"
282
+ "vite": "^7.2.7"
253
283
  },
254
284
  "dependencies": {
255
285
  "@hookform/resolvers": "^3.9.0",