@sudobility/building_blocks 0.0.46 → 0.0.48
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 +186 -10
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
|
@@ -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";
|
|
@@ -437,7 +437,171 @@ const breadcrumbContainerVariants = cva("border-b", {
|
|
|
437
437
|
variant: "default"
|
|
438
438
|
}
|
|
439
439
|
});
|
|
440
|
-
const
|
|
440
|
+
const createShareUrl = {
|
|
441
|
+
twitter: (url, text, hashtags) => {
|
|
442
|
+
const hashtagStr = hashtags.length > 0 ? `&hashtags=${hashtags.join(",")}` : "";
|
|
443
|
+
return `https://twitter.com/intent/tweet?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}${hashtagStr}`;
|
|
444
|
+
},
|
|
445
|
+
facebook: (url) => {
|
|
446
|
+
return `https://www.facebook.com/sharer/sharer.php?u=${encodeURIComponent(url)}`;
|
|
447
|
+
},
|
|
448
|
+
linkedin: (url) => {
|
|
449
|
+
return `https://www.linkedin.com/sharing/share-offsite/?url=${encodeURIComponent(url)}`;
|
|
450
|
+
},
|
|
451
|
+
reddit: (url, title) => {
|
|
452
|
+
return `https://reddit.com/submit?url=${encodeURIComponent(url)}&title=${encodeURIComponent(title)}`;
|
|
453
|
+
},
|
|
454
|
+
telegram: (url, text) => {
|
|
455
|
+
return `https://t.me/share/url?url=${encodeURIComponent(url)}&text=${encodeURIComponent(text)}`;
|
|
456
|
+
},
|
|
457
|
+
email: (url, title, description) => {
|
|
458
|
+
return `mailto:?subject=${encodeURIComponent(title)}&body=${encodeURIComponent(description + "\n\n" + url)}`;
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
const ShareDropdown = ({
|
|
462
|
+
shareConfig
|
|
463
|
+
}) => {
|
|
464
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
465
|
+
const [shareUrl, setShareUrl] = useState("");
|
|
466
|
+
const [isPreparingShare, setIsPreparingShare] = useState(false);
|
|
467
|
+
const [showCopiedFeedback, setShowCopiedFeedback] = useState(false);
|
|
468
|
+
React.useEffect(() => {
|
|
469
|
+
const onBeforeShare = shareConfig.onBeforeShare;
|
|
470
|
+
if (onBeforeShare && !shareUrl) {
|
|
471
|
+
const prepareUrl = async () => {
|
|
472
|
+
setIsPreparingShare(true);
|
|
473
|
+
try {
|
|
474
|
+
const baseUrl = typeof window !== "undefined" ? window.location.href : "";
|
|
475
|
+
const modifiedUrl = await onBeforeShare(baseUrl);
|
|
476
|
+
setShareUrl(modifiedUrl);
|
|
477
|
+
} catch {
|
|
478
|
+
const baseUrl = typeof window !== "undefined" ? window.location.href : "";
|
|
479
|
+
setShareUrl(baseUrl);
|
|
480
|
+
} finally {
|
|
481
|
+
setIsPreparingShare(false);
|
|
482
|
+
}
|
|
483
|
+
};
|
|
484
|
+
prepareUrl();
|
|
485
|
+
}
|
|
486
|
+
}, [shareConfig, shareUrl]);
|
|
487
|
+
const url = shareUrl || (typeof window !== "undefined" ? window.location.href : "");
|
|
488
|
+
const copyToClipboard = async () => {
|
|
489
|
+
try {
|
|
490
|
+
await navigator.clipboard.writeText(url);
|
|
491
|
+
setShowCopiedFeedback(true);
|
|
492
|
+
setTimeout(() => {
|
|
493
|
+
setShowCopiedFeedback(false);
|
|
494
|
+
setIsOpen(false);
|
|
495
|
+
}, 1500);
|
|
496
|
+
} catch {
|
|
497
|
+
}
|
|
498
|
+
};
|
|
499
|
+
const handleSocialShare = (platformUrl) => {
|
|
500
|
+
window.open(
|
|
501
|
+
platformUrl,
|
|
502
|
+
"_blank",
|
|
503
|
+
"noopener,noreferrer,width=600,height=400"
|
|
504
|
+
);
|
|
505
|
+
setIsOpen(false);
|
|
506
|
+
};
|
|
507
|
+
const sharePlatforms = [
|
|
508
|
+
{
|
|
509
|
+
name: "Twitter",
|
|
510
|
+
url: createShareUrl.twitter(url, shareConfig.title, shareConfig.hashtags),
|
|
511
|
+
color: "text-blue-400"
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
name: "Facebook",
|
|
515
|
+
url: createShareUrl.facebook(url),
|
|
516
|
+
color: "text-blue-600"
|
|
517
|
+
},
|
|
518
|
+
{
|
|
519
|
+
name: "LinkedIn",
|
|
520
|
+
url: createShareUrl.linkedin(url),
|
|
521
|
+
color: "text-blue-700"
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
name: "Reddit",
|
|
525
|
+
url: createShareUrl.reddit(url, shareConfig.title),
|
|
526
|
+
color: "text-orange-600"
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
name: "Telegram",
|
|
530
|
+
url: createShareUrl.telegram(url, shareConfig.title),
|
|
531
|
+
color: "text-blue-500"
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
name: "Email",
|
|
535
|
+
url: createShareUrl.email(
|
|
536
|
+
url,
|
|
537
|
+
shareConfig.title,
|
|
538
|
+
shareConfig.description
|
|
539
|
+
),
|
|
540
|
+
color: "text-gray-600"
|
|
541
|
+
}
|
|
542
|
+
];
|
|
543
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
544
|
+
/* @__PURE__ */ jsx(
|
|
545
|
+
"button",
|
|
546
|
+
{
|
|
547
|
+
onClick: () => setIsOpen(!isOpen),
|
|
548
|
+
disabled: isPreparingShare,
|
|
549
|
+
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",
|
|
550
|
+
title: "Share this page",
|
|
551
|
+
children: isPreparingShare ? /* @__PURE__ */ jsx("div", { className: "w-4 h-4 border-2 border-blue-600 border-t-transparent rounded-full animate-spin" }) : /* @__PURE__ */ jsx(
|
|
552
|
+
"svg",
|
|
553
|
+
{
|
|
554
|
+
className: "w-4 h-4",
|
|
555
|
+
fill: "none",
|
|
556
|
+
stroke: "currentColor",
|
|
557
|
+
viewBox: "0 0 24 24",
|
|
558
|
+
children: /* @__PURE__ */ jsx(
|
|
559
|
+
"path",
|
|
560
|
+
{
|
|
561
|
+
strokeLinecap: "round",
|
|
562
|
+
strokeLinejoin: "round",
|
|
563
|
+
strokeWidth: 2,
|
|
564
|
+
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"
|
|
565
|
+
}
|
|
566
|
+
)
|
|
567
|
+
}
|
|
568
|
+
)
|
|
569
|
+
}
|
|
570
|
+
),
|
|
571
|
+
isOpen && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
572
|
+
/* @__PURE__ */ jsx(
|
|
573
|
+
"div",
|
|
574
|
+
{
|
|
575
|
+
className: "fixed inset-0 z-[999998]",
|
|
576
|
+
onClick: () => setIsOpen(false)
|
|
577
|
+
}
|
|
578
|
+
),
|
|
579
|
+
/* @__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: [
|
|
580
|
+
sharePlatforms.map((platform) => /* @__PURE__ */ jsx(
|
|
581
|
+
"button",
|
|
582
|
+
{
|
|
583
|
+
onClick: () => handleSocialShare(platform.url),
|
|
584
|
+
className: "w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors",
|
|
585
|
+
children: /* @__PURE__ */ jsx("span", { className: `text-sm ${platform.color}`, children: platform.name })
|
|
586
|
+
},
|
|
587
|
+
platform.name
|
|
588
|
+
)),
|
|
589
|
+
/* @__PURE__ */ jsx("div", { className: "border-t border-gray-200 dark:border-gray-700 my-1" }),
|
|
590
|
+
/* @__PURE__ */ jsx(
|
|
591
|
+
"button",
|
|
592
|
+
{
|
|
593
|
+
onClick: copyToClipboard,
|
|
594
|
+
className: "w-full flex items-center px-3 py-1.5 hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer transition-colors",
|
|
595
|
+
children: /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-700 dark:text-gray-300", children: showCopiedFeedback ? "Copied!" : "Copy Link" })
|
|
596
|
+
}
|
|
597
|
+
)
|
|
598
|
+
] })
|
|
599
|
+
] })
|
|
600
|
+
] });
|
|
601
|
+
};
|
|
602
|
+
const TalkToFounderButton = ({
|
|
603
|
+
config
|
|
604
|
+
}) => {
|
|
441
605
|
const IconComponent = config.icon || CalendarDaysIcon;
|
|
442
606
|
const buttonText = config.buttonText || "Talk to Founder";
|
|
443
607
|
return /* @__PURE__ */ jsxs(
|
|
@@ -447,14 +611,13 @@ const TalkToFounderButton = ({ config }) => {
|
|
|
447
611
|
target: "_blank",
|
|
448
612
|
rel: "noopener noreferrer",
|
|
449
613
|
className: cn(
|
|
450
|
-
"inline-flex items-center gap-
|
|
614
|
+
"inline-flex items-center gap-1.5 px-2.5 h-8",
|
|
451
615
|
"text-sm font-medium",
|
|
452
616
|
"text-blue-600 dark:text-blue-400",
|
|
453
617
|
"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",
|
|
618
|
+
"bg-blue-50 dark:bg-blue-900/30",
|
|
619
|
+
"hover:bg-blue-100 dark:hover:bg-blue-900/50",
|
|
620
|
+
"rounded-lg",
|
|
458
621
|
"transition-colors"
|
|
459
622
|
),
|
|
460
623
|
children: [
|
|
@@ -475,9 +638,22 @@ const AppBreadcrumbs = ({
|
|
|
475
638
|
if (!items || items.length === 0) {
|
|
476
639
|
return null;
|
|
477
640
|
}
|
|
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
|
-
|
|
641
|
+
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: [
|
|
642
|
+
/* @__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: [
|
|
643
|
+
/* @__PURE__ */ jsx("li", { children: item.current || !item.href ? /* @__PURE__ */ jsx("span", { className: "text-gray-700 dark:text-gray-300", children: item.label }) : /* @__PURE__ */ jsx(
|
|
644
|
+
"a",
|
|
645
|
+
{
|
|
646
|
+
href: item.href,
|
|
647
|
+
className: "text-blue-600 dark:text-blue-400 hover:text-blue-800 dark:hover:text-blue-300 transition-colors",
|
|
648
|
+
children: item.label
|
|
649
|
+
}
|
|
650
|
+
) }),
|
|
651
|
+
index < items.length - 1 && /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("span", { className: "text-gray-400 dark:text-gray-500", children: "/" }) })
|
|
652
|
+
] }, index)) }) }),
|
|
653
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
654
|
+
talkToFounder && /* @__PURE__ */ jsx(TalkToFounderButton, { config: talkToFounder }),
|
|
655
|
+
shareConfig && /* @__PURE__ */ jsx(ShareDropdown, { shareConfig })
|
|
656
|
+
] })
|
|
481
657
|
] }) }) });
|
|
482
658
|
};
|
|
483
659
|
const DefaultLinkComponent$1 = ({
|