@redacto.io/consent-sdk-react 3.4.0 → 3.6.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 (155) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +176 -0
  3. package/dist/index.d.mts +51 -4
  4. package/dist/index.d.ts +51 -4
  5. package/dist/index.js +1912 -345
  6. package/dist/index.mjs +1911 -345
  7. package/dist/privacy-center.d.mts +566 -0
  8. package/dist/privacy-center.d.ts +566 -0
  9. package/dist/privacy-center.js +17174 -0
  10. package/dist/privacy-center.mjs +17136 -0
  11. package/package.json +47 -3
  12. package/src/RedactoNoticeConsent/RedactoNoticeConsent.test.tsx +201 -118
  13. package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +1194 -93
  14. package/src/RedactoNoticeConsent/api/index.ts +337 -246
  15. package/src/RedactoNoticeConsent/api/types.ts +140 -41
  16. package/src/RedactoNoticeConsent/components/DigiLockerCallback.tsx +602 -0
  17. package/src/RedactoNoticeConsent/components/index.ts +7 -0
  18. package/src/RedactoNoticeConsent/injectStyles.ts +11 -0
  19. package/src/RedactoNoticeConsent/language-codes.ts +61 -0
  20. package/src/RedactoNoticeConsent/services/storage.ts +122 -0
  21. package/src/RedactoNoticeConsent/types.ts +2 -0
  22. package/src/RedactoNoticeConsentInline/api/index.ts +26 -64
  23. package/src/RedactoNoticeConsentInline/api/types.ts +0 -25
  24. package/src/RedactoPrivacyCenter/PrivacyCenterActivityPage.tsx +19 -0
  25. package/src/RedactoPrivacyCenter/PrivacyCenterConsentManagerPage.tsx +17 -0
  26. package/src/RedactoPrivacyCenter/PrivacyCenterFormPage.tsx +79 -0
  27. package/src/RedactoPrivacyCenter/PrivacyCenterHomePage.tsx +27 -0
  28. package/src/RedactoPrivacyCenter/PrivacyCenterLayout.tsx +142 -0
  29. package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +51 -0
  30. package/src/RedactoPrivacyCenter/api/actions.ts +444 -0
  31. package/src/RedactoPrivacyCenter/api/client.ts +413 -0
  32. package/src/RedactoPrivacyCenter/api/config.ts +33 -0
  33. package/src/RedactoPrivacyCenter/api/fetcher.ts +181 -0
  34. package/src/RedactoPrivacyCenter/api/upload.ts +93 -0
  35. package/src/RedactoPrivacyCenter/assets/character.svg +31 -0
  36. package/src/RedactoPrivacyCenter/assets/fileAttach.svg +9 -0
  37. package/src/RedactoPrivacyCenter/assets/greenTick.svg +4 -0
  38. package/src/RedactoPrivacyCenter/assets/mail.svg +3 -0
  39. package/src/RedactoPrivacyCenter/assets/poweredByRedacto.svg +9 -0
  40. package/src/RedactoPrivacyCenter/assets/sentImg.svg +9 -0
  41. package/src/RedactoPrivacyCenter/assets/uploadFileIcon.svg +9 -0
  42. package/src/RedactoPrivacyCenter/components/ActivitiesList.tsx +272 -0
  43. package/src/RedactoPrivacyCenter/components/CaseDetailsModal.tsx +468 -0
  44. package/src/RedactoPrivacyCenter/components/CaseHistory.tsx +433 -0
  45. package/src/RedactoPrivacyCenter/components/ConsentManager.tsx +726 -0
  46. package/src/RedactoPrivacyCenter/components/ConsentManagerColumns.tsx +239 -0
  47. package/src/RedactoPrivacyCenter/components/ConsentManagerConstants.ts +7 -0
  48. package/src/RedactoPrivacyCenter/components/ConsentManagerTableSkeleton.tsx +155 -0
  49. package/src/RedactoPrivacyCenter/components/DataRequest/CorrectionDataSection.tsx +189 -0
  50. package/src/RedactoPrivacyCenter/components/DataRequest/GrievanceDataSection.tsx +118 -0
  51. package/src/RedactoPrivacyCenter/components/DataRequest/NominationDataSection.tsx +66 -0
  52. package/src/RedactoPrivacyCenter/components/DataRequest/PurposeSelectionSection.tsx +305 -0
  53. package/src/RedactoPrivacyCenter/components/Form.tsx +1455 -0
  54. package/src/RedactoPrivacyCenter/components/GrievanceTable.tsx +176 -0
  55. package/src/RedactoPrivacyCenter/components/GrievanceTablePagination.tsx +330 -0
  56. package/src/RedactoPrivacyCenter/components/ModifyConsentModal.tsx +329 -0
  57. package/src/RedactoPrivacyCenter/components/Pagination.tsx +140 -0
  58. package/src/RedactoPrivacyCenter/components/PrivacyCenterLayout.tsx +302 -0
  59. package/src/RedactoPrivacyCenter/components/RequestSubmit.tsx +218 -0
  60. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/SideBarPC.tsx +475 -0
  61. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/SideMenuPC.tsx +412 -0
  62. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/constants.tsx +42 -0
  63. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/menuItemsPC.tsx +1 -0
  64. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/types.ts +40 -0
  65. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/utils.ts +38 -0
  66. package/src/RedactoPrivacyCenter/components/ThemeTransitionOverlay.tsx +85 -0
  67. package/src/RedactoPrivacyCenter/components/activitiesColumns.tsx +141 -0
  68. package/src/RedactoPrivacyCenter/components/caseHistoryColumns.tsx +179 -0
  69. package/src/RedactoPrivacyCenter/components/constant.ts +20 -0
  70. package/src/RedactoPrivacyCenter/components/types.ts +68 -0
  71. package/src/RedactoPrivacyCenter/components/utils.tsx +10 -0
  72. package/src/RedactoPrivacyCenter/config/routes.ts +9 -0
  73. package/src/RedactoPrivacyCenter/config/table.ts +25 -0
  74. package/src/RedactoPrivacyCenter/context/AuthContext.tsx +123 -0
  75. package/src/RedactoPrivacyCenter/context/BaseUrlContext.tsx +44 -0
  76. package/src/RedactoPrivacyCenter/context/LocaleContext.tsx +11 -0
  77. package/src/RedactoPrivacyCenter/context/NavigationContext.tsx +64 -0
  78. package/src/RedactoPrivacyCenter/context/OrganizationContext.tsx +30 -0
  79. package/src/RedactoPrivacyCenter/context/PageChromeContext.tsx +60 -0
  80. package/src/RedactoPrivacyCenter/context/theme.tsx +127 -0
  81. package/src/RedactoPrivacyCenter/lib/api.ts +468 -0
  82. package/src/RedactoPrivacyCenter/lib/consent-manager/utils.tsx +63 -0
  83. package/src/RedactoPrivacyCenter/lib/constants.ts +116 -0
  84. package/src/RedactoPrivacyCenter/lib/i18n.ts +81 -0
  85. package/src/RedactoPrivacyCenter/lib/locales.ts +105 -0
  86. package/src/RedactoPrivacyCenter/lib/queries.ts +30 -0
  87. package/src/RedactoPrivacyCenter/lib/types.ts +346 -0
  88. package/src/RedactoPrivacyCenter/lib/useCurrentLanguage.ts +37 -0
  89. package/src/RedactoPrivacyCenter/lib/utils.ts +625 -0
  90. package/src/RedactoPrivacyCenter/locales/as/translation.json +188 -0
  91. package/src/RedactoPrivacyCenter/locales/bho/translation.json +188 -0
  92. package/src/RedactoPrivacyCenter/locales/bn/translation.json +188 -0
  93. package/src/RedactoPrivacyCenter/locales/brx/translation.json +188 -0
  94. package/src/RedactoPrivacyCenter/locales/doi/translation.json +188 -0
  95. package/src/RedactoPrivacyCenter/locales/en/translation.json +188 -0
  96. package/src/RedactoPrivacyCenter/locales/gom/translation.json +188 -0
  97. package/src/RedactoPrivacyCenter/locales/gu/translation.json +188 -0
  98. package/src/RedactoPrivacyCenter/locales/hi/translation.json +188 -0
  99. package/src/RedactoPrivacyCenter/locales/kn/translation.json +188 -0
  100. package/src/RedactoPrivacyCenter/locales/ks/translation.json +188 -0
  101. package/src/RedactoPrivacyCenter/locales/mai/translation.json +188 -0
  102. package/src/RedactoPrivacyCenter/locales/ml/translation.json +188 -0
  103. package/src/RedactoPrivacyCenter/locales/mni-Mtei/translation.json +188 -0
  104. package/src/RedactoPrivacyCenter/locales/mr/translation.json +188 -0
  105. package/src/RedactoPrivacyCenter/locales/ne/translation.json +188 -0
  106. package/src/RedactoPrivacyCenter/locales/or/translation.json +188 -0
  107. package/src/RedactoPrivacyCenter/locales/pa/translation.json +188 -0
  108. package/src/RedactoPrivacyCenter/locales/sa/translation.json +188 -0
  109. package/src/RedactoPrivacyCenter/locales/sat/translation.json +188 -0
  110. package/src/RedactoPrivacyCenter/locales/sd/translation.json +188 -0
  111. package/src/RedactoPrivacyCenter/locales/ta/translation.json +188 -0
  112. package/src/RedactoPrivacyCenter/locales/te/translation.json +188 -0
  113. package/src/RedactoPrivacyCenter/locales/ur/translation.json +188 -0
  114. package/src/RedactoPrivacyCenter/styles/base.css +117 -0
  115. package/src/RedactoPrivacyCenter/styles/injectStyles.ts +1000 -0
  116. package/src/RedactoPrivacyCenter/styles/pcStyles.ts +819 -0
  117. package/src/RedactoPrivacyCenter/styles/responsive.ts +138 -0
  118. package/src/RedactoPrivacyCenter/styles/variables.css +133 -0
  119. package/src/RedactoPrivacyCenter/table/AdvancedTable.tsx +365 -0
  120. package/src/RedactoPrivacyCenter/table/AdvancedTablePagination.tsx +479 -0
  121. package/src/RedactoPrivacyCenter/table/index.ts +2 -0
  122. package/src/RedactoPrivacyCenter/types/images.d.ts +29 -0
  123. package/src/RedactoPrivacyCenter/ui/Footer.tsx +73 -0
  124. package/src/RedactoPrivacyCenter/ui/FormBlockWrapper.tsx +54 -0
  125. package/src/RedactoPrivacyCenter/ui/PCAccordion.tsx +87 -0
  126. package/src/RedactoPrivacyCenter/ui/PCActionIcon.tsx +47 -0
  127. package/src/RedactoPrivacyCenter/ui/PCAvatar.tsx +69 -0
  128. package/src/RedactoPrivacyCenter/ui/PCBadge.tsx +48 -0
  129. package/src/RedactoPrivacyCenter/ui/PCButton.tsx +77 -0
  130. package/src/RedactoPrivacyCenter/ui/PCCheckbox.tsx +55 -0
  131. package/src/RedactoPrivacyCenter/ui/PCCollapse.tsx +97 -0
  132. package/src/RedactoPrivacyCenter/ui/PCEmpty.tsx +35 -0
  133. package/src/RedactoPrivacyCenter/ui/PCInput.tsx +128 -0
  134. package/src/RedactoPrivacyCenter/ui/PCLoader.tsx +30 -0
  135. package/src/RedactoPrivacyCenter/ui/PCModal.tsx +104 -0
  136. package/src/RedactoPrivacyCenter/ui/PCPopover.tsx +175 -0
  137. package/src/RedactoPrivacyCenter/ui/PCSelect.tsx +381 -0
  138. package/src/RedactoPrivacyCenter/ui/PCTable.tsx +137 -0
  139. package/src/RedactoPrivacyCenter/ui/PCText.tsx +39 -0
  140. package/src/RedactoPrivacyCenter/ui/PCTextarea.tsx +43 -0
  141. package/src/RedactoPrivacyCenter/ui/PCTitle.tsx +37 -0
  142. package/src/RedactoPrivacyCenter/ui/PCTooltip.tsx +119 -0
  143. package/src/RedactoPrivacyCenter/ui/SimpleBar.tsx +25 -0
  144. package/src/RedactoPrivacyCenter/ui/StatusBadge.tsx +55 -0
  145. package/src/RedactoPrivacyCenter/ui/ThemeToggle.tsx +70 -0
  146. package/src/RedactoPrivacyCenter/ui/index.ts +18 -0
  147. package/src/RedactoPrivacyCenter/utils/cn.ts +28 -0
  148. package/src/RedactoPrivacyCenter/utils/date.ts +48 -0
  149. package/src/RedactoPrivacyCenter/utils/status.ts +111 -0
  150. package/src/RedactoPrivacyCenter/utils/toast.ts +130 -0
  151. package/src/index.ts +10 -0
  152. package/src/privacy-center.ts +107 -0
  153. package/tsconfig.json +2 -0
  154. package/tsup.config.ts +16 -1
  155. package/src/utils/isLegacyApi.ts +0 -12
