kyd-shared-badge 0.2.15 → 0.2.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kyd-shared-badge",
3
- "version": "0.2.15",
3
+ "version": "0.2.16",
4
4
  "private": false,
5
5
  "main": "./src/index.ts",
6
6
  "module": "./src/index.ts",
@@ -7,6 +7,7 @@ interface SanctionSource {
7
7
  issuingEntity: string;
8
8
  listName: string;
9
9
  matched?: boolean;
10
+ sublists?: string[];
10
11
  }
11
12
 
12
13
  interface DomainSource {
@@ -25,48 +26,73 @@ interface AppendixTableProps {
25
26
  developerName: string;
26
27
  }
27
28
 
28
- const SanctionsRow = ({ source, searchedAt, developerName }: { source: SanctionSource & { sublists?: string[] }, searchedAt: string, developerName: string }) => (
29
- <tr className={'transition-colors'} style={source.matched ? { backgroundColor: 'rgba(236,102,98,0.08)' } : undefined}>
30
- <td className={'px-4 py-4 whitespace-nowrap align-top text-sm font-medium'} style={{ color: 'var(--text-main)' }}>
31
- {source.issuingEntity}
32
- </td>
33
- <td className={'px-4 py-4 whitespace-normal align-top text-sm'} style={{ color: 'var(--text-secondary)' }}>
34
- <div className="flex flex-col gap-2">
35
- <div className="flex items-center justify-between gap-3">
36
- <span>{source.listName}</span>
29
+ const SanctionsRow = ({
30
+ source,
31
+ searchedAt,
32
+ developerName,
33
+ onToggle,
34
+ expanded,
35
+ colSpan,
36
+ }: {
37
+ source: SanctionSource;
38
+ searchedAt: string;
39
+ developerName: string;
40
+ onToggle: () => void;
41
+ expanded: boolean;
42
+ colSpan: number;
43
+ }) => (
44
+ <>
45
+ <tr className={'transition-colors'} style={source.matched ? { backgroundColor: 'rgba(236,102,98,0.08)' } : undefined}>
46
+ <td className={'px-4 py-4 whitespace-nowrap align-top text-sm font-medium'} style={{ color: 'var(--text-main)' }}>
47
+ <div className="flex flex-col gap-1">
48
+ <span>{source.issuingEntity}</span>
37
49
  {source.sublists && source.sublists.length > 0 && (
38
- <details className="ml-auto">
39
- <summary className={'cursor-pointer text-xs font-semibold px-2 py-1 rounded-full'} style={{ backgroundColor: 'var(--icon-button-secondary)', color: 'var(--text-main)' }}>View sub-lists</summary>
40
- <ul className="mt-2 text-xs list-disc pl-4 space-y-1" style={{ color: 'var(--text-secondary)' }}>
41
- {source.sublists.map((sl, idx) => (
42
- <li key={idx}>{sl}</li>
43
- ))}
44
- </ul>
45
- </details>
50
+ <button
51
+ type="button"
52
+ onClick={onToggle}
53
+ className={'text-xs inline-flex items-center gap-1 text-left'}
54
+ style={{ color: 'var(--text-secondary)' }}
55
+ aria-expanded={expanded}
56
+ >
57
+ <span style={{ display: 'inline-block', transform: expanded ? 'rotate(90deg)' : 'rotate(0deg)', transition: 'transform 150ms ease' }}>▶</span>
58
+ <span>View sub-lists</span>
59
+ </button>
46
60
  )}
47
61
  </div>
48
- </div>
49
- </td>
50
- <td className={'px-4 py-4 whitespace-nowrap align-top text-sm'} style={{ color: 'var(--text-secondary)' }}>
51
- {searchedAt}
52
- </td>
53
- <td className={'px-4 py-4 whitespace-nowrap align-top text-sm'} style={{ color: 'var(--text-secondary)' }}>
54
- {source.matched ? (
55
- <span className={'px-2 inline-flex text-xs leading-5 font-semibold rounded-full'} style={{ backgroundColor: 'rgba(236,102,98,0.2)', color: 'var(--text-main)' }}>
56
- Match
57
- </span>
58
- ) : (
59
- <span className={'px-2 inline-flex text-xs leading-5 font-semibold rounded-full'} style={{ backgroundColor: 'var(--icon-button-secondary)', color: 'var(--text-main)' }}>
60
- Not Found
61
- </span>
62
- )}
63
- </td>
64
- <td className={'px-4 py-4 text-sm whitespace-normal align-top'} style={{ color: 'var(--text-secondary)' }}>
65
- {source.matched
66
- ? (<span>Exact or strong match for <strong style={{ color: 'var(--text-main)' }}>{developerName}</strong> was found on this list.</span>)
67
- : (<span>No exact match for <strong style={{ color: 'var(--text-main)' }}>{developerName}</strong> was found on this list.</span>)}
68
- </td>
69
- </tr>
62
+ </td>
63
+ <td className={'px-4 py-4 whitespace-normal align-top text-sm'} style={{ color: 'var(--text-secondary)' }}>
64
+ {source.listName}
65
+ </td>
66
+ <td className={'px-4 py-4 whitespace-nowrap align-top text-sm'} style={{ color: 'var(--text-secondary)' }}>
67
+ {searchedAt}
68
+ </td>
69
+ <td className={'px-4 py-4 whitespace-nowrap align-top text-sm'} style={{ color: 'var(--text-secondary)' }}>
70
+ {source.matched ? (
71
+ <span className={'text-xs font-semibold'} style={{ color: 'var(--text-main)' }}>Match</span>
72
+ ) : (
73
+ <span className={'text-xs'} style={{ color: 'var(--text-secondary)' }}>Not Found</span>
74
+ )}
75
+ </td>
76
+ <td className={'px-4 py-4 text-sm whitespace-normal align-top'} style={{ color: 'var(--text-secondary)' }}>
77
+ {source.matched
78
+ ? (<span>Exact or strong match for <strong style={{ color: 'var(--text-main)' }}>{developerName}</strong> was found on this list.</span>)
79
+ : (<span>No exact match for <strong style={{ color: 'var(--text-main)' }}>{developerName}</strong> was found on this list.</span>)}
80
+ </td>
81
+ </tr>
82
+ {expanded && source.sublists && source.sublists.length > 0 && (
83
+ <tr>
84
+ <td colSpan={colSpan} className={'px-6 pb-4'}>
85
+ <div className={'mt-1 border-t pt-3'} style={{ borderColor: 'var(--icon-button-secondary)' }}>
86
+ <ul className={'grid grid-cols-1 sm:grid-cols-2 gap-y-1 gap-x-6 text-sm list-disc pl-5'} style={{ color: 'var(--text-secondary)' }}>
87
+ {source.sublists.map((sl, idx) => (
88
+ <li key={idx}>{sl}</li>
89
+ ))}
90
+ </ul>
91
+ </div>
92
+ </td>
93
+ </tr>
94
+ )}
95
+ </>
70
96
  );
71
97
 
72
98
  const DomainRow = ({ source, searchedAt, developerName }: { source: DomainSource, searchedAt: string, developerName: string }) => (
@@ -89,6 +115,7 @@ const DomainRow = ({ source, searchedAt, developerName }: { source: DomainSource
89
115
 
90
116
  const AppendixTables: React.FC<AppendixTableProps> = ({ type, sources, searchedAt, developerName }) => {
91
117
  const [visibleCount, setVisibleCount] = useState(PAGE_SIZE);
118
+ const [expanded, setExpanded] = useState<{ [k: number]: boolean }>({});
92
119
 
93
120
  const formattedDate = new Date(searchedAt).toLocaleString(undefined, {
94
121
  year: 'numeric', month: 'short', day: 'numeric',
@@ -147,11 +174,23 @@ const AppendixTables: React.FC<AppendixTableProps> = ({ type, sources, searchedA
147
174
  </tr>
148
175
  </thead>
149
176
  <tbody className={''}>
150
- {visibleParsedSources.map((source, index) =>
151
- type === 'sanctions'
152
- ? <SanctionsRow key={index} source={source as SanctionSource} searchedAt={formattedDate} developerName={developerName} />
153
- : <DomainRow key={index} source={source as DomainSource} searchedAt={formattedDate} developerName={developerName} />
154
- )}
177
+ {visibleParsedSources.map((source, index) => {
178
+ if (type === 'sanctions') {
179
+ const src = source as SanctionSource;
180
+ return (
181
+ <SanctionsRow
182
+ key={index}
183
+ source={src}
184
+ searchedAt={formattedDate}
185
+ developerName={developerName}
186
+ onToggle={() => setExpanded(prev => ({ ...prev, [index]: !prev[index] }))}
187
+ expanded={!!expanded[index]}
188
+ colSpan={headers.length}
189
+ />
190
+ );
191
+ }
192
+ return <DomainRow key={index} source={source as DomainSource} searchedAt={formattedDate} developerName={developerName} />
193
+ })}
155
194
  </tbody>
156
195
  </table>
157
196
  </div>