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,146 @@
1
+ "use client";
2
+
3
+ import type { FC, ReactNode, Ref, RefAttributes } from "react";
4
+ import { createContext, isValidElement } from "react";
5
+ import { ChevronDown } from "@untitledui/icons";
6
+ import type { SelectProps as AriaSelectProps } from "react-aria-components";
7
+ import { Button as AriaButton, ListBox as AriaListBox, Select as AriaSelect, SelectValue as AriaSelectValue } from "react-aria-components";
8
+ import { Avatar } from '../avatar/avatar';
9
+ import { HintText } from '../input/hint-text';
10
+ import { Label } from '../input/label';
11
+ import { cx } from '../../../utils/cx';
12
+ import { isReactComponent } from '../../../utils/is-react-component';
13
+ import { ComboBox } from './combobox';
14
+ import { Popover } from "./popover";
15
+ import { SelectItem } from "./select-item";
16
+
17
+ export type SelectItemType = {
18
+ id: string;
19
+ label?: string;
20
+ avatarUrl?: string;
21
+ isDisabled?: boolean;
22
+ supportingText?: string;
23
+ icon?: FC | ReactNode;
24
+ };
25
+
26
+ export interface CommonProps {
27
+ hint?: string;
28
+ label?: string;
29
+ tooltip?: string;
30
+ size?: "sm" | "md";
31
+ placeholder?: string;
32
+ }
33
+
34
+ interface SelectProps extends Omit<AriaSelectProps<SelectItemType>, "children" | "items">, RefAttributes<HTMLDivElement>, CommonProps {
35
+ items?: SelectItemType[];
36
+ popoverClassName?: string;
37
+ placeholderIcon?: FC | ReactNode;
38
+ children: ReactNode | ((item: SelectItemType) => ReactNode);
39
+ }
40
+
41
+ interface SelectValueProps {
42
+ isOpen: boolean;
43
+ size: "sm" | "md";
44
+ isFocused: boolean;
45
+ isDisabled: boolean;
46
+ placeholder?: string;
47
+ ref?: Ref<HTMLButtonElement>;
48
+ placeholderIcon?: FC | ReactNode;
49
+ }
50
+
51
+ export const sizes = {
52
+ sm: { root: "py-2 px-3", shortcut: "pr-2.5" },
53
+ md: { root: "py-2.5 px-3.5", shortcut: "pr-3" },
54
+ };
55
+
56
+ const SelectValue = ({ isOpen, isFocused, isDisabled, size, placeholder, placeholderIcon, ref }: SelectValueProps) => {
57
+ return (
58
+ <AriaButton
59
+ ref={ref}
60
+ className={cx(
61
+ "relative flex w-full cursor-pointer items-center rounded-lg bg-primary shadow-xs ring-1 ring-primary outline-hidden transition duration-100 ease-linear ring-inset",
62
+ (isFocused || isOpen) && "ring-2 ring-brand",
63
+ isDisabled && "cursor-not-allowed bg-disabled_subtle text-disabled",
64
+ )}
65
+ >
66
+ <AriaSelectValue<SelectItemType>
67
+ className={cx(
68
+ "flex h-max w-full items-center justify-start gap-2 truncate text-left align-middle",
69
+
70
+ // Icon styles
71
+ "*:data-icon:size-5 *:data-icon:shrink-0 *:data-icon:text-fg-quaternary in-disabled:*:data-icon:text-fg-disabled",
72
+
73
+ sizes[size].root,
74
+ )}
75
+ >
76
+ {(state) => {
77
+ const Icon = state.selectedItem?.icon || placeholderIcon;
78
+ return (
79
+ <>
80
+ {state.selectedItem?.avatarUrl ? (
81
+ <Avatar size="xs" src={state.selectedItem.avatarUrl} alt={state.selectedItem.label} />
82
+ ) : isReactComponent(Icon) ? (
83
+ <Icon data-icon aria-hidden="true" />
84
+ ) : isValidElement(Icon) ? (
85
+ Icon
86
+ ) : null}
87
+
88
+ {state.selectedItem ? (
89
+ <section className="flex w-full gap-2 truncate">
90
+ <p className="truncate text-md font-medium text-primary">{state.selectedItem?.label}</p>
91
+ {state.selectedItem?.supportingText && <p className="text-md text-tertiary">{state.selectedItem?.supportingText}</p>}
92
+ </section>
93
+ ) : (
94
+ <p className={cx("text-md text-placeholder", isDisabled && "text-disabled")}>{placeholder}</p>
95
+ )}
96
+
97
+ <ChevronDown
98
+ aria-hidden="true"
99
+ className={cx("ml-auto shrink-0 text-fg-quaternary", size === "sm" ? "size-4 stroke-[2.5px]" : "size-5")}
100
+ />
101
+ </>
102
+ );
103
+ }}
104
+ </AriaSelectValue>
105
+ </AriaButton>
106
+ );
107
+ };
108
+
109
+ export const SelectContext = createContext<{ size: "sm" | "md" }>({ size: "sm" });
110
+
111
+ const Select = ({ placeholder = "Select", placeholderIcon, size = "sm", children, items, label, hint, tooltip, className, ...rest }: SelectProps) => {
112
+ return (
113
+ <SelectContext.Provider value={{ size }}>
114
+ <AriaSelect {...rest} className={(state) => cx("flex flex-col gap-1.5", typeof className === "function" ? className(state) : className)}>
115
+ {(state) => (
116
+ <>
117
+ {label && (
118
+ <Label isRequired={state.isRequired} tooltip={tooltip}>
119
+ {label}
120
+ </Label>
121
+ )}
122
+
123
+ <SelectValue {...state} {...{ size, placeholder }} placeholderIcon={placeholderIcon} />
124
+
125
+ <Popover size={size} className={rest.popoverClassName}>
126
+ <AriaListBox items={items} className="size-full outline-hidden">
127
+ {children}
128
+ </AriaListBox>
129
+ </Popover>
130
+
131
+ {hint && <HintText isInvalid={state.isInvalid}>{hint}</HintText>}
132
+ </>
133
+ )}
134
+ </AriaSelect>
135
+ </SelectContext.Provider>
136
+ );
137
+ };
138
+
139
+ const _Select = Select as typeof Select & {
140
+ ComboBox: typeof ComboBox;
141
+ Item: typeof SelectItem;
142
+ };
143
+ _Select.ComboBox = ComboBox;
144
+ _Select.Item = SelectItem;
145
+
146
+ export { _Select as Select };
@@ -0,0 +1,237 @@
1
+ "use client";
2
+
3
+ import { useMemo } from "react";
4
+ import { cx, sortCx } from '../../../../utils/cx';
5
+ import { MastercardIcon, MastercardIconWhite, PaypassIcon } from "./icons";
6
+
7
+ const styles = sortCx({
8
+ // Normal
9
+ transparent: {
10
+ root: "bg-black/10 bg-linear-to-br from-white/30 to-transparent backdrop-blur-[6px] before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
11
+ company: "text-white",
12
+ footerText: "text-white",
13
+ paypassIcon: "text-white",
14
+ cardTypeRoot: "bg-white/10",
15
+ },
16
+ "transparent-gradient": {
17
+ root: "bg-black/10 bg-linear-to-br from-white/30 to-transparent backdrop-blur-[6px] before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
18
+ company: "text-white",
19
+ footerText: "text-white",
20
+ paypassIcon: "text-white",
21
+ cardTypeRoot: "bg-white/10",
22
+ },
23
+ "brand-dark": {
24
+ root: "bg-linear-to-tr from-brand-900 to-brand-700 before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
25
+ company: "text-white",
26
+ footerText: "text-white",
27
+ paypassIcon: "text-white",
28
+ cardTypeRoot: "bg-white/10",
29
+ },
30
+ "brand-light": {
31
+ root: "bg-brand-100 before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-black/10 before:ring-inset",
32
+ company: "text-gray-700",
33
+ footerText: "text-gray-700",
34
+ paypassIcon: "text-white",
35
+ cardTypeRoot: "bg-white",
36
+ },
37
+ "gray-dark": {
38
+ root: "bg-linear-to-tr from-gray-900 to-gray-700 before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
39
+ company: "text-white",
40
+ footerText: "text-white",
41
+ paypassIcon: "text-white",
42
+ cardTypeRoot: "bg-white/10",
43
+ },
44
+ "gray-light": {
45
+ root: "bg-gray-100 before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-black/10 before:ring-inset",
46
+ company: "text-gray-700",
47
+ footerText: "text-gray-700",
48
+ paypassIcon: "text-gray-400",
49
+ cardTypeRoot: "bg-white",
50
+ },
51
+
52
+ // Strip
53
+ "transparent-strip": {
54
+ root: "bg-linear-to-br from-white/30 to-transparent backdrop-blur-[6px] before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
55
+ company: "text-white",
56
+ footerText: "text-white",
57
+ paypassIcon: "text-white",
58
+ cardTypeRoot: "bg-white/10",
59
+ },
60
+ "gray-strip": {
61
+ root: "bg-gray-100 before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
62
+ company: "text-gray-700",
63
+ footerText: "text-white",
64
+ paypassIcon: "text-gray-400",
65
+ cardTypeRoot: "bg-white/10",
66
+ },
67
+ "gradient-strip": {
68
+ root: "bg-linear-to-b from-[#A5C0EE] to-[#FBC5EC] before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
69
+ company: "text-white",
70
+ footerText: "text-white",
71
+ paypassIcon: "text-white",
72
+ cardTypeRoot: "bg-white/10",
73
+ },
74
+ "salmon-strip": {
75
+ root: "bg-[#F4D9D0] before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
76
+ company: "text-gray-700",
77
+ footerText: "text-white",
78
+ paypassIcon: "text-white",
79
+ cardTypeRoot: "bg-white/10",
80
+ },
81
+
82
+ // Vertical strip
83
+ "gray-strip-vertical": {
84
+ root: "bg-linear-to-br from-white/30 to-transparent before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
85
+ company: "text-white",
86
+ footerText: "text-white",
87
+ paypassIcon: "text-gray-400",
88
+ cardTypeRoot: "bg-white/10",
89
+ },
90
+ "gradient-strip-vertical": {
91
+ root: "bg-linear-to-b from-[#FBC2EB] to-[#A18CD1] before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
92
+ company: "text-white",
93
+ footerText: "text-white",
94
+ paypassIcon: "text-white",
95
+ cardTypeRoot: "bg-white/10",
96
+ },
97
+ "salmon-strip-vertical": {
98
+ root: "bg-[#F4D9D0] before:pointer-events-none before:absolute before:inset-0 before:z-1 before:rounded-[inherit] before:mask-linear-135 before:mask-linear-to-white/20 before:ring-1 before:ring-white/30 before:ring-inset",
99
+ company: "text-white",
100
+ footerText: "text-white",
101
+ paypassIcon: "text-white",
102
+ cardTypeRoot: "bg-white/10",
103
+ },
104
+ });
105
+
106
+ const _NORMAL_TYPES = ["transparent", "transparent-gradient", "brand-dark", "brand-light", "gray-dark", "gray-light"] as const;
107
+ const STRIP_TYPES = ["transparent-strip", "gray-strip", "gradient-strip", "salmon-strip"] as const;
108
+ const VERTICAL_STRIP_TYPES = ["gray-strip-vertical", "gradient-strip-vertical", "salmon-strip-vertical"] as const;
109
+
110
+ const CARD_WITH_COLOR_LOGO = ["brand-dark", "brand-light", "gray-dark", "gray-light"] as const;
111
+
112
+ type CreditCardType = (typeof _NORMAL_TYPES)[number] | (typeof STRIP_TYPES)[number] | (typeof VERTICAL_STRIP_TYPES)[number];
113
+
114
+ interface CreditCardProps {
115
+ company?: string;
116
+ cardNumber?: string;
117
+ cardHolder?: string;
118
+ cardExpiration?: string;
119
+ type?: CreditCardType;
120
+ className?: string;
121
+ width?: number;
122
+ }
123
+
124
+ const calculateScale = (desiredWidth: number, originalWidth: number, originalHeight: number) => {
125
+ // Calculate the scale factor
126
+ const scale = desiredWidth / originalWidth;
127
+
128
+ // Calculate the new dimensions
129
+ const scaledWidth = originalWidth * scale;
130
+ const scaledHeight = originalHeight * scale;
131
+
132
+ return {
133
+ scale: scale.toFixed(4), // Scale rounded to 4 decimal places
134
+ scaledWidth: scaledWidth.toFixed(2), // Width rounded to 2 decimal places
135
+ scaledHeight: scaledHeight.toFixed(2), // Height rounded to 2 decimal places
136
+ };
137
+ };
138
+
139
+ export const CreditCard = ({
140
+ company = "Untitled.",
141
+ cardNumber = "1234 1234 1234 1234",
142
+ cardHolder = "OLIVIA RHYE",
143
+ cardExpiration = "06/28",
144
+ type = "brand-dark",
145
+ className,
146
+ width,
147
+ }: CreditCardProps) => {
148
+ const originalWidth = 316;
149
+ const originalHeight = 190;
150
+
151
+ const { scale, scaledWidth, scaledHeight } = useMemo(() => {
152
+ if (!width)
153
+ return {
154
+ scale: 1,
155
+ scaledWidth: originalWidth,
156
+ scaledHeight: originalHeight,
157
+ };
158
+
159
+ return calculateScale(width, originalWidth, originalHeight);
160
+ }, [width]);
161
+
162
+ return (
163
+ <div
164
+ style={{
165
+ width: `${scaledWidth}px`,
166
+ height: `${scaledHeight}px`,
167
+ }}
168
+ className={cx("relative flex", className)}
169
+ >
170
+ <div
171
+ style={{
172
+ transform: `scale(${scale})`,
173
+ width: `${originalWidth}px`,
174
+ height: `${originalHeight}px`,
175
+ }}
176
+ className={cx("absolute top-0 left-0 flex origin-top-left flex-col justify-between overflow-hidden rounded-2xl p-4", styles[type].root)}
177
+ >
178
+ {/* Horizontal strip */}
179
+ {STRIP_TYPES.includes(type as (typeof STRIP_TYPES)[number]) && (
180
+ <div className="pointer-events-none absolute inset-x-0 bottom-0 z-0 h-1/2 bg-gray-800"></div>
181
+ )}
182
+ {/* Vertical stripe */}
183
+ {VERTICAL_STRIP_TYPES.includes(type as (typeof VERTICAL_STRIP_TYPES)[number]) && (
184
+ <div className="pointer-events-none absolute inset-y-0 right-22 left-0 z-0 bg-gray-800"></div>
185
+ )}
186
+ {/* Gradient diffusor */}
187
+ {type === "transparent-gradient" && (
188
+ <div className="absolute -top-4 -left-4 grid grid-cols-2 blur-3xl">
189
+ <div className="size-20 rounded-tl-full bg-pink-500 opacity-30 mix-blend-normal" />
190
+ <div className="size-20 rounded-tr-full bg-orange-500 opacity-50 mix-blend-normal" />
191
+ <div className="size-20 rounded-bl-full bg-blue-500 opacity-30 mix-blend-normal" />
192
+ <div className="size-20 rounded-br-full bg-success-500 opacity-30 mix-blend-normal" />
193
+ </div>
194
+ )}
195
+
196
+ <div className="relative flex items-start justify-between px-1 pt-1">
197
+ <div className={cx("text-md leading-[normal] font-semibold", styles[type].company)}>{company}</div>
198
+
199
+ <PaypassIcon className={styles[type].paypassIcon} />
200
+ </div>
201
+
202
+ <div className="relative flex items-end justify-between gap-3">
203
+ <div className="flex min-w-0 flex-col gap-2">
204
+ <div className="flex items-end gap-1">
205
+ <p
206
+ style={{
207
+ wordBreak: "break-word",
208
+ }}
209
+ className={cx("text-xs leading-snug font-semibold tracking-[0.6px] uppercase", styles[type].footerText)}
210
+ >
211
+ {cardHolder}
212
+ </p>
213
+ <p
214
+ className={cx(
215
+ "ml-auto text-right text-xs leading-[normal] font-semibold tracking-[0.6px] tabular-nums",
216
+ styles[type].footerText,
217
+ )}
218
+ >
219
+ {cardExpiration}
220
+ </p>
221
+ </div>
222
+ <div className={cx("text-md leading-[normal] font-semibold tracking-[1px] tabular-nums", styles[type].footerText)}>
223
+ {cardNumber}
224
+
225
+ {/* This is just a placeholder to always keep the space for card number even if there's no card number yet. */}
226
+ <span className="pointer-events-none invisible inline-block w-0 max-w-0 opacity-0">1</span>
227
+ </div>
228
+ </div>
229
+
230
+ <div className={cx("flex h-8 w-11.5 shrink-0 items-center justify-center rounded", styles[type].cardTypeRoot)}>
231
+ {CARD_WITH_COLOR_LOGO.includes(type as (typeof CARD_WITH_COLOR_LOGO)[number]) ? <MastercardIcon /> : <MastercardIconWhite />}
232
+ </div>
233
+ </div>
234
+ </div>
235
+ </div>
236
+ );
237
+ };
@@ -0,0 +1,75 @@
1
+ "use client";
2
+
3
+ import type { SVGProps } from "react";
4
+
5
+ export const PaypassIcon = (props: SVGProps<SVGSVGElement>) => {
6
+ return (
7
+ <svg width="20" height="24" viewBox="0 0 20 24" fill="none" {...props}>
8
+ <g clipPath="url(#clip0_1307_7682)">
9
+ <path
10
+ d="M15.1429 1.28571C17.0236 4.54326 18.0138 8.23849 18.0138 12C18.0138 15.7615 17.0236 19.4567 15.1429 22.7143M10.4286 3.64285C11.8956 6.18374 12.6679 9.06602 12.6679 12C12.6679 14.934 11.8956 17.8162 10.4286 20.3571M5.92859 5.80713C6.98933 7.66394 7.54777 9.77022 7.54777 11.9143C7.54777 14.0583 6.98933 16.1646 5.92859 18.0214M1.42859 8.14285C2.19306 9.29983 2.59834 10.6362 2.59834 12C2.59834 13.3638 2.19306 14.7002 1.42859 15.8571"
11
+ stroke="currentColor"
12
+ strokeWidth="2.57143"
13
+ strokeLinecap="round"
14
+ />
15
+ </g>
16
+ <defs>
17
+ <clipPath id="clip0_1307_7682">
18
+ <rect width="20" height="24" fill="white" />
19
+ </clipPath>
20
+ </defs>
21
+ </svg>
22
+ );
23
+ };
24
+
25
+ export const MastercardIconWhite = (props: SVGProps<SVGSVGElement>) => {
26
+ return (
27
+ <svg width="30" height="19" viewBox="0 0 30 19" fill="none" {...props}>
28
+ <path
29
+ opacity="0.5"
30
+ fillRule="evenodd"
31
+ clipRule="evenodd"
32
+ d="M14.9053 16.4392C13.3266 17.7699 11.2787 18.5733 9.04092 18.5733C4.04776 18.5733 0 14.5737 0 9.63994C0 4.70619 4.04776 0.706604 9.04092 0.706604C11.2787 0.706604 13.3266 1.50993 14.9053 2.84066C16.484 1.50993 18.5319 0.706604 20.7697 0.706604C25.7629 0.706604 29.8106 4.70619 29.8106 9.63994C29.8106 14.5737 25.7629 18.5733 20.7697 18.5733C18.5319 18.5733 16.484 17.7699 14.9053 16.4392Z"
33
+ fill="white"
34
+ />
35
+ <path
36
+ opacity="0.5"
37
+ fillRule="evenodd"
38
+ clipRule="evenodd"
39
+ d="M14.9053 16.4392C16.8492 14.8007 18.0818 12.3625 18.0818 9.63994C18.0818 6.91733 16.8492 4.47919 14.9053 2.84066C16.484 1.50993 18.5319 0.706604 20.7697 0.706604C25.7628 0.706604 29.8106 4.70619 29.8106 9.63994C29.8106 14.5737 25.7628 18.5733 20.7697 18.5733C18.5319 18.5733 16.484 17.7699 14.9053 16.4392Z"
40
+ fill="white"
41
+ />
42
+ <path
43
+ fillRule="evenodd"
44
+ clipRule="evenodd"
45
+ d="M14.9053 16.4392C16.8492 14.8007 18.0818 12.3625 18.0818 9.63995C18.0818 6.91736 16.8492 4.47924 14.9053 2.8407C12.9614 4.47924 11.7288 6.91736 11.7288 9.63995C11.7288 12.3625 12.9614 14.8007 14.9053 16.4392Z"
46
+ fill="white"
47
+ />
48
+ </svg>
49
+ );
50
+ };
51
+
52
+ export const MastercardIcon = (props: SVGProps<SVGSVGElement>) => {
53
+ return (
54
+ <svg width="30" height="19" viewBox="0 0 30 19" fill="none" {...props}>
55
+ <path
56
+ fillRule="evenodd"
57
+ clipRule="evenodd"
58
+ d="M14.9053 16.4393C13.3266 17.77 11.2787 18.5733 9.04092 18.5733C4.04776 18.5733 0 14.5737 0 9.64C0 4.70625 4.04776 0.706665 9.04092 0.706665C11.2787 0.706665 13.3266 1.51 14.9053 2.84072C16.484 1.51 18.5319 0.706665 20.7697 0.706665C25.7629 0.706665 29.8106 4.70625 29.8106 9.64C29.8106 14.5737 25.7629 18.5733 20.7697 18.5733C18.5319 18.5733 16.484 17.77 14.9053 16.4393Z"
59
+ fill="#ED0006"
60
+ />
61
+ <path
62
+ fillRule="evenodd"
63
+ clipRule="evenodd"
64
+ d="M14.9053 16.4393C16.8492 14.8007 18.0818 12.3626 18.0818 9.64C18.0818 6.91739 16.8492 4.47925 14.9053 2.84072C16.484 1.50999 18.5319 0.706665 20.7697 0.706665C25.7628 0.706665 29.8106 4.70625 29.8106 9.64C29.8106 14.5737 25.7628 18.5733 20.7697 18.5733C18.5319 18.5733 16.484 17.77 14.9053 16.4393Z"
65
+ fill="#F9A000"
66
+ />
67
+ <path
68
+ fillRule="evenodd"
69
+ clipRule="evenodd"
70
+ d="M14.9053 16.4393C16.8492 14.8008 18.0818 12.3627 18.0818 9.64007C18.0818 6.91748 16.8492 4.47936 14.9053 2.84082C12.9614 4.47936 11.7288 6.91748 11.7288 9.64007C11.7288 12.3627 12.9614 14.8008 14.9053 16.4393Z"
71
+ fill="#FF5E00"
72
+ />
73
+ </svg>
74
+ );
75
+ };
@@ -0,0 +1,172 @@
1
+ "use client";
2
+
3
+ import type { SVGProps } from "react";
4
+ import { useId } from "react";
5
+ import { cx } from '../../../utils/cx';
6
+
7
+ interface IPhoneMockupProps extends SVGProps<SVGSVGElement> {
8
+ /**
9
+ * The image to display on the phone.
10
+ */
11
+ image: string;
12
+ /**
13
+ * The dark mode image to display in dark mode.
14
+ * If not provided, the light mode image will be used in dark mode.
15
+ */
16
+ imageDark?: string;
17
+ /**
18
+ * The theme of the phone.
19
+ * @default "light"
20
+ */
21
+ theme?: "light" | "dark";
22
+ }
23
+
24
+ export const IPhoneMockup = ({ image, imageDark, theme, className, ...svgProps }: IPhoneMockupProps) => {
25
+ // We need to use a unique ID because there might be
26
+ // multiple instances of this element in the same page.
27
+ const id = useId();
28
+
29
+ return (
30
+ <svg
31
+ width="314"
32
+ viewBox="0 0 314 640"
33
+ fill="none"
34
+ preserveAspectRatio="xMidYMin slice"
35
+ {...svgProps}
36
+ className={cx("h-auto", theme === undefined ? "text-black dark:text-white" : theme === "light" ? "text-black" : "text-white", className)}
37
+ >
38
+ <defs>
39
+ <pattern id={`screen-${id}`} patternContentUnits="objectBoundingBox" width="1" height="1">
40
+ <use xlinkHref={`#screen-image-${id}`} className={cx(imageDark && "dark:hidden")} transform="scale(0.00133333 0.000615764)" />
41
+ {imageDark && <use xlinkHref={`#screen-image-dark-${id}`} className="not-dark:hidden" transform="scale(0.00133333 0.000615764)" />}{" "}
42
+ </pattern>
43
+ <clipPath id="status-bar-box">
44
+ <rect width="281.69" height="609.953" fill="white" transform="translate(15.7744 14.2725)" />
45
+ </clipPath>
46
+
47
+ {/* Light mode image (hidden in dark mode) */}
48
+ <image id={`screen-image-${id}`} width="750" height="1624" xlinkHref={image} className={cx(imageDark && "dark:hidden")} />
49
+ {/* Dark mode image (hidden in light mode) */}
50
+ {imageDark && <image id={`screen-image-dark-${id}`} width="750" height="1624" xlinkHref={imageDark} className="not-dark:hidden" />}
51
+ </defs>
52
+
53
+ {/* Status bar */}
54
+ <g clipPath="url(#status-bar-box)">
55
+ <rect
56
+ width="281.69"
57
+ height="609.953"
58
+ transform="translate(15.7744 14.2725)"
59
+ className={cx(theme === undefined ? "fill-white dark:fill-black" : theme === "light" ? "fill-white" : "fill-black")}
60
+ />
61
+ {/* The screen */}
62
+ <rect width="281.69" height="609.953" transform="translate(15.7744 38.3096)" fill={`url(#screen-${id})`} />
63
+ <path
64
+ opacity="0.35"
65
+ d="M268.545 29.2961C268.545 28.3972 269.273 27.6686 270.172 27.6686H282.692C283.591 27.6686 284.319 28.3972 284.319 29.2961V33.8031C284.319 34.702 283.591 35.4307 282.692 35.4307H270.172C269.273 35.4307 268.545 34.702 268.545 33.8031V29.2961Z"
66
+ strokeWidth="0.751174"
67
+ stroke="currentColor"
68
+ />
69
+ <path
70
+ opacity="0.4"
71
+ d="M285.446 30.0479V33.0525C286.05 32.7981 286.443 32.2061 286.443 31.5502C286.443 30.8943 286.05 30.3023 285.446 30.0479Z"
72
+ fill="currentColor"
73
+ />
74
+ <path
75
+ d="M269.671 29.7975C269.671 29.2443 270.12 28.7959 270.673 28.7959H282.191C282.744 28.7959 283.193 29.2443 283.193 29.7975V33.3029C283.193 33.8561 282.744 34.3045 282.191 34.3045H270.673C270.12 34.3045 269.671 33.8561 269.671 33.3029V29.7975Z"
76
+ fill="currentColor"
77
+ />
78
+ <path
79
+ fillRule="evenodd"
80
+ clipRule="evenodd"
81
+ d="M258.651 29.0017C260.316 29.0018 261.917 29.6413 263.123 30.7882C263.214 30.8768 263.359 30.8757 263.449 30.7857L264.317 29.9094C264.362 29.8637 264.388 29.802 264.387 29.7377C264.387 29.6734 264.361 29.6119 264.315 29.5668C261.149 26.5324 256.154 26.5324 252.987 29.5668C252.941 29.6119 252.915 29.6733 252.915 29.7376C252.915 29.8019 252.94 29.8637 252.985 29.9094L253.854 30.7857C253.943 30.8758 254.088 30.8769 254.179 30.7882C255.386 29.6413 256.987 29.0017 258.651 29.0017ZM258.651 31.8527C259.566 31.8527 260.448 32.1926 261.126 32.8065C261.218 32.8936 261.362 32.8917 261.451 32.8022L262.319 31.9258C262.364 31.8799 262.39 31.8175 262.389 31.7527C262.388 31.6879 262.362 31.6261 262.315 31.5811C260.251 29.6608 257.054 29.6608 254.989 31.5811C254.943 31.6261 254.916 31.688 254.916 31.7528C254.915 31.8176 254.94 31.8799 254.986 31.9258L255.853 32.8022C255.943 32.8917 256.087 32.8936 256.179 32.8065C256.856 32.193 257.738 31.8531 258.651 31.8527ZM260.389 33.7709C260.39 33.8359 260.365 33.8985 260.318 33.9441L258.818 35.4582C258.774 35.5027 258.714 35.5277 258.652 35.5277C258.589 35.5277 258.529 35.5027 258.485 35.4582L256.984 33.9441C256.938 33.8985 256.913 33.8358 256.914 33.7709C256.915 33.7059 256.943 33.6443 256.992 33.6008C257.95 32.7903 259.353 32.7903 260.311 33.6008C260.36 33.6444 260.388 33.7059 260.389 33.7709Z"
82
+ fill="currentColor"
83
+ />
84
+ <path
85
+ fillRule="evenodd"
86
+ clipRule="evenodd"
87
+ d="M248.388 27.5439H247.637C247.222 27.5439 246.886 27.8803 246.886 28.2951V34.8053C246.886 35.2202 247.222 35.5565 247.637 35.5565H248.388C248.803 35.5565 249.139 35.2202 249.139 34.8053V28.2951C249.139 27.8803 248.803 27.5439 248.388 27.5439ZM244.131 29.2964H244.883C245.297 29.2964 245.634 29.6328 245.634 30.0476V34.805C245.634 35.2199 245.297 35.5562 244.883 35.5562H244.131C243.717 35.5562 243.38 35.2199 243.38 34.805V30.0476C243.38 29.6328 243.717 29.2964 244.131 29.2964ZM241.377 31.0497H240.626C240.211 31.0497 239.874 31.386 239.874 31.8008V34.8055C239.874 35.2204 240.211 35.5567 240.626 35.5567H241.377C241.792 35.5567 242.128 35.2204 242.128 34.8055V31.8008C242.128 31.386 241.792 31.0497 241.377 31.0497ZM237.871 32.552H237.12C236.705 32.552 236.369 32.8883 236.369 33.3032V34.8055C236.369 35.2204 236.705 35.5567 237.12 35.5567H237.871C238.286 35.5567 238.623 35.2204 238.623 34.8055V33.3032C238.623 32.8883 238.286 32.552 237.871 32.552Z"
88
+ fill="currentColor"
89
+ />
90
+ <path
91
+ d="M43.8087 35.4986C45.8279 35.4986 47.0273 33.9196 47.0273 31.2457C47.0273 30.2389 46.8347 29.3917 46.4661 28.7369C45.9324 27.7191 45.0136 27.1689 43.8528 27.1689C42.1252 27.1689 40.9038 28.3298 40.9038 29.9583C40.9038 31.4878 42.0042 32.5992 43.5171 32.5992C44.4469 32.5992 45.2007 32.1645 45.5748 31.4108H45.5913C45.5913 31.4108 45.6133 31.4108 45.6188 31.4108C45.6298 31.4108 45.6683 31.4108 45.6683 31.4108C45.6683 33.2264 44.9806 34.3102 43.8197 34.3102C43.1375 34.3102 42.6094 33.9361 42.4278 33.3364H41.0138C41.2504 34.6403 42.3563 35.4986 43.8087 35.4986ZM43.8583 31.4713C42.945 31.4713 42.2958 30.8221 42.2958 29.9143C42.2958 29.0285 42.978 28.3518 43.8638 28.3518C44.7495 28.3518 45.4318 29.0395 45.4318 29.9363C45.4318 30.8221 44.766 31.4713 43.8583 31.4713Z"
92
+ fill="currentColor"
93
+ />
94
+ <path
95
+ d="M49.3492 35.4216C49.8719 35.4216 50.2295 35.0475 50.2295 34.5523C50.2295 34.0516 49.8719 33.683 49.3492 33.683C48.8321 33.683 48.4689 34.0516 48.4689 34.5523C48.4689 35.0475 48.8321 35.4216 49.3492 35.4216ZM49.3492 31.2953C49.8719 31.2953 50.2295 30.9266 50.2295 30.4315C50.2295 29.9308 49.8719 29.5622 49.3492 29.5622C48.8321 29.5622 48.4689 29.9308 48.4689 30.4315C48.4689 30.9266 48.8321 31.2953 49.3492 31.2953Z"
96
+ fill="currentColor"
97
+ />
98
+ <path
99
+ d="M55.3794 35.306H56.7383V33.8261H57.8112V32.6267H56.7383V27.367H54.7357C53.3327 29.4797 52.2159 31.2457 51.5006 32.5607V33.8261H55.3794V35.306ZM52.8156 32.5772C53.7399 30.9487 54.5651 29.6447 55.3244 28.5224H55.4014V32.6597H52.8156V32.5772Z"
100
+ fill="currentColor"
101
+ />
102
+ <path d="M60.8373 35.306H62.2568V27.367H60.8428L58.7687 28.8195V30.1839L60.7438 28.7975H60.8373V35.306Z" fill="currentColor" />
103
+ <rect x="106.667" y="614.46" width="100.657" height="3.75587" rx="1.87793" fill="currentColor" />
104
+ </g>
105
+ <path
106
+ d="M311.294 163.718H312.406C313.02 163.718 313.517 164.218 313.517 164.834V237.763C313.517 238.379 313.02 238.879 312.406 238.879H311.294V163.718Z"
107
+ fill="#303030"
108
+ />
109
+ <path
110
+ d="M2.22266 254.506L1.11089 254.506C0.496874 254.506 -0.000880198 254.006 -0.000880144 253.39L-0.000876321 209.484C-0.000876268 208.867 0.496878 208.367 1.11089 208.367L2.22266 208.367L2.22266 254.506Z"
111
+ fill="#303030"
112
+ />
113
+ <path
114
+ d="M2.22266 193.484L1.11089 193.484C0.496874 193.484 -0.000880198 192.985 -0.000880144 192.368L-0.000876321 148.462C-0.000876268 147.846 0.496878 147.346 1.11089 147.346L2.22266 147.346L2.22266 193.484Z"
115
+ fill="#333333"
116
+ />
117
+ <path
118
+ d="M2.22266 125.021L1.11089 125.021C0.496878 125.021 -0.000877337 124.521 -0.000877283 123.904L-0.000875404 102.323C-0.00087535 101.707 0.496879 101.207 1.11089 101.207L2.22266 101.207L2.22266 125.021Z"
119
+ fill="#333333"
120
+ />
121
+ <path
122
+ fillRule="evenodd"
123
+ clipRule="evenodd"
124
+ d="M4.58058 33.4236C2.22266 40.7098 2.22266 49.713 2.22266 67.7195V570.778C2.22266 588.785 2.22266 597.788 4.58058 605.074C9.3461 619.8 20.8451 631.345 35.5118 636.13C42.7688 638.498 51.7358 638.498 69.6698 638.498H243.846C261.78 638.498 270.747 638.498 278.004 636.13C292.671 631.345 304.17 619.8 308.936 605.074C311.294 597.788 311.294 588.785 311.294 570.778V67.7194C311.294 49.713 311.294 40.7098 308.936 33.4236C304.17 18.6976 292.671 7.15221 278.004 2.36745C270.747 0 261.78 0 243.846 0H69.6698C51.7358 0 42.7688 0 35.5118 2.36745C20.8451 7.15221 9.3461 18.6976 4.58058 33.4236ZM80.7881 18.2322V21.5809L80.841 21.5793L80.7878 21.953C80.7878 30.7894 87.9223 37.9526 96.7231 37.9526H216.794C225.595 37.9526 232.729 30.7894 232.729 21.953L232.676 21.5793L232.729 21.5809V18.2322C232.729 15.9717 234.554 14.1392 236.805 14.1392L246.352 14.1392C261.276 14.1392 268.738 14.1392 274.69 16.3971C284.044 19.9461 291.428 27.36 294.963 36.7521C297.212 42.7274 297.212 50.2197 297.212 65.2041V573.294C297.212 588.278 297.212 595.77 294.963 601.746C291.428 611.138 284.044 618.552 274.69 622.101C268.738 624.358 261.276 624.358 246.352 624.358H67.165C52.2408 624.358 44.7787 624.358 38.8273 622.101C29.473 618.552 22.0889 611.138 18.5542 601.746C16.3054 595.77 16.3054 588.278 16.3054 573.294V65.2041C16.3054 50.2197 16.3054 42.7274 18.5542 36.7521C22.0889 27.36 29.473 19.9461 38.8273 16.3971C44.7787 14.1392 52.2408 14.1392 67.165 14.1392L76.7116 14.1392C78.963 14.1392 80.7881 15.9717 80.7881 18.2322Z"
125
+ fill="#333333"
126
+ />
127
+ <path
128
+ fillRule="evenodd"
129
+ clipRule="evenodd"
130
+ d="M244.144 1.48831H69.3739C51.6581 1.48831 42.9759 1.49749 35.9704 3.78291C21.7549 8.42045 10.6098 19.6106 5.99091 33.8835C3.71468 40.9173 3.70553 49.6344 3.70553 67.4217V571.076C3.70553 588.863 3.71468 597.58 5.99091 604.614C10.6098 618.887 21.7549 630.077 35.9704 634.715C42.9759 637 51.6581 637.009 69.3739 637.009H244.144C261.859 637.009 270.541 637 277.547 634.715C291.762 630.077 302.908 618.887 307.527 604.614C309.803 597.58 309.812 588.863 309.812 571.076V67.4217C309.812 49.6344 309.803 40.9173 307.527 33.8835C302.908 19.6106 291.762 8.42045 277.547 3.78291C270.541 1.49749 261.859 1.48831 244.144 1.48831ZM5.28601 33.6535C2.96436 40.8276 2.96436 49.6923 2.96436 67.4217V571.076C2.96436 588.805 2.96436 597.67 5.28601 604.844C9.97821 619.344 21.3003 630.711 35.7414 635.422C42.8867 637.753 51.7158 637.753 69.3739 637.753H244.144C261.802 637.753 270.631 637.753 277.776 635.422C292.217 630.711 303.539 619.344 308.231 604.844C310.553 597.67 310.553 588.805 310.553 571.076V67.4217C310.553 49.6923 310.553 40.8276 308.231 33.6535C303.539 19.1541 292.217 7.78631 277.776 3.07517C270.631 0.744141 261.802 0.744141 244.144 0.744141H69.3739C51.7158 0.744141 42.8867 0.744141 35.7414 3.07517C21.3003 7.78631 9.97821 19.1541 5.28601 33.6535Z"
131
+ fill="#303030"
132
+ />
133
+ <path
134
+ fillRule="evenodd"
135
+ clipRule="evenodd"
136
+ d="M8.10672 34.5732C5.93018 41.299 5.93018 49.6096 5.93018 66.231V572.266C5.93018 588.888 5.93018 597.198 8.10672 603.924C12.5057 617.517 23.1201 628.174 36.6586 632.591C43.3574 634.777 51.6346 634.777 68.1891 634.777H245.33C261.885 634.777 270.162 634.777 276.861 632.591C290.399 628.174 301.014 617.517 305.413 603.924C307.589 597.198 307.589 588.888 307.589 572.266V66.231C307.589 49.6096 307.589 41.299 305.413 34.5732C301.014 20.98 290.399 10.3227 276.861 5.90604C270.162 3.7207 261.885 3.7207 245.33 3.7207H68.1891C51.6346 3.7207 43.3574 3.7207 36.6586 5.90604C23.1201 10.3227 12.5057 20.98 8.10672 34.5732ZM80.7888 18.232V21.5808L80.8418 21.5791L80.7886 21.9528C80.7886 30.7892 87.9231 37.9525 96.7239 37.9525H216.795C225.596 37.9525 232.73 30.7892 232.73 21.9528L232.677 21.5791L232.73 21.5808V18.232C232.73 15.9716 234.555 14.1391 236.806 14.1391L246.353 14.1391C261.277 14.1391 268.739 14.1391 274.69 16.397C284.045 19.9459 291.429 27.3599 294.964 36.7519C297.212 42.7273 297.212 50.2195 297.212 65.204V573.293C297.212 588.278 297.212 595.77 294.964 601.745C291.429 611.137 284.045 618.551 274.69 622.1C268.739 624.358 261.277 624.358 246.353 624.358H67.1657C52.2415 624.358 44.7794 624.358 38.8281 622.1C29.4738 618.551 22.0897 611.137 18.555 601.745C16.3062 595.77 16.3062 588.278 16.3062 573.293V65.204C16.3062 50.2195 16.3062 42.7273 18.555 36.7519C22.0897 27.3599 29.4738 19.9459 38.8281 16.397C44.7794 14.1391 52.2415 14.1391 67.1658 14.1391L76.7124 14.1391C78.9638 14.1391 80.7888 15.9716 80.7888 18.232Z"
137
+ fill="#121515"
138
+ />
139
+ <rect x="245.33" width="4.44705" height="3.72085" fill="#414141" />
140
+ <rect x="307.588" y="63.999" width="3.70594" height="4.46502" fill="#414141" />
141
+ <rect x="2.22363" y="63.999" width="3.70589" height="4.46502" fill="#414141" />
142
+ <rect x="2.22363" y="570.033" width="3.70589" height="4.465" fill="#414141" />
143
+ <rect x="307.588" y="570.033" width="3.70594" height="4.465" fill="#414141" />
144
+ <rect x="63.7402" y="634.777" width="4.44707" height="3.72084" fill="#414141" />
145
+ <path
146
+ fillRule="evenodd"
147
+ clipRule="evenodd"
148
+ d="M188.259 29.7671C191.534 29.7671 194.188 27.1017 194.188 23.8137C194.188 20.5258 191.534 17.8604 188.259 17.8604C184.984 17.8604 182.33 20.5258 182.33 23.8137C182.33 27.1017 184.984 29.7671 188.259 29.7671Z"
149
+ fill="#262C2D"
150
+ />
151
+ <path
152
+ fillRule="evenodd"
153
+ clipRule="evenodd"
154
+ d="M188.259 27.5345C190.305 27.5345 191.965 25.8686 191.965 23.8136C191.965 21.7587 190.305 20.0928 188.259 20.0928C186.212 20.0928 184.553 21.7587 184.553 23.8136C184.553 25.8686 186.212 27.5345 188.259 27.5345Z"
155
+ fill="#121515"
156
+ />
157
+ <path
158
+ opacity="0.4"
159
+ fillRule="evenodd"
160
+ clipRule="evenodd"
161
+ d="M188.26 23.0701C188.67 23.0701 189.002 22.7368 189.002 22.3256C189.002 21.9144 188.67 21.5811 188.26 21.5811C187.851 21.5811 187.519 21.9144 187.519 22.3256C187.519 22.7368 187.851 23.0701 188.26 23.0701Z"
162
+ fill="#636F73"
163
+ />
164
+ <path
165
+ fillRule="evenodd"
166
+ clipRule="evenodd"
167
+ d="M138.601 23.8136C138.601 22.5806 139.6 21.5811 140.833 21.5811H172.686C173.919 21.5811 174.918 22.5806 174.918 23.8136C174.918 25.0465 173.919 26.0461 172.686 26.0461H140.833C139.6 26.0461 138.601 25.0465 138.601 23.8136Z"
168
+ fill="#262C2D"
169
+ />
170
+ </svg>
171
+ );
172
+ };
@@ -0,0 +1,12 @@
1
+ "use client";
2
+
3
+ import type { HTMLAttributes } from "react";
4
+ import { cx } from '../../../utils/cx';
5
+
6
+ export const SectionDivider = (props: HTMLAttributes<HTMLDivElement>) => {
7
+ return (
8
+ <div {...props} className={cx("mx-auto max-w-container px-4 md:px-8", props.className)}>
9
+ <hr className="h-px w-full border-none bg-border-secondary" />
10
+ </div>
11
+ );
12
+ };