@consilioweb/payload-support 5.0.0 → 6.0.1

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 (120) hide show
  1. package/README.md +249 -22
  2. package/dist/components/RichTextEditor/index.js +1 -1
  3. package/dist/components/TicketConversation/RewriteDropdown.js +1 -1
  4. package/dist/components/TicketConversation/components/AISummaryPanel.js +3 -0
  5. package/dist/components/TicketConversation/components/ActionPanels.js +13 -8
  6. package/dist/components/TicketConversation/components/ClientHistory.js +1 -0
  7. package/dist/components/TicketConversation/components/CodeBlock.js +1 -0
  8. package/dist/components/TicketConversation/components/CodeBlockInserter.js +1 -1
  9. package/dist/components/TicketConversation/components/QuickActions.js +10 -8
  10. package/dist/components/TicketConversation/components/TicketHeader.js +2 -0
  11. package/dist/components/TicketConversation/components/TimeTrackingPanel.js +15 -9
  12. package/dist/components/TicketConversation/index.d.ts +10 -0
  13. package/dist/components/TicketConversation/index.js +25 -7
  14. package/dist/index.cjs +306 -60
  15. package/dist/index.d.cts +107 -38
  16. package/dist/index.d.ts +107 -38
  17. package/dist/index.js +300 -59
  18. package/dist/styles/BillingView.module.scss +11 -11
  19. package/dist/styles/ChatView.module.scss +7 -7
  20. package/dist/styles/CommandPalette.module.scss +1 -1
  21. package/dist/styles/CrmView.module.scss +9 -9
  22. package/dist/styles/EmailTracking.module.scss +6 -6
  23. package/dist/styles/ImportConversation.module.scss +5 -5
  24. package/dist/styles/Logs.module.scss +5 -5
  25. package/dist/styles/NewTicket.module.scss +2 -2
  26. package/dist/styles/PendingEmails.module.scss +13 -13
  27. package/dist/styles/SupportDashboard.module.scss +24 -8
  28. package/dist/styles/TicketDetail.module.scss +20 -20
  29. package/dist/styles/TicketInbox.module.scss +6 -6
  30. package/dist/styles/TicketingSettings.module.scss +10 -10
  31. package/dist/styles/TimeDashboard.module.scss +6 -6
  32. package/dist/styles/_tokens.scss +3 -1
  33. package/dist/utils/db.js +20 -0
  34. package/dist/utils/readSettings.js +150 -0
  35. package/dist/views/BillingView/client.js +15 -8
  36. package/dist/views/ChatView/client.js +2 -0
  37. package/dist/views/CrmView/client.js +2 -0
  38. package/dist/views/EmailTrackingView/client.js +23 -11
  39. package/dist/views/ImportConversationView/client.js +1 -0
  40. package/dist/views/LogsView/client.js +1 -1
  41. package/dist/views/NewTicketView/client.js +20 -13
  42. package/dist/views/PendingEmailsView/client.js +9 -3
  43. package/dist/views/SupportDashboardView/client.js +17 -19
  44. package/dist/views/TicketDetailView/client.js +23 -11
  45. package/dist/views/TicketInboxView/client.js +52 -26
  46. package/dist/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
  47. package/dist/views/TicketingSettingsView/client.js +44 -26
  48. package/dist/views/TimeDashboardView/client.js +10 -7
  49. package/dist/views/shared/ErrorBoundary.d.ts +36 -1
  50. package/dist/views/shared/ErrorBoundary.js +59 -28
  51. package/dist/views/shared/adminTokens.d.ts +15 -5
  52. package/dist/views/shared/adminTokens.js +23 -7
  53. package/dist/views/shared/icons.d.ts +49 -0
  54. package/dist/views/shared/icons.js +92 -0
  55. package/dist/views/shared/locales/en.json +15 -1
  56. package/dist/views/shared/locales/fr.json +15 -1
  57. package/package.json +9 -4
  58. package/scripts/copy-subpath-types.mjs +103 -0
  59. package/scripts/uninstall-data.mjs +178 -0
  60. package/scripts/uninstall.mjs +184 -0
  61. package/scripts/verify-dist-imports.mjs +84 -0
  62. package/src/collections/Tickets.ts +7 -0
  63. package/src/collections/TimeEntries.ts +11 -3
  64. package/src/components/RichTextEditor/index.tsx +1 -1
  65. package/src/components/TicketConversation/RewriteDropdown.tsx +1 -1
  66. package/src/components/TicketConversation/components/AISummaryPanel.tsx +3 -0
  67. package/src/components/TicketConversation/components/ActionPanels.tsx +13 -8
  68. package/src/components/TicketConversation/components/ClientHistory.tsx +1 -0
  69. package/src/components/TicketConversation/components/CodeBlock.tsx +1 -0
  70. package/src/components/TicketConversation/components/CodeBlockInserter.tsx +1 -1
  71. package/src/components/TicketConversation/components/QuickActions.tsx +10 -8
  72. package/src/components/TicketConversation/components/TicketHeader.tsx +2 -0
  73. package/src/components/TicketConversation/components/TimeTrackingPanel.tsx +17 -9
  74. package/src/components/TicketConversation/index.tsx +41 -7
  75. package/src/endpoints/delete-account.ts +191 -47
  76. package/src/endpoints/export-data.ts +104 -4
  77. package/src/endpoints/purge-logs.ts +6 -15
  78. package/src/index.ts +2 -0
  79. package/src/plugin.ts +51 -1
  80. package/src/portal/LiveChat.tsx +1 -1
  81. package/src/portal/auth/profile/page.tsx +3 -2
  82. package/src/portal/icons.tsx +91 -0
  83. package/src/styles/BillingView.module.scss +11 -11
  84. package/src/styles/ChatView.module.scss +7 -7
  85. package/src/styles/CommandPalette.module.scss +1 -1
  86. package/src/styles/CrmView.module.scss +9 -9
  87. package/src/styles/EmailTracking.module.scss +6 -6
  88. package/src/styles/ImportConversation.module.scss +5 -5
  89. package/src/styles/Logs.module.scss +5 -5
  90. package/src/styles/NewTicket.module.scss +2 -2
  91. package/src/styles/PendingEmails.module.scss +13 -13
  92. package/src/styles/SupportDashboard.module.scss +24 -8
  93. package/src/styles/TicketDetail.module.scss +20 -20
  94. package/src/styles/TicketInbox.module.scss +6 -6
  95. package/src/styles/TicketingSettings.module.scss +10 -10
  96. package/src/styles/TimeDashboard.module.scss +6 -6
  97. package/src/styles/_tokens.scss +3 -1
  98. package/src/types.ts +20 -0
  99. package/src/utils/retention.ts +111 -0
  100. package/src/utils/slugs.ts +15 -0
  101. package/src/views/BillingView/client.tsx +17 -8
  102. package/src/views/ChatView/client.tsx +2 -0
  103. package/src/views/CrmView/client.tsx +2 -0
  104. package/src/views/EmailTrackingView/client.tsx +18 -7
  105. package/src/views/ImportConversationView/client.tsx +1 -0
  106. package/src/views/LogsView/client.tsx +1 -1
  107. package/src/views/NewTicketView/client.tsx +22 -13
  108. package/src/views/PendingEmailsView/client.tsx +9 -3
  109. package/src/views/SupportDashboardView/client.tsx +11 -5
  110. package/src/views/TicketDetailView/client.tsx +25 -11
  111. package/src/views/TicketInboxView/client.tsx +47 -7
  112. package/src/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
  113. package/src/views/TicketingSettingsView/client.tsx +201 -144
  114. package/src/views/TimeDashboardView/client.tsx +10 -7
  115. package/src/views/shared/ErrorBoundary.tsx +95 -31
  116. package/src/views/shared/adminTokens.ts +28 -11
  117. package/src/views/shared/icons.tsx +146 -0
  118. package/src/views/shared/locales/en.json +15 -1
  119. package/src/views/shared/locales/fr.json +15 -1
  120. package/src/types/lucide-react.d.ts +0 -42