@@ -0,0 +1,87 @@
1
+ import { type ReactNode, type CSSProperties, type HTMLAttributes } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
3
+
4
+ export interface PCAccordionProps extends HTMLAttributes<HTMLDivElement> {
5
+ children: ReactNode;
6
+ className?: string;
7
+ style?: CSSProperties;
8
+ }
9
+
10
+ export function PCAccordion({ children, className = '', style = {}, ...props }: PCAccordionProps) {
11
+ const accordionStyle: CSSProperties = {
12
+ ...pcStyles.accordion,
13
+ ...style,
14
+ };
15
+
16
+ return (
17
+ <div className={`pc-accordion ${className}`} style={accordionStyle} {...props}>
18
+ {children}
19
+ </div>
20
+ );
21
+ }
22
+
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
+ }
30
+
31
+ export function PCAccordionHeader({
32
+ children,
33
+ className = '',
34
+ style = {},
35
+ open = false,
36
+ onToggle,
37
+ ...props
38
+ }: PCAccordionHeaderProps) {
39
+ const headerStyle: CSSProperties = {
40
+ ...pcStyles.accordionHeader,
41
+ ...style,
42
+ };
43
+
44
+ return (
45
+ <div
46
+ className={`pc-accordion-header ${className}`}
47
+ style={headerStyle}
48
+ onClick={onToggle}
49
+ {...props}
50
+ >
51
+ {typeof children === 'function' ? children({ open, toggle: onToggle || (() => {}) }) : children}
52
+ </div>
53
+ );
54
+ }
55
+
56
+ export interface PCAccordionBodyProps extends HTMLAttributes<HTMLDivElement> {
57
+ children: ReactNode;
58
+ className?: string;
59
+ style?: CSSProperties;
60
+ open?: boolean;
61
+ }
62
+
63
+ export function PCAccordionBody({
64
+ children,
65
+ className = '',
66
+ style = {},
67
+ open = false,
68
+ ...props
69
+ }: PCAccordionBodyProps) {
70
+ const bodyStyle: CSSProperties = {
71
+ ...pcStyles.accordionBody,
72
+ maxHeight: open ? '1000px' : '0',
73
+ overflow: open ? 'visible' : 'hidden',
74
+ padding: open ? pcStyles.accordionBody.padding : '0',
75
+ ...style,
76
+ };
77
+
78
+ return (
79
+ <div className={`pc-accordion-body ${className}`} style={bodyStyle} {...props}>
80
+ {children}
81
+ </div>
82
+ );
83
+ }
84
+
85
+ // Compound component pattern
86
+ PCAccordion.Header = PCAccordionHeader;
87
+ PCAccordion.Body = PCAccordionBody;
@@ -0,0 +1,47 @@
1
+ import { type ReactNode, type CSSProperties, type ButtonHTMLAttributes, forwardRef } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
3
+
4
+ export interface PCActionIconProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'style'> {
5
+ children: ReactNode;
6
+ className?: string;
7
+ style?: CSSProperties;
8
+ variant?: 'default' | 'outline';
9
+ size?: 'sm' | 'md';
10
+ disabled?: boolean;
11
+ 'aria-label': string;
12
+ }
13
+
14
+ export const PCActionIcon = forwardRef<HTMLButtonElement, PCActionIconProps>(({
15
+ children,
16
+ className = '',
17
+ style = {},
18
+ variant = 'default',
19
+ size = 'md',
20
+ disabled = false,
21
+ type = 'button',
22
+ ...props
23
+ }, ref) => {
24
+ const baseStyle: CSSProperties = {
25
+ ...pcStyles.actionIcon,
26
+ ...(variant === 'outline' && pcStyles.actionIconOutline),
27
+ ...(size === 'sm' && pcStyles.actionIconSm),
28
+ ...(size === 'md' && pcStyles.actionIconMd),
29
+ ...(disabled && pcStyles.actionIconDisabled),
30
+ ...style,
31
+ };
32
+
33
+ return (
34
+ <button
35
+ ref={ref}
36
+ type={type}
37
+ className={`pc-action-icon ${className}`}
38
+ style={baseStyle}
39
+ disabled={disabled}
40
+ {...props}
41
+ >
42
+ {children}
43
+ </button>
44
+ );
45
+ });
46
+
47
+ PCActionIcon.displayName = 'PCActionIcon';
@@ -0,0 +1,69 @@
1
+ import { type CSSProperties } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
3
+
4
+ export interface PCAvatarProps {
5
+ name?: string;
6
+ src?: string;
7
+ className?: string;
8
+ style?: CSSProperties;
9
+ size?: 'sm' | 'md' | 'lg';
10
+ color?: 'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info';
11
+ }
12
+
13
+ function getInitials(name: string): string {
14
+ return name
15
+ .split(' ')
16
+ .map((n) => n[0])
17
+ .join('')
18
+ .toUpperCase()
19
+ .slice(0, 2);
20
+ }
21
+
22
+ function getColor(color: string): string {
23
+ const colorMap: Record<string, string> = {
24
+ primary: getVar('--pc-primary'),
25
+ secondary: getVar('--pc-secondary'),
26
+ success: getVar('--pc-success'),
27
+ error: getVar('--pc-error'),
28
+ warning: getVar('--pc-warning'),
29
+ info: getVar('--pc-info'),
30
+ };
31
+ return colorMap[color] || colorMap.primary;
32
+ }
33
+
34
+ const getVar = (varName: string): string => `var(${varName})`;
35
+
36
+ export function PCAvatar({
37
+ name = '',
38
+ src,
39
+ className = '',
40
+ style = {},
41
+ size = 'md',
42
+ color = 'primary',
43
+ }: PCAvatarProps) {
44
+ const avatarStyle: CSSProperties = {
45
+ ...pcStyles.avatar,
46
+ ...(size === 'sm' && pcStyles.avatarSm),
47
+ ...(size === 'md' && pcStyles.avatarMd),
48
+ ...(size === 'lg' && pcStyles.avatarLg),
49
+ backgroundColor: getColor(color),
50
+ ...style,
51
+ };
52
+
53
+ if (src) {
54
+ return (
55
+ <img
56
+ src={src}
57
+ alt={name}
58
+ className={className}
59
+ style={avatarStyle}
60
+ />
61
+ );
62
+ }
63
+
64
+ return (
65
+ <div className={className} style={avatarStyle}>
66
+ {name ? getInitials(name) : '?'}
67
+ </div>
68
+ );
69
+ }
@@ -0,0 +1,48 @@
1
+ import { type ReactNode, type CSSProperties } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
3
+
4
+ export interface PCBadgeProps {
5
+ children: ReactNode;
6
+ className?: string;
7
+ style?: CSSProperties;
8
+ variant?: 'success' | 'error' | 'warning' | 'info' | 'secondary';
9
+ size?: 'sm' | 'md';
10
+ renderAsDot?: boolean;
11
+ }
12
+
13
+ export function PCBadge({
14
+ children,
15
+ className = '',
16
+ style = {},
17
+ variant = 'secondary',
18
+ size = 'md',
19
+ renderAsDot = false,
20
+ }: PCBadgeProps) {
21
+ const badgeStyle: CSSProperties = {
22
+ ...pcStyles.badge,
23
+ ...(variant === 'success' && pcStyles.badgeSuccess),
24
+ ...(variant === 'error' && pcStyles.badgeError),
25
+ ...(variant === 'warning' && pcStyles.badgeWarning),
26
+ ...(variant === 'info' && pcStyles.badgeInfo),
27
+ ...(variant === 'secondary' && pcStyles.badgeSecondary),
28
+ ...(size === 'sm' && pcStyles.badgeSm),
29
+ ...(renderAsDot && {
30
+ width: size === 'sm' ? '6px' : '8px',
31
+ height: size === 'sm' ? '6px' : '8px',
32
+ padding: 0,
33
+ borderRadius: '50%',
34
+ display: 'inline-block',
35
+ }),
36
+ ...style,
37
+ };
38
+
39
+ if (renderAsDot) {
40
+ return <span className={className} style={badgeStyle} />;
41
+ }
42
+
43
+ return (
44
+ <span className={className} style={badgeStyle}>
45
+ {children}
46
+ </span>
47
+ );
48
+ }
@@ -0,0 +1,77 @@
1
+ import { type ReactNode, type CSSProperties, type ButtonHTMLAttributes } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
3
+
4
+ const getVar = (varName: string): string => `var(${varName})`;
5
+
6
+ export interface PCButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'style'> {
7
+ children: ReactNode;
8
+ className?: string;
9
+ style?: CSSProperties;
10
+ variant?: 'primary' | 'secondary' | 'outline' | 'text' | 'danger';
11
+ size?: 'sm' | 'md' | 'lg';
12
+ isLoading?: boolean;
13
+ disabled?: boolean;
14
+ }
15
+
16
+ export function PCButton({
17
+ children,
18
+ className = '',
19
+ style = {},
20
+ variant = 'primary',
21
+ size = 'md',
22
+ isLoading = false,
23
+ disabled = false,
24
+ type = 'button',
25
+ ...props
26
+ }: PCButtonProps) {
27
+ const variantClass = `pc-button-${variant}`;
28
+ const baseStyle: CSSProperties = {
29
+ ...pcStyles.button,
30
+ ...(variant === 'primary' && pcStyles.buttonPrimary),
31
+ ...(variant === 'secondary' && pcStyles.buttonSecondary),
32
+ ...(variant === 'outline' && pcStyles.buttonOutline),
33
+ ...(variant === 'text' && pcStyles.buttonText),
34
+ ...(variant === 'danger' && pcStyles.buttonDanger),
35
+ ...(size === 'sm' && pcStyles.buttonSm),
36
+ ...(size === 'lg' && pcStyles.buttonLg),
37
+ ...(disabled && pcStyles.buttonDisabled),
38
+ ...style,
39
+ };
40
+
41
+ // Determine loader color based on variant
42
+ const loaderColor = variant === 'primary' || variant === 'danger' || variant === 'secondary'
43
+ ? 'inverse'
44
+ : 'primary';
45
+
46
+ return (
47
+ <button
48
+ type={type}
49
+ className={`pc-button ${variantClass} ${className}`}
50
+ style={baseStyle}
51
+ disabled={disabled || isLoading}
52
+ {...props}
53
+ >
54
+ {isLoading ? (
55
+ <span style={{
56
+ display: 'inline-flex',
57
+ alignItems: 'center',
58
+ justifyContent: 'center',
59
+ gap: '6px',
60
+ }}>
61
+ <div style={{
62
+ ...pcStyles.loader,
63
+ ...pcStyles.loaderMd,
64
+ ...(loaderColor === 'inverse'
65
+ ? { borderColor: `${getVar('--pc-text-inverse')} transparent ${getVar('--pc-text-inverse')} transparent` }
66
+ : pcStyles.loaderPrimary
67
+ ),
68
+ }} />
69
+ {children}
70
+ </span>
71
+ ) : (
72
+ children
73
+ )}
74
+ </button>
75
+ );
76
+ }
77
+
@@ -0,0 +1,55 @@
1
+ import { type ReactNode, type CSSProperties, type InputHTMLAttributes } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
3
+
4
+ export interface PCCheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'style' | 'size' | 'type'> {
5
+ className?: string;
6
+ style?: CSSProperties;
7
+ label?: ReactNode;
8
+ labelClassName?: string;
9
+ size?: 'sm' | 'md';
10
+ checked?: boolean;
11
+ onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
12
+ }
13
+
14
+ export function PCCheckbox({
15
+ className = '',
16
+ style = {},
17
+ label,
18
+ labelClassName = '',
19
+ size = 'md',
20
+ checked,
21
+ onChange,
22
+ ...props
23
+ }: PCCheckboxProps) {
24
+ const checkboxStyle: CSSProperties = {
25
+ ...pcStyles.checkbox,
26
+ ...(size === 'sm' && pcStyles.checkboxSm),
27
+ ...style,
28
+ };
29
+
30
+ const labelStyle: CSSProperties = {
31
+ ...pcStyles.checkboxLabel,
32
+ };
33
+
34
+ const checkbox = (
35
+ <input
36
+ type="checkbox"
37
+ className={`pc-checkbox ${size === 'sm' ? 'pc-checkbox-sm' : ''} ${className}`}
38
+ style={checkboxStyle}
39
+ checked={checked}
40
+ onChange={onChange}
41
+ {...props}
42
+ />
43
+ );
44
+
45
+ if (label) {
46
+ return (
47
+ <label className={labelClassName} style={labelStyle}>
48
+ {checkbox}
49
+ <span>{label}</span>
50
+ </label>
51
+ );
52
+ }
53
+
54
+ return checkbox;
55
+ }
@@ -0,0 +1,97 @@
1
+ import { type ReactNode, type CSSProperties, type HTMLAttributes, useState } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
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
+ }
10
+
11
+ export function PCCollapse({
12
+ children,
13
+ defaultOpen = false,
14
+ className = '',
15
+ style = {},
16
+ ...props
17
+ }: PCCollapseProps) {
18
+ const [open, setOpen] = useState(defaultOpen);
19
+
20
+ const toggle = () => setOpen(!open);
21
+
22
+ const collapseStyle: CSSProperties = {
23
+ ...style,
24
+ };
25
+
26
+ return (
27
+ <div className={`pc-collapse ${className}`} style={collapseStyle} {...props}>
28
+ {typeof children === 'function' ? children({ open, toggle }) : children}
29
+ </div>
30
+ );
31
+ }
32
+
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
+ }
40
+
41
+ export function PCCollapseHeader({
42
+ children,
43
+ className = '',
44
+ style = {},
45
+ open = false,
46
+ toggle,
47
+ ...props
48
+ }: PCCollapseHeaderProps) {
49
+ const headerStyle: CSSProperties = {
50
+ ...pcStyles.accordionHeader,
51
+ ...style,
52
+ };
53
+
54
+ return (
55
+ <div
56
+ className={`pc-collapse-header ${className}`}
57
+ style={headerStyle}
58
+ onClick={toggle}
59
+ {...props}
60
+ >
61
+ {typeof children === 'function' && toggle ? children({ open, toggle }) : children}
62
+ </div>
63
+ );
64
+ }
65
+
66
+ export interface PCCollapseBodyProps extends HTMLAttributes<HTMLDivElement> {
67
+ children: ReactNode;
68
+ className?: string;
69
+ style?: CSSProperties;
70
+ open?: boolean;
71
+ }
72
+
73
+ export function PCCollapseBody({
74
+ children,
75
+ className = '',
76
+ style = {},
77
+ open = false,
78
+ ...props
79
+ }: PCCollapseBodyProps) {
80
+ const bodyStyle: CSSProperties = {
81
+ ...pcStyles.accordionBody,
82
+ maxHeight: open ? '1000px' : '0',
83
+ overflow: open ? 'visible' : 'hidden',
84
+ padding: open ? pcStyles.accordionBody.padding : '0',
85
+ ...style,
86
+ };
87
+
88
+ return (
89
+ <div className={`pc-collapse-body ${className}`} style={bodyStyle} {...props}>
90
+ {children}
91
+ </div>
92
+ );
93
+ }
94
+
95
+ // Compound component pattern
96
+ PCCollapse.Header = PCCollapseHeader;
97
+ PCCollapse.Body = PCCollapseBody;
@@ -0,0 +1,35 @@
1
+ import { type ReactNode, type CSSProperties } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
3
+
4
+ export interface PCEmptyProps {
5
+ icon?: ReactNode;
6
+ title?: ReactNode;
7
+ description?: ReactNode;
8
+ className?: string;
9
+ style?: CSSProperties;
10
+ }
11
+
12
+ export function PCEmpty({
13
+ icon,
14
+ title,
15
+ description,
16
+ className = '',
17
+ style = {},
18
+ }: PCEmptyProps) {
19
+ const emptyStyle: CSSProperties = {
20
+ ...pcStyles.empty,
21
+ ...style,
22
+ };
23
+
24
+ return (
25
+ <div className={`pc-empty ${className}`} style={emptyStyle}>
26
+ {icon && <div style={pcStyles.emptyIcon}>{icon}</div>}
27
+ {title && (
28
+ <div style={{ ...pcStyles.emptyText, fontWeight: pcStyles.fontWeightSemibold.fontWeight, marginBottom: pcStyles.gapSm.gap }}>
29
+ {title}
30
+ </div>
31
+ )}
32
+ {description && <div style={pcStyles.emptyText}>{description}</div>}
33
+ </div>
34
+ );
35
+ }
@@ -0,0 +1,128 @@
1
+ import { type ReactNode, type CSSProperties, type InputHTMLAttributes, useState, useRef, useEffect } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
3
+ import { X } from 'lucide-react';
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
+ }
17
+
18
+ export function PCInput({
19
+ className = '',
20
+ style = {},
21
+ label,
22
+ error = false,
23
+ clearable = false,
24
+ onClear,
25
+ prefix,
26
+ suffix,
27
+ inputClassName = '',
28
+ size = 'md',
29
+ value,
30
+ onChange,
31
+ ...props
32
+ }: PCInputProps) {
33
+ const [showClear, setShowClear] = useState(false);
34
+ const inputRef = useRef<HTMLInputElement>(null);
35
+
36
+ useEffect(() => {
37
+ if (clearable && value && String(value).length > 0) {
38
+ setShowClear(true);
39
+ } else {
40
+ setShowClear(false);
41
+ }
42
+ }, [value, clearable]);
43
+
44
+ const handleClear = () => {
45
+ if (inputRef.current) {
46
+ const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
47
+ window.HTMLInputElement.prototype,
48
+ 'value'
49
+ )?.set;
50
+ nativeInputValueSetter?.call(inputRef.current, '');
51
+ const ev = new Event('input', { bubbles: true });
52
+ inputRef.current.dispatchEvent(ev);
53
+ }
54
+ onClear?.();
55
+ };
56
+
57
+ const inputStyle: CSSProperties = {
58
+ ...pcStyles.input,
59
+ ...(size === 'sm' && pcStyles.inputSm),
60
+ ...(size === 'lg' && pcStyles.inputLg),
61
+ ...(error && pcStyles.inputError),
62
+ ...(props.disabled && pcStyles.inputDisabled),
63
+ };
64
+
65
+ const wrapperStyle: CSSProperties = {
66
+ ...pcStyles.inputWrapper,
67
+ ...style,
68
+ };
69
+
70
+ if (prefix || suffix || clearable) {
71
+ return (
72
+ <div className={className} style={wrapperStyle}>
73
+ {label && <label style={pcStyles.inputLabel}>{label}</label>}
74
+ <div style={pcStyles.inputWithPrefix}>
75
+ {prefix && <span style={pcStyles.inputPrefix}>{prefix}</span>}
76
+ <input
77
+ ref={inputRef}
78
+ className={`pc-input ${inputClassName}`}
79
+ style={{
80
+ ...inputStyle,
81
+ border: 'none',
82
+ flex: 1,
83
+ paddingLeft: prefix ? 0 : undefined,
84
+ paddingRight: (suffix || showClear) ? 0 : undefined,
85
+ }}
86
+ value={value}
87
+ onChange={onChange}
88
+ {...props}
89
+ />
90
+ {showClear && (
91
+ <button
92
+ type="button"
93
+ onClick={handleClear}
94
+ style={{
95
+ ...pcStyles.actionIcon,
96
+ padding: '0.25rem',
97
+ background: 'none',
98
+ border: 'none',
99
+ cursor: 'pointer',
100
+ display: 'flex',
101
+ alignItems: 'center',
102
+ color: pcStyles.textSecondary.color,
103
+ }}
104
+ aria-label="Clear input"
105
+ >
106
+ <X size={16} />
107
+ </button>
108
+ )}
109
+ {suffix && <span style={pcStyles.inputSuffix}>{suffix}</span>}
110
+ </div>
111
+ </div>
112
+ );
113
+ }
114
+
115
+ return (
116
+ <div className={className} style={wrapperStyle}>
117
+ {label && <label style={pcStyles.inputLabel}>{label}</label>}
118
+ <input
119
+ ref={inputRef}
120
+ className={`pc-input ${inputClassName}`}
121
+ style={inputStyle}
122
+ value={value}
123
+ onChange={onChange}
124
+ {...props}
125
+ />
126
+ </div>
127
+ );
128
+ }
@@ -0,0 +1,30 @@
1
+ import { type CSSProperties } from 'react';
2
+ import { pcStyles } from '../styles/pcStyles';
3
+
4
+ export interface PCLoaderProps {
5
+ className?: string;
6
+ style?: CSSProperties;
7
+ size?: 'sm' | 'md' | 'lg';
8
+ color?: 'primary' | 'info';
9
+ variant?: 'spinner';
10
+ }
11
+
12
+ export function PCLoader({
13
+ className = '',
14
+ style = {},
15
+ size = 'md',
16
+ color = 'primary',
17
+ variant = 'spinner',
18
+ }: PCLoaderProps) {
19
+ const loaderStyle: CSSProperties = {
20
+ ...pcStyles.loader,
21
+ ...(size === 'sm' && pcStyles.loaderSm),
22
+ ...(size === 'md' && pcStyles.loaderMd),
23
+ ...(size === 'lg' && pcStyles.loaderLg),
24
+ ...(color === 'primary' && pcStyles.loaderPrimary),
25
+ ...(color === 'info' && pcStyles.loaderInfo),
26
+ ...style,
27
+ };
28
+
29
+ return <div className={className} style={loaderStyle} aria-label="Loading" role="status" />;
30
+ }