@redacto.io/consent-sdk-react 3.6.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/index.d.mts +4 -4
  3. package/dist/index.d.ts +4 -4
  4. package/dist/index.js +36 -7
  5. package/dist/index.mjs +36 -7
  6. package/dist/privacy-center.d.mts +134 -51
  7. package/dist/privacy-center.d.ts +134 -51
  8. package/dist/privacy-center.js +6391 -2741
  9. package/dist/privacy-center.mjs +6135 -2482
  10. package/package.json +1 -1
  11. package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +5 -5
  12. package/src/RedactoNoticeConsent/language-codes.ts +37 -1
  13. package/src/RedactoNoticeConsentInline/RedactoNoticeConsentInline.tsx +0 -3
  14. package/src/RedactoNoticeConsentInline/api/index.ts +0 -1
  15. package/src/RedactoPrivacyCenter/PrivacyCenterCaseDetailsPage.tsx +154 -0
  16. package/src/RedactoPrivacyCenter/PrivacyCenterHomePage.tsx +3 -0
  17. package/src/RedactoPrivacyCenter/PrivacyCenterLayout.tsx +81 -50
  18. package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +4 -0
  19. package/src/RedactoPrivacyCenter/api/actions.ts +68 -36
  20. package/src/RedactoPrivacyCenter/api/client.ts +125 -14
  21. package/src/RedactoPrivacyCenter/components/CaseDetails/AttachmentCard.tsx +38 -0
  22. package/src/RedactoPrivacyCenter/components/CaseDetails/ChatBubble.tsx +31 -0
  23. package/src/RedactoPrivacyCenter/components/CaseDetails/DocumentRequestCard.tsx +73 -0
  24. package/src/RedactoPrivacyCenter/components/CaseDetails/MessageComposer.tsx +87 -0
  25. package/src/RedactoPrivacyCenter/components/CaseDetails/MessageItem.tsx +95 -0
  26. package/src/RedactoPrivacyCenter/components/CaseDetails/MessagesTab.tsx +147 -0
  27. package/src/RedactoPrivacyCenter/components/CaseDetails/RequestDetailsTab.tsx +171 -0
  28. package/src/RedactoPrivacyCenter/components/CaseDetails/StatusEvent.tsx +23 -0
  29. package/src/RedactoPrivacyCenter/components/CaseDetails/useFileUpload.ts +116 -0
  30. package/src/RedactoPrivacyCenter/components/CaseDetails/useMessagePolling.ts +36 -0
  31. package/src/RedactoPrivacyCenter/components/CaseDetails/utils.ts +56 -0
  32. package/src/RedactoPrivacyCenter/components/CaseDetailsModal.tsx +1 -0
  33. package/src/RedactoPrivacyCenter/components/CaseHistory.tsx +6 -13
  34. package/src/RedactoPrivacyCenter/components/ConsentManager.tsx +6 -0
  35. package/src/RedactoPrivacyCenter/components/ConsentManagerColumns.tsx +0 -1
  36. package/src/RedactoPrivacyCenter/components/DataRequest/CorrectionDataSection.tsx +2 -2
  37. package/src/RedactoPrivacyCenter/components/DataRequest/PurposeSelectionSection.tsx +2 -3
  38. package/src/RedactoPrivacyCenter/components/Form.tsx +152 -11
  39. package/src/RedactoPrivacyCenter/components/GrievanceTable.tsx +4 -6
  40. package/src/RedactoPrivacyCenter/components/GrievanceTablePagination.tsx +9 -2
  41. package/src/RedactoPrivacyCenter/components/ModifyConsentModal.tsx +1 -0
  42. package/src/RedactoPrivacyCenter/components/Pagination.tsx +12 -12
  43. package/src/RedactoPrivacyCenter/components/PrivacyCenterLayout.tsx +3 -1
  44. package/src/RedactoPrivacyCenter/components/RequestSubmit.tsx +15 -1
  45. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/SideBarPC.tsx +8 -8
  46. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/SideMenuPC.tsx +7 -11
  47. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/types.ts +1 -1
  48. package/src/RedactoPrivacyCenter/components/activitiesColumns.tsx +1 -1
  49. package/src/RedactoPrivacyCenter/components/caseHistoryColumns.tsx +4 -24
  50. package/src/RedactoPrivacyCenter/components/constant.ts +3 -7
  51. package/src/RedactoPrivacyCenter/components/types.ts +12 -4
  52. package/src/RedactoPrivacyCenter/context/AuthContext.tsx +30 -16
  53. package/src/RedactoPrivacyCenter/context/BaseUrlContext.tsx +3 -6
  54. package/src/RedactoPrivacyCenter/context/NavigationContext.tsx +35 -3
  55. package/src/RedactoPrivacyCenter/context/OrganizationContext.tsx +1 -1
  56. package/src/RedactoPrivacyCenter/context/types.ts +14 -0
  57. package/src/RedactoPrivacyCenter/lib/api.ts +101 -3
  58. package/src/RedactoPrivacyCenter/lib/constants.ts +46 -1
  59. package/src/RedactoPrivacyCenter/lib/i18n.ts +1 -1
  60. package/src/RedactoPrivacyCenter/lib/queries.ts +106 -2
  61. package/src/RedactoPrivacyCenter/lib/types.ts +186 -1
  62. package/src/RedactoPrivacyCenter/lib/utils.ts +1 -0
  63. package/src/RedactoPrivacyCenter/locales/as/translation.json +93 -1
  64. package/src/RedactoPrivacyCenter/locales/bho/translation.json +93 -1
  65. package/src/RedactoPrivacyCenter/locales/bn/translation.json +93 -1
  66. package/src/RedactoPrivacyCenter/locales/brx/translation.json +93 -1
  67. package/src/RedactoPrivacyCenter/locales/doi/translation.json +93 -1
  68. package/src/RedactoPrivacyCenter/locales/en/translation.json +69 -2
  69. package/src/RedactoPrivacyCenter/locales/gom/translation.json +93 -1
  70. package/src/RedactoPrivacyCenter/locales/gu/translation.json +93 -1
  71. package/src/RedactoPrivacyCenter/locales/hi/translation.json +93 -1
  72. package/src/RedactoPrivacyCenter/locales/kn/translation.json +93 -1
  73. package/src/RedactoPrivacyCenter/locales/ks/translation.json +93 -1
  74. package/src/RedactoPrivacyCenter/locales/mai/translation.json +93 -1
  75. package/src/RedactoPrivacyCenter/locales/ml/translation.json +93 -1
  76. package/src/RedactoPrivacyCenter/locales/mni-Mtei/translation.json +93 -1
  77. package/src/RedactoPrivacyCenter/locales/mr/translation.json +93 -1
  78. package/src/RedactoPrivacyCenter/locales/ne/translation.json +93 -1
  79. package/src/RedactoPrivacyCenter/locales/or/translation.json +93 -1
  80. package/src/RedactoPrivacyCenter/locales/pa/translation.json +93 -1
  81. package/src/RedactoPrivacyCenter/locales/sa/translation.json +93 -1
  82. package/src/RedactoPrivacyCenter/locales/sat/translation.json +93 -1
  83. package/src/RedactoPrivacyCenter/locales/sd/translation.json +93 -1
  84. package/src/RedactoPrivacyCenter/locales/ta/translation.json +93 -1
  85. package/src/RedactoPrivacyCenter/locales/te/translation.json +93 -1
  86. package/src/RedactoPrivacyCenter/locales/ur/translation.json +93 -1
  87. package/src/RedactoPrivacyCenter/styles/injectStyles.ts +725 -0
  88. package/src/RedactoPrivacyCenter/styles/pcStyles.ts +0 -6
  89. package/src/RedactoPrivacyCenter/table/AdvancedTable.tsx +5 -3
  90. package/src/RedactoPrivacyCenter/table/AdvancedTablePagination.tsx +9 -12
  91. package/src/RedactoPrivacyCenter/ui/Footer.tsx +4 -2
  92. package/src/RedactoPrivacyCenter/ui/PCAccordion.tsx +24 -18
  93. package/src/RedactoPrivacyCenter/ui/PCCollapse.tsx +30 -20
  94. package/src/RedactoPrivacyCenter/ui/PCInput.tsx +17 -13
  95. package/src/RedactoPrivacyCenter/ui/PCLoader.tsx +3 -2
  96. package/src/RedactoPrivacyCenter/ui/PCModal.tsx +3 -1
  97. package/src/RedactoPrivacyCenter/ui/PCPopover.tsx +0 -2
  98. package/src/RedactoPrivacyCenter/ui/PCSelect.tsx +10 -4
  99. package/src/RedactoPrivacyCenter/ui/PCTable.tsx +44 -32
  100. package/src/RedactoPrivacyCenter/ui/PCText.tsx +5 -3
  101. package/src/RedactoPrivacyCenter/ui/StatusBadge.tsx +0 -2
  102. package/src/RedactoPrivacyCenter/ui/ThemeToggle.tsx +4 -2
  103. package/src/privacy-center.ts +1 -0