@@ -1,25 +1,100 @@
1
1
  'use client'
2
2
 
3
3
  import React from 'react'
4
+ import { useTranslation } from '../../components/TicketConversation/hooks/useTranslation'
4
5
 
5
6
  interface ErrorBoundaryProps {
6
7
  children: React.ReactNode
7
8
  fallback?: React.ReactNode
8
9
  viewName?: string
10
+ /**
11
+ * Values that identify the input the subtree renders from (a ticket id, a
12
+ * filter, a page number...). When any of them changes the boundary clears
13
+ * the error on its own, because the new input may well render fine.
14
+ */
15
+ resetKeys?: unknown[]
9
16
  }
10
17
 
11
18
  interface ErrorBoundaryState {
12
19
  hasError: boolean
13
20
  error: Error | null
21
+ /**
22
+ * Bumped on every reset. It is used as the `key` of the wrapper around the
23
+ * children so that a retry REMOUNTS the subtree. Clearing `hasError` alone
24
+ * keeps the broken component instance and its state, so anything that threw
25
+ * from a bad piece of state throws again on the very next render.
26
+ */
27
+ resetCount: number
28
+ }
29
+
30
+ /**
31
+ * Shallow comparison of two reset-key arrays. A missing array is treated as
32
+ * empty, so a boundary declared without `resetKeys` never auto-resets.
33
+ */
34
+ export function haveResetKeysChanged(previous?: unknown[], next?: unknown[]): boolean {
35
+ const a = previous ?? []
36
+ const b = next ?? []
37
+
38
+ if (a.length !== b.length) return true
39
+ return a.some((value, index) => !Object.is(value, b[index]))
40
+ }
41
+
42
+ /**
43
+ * Default fallback UI.
44
+ *
45
+ * Exported so it can be rendered (and asserted on) in isolation. It is the
46
+ * only screen a user sees when a view is broken, so it must stay readable in
47
+ * both themes: every colour comes from a Payload theme token, never a hex
48
+ * literal that only works on a light background.
49
+ *
50
+ * The thrown message is deliberately NOT displayed — it can carry a stack
51
+ * fragment, an internal path or a raw API payload. It is logged to the console
52
+ * by `componentDidCatch` instead.
53
+ */
54
+ export function AdminErrorFallback({ onRetry }: { onRetry: () => void }): React.ReactElement {
55
+ const { t } = useTranslation()
56
+
57
+ return (
58
+ <div
59
+ role="alert"
60
+ style={{
61
+ padding: '40px',
62
+ textAlign: 'center',
63
+ color: 'var(--theme-error-550)',
64
+ }}
65
+ >
66
+ <h2 style={{ marginBottom: '16px', fontSize: '18px' }}>
67
+ {t('errorBoundary.title')}
68
+ </h2>
69
+ <p style={{ marginBottom: '24px', color: 'var(--theme-elevation-650)', fontSize: '14px' }}>
70
+ {t('errorBoundary.description')}
71
+ </p>
72
+ <button
73
+ type="button"
74
+ onClick={onRetry}
75
+ style={{
76
+ padding: '8px 20px',
77
+ backgroundColor: 'var(--theme-success-550)',
78
+ color: 'var(--theme-elevation-0)',
79
+ border: 'none',
80
+ borderRadius: '6px',
81
+ cursor: 'pointer',
82
+ fontSize: '14px',
83
+ }}
84
+ >
85
+ {t('errorBoundary.retry')}
86
+ </button>
87
+ </div>
88
+ )
14
89
  }
