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,430 @@
1
+ .prose:not(:where([class~="not-prose"], [class~="not-prose"] *)) {
2
+ --tw-prose-body: var(--color-text-tertiary);
3
+ --tw-prose-headings: var(--color-text-primary);
4
+ --tw-prose-lead: var(--color-text-tertiary);
5
+ --tw-prose-links: var(--color-text-tertiary);
6
+ --tw-prose-bold: var(--color-text-primary);
7
+ --tw-prose-counters: var(--color-text-tertiary);
8
+ --tw-prose-bullets: var(--color-text-tertiary);
9
+ --tw-prose-hr: var(--color-border-secondary);
10
+ --tw-prose-quotes: var(--color-text-primary);
11
+ --tw-prose-quote-borders: var(--color-fg-brand-primary_alt);
12
+ --tw-prose-captions: var(--color-text-tertiary);
13
+ --tw-prose-code: var(--color-text-tertiary);
14
+ --tw-prose-pre-code: var(--color-text-tertiary);
15
+ --tw-prose-pre-bg: var(--color-bg-primary);
16
+ --tw-prose-th-borders: var(--color-border-primary);
17
+ --tw-prose-td-borders: var(--color-border-secondary);
18
+
19
+ /* Base */
20
+ color: var(--tw-prose-body);
21
+ font-size: var(--text-md);
22
+ line-height: var(--text-md--line-height);
23
+ }
24
+
25
+ .prose :not(:where([class~="not-prose"], [class~="not-prose"] *)) {
26
+ /* Text */
27
+ &:where(p) {
28
+ margin-top: calc(var(--spacing) * 4);
29
+ margin-bottom: calc(var(--spacing) * 4);
30
+ }
31
+
32
+ &:where([class~="lead"]) {
33
+ font-size: var(--text-md);
34
+ line-height: var(--text-md--line-height);
35
+ margin-top: 1.2em;
36
+ margin-bottom: 1.2em;
37
+ }
38
+
39
+ /* Lists */
40
+ &:where(ol) {
41
+ list-style-type: decimal;
42
+
43
+ margin-top: calc(var(--spacing) * 4);
44
+ margin-bottom: calc(var(--spacing) * 4);
45
+ padding-inline-start: calc(var(--spacing) * 5.75);
46
+ }
47
+ &:where(ul) {
48
+ list-style-type: disc;
49
+
50
+ margin-top: calc(var(--spacing) * 4);
51
+ margin-bottom: calc(var(--spacing) * 4);
52
+ padding-inline-start: calc(var(--spacing) * 5.75);
53
+ }
54
+ &:where(li) {
55
+ margin-top: calc(var(--spacing) * 2);
56
+ margin-bottom: calc(var(--spacing) * 2);
57
+ }
58
+ &:where(ol > li) {
59
+ padding-inline-start: 1px;
60
+ margin-top: 0;
61
+ margin-bottom: 0;
62
+ }
63
+ &:where(ul > li) {
64
+ padding-inline-start: 1px;
65
+ margin-top: 0;
66
+ margin-bottom: 0;
67
+ }
68
+
69
+ /* Horizontal rules */
70
+ &:where(hr) {
71
+ margin-top: calc(var(--spacing) * 8);
72
+ margin-bottom: calc(var(--spacing) * 8);
73
+ }
74
+
75
+ /* Quotes */
76
+ &:where(blockquote) {
77
+ color: var(--tw-prose-quotes);
78
+
79
+ border-left-width: 2px;
80
+ border-left-color: var(--tw-prose-quote-borders);
81
+
82
+ padding-inline-start: 0;
83
+ margin-top: calc(var(--spacing) * 10);
84
+ margin-bottom: calc(var(--spacing) * 10);
85
+ }
86
+ &:where(blockquote p) {
87
+ margin: 0;
88
+ font-weight: 500;
89
+ font-style: italic;
90
+
91
+ font-size: var(--text-xl);
92
+ line-height: var(--text-xl--line-height);
93
+ }
94
+ &:where(blockquote p:first-of-type::before) {
95
+ content: open-quote;
96
+ }
97
+ &:where(blockquote p:last-of-type::after) {
98
+ content: close-quote;
99
+ }
100
+
101
+ /* Headings */
102
+ &:where(h1) {
103
+ color: var(--tw-prose-headings);
104
+ font-weight: 600;
105
+
106
+ font-size: var(--text-display-sm);
107
+ line-height: var(--text-display-sm--line-height);
108
+ margin-bottom: calc(var(--spacing) * 5);
109
+ margin-top: calc(var(--spacing) * 10);
110
+ }
111
+ &:where(h2) {
112
+ color: var(--tw-prose-headings);
113
+ font-weight: 600;
114
+
115
+ font-size: var(--text-display-xs);
116
+ line-height: var(--text-display-xs--line-height);
117
+ margin-bottom: calc(var(--spacing) * 4);
118
+ margin-top: calc(var(--spacing) * 8);
119
+ }
120
+ &:where(h3) {
121
+ color: var(--tw-prose-headings);
122
+ font-weight: 600;
123
+
124
+ font-size: var(--text-xl);
125
+ line-height: var(--text-xl--line-height);
126
+ margin-bottom: calc(var(--spacing) * 3);
127
+ margin-top: calc(var(--spacing) * 8);
128
+ }
129
+ &:where(h4) {
130
+ color: var(--tw-prose-headings);
131
+ font-weight: 600;
132
+
133
+ font-size: var(--text-lg);
134
+ line-height: var(--text-lg--line-height);
135
+ margin-bottom: calc(var(--spacing) * 2);
136
+ margin-top: calc(var(--spacing) * 5);
137
+ }
138
+
139
+ &:where(h2 + *) {
140
+ margin-top: 0;
141
+ }
142
+ &:where(h3 + *) {
143
+ margin-top: 0;
144
+ }
145
+ &:where(h4 + *) {
146
+ margin-top: 0;
147
+ }
148
+
149
+ &:where(h1 strong) {
150
+ font-weight: 900;
151
+ color: inherit;
152
+ }
153
+ &:where(h2 strong) {
154
+ font-weight: 800;
155
+ color: inherit;
156
+ }
157
+ &:where(h3 strong) {
158
+ font-weight: 700;
159
+ color: inherit;
160
+ }
161
+ &:where(h4 strong) {
162
+ font-weight: 700;
163
+ color: inherit;
164
+ }
165
+
166
+ /* Media */
167
+
168
+ &:where(img) {
169
+ border-radius: var(--radius-xl);
170
+ width: 100%;
171
+ object-fit: cover;
172
+
173
+ margin-top: calc(var(--spacing) * 8);
174
+ margin-bottom: calc(var(--spacing) * 8);
175
+ }
176
+ &:where(video) {
177
+ margin-top: calc(var(--spacing) * 8);
178
+ margin-bottom: calc(var(--spacing) * 8);
179
+ }
180
+ &:where(figure) {
181
+ margin-top: calc(var(--spacing) * 10);
182
+ margin-bottom: calc(var(--spacing) * 10);
183
+ }
184
+ &:where(figure > *) {
185
+ margin-top: 0;
186
+ margin-bottom: 0;
187
+ }
188
+ &:where(figure:has(> blockquote)) {
189
+ border-left-width: 2px;
190
+ border-left-color: var(--tw-prose-quote-borders);
191
+ padding-top: calc(var(--spacing) * 2);
192
+ padding-bottom: calc(var(--spacing) * 2);
193
+
194
+ padding-inline-start: calc(var(--spacing) * 4);
195
+ }
196
+ &:where(figure:has(> blockquote) blockquote) {
197
+ padding-inline-start: 0;
198
+ border: none;
199
+ }
200
+ &:where(img + figcaption) {
201
+ display: flex;
202
+ align-items: center;
203
+ gap: calc(var(--spacing) * 1.5);
204
+ }
205
+ &:where(figcaption) {
206
+ color: var(--tw-prose-captions);
207
+
208
+ font-size: var(--text-sm);
209
+ line-height: var(--text-sm--line-height);
210
+ margin-top: calc(var(--spacing) * 3);
211
+ }
212
+ &:where(cite) {
213
+ font-style: normal;
214
+ }
215
+
216
+ /* Inline elements */
217
+ &:where(a:not(h1 a, h2 a, h3 a, h4 a, h5 a, h6 a)) {
218
+ font-weight: 400;
219
+ text-decoration: underline;
220
+ text-underline-offset: 3px;
221
+ }
222
+
223
+ &:where(a:focus-visible) {
224
+ border-radius: var(--radius-sm);
225
+ outline: 2px solid var(--color-focus-ring);
226
+ outline-offset: 2px;
227
+ }
228
+ &:where(:is(h1, h2, h3) a) {
229
+ color: var(--tw-prose-headings);
230
+ font-weight: inherit;
231
+ text-decoration: none;
232
+ }
233
+
234
+ /* Inline code element */
235
+ &:where(code:not(pre code)) {
236
+ font-size: 0.875rem;
237
+ line-height: 1.25rem;
238
+ font-weight: 700;
239
+ border-radius: 6px;
240
+ padding: calc(var(--spacing) * 0.5) calc(var(--spacing) * 1.5);
241
+ margin: calc(var(--spacing) * -0.5) 0px;
242
+ background: var(--color-bg-secondary);
243
+ box-shadow: 0 0 0 1px var(--color-border-secondary);
244
+
245
+ &::before,
246
+ &::after {
247
+ content: "";
248
+ }
249
+ }
250
+ }
251
+
252
+ .prose.prose-centered-quote :not(:where([class~="not-prose"], [class~="not-prose"] *)) {
253
+ &:where(blockquote) {
254
+ padding-inline-start: 0px !important;
255
+ border-left: none;
256
+ text-align: center;
257
+ }
258
+ &:where(figure:has(> blockquote)) {
259
+ border-left: none;
260
+ padding-inline-start: 0px !important;
261
+ padding-top: 0px !important;
262
+ padding-bottom: 0px !important;
263
+ text-align: center;
264
+ }
265
+ }
266
+
267
+ .prose.prose-minimal-quote :not(:where([class~="not-prose"], [class~="not-prose"] *)) {
268
+ &:where(blockquote) {
269
+ border-left: none;
270
+ padding-inline-start: 0px !important;
271
+ }
272
+ &:where(figure:has(> blockquote)) {
273
+ border-left: none;
274
+ padding-inline-start: 0px !important;
275
+ }
276
+ }
277
+
278
+ .prose.md\:prose-lg:not(:where([class~="not-prose"], [class~="not-prose"] *)) {
279
+ @media (width >= 48rem /* 768px */) {
280
+ /* Base */
281
+ font-size: var(--text-lg);
282
+ line-height: var(--text-lg--line-height);
283
+ }
284
+ }
285
+
286
+ .prose.md\:prose-lg :not(:where([class~="not-prose"], [class~="not-prose"] *)) {
287
+ @media (width >= 48rem /* 768px */) {
288
+ /* Text */
289
+ &:where(p) {
290
+ margin-top: calc(var(--spacing) * 4.5);
291
+ margin-bottom: calc(var(--spacing) * 4.5);
292
+ }
293
+
294
+ &:where([class~="lead"]) {
295
+ font-size: var(--text-xl);
296
+ line-height: var(--text-xl--line-height);
297
+ margin-top: 1.09em;
298
+ margin-bottom: 1.09em;
299
+ }
300
+
301
+ /* Lists */
302
+ &:where(ol) {
303
+ margin-top: calc(var(--spacing) * 4.5);
304
+ margin-bottom: calc(var(--spacing) * 4.5);
305
+ padding-inline-start: calc(var(--spacing) * 6.5);
306
+ }
307
+ &:where(ul) {
308
+ margin-top: calc(var(--spacing) * 4.5);
309
+ margin-bottom: calc(var(--spacing) * 4.5);
310
+ padding-inline-start: calc(var(--spacing) * 6.5);
311
+ }
312
+
313
+ &:where(ol > li) {
314
+ padding-inline-start: 1px;
315
+ margin-top: 0;
316
+ margin-bottom: 0;
317
+ }
318
+ &:where(ul > li) {
319
+ padding-inline-start: 1px;
320
+ margin-top: 0;
321
+ margin-bottom: 0;
322
+ }
323
+
324
+ /* Horizontal rules */
325
+ &:where(hr) {
326
+ margin-top: calc(var(--spacing) * 8);
327
+ margin-bottom: calc(var(--spacing) * 8);
328
+ }
329
+
330
+ /* Quotes */
331
+ &:where(blockquote) {
332
+ padding-inline-start: 0;
333
+ margin-top: calc(var(--spacing) * 12);
334
+ margin-bottom: calc(var(--spacing) * 12);
335
+ }
336
+ &:where(blockquote p) {
337
+ margin: 0;
338
+
339
+ font-size: var(--text-display-xs);
340
+ line-height: var(--text-display-xs--line-height);
341
+ }
342
+
343
+ /* Headings */
344
+ &:where(h1) {
345
+ font-size: var(--text-display-md);
346
+ line-height: var(--text-display-md--line-height);
347
+ margin-bottom: calc(var(--spacing) * 6);
348
+ margin-top: calc(var(--spacing) * 12);
349
+ }
350
+ &:where(h2) {
351
+ font-size: var(--text-display-sm);
352
+ line-height: var(--text-display-sm--line-height);
353
+ margin-bottom: calc(var(--spacing) * 5);
354
+ margin-top: calc(var(--spacing) * 10);
355
+ }
356
+ &:where(h3) {
357
+ font-size: var(--text-display-xs);
358
+ line-height: var(--text-display-xs--line-height);
359
+ margin-bottom: calc(var(--spacing) * 4);
360
+ margin-top: calc(var(--spacing) * 8);
361
+ }
362
+ &:where(h4) {
363
+ font-size: var(--text-xl);
364
+ line-height: var(--text-xl--line-height);
365
+ margin-bottom: calc(var(--spacing) * 3);
366
+ margin-top: calc(var(--spacing) * 8);
367
+ }
368
+ &:where(h2 + *) {
369
+ margin-top: 0;
370
+ }
371
+ &:where(h3 + *) {
372
+ margin-top: 0;
373
+ }
374
+ &:where(h4 + *) {
375
+ margin-top: 0;
376
+ }
377
+
378
+ &:where(figure) {
379
+ margin-top: calc(var(--spacing) * 12);
380
+ margin-bottom: calc(var(--spacing) * 12);
381
+ }
382
+ &:where(figure > *) {
383
+ margin-top: 0;
384
+ margin-bottom: 0;
385
+ }
386
+ &:where(figure:has(> blockquote)) {
387
+ padding-inline-start: calc(var(--spacing) * 5);
388
+ }
389
+ &:where(figure > blockquote + figcaption) {
390
+ font-size: var(--text-md);
391
+ line-height: var(--text-md--line-height);
392
+ }
393
+
394
+ &:where(figcaption) {
395
+ margin-top: calc(var(--spacing) * 4);
396
+ }
397
+
398
+ /* Inline elements */
399
+ &:where(a:not(h1 a, h2 a, h3 a, h4 a, h5 a, h6 a)) {
400
+ font-weight: 400;
401
+ text-decoration: underline;
402
+ text-underline-offset: 3px;
403
+ }
404
+ &:where(:is(h1, h2, h3) a) {
405
+ color: var(--tw-prose-headings);
406
+ font-weight: inherit;
407
+ text-decoration: none;
408
+ }
409
+
410
+ /* Inline code element */
411
+ &:where(code:not(pre code)) {
412
+ font-size: 0.875rem;
413
+ line-height: 1.25rem;
414
+ font-weight: 700;
415
+ border-radius: 6px;
416
+ padding: calc(var(--spacing) * 0.5) calc(var(--spacing) * 1.5);
417
+ margin: calc(var(--spacing) * -0.5) 0px;
418
+ background: var(--color-bg-secondary);
419
+ box-shadow: 0 0 0 1px var(--color-border-secondary);
420
+ }
421
+ }
422
+ }
423
+
424
+ /* Remove top margin from first element */
425
+ .prose > :first-child:not(:where([class~="not-prose"], [class~="not-prose"] *)) {
426
+ margin-top: 0;
427
+ }
428
+ .prose > :last-child:not(:where([class~="not-prose"], [class~="not-prose"] *)) {
429
+ margin-bottom: 0;
430
+ }
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Theme Configuration
3
+ * Single source of truth for all themes
4
+ */
5
+
6
+ export const THEME_CONFIG = {
7
+ classic: '', // Base files with no suffix (hero-home.tsx)
8
+ aman: '.aman', // Aman Hotels variant files (hero-home.aman.tsx)
9
+ } as const;
10
+
11
+ export type Theme = keyof typeof THEME_CONFIG;
12
+
13
+ export function getAvailableThemes(): Theme[] {
14
+ return Object.keys(THEME_CONFIG) as Theme[];
15
+ }
16
+
17
+ export function getThemeSuffix(theme: Theme): string {
18
+ return THEME_CONFIG[theme] || '';
19
+ }
20
+
21
+ export function isValidTheme(theme: string): theme is Theme {
22
+ return theme in THEME_CONFIG;
23
+ }
@@ -0,0 +1,53 @@
1
+ import { Photo, PhotoAttachment } from './photos';
2
+
3
+ // Blog post type definitions (aligned with Rails BlogPostSerializer)
4
+ export interface BlogPost {
5
+ id: number;
6
+ title: string;
7
+ slug: string;
8
+ status: string;
9
+ published_at?: string;
10
+ excerpt_markdown?: string;
11
+ content_markdown: string;
12
+ featured: boolean;
13
+ seo_title?: string;
14
+ seo_description?: string;
15
+ seo_keywords?: string;
16
+ created_at: string;
17
+ updated_at: string;
18
+ photo_attachments?: PhotoAttachment[];
19
+ blog_post_authors?: BlogPostAuthor[];
20
+ blog_post_tags?: BlogPostTag[];
21
+ }
22
+
23
+ export interface BlogPostParams {
24
+ status?: string;
25
+ author_id?: number;
26
+ tag_id?: number;
27
+ q?: string;
28
+ page?: number;
29
+ per_page?: number;
30
+ featured?: boolean;
31
+ }
32
+
33
+ export type BlogPostResponse = BlogPost[];
34
+
35
+ export interface BlogPostAuthor {
36
+ id: number;
37
+ name: string;
38
+ slug: string;
39
+ bio_markdown?: string;
40
+ active: boolean;
41
+ created_at: string;
42
+ updated_at: string;
43
+ photo_attachments?: PhotoAttachment[];
44
+ }
45
+
46
+ export interface BlogPostTag {
47
+ id: number;
48
+ name: string;
49
+ slug: string;
50
+ description?: string;
51
+ created_at: string;
52
+ updated_at: string;
53
+ }
@@ -0,0 +1,44 @@
1
+ import { Photo, PhotoAttachment } from './photos';
2
+
3
+ // Company information type definitions (aligned with Rails CompanyInformationSerializer)
4
+ export interface CompanyInformation {
5
+ id: number;
6
+ company_name: string;
7
+ tagline: string;
8
+ mission_statement_markdown?: string;
9
+ about_text_markdown?: string;
10
+ description_markdown?: string;
11
+ values_markdown?: string;
12
+ stats_markdown?: string;
13
+ founded_year?: number;
14
+ logo_photo?: Photo; // Direct logo_photo association
15
+ favicon_url?: string;
16
+ facebook_url?: string;
17
+ instagram_url?: string;
18
+ tiktok_url?: string;
19
+ linkedin_url?: string;
20
+ twitter_url?: string;
21
+ youtube_url?: string;
22
+ pinterest_url?: string;
23
+ google_my_business_url?: string;
24
+ yelp_url?: string;
25
+ tripadvisor_url?: string;
26
+ google_reviews_url?: string;
27
+ primary_phone?: string;
28
+ primary_email?: string;
29
+ primary_address_line_1?: string;
30
+ primary_address_line_2?: string;
31
+ primary_city?: string;
32
+ primary_state?: string;
33
+ primary_zip_code?: string;
34
+ primary_country?: string;
35
+ support_email?: string;
36
+ sales_email?: string;
37
+ business_hours?: string;
38
+ created_at: string;
39
+ updated_at: string;
40
+ photo_attachments?: PhotoAttachment[];
41
+ account_status?: string; // 'active', 'stub', etc. - for stub mode detection
42
+ }
43
+
44
+ export type CompanyInformationResponse = CompanyInformation | null;
@@ -0,0 +1,63 @@
1
+ import { Photo, PhotoAttachment } from './photos';
2
+
3
+ // Contact type definitions
4
+ export interface ContactInfo {
5
+ id?: number;
6
+ about_text_markdown?: string;
7
+ business_hours?: Record<string, { open: string; close: string }>;
8
+ company_name?: string;
9
+ description_markdown?: string;
10
+ facebook_url?: string;
11
+ favicon_url?: string;
12
+ founded_year?: string;
13
+ google_my_business_url?: string;
14
+ google_reviews_url?: string;
15
+ instagram_url?: string;
16
+ linkedin_url?: string;
17
+ mission_statement_markdown?: string;
18
+ pinterest_url?: string;
19
+ primary_address_line_1?: string;
20
+ primary_address_line_2?: string;
21
+ primary_city?: string;
22
+ primary_country?: string;
23
+ primary_email?: string;
24
+ primary_phone?: string;
25
+ primary_state?: string;
26
+ primary_zip_code?: string;
27
+ sales_email?: string;
28
+ stats_markdown?: string;
29
+ support_email?: string;
30
+ tagline?: string;
31
+ tiktok_url?: string;
32
+ tripadvisor_url?: string;
33
+ twitter_url?: string;
34
+ values_markdown?: string;
35
+ yelp_url?: string;
36
+ youtube_url?: string;
37
+ photo_attachments?: PhotoAttachment[];
38
+ }
39
+
40
+ export interface ContactFormSubmission {
41
+ id: number;
42
+ name: string;
43
+ email: string;
44
+ phone?: string;
45
+ message: string;
46
+ source: string;
47
+ created_at: string;
48
+ }
49
+
50
+ export interface ContactFormData {
51
+ name: string;
52
+ email: string;
53
+ phone?: string;
54
+ message: string;
55
+ source?: string;
56
+ }
57
+
58
+ export type ContactResponse = ContactInfo | null;
59
+
60
+ export interface ContactFormResponse {
61
+ message: string;
62
+ data: ContactFormSubmission;
63
+ }
@@ -0,0 +1,37 @@
1
+ import { PhotoAttachment } from './photos';
2
+
3
+ // FAQ type definitions
4
+ export interface FaqQuestion {
5
+ id: number;
6
+ question: string;
7
+ answer: string;
8
+ answer_markdown?: string;
9
+ category_slug?: string;
10
+ featured: boolean;
11
+ sort_order: number;
12
+ created_at: string;
13
+ updated_at: string;
14
+ photo_attachments?: PhotoAttachment[];
15
+ }
16
+
17
+ export interface FaqCategory {
18
+ id: number;
19
+ name: string;
20
+ slug: string;
21
+ description?: string;
22
+ active: boolean;
23
+ sort_order: number;
24
+ questions_count: number;
25
+ }
26
+
27
+ export interface FaqParams {
28
+ category_slug?: string;
29
+ featured?: boolean;
30
+ q?: string;
31
+ page?: number;
32
+ per_page?: number;
33
+ }
34
+
35
+ export type FaqResponse = FaqQuestion[];
36
+
37
+ export type FaqCategoryResponse = FaqCategory[];
@@ -0,0 +1,34 @@
1
+ import { PhotoAttachment } from './photos';
2
+
3
+ // Job posting type definitions
4
+ export interface JobPosting {
5
+ id: number;
6
+ title: string;
7
+ slug: string;
8
+ description_markdown: string;
9
+ requirements_markdown?: string;
10
+ benefits_markdown?: string;
11
+ employment_type: string;
12
+ location: string;
13
+ experience_level?: string;
14
+ remote_ok?: boolean;
15
+ salary_range?: string;
16
+ posted_at: string;
17
+ expires_at?: string;
18
+ status: 'active' | 'inactive' | 'expired';
19
+ featured: boolean;
20
+ created_at: string;
21
+ updated_at: string;
22
+ photo_attachments?: PhotoAttachment[];
23
+ }
24
+
25
+ export interface JobPostingParams {
26
+ featured?: boolean;
27
+ employment_type?: string;
28
+ location?: string;
29
+ q?: string;
30
+ page?: number;
31
+ per_page?: number;
32
+ }
33
+
34
+ export type JobPostingResponse = JobPosting[];