@@ -8,12 +8,6 @@
8
8
  // Helper to get CSS variable value
9
9
  const getVar = (varName: string): string => `var(${varName})`;
10
10
 
11
- // Helper to get computed CSS variable value (for runtime theme switching)
12
- const getComputedVar = (varName: string): string => {
13
- if (typeof window === 'undefined') return '';
14
- return getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
15
- };
16
-
17
11
  export const pcStyles = {
18
12
  // Layout utilities
19
13
  flex: {
@@ -11,6 +11,7 @@ import type {
11
11
  Cell,
12
12
  HeaderGroup,
13
13
  } from '@tanstack/react-table';
14
+ import type { TableColumnMeta } from '../components/types';
14
15
 
15
16
  const getVar = (varName: string): string => `var(${varName})`;
16
17
 
@@ -252,12 +253,13 @@ export function TableHeadBasic<TData extends Record<string, any>>({
252
253
  headerGroup,
253
254
  className,
254
255
  }: CustomHeaderCellProps<TData>) {
256
+ const { t } = useTranslation();
255
257
  if (!headerGroup) return null;
256
258
 
257
259
  return (
258
260
  <>
259
261
  {headerGroup.headers.map((header) => {
260
- const align = header.column.columnDef.meta?.align || 'left';
262
+ const align = (header.column.columnDef.meta as TableColumnMeta | undefined)?.align || 'left';
261
263
  return (
262
264
  <PCTable.Head
263
265
  key={header.id}
@@ -291,7 +293,7 @@ export function TableHeadBasic<TData extends Record<string, any>>({
291
293
  color: getVar('--pc-text-secondary'),
292
294
  transition: 'color 0.2s ease',
293
295
  }}
294
- aria-label="Sort by column"
296
+ aria-label={t('sortByColumn')}
295
297
  onMouseEnter={(e) => {
296
298
  e.currentTarget.style.color = getVar('--pc-text-primary');
297
299
  }}
@@ -352,7 +354,7 @@ export function TableCellBasic<TData extends Record<string, any>>({
352
354
  }: CustomBodyCellProps<TData>) {
353
355
  if (!cell) return null;
354
356
 
355
- const align = cell.column.columnDef.meta?.align || 'left';
357
+ const align = (cell.column.columnDef.meta as TableColumnMeta | undefined)?.align || 'left';
356
358
 
357
359
  return (
358
360
  <PCTable.Cell
@@ -1,4 +1,3 @@
1
- import React from 'react';
2
1
  import { useTranslation } from 'react-i18next';
3
2
  import { type Table as ReactTableType } from '@tanstack/react-table';
4
3
  import {
@@ -7,7 +6,7 @@ import {
7
6
  PiCaretLeftBold,
8
7
  PiCaretRightBold,
9
8
  } from 'react-icons/pi';
10
- import { PCActionIcon, PCSelect, PCText, type SelectOption } from '../ui';
9
+ import { PCActionIcon, PCSelect, PCText } from '../ui';
11
10
  import { pcStyles } from '../styles/pcStyles';
12
11
 
13
12
  const getVar = (varName: string): string => `var(${varName})`;
@@ -42,8 +41,6 @@ export default function AdvancedTablePagination<
42
41
  const currentPage = table.getState().pagination.pageIndex + 1;
43
42
  const totalPages = table.getPageCount();
44
43
  const totalRows = table.getFilteredRowModel().rows.length;
45
- const pageStart = totalRows === 0 ? 0 : (currentPage - 1) * currentPageSize + 1;
46
- const pageEnd = Math.min(currentPage * currentPageSize, totalRows);
47
44
 
48
45
  // Preserve pagination visibility even when rows are temporarily empty during loading
49
46
  const shouldShowPagination = totalPages > 0 || totalRows > 0;
@@ -146,7 +143,7 @@ export default function AdvancedTablePagination<
146
143
  <PCActionIcon
147
144
  size="sm"
148
145
  variant="outline"
149
- aria-label="Go to first page"
146
+ aria-label={t('goToFirstPage')}
150
147
  onClick={() => table.firstPage()}
151
148
  disabled={!table.getCanPreviousPage()}
152
149
  style={{
@@ -174,7 +171,7 @@ export default function AdvancedTablePagination<
174
171
  <PCActionIcon
175
172
  size="sm"
176
173
  variant="outline"
177
- aria-label="Go to previous page"
174
+ aria-label={t('goToPreviousPage')}
178
175
  onClick={() => table.previousPage()}
179
176
  disabled={!table.getCanPreviousPage()}
180
177
  style={{
@@ -202,7 +199,7 @@ export default function AdvancedTablePagination<
202
199
  <PCActionIcon
203
200
  size="sm"
204
201
  variant="outline"
205
- aria-label="Go to next page"
202
+ aria-label={t('goToNextPage')}
206
203
  onClick={() => table.nextPage()}
207
204
  disabled={!table.getCanNextPage()}
208
205
  style={{
@@ -230,7 +227,7 @@ export default function AdvancedTablePagination<
230
227
  <PCActionIcon
231
228
  size="sm"
232
229
  variant="outline"
233
- aria-label="Go to last page"
230
+ aria-label={t('goToLastPage')}
234
231
  onClick={() => table.lastPage()}
235
232
  disabled={!table.getCanNextPage()}
236
233
  style={{
@@ -362,7 +359,7 @@ export default function AdvancedTablePagination<
362
359
  <PCActionIcon
363
360
  size="sm"
364
361
  variant="outline"
365
- aria-label="Go to first page"
362
+ aria-label={t('goToFirstPage')}
366
363
  onClick={() => table.firstPage()}
367
364
  disabled={!table.getCanPreviousPage()}
368
365
  style={{
@@ -390,7 +387,7 @@ export default function AdvancedTablePagination<
390
387
  <PCActionIcon
391
388
  size="sm"
392
389
  variant="outline"
393
- aria-label="Go to previous page"
390
+ aria-label={t('goToPreviousPage')}
394
391
  onClick={() => table.previousPage()}
395
392
  disabled={!table.getCanPreviousPage()}
396
393
  style={{
@@ -418,7 +415,7 @@ export default function AdvancedTablePagination<
418
415
  <PCActionIcon
419
416
  size="sm"
420
417
  variant="outline"
421
- aria-label="Go to next page"
418
+ aria-label={t('goToNextPage')}
422
419
  onClick={() => table.nextPage()}
423
420
  disabled={!table.getCanNextPage()}
424
421
  style={{
@@ -446,7 +443,7 @@ export default function AdvancedTablePagination<
446
443
  <PCActionIcon
447
444
  size="sm"
448
445
  variant="outline"
449
- aria-label="Go to last page"
446
+ aria-label={t('goToLastPage')}
450
447
  onClick={() => table.lastPage()}
451
448
  disabled={!table.getCanNextPage()}
452
449
  style={{
@@ -1,3 +1,4 @@
1
+ import { useTranslation } from 'react-i18next';
1
2
  import { pcStyles } from '../styles/pcStyles';
2
3
  import PoweredByRedacto from '../assets/poweredByRedacto.svg';
3
4
  import { useTheme } from '../context/theme';
@@ -5,6 +6,7 @@ import { useTheme } from '../context/theme';
5
6
  const getVar = (varName: string): string => `var(${varName})`;
6
7
 
7
8
  export default function Footer() {
9
+ const { t } = useTranslation();
8
10
  const { theme } = useTheme();
9
11
 
10
12
  return (
@@ -36,7 +38,7 @@ export default function Footer() {
36
38
  lineHeight: 1.2,
37
39
  }}
38
40
  >
39
- Powered by
41
+ {t('poweredBy')}
40
42
  </span>
41
43
  <div
42
44
  style={{
@@ -57,7 +59,7 @@ export default function Footer() {
57
59
  >
58
60
  <img
59
61
  src={PoweredByRedacto}
60
- alt="Redacto Logo"
62
+ alt={t('redactoLogoAlt')}
61
63
  style={{
62
64
  height: 'clamp(1.125rem, 2.5vw, 1.75rem)',
63
65
  width: 'auto',
@@ -1,11 +1,13 @@
1
1
  import { type ReactNode, type CSSProperties, type HTMLAttributes } from 'react';
2
2
  import { pcStyles } from '../styles/pcStyles';
3
3
 
4
- export interface PCAccordionProps extends HTMLAttributes<HTMLDivElement> {
5
- children: ReactNode;
6
- className?: string;
7
- style?: CSSProperties;
8
- }
4
+ export type PCAccordionProps = Readonly<
5
+ HTMLAttributes<HTMLDivElement> & {
6
+ children: ReactNode;
7
+ className?: string;
8
+ style?: CSSProperties;
9
+ }
10
+ >;
9
11
 
10
12
  export function PCAccordion({ children, className = '', style = {}, ...props }: PCAccordionProps) {
11
13
  const accordionStyle: CSSProperties = {
@@ -20,13 +22,15 @@ export function PCAccordion({ children, className = '', style = {}, ...props }:
20
22
  );
21
23
  }
22
24
 
23
- export interface PCAccordionHeaderProps extends HTMLAttributes<HTMLDivElement> {
24
- children: ReactNode | ((props: { open: boolean; toggle: () => void }) => ReactNode);
25
- className?: string;
26
- style?: CSSProperties;
27
- open?: boolean;
28
- onToggle?: () => void;
29
- }
25
+ export type PCAccordionHeaderProps = Readonly<
26
+ Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
27
+ children: ReactNode | ((props: { open: boolean; toggle: () => void }) => ReactNode);
28
+ className?: string;
29
+ style?: CSSProperties;
30
+ open?: boolean;
31
+ onToggle?: () => void;
32
+ }
33
+ >;
30
34
 
31
35
  export function PCAccordionHeader({
32
36
  children,
@@ -53,12 +57,14 @@ export function PCAccordionHeader({
53
57
  );
54
58
  }
55
59
 
56
- export interface PCAccordionBodyProps extends HTMLAttributes<HTMLDivElement> {
57
- children: ReactNode;
58
- className?: string;
59
- style?: CSSProperties;
60
- open?: boolean;
61
- }
60
+ export type PCAccordionBodyProps = Readonly<
61
+ HTMLAttributes<HTMLDivElement> & {
62
+ children: ReactNode;
63
+ className?: string;
64
+ style?: CSSProperties;
65
+ open?: boolean;
66
+ }
67
+ >;
62
68
 
63
69
  export function PCAccordionBody({
64
70
  children,
@@ -1,12 +1,14 @@
1
1
  import { type ReactNode, type CSSProperties, type HTMLAttributes, useState } from 'react';
2
2
  import { pcStyles } from '../styles/pcStyles';
3
3
 
4
- export interface PCCollapseProps extends HTMLAttributes<HTMLDivElement> {
5
- children: ReactNode | ((props: { open: boolean; toggle: () => void }) => ReactNode);
6
- defaultOpen?: boolean;
7
- className?: string;
8
- style?: CSSProperties;
9
- }
4
+ export type PCCollapseProps = Readonly<
5
+ Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
6
+ children: ReactNode | ((props: { open: boolean; toggle: () => void }) => ReactNode);
7
+ defaultOpen?: boolean;
8
+ className?: string;
9
+ style?: CSSProperties;
10
+ }
11
+ >;
10
12
 
11
13
  export function PCCollapse({
12
14
  children,
@@ -30,13 +32,15 @@ export function PCCollapse({
30
32
  );
31
33
  }
32
34
 
33
- export interface PCCollapseHeaderProps extends HTMLAttributes<HTMLDivElement> {
34
- children: ReactNode | ((props: { open: boolean; toggle: () => void }) => ReactNode);
35
- className?: string;
36
- style?: CSSProperties;
37
- open?: boolean;
38
- toggle?: () => void;
39
- }
35
+ export type PCCollapseHeaderProps = Readonly<
36
+ Omit<HTMLAttributes<HTMLDivElement>, 'children'> & {
37
+ children: ReactNode | ((props: { open: boolean; toggle: () => void }) => ReactNode);
38
+ className?: string;
39
+ style?: CSSProperties;
40
+ open?: boolean;
41
+ toggle?: () => void;
42
+ }
43
+ >;
40
44
 
41
45
  export function PCCollapseHeader({
42
46
  children,
@@ -51,6 +55,10 @@ export function PCCollapseHeader({
51
55
  ...style,
52
56
  };
53
57
 
58
+ const rendered: ReactNode = typeof children === 'function'
59
+ ? children({ open, toggle: toggle || (() => {}) })
60
+ : children;
61
+
54
62
  return (
55
63
  <div
56
64
  className={`pc-collapse-header ${className}`}
@@ -58,17 +66,19 @@ export function PCCollapseHeader({
58
66
  onClick={toggle}
59
67
  {...props}
60
68
  >
61
- {typeof children === 'function' && toggle ? children({ open, toggle }) : children}
69
+ {rendered}
62
70
  </div>
63
71
  );
64
72
  }
65
73
 
66
- export interface PCCollapseBodyProps extends HTMLAttributes<HTMLDivElement> {
67
- children: ReactNode;
68
- className?: string;
69
- style?: CSSProperties;
70
- open?: boolean;
71
- }
74
+ export type PCCollapseBodyProps = Readonly<
75
+ HTMLAttributes<HTMLDivElement> & {
76
+ children: ReactNode;
77
+ className?: string;
78
+ style?: CSSProperties;
79
+ open?: boolean;
80
+ }
81
+ >;
72
82
 
73
83
  export function PCCollapseBody({
74
84
  children,
@@ -2,18 +2,21 @@ import { type ReactNode, type CSSProperties, type InputHTMLAttributes, useState,
2
2
  import { pcStyles } from '../styles/pcStyles';
3
3
  import { X } from 'lucide-react';
4
4
 
5
- export interface PCInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'style' | 'size'> {
6
- className?: string;
7
- style?: CSSProperties;
8
- label?: ReactNode;
9
- error?: boolean;
10
- clearable?: boolean;
11
- onClear?: () => void;
12
- prefix?: ReactNode;
13
- suffix?: ReactNode;
14
- inputClassName?: string;
15
- size?: 'sm' | 'md' | 'lg';
16
- }
5
+ export type PCInputProps = Readonly<
6
+ Omit<InputHTMLAttributes<HTMLInputElement>, 'style' | 'size' | 'prefix'> & {
7
+ className?: string;
8
+ style?: CSSProperties;
9
+ label?: ReactNode;
10
+ error?: boolean;
11
+ clearable?: boolean;
12
+ onClear?: () => void;
13
+ prefix?: ReactNode;
14
+ suffix?: ReactNode;
15
+ inputClassName?: string;
16
+ size?: 'sm' | 'md' | 'lg';
17
+ clearAriaLabel?: string;
18
+ }
19
+ >;
17
20
 
18
21
  export function PCInput({
19
22
  className = '',
@@ -26,6 +29,7 @@ export function PCInput({
26
29
  suffix,
27
30
  inputClassName = '',
28
31
  size = 'md',
32
+ clearAriaLabel = 'Clear input',
29
33
  value,
30
34
  onChange,
31
35
  ...props
@@ -101,7 +105,7 @@ export function PCInput({
101
105
  alignItems: 'center',
102
106
  color: pcStyles.textSecondary.color,
103
107
  }}
104
- aria-label="Clear input"
108
+ aria-label={clearAriaLabel}
105
109
  >
106
110
  <X size={16} />
107
111
  </button>
@@ -7,6 +7,7 @@ export interface PCLoaderProps {
7
7
  size?: 'sm' | 'md' | 'lg';
8
8
  color?: 'primary' | 'info';
9
9
  variant?: 'spinner';
10
+ ariaLabel?: string;
10
11
  }
11
12
 
12
13
  export function PCLoader({
@@ -14,7 +15,7 @@ export function PCLoader({
14
15
  style = {},
15
16
  size = 'md',
16
17
  color = 'primary',
17
- variant = 'spinner',
18
+ ariaLabel = 'Loading',
18
19
  }: PCLoaderProps) {
19
20
  const loaderStyle: CSSProperties = {
20
21
  ...pcStyles.loader,
@@ -26,5 +27,5 @@ export function PCLoader({
26
27
  ...style,
27
28
  };
28
29
 
29
- return <div className={className} style={loaderStyle} aria-label="Loading" role="status" />;
30
+ return <div className={className} style={loaderStyle} aria-label={ariaLabel} role="status" />;
30
31
  }
@@ -12,6 +12,7 @@ export interface PCModalProps {
12
12
  showCloseButton?: boolean;
13
13
  title?: ReactNode;
14
14
  footer?: ReactNode;
15
+ closeAriaLabel?: string;
15
16
  }
16
17
 
17
18
  export function PCModal({
@@ -24,6 +25,7 @@ export function PCModal({
24
25
  showCloseButton = true,
25
26
  title,
26
27
  footer,
28
+ closeAriaLabel = 'Close modal',
27
29
  }: PCModalProps) {
28
30
  useEffect(() => {
29
31
  if (isOpen) {
@@ -77,7 +79,7 @@ export function PCModal({
77
79
  className="pc-modal-close-button"
78
80
  style={pcStyles.modalCloseButton}
79
81
  onClick={onClose}
80
- aria-label="Close modal"
82
+ aria-label={closeAriaLabel}
81
83
  >
82
84
  <X size={20} />
83
85
  </button>
@@ -1,8 +1,6 @@
1
1
  import { type ReactNode, type CSSProperties, useState, useRef, useEffect } from 'react';
2
2
  import { pcStyles } from '../styles/pcStyles';
3
3
 
4
- const getVar = (varName: string): string => `var(${varName})`;
5
-
6
4
  export interface PCPopoverProps {
7
5
  content: ReactNode;
8
6
  children: ReactNode;
@@ -23,7 +23,7 @@ export interface PCSelectProps {
23
23
  className?: string;
24
24
  style?: CSSProperties;
25
25
  placeholder?: string;
26
- options: SelectOption[];
26
+ options: readonly SelectOption[];
27
27
  value: SelectOption | null;
28
28
  onChange?: (option: SelectOption | null) => void;
29
29
  onClear?: () => void;
@@ -37,6 +37,9 @@ export interface PCSelectProps {
37
37
  * Useful in tight filter rows where you want trigger + dropdown aligned.
38
38
  */
39
39
  dropdownMatchTriggerWidth?: boolean;
40
+ searchPlaceholder?: string;
41
+ noOptionsMessage?: string;
42
+ clearAriaLabel?: string;
40
43
  }
41
44
 
42
45
  export function PCSelect({
@@ -53,6 +56,9 @@ export function PCSelect({
53
56
  size = 'md',
54
57
  label,
55
58
  dropdownMatchTriggerWidth = false,
59
+ searchPlaceholder = 'Search...',
60
+ noOptionsMessage = 'No options found',
61
+ clearAriaLabel = 'Clear selection',
56
62
  }: PCSelectProps) {
57
63
  const [isOpen, setIsOpen] = useState(false);
58
64
  const [searchQuery, setSearchQuery] = useState('');
@@ -278,7 +284,7 @@ export function PCSelect({
278
284
  alignItems: 'center',
279
285
  color: pcStyles.textSecondary.color,
280
286
  }}
281
- aria-label="Clear selection"
287
+ aria-label={clearAriaLabel}
282
288
  >
283
289
  <X size={16} />
284
290
  </button>
@@ -322,7 +328,7 @@ export function PCSelect({
322
328
  ...pcStyles.inputSm,
323
329
  width: '100%',
324
330
  }}
325
- placeholder="Search..."
331
+ placeholder={searchPlaceholder}
326
332
  value={searchQuery}
327
333
  onChange={(e) => setSearchQuery(e.target.value)}
328
334
  onClick={(e) => e.stopPropagation()}
@@ -336,7 +342,7 @@ export function PCSelect({
336
342
  textAlign: 'center',
337
343
  backgroundColor: getVar('--pc-bg-primary'),
338
344
  }}>
339
- No options found
345
+ {noOptionsMessage}
340
346
  </div>
341
347
  ) : (
342
348
  filteredOptions.map((option) => (
@@ -1,4 +1,4 @@
1
- import { type ReactNode, type CSSProperties, type HTMLAttributes, createContext, useContext } from 'react';
1
+ import { type ReactNode, type CSSProperties, type HTMLAttributes, type TdHTMLAttributes, type ThHTMLAttributes, createContext } from 'react';
2
2
  import { pcStyles } from '../styles/pcStyles';
3
3
 
4
4
  interface TableContextValue {
@@ -8,12 +8,14 @@ interface TableContextValue {
8
8
  const TableContext = createContext<TableContextValue>({});
9
9
 
10
10
  // Main Table component
11
- export interface PCTableProps extends HTMLAttributes<HTMLTableElement> {
12
- children: ReactNode;
13
- variant?: 'modern' | 'minimal';
14
- className?: string;
15
- style?: CSSProperties;
16
- }
11
+ export type PCTableProps = Readonly<
12
+ HTMLAttributes<HTMLTableElement> & {
13
+ children: ReactNode;
14
+ variant?: 'modern' | 'minimal';
15
+ className?: string;
16
+ style?: CSSProperties;
17
+ }
18
+ >;
17
19
 
18
20
  export function PCTable({ children, variant = 'modern', className = '', style = {}, ...props }: PCTableProps) {
19
21
  const tableStyle: CSSProperties = {
@@ -31,11 +33,13 @@ export function PCTable({ children, variant = 'modern', className = '', style =
31
33
  }
32
34
 
33
35
  // Header component
34
- export interface PCTableHeaderProps extends HTMLAttributes<HTMLTableSectionElement> {
35
- children: ReactNode;
36
- className?: string;
37
- style?: CSSProperties;
38
- }
36
+ export type PCTableHeaderProps = Readonly<
37
+ HTMLAttributes<HTMLTableSectionElement> & {
38
+ children: ReactNode;
39
+ className?: string;
40
+ style?: CSSProperties;
41
+ }
42
+ >;
39
43
 
40
44
  export function PCTableHeader({ children, className = '', style = {}, ...props }: PCTableHeaderProps) {
41
45
  const headerStyle: CSSProperties = {
@@ -51,11 +55,13 @@ export function PCTableHeader({ children, className = '', style = {}, ...props }
51
55
  }
52
56
 
53
57
  // Body component
54
- export interface PCTableBodyProps extends HTMLAttributes<HTMLTableSectionElement> {
55
- children: ReactNode;
56
- className?: string;
57
- style?: CSSProperties;
58
- }
58
+ export type PCTableBodyProps = Readonly<
59
+ HTMLAttributes<HTMLTableSectionElement> & {
60
+ children: ReactNode;
61
+ className?: string;
62
+ style?: CSSProperties;
63
+ }
64
+ >;
59
65
 
60
66
  export function PCTableBody({ children, className = '', style = {}, ...props }: PCTableBodyProps) {
61
67
  const bodyStyle: CSSProperties = {
@@ -70,11 +76,13 @@ export function PCTableBody({ children, className = '', style = {}, ...props }:
70
76
  }
71
77
 
72
78
  // Row component
73
- export interface PCTableRowProps extends HTMLAttributes<HTMLTableRowElement> {
74
- children: ReactNode;
75
- className?: string;
76
- style?: CSSProperties;
77
- }
79
+ export type PCTableRowProps = Readonly<
80
+ HTMLAttributes<HTMLTableRowElement> & {
81
+ children: ReactNode;
82
+ className?: string;
83
+ style?: CSSProperties;
84
+ }
85
+ >;
78
86
 
79
87
  export function PCTableRow({ children, className = '', style = {}, ...props }: PCTableRowProps) {
80
88
  const rowStyle: CSSProperties = {
@@ -90,11 +98,13 @@ export function PCTableRow({ children, className = '', style = {}, ...props }: P
90
98
  }
91
99
 
92
100
  // Header Cell component
93
- export interface PCTableHeadProps extends HTMLAttributes<HTMLTableCellElement> {
94
- children: ReactNode;
95
- className?: string;
96
- style?: CSSProperties;
97
- }
101
+ export type PCTableHeadProps = Readonly<
102
+ ThHTMLAttributes<HTMLTableCellElement> & {
103
+ children: ReactNode;
104
+ className?: string;
105
+ style?: CSSProperties;
106
+ }
107
+ >;
98
108
 
99
109
  export function PCTableHead({ children, className = '', style = {}, ...props }: PCTableHeadProps) {
100
110
  const headStyle: CSSProperties = {
@@ -110,11 +120,13 @@ export function PCTableHead({ children, className = '', style = {}, ...props }:
110
120
  }
111
121
 
112
122
  // Cell component
113
- export interface PCTableCellProps extends HTMLAttributes<HTMLTableCellElement> {
114
- children: ReactNode;
115
- className?: string;
116
- style?: CSSProperties;
117
- }
123
+ export type PCTableCellProps = Readonly<
124
+ TdHTMLAttributes<HTMLTableCellElement> & {
125
+ children: ReactNode;
126
+ className?: string;
127
+ style?: CSSProperties;
128
+ }
129
+ >;
118
130
 
119
131
  export function PCTableCell({ children, className = '', style = {}, ...props }: PCTableCellProps) {
120
132
  const cellStyle: CSSProperties = {
@@ -1,7 +1,7 @@
1
1
  import { type ReactNode, type CSSProperties } from 'react';
2
2
  import { pcStyles } from '../styles/pcStyles';
3
3
 
4
- export interface PCTextProps {
4
+ export type PCTextProps = Readonly<{
5
5
  children: ReactNode;
6
6
  className?: string;
7
7
  style?: CSSProperties;
@@ -10,7 +10,8 @@ export interface PCTextProps {
10
10
  weight?: 'normal' | 'medium' | 'semibold' | 'bold';
11
11
  color?: 'primary' | 'secondary' | 'tertiary' | 'inverse' | 'disabled';
12
12
  align?: 'left' | 'center' | 'right';
13
- }
13
+ title?: string;
14
+ }>;
14
15
 
15
16
  export function PCText({
16
17
  children,
@@ -21,6 +22,7 @@ export function PCText({
21
22
  weight = 'normal',
22
23
  color = 'primary',
23
24
  align,
25
+ title,
24
26
  }: PCTextProps) {
25
27
  const baseStyle: CSSProperties = {
26
28
  ...pcStyles.text,
@@ -32,7 +34,7 @@ export function PCText({
32
34
  };
33
35
 
34
36
  return (
35
- <Component className={className} style={baseStyle}>
37
+ <Component className={className} style={baseStyle} title={title}>
36
38
  {children}
37
39
  </Component>
38
40
  );
@@ -4,7 +4,6 @@ type StatusBadgeProps = {
4
4
  status?: 'success' | 'warning' | 'error' | 'info' | 'pending' | string;
5
5
  children?: React.ReactNode;
6
6
  className?: string;
7
- variant?: 'filled' | 'outlined';
8
7
  };
9
8
 
10
9
  const predefinedStatusMap: Record<string, 'success' | 'warning' | 'error' | 'info' | 'pending'> = {
@@ -29,7 +28,6 @@ export default function StatusBadge({
29
28
  status = 'info',
30
29
  children,
31
30
  className,
32
- variant = 'filled',
33
31
  }: StatusBadgeProps) {
34
32
  // Check if it's a predefined status
35
33
  const normalizedStatus = status.toLowerCase();