kyd-shared-badge 0.3.71 → 0.3.73
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 +4 -1
- package/src/connect/ConnectAccounts.tsx +127 -119
- package/src/connect/types.ts +3 -0
- package/src/ui/button.tsx +1 -1
- package/src/ui/card.tsx +1 -1
- package/src/ui/input.tsx +1 -1
- package/src/utils/index.ts +2 -0
- package/src/utils/utils.ts +9 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kyd-shared-badge",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.73",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"module": "./src/index.ts",
|
|
@@ -21,7 +21,9 @@
|
|
|
21
21
|
"@aws-sdk/lib-dynamodb": "^3.893.0",
|
|
22
22
|
"@chatscope/chat-ui-kit-react": "^2.1.1",
|
|
23
23
|
"@chatscope/chat-ui-kit-styles": "^1.4.0",
|
|
24
|
+
"@radix-ui/react-slot": "^1.2.3",
|
|
24
25
|
"ai": "5.0.47",
|
|
26
|
+
"class-variance-authority": "^0.7.1",
|
|
25
27
|
"framer-motion": "^12.23.24",
|
|
26
28
|
"i18n-iso-countries": "^7.14.0",
|
|
27
29
|
"lucide-react": "^0.545.0",
|
|
@@ -29,6 +31,7 @@
|
|
|
29
31
|
"react-hot-toast": "^2.6.0",
|
|
30
32
|
"react-icons": "^5.5.0",
|
|
31
33
|
"recharts": "^2.15.4",
|
|
34
|
+
"tailwind-merge": "^3.3.1",
|
|
32
35
|
"ulid": "^3.0.1"
|
|
33
36
|
},
|
|
34
37
|
"publishConfig": {
|
|
@@ -5,7 +5,7 @@ import { normalizeLinkedInInput } from './linkedin';
|
|
|
5
5
|
import type { ConnectAccountsProps } from './types';
|
|
6
6
|
import { CheckCircle, Link2, LinkIcon, Unlink, ArrowLeft, ExternalLink } from 'lucide-react';
|
|
7
7
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
8
|
-
import { Button, Input, Spinner } from '../ui';
|
|
8
|
+
import { Button, Input, Spinner, Card, CardHeader, CardContent, CardFooter, CardTitle } from '../ui';
|
|
9
9
|
import Link from 'next/link';
|
|
10
10
|
|
|
11
11
|
function byPriority(a: string, b: string) {
|
|
@@ -32,6 +32,9 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
32
32
|
className,
|
|
33
33
|
oauthClientIds,
|
|
34
34
|
providerPickCallback,
|
|
35
|
+
handleBackButton,
|
|
36
|
+
headerTitle,
|
|
37
|
+
headerDescription,
|
|
35
38
|
} = props;
|
|
36
39
|
|
|
37
40
|
const router = useRouter();
|
|
@@ -148,11 +151,11 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
148
151
|
setLinkUrl('');
|
|
149
152
|
};
|
|
150
153
|
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
exit: { opacity: 0, y:
|
|
155
|
-
}
|
|
154
|
+
const cardVariants = {
|
|
155
|
+
initial: { opacity: 0, y: 20 },
|
|
156
|
+
animate: { opacity: 1, y: 0 },
|
|
157
|
+
exit: { opacity: 0, y: -20 },
|
|
158
|
+
};
|
|
156
159
|
|
|
157
160
|
return (
|
|
158
161
|
<>
|
|
@@ -162,7 +165,7 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
162
165
|
key="connect-card"
|
|
163
166
|
className="rounded-xl border max-w-xl w-full"
|
|
164
167
|
style={{ backgroundColor: 'var(--content-card-background)', borderColor: 'var(--icon-button-secondary)'}}
|
|
165
|
-
initial="
|
|
168
|
+
initial="initial" animate="animate" exit="exit" variants={cardVariants}
|
|
166
169
|
>
|
|
167
170
|
<div className="sm:p-6 p-4">
|
|
168
171
|
<button onClick={handleConnectBack} className="flex items-center gap-2 text-sm text-[var(--text-secondary)] hover:text-[var(--text-main)] transition-colors mb-4">
|
|
@@ -189,7 +192,7 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
189
192
|
<motion.form
|
|
190
193
|
onSubmit={(e) => { e.preventDefault(); onSubmitLink(selectedProvider.id); }}
|
|
191
194
|
className="mt-6 space-y-4"
|
|
192
|
-
initial="
|
|
195
|
+
initial="initial" animate="animate" exit="exit" variants={cardVariants}
|
|
193
196
|
>
|
|
194
197
|
{selectedProvider.id === 'linkedin' && (
|
|
195
198
|
<p className="sm:text-xs items-center text-[10px] text-[var(--text-secondary)] leading-relaxed max-w-xs mx-auto -mt-2">
|
|
@@ -246,128 +249,133 @@ export function ConnectAccounts(props: ConnectAccountsProps) {
|
|
|
246
249
|
</motion.div>
|
|
247
250
|
</AnimatePresence>
|
|
248
251
|
) : (
|
|
249
|
-
<
|
|
250
|
-
<
|
|
251
|
-
<
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
252
|
+
<Card className="border-[var(--icon-button-secondary)] pt-2" style={{ backgroundColor: 'var(--content-card-background)'}}>
|
|
253
|
+
<AnimatePresence mode="wait">
|
|
254
|
+
<motion.div key="platform-list-shared" variants={cardVariants} initial="initial" animate="animate" exit="exit" transition={{ duration: 0.3 }}>
|
|
255
|
+
<CardHeader className="pb-4">
|
|
256
|
+
{handleBackButton && (
|
|
257
|
+
<button onClick={() => handleBackButton()} className="flex items-center gap-2 text-sm sm:mb-1 mb-4 text-[var(--text-secondary)] hover:text-[var(--text-main)] transition-colors">
|
|
258
|
+
<ArrowLeft className="w-4 h-4" /> Back
|
|
259
|
+
</button>
|
|
260
|
+
)}
|
|
261
|
+
<CardTitle className="sm:text-xl text-base font-semibold text-[var(--text-main)] mb-2">{headerTitle}</CardTitle>
|
|
262
|
+
<p className="sm:text-sm text-xs text-[var(--text-secondary)] leading-relaxed">{headerDescription}</p>
|
|
263
|
+
</CardHeader>
|
|
264
|
+
<CardContent className="space-y-2">
|
|
265
|
+
{(() => {
|
|
266
|
+
const oauthList = list.filter(p => p.connectionType === 'oauth');
|
|
267
|
+
const urlList = list.filter(p => (p.connectionType || 'url') === 'url' || p.connectionType === 'link');
|
|
261
268
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
269
|
+
const Row = (provider: typeof list[number]) => {
|
|
270
|
+
const providerId = provider.id;
|
|
271
|
+
const isConnected = connectedIds.has(providerId.toLowerCase());
|
|
272
|
+
const needsReconnect = reconnectIds.has(providerId.toLowerCase());
|
|
273
|
+
const isOauth = provider.connectionType === 'oauth'
|
|
274
|
+
const connectedUrl = connected.find(c => c.id.toLowerCase() === providerId.toLowerCase())?.url;
|
|
275
|
+
const betaFlag = () => (
|
|
276
|
+
<span
|
|
277
|
+
className="ml-2 inline-block rounded-full px-2 py-0.5 text-xs font-semibold bg-blue-100 text-blue-700 border border-blue-200"
|
|
278
|
+
style={{ verticalAlign: 'middle', letterSpacing: '0.05em' }}
|
|
279
|
+
>
|
|
280
|
+
Beta
|
|
281
|
+
</span>
|
|
282
|
+
);
|
|
276
283
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
284
|
+
return (
|
|
285
|
+
<div key={providerId} className="group flex items-center justify-between p-2 rounded-lg transition-colors hover:bg-[var(--icon-button-secondary)]/10 transform transition-transform hover:-translate-y-px">
|
|
286
|
+
<div className="flex items-center gap-3">
|
|
280
287
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
288
|
+
{isConnected && connectedUrl ? (
|
|
289
|
+
<Link href={connectedUrl} target="_blank" rel="noopener noreferrer" className="flex items-center gap-3 hover:underline">
|
|
290
|
+
<ProviderIcon name={provider.id} className={`sm:size-7 size-5 ${provider.iconColor || 'text-gray-500'}`} />
|
|
291
|
+
<span className="font-medium sm:text-base text-sm" style={{ color: 'var(--text-main)'}}>{provider.name}</span>
|
|
292
|
+
</Link>
|
|
293
|
+
) : (
|
|
294
|
+
<div className="flex items-center gap-3">
|
|
295
|
+
<ProviderIcon name={provider.id} className={`sm:size-7 size-5 ${provider.iconColor || 'text-gray-500'}`} />
|
|
296
|
+
<span className="font-medium sm:text-base text-sm" style={{ color: 'var(--text-main)'}}>{provider.name}</span>
|
|
297
|
+
</div>
|
|
298
|
+
)}
|
|
299
|
+
{provider.beta ? betaFlag() : null}
|
|
300
|
+
</div>
|
|
301
|
+
|
|
302
|
+
{isConnected ? (
|
|
303
|
+
<div className="relative flex items-center">
|
|
304
|
+
<div className="flex items-center gap-2 transition-opacity group-hover:opacity-0" style={{ color: 'var(--success-green)'}}>
|
|
305
|
+
<CheckCircle className="size-3 sm:size-4" />
|
|
306
|
+
<span className="text-sm font-medium">Connected</span>
|
|
307
|
+
</div>
|
|
308
|
+
<div className="absolute right-0 opacity-0 transition-opacity group-hover:opacity-100">
|
|
309
|
+
<button
|
|
310
|
+
onClick={() => onDisconnect(providerId)}
|
|
311
|
+
className="inline-flex items-center gap-1.5 px-3 py-1.5 text-sm text-red-600 hover:text-red-700 hover:underline"
|
|
312
|
+
>
|
|
313
|
+
<Unlink className="size-3 sm:size-4" />
|
|
314
|
+
<span>Disconnect</span>
|
|
315
|
+
</button>
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
286
318
|
) : (
|
|
287
|
-
<div className="flex items-center gap-
|
|
288
|
-
|
|
289
|
-
|
|
319
|
+
<div className="flex items-center gap-2">
|
|
320
|
+
<>
|
|
321
|
+
<Button
|
|
322
|
+
onClick={() => setSelectedProviderIdAndCallback(providerId)}
|
|
323
|
+
className="bg-[var(--icon-button-secondary)] text-[var(--text-main)] hover:bg-[var(--icon-accent)] hover:text-white border-0 sm:px-4 px-3 py-1 sm:py-2 rounded-lg flex items-center gap-2"
|
|
324
|
+
>
|
|
325
|
+
{isOauth ? (
|
|
326
|
+
<Link2 className="size-3 sm:size-4" />
|
|
327
|
+
) : (
|
|
328
|
+
<LinkIcon className="size-3 sm:size-4" />
|
|
329
|
+
)}
|
|
330
|
+
<span className="sm:text-base text-sm">Connect</span>
|
|
331
|
+
</Button>
|
|
332
|
+
{needsReconnect && (
|
|
333
|
+
<Button
|
|
334
|
+
onClick={() => onDisconnect(providerId)}
|
|
335
|
+
className="inline-flex items-center justify-center gap-1.5 px-4 py-2 text-sm rounded border"
|
|
336
|
+
style={{ color: 'var(--text-main)', borderColor: 'var(--icon-button-secondary)'}}
|
|
337
|
+
>
|
|
338
|
+
<Unlink className="size-3 sm:size-4" />
|
|
339
|
+
<span>Remove</span>
|
|
340
|
+
</Button>
|
|
341
|
+
)}
|
|
342
|
+
</>
|
|
290
343
|
</div>
|
|
291
344
|
)}
|
|
292
|
-
{provider.beta ? betaFlag() : null}
|
|
293
345
|
</div>
|
|
346
|
+
);
|
|
347
|
+
};
|
|
294
348
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
349
|
+
return (
|
|
350
|
+
<>
|
|
351
|
+
{oauthList.length ? (
|
|
352
|
+
<>
|
|
353
|
+
<div className="flex items-center my-2">
|
|
354
|
+
<div className="flex-1 border-t" style={{ borderColor: 'var(--icon-button-secondary)', opacity: 0.3 }} />
|
|
355
|
+
<span className="mx-3 text-[10px] sm:text-xs uppercase tracking-wide" style={{ color: 'var(--text-secondary)'}}>OAuth</span>
|
|
356
|
+
<div className="flex-1 border-t" style={{ borderColor: 'var(--icon-button-secondary)', opacity: 0.3 }} />
|
|
300
357
|
</div>
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
358
|
+
{oauthList.map(p => Row(p))}
|
|
359
|
+
</>
|
|
360
|
+
) : null}
|
|
361
|
+
|
|
362
|
+
{urlList.length ? (
|
|
363
|
+
<>
|
|
364
|
+
<div className="flex items-center my-2">
|
|
365
|
+
<div className="flex-1 border-t" style={{ borderColor: 'var(--icon-button-secondary)', opacity: 0.3 }} />
|
|
366
|
+
<span className="mx-3 text-[10px] sm:text-xs uppercase tracking-wide" style={{ color: 'var(--text-secondary)'}}>Public Urls</span>
|
|
367
|
+
<div className="flex-1 border-t" style={{ borderColor: 'var(--icon-button-secondary)', opacity: 0.3 }} />
|
|
309
368
|
</div>
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
<Button
|
|
315
|
-
onClick={() => setSelectedProviderIdAndCallback(providerId)}
|
|
316
|
-
className="bg-[var(--icon-button-secondary)] text-[var(--text-main)] hover:bg-[var(--icon-accent)] hover:text-white border-0 sm:px-4 px-3 py-1 sm:py-2 rounded-lg flex items-center gap-2"
|
|
317
|
-
>
|
|
318
|
-
{isOauth ? (
|
|
319
|
-
<Link2 className="size-3 sm:size-4" />
|
|
320
|
-
) : (
|
|
321
|
-
<LinkIcon className="size-3 sm:size-4" />
|
|
322
|
-
)}
|
|
323
|
-
<span className="sm:text-base text-sm">Connect</span>
|
|
324
|
-
</Button>
|
|
325
|
-
{needsReconnect && (
|
|
326
|
-
<Button
|
|
327
|
-
onClick={() => onDisconnect(providerId)}
|
|
328
|
-
className="inline-flex items-center justify-center gap-1.5 px-4 py-2 text-sm rounded border"
|
|
329
|
-
style={{ color: 'var(--text-main)', borderColor: 'var(--icon-button-secondary)'}}
|
|
330
|
-
>
|
|
331
|
-
<Unlink className="size-3 sm:size-4" />
|
|
332
|
-
<span>Remove</span>
|
|
333
|
-
</Button>
|
|
334
|
-
)}
|
|
335
|
-
</>
|
|
336
|
-
</div>
|
|
337
|
-
)}
|
|
338
|
-
</div>
|
|
369
|
+
{urlList.map(p => Row(p))}
|
|
370
|
+
</>
|
|
371
|
+
) : null}
|
|
372
|
+
</>
|
|
339
373
|
);
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
<>
|
|
346
|
-
<div className="flex items-center my-2">
|
|
347
|
-
<div className="flex-1 border-t" style={{ borderColor: 'var(--icon-button-secondary)', opacity: 0.3 }} />
|
|
348
|
-
<span className="mx-3 text-[10px] sm:text-xs uppercase tracking-wide" style={{ color: 'var(--text-secondary)'}}>OAuth</span>
|
|
349
|
-
<div className="flex-1 border-t" style={{ borderColor: 'var(--icon-button-secondary)', opacity: 0.3 }} />
|
|
350
|
-
</div>
|
|
351
|
-
{oauthList.map(p => Row(p))}
|
|
352
|
-
</>
|
|
353
|
-
) : null}
|
|
354
|
-
|
|
355
|
-
{urlList.length ? (
|
|
356
|
-
<>
|
|
357
|
-
<div className="flex items-center my-2">
|
|
358
|
-
<div className="flex-1 border-t" style={{ borderColor: 'var(--icon-button-secondary)', opacity: 0.3 }} />
|
|
359
|
-
<span className="mx-3 text-[10px] sm:text-xs uppercase tracking-wide" style={{ color: 'var(--text-secondary)'}}>Public Urls</span>
|
|
360
|
-
<div className="flex-1 border-t" style={{ borderColor: 'var(--icon-button-secondary)', opacity: 0.3 }} />
|
|
361
|
-
</div>
|
|
362
|
-
{urlList.map(p => Row(p))}
|
|
363
|
-
</>
|
|
364
|
-
) : null}
|
|
365
|
-
</>
|
|
366
|
-
);
|
|
367
|
-
})()}
|
|
368
|
-
</div>
|
|
369
|
-
</motion.div>
|
|
370
|
-
</motion.div>
|
|
374
|
+
})()}
|
|
375
|
+
</CardContent>
|
|
376
|
+
</motion.div>
|
|
377
|
+
</AnimatePresence>
|
|
378
|
+
</Card>
|
|
371
379
|
)}
|
|
372
380
|
</>
|
|
373
381
|
);
|
package/src/connect/types.ts
CHANGED
|
@@ -33,6 +33,9 @@ export interface ConnectAccountsProps {
|
|
|
33
33
|
onError?: (message: string) => void;
|
|
34
34
|
className?: string;
|
|
35
35
|
providerPickCallback: (providerId: string | null) => void;
|
|
36
|
+
handleBackButton?: () => void;
|
|
37
|
+
headerTitle: string;
|
|
38
|
+
headerDescription: string;
|
|
36
39
|
}
|
|
37
40
|
|
|
38
41
|
|
package/src/ui/button.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import * as React from "react"
|
|
|
2
2
|
import { Slot } from "@radix-ui/react-slot"
|
|
3
3
|
import { cva, type VariantProps } from "class-variance-authority"
|
|
4
4
|
|
|
5
|
-
import { cn } from "
|
|
5
|
+
import { cn } from "../utils"
|
|
6
6
|
|
|
7
7
|
const buttonVariants = cva(
|
|
8
8
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
package/src/ui/card.tsx
CHANGED
package/src/ui/input.tsx
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { clsx, type ClassValue } from "clsx"
|
|
2
|
+
import { twMerge } from "tailwind-merge"
|
|
3
|
+
|
|
4
|
+
export function cn(...inputs: ClassValue[]) {
|
|
5
|
+
return twMerge(clsx(inputs))
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const ROLE_NAME_MAX_LENGTH = 500;
|
|
9
|
+
export const ROLE_DESCRIPTION_MAX_LENGTH = 5500;
|