@sudobility/building_blocks 0.0.47 → 0.0.49
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/dist/components/breadcrumbs/app-breadcrumbs.d.ts +1 -28
- package/dist/index.js +188 -11
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/package.json +4 -4
|
@@ -19,34 +19,7 @@ export interface AppBreadcrumbsProps extends VariantProps<typeof breadcrumbConta
|
|
|
19
19
|
contentClassName?: string;
|
|
20
20
|
}
|
|
21
21
|
/**
|
|
22
|
-
* AppBreadcrumbs -
|
|
23
|
-
*
|
|
24
|
-
* Features:
|
|
25
|
-
* - Breadcrumb trail with links
|
|
26
|
-
* - Social share buttons on the right
|
|
27
|
-
* - Optional "Talk to Founder" meeting button
|
|
28
|
-
* - Always renders at max-w-7xl width
|
|
29
|
-
* - Dark mode support
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```tsx
|
|
33
|
-
* <AppBreadcrumbs
|
|
34
|
-
* items={[
|
|
35
|
-
* { label: 'Home', href: '/' },
|
|
36
|
-
* { label: 'Products', href: '/products' },
|
|
37
|
-
* { label: 'Widget', current: true },
|
|
38
|
-
* ]}
|
|
39
|
-
* shareConfig={{
|
|
40
|
-
* title: 'Check out this widget',
|
|
41
|
-
* description: 'Amazing widget for your needs',
|
|
42
|
-
* hashtags: ['widget', 'product'],
|
|
43
|
-
* }}
|
|
44
|
-
* talkToFounder={{
|
|
45
|
-
* meetingUrl: 'https://calendly.com/founder/30min',
|
|
46
|
-
* buttonText: 'Book a call',
|
|
47
|
-
* }}
|
|
48
|
-
* />
|
|
49
|
-
* ```
|
|
22
|
+
* AppBreadcrumbs - Self-contained breadcrumb navigation with share and "Talk to Founder" button.
|
|
50
23
|
*/
|
|
51
24
|
export declare const AppBreadcrumbs: React.FC<AppBreadcrumbsProps>;
|
|
52
25
|
export default AppBreadcrumbs;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import React, { useState, useRef, useMemo, useCallback, useEffect } from "react";
|
|
3
|
-
import { TopbarProvider, Topbar, TopbarLeft, TopbarNavigation, TopbarLogo, Logo, TopbarCenter, TopbarRight, TopbarActions, TopbarMobileContent,
|
|
3
|
+
import { TopbarProvider, Topbar, TopbarLeft, TopbarNavigation, TopbarLogo, Logo, TopbarCenter, TopbarRight, TopbarActions, TopbarMobileContent, Footer, FooterCompact, FooterCompactLeft, FooterVersion, FooterCopyright, FooterCompactRight, FooterGrid, FooterLinkSection, FooterLink, FooterBottom, FooterBrand, FooterSocialLinks, LayoutProvider, Label, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, MasterListItem, Section, MasterDetailLayout } from "@sudobility/components";
|
|
4
4
|
import { clsx } from "clsx";
|
|
5
5
|
import { twMerge } from "tailwind-merge";
|
|
6
6
|
import { ChevronDownIcon, CalendarDaysIcon, PaintBrushIcon, LanguageIcon, ChevronRightIcon, EnvelopeIcon, DocumentTextIcon, CogIcon, HomeIcon } from "@heroicons/react/24/outline";
|
|
@@ -251,7 +251,8 @@ const AppTopBar = ({
|
|
|
251
251
|
id: item.id,
|
|
252
252
|
label: item.label,
|
|
253
253
|
icon: item.icon,
|
|
254
|
-
href: item.href
|
|
254
|
+
href: item.href,
|
|
255
|
+
className: item.className
|
|
255
256
|
})),
|
|
256
257
|
[visibleMenuItems]
|
|
257
258
|
);
|
|
@@ -437,7 +438,171 @@ const breadcrumbContainerVariants = cva("border-b", {
|
|
|
437
438
|
variant: "default"
|
|
438
439
|
}
|
|
439
440
|
});
|
|
440
|
-
const
|
|
441
|
+
const createShareUrl = {
|
|
442
|
+
twitter: (url, text, hashtags) => {
|
|
443
|
+
const hashtagStr = hashtags.length > 0 ? `&hashtags=${hashtags.join(",")}` : "";
|
|
444
|
+
return `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}${hashtagStr}`;
|
|
445
|
+
},
|
|
446
|
+
facebook: (url) => {
|
|
447
|
+
return `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`;
|
|
448
|
+
},
|
|
449
|
+
linkedin: (url) => {
|
|
450
|
+
return `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`;
|
|
451
|
+
},
|
|
452
|
+
reddit: (url, title) => {
|
|
453
|
+
return `https://reddit.com/submit?url=${encodeURIComponent(url)}&title=${encodeURIComponent(title)}`;
|
|
454
|
+
},
|
|
455
|
+
telegram: (url, text) => {
|
|
456
|
+
return `https://t.me/share/url?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`;
|
|
457
|
+
},
|
|
458
|
+
email: (url, title, description) => {
|
|
459
|
+
return `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(description + "\n\n" + url)}`;
|
|
460
|
+
}
|
|
461
|
+
};
|
|
462
|
+
const ShareDropdown = ({
|
|
463
|
+
shareConfig
|
|
464
|
+
}) => {
|
|
465
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
466
|
+
const [shareUrl, setShareUrl] = useState("");
|
|
467
|
+
const [isPreparingShare, setIsPreparingShare] = useState(false);
|
|
468
|
+
const [showCopiedFeedback, setShowCopiedFeedback] = useState(false);
|
|
469
|
+
React.useEffect(() => {
|
|
470
|
+
const onBeforeShare = shareConfig.onBeforeShare;
|
|
471
|
+
if (onBeforeShare && !shareUrl) {
|
|
472
|
+
const prepareUrl = async () => {
|
|
473
|
+
setIsPreparingShare(true);
|
|
474
|
+
try {
|
|
475
|
+
const baseUrl = typeof window !== "undefined" ? window.location.href : "";
|
|
476
|
+
const modifiedUrl = await onBeforeShare(baseUrl);
|
|
477
|
+
setShareUrl(modifiedUrl);
|
|
478
|
+
} catch {
|
|
479
|
+
const baseUrl = typeof window !== "undefined" ? window.location.href : "";
|
|
480
|
+
setShareUrl(baseUrl);
|
|
481
|
+
} finally {
|
|
482
|
+
setIsPreparingShare(false);
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
prepareUrl();
|
|
486
|
+
}
|
|
487
|
+
}, [shareConfig, shareUrl]);
|
|
488
|
+
const url = shareUrl || (typeof window !== "undefined" ? window.location.href : "");
|
|
489
|
+
const copyToClipboard = async () => {
|
|
490
|
+
try {
|
|
491
|
+
await navigator.clipboard.writeText(url);
|
|
492
|
+
setShowCopiedFeedback(true);
|
|
493
|
+
setTimeout(() => {
|
|
494
|
+
setShowCopiedFeedback(false);
|
|
495
|
+
setIsOpen(false);
|
|
496
|
+
}, 1500);
|
|
497
|
+
} catch {
|
|
498
|
+
}
|
|
499
|
+
};
|
|
500
|
+
const handleSocialShare = (platformUrl) => {
|
|
501
|
+
window.open(
|
|
502
|
+
platformUrl,
|
|
503
|
+
"_blank",
|
|
504
|
+
"noopener,noreferrer,width=600,height=400"
|
|
505
|
+
);
|
|
506
|
+
setIsOpen(false);
|
|
507
|
+
};
|
|
508
|
+
const sharePlatforms = [
|
|
509
|
+
{
|
|
510
|
+
name: "Twitter",
|
|
511
|
+
url: createShareUrl.twitter(url, shareConfig.title, shareConfig.hashtags),
|
|
512
|
+
color: "text-blue-400"
|
|
513
|
+
},
|
|
514
|
+
{
|
|
515
|
+
name: "Facebook",
|
|
516
|
+
url: createShareUrl.facebook(url),
|
|
517
|
+
color: "text-blue-600"
|
|
518
|
+
},
|
|
519
|
+
{
|
|
520
|
+
name: "LinkedIn",
|
|
521
|
+
url: createShareUrl.linkedin(url),
|
|
522
|
+
color: "text-blue-700"
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
name: "Reddit",
|
|
526
|
+
url: createShareUrl.reddit(url, shareConfig.title),
|
|
527
|
+
color: "text-orange-600"
|
|
528
|
+
},
|
|
529
|
+
{
|
|
530
|
+
name: "Telegram",
|
|
531
|
+
url: createShareUrl.telegram(url, shareConfig.title),
|
|
532
|
+
color: "text-blue-500"
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
name: "Email",
|
|
536
|
+
url: createShareUrl.email(
|
|
537
|
+
url,
|
|
538
|
+
shareConfig.title,
|
|
539
|
+
shareConfig.description
|
|
540
|
+
),
|
|
541
|
+
color: "text-gray-600"
|
|
542
|
+
}
|
|
543
|
+
];
|
|
544
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
545
|
+
/* @__PURE__ */ jsx(
|
|
546
|
+
"button",
|
|
547
|
+
{
|
|
548
|
+
onClick: () => setIsOpen(!isOpen),
|
|
549
|
+
disabled: isPreparingShare,
|
|
550
|
+
className: "flex items-center justify-center w-8 h-8 bg-blue-50 hover:bg-blue-100 dark:bg-blue-900/30 dark:hover:bg-blue-900/50 text-blue-600 dark:text-blue-400 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed",
|
|
551
|
+
title: "Share this page",
|
|
552
|
+
children: isPreparingShare ? /* @__PURE__ */ jsx("div", { className: "w-4 h-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" }) : /* @__PURE__ */ jsx(
|
|
553
|
+
"svg",
|
|
554
|
+
{
|
|
555
|
+
className: "w-4 h-4",
|
|
556
|
+
fill: "none",
|
|
557
|
+
stroke: "currentColor",
|
|
558
|
+
viewBox: "0 0 24 24",
|
|
559
|
+
children: /* @__PURE__ */ jsx(
|
|
560
|
+
"path",
|
|
561
|
+
{
|
|
562
|
+
strokeLinecap: "round",
|
|
563
|
+
strokeLinejoin: "round",
|
|
564
|
+
strokeWidth: 2,
|
|
565
|
+
d: "M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.367 2.684 3 3 0 00-5.367-2.684z"
|
|
566
|
+
}
|
|
567
|
+
)
|
|
568
|
+
}
|
|
569
|
+
)
|
|
570
|
+
}
|
|
571
|
+
),
|
|
572
|
+
isOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
573
|
+
/* @__PURE__ */ jsx(
|
|
574
|
+
"div",
|
|
575
|
+
{
|
|
576
|
+
className: "fixed inset-0 z-[999998]",
|
|
577
|
+
onClick: () => setIsOpen(false)
|
|
578
|
+
}
|
|
579
|
+
),
|
|
580
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute right-0 top-10 z-[999999] w-40 bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-700 py-1", children: [
|
|
581
|
+
sharePlatforms.map((platform) => /* @__PURE__ */ jsx(
|
|
582
|
+
"button",
|
|
583
|
+
{
|
|
584
|
+
onClick: () => handleSocialShare(platform.url),
|
|
585
|
+
className: "w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors",
|
|
586
|
+
children: /* @__PURE__ */ jsx("span", { className: `text-sm ${platform.color}`, children: platform.name })
|
|
587
|
+
},
|
|
588
|
+
platform.name
|
|
589
|
+
)),
|
|
590
|
+
/* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 dark:border-gray-700 my-1" }),
|
|
591
|
+
/* @__PURE__ */ jsx(
|
|
592
|
+
"button",
|
|
593
|
+
{
|
|
594
|
+
onClick: copyToClipboard,
|
|
595
|
+
className: "w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors",
|
|
596
|
+
children: /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: showCopiedFeedback ? "Copied!" : "Copy Link" })
|
|
597
|
+
}
|
|
598
|
+
)
|
|
599
|
+
] })
|
|
600
|
+
] })
|
|
601
|
+
] });
|
|
602
|
+
};
|
|
603
|
+
const TalkToFounderButton = ({
|
|
604
|
+
config
|
|
605
|
+
}) => {
|
|
441
606
|
const IconComponent = config.icon || CalendarDaysIcon;
|
|
442
607
|
const buttonText = config.buttonText || "Talk to Founder";
|
|
443
608
|
return /* @__PURE__ */ jsxs(
|
|
@@ -447,14 +612,13 @@ const TalkToFounderButton = ({ config }) => {
|
|
|
447
612
|
target: "_blank",
|
|
448
613
|
rel: "noopener noreferrer",
|
|
449
614
|
className: cn(
|
|
450
|
-
"inline-flex items-center gap-
|
|
615
|
+
"inline-flex items-center gap-1.5 px-2.5 h-8",
|
|
451
616
|
"text-sm font-medium",
|
|
452
617
|
"text-blue-600 dark:text-blue-400",
|
|
453
618
|
"hover:text-blue-700 dark:hover:text-blue-300",
|
|
454
|
-
"bg-blue-50 dark:bg-blue-900/
|
|
455
|
-
"hover:bg-blue-100 dark:hover:bg-blue-900/
|
|
456
|
-
"rounded-
|
|
457
|
-
"border border-blue-200 dark:border-blue-800",
|
|
619
|
+
"bg-blue-50 dark:bg-blue-900/30",
|
|
620
|
+
"hover:bg-blue-100 dark:hover:bg-blue-900/50",
|
|
621
|
+
"rounded-lg",
|
|
458
622
|
"transition-colors"
|
|
459
623
|
),
|
|
460
624
|
children: [
|
|
@@ -475,9 +639,22 @@ const AppBreadcrumbs = ({
|
|
|
475
639
|
if (!items || items.length === 0) {
|
|
476
640
|
return null;
|
|
477
641
|
}
|
|
478
|
-
return /* @__PURE__ */ jsx("div", { className: cn(breadcrumbContainerVariants({ variant }), className), children: /* @__PURE__ */ jsx("div", { className: cn("max-w-7xl mx-auto px-4 py-
|
|
479
|
-
/* @__PURE__ */ jsx("
|
|
480
|
-
|
|
642
|
+
return /* @__PURE__ */ jsx("div", { className: cn(breadcrumbContainerVariants({ variant }), className), children: /* @__PURE__ */ jsx("div", { className: cn("max-w-7xl mx-auto px-4 py-2", contentClassName), children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
643
|
+
/* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", children: /* @__PURE__ */ jsx("ol", { className: "flex items-center text-sm space-x-2", children: items.map((item, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
644
|
+
/* @__PURE__ */ jsx("li", { children: item.current || !item.href ? /* @__PURE__ */ jsx("span", { className: "text-gray-700 dark:text-gray-300", children: item.label }) : /* @__PURE__ */ jsx(
|
|
645
|
+
"a",
|
|
646
|
+
{
|
|
647
|
+
href: item.href,
|
|
648
|
+
className: "text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 transition-colors",
|
|
649
|
+
children: item.label
|
|
650
|
+
}
|
|
651
|
+
) }),
|
|
652
|
+
index < items.length - 1 && /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("span", { className: "text-gray-400 dark:text-gray-500", children: "/" }) })
|
|
653
|
+
] }, index)) }) }),
|
|
654
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
655
|
+
talkToFounder && /* @__PURE__ */ jsx(TalkToFounderButton, { config: talkToFounder }),
|
|
656
|
+
shareConfig && /* @__PURE__ */ jsx(ShareDropdown, { shareConfig })
|
|
657
|
+
] })
|
|
481
658
|
] }) }) });
|
|
482
659
|
};
|
|
483
660
|
const DefaultLinkComponent$1 = ({
|