keystone-design-bootstrap 1.0.3

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 (182) hide show
  1. package/README.md +179 -0
  2. package/package.json +59 -0
  3. package/src/contexts/ThemeContext.tsx +34 -0
  4. package/src/contexts/index.ts +1 -0
  5. package/src/design_system/elements/IconComponent.tsx +98 -0
  6. package/src/design_system/elements/avatar/avatar-label-group.tsx +30 -0
  7. package/src/design_system/elements/avatar/avatar-profile-photo.tsx +125 -0
  8. package/src/design_system/elements/avatar/avatar.tsx +131 -0
  9. package/src/design_system/elements/avatar/base-components/avatar-add-button.tsx +34 -0
  10. package/src/design_system/elements/avatar/base-components/avatar-company-icon.tsx +26 -0
  11. package/src/design_system/elements/avatar/base-components/avatar-online-indicator.tsx +31 -0
  12. package/src/design_system/elements/avatar/base-components/index.tsx +4 -0
  13. package/src/design_system/elements/avatar/base-components/verified-tick.tsx +34 -0
  14. package/src/design_system/elements/avatar/utils.ts +12 -0
  15. package/src/design_system/elements/badges/avatar.tsx +132 -0
  16. package/src/design_system/elements/badges/badge-groups.tsx +176 -0
  17. package/src/design_system/elements/badges/badge-types.ts +266 -0
  18. package/src/design_system/elements/badges/badges.tsx +430 -0
  19. package/src/design_system/elements/breadcrumb/Breadcrumb.tsx +33 -0
  20. package/src/design_system/elements/button-group/button-group.tsx +106 -0
  21. package/src/design_system/elements/buttons/app-store-buttons-outline.tsx +378 -0
  22. package/src/design_system/elements/buttons/app-store-buttons.tsx +567 -0
  23. package/src/design_system/elements/buttons/button-utility.tsx +116 -0
  24. package/src/design_system/elements/buttons/button.aman.tsx +174 -0
  25. package/src/design_system/elements/buttons/button.tsx +271 -0
  26. package/src/design_system/elements/buttons/close-button.tsx +42 -0
  27. package/src/design_system/elements/buttons/round-button.tsx +29 -0
  28. package/src/design_system/elements/buttons/social-button.tsx +148 -0
  29. package/src/design_system/elements/buttons/social-logos.tsx +115 -0
  30. package/src/design_system/elements/carousel/carousel-base.tsx +308 -0
  31. package/src/design_system/elements/carousel/carousel.tsx +308 -0
  32. package/src/design_system/elements/checkbox/checkbox.tsx +120 -0
  33. package/src/design_system/elements/date-picker/calendar.tsx +101 -0
  34. package/src/design_system/elements/date-picker/cell.tsx +106 -0
  35. package/src/design_system/elements/date-picker/date-input.tsx +32 -0
  36. package/src/design_system/elements/date-picker/date-picker.tsx +86 -0
  37. package/src/design_system/elements/date-picker/date-range-picker.tsx +163 -0
  38. package/src/design_system/elements/date-picker/range-calendar.tsx +161 -0
  39. package/src/design_system/elements/date-picker/range-preset.tsx +28 -0
  40. package/src/design_system/elements/featured-icon/featured-icon.tsx +154 -0
  41. package/src/design_system/elements/form/form.tsx +10 -0
  42. package/src/design_system/elements/form/hook-form.tsx +75 -0
  43. package/src/design_system/elements/hint-text/hint-text.tsx +33 -0
  44. package/src/design_system/elements/index.tsx +158 -0
  45. package/src/design_system/elements/input/hint-text.tsx +33 -0
  46. package/src/design_system/elements/input/input-group.tsx +133 -0
  47. package/src/design_system/elements/input/input.aman.tsx +172 -0
  48. package/src/design_system/elements/input/input.tsx +271 -0
  49. package/src/design_system/elements/input/label.tsx +50 -0
  50. package/src/design_system/elements/label/label.tsx +50 -0
  51. package/src/design_system/elements/loading-indicator/loading-indicator.tsx +123 -0
  52. package/src/design_system/elements/map/GoogleMap.tsx +286 -0
  53. package/src/design_system/elements/markdown-renderer/MarkdownRenderer.tsx +155 -0
  54. package/src/design_system/elements/modals/modal.tsx +41 -0
  55. package/src/design_system/elements/pagination/pagination-base.tsx +378 -0
  56. package/src/design_system/elements/pagination/pagination-dot.tsx +54 -0
  57. package/src/design_system/elements/pagination/pagination-line.tsx +50 -0
  58. package/src/design_system/elements/pagination/pagination.tsx +330 -0
  59. package/src/design_system/elements/photo-fallback/photo-fallback.tsx +143 -0
  60. package/src/design_system/elements/progress-indicators/progress-circles.tsx +176 -0
  61. package/src/design_system/elements/progress-indicators/progress-indicators.tsx +123 -0
  62. package/src/design_system/elements/progress-indicators/simple-circle.tsx +29 -0
  63. package/src/design_system/elements/radio-buttons/radio-buttons.tsx +129 -0
  64. package/src/design_system/elements/rating/rating-badge.tsx +144 -0
  65. package/src/design_system/elements/rating/rating-stars.tsx +77 -0
  66. package/src/design_system/elements/select/combobox.tsx +152 -0
  67. package/src/design_system/elements/select/multi-select.tsx +363 -0
  68. package/src/design_system/elements/select/popover.tsx +34 -0
  69. package/src/design_system/elements/select/select-item.tsx +97 -0
  70. package/src/design_system/elements/select/select-native.tsx +69 -0
  71. package/src/design_system/elements/select/select.aman.tsx +75 -0
  72. package/src/design_system/elements/select/select.tsx +146 -0
  73. package/src/design_system/elements/shared-assets/credit-card/credit-card.tsx +237 -0
  74. package/src/design_system/elements/shared-assets/credit-card/icons.tsx +75 -0
  75. package/src/design_system/elements/shared-assets/iphone-mockup.tsx +172 -0
  76. package/src/design_system/elements/shared-assets/section-divider.tsx +12 -0
  77. package/src/design_system/elements/slideout-menus/slideout-menu.tsx +122 -0
  78. package/src/design_system/elements/tabs/tabs.tsx +225 -0
  79. package/src/design_system/elements/tags/base-components/tag-checkbox.tsx +45 -0
  80. package/src/design_system/elements/tags/base-components/tag-close-x.tsx +34 -0
  81. package/src/design_system/elements/tags/tags.tsx +176 -0
  82. package/src/design_system/elements/textarea/textarea.aman.tsx +52 -0
  83. package/src/design_system/elements/textarea/textarea.tsx +111 -0
  84. package/src/design_system/elements/toggle/toggle.tsx +140 -0
  85. package/src/design_system/elements/tooltip/tooltip.tsx +109 -0
  86. package/src/design_system/hooks/use-breakpoint.ts +37 -0
  87. package/src/design_system/hooks/use-resize-observer.ts +68 -0
  88. package/src/design_system/logo/keystone-logo-minimal.tsx +93 -0
  89. package/src/design_system/logo/keystone-logo.tsx +22 -0
  90. package/src/design_system/sections/about-home.aman.tsx +85 -0
  91. package/src/design_system/sections/about-home.tsx +115 -0
  92. package/src/design_system/sections/blog-cards.tsx +848 -0
  93. package/src/design_system/sections/blog-gallery.aman.tsx +77 -0
  94. package/src/design_system/sections/blog-gallery.tsx +204 -0
  95. package/src/design_system/sections/blog-home.aman.tsx +84 -0
  96. package/src/design_system/sections/blog-home.tsx +153 -0
  97. package/src/design_system/sections/blog-post.aman.tsx +74 -0
  98. package/src/design_system/sections/blog-post.tsx +301 -0
  99. package/src/design_system/sections/blog-section.aman.tsx +101 -0
  100. package/src/design_system/sections/blog-section.tsx +179 -0
  101. package/src/design_system/sections/contact-home.tsx +25 -0
  102. package/src/design_system/sections/contact-section.aman.tsx +173 -0
  103. package/src/design_system/sections/contact-section.tsx +143 -0
  104. package/src/design_system/sections/faq-grid.aman.tsx +79 -0
  105. package/src/design_system/sections/faq-grid.tsx +102 -0
  106. package/src/design_system/sections/faq-home.aman.tsx +92 -0
  107. package/src/design_system/sections/faq-home.tsx +134 -0
  108. package/src/design_system/sections/feature-tab.tsx +43 -0
  109. package/src/design_system/sections/feature-text.tsx +284 -0
  110. package/src/design_system/sections/footer-home.aman.tsx +62 -0
  111. package/src/design_system/sections/footer-home.tsx +259 -0
  112. package/src/design_system/sections/generic-header-component.tsx +103 -0
  113. package/src/design_system/sections/header-navigation.aman.tsx +360 -0
  114. package/src/design_system/sections/header-navigation.tsx +334 -0
  115. package/src/design_system/sections/hero-faq.aman.tsx +38 -0
  116. package/src/design_system/sections/hero-faq.tsx +55 -0
  117. package/src/design_system/sections/hero-generic-text.aman.tsx +49 -0
  118. package/src/design_system/sections/hero-generic-text.tsx +51 -0
  119. package/src/design_system/sections/hero-home.aman.tsx +84 -0
  120. package/src/design_system/sections/hero-home.tsx +246 -0
  121. package/src/design_system/sections/hero-location-detail.aman.tsx +33 -0
  122. package/src/design_system/sections/hero-location-detail.tsx +72 -0
  123. package/src/design_system/sections/hero-service-detail.aman.tsx +53 -0
  124. package/src/design_system/sections/hero-service-detail.tsx +51 -0
  125. package/src/design_system/sections/hero-social-media.aman.tsx +42 -0
  126. package/src/design_system/sections/hero-social-media.tsx +35 -0
  127. package/src/design_system/sections/hero-testimonials.aman.tsx +38 -0
  128. package/src/design_system/sections/hero-testimonials.tsx +55 -0
  129. package/src/design_system/sections/home-hero-component.tsx +228 -0
  130. package/src/design_system/sections/index.tsx +131 -0
  131. package/src/design_system/sections/job-gallery.aman.tsx +91 -0
  132. package/src/design_system/sections/job-gallery.tsx +183 -0
  133. package/src/design_system/sections/location-details-section.aman.tsx +179 -0
  134. package/src/design_system/sections/location-details-section.tsx +196 -0
  135. package/src/design_system/sections/location-grid.aman.tsx +76 -0
  136. package/src/design_system/sections/location-grid.tsx +123 -0
  137. package/src/design_system/sections/services-grid.aman.tsx +85 -0
  138. package/src/design_system/sections/services-grid.tsx +104 -0
  139. package/src/design_system/sections/services-home.aman.tsx +78 -0
  140. package/src/design_system/sections/services-home.tsx +131 -0
  141. package/src/design_system/sections/social-media-grid.aman.tsx +132 -0
  142. package/src/design_system/sections/social-media-grid.tsx +189 -0
  143. package/src/design_system/sections/statistics-section.aman.tsx +79 -0
  144. package/src/design_system/sections/statistics-section.tsx +97 -0
  145. package/src/design_system/sections/team-grid.aman.tsx +85 -0
  146. package/src/design_system/sections/team-grid.tsx +88 -0
  147. package/src/design_system/sections/testimonials-home.aman.tsx +113 -0
  148. package/src/design_system/sections/testimonials-home.tsx +90 -0
  149. package/src/design_system/sections/values-section.aman.tsx +73 -0
  150. package/src/design_system/sections/values-section.tsx +128 -0
  151. package/src/design_system/utils/icon-mapping.tsx +28 -0
  152. package/src/index.ts +7 -0
  153. package/src/lib/component-registry.ts +53 -0
  154. package/src/lib/hooks/index.ts +8 -0
  155. package/src/lib/hooks/use-breakpoint.ts +37 -0
  156. package/src/lib/hooks/use-clipboard.ts +79 -0
  157. package/src/lib/hooks/use-resize-observer.ts +68 -0
  158. package/src/lib/server-api.ts +115 -0
  159. package/src/styles/style-overrides.aman.css +101 -0
  160. package/src/styles/theme.css +224 -0
  161. package/src/styles/typography.css +430 -0
  162. package/src/themes/index.ts +23 -0
  163. package/src/types/api/blog-post.ts +53 -0
  164. package/src/types/api/company-information.ts +44 -0
  165. package/src/types/api/contact.ts +63 -0
  166. package/src/types/api/faq.ts +37 -0
  167. package/src/types/api/job-posting.ts +34 -0
  168. package/src/types/api/location.ts +36 -0
  169. package/src/types/api/photos.ts +28 -0
  170. package/src/types/api/service.ts +37 -0
  171. package/src/types/api/social-post.ts +28 -0
  172. package/src/types/api/team-member.ts +29 -0
  173. package/src/types/api/testimonial.ts +29 -0
  174. package/src/types/api/website-photos.ts +22 -0
  175. package/src/types/config.ts +21 -0
  176. package/src/types/index.ts +21 -0
  177. package/src/utils/countries.tsx +1351 -0
  178. package/src/utils/cx.ts +25 -0
  179. package/src/utils/gradient-placeholder.ts +59 -0
  180. package/src/utils/is-react-component.ts +33 -0
  181. package/src/utils/markdown-toc.ts +54 -0
  182. package/src/utils/photo-helpers.ts +94 -0
@@ -0,0 +1,134 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { motion } from "motion/react";
5
+ import { cx } from '../../utils/cx';
6
+ import type { FaqQuestion } from '../../types/api/faq';
7
+
8
+
9
+ interface FAQHomeProps {
10
+ config: {
11
+ pages?: any[];
12
+ };
13
+ faqs: FaqQuestion[];
14
+ pageName?: string;
15
+ sectionKey?: string;
16
+ }
17
+
18
+ export const FAQHome = ({
19
+ config,
20
+ faqs: faqsData,
21
+ pageName = 'Home',
22
+ sectionKey = 'home_page_section_4_faq',
23
+ }: FAQHomeProps) => {
24
+ const items = Array.isArray(faqsData) ? faqsData : [];
25
+
26
+ // Extract values from config
27
+ const faqSection = pageName === 'Home'
28
+ const title = "Frequently asked questions";
29
+ const subtitle = "";
30
+ const maxItems = undefined;
31
+ const [openQuestions, setOpenQuestions] = useState<Set<number>>(new Set([0]));
32
+
33
+ const handleToggle = (index: number) => {
34
+ const newSet = new Set(openQuestions);
35
+ if (newSet.has(index)) {
36
+ newSet.delete(index);
37
+ } else {
38
+ newSet.add(index);
39
+ }
40
+ setOpenQuestions(newSet);
41
+ };
42
+
43
+ const displayItems = maxItems ? items.slice(0, maxItems) : items;
44
+
45
+ return (
46
+ <section className="bg-primary py-16 md:py-24">
47
+ <div className="mx-auto max-w-container px-4 md:px-8">
48
+ <div className="mx-auto flex w-full max-w-3xl flex-col items-center text-center">
49
+ <h2 className="text-display-sm font-semibold text-primary md:text-display-md">
50
+ {title}
51
+ </h2>
52
+ <p className="mt-4 text-lg text-tertiary md:mt-5 md:text-xl">
53
+ {subtitle}
54
+ </p>
55
+ </div>
56
+
57
+ {displayItems && displayItems.length > 0 ? (
58
+ <div className="mx-auto mt-12 max-w-3xl md:mt-16">
59
+ <div className="flex flex-col gap-4">
60
+ {displayItems.map((faq, index) => (
61
+ <div
62
+ key={faq.id || index}
63
+ className={cx(
64
+ "rounded-2xl bg-transparent p-5 transition duration-300 ease-in-out md:p-6",
65
+ openQuestions.has(index) && "bg-secondary",
66
+ )}
67
+ >
68
+ <h3>
69
+ <button
70
+ onClick={() => handleToggle(index)}
71
+ className="flex w-full cursor-pointer gap-2 rounded-md text-left outline-focus-ring select-none focus-visible:outline-2 focus-visible:outline-offset-2 md:flex-row-reverse md:gap-4"
72
+ >
73
+ <span className="flex-1 text-md font-semibold text-primary">{faq.question}</span>
74
+ <span aria-hidden="true" className="flex size-6 items-center text-fg-quaternary">
75
+ <svg
76
+ width="24"
77
+ height="24"
78
+ viewBox="0 0 24 24"
79
+ fill="none"
80
+ stroke="currentColor"
81
+ strokeWidth="2"
82
+ strokeLinecap="round"
83
+ strokeLinejoin="round"
84
+ >
85
+ <circle cx="12" cy="12" r="10"></circle>
86
+ <line
87
+ className={cx(
88
+ "origin-center rotate-0 transition duration-150 ease-out",
89
+ openQuestions.has(index) && "-rotate-90",
90
+ )}
91
+ x1="12"
92
+ y1="8"
93
+ x2="12"
94
+ y2="16"
95
+ ></line>
96
+ <line x1="8" y1="12" x2="16" y2="12"></line>
97
+ </svg>
98
+ </span>
99
+ </button>
100
+ </h3>
101
+
102
+ <motion.div
103
+ className="overflow-hidden"
104
+ initial={false}
105
+ animate={{
106
+ height: openQuestions.has(index) ? "auto" : 0,
107
+ opacity: openQuestions.has(index) ? 1 : 0,
108
+ }}
109
+ transition={{
110
+ type: "spring",
111
+ damping: 24,
112
+ stiffness: 240,
113
+ bounce: 0.4,
114
+ }}
115
+ >
116
+ <div className="pt-1 pr-8 md:pr-0 md:pl-10">
117
+ <div className="text-md text-tertiary">
118
+ {faq.answer_markdown || ''}
119
+ </div>
120
+ </div>
121
+ </motion.div>
122
+ </div>
123
+ ))}
124
+ </div>
125
+ </div>
126
+ ) : (
127
+ <div className="text-center mt-12">
128
+ <p className="text-gray-500">No FAQ items available</p>
129
+ </div>
130
+ )}
131
+ </div>
132
+ </section>
133
+ );
134
+ };
@@ -0,0 +1,43 @@
1
+ "use client";
2
+
3
+ import { type ReactNode } from "react";
4
+ import { cx } from '../../utils/cx';
5
+
6
+ interface FeatureTabProps {
7
+ title: string;
8
+ subtitle: string;
9
+ footer?: ReactNode;
10
+ isCurrent?: boolean;
11
+ }
12
+
13
+ export const FeatureTabVertical = ({ title, subtitle, footer, isCurrent }: FeatureTabProps) => (
14
+ <div
15
+ className={cx(
16
+ "relative flex max-w-[405px] cursor-pointer flex-col items-center gap-4 border-t-4 border-tertiary pt-5 text-center transition duration-100 ease-linear hover:border-brand md:gap-5 md:px-4",
17
+ isCurrent && "border-brand",
18
+ )}
19
+ >
20
+ <div>
21
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
22
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
23
+ </div>
24
+
25
+ {footer}
26
+ </div>
27
+ );
28
+
29
+ export const FeatureTabHorizontal = ({ title, subtitle, footer, isCurrent }: FeatureTabProps) => (
30
+ <div
31
+ className={cx(
32
+ "relative flex cursor-pointer flex-col items-start gap-4 border-l-4 border-tertiary py-4 pl-5 transition duration-100 ease-linear hover:border-brand",
33
+ isCurrent && "border-brand",
34
+ )}
35
+ >
36
+ <div>
37
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
38
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
39
+ </div>
40
+
41
+ {footer}
42
+ </div>
43
+ );
@@ -0,0 +1,284 @@
1
+ "use client";
2
+
3
+ import type { FC } from "react";
4
+ import { type ReactNode } from "react";
5
+ import { FeaturedIcon } from '../elements';
6
+
7
+ interface TextCentered {
8
+ title: string;
9
+ subtitle: string;
10
+ footer?: ReactNode;
11
+ }
12
+
13
+ export const FeatureTextCentered = ({ title, subtitle, footer }: TextCentered) => (
14
+ <div className="flex max-w-sm flex-col items-center gap-4 text-center">
15
+ <div>
16
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
17
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
18
+ </div>
19
+
20
+ {footer}
21
+ </div>
22
+ );
23
+
24
+ export const FeatureTextLeft = ({ title, subtitle, footer }: TextCentered) => (
25
+ <div className="flex max-w-sm flex-col gap-4">
26
+ <div>
27
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
28
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
29
+ </div>
30
+
31
+ {footer}
32
+ </div>
33
+ );
34
+
35
+ interface FeatureTextIcon extends TextCentered {
36
+ icon: FC<{ className?: string }>;
37
+ }
38
+
39
+ export const FeatureTextIconTopCentered = ({ icon: Icon, title, subtitle, footer }: FeatureTextIcon) => (
40
+ <div className="flex max-w-sm flex-col items-center gap-3 text-center md:gap-4">
41
+ <Icon className="size-6 text-icon-fg-brand" />
42
+
43
+ <div>
44
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
45
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
46
+ </div>
47
+
48
+ {footer}
49
+ </div>
50
+ );
51
+
52
+ export const FeatureTextIconTopLeft = ({ icon: Icon, title, subtitle, footer }: FeatureTextIcon) => (
53
+ <div className="flex max-w-sm flex-col gap-4">
54
+ <Icon className="size-6 text-icon-fg-brand" />
55
+
56
+ <div>
57
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
58
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
59
+ </div>
60
+
61
+ {footer}
62
+ </div>
63
+ );
64
+
65
+ export const FeatureTextIconLeft = ({ icon: Icon, title, subtitle, footer }: FeatureTextIcon) => (
66
+ <div className="flex max-w-140 gap-4">
67
+ <Icon className="size-6 shrink-0 text-icon-fg-brand" />
68
+
69
+ <div className="flex flex-col gap-4">
70
+ <div>
71
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
72
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
73
+ </div>
74
+
75
+ {footer}
76
+ </div>
77
+ </div>
78
+ );
79
+
80
+ export const FeatureTextFeaturedIconTopCentered = ({
81
+ color = "gray",
82
+ theme = "modern",
83
+ icon,
84
+ title,
85
+ subtitle,
86
+ footer,
87
+ }: FeatureTextIcon & {
88
+ color?: "brand" | "gray" | "success" | "warning" | "error";
89
+ theme?: "light" | "gradient" | "dark" | "outline" | "modern";
90
+ }) => (
91
+ <div className="flex max-w-sm flex-col items-center gap-4 text-center">
92
+ <FeaturedIcon icon={icon} size="lg" color={color} theme={theme} className="hidden md:inline-flex" />
93
+ <FeaturedIcon icon={icon} size="md" color={color} theme={theme} className="inline-flex md:hidden" />
94
+
95
+ <div>
96
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
97
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
98
+ </div>
99
+
100
+ {footer}
101
+ </div>
102
+ );
103
+
104
+ export const FeatureTextFeaturedIconTopLeft = ({ icon, title, subtitle, footer }: FeatureTextIcon) => (
105
+ <div className="flex max-w-sm flex-col gap-4">
106
+ <FeaturedIcon icon={icon} size="lg" color="gray" theme="modern" className="hidden md:inline-flex" />
107
+ <FeaturedIcon icon={icon} size="md" color="gray" theme="modern" className="inline-flex md:hidden" />
108
+
109
+ <div>
110
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
111
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
112
+ </div>
113
+
114
+ {footer}
115
+ </div>
116
+ );
117
+
118
+ export const FeatureTextFeaturedIconLeft = ({ icon, title, subtitle, footer }: FeatureTextIcon) => (
119
+ <div className="flex max-w-140 gap-4">
120
+ <FeaturedIcon icon={icon} size="lg" color="gray" theme="modern" className="hidden md:inline-flex" />
121
+ <FeaturedIcon icon={icon} size="md" color="gray" theme="modern" className="inline-flex md:hidden" />
122
+
123
+ <div className="flex flex-col items-start gap-4">
124
+ <div>
125
+ <h3 className="mt-1.5 text-lg font-semibold text-primary md:mt-2.5">{title}</h3>
126
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
127
+ </div>
128
+
129
+ {footer}
130
+ </div>
131
+ </div>
132
+ );
133
+
134
+ export const FeatureTextFeaturedIconBox = ({ icon, title, subtitle, footer }: FeatureTextIcon) => (
135
+ <div className="mt-6 flex max-w-sm flex-col items-center gap-4 rounded-2xl bg-secondary px-6 pb-8 text-center">
136
+ <FeaturedIcon icon={icon} size="lg" color="gray" theme="modern" className="-mt-6" />
137
+
138
+ <div>
139
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
140
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
141
+ </div>
142
+
143
+ {footer}
144
+ </div>
145
+ );
146
+
147
+ interface FeatureTextIntegrationIcon extends TextCentered {
148
+ imgUrl: string;
149
+ }
150
+
151
+ export const FeatureTextIntegrationIconTopCentered = ({ imgUrl, title, subtitle, footer }: FeatureTextIntegrationIcon) => (
152
+ <div className="flex max-w-sm flex-col items-center gap-4 text-center">
153
+ <span className="flex size-13 shrink-0 items-center justify-center rounded-lg bg-primary shadow-xs ring-1 ring-secondary ring-inset md:size-16 md:rounded-xl">
154
+ <img alt={title} src={imgUrl} className="size-12 md:size-14" />
155
+ </span>
156
+
157
+ <div className="5 flex flex-col items-center gap-4">
158
+ <div>
159
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
160
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
161
+ </div>
162
+
163
+ {footer}
164
+ </div>
165
+ </div>
166
+ );
167
+
168
+ export const FeatureTextIntegrationIconTopLeft = ({ imgUrl, title, subtitle, footer }: FeatureTextIntegrationIcon) => (
169
+ <div className="flex max-w-sm flex-col gap-4">
170
+ <span className="flex size-13 shrink-0 items-center justify-center rounded-lg bg-primary shadow-xs ring-1 ring-secondary ring-inset md:size-16 md:rounded-xl">
171
+ <img alt={title} src={imgUrl} className="size-12 md:size-14" />
172
+ </span>
173
+
174
+ <div className="flex flex-col gap-4">
175
+ <div>
176
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
177
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
178
+ </div>
179
+
180
+ {footer}
181
+ </div>
182
+ </div>
183
+ );
184
+
185
+ export const FeatureTextIntegrationIconLeft = ({ imgUrl, title, subtitle, footer }: FeatureTextIntegrationIcon) => (
186
+ <div className="flex max-w-140 gap-4">
187
+ <span className="flex size-13 shrink-0 items-center justify-center rounded-lg bg-primary shadow-xs ring-1 ring-secondary ring-inset md:size-16 md:rounded-xl">
188
+ <img alt={title} src={imgUrl} className="size-12 md:size-14" />
189
+ </span>
190
+
191
+ <div className="flex flex-col gap-4">
192
+ <div>
193
+ <h3 className="mt-2.5 text-lg font-semibold text-primary md:mt-4">{title}</h3>
194
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
195
+ </div>
196
+
197
+ {footer}
198
+ </div>
199
+ </div>
200
+ );
201
+
202
+ export const FeatureTextIntegrationIconBox = ({ imgUrl, title, subtitle, footer }: FeatureTextIntegrationIcon) => (
203
+ <div className="mt-6 flex max-w-sm flex-col items-center gap-4 rounded-2xl bg-secondary px-6 pb-8 text-center">
204
+ <span className="-mt-[26px] flex size-13 shrink-0 items-center justify-center rounded-lg bg-primary shadow-xs ring-1 ring-secondary ring-inset md:-mt-8 md:size-16 md:rounded-xl">
205
+ <img alt={title} src={imgUrl} className="size-12 md:size-14" />
206
+ </span>
207
+
208
+ <div>
209
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
210
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
211
+ </div>
212
+
213
+ {footer}
214
+ </div>
215
+ );
216
+
217
+ export const FeatureTextIconCard = ({ icon: Icon, title, subtitle, footer }: FeatureTextIcon) => (
218
+ <div className="flex flex-col gap-8 bg-secondary p-5 md:max-w-71.5 md:gap-12 md:p-6">
219
+ <Icon className="size-6 text-icon-fg-brand" />
220
+
221
+ <div className="flex flex-col gap-4">
222
+ <div>
223
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
224
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
225
+ </div>
226
+
227
+ {footer}
228
+ </div>
229
+ </div>
230
+ );
231
+
232
+ export const FeatureTextFeaturedIconCard = ({ icon, title, subtitle, footer }: FeatureTextIcon) => (
233
+ <div className="flex flex-col gap-12 bg-secondary p-5 md:inline-flex md:gap-16 md:p-6">
234
+ <FeaturedIcon icon={icon} size="lg" color="gray" theme="light" />
235
+
236
+ <div className="flex flex-col gap-4">
237
+ <div>
238
+ <h3 className="text-lg font-semibold text-primary">{title}</h3>
239
+ <p className="mt-1 text-md text-tertiary">{subtitle}</p>
240
+ </div>
241
+
242
+ {footer}
243
+ </div>
244
+ </div>
245
+ );
246
+
247
+ export const FeatureTextLeftBrand = ({ title, subtitle, footer }: TextCentered) => (
248
+ <div className="flex max-w-sm flex-col gap-4">
249
+ <div>
250
+ <h3 className="text-lg font-semibold text-primary_on-brand">{title}</h3>
251
+ <p className="mt-1 text-md text-tertiary_on-brand">{subtitle}</p>
252
+ </div>
253
+
254
+ {footer}
255
+ </div>
256
+ );
257
+
258
+ export const FeatureTextFeaturedIconTopCenteredBrand = ({ icon, title, subtitle, footer }: FeatureTextIcon) => (
259
+ <div className="flex max-w-sm flex-col items-center gap-4 text-center">
260
+ <FeaturedIcon icon={icon} size="lg" color="brand" theme="dark" className="hidden md:inline-flex" />
261
+ <FeaturedIcon icon={icon} size="md" color="brand" theme="dark" className="inline-flex md:hidden" />
262
+
263
+ <div>
264
+ <h3 className="text-lg font-semibold text-primary_on-brand">{title}</h3>
265
+ <p className="mt-1 text-md text-tertiary_on-brand">{subtitle}</p>
266
+ </div>
267
+
268
+ {footer}
269
+ </div>
270
+ );
271
+
272
+ export const FeatureTextFeaturedIconTopLeftBrand = ({ icon, title, subtitle, footer }: FeatureTextIcon) => (
273
+ <div className="flex max-w-sm flex-col gap-4">
274
+ <FeaturedIcon icon={icon} size="lg" color="brand" theme="dark" className="hidden md:inline-flex" />
275
+ <FeaturedIcon icon={icon} size="md" color="brand" theme="dark" className="inline-flex md:hidden" />
276
+
277
+ <div>
278
+ <h3 className="text-lg font-semibold text-primary_on-brand">{title}</h3>
279
+ <p className="mt-1 text-md text-tertiary_on-brand">{subtitle}</p>
280
+ </div>
281
+
282
+ {footer}
283
+ </div>
284
+ );
@@ -0,0 +1,62 @@
1
+ "use client";
2
+
3
+ import Link from "next/link";
4
+ import type { CompanyInformation } from '../../types/api/company-information';
5
+ import type { SiteConfig } from '../../types/config';
6
+
7
+ interface FooterHomeProps {
8
+ config?: SiteConfig;
9
+ companyInformation?: CompanyInformation | null;
10
+ }
11
+
12
+ const COLUMN_TITLES = ['Home', 'Services', 'Locations', 'About Us'];
13
+
14
+ export const FooterHome = ({
15
+ config,
16
+ companyInformation,
17
+ }: FooterHomeProps) => {
18
+ const currentYear = new Date().getFullYear();
19
+ const apiCompanyInfo = companyInformation as any;
20
+
21
+ // Get footer navigation from config
22
+ const footerColumns = config?.navigation?.footer || [];
23
+
24
+ const companyName = apiCompanyInfo?.company_name || '';
25
+
26
+ return (
27
+ <footer className="bg-primary border-t border-secondary py-12 md:py-16">
28
+ <div className="mx-auto max-w-container px-4 md:px-8">
29
+ <div className="grid grid-cols-1 gap-12 md:grid-cols-4">
30
+ {footerColumns.map((column, i) => (
31
+ <div key={i}>
32
+ <h4 className="font-body text-sm font-medium uppercase tracking-wide text-fg-primary mb-4">
33
+ {COLUMN_TITLES[i] || `Column ${i + 1}`}
34
+ </h4>
35
+ <ul className="space-y-2">
36
+ {column.map((link, j) => (
37
+ <li key={j}>
38
+ <Link
39
+ href={link.href}
40
+ className="font-body text-sm text-tertiary hover:underline"
41
+ >
42
+ {link.label}
43
+ </Link>
44
+ </li>
45
+ ))}
46
+ </ul>
47
+ </div>
48
+ ))}
49
+ </div>
50
+
51
+ <div className="mt-12 pt-8 border-t border-secondary text-center">
52
+ <p className="font-body text-sm text-tertiary">
53
+ © {currentYear} {companyName || 'Company Name'}. All rights reserved.
54
+ </p>
55
+ </div>
56
+ </div>
57
+ </footer>
58
+ );
59
+ };
60
+
61
+ import { registerThemeVariant } from '../../lib/component-registry';
62
+ registerThemeVariant('footer-home', 'aman', FooterHome);