15
90
 
16
91
  export class AdminErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {
17
92
  constructor(props: ErrorBoundaryProps) {
18
93
  super(props)
19
- this.state = { hasError: false, error: null }
94
+ this.state = { hasError: false, error: null, resetCount: 0 }
20
95
  }
21
96
 
22
- static getDerivedStateFromError(error: Error): ErrorBoundaryState {
97
+ static getDerivedStateFromError(error: Error): Pick<ErrorBoundaryState, 'hasError' | 'error'> {
23
98
  return { hasError: true, error }
24
99
  }
25
100
 
@@ -27,42 +102,31 @@ export class AdminErrorBoundary extends React.Component<ErrorBoundaryProps, Erro
27
102
  console.error(`[${this.props.viewName || 'AdminView'}] Error:`, error, errorInfo)
28
103
  }
29
104
 
105
+ componentDidUpdate(prevProps: ErrorBoundaryProps): void {
106
+ if (!this.state.hasError) return
107
+ if (!haveResetKeysChanged(prevProps.resetKeys, this.props.resetKeys)) return
108
+ this.reset()
109
+ }
110
+
111
+ reset = (): void => {
112
+ this.setState((prev) => ({
113
+ hasError: false,
114
+ error: null,
115
+ resetCount: prev.resetCount + 1,
116
+ }))
117
+ }
118
+
30
119
  render(): React.ReactNode {
31
120
  if (this.state.hasError) {
32
121
  if (this.props.fallback) {
33
122
  return this.props.fallback
34
123
  }
35
124
 
36
- return (
37
- <div style={{
38
- padding: '40px',
39
- textAlign: 'center',
40
- color: '#dc2626',
41
- }}>
42
- <h2 style={{ marginBottom: '16px', fontSize: '18px' }}>
43
- Une erreur est survenue
44
- </h2>
45
- <p style={{ marginBottom: '24px', color: '#6b7280', fontSize: '14px' }}>
46
- {this.state.error?.message || 'Erreur inattendue'}
47
- </p>
48
- <button
49
- onClick={() => this.setState({ hasError: false, error: null })}
50
- style={{
51
- padding: '8px 20px',
52
- backgroundColor: '#2563eb',
53
- color: '#fff',
54
- border: 'none',
55
- borderRadius: '6px',
56
- cursor: 'pointer',
57
- fontSize: '14px',
58
- }}
59
- >
60
- Reessayer
61
- </button>
62
- </div>
63
- )
125
+ return <AdminErrorFallback onRetry={this.reset} />
64
126
  }
65
127
 
66
- return this.props.children
128
+ // The key forces a full remount after a reset instead of resuming the
129
+ // component instance that just threw.
130
+ return <React.Fragment key={this.state.resetCount}>{this.props.children}</React.Fragment>
67
131
  }
68
132
  }
@@ -3,31 +3,48 @@ import type React from 'react'
3
3
  // Shared design tokens for all admin views (professional style)
4
4
  export const V = {
5
5
  text: 'var(--theme-text)',
6
- textSecondary: 'var(--theme-elevation-500)',
6
+ // elevation-650, not elevation-500: Payload's dark theme does not redefine
7
+ // the 500 step (colors.scss jumps from 450 to 550), so elevation-500 stays
8
+ // rgb(128,128,128) in both themes — 3.62:1 on a light background and 4.03:1
9
+ // on a dark one, below WCAG AA in both. elevation-650 gives 6.63:1 / 9.03:1.
10
+ textSecondary: 'var(--theme-elevation-650)',
7
11
  bg: 'var(--theme-elevation-50)',
8
12
  bgCard: 'var(--theme-elevation-100)',
9
13
  border: 'var(--theme-elevation-300)',
10
- // Professional palette
11
- blue: '#2563eb',
12
- amber: '#d97706',
13
- orange: '#ea580c',
14
- green: '#16a34a',
15
- red: '#dc2626',
14
+ // Professional palette. These are fixed hex values (they do not follow the
15
+ // admin theme), so they are only ever used as a background behind white
16
+ // text; each one is dark enough for white to reach at least 4.5:1.
17
+ blue: '#2563eb', // white on it: 5.17:1
18
+ amber: '#b45309', // white on it: 5.02:1
19
+ orange: '#c2410c', // white on it: 5.18:1
20
+ green: '#15803d', // white on it: 5.02:1
21
+ red: '#dc2626', // white on it: 4.83:1
22
+ // Neutral / secondary button. Both halves follow the admin theme, so they
23
+ // must be used together — white on a theme token is unreadable in one of
24
+ // the two themes whichever token is picked.
25
+ neutralBg: 'var(--theme-elevation-150)',
26
+ neutralFg: 'var(--theme-text)',
16
27
  // Legacy aliases (backward compat for views not yet updated)
17
28
  cyan: '#2563eb',
18
- yellow: '#d97706',
29
+ yellow: '#b45309',
19
30
  } as const
20
31
 
21
- // Button style factory
32
+ /**
33
+ * Button style factory.
34
+ *
35
+ * `bg` is expected to be one of the fixed hex values of `V`; the default
36
+ * foreground is white, which reaches AA on all of them. Pass `fg` whenever
37
+ * `bg` is a theme variable, since white only works on one of the two themes.
38
+ */
22
39
  export const btnStyle = (
23
40
  bg: string,
24
- opts?: { disabled?: boolean; small?: boolean },
41
+ opts?: { disabled?: boolean; small?: boolean; fg?: string },
25
42
  ): React.CSSProperties => ({
26
43
  padding: opts?.small ? '6px 12px' : '8px 14px',
27
44
  borderRadius: 6,
28
45
  border: `1px solid var(--theme-elevation-300)`,
29
46
  backgroundColor: bg,
30
- color: '#fff',
47
+ color: opts?.fg ?? '#fff',
31
48
  fontWeight: 600,
32
49
  fontSize: opts?.small ? 12 : 13,
33
50
  cursor: opts?.disabled ? 'not-allowed' : 'pointer',
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Inlined Lucide icons.
3
+ *
4
+ * The plugin used to require `lucide-react` as a peer dependency for exactly
5
+ * 15 icons across two admin views. That made every integrator install an icon set,
6
+ * and a missing install a build-time failure, for 15 paths totalling a few
7
+ * hundred bytes. They are inlined here instead, and `lucide-react` is no longer
8
+ * a peer dependency.
9
+ *
10
+ * The geometry below is copied from lucide-react v1.41.0 and, like the rest of
11
+ * Lucide, is under the ISC licence:
12
+ *
13
+ * ISC License
14
+ * Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as
15
+ * part of Feather (MIT). All other copyright (c) for Lucide are held by
16
+ * Lucide Contributors 2022.
17
+ *
18
+ * Permission to use, copy, modify, and/or distribute this software for any
19
+ * purpose with or without fee is hereby granted, provided that the above
20
+ * copyright notice and this permission notice appear in all copies.
21
+ *
22
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
23
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
24
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
25
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
27
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
28
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29
+ */
30
+
31
+ import React from 'react'
32
+
33
+ export interface IconProps extends Omit<React.SVGProps<SVGSVGElement>, 'width' | 'height'> {
34
+ /** Rendered width and height. Lucide's own default is 24. */
35
+ size?: number | string
36
+ }
37
+
38
+ type IconNode = ReadonlyArray<readonly [string, Record<string, string | number>]>
39
+
40
+ /**
41
+ * Icons are decorative by default (`aria-hidden`): every control that has
42
+ * nothing but an icon inside carries its own `aria-label`. Pass
43
+ * `aria-hidden={false}` plus a label to make one meaningful on its own.
44
+ */
45
+ function createIcon(displayName: string, nodes: IconNode): React.FC<IconProps> {
46
+ const Icon: React.FC<IconProps> = ({ size = 24, strokeWidth = 2, ...rest }) => (
47
+ <svg
48
+ xmlns="http://www.w3.org/2000/svg"
49
+ width={size}
50
+ height={size}
51
+ viewBox="0 0 24 24"
52
+ fill="none"
53
+ stroke="currentColor"
54
+ strokeWidth={strokeWidth}
55
+ strokeLinecap="round"
56
+ strokeLinejoin="round"
57
+ aria-hidden="true"
58
+ {...rest}
59
+ >
60
+ {nodes.map(([tag, attrs], index) => React.createElement(tag, { key: index, ...attrs }))}
61
+ </svg>
62
+ )
63
+ Icon.displayName = displayName
64
+ return Icon
65
+ }
66
+
67
+ export const Bot = createIcon('Bot', [
68
+ ['path', { d: "M12 8V4H8" }],
69
+ ['rect', { width: "16", height: "12", x: "4", y: "8", rx: "2" }],
70
+ ['path', { d: "M2 14h2" }],
71
+ ['path', { d: "M20 14h2" }],
72
+ ['path', { d: "M15 13v2" }],
73
+ ['path', { d: "M9 13v2" }],
74
+ ] as const)
75
+
76
+ export const ChevronDown = createIcon('ChevronDown', [
77
+ ['path', { d: "m6 9 6 6 6-6" }],
78
+ ] as const)
79
+
80
+ export const ChevronUp = createIcon('ChevronUp', [
81
+ ['path', { d: "m18 15-6-6-6 6" }],
82
+ ] as const)
83
+
84
+ export const Clock = createIcon('Clock', [
85
+ ['circle', { cx: "12", cy: "12", r: "10" }],
86
+ ['path', { d: "M12 6v6l4 2" }],
87
+ ] as const)
88
+
89
+ export const FileSignature = createIcon('FileSignature', [
90
+ ['path', { d: "M14.364 13.634a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506l4.013-4.009a1 1 0 0 0-3.004-3.004z" }],
91
+ ['path', { d: "M14.487 7.858A1 1 0 0 1 14 7V2" }],
92
+ ['path', { d: "M20 19.645V20a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l2.516 2.516" }],
93
+ ['path', { d: "M8 18h1" }],
94
+ ] as const)
95
+
96
+ export const Globe = createIcon('Globe', [
97
+ ['circle', { cx: "12", cy: "12", r: "10" }],
98
+ ['path', { d: "M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20" }],
99
+ ['path', { d: "M2 12h20" }],
100
+ ] as const)
101
+
102
+ export const Inbox = createIcon('Inbox', [
103
+ ['polyline', { points: "22 12 16 12 14 15 10 15 8 12 2 12" }],
104
+ ['path', { d: "M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" }],
105
+ ] as const)
106
+
107
+ export const Link2 = createIcon('Link2', [
108
+ ['path', { d: "M9 17H7A5 5 0 0 1 7 7h2" }],
109
+ ['path', { d: "M15 7h2a5 5 0 1 1 0 10h-2" }],
110
+ ['line', { x1: "8", x2: "16", y1: "12", y2: "12" }],
111
+ ] as const)
112
+
113
+ export const Mail = createIcon('Mail', [
114
+ ['path', { d: "m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" }],
115
+ ['rect', { x: "2", y: "4", width: "20", height: "16", rx: "2" }],
116
+ ] as const)
117
+
118
+ export const Paperclip = createIcon('Paperclip', [
119
+ ['path', { d: "m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551" }],
120
+ ] as const)
121
+
122
+ export const Plus = createIcon('Plus', [
123
+ ['path', { d: "M5 12h14" }],
124
+ ['path', { d: "M12 5v14" }],
125
+ ] as const)
126
+
127
+ export const Search = createIcon('Search', [
128
+ ['path', { d: "m21 21-4.34-4.34" }],
129
+ ['circle', { cx: "11", cy: "11", r: "8" }],
130
+ ] as const)
131
+
132
+ export const Settings = createIcon('Settings', [
133
+ ['path', { d: "M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915" }],
134
+ ['circle', { cx: "12", cy: "12", r: "3" }],
135
+ ] as const)
136
+
137
+ export const Timer = createIcon('Timer', [
138
+ ['line', { x1: "10", x2: "14", y1: "2", y2: "2" }],
139
+ ['line', { x1: "12", x2: "15", y1: "14", y2: "11" }],
140
+ ['circle', { cx: "12", cy: "14", r: "8" }],
141
+ ] as const)
142
+
143
+ export const X = createIcon('X', [
144
+ ['path', { d: "M18 6 6 18" }],
145
+ ['path', { d: "m6 6 12 12" }],
146
+ ] as const)
@@ -1,4 +1,9 @@
1
1
  {
2
+ "errorBoundary": {
3
+ "title": "Something went wrong",
4
+ "description": "This section could not be displayed. The technical details were logged to the browser console.",
5
+ "retry": "Retry"
6
+ },
2
7
  "common": {
3
8
  "loading": "Loading...",
4
9
  "cancel": "Cancel",
@@ -144,6 +149,7 @@
144
149
  "title": "CRM Clients",
145
150
  "subtitle": "Client management and history",
146
151
  "searchPlaceholder": "Search a client...",
152
+ "searchLabel": "Search a client",
147
153
  "noClientFound": "No client found",
148
154
  "selectClient": "Select a client to see their details",
149
155
  "editButton": "Edit",
@@ -316,6 +322,8 @@
316
322
  "resolved": "Resolved",
317
323
  "slaBreach": "SLA breached"
318
324
  },
325
+ "searchLabel": "Search a ticket",
326
+ "sortLabel": "Sort the tickets",
319
327
  "sort": {
320
328
  "newest": "Most recent",
321
329
  "oldest": "Oldest first",
@@ -324,6 +332,7 @@
324
332
  },
325
333
  "selected": "{{count}} selected",
326
334
  "selectedPlural": "{{count}} selected",
335
+ "tabsLabel": "Inbox filters",
327
336
  "closeAction": "Close",
328
337
  "reopenAction": "Reopen",
329
338
  "moreActions": "More actions...",
@@ -344,6 +353,7 @@
344
353
  "emailTracking": {
345
354
  "title": "Email tracking",
346
355
  "searchPlaceholder": "Search by recipient or subject...",
356
+ "searchLabel": "Search an email",
347
357
  "noLogs": "No logs found for this period",
348
358
  "tabs": {
349
359
  "all": "All",
@@ -366,7 +376,8 @@
366
376
  "action": "Action",
367
377
  "time": "Time"
368
378
  },
369
- "errorLabel": "Error"
379
+ "errorLabel": "Error",
380
+ "toggleError": "Show the error detail"
370
381
  },
371
382
  "logs": {
372
383
  "title": "Email Logs",
@@ -530,8 +541,11 @@
530
541
  "messageDeletedToast": "Message deleted",
531
542
  "split": {
532
543
  "subjectPlaceholder": "New ticket subject...",
544
+ "subjectLabel": "Subject of the new ticket",
533
545
  "createBtn": "Create ticket"
534
546
  },
547
+ "sendAs": "Send as",
548
+ "manualMinutes": "Minutes to add",
535
549
  "editMessage": "Edit",
536
550
  "editMessageLabel": "Edit message",
537
551
  "uploadItem": "Attachment {{name}}",
@@ -1,4 +1,9 @@
1
1
  {
2
+ "errorBoundary": {
3
+ "title": "Une erreur est survenue",
4
+ "description": "Cette section n'a pas pu s'afficher. Le detail technique est consigne dans la console du navigateur.",
5
+ "retry": "Reessayer"
6
+ },
2
7
  "common": {
3
8
  "loading": "Chargement...",
4
9
  "cancel": "Annuler",
@@ -144,6 +149,7 @@
144
149
  "title": "CRM Clients",
145
150
  "subtitle": "Gestion des clients et historique",
146
151
  "searchPlaceholder": "Rechercher un client...",
152
+ "searchLabel": "Rechercher un client",
147
153
  "noClientFound": "Aucun client trouvé",
148
154
  "selectClient": "Sélectionnez un client pour voir ses détails",
149
155
  "editButton": "Modifier",
@@ -316,6 +322,8 @@
316
322
  "resolved": "Résolus",
317
323
  "slaBreach": "SLA dépassé"
318
324
  },
325
+ "searchLabel": "Rechercher un ticket",
326
+ "sortLabel": "Trier les tickets",
319
327
  "sort": {
320
328
  "newest": "Plus récent",
321
329
  "oldest": "Plus ancien",
@@ -324,6 +332,7 @@
324
332
  },
325
333
  "selected": "{{count}} sélectionné",
326
334
  "selectedPlural": "{{count}} sélectionnés",
335
+ "tabsLabel": "Filtres de la boite de reception",
327
336
  "closeAction": "Fermer",
328
337
  "reopenAction": "Rouvrir",
329
338
  "moreActions": "Plus d'actions...",
@@ -344,6 +353,7 @@
344
353
  "emailTracking": {
345
354
  "title": "Suivi des emails",
346
355
  "searchPlaceholder": "Rechercher par destinataire ou sujet...",
356
+ "searchLabel": "Rechercher un email",
347
357
  "noLogs": "Aucun log trouvé pour cette période",
348
358
  "tabs": {
349
359
  "all": "Tous",
@@ -366,7 +376,8 @@
366
376
  "action": "Action",
367
377
  "time": "Temps"
368
378
  },
369
- "errorLabel": "Erreur"
379
+ "errorLabel": "Erreur",
380
+ "toggleError": "Afficher le detail de l'erreur"
370
381
  },
371
382
  "logs": {
372
383
  "title": "Logs Email",
@@ -530,8 +541,11 @@
530
541
  "messageDeletedToast": "Message supprimé",
531
542
  "split": {
532
543
  "subjectPlaceholder": "Sujet du nouveau ticket...",
544
+ "subjectLabel": "Sujet du nouveau ticket",
533
545
  "createBtn": "Créer le ticket"
534
546
  },
547
+ "sendAs": "Envoyer en tant que",
548
+ "manualMinutes": "Minutes a ajouter",
535
549
  "editMessage": "Éditer",
536
550
  "editMessageLabel": "Éditer le message",
537
551
  "uploadItem": "PJ {{name}}",
@@ -1,42 +0,0 @@
1
- /**
2
- * Ambient stub for 'lucide-react'.
3
- *
4
- * lucide-react is a REQUIRED peer dependency — three unconditionally registered
5
- * components import it statically, so a host without it fails at build time.
6
- * It is deliberately not a devDependency here; this stub is what lets the plugin
7
- * type-check in isolation without pulling the icon set into the repo.
8
- *
9
- * Keep the icon list below in sync with the actual imports:
10
- * src/portal/LiveChat.tsx
11
- * src/views/PendingEmailsView/client.tsx
12
- * src/views/TicketingSettingsView/client.tsx
13
- */
14
- declare module 'lucide-react' {
15
- import type { FC, SVGProps } from 'react'
16
- type LucideIcon = FC<SVGProps<SVGSVGElement> & { size?: number | string; strokeWidth?: number | string }>
17
- // Export every named icon as LucideIcon so any import resolves cleanly
18
- const MessageCircle: LucideIcon
19
- const Send: LucideIcon
20
- const X: LucideIcon
21
- const Minimize2: LucideIcon
22
- const ArrowLeft: LucideIcon
23
- const Inbox: LucideIcon
24
- const Plus: LucideIcon
25
- const Link2: LucideIcon
26
- const Search: LucideIcon
27
- const ChevronDown: LucideIcon
28
- const ChevronUp: LucideIcon
29
- const Paperclip: LucideIcon
30
- const Settings: LucideIcon
31
- const Mail: LucideIcon
32
- const Bot: LucideIcon
33
- const Clock: LucideIcon
34
- const Timer: LucideIcon
35
- const Globe: LucideIcon
36
- const FileSignature: LucideIcon
37
- export {
38
- MessageCircle, Send, X, Minimize2, ArrowLeft,
39
- Inbox, Plus, Link2, Search, ChevronDown, ChevronUp, Paperclip,
40
- Settings, Mail, Bot, Clock, Timer, Globe, FileSignature,
41
- }
42
- }