keystone-design-bootstrap 1.0.48 → 1.0.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/{blog-post-CvRhU9ss.d.ts → blog-post-D7HFCDp1.d.ts} +2 -2
  2. package/dist/design_system/elements/index.d.ts +25 -1
  3. package/dist/design_system/elements/index.js +103 -3
  4. package/dist/design_system/elements/index.js.map +1 -1
  5. package/dist/design_system/sections/index.d.ts +64 -3
  6. package/dist/design_system/sections/index.js +1305 -458
  7. package/dist/design_system/sections/index.js.map +1 -1
  8. package/dist/form-BLZuTGkr.d.ts +137 -0
  9. package/dist/index.d.ts +6 -5
  10. package/dist/index.js +1335 -487
  11. package/dist/index.js.map +1 -1
  12. package/dist/lib/server-api.d.ts +49 -4
  13. package/dist/lib/server-api.js +17 -0
  14. package/dist/lib/server-api.js.map +1 -1
  15. package/dist/photos-8jMeetqV.d.ts +47 -0
  16. package/dist/types/index.d.ts +6 -5
  17. package/dist/utils/photo-helpers.d.ts +6 -15
  18. package/dist/utils/photo-helpers.js +10 -1
  19. package/dist/utils/photo-helpers.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/design_system/elements/index.tsx +4 -0
  22. package/src/design_system/elements/modal/modal.tsx +129 -0
  23. package/src/design_system/sections/index.tsx +20 -2
  24. package/src/design_system/sections/offer-detail.tsx +46 -0
  25. package/src/design_system/sections/offers-gallery.tsx +40 -0
  26. package/src/design_system/sections/offers-grid.tsx +108 -0
  27. package/src/design_system/sections/offers-section.tsx +90 -0
  28. package/src/design_system/sections/service-menu-section.tsx +813 -0
  29. package/src/lib/server-api.ts +63 -0
  30. package/src/types/api/photos.ts +11 -10
  31. package/src/types/api/service.ts +21 -0
  32. package/src/utils/photo-helpers.ts +3 -14
  33. package/dist/company-information-C_k_sLSB.d.ts +0 -46
  34. package/dist/form-CWXC-IHT.d.ts +0 -88
  35. package/dist/website-photos-_n2g24IM.d.ts +0 -20
@@ -4,6 +4,7 @@
4
4
  */
5
5
 
6
6
  import type { CompanyInformation } from '../types/api/company-information';
7
+ import type { PhotoAttachment } from '../types/api/photos';
7
8
  import type { Service } from '../types/api/service';
8
9
  import type { WebsitePhotos } from '../types/api/website-photos';
9
10
 
@@ -129,6 +130,15 @@ export async function getSocialPosts() {
129
130
  return serverFetch('/public/social_posts', defaultOptions);
130
131
  }
131
132
 
133
+ /** Packages (bundles of service items). */
134
+ export async function getPackages() {
135
+ return serverFetch('/public/packages', defaultOptions);
136
+ }
137
+
138
+ export async function getPackage(slug: string) {
139
+ return serverFetch(`/public/packages/by_slug/${encodeURIComponent(slug)}`, defaultOptions);
140
+ }
141
+
132
142
  // Alias for testimonials (API uses "reviews")
133
143
  export async function getTestimonials() {
134
144
  return getReviews();
@@ -140,3 +150,56 @@ export async function getForm(formType: string) {
140
150
  return serverFetch<FormDefinition>(`/public/forms/${encodeURIComponent(formType)}`, defaultOptions);
141
151
  }
142
152
 
153
+ /** Minimal service for offer detail (from GET /public/offers/:id). */
154
+ export interface OfferServiceSummary {
155
+ id: number;
156
+ name: string;
157
+ slug: string;
158
+ summary?: string | null;
159
+ }
160
+
161
+ /** Package summary (nested on each offer in list and single-offer responses). */
162
+ export interface OfferPackageSummary {
163
+ id: number;
164
+ name: string;
165
+ slug: string;
166
+ summary?: string | null;
167
+ description_markdown?: string | null;
168
+ }
169
+
170
+ /** Offer from public API. */
171
+ export interface OfferPublic {
172
+ id: number;
173
+ name: string;
174
+ description: string | null;
175
+ value_terms: string | null;
176
+ /** Optional; when absent or null, offer has no expiration. */
177
+ expires_at?: string | null;
178
+ expired?: boolean;
179
+ /** Service IDs (used for category_names fallback when not provided by API). */
180
+ service_ids?: number[];
181
+ /** Package IDs (included in list response; nested services/packages are the source of truth). */
182
+ package_ids?: number[];
183
+ /** Category names from API (services + service_items + packages). */
184
+ category_names?: string[];
185
+ /** Photo attachments from related services (same shape as Service.photo_attachments). */
186
+ photo_attachments?: PhotoAttachment[];
187
+ /** Present when fetching single offer (GET /public/offers/:id). */
188
+ services?: OfferServiceSummary[];
189
+ /** Specific menu items this offer applies to (single offer only). */
190
+ service_items?: OfferServiceSummary[];
191
+ /** Packages this offer applies to (single offer only). */
192
+ packages?: OfferPackageSummary[];
193
+ }
194
+
195
+ /** List offers for the current account (API key scoped). */
196
+ export async function getOffers(): Promise<OfferPublic[] | null> {
197
+ const data = await serverFetch<OfferPublic[]>('/public/offers', defaultOptions);
198
+ return Array.isArray(data) ? data : null;
199
+ }
200
+
201
+ /** Single offer with services for detail page. */
202
+ export async function getOffer(id: number | string): Promise<OfferPublic | null> {
203
+ return serverFetch<OfferPublic>(`/public/offers/${id}`, defaultOptions);
204
+ }
205
+
@@ -3,26 +3,27 @@
3
3
  */
4
4
 
5
5
  export interface Photo {
6
- id: number;
7
- title: string;
6
+ id?: number;
7
+ title?: string;
8
8
  description?: string;
9
9
  alt_text?: string;
10
10
  thumbnail_url?: string;
11
11
  medium_url?: string;
12
12
  large_url?: string;
13
13
  original_url?: string;
14
- generated: boolean;
15
- created_at: string;
16
- updated_at: string;
14
+ generated?: boolean;
15
+ created_at?: string;
16
+ updated_at?: string;
17
17
  }
18
18
 
19
19
  export interface PhotoAttachment {
20
20
  id: number;
21
- photo: Photo;
22
- featured: boolean;
23
- sort_order: number;
24
- created_at: string;
25
- updated_at: string;
21
+ /** May be omitted in some API responses. */
22
+ photo?: Photo;
23
+ featured?: boolean;
24
+ sort_order?: number;
25
+ created_at?: string;
26
+ updated_at?: string;
26
27
  }
27
28
 
28
29
 
@@ -23,10 +23,31 @@ export interface Service {
23
23
  original_url?: string;
24
24
  };
25
25
  }>;
26
+ /** Menu items under this service category (when loaded with associations). */
27
+ service_items?: ServiceItem[];
26
28
  created_at: string;
27
29
  updated_at: string;
28
30
  }
29
31
 
32
+ /** Single menu item under a service category. */
33
+ export interface ServiceItem {
34
+ id: number;
35
+ name: string;
36
+ slug: string;
37
+ summary?: string | null;
38
+ description_markdown?: string | null;
39
+ pricing_info?: string | null;
40
+ price_cents?: number | null;
41
+ duration_minutes?: number | null;
42
+ sort_order: number;
43
+ service_id?: number;
44
+ /** Present when loaded for public/menu (from related service’s photos). */
45
+ photo_attachments?: Array<{
46
+ id: number;
47
+ photo?: { thumbnail_url?: string; medium_url?: string; large_url?: string; original_url?: string; title?: string; alt_text?: string };
48
+ }>;
49
+ }
50
+
30
51
  export interface ServiceParams {
31
52
  featured?: boolean;
32
53
  q?: string;
@@ -2,8 +2,11 @@
2
2
  * Helper functions for extracting photo URLs from photo associations
3
3
  */
4
4
 
5
+ import type { PhotoAttachment } from '../types/api/photos';
5
6
  import type { WebsitePhotos } from '../types/api/website-photos';
6
7
 
8
+ export type { PhotoAttachment } from '../types/api/photos';
9
+
7
10
  /** Video file extensions treated as video (match backend ExternalPhotoService.video_url?) */
8
11
  const VIDEO_EXTENSIONS = ['.mp4', '.mov', '.webm', '.m4v', '.avi', '.mkv', '.flv', '.wmv'];
9
12
 
@@ -17,20 +20,6 @@ export function isVideoUrl(url: string | null | undefined): boolean {
17
20
  return VIDEO_EXTENSIONS.includes(ext);
18
21
  }
19
22
 
20
- export interface PhotoAttachment {
21
- id: number;
22
- photo: {
23
- id: number;
24
- title: string;
25
- thumbnail_url?: string;
26
- medium_url?: string;
27
- large_url?: string;
28
- original_url?: string;
29
- };
30
- featured: boolean;
31
- sort_order: number;
32
- }
33
-
34
23
  /**
35
24
  * Get the best available photo URL from a photos array
36
25
  * Priority: featured photo > first photo > fallback
@@ -1,46 +0,0 @@
1
- import { P as Photo, a as PhotoAttachment } from './form-CWXC-IHT.js';
2
-
3
- interface CompanyInformation {
4
- id: number;
5
- company_name: string;
6
- tagline: string;
7
- mission_statement_markdown?: string;
8
- about_text_markdown?: string;
9
- description_markdown?: string;
10
- values_markdown?: string;
11
- stats_markdown?: string;
12
- founded_year?: number;
13
- logo_photo?: Photo;
14
- favicon_url?: string;
15
- facebook_url?: string;
16
- instagram_url?: string;
17
- tiktok_url?: string;
18
- linkedin_url?: string;
19
- twitter_url?: string;
20
- youtube_url?: string;
21
- pinterest_url?: string;
22
- google_my_business_url?: string;
23
- yelp_url?: string;
24
- tripadvisor_url?: string;
25
- google_reviews_url?: string;
26
- primary_phone?: string;
27
- primary_email?: string;
28
- primary_address_line_1?: string;
29
- primary_address_line_2?: string;
30
- primary_city?: string;
31
- primary_state?: string;
32
- primary_zip_code?: string;
33
- primary_country?: string;
34
- support_email?: string;
35
- sales_email?: string;
36
- business_hours?: string;
37
- external_management_url?: string;
38
- created_at: string;
39
- updated_at: string;
40
- photo_attachments?: PhotoAttachment[];
41
- account_status?: string;
42
- chat_enabled?: boolean;
43
- }
44
- type CompanyInformationResponse = CompanyInformation | null;
45
-
46
- export type { CompanyInformation as C, CompanyInformationResponse as a };
@@ -1,88 +0,0 @@
1
- interface Service {
2
- id: number;
3
- name: string;
4
- slug: string;
5
- description_markdown: string;
6
- summary?: string;
7
- pricing_info?: string;
8
- features_markdown?: string;
9
- featured: boolean;
10
- sort_order: number;
11
- photo_attachments?: Array<{
12
- id: number;
13
- featured: boolean;
14
- attachable_id?: number;
15
- attachable_type?: string;
16
- photo?: {
17
- id: number;
18
- title: string;
19
- thumbnail_url?: string;
20
- medium_url?: string;
21
- large_url?: string;
22
- original_url?: string;
23
- };
24
- }>;
25
- created_at: string;
26
- updated_at: string;
27
- }
28
- interface ServiceParams {
29
- featured?: boolean;
30
- q?: string;
31
- page?: number;
32
- per_page?: number;
33
- }
34
- type ServiceResponse = Service[];
35
-
36
- /**
37
- * Photo and PhotoAttachment type definitions
38
- */
39
- interface Photo {
40
- id: number;
41
- title: string;
42
- description?: string;
43
- alt_text?: string;
44
- thumbnail_url?: string;
45
- medium_url?: string;
46
- large_url?: string;
47
- original_url?: string;
48
- generated: boolean;
49
- created_at: string;
50
- updated_at: string;
51
- }
52
- interface PhotoAttachment {
53
- id: number;
54
- photo: Photo;
55
- featured: boolean;
56
- sort_order: number;
57
- created_at: string;
58
- updated_at: string;
59
- }
60
-
61
- /**
62
- * Form definition from API (GET /public/forms/:form_type).
63
- * fields is an ordered array; each item is a single field or an array of fields (inline row). Max depth 2.
64
- */
65
- interface FormFieldDefinition {
66
- name: string;
67
- type: string;
68
- label: string;
69
- required?: boolean;
70
- placeholder?: string;
71
- /** For hidden fields, optional value to submit. */
72
- value?: string;
73
- }
74
- /** One item in the fields array: either a single field or a row of fields (inline). */
75
- type FormFieldItem = FormFieldDefinition | FormFieldDefinition[];
76
- interface FormDefinition {
77
- id: number;
78
- name: string;
79
- form_type: string;
80
- /** Ordered array; each element is a field or an array of fields (inline row). */
81
- fields: FormFieldItem[];
82
- settings?: Record<string, unknown>;
83
- created_at?: string;
84
- updated_at?: string;
85
- }
86
- type FormType = 'lead' | 'job_application';
87
-
88
- export type { FormDefinition as F, Photo as P, Service as S, PhotoAttachment as a, FormFieldDefinition as b, FormFieldItem as c, FormType as d, ServiceParams as e, ServiceResponse as f };
@@ -1,20 +0,0 @@
1
- interface WebsitePhoto {
2
- id: number;
3
- url: string;
4
- thumbnail_url?: string;
5
- medium_url?: string;
6
- alt: string;
7
- source: 'account' | 'industry';
8
- }
9
- interface WebsitePhotos {
10
- logo?: WebsitePhoto | null;
11
- favicon?: WebsitePhoto | null;
12
- hero?: WebsitePhoto | null;
13
- contact?: WebsitePhoto | null;
14
- about?: WebsitePhoto | null;
15
- careers?: WebsitePhoto | null;
16
- stock_photos?: WebsitePhoto[];
17
- }
18
- type WebsitePhotosResponse = WebsitePhotos;
19
-
20
- export type { WebsitePhotos as W, WebsitePhoto as a, WebsitePhotosResponse as b };