@aws505/sheetsite 1.0.0

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 (57) hide show
  1. package/README.md +105 -0
  2. package/dist/components/index.js +1696 -0
  3. package/dist/components/index.js.map +1 -0
  4. package/dist/components/index.mjs +1630 -0
  5. package/dist/components/index.mjs.map +1 -0
  6. package/dist/config/index.js +1840 -0
  7. package/dist/config/index.js.map +1 -0
  8. package/dist/config/index.mjs +1793 -0
  9. package/dist/config/index.mjs.map +1 -0
  10. package/dist/data/index.js +1296 -0
  11. package/dist/data/index.js.map +1 -0
  12. package/dist/data/index.mjs +1220 -0
  13. package/dist/data/index.mjs.map +1 -0
  14. package/dist/index.js +5433 -0
  15. package/dist/index.js.map +1 -0
  16. package/dist/index.mjs +5285 -0
  17. package/dist/index.mjs.map +1 -0
  18. package/dist/seo/index.js +187 -0
  19. package/dist/seo/index.js.map +1 -0
  20. package/dist/seo/index.mjs +155 -0
  21. package/dist/seo/index.mjs.map +1 -0
  22. package/dist/theme/index.js +552 -0
  23. package/dist/theme/index.js.map +1 -0
  24. package/dist/theme/index.mjs +526 -0
  25. package/dist/theme/index.mjs.map +1 -0
  26. package/package.json +96 -0
  27. package/src/components/index.ts +41 -0
  28. package/src/components/layout/Footer.tsx +234 -0
  29. package/src/components/layout/Header.tsx +134 -0
  30. package/src/components/sections/FAQ.tsx +178 -0
  31. package/src/components/sections/Gallery.tsx +107 -0
  32. package/src/components/sections/Hero.tsx +202 -0
  33. package/src/components/sections/Hours.tsx +225 -0
  34. package/src/components/sections/Services.tsx +216 -0
  35. package/src/components/sections/Testimonials.tsx +184 -0
  36. package/src/components/ui/Button.tsx +158 -0
  37. package/src/components/ui/Card.tsx +162 -0
  38. package/src/components/ui/Icons.tsx +508 -0
  39. package/src/config/index.ts +207 -0
  40. package/src/config/presets/generic.ts +153 -0
  41. package/src/config/presets/home-kitchen.ts +154 -0
  42. package/src/config/presets/index.ts +708 -0
  43. package/src/config/presets/professional.ts +165 -0
  44. package/src/config/presets/repair.ts +160 -0
  45. package/src/config/presets/restaurant.ts +162 -0
  46. package/src/config/presets/salon.ts +178 -0
  47. package/src/config/presets/tailor.ts +159 -0
  48. package/src/config/types.ts +314 -0
  49. package/src/data/csv-parser.ts +154 -0
  50. package/src/data/defaults.ts +202 -0
  51. package/src/data/google-drive.ts +148 -0
  52. package/src/data/index.ts +535 -0
  53. package/src/data/sheets.ts +709 -0
  54. package/src/data/types.ts +379 -0
  55. package/src/seo/index.ts +272 -0
  56. package/src/theme/colors.ts +351 -0
  57. package/src/theme/index.ts +249 -0
@@ -0,0 +1,1630 @@
1
+ // src/components/layout/Header.tsx
2
+ import { useState } from "react";
3
+
4
+ // src/components/ui/Icons.tsx
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ function PhoneIcon({ className = "", size = 24, ...props }) {
7
+ return /* @__PURE__ */ jsx(
8
+ "svg",
9
+ {
10
+ xmlns: "http://www.w3.org/2000/svg",
11
+ width: size,
12
+ height: size,
13
+ viewBox: "0 0 24 24",
14
+ fill: "none",
15
+ stroke: "currentColor",
16
+ strokeWidth: "2",
17
+ strokeLinecap: "round",
18
+ strokeLinejoin: "round",
19
+ className,
20
+ ...props,
21
+ children: /* @__PURE__ */ jsx("path", { d: "M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z" })
22
+ }
23
+ );
24
+ }
25
+ function MailIcon({ className = "", size = 24, ...props }) {
26
+ return /* @__PURE__ */ jsxs(
27
+ "svg",
28
+ {
29
+ xmlns: "http://www.w3.org/2000/svg",
30
+ width: size,
31
+ height: size,
32
+ viewBox: "0 0 24 24",
33
+ fill: "none",
34
+ stroke: "currentColor",
35
+ strokeWidth: "2",
36
+ strokeLinecap: "round",
37
+ strokeLinejoin: "round",
38
+ className,
39
+ ...props,
40
+ children: [
41
+ /* @__PURE__ */ jsx("rect", { width: "20", height: "16", x: "2", y: "4", rx: "2" }),
42
+ /* @__PURE__ */ jsx("path", { d: "m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" })
43
+ ]
44
+ }
45
+ );
46
+ }
47
+ function MapPinIcon({ className = "", size = 24, ...props }) {
48
+ return /* @__PURE__ */ jsxs(
49
+ "svg",
50
+ {
51
+ xmlns: "http://www.w3.org/2000/svg",
52
+ width: size,
53
+ height: size,
54
+ viewBox: "0 0 24 24",
55
+ fill: "none",
56
+ stroke: "currentColor",
57
+ strokeWidth: "2",
58
+ strokeLinecap: "round",
59
+ strokeLinejoin: "round",
60
+ className,
61
+ ...props,
62
+ children: [
63
+ /* @__PURE__ */ jsx("path", { d: "M20 10c0 6-8 12-8 12s-8-6-8-12a8 8 0 0 1 16 0Z" }),
64
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "10", r: "3" })
65
+ ]
66
+ }
67
+ );
68
+ }
69
+ function ClockIcon({ className = "", size = 24, ...props }) {
70
+ return /* @__PURE__ */ jsxs(
71
+ "svg",
72
+ {
73
+ xmlns: "http://www.w3.org/2000/svg",
74
+ width: size,
75
+ height: size,
76
+ viewBox: "0 0 24 24",
77
+ fill: "none",
78
+ stroke: "currentColor",
79
+ strokeWidth: "2",
80
+ strokeLinecap: "round",
81
+ strokeLinejoin: "round",
82
+ className,
83
+ ...props,
84
+ children: [
85
+ /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
86
+ /* @__PURE__ */ jsx("polyline", { points: "12 6 12 12 16 14" })
87
+ ]
88
+ }
89
+ );
90
+ }
91
+ function StarIcon({ className = "", size = 24, filled = false, ...props }) {
92
+ return /* @__PURE__ */ jsx(
93
+ "svg",
94
+ {
95
+ xmlns: "http://www.w3.org/2000/svg",
96
+ width: size,
97
+ height: size,
98
+ viewBox: "0 0 24 24",
99
+ fill: filled ? "currentColor" : "none",
100
+ stroke: "currentColor",
101
+ strokeWidth: "2",
102
+ strokeLinecap: "round",
103
+ strokeLinejoin: "round",
104
+ className,
105
+ ...props,
106
+ children: /* @__PURE__ */ jsx("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" })
107
+ }
108
+ );
109
+ }
110
+ function ChevronDownIcon({ className = "", size = 24, ...props }) {
111
+ return /* @__PURE__ */ jsx(
112
+ "svg",
113
+ {
114
+ xmlns: "http://www.w3.org/2000/svg",
115
+ width: size,
116
+ height: size,
117
+ viewBox: "0 0 24 24",
118
+ fill: "none",
119
+ stroke: "currentColor",
120
+ strokeWidth: "2",
121
+ strokeLinecap: "round",
122
+ strokeLinejoin: "round",
123
+ className,
124
+ ...props,
125
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
126
+ }
127
+ );
128
+ }
129
+ function ChevronRightIcon({ className = "", size = 24, ...props }) {
130
+ return /* @__PURE__ */ jsx(
131
+ "svg",
132
+ {
133
+ xmlns: "http://www.w3.org/2000/svg",
134
+ width: size,
135
+ height: size,
136
+ viewBox: "0 0 24 24",
137
+ fill: "none",
138
+ stroke: "currentColor",
139
+ strokeWidth: "2",
140
+ strokeLinecap: "round",
141
+ strokeLinejoin: "round",
142
+ className,
143
+ ...props,
144
+ children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
145
+ }
146
+ );
147
+ }
148
+ function MenuIcon({ className = "", size = 24, ...props }) {
149
+ return /* @__PURE__ */ jsxs(
150
+ "svg",
151
+ {
152
+ xmlns: "http://www.w3.org/2000/svg",
153
+ width: size,
154
+ height: size,
155
+ viewBox: "0 0 24 24",
156
+ fill: "none",
157
+ stroke: "currentColor",
158
+ strokeWidth: "2",
159
+ strokeLinecap: "round",
160
+ strokeLinejoin: "round",
161
+ className,
162
+ ...props,
163
+ children: [
164
+ /* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
165
+ /* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
166
+ /* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
167
+ ]
168
+ }
169
+ );
170
+ }
171
+ function XIcon({ className = "", size = 24, ...props }) {
172
+ return /* @__PURE__ */ jsxs(
173
+ "svg",
174
+ {
175
+ xmlns: "http://www.w3.org/2000/svg",
176
+ width: size,
177
+ height: size,
178
+ viewBox: "0 0 24 24",
179
+ fill: "none",
180
+ stroke: "currentColor",
181
+ strokeWidth: "2",
182
+ strokeLinecap: "round",
183
+ strokeLinejoin: "round",
184
+ className,
185
+ ...props,
186
+ children: [
187
+ /* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
188
+ /* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
189
+ ]
190
+ }
191
+ );
192
+ }
193
+ function CheckIcon({ className = "", size = 24, ...props }) {
194
+ return /* @__PURE__ */ jsx(
195
+ "svg",
196
+ {
197
+ xmlns: "http://www.w3.org/2000/svg",
198
+ width: size,
199
+ height: size,
200
+ viewBox: "0 0 24 24",
201
+ fill: "none",
202
+ stroke: "currentColor",
203
+ strokeWidth: "2",
204
+ strokeLinecap: "round",
205
+ strokeLinejoin: "round",
206
+ className,
207
+ ...props,
208
+ children: /* @__PURE__ */ jsx("path", { d: "M20 6 9 17l-5-5" })
209
+ }
210
+ );
211
+ }
212
+ function ScissorsIcon({ className = "", size = 24, ...props }) {
213
+ return /* @__PURE__ */ jsxs(
214
+ "svg",
215
+ {
216
+ xmlns: "http://www.w3.org/2000/svg",
217
+ width: size,
218
+ height: size,
219
+ viewBox: "0 0 24 24",
220
+ fill: "none",
221
+ stroke: "currentColor",
222
+ strokeWidth: "2",
223
+ strokeLinecap: "round",
224
+ strokeLinejoin: "round",
225
+ className,
226
+ ...props,
227
+ children: [
228
+ /* @__PURE__ */ jsx("circle", { cx: "6", cy: "6", r: "3" }),
229
+ /* @__PURE__ */ jsx("path", { d: "M8.12 8.12 12 12" }),
230
+ /* @__PURE__ */ jsx("path", { d: "M20 4 8.12 15.88" }),
231
+ /* @__PURE__ */ jsx("circle", { cx: "6", cy: "18", r: "3" }),
232
+ /* @__PURE__ */ jsx("path", { d: "M14.8 14.8 20 20" })
233
+ ]
234
+ }
235
+ );
236
+ }
237
+ function WrenchIcon({ className = "", size = 24, ...props }) {
238
+ return /* @__PURE__ */ jsx(
239
+ "svg",
240
+ {
241
+ xmlns: "http://www.w3.org/2000/svg",
242
+ width: size,
243
+ height: size,
244
+ viewBox: "0 0 24 24",
245
+ fill: "none",
246
+ stroke: "currentColor",
247
+ strokeWidth: "2",
248
+ strokeLinecap: "round",
249
+ strokeLinejoin: "round",
250
+ className,
251
+ ...props,
252
+ children: /* @__PURE__ */ jsx("path", { d: "M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94l-3.76 3.76z" })
253
+ }
254
+ );
255
+ }
256
+ function SparklesIcon({ className = "", size = 24, ...props }) {
257
+ return /* @__PURE__ */ jsxs(
258
+ "svg",
259
+ {
260
+ xmlns: "http://www.w3.org/2000/svg",
261
+ width: size,
262
+ height: size,
263
+ viewBox: "0 0 24 24",
264
+ fill: "none",
265
+ stroke: "currentColor",
266
+ strokeWidth: "2",
267
+ strokeLinecap: "round",
268
+ strokeLinejoin: "round",
269
+ className,
270
+ ...props,
271
+ children: [
272
+ /* @__PURE__ */ jsx("path", { d: "m12 3-1.912 5.813a2 2 0 0 1-1.275 1.275L3 12l5.813 1.912a2 2 0 0 1 1.275 1.275L12 21l1.912-5.813a2 2 0 0 1 1.275-1.275L21 12l-5.813-1.912a2 2 0 0 1-1.275-1.275L12 3Z" }),
273
+ /* @__PURE__ */ jsx("path", { d: "M5 3v4" }),
274
+ /* @__PURE__ */ jsx("path", { d: "M19 17v4" }),
275
+ /* @__PURE__ */ jsx("path", { d: "M3 5h4" }),
276
+ /* @__PURE__ */ jsx("path", { d: "M17 19h4" })
277
+ ]
278
+ }
279
+ );
280
+ }
281
+ function HeartIcon({ className = "", size = 24, filled = false, ...props }) {
282
+ return /* @__PURE__ */ jsx(
283
+ "svg",
284
+ {
285
+ xmlns: "http://www.w3.org/2000/svg",
286
+ width: size,
287
+ height: size,
288
+ viewBox: "0 0 24 24",
289
+ fill: filled ? "currentColor" : "none",
290
+ stroke: "currentColor",
291
+ strokeWidth: "2",
292
+ strokeLinecap: "round",
293
+ strokeLinejoin: "round",
294
+ className,
295
+ ...props,
296
+ children: /* @__PURE__ */ jsx("path", { d: "M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z" })
297
+ }
298
+ );
299
+ }
300
+ function UtensilsIcon({ className = "", size = 24, ...props }) {
301
+ return /* @__PURE__ */ jsxs(
302
+ "svg",
303
+ {
304
+ xmlns: "http://www.w3.org/2000/svg",
305
+ width: size,
306
+ height: size,
307
+ viewBox: "0 0 24 24",
308
+ fill: "none",
309
+ stroke: "currentColor",
310
+ strokeWidth: "2",
311
+ strokeLinecap: "round",
312
+ strokeLinejoin: "round",
313
+ className,
314
+ ...props,
315
+ children: [
316
+ /* @__PURE__ */ jsx("path", { d: "M3 2v7c0 1.1.9 2 2 2h4a2 2 0 0 0 2-2V2" }),
317
+ /* @__PURE__ */ jsx("path", { d: "M7 2v20" }),
318
+ /* @__PURE__ */ jsx("path", { d: "M21 15V2v0a5 5 0 0 0-5 5v6c0 1.1.9 2 2 2h3Zm0 0v7" })
319
+ ]
320
+ }
321
+ );
322
+ }
323
+ function CakeIcon({ className = "", size = 24, ...props }) {
324
+ return /* @__PURE__ */ jsxs(
325
+ "svg",
326
+ {
327
+ xmlns: "http://www.w3.org/2000/svg",
328
+ width: size,
329
+ height: size,
330
+ viewBox: "0 0 24 24",
331
+ fill: "none",
332
+ stroke: "currentColor",
333
+ strokeWidth: "2",
334
+ strokeLinecap: "round",
335
+ strokeLinejoin: "round",
336
+ className,
337
+ ...props,
338
+ children: [
339
+ /* @__PURE__ */ jsx("path", { d: "M20 21v-8a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8" }),
340
+ /* @__PURE__ */ jsx("path", { d: "M4 16s.5-1 2-1 2.5 2 4 2 2.5-2 4-2 2.5 2 4 2 2-1 2-1" }),
341
+ /* @__PURE__ */ jsx("path", { d: "M2 21h20" }),
342
+ /* @__PURE__ */ jsx("path", { d: "M7 8v3" }),
343
+ /* @__PURE__ */ jsx("path", { d: "M12 8v3" }),
344
+ /* @__PURE__ */ jsx("path", { d: "M17 8v3" }),
345
+ /* @__PURE__ */ jsx("path", { d: "M7 4h.01" }),
346
+ /* @__PURE__ */ jsx("path", { d: "M12 4h.01" }),
347
+ /* @__PURE__ */ jsx("path", { d: "M17 4h.01" })
348
+ ]
349
+ }
350
+ );
351
+ }
352
+ function BriefcaseIcon({ className = "", size = 24, ...props }) {
353
+ return /* @__PURE__ */ jsxs(
354
+ "svg",
355
+ {
356
+ xmlns: "http://www.w3.org/2000/svg",
357
+ width: size,
358
+ height: size,
359
+ viewBox: "0 0 24 24",
360
+ fill: "none",
361
+ stroke: "currentColor",
362
+ strokeWidth: "2",
363
+ strokeLinecap: "round",
364
+ strokeLinejoin: "round",
365
+ className,
366
+ ...props,
367
+ children: [
368
+ /* @__PURE__ */ jsx("rect", { width: "20", height: "14", x: "2", y: "7", rx: "2", ry: "2" }),
369
+ /* @__PURE__ */ jsx("path", { d: "M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16" })
370
+ ]
371
+ }
372
+ );
373
+ }
374
+ function YelpIcon({ className = "", size = 24, ...props }) {
375
+ return /* @__PURE__ */ jsx(
376
+ "svg",
377
+ {
378
+ xmlns: "http://www.w3.org/2000/svg",
379
+ width: size,
380
+ height: size,
381
+ viewBox: "0 0 24 24",
382
+ fill: "currentColor",
383
+ className,
384
+ ...props,
385
+ children: /* @__PURE__ */ jsx("path", { d: "M20.16 12.73l-3.29 1.47c-.64.28-1.31-.26-1.2-.97l.52-3.4c.08-.56.49-.98 1.03-1.04l3.39-.38c.7-.08 1.22.58 1 1.23l-1.07 2.62c-.14.35-.36.41-.38.47zM14.13 15.58l-.52 3.4c-.11.7.55 1.25 1.2.97l3.29-1.47c.02-.06.24-.12.38-.47l1.07-2.62c.22-.65-.3-1.31-1-1.23l-3.39.38c-.54.06-.95.48-1.03 1.04zM10.98 3.05c-.47-.6-1.37-.5-1.7.2l-3.6 7.51c-.24.5-.01 1.1.51 1.33l2.63 1.21c.62.28 1.3-.2 1.27-.89l-.33-7.97c-.02-.56-.3-1.01-.78-1.39zM8.37 14.35l-2.63-1.21c-.52-.23-.75-.83-.51-1.33l3.6-7.51c.33-.7 1.23-.8 1.7-.2.48.38.76.83.78 1.39l.33 7.97c.03.69-.65 1.17-1.27.89zM10.04 16.42l-3.22 1.8c-.62.35-1.36-.14-1.28-.86l.44-3.52c.06-.53.42-.95.92-1.08l3.02-.78c.69-.18 1.32.43 1.09 1.1l-1.24 3.06c-.14.33-.38.34-.42.34-.04 0-.18-.01-.31.04v-.1z" })
386
+ }
387
+ );
388
+ }
389
+ function InstagramIcon({ className = "", size = 24, ...props }) {
390
+ return /* @__PURE__ */ jsxs(
391
+ "svg",
392
+ {
393
+ xmlns: "http://www.w3.org/2000/svg",
394
+ width: size,
395
+ height: size,
396
+ viewBox: "0 0 24 24",
397
+ fill: "none",
398
+ stroke: "currentColor",
399
+ strokeWidth: "2",
400
+ strokeLinecap: "round",
401
+ strokeLinejoin: "round",
402
+ className,
403
+ ...props,
404
+ children: [
405
+ /* @__PURE__ */ jsx("rect", { width: "20", height: "20", x: "2", y: "2", rx: "5", ry: "5" }),
406
+ /* @__PURE__ */ jsx("path", { d: "M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z" }),
407
+ /* @__PURE__ */ jsx("line", { x1: "17.5", x2: "17.51", y1: "6.5", y2: "6.5" })
408
+ ]
409
+ }
410
+ );
411
+ }
412
+ function FacebookIcon({ className = "", size = 24, ...props }) {
413
+ return /* @__PURE__ */ jsx(
414
+ "svg",
415
+ {
416
+ xmlns: "http://www.w3.org/2000/svg",
417
+ width: size,
418
+ height: size,
419
+ viewBox: "0 0 24 24",
420
+ fill: "none",
421
+ stroke: "currentColor",
422
+ strokeWidth: "2",
423
+ strokeLinecap: "round",
424
+ strokeLinejoin: "round",
425
+ className,
426
+ ...props,
427
+ children: /* @__PURE__ */ jsx("path", { d: "M18 2h-3a5 5 0 0 0-5 5v3H7v4h3v8h4v-8h3l1-4h-4V7a1 1 0 0 1 1-1h3z" })
428
+ }
429
+ );
430
+ }
431
+ var iconMap = {
432
+ phone: PhoneIcon,
433
+ mail: MailIcon,
434
+ email: MailIcon,
435
+ "map-pin": MapPinIcon,
436
+ location: MapPinIcon,
437
+ clock: ClockIcon,
438
+ time: ClockIcon,
439
+ star: StarIcon,
440
+ "chevron-down": ChevronDownIcon,
441
+ "chevron-right": ChevronRightIcon,
442
+ menu: MenuIcon,
443
+ x: XIcon,
444
+ close: XIcon,
445
+ check: CheckIcon,
446
+ scissors: ScissorsIcon,
447
+ wrench: WrenchIcon,
448
+ tool: WrenchIcon,
449
+ sparkles: SparklesIcon,
450
+ heart: HeartIcon,
451
+ utensils: UtensilsIcon,
452
+ food: UtensilsIcon,
453
+ cake: CakeIcon,
454
+ briefcase: BriefcaseIcon,
455
+ yelp: YelpIcon,
456
+ instagram: InstagramIcon,
457
+ facebook: FacebookIcon
458
+ };
459
+ function getIcon(name) {
460
+ return iconMap[name.toLowerCase()] || null;
461
+ }
462
+ function Icon({ name, ...props }) {
463
+ const IconComponent = getIcon(name);
464
+ if (!IconComponent) return null;
465
+ return /* @__PURE__ */ jsx(IconComponent, { ...props });
466
+ }
467
+
468
+ // src/components/layout/Header.tsx
469
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
470
+ var defaultNavigation = [
471
+ { label: "Home", href: "/" },
472
+ { label: "Services", href: "/services" },
473
+ { label: "Gallery", href: "/gallery" },
474
+ { label: "About", href: "/about" },
475
+ { label: "Contact", href: "/contact" }
476
+ ];
477
+ function Header({
478
+ business,
479
+ navigation = defaultNavigation,
480
+ sticky = true,
481
+ transparent = false,
482
+ showPhone = true,
483
+ className = ""
484
+ }) {
485
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
486
+ return /* @__PURE__ */ jsx2(
487
+ "header",
488
+ {
489
+ className: `
490
+ ${sticky ? "sticky top-0 z-50" : ""}
491
+ ${transparent ? "bg-transparent" : "bg-white shadow-sm"}
492
+ ${className}
493
+ `,
494
+ children: /* @__PURE__ */ jsxs2("nav", { className: "container mx-auto px-4", children: [
495
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between h-16", children: [
496
+ /* @__PURE__ */ jsx2("a", { href: "/", className: "flex items-center", children: business.logoUrl ? /* @__PURE__ */ jsx2(
497
+ "img",
498
+ {
499
+ src: business.logoUrl,
500
+ alt: business.name,
501
+ className: "h-10 w-auto"
502
+ }
503
+ ) : /* @__PURE__ */ jsx2("span", { className: "text-xl font-bold text-gray-900", children: business.name }) }),
504
+ /* @__PURE__ */ jsxs2("div", { className: "hidden md:flex items-center space-x-8", children: [
505
+ navigation.map((item) => /* @__PURE__ */ jsx2(
506
+ "a",
507
+ {
508
+ href: item.href,
509
+ className: "text-gray-600 hover:text-primary-600 font-medium transition-colors",
510
+ children: item.label
511
+ },
512
+ item.href
513
+ )),
514
+ showPhone && business.phone && /* @__PURE__ */ jsxs2(
515
+ "a",
516
+ {
517
+ href: `tel:${business.phone.replace(/\D/g, "")}`,
518
+ className: "inline-flex items-center px-4 py-2 bg-primary-600 text-white rounded-lg hover:bg-primary-700 transition-colors",
519
+ children: [
520
+ /* @__PURE__ */ jsx2(PhoneIcon, { size: 18, className: "mr-2" }),
521
+ business.phone
522
+ ]
523
+ }
524
+ )
525
+ ] }),
526
+ /* @__PURE__ */ jsx2(
527
+ "button",
528
+ {
529
+ className: "md:hidden p-2 rounded-lg hover:bg-gray-100",
530
+ onClick: () => setMobileMenuOpen(!mobileMenuOpen),
531
+ "aria-label": mobileMenuOpen ? "Close menu" : "Open menu",
532
+ children: mobileMenuOpen ? /* @__PURE__ */ jsx2(XIcon, { size: 24 }) : /* @__PURE__ */ jsx2(MenuIcon, { size: 24 })
533
+ }
534
+ )
535
+ ] }),
536
+ mobileMenuOpen && /* @__PURE__ */ jsxs2("div", { className: "md:hidden py-4 border-t", children: [
537
+ navigation.map((item) => /* @__PURE__ */ jsx2(
538
+ "a",
539
+ {
540
+ href: item.href,
541
+ className: "block py-2 text-gray-600 hover:text-primary-600 font-medium",
542
+ onClick: () => setMobileMenuOpen(false),
543
+ children: item.label
544
+ },
545
+ item.href
546
+ )),
547
+ showPhone && business.phone && /* @__PURE__ */ jsxs2(
548
+ "a",
549
+ {
550
+ href: `tel:${business.phone.replace(/\D/g, "")}`,
551
+ className: "flex items-center py-2 text-primary-600 font-medium",
552
+ children: [
553
+ /* @__PURE__ */ jsx2(PhoneIcon, { size: 18, className: "mr-2" }),
554
+ business.phone
555
+ ]
556
+ }
557
+ )
558
+ ] })
559
+ ] })
560
+ }
561
+ );
562
+ }
563
+
564
+ // src/components/layout/Footer.tsx
565
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
566
+ var defaultQuickLinks = [
567
+ { label: "Home", href: "/" },
568
+ { label: "Services", href: "/services" },
569
+ { label: "About", href: "/about" },
570
+ { label: "Contact", href: "/contact" },
571
+ { label: "Privacy Policy", href: "/privacy" }
572
+ ];
573
+ var dayNames = {
574
+ monday: "Mon",
575
+ tuesday: "Tue",
576
+ wednesday: "Wed",
577
+ thursday: "Thu",
578
+ friday: "Fri",
579
+ saturday: "Sat",
580
+ sunday: "Sun"
581
+ };
582
+ function Footer({
583
+ business,
584
+ hours = [],
585
+ quickLinks = defaultQuickLinks,
586
+ showHours = true,
587
+ showSocial = true,
588
+ variant = "columns",
589
+ className = ""
590
+ }) {
591
+ const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
592
+ const socialLinks = [
593
+ { url: business.socialYelp, icon: YelpIcon, label: "Yelp" },
594
+ { url: business.socialInstagram, icon: InstagramIcon, label: "Instagram" },
595
+ { url: business.socialFacebook, icon: FacebookIcon, label: "Facebook" }
596
+ ].filter((link) => link.url);
597
+ if (variant === "simple") {
598
+ return /* @__PURE__ */ jsx3("footer", { className: `bg-gray-900 text-white py-8 ${className}`, children: /* @__PURE__ */ jsxs3("div", { className: "container mx-auto px-4 text-center", children: [
599
+ /* @__PURE__ */ jsx3("p", { className: "text-lg font-semibold mb-2", children: business.name }),
600
+ business.phone && /* @__PURE__ */ jsx3("p", { className: "text-gray-400", children: business.phone }),
601
+ /* @__PURE__ */ jsxs3("p", { className: "text-gray-500 text-sm mt-4", children: [
602
+ "\xA9 ",
603
+ currentYear,
604
+ " ",
605
+ business.name,
606
+ ". All rights reserved."
607
+ ] })
608
+ ] }) });
609
+ }
610
+ if (variant === "centered") {
611
+ return /* @__PURE__ */ jsx3("footer", { className: `bg-gray-900 text-white py-12 ${className}`, children: /* @__PURE__ */ jsxs3("div", { className: "container mx-auto px-4 text-center", children: [
612
+ /* @__PURE__ */ jsx3("p", { className: "text-2xl font-bold mb-4", children: business.name }),
613
+ business.tagline && /* @__PURE__ */ jsx3("p", { className: "text-gray-400 mb-6", children: business.tagline }),
614
+ /* @__PURE__ */ jsx3("div", { className: "flex flex-wrap justify-center gap-6 mb-8", children: quickLinks.map((link) => /* @__PURE__ */ jsx3(
615
+ "a",
616
+ {
617
+ href: link.href,
618
+ className: "text-gray-400 hover:text-white transition-colors",
619
+ children: link.label
620
+ },
621
+ link.href
622
+ )) }),
623
+ showSocial && socialLinks.length > 0 && /* @__PURE__ */ jsx3("div", { className: "flex justify-center gap-4 mb-8", children: socialLinks.map((link) => /* @__PURE__ */ jsx3(
624
+ "a",
625
+ {
626
+ href: link.url,
627
+ target: "_blank",
628
+ rel: "noopener noreferrer",
629
+ className: "p-2 bg-gray-800 rounded-full hover:bg-gray-700 transition-colors",
630
+ "aria-label": link.label,
631
+ children: /* @__PURE__ */ jsx3(link.icon, { size: 20 })
632
+ },
633
+ link.label
634
+ )) }),
635
+ /* @__PURE__ */ jsxs3("p", { className: "text-gray-500 text-sm", children: [
636
+ "\xA9 ",
637
+ currentYear,
638
+ " ",
639
+ business.name,
640
+ ". All rights reserved."
641
+ ] })
642
+ ] }) });
643
+ }
644
+ return /* @__PURE__ */ jsx3("footer", { className: `bg-gray-900 text-white py-12 ${className}`, children: /* @__PURE__ */ jsxs3("div", { className: "container mx-auto px-4", children: [
645
+ /* @__PURE__ */ jsxs3("div", { className: "grid md:grid-cols-3 gap-8", children: [
646
+ /* @__PURE__ */ jsxs3("div", { children: [
647
+ /* @__PURE__ */ jsx3("h3", { className: "text-xl font-bold mb-4", children: business.name }),
648
+ business.addressLine1 && /* @__PURE__ */ jsxs3("div", { className: "flex items-start text-gray-400 mb-3", children: [
649
+ /* @__PURE__ */ jsx3(MapPinIcon, { size: 18, className: "mr-2 mt-1 flex-shrink-0" }),
650
+ /* @__PURE__ */ jsxs3("div", { children: [
651
+ /* @__PURE__ */ jsx3("p", { children: business.addressLine1 }),
652
+ business.addressLine2 && /* @__PURE__ */ jsx3("p", { children: business.addressLine2 }),
653
+ /* @__PURE__ */ jsxs3("p", { children: [
654
+ business.city,
655
+ ", ",
656
+ business.state,
657
+ " ",
658
+ business.zip
659
+ ] })
660
+ ] })
661
+ ] }),
662
+ business.phone && /* @__PURE__ */ jsxs3(
663
+ "a",
664
+ {
665
+ href: `tel:${business.phone.replace(/\D/g, "")}`,
666
+ className: "flex items-center text-gray-400 hover:text-white mb-3",
667
+ children: [
668
+ /* @__PURE__ */ jsx3(PhoneIcon, { size: 18, className: "mr-2" }),
669
+ business.phone
670
+ ]
671
+ }
672
+ ),
673
+ business.email && /* @__PURE__ */ jsxs3(
674
+ "a",
675
+ {
676
+ href: `mailto:${business.email}`,
677
+ className: "flex items-center text-gray-400 hover:text-white",
678
+ children: [
679
+ /* @__PURE__ */ jsx3(MailIcon, { size: 18, className: "mr-2" }),
680
+ business.email
681
+ ]
682
+ }
683
+ )
684
+ ] }),
685
+ /* @__PURE__ */ jsxs3("div", { children: [
686
+ /* @__PURE__ */ jsx3("h3", { className: "text-lg font-semibold mb-4", children: "Quick Links" }),
687
+ /* @__PURE__ */ jsx3("ul", { className: "space-y-2", children: quickLinks.map((link) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsx3(
688
+ "a",
689
+ {
690
+ href: link.href,
691
+ className: "text-gray-400 hover:text-white transition-colors",
692
+ children: link.label
693
+ }
694
+ ) }, link.href)) }),
695
+ showSocial && socialLinks.length > 0 && /* @__PURE__ */ jsx3("div", { className: "flex gap-3 mt-6", children: socialLinks.map((link) => /* @__PURE__ */ jsx3(
696
+ "a",
697
+ {
698
+ href: link.url,
699
+ target: "_blank",
700
+ rel: "noopener noreferrer",
701
+ className: "p-2 bg-gray-800 rounded-full hover:bg-gray-700 transition-colors",
702
+ "aria-label": link.label,
703
+ children: /* @__PURE__ */ jsx3(link.icon, { size: 20 })
704
+ },
705
+ link.label
706
+ )) })
707
+ ] }),
708
+ showHours && hours.length > 0 && /* @__PURE__ */ jsxs3("div", { children: [
709
+ /* @__PURE__ */ jsxs3("h3", { className: "text-lg font-semibold mb-4 flex items-center", children: [
710
+ /* @__PURE__ */ jsx3(ClockIcon, { size: 18, className: "mr-2" }),
711
+ "Hours"
712
+ ] }),
713
+ /* @__PURE__ */ jsx3("ul", { className: "space-y-1 text-gray-400", children: hours.map((entry) => /* @__PURE__ */ jsxs3("li", { className: "flex justify-between", children: [
714
+ /* @__PURE__ */ jsx3("span", { children: dayNames[entry.day] }),
715
+ /* @__PURE__ */ jsx3("span", { children: entry.closed ? "Closed" : `${entry.open} - ${entry.close}` })
716
+ ] }, entry.day)) })
717
+ ] })
718
+ ] }),
719
+ /* @__PURE__ */ jsx3("div", { className: "mt-12 pt-8 border-t border-gray-800 text-center text-gray-500 text-sm", children: /* @__PURE__ */ jsxs3("p", { children: [
720
+ "\xA9 ",
721
+ currentYear,
722
+ " ",
723
+ business.name,
724
+ ". All rights reserved."
725
+ ] }) })
726
+ ] }) });
727
+ }
728
+
729
+ // src/components/sections/Hero.tsx
730
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
731
+ function Hero({
732
+ business,
733
+ variant = "centered",
734
+ showOpenStatus = true,
735
+ isOpen,
736
+ todayHours,
737
+ backgroundImage,
738
+ overlay = true,
739
+ className = ""
740
+ }) {
741
+ const bgStyle = backgroundImage ? { backgroundImage: `url(${backgroundImage})` } : void 0;
742
+ const handleCallClick = () => {
743
+ if (business.phone) {
744
+ window.location.href = `tel:${business.phone.replace(/\D/g, "")}`;
745
+ }
746
+ };
747
+ const handleDirectionsClick = () => {
748
+ if (business.googleMapsUrl) {
749
+ window.open(business.googleMapsUrl, "_blank");
750
+ } else {
751
+ const address = [
752
+ business.addressLine1,
753
+ business.city,
754
+ business.state,
755
+ business.zip
756
+ ].filter(Boolean).join(", ");
757
+ window.open(`https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(address)}`, "_blank");
758
+ }
759
+ };
760
+ const handlePrimaryClick = () => {
761
+ if (business.primaryCtaUrl) {
762
+ if (business.primaryCtaUrl.startsWith("http")) {
763
+ window.open(business.primaryCtaUrl, "_blank");
764
+ } else if (business.primaryCtaUrl.startsWith("mailto:")) {
765
+ window.location.href = business.primaryCtaUrl;
766
+ } else {
767
+ window.location.href = business.primaryCtaUrl;
768
+ }
769
+ } else if (business.bookingUrl) {
770
+ window.open(business.bookingUrl, "_blank");
771
+ } else if (business.email) {
772
+ window.location.href = `mailto:${business.email}`;
773
+ }
774
+ };
775
+ return /* @__PURE__ */ jsxs4(
776
+ "section",
777
+ {
778
+ className: `
779
+ relative min-h-[500px] flex items-center
780
+ ${backgroundImage ? "bg-cover bg-center" : "bg-gradient-to-br from-primary-600 to-primary-800"}
781
+ ${className}
782
+ `,
783
+ style: bgStyle,
784
+ children: [
785
+ overlay && backgroundImage && /* @__PURE__ */ jsx4("div", { className: "absolute inset-0 bg-black/50" }),
786
+ /* @__PURE__ */ jsx4("div", { className: "relative z-10 container mx-auto px-4 py-16", children: /* @__PURE__ */ jsxs4(
787
+ "div",
788
+ {
789
+ className: `
790
+ ${variant === "centered" ? "text-center max-w-3xl mx-auto" : ""}
791
+ ${variant === "left" ? "max-w-2xl" : ""}
792
+ ${variant === "split" ? "grid md:grid-cols-2 gap-8 items-center" : ""}
793
+ `,
794
+ children: [
795
+ /* @__PURE__ */ jsxs4("div", { children: [
796
+ showOpenStatus && isOpen !== void 0 && /* @__PURE__ */ jsx4("div", { className: "mb-4", children: /* @__PURE__ */ jsxs4(
797
+ "span",
798
+ {
799
+ className: `
800
+ inline-flex items-center px-3 py-1 rounded-full text-sm font-medium
801
+ ${isOpen ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800"}
802
+ `,
803
+ children: [
804
+ /* @__PURE__ */ jsx4(
805
+ "span",
806
+ {
807
+ className: `w-2 h-2 rounded-full mr-2 ${isOpen ? "bg-green-500" : "bg-red-500"}`
808
+ }
809
+ ),
810
+ isOpen ? "Open Now" : "Closed",
811
+ todayHours && /* @__PURE__ */ jsxs4("span", { className: "ml-2 opacity-75", children: [
812
+ "\xB7 ",
813
+ todayHours
814
+ ] })
815
+ ]
816
+ }
817
+ ) }),
818
+ /* @__PURE__ */ jsx4("h1", { className: "text-4xl md:text-5xl lg:text-6xl font-bold text-white mb-4", children: business.name }),
819
+ business.tagline && /* @__PURE__ */ jsx4("p", { className: "text-xl md:text-2xl text-white/90 mb-6", children: business.tagline }),
820
+ business.aboutShort && /* @__PURE__ */ jsx4("p", { className: "text-lg text-white/80 mb-8 max-w-xl", children: business.aboutShort }),
821
+ /* @__PURE__ */ jsx4("div", { className: "flex flex-wrap justify-center gap-4 mb-8", children: ["Quality Work", "Fair Prices", "Fast Service"].map((signal) => /* @__PURE__ */ jsxs4("div", { className: "flex items-center text-white/90", children: [
822
+ /* @__PURE__ */ jsx4("svg", { className: "w-5 h-5 text-accent-400 mr-2", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx4(
823
+ "path",
824
+ {
825
+ fillRule: "evenodd",
826
+ d: "M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z",
827
+ clipRule: "evenodd"
828
+ }
829
+ ) }),
830
+ /* @__PURE__ */ jsx4("span", { className: "text-sm font-medium", children: signal })
831
+ ] }, signal)) }),
832
+ /* @__PURE__ */ jsxs4("div", { className: "flex flex-col sm:flex-row gap-4 justify-center", children: [
833
+ business.phone && /* @__PURE__ */ jsxs4(
834
+ "button",
835
+ {
836
+ onClick: handleCallClick,
837
+ className: "inline-flex items-center justify-center px-6 py-3 bg-white text-primary-700 font-semibold rounded-lg hover:bg-gray-100 transition-colors",
838
+ children: [
839
+ /* @__PURE__ */ jsx4(PhoneIcon, { size: 20, className: "mr-2" }),
840
+ "Call Now"
841
+ ]
842
+ }
843
+ ),
844
+ (business.addressLine1 || business.googleMapsUrl) && /* @__PURE__ */ jsxs4(
845
+ "button",
846
+ {
847
+ onClick: handleDirectionsClick,
848
+ className: "inline-flex items-center justify-center px-6 py-3 border-2 border-white text-white font-semibold rounded-lg hover:bg-white/10 transition-colors",
849
+ children: [
850
+ /* @__PURE__ */ jsx4(MapPinIcon, { size: 20, className: "mr-2" }),
851
+ "Get Directions"
852
+ ]
853
+ }
854
+ ),
855
+ (business.primaryCtaUrl || business.bookingUrl || business.email) && /* @__PURE__ */ jsx4(
856
+ "button",
857
+ {
858
+ onClick: handlePrimaryClick,
859
+ className: "inline-flex items-center justify-center px-6 py-3 bg-accent-500 text-white font-semibold rounded-lg hover:bg-accent-600 transition-colors",
860
+ children: business.primaryCtaText || "Contact Us"
861
+ }
862
+ )
863
+ ] })
864
+ ] }),
865
+ variant === "split" && /* @__PURE__ */ jsx4("div", { className: "hidden md:block" })
866
+ ]
867
+ }
868
+ ) })
869
+ ]
870
+ }
871
+ );
872
+ }
873
+
874
+ // src/components/sections/Services.tsx
875
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
876
+ function Services({
877
+ services,
878
+ title = "Our Services",
879
+ subtitle,
880
+ columns = 3,
881
+ showPrices = true,
882
+ showIcons = true,
883
+ variant = "cards",
884
+ limit,
885
+ className = ""
886
+ }) {
887
+ const displayedServices = limit ? services.slice(0, limit) : services;
888
+ const gridCols = {
889
+ 2: "md:grid-cols-2",
890
+ 3: "md:grid-cols-2 lg:grid-cols-3",
891
+ 4: "md:grid-cols-2 lg:grid-cols-4"
892
+ };
893
+ if (variant === "list") {
894
+ return /* @__PURE__ */ jsx5("section", { className: `py-16 ${className}`, children: /* @__PURE__ */ jsxs5("div", { className: "container mx-auto px-4", children: [
895
+ /* @__PURE__ */ jsx5(SectionHeader, { title, subtitle }),
896
+ /* @__PURE__ */ jsx5("div", { className: "max-w-3xl mx-auto divide-y divide-gray-200", children: displayedServices.map((service) => /* @__PURE__ */ jsx5(
897
+ ServiceListItem,
898
+ {
899
+ service,
900
+ showPrice: showPrices,
901
+ showIcon: showIcons
902
+ },
903
+ service.id || service.title
904
+ )) })
905
+ ] }) });
906
+ }
907
+ if (variant === "minimal") {
908
+ return /* @__PURE__ */ jsx5("section", { className: `py-16 ${className}`, children: /* @__PURE__ */ jsxs5("div", { className: "container mx-auto px-4", children: [
909
+ /* @__PURE__ */ jsx5(SectionHeader, { title, subtitle }),
910
+ /* @__PURE__ */ jsx5("div", { className: `grid gap-6 ${gridCols[columns]}`, children: displayedServices.map((service) => /* @__PURE__ */ jsx5(
911
+ ServiceMinimalCard,
912
+ {
913
+ service,
914
+ showPrice: showPrices
915
+ },
916
+ service.id || service.title
917
+ )) })
918
+ ] }) });
919
+ }
920
+ return /* @__PURE__ */ jsx5("section", { className: `py-16 bg-gray-50 ${className}`, children: /* @__PURE__ */ jsxs5("div", { className: "container mx-auto px-4", children: [
921
+ /* @__PURE__ */ jsx5(SectionHeader, { title, subtitle }),
922
+ /* @__PURE__ */ jsx5("div", { className: `grid gap-6 ${gridCols[columns]}`, children: displayedServices.map((service) => /* @__PURE__ */ jsx5(
923
+ ServiceCard,
924
+ {
925
+ service,
926
+ showPrice: showPrices,
927
+ showIcon: showIcons
928
+ },
929
+ service.id || service.title
930
+ )) })
931
+ ] }) });
932
+ }
933
+ function SectionHeader({ title, subtitle }) {
934
+ return /* @__PURE__ */ jsxs5("div", { className: "text-center mb-12", children: [
935
+ /* @__PURE__ */ jsx5("h2", { className: "text-3xl md:text-4xl font-bold text-gray-900 mb-4", children: title }),
936
+ subtitle && /* @__PURE__ */ jsx5("p", { className: "text-lg text-gray-600 max-w-2xl mx-auto", children: subtitle })
937
+ ] });
938
+ }
939
+ function ServiceCard({
940
+ service,
941
+ showPrice,
942
+ showIcon
943
+ }) {
944
+ return /* @__PURE__ */ jsxs5("div", { className: "bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow", children: [
945
+ showIcon && service.icon && /* @__PURE__ */ jsx5("div", { className: "w-12 h-12 bg-primary-100 rounded-lg flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx5(Icon, { name: service.icon, size: 24, className: "text-primary-600" }) }),
946
+ /* @__PURE__ */ jsx5("h3", { className: "text-xl font-semibold text-gray-900 mb-2", children: service.title }),
947
+ service.description && /* @__PURE__ */ jsx5("p", { className: "text-gray-600 mb-4", children: service.description }),
948
+ showPrice && service.priceNote && /* @__PURE__ */ jsx5("p", { className: "text-primary-600 font-medium", children: service.priceNote }),
949
+ showPrice && service.price && !service.priceNote && /* @__PURE__ */ jsxs5("p", { className: "text-primary-600 font-medium", children: [
950
+ "$",
951
+ service.price.toFixed(2)
952
+ ] })
953
+ ] });
954
+ }
955
+ function ServiceListItem({
956
+ service,
957
+ showPrice,
958
+ showIcon
959
+ }) {
960
+ return /* @__PURE__ */ jsxs5("div", { className: "py-4 flex items-start justify-between", children: [
961
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-start", children: [
962
+ showIcon && service.icon && /* @__PURE__ */ jsx5("div", { className: "w-10 h-10 bg-primary-100 rounded-lg flex items-center justify-center mr-4 flex-shrink-0", children: /* @__PURE__ */ jsx5(Icon, { name: service.icon, size: 20, className: "text-primary-600" }) }),
963
+ /* @__PURE__ */ jsxs5("div", { children: [
964
+ /* @__PURE__ */ jsx5("h3", { className: "text-lg font-semibold text-gray-900", children: service.title }),
965
+ service.description && /* @__PURE__ */ jsx5("p", { className: "text-gray-600 text-sm mt-1", children: service.description })
966
+ ] })
967
+ ] }),
968
+ showPrice && (service.priceNote || service.price) && /* @__PURE__ */ jsx5("div", { className: "text-right ml-4 flex-shrink-0", children: /* @__PURE__ */ jsx5("p", { className: "text-primary-600 font-medium", children: service.priceNote || `$${service.price?.toFixed(2)}` }) })
969
+ ] });
970
+ }
971
+ function ServiceMinimalCard({
972
+ service,
973
+ showPrice
974
+ }) {
975
+ return /* @__PURE__ */ jsxs5("div", { className: "p-4 border border-gray-200 rounded-lg hover:border-primary-300 transition-colors", children: [
976
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between", children: [
977
+ /* @__PURE__ */ jsx5("h3", { className: "font-semibold text-gray-900", children: service.title }),
978
+ showPrice && (service.priceNote || service.price) && /* @__PURE__ */ jsx5("span", { className: "text-primary-600 text-sm font-medium", children: service.priceNote || `$${service.price?.toFixed(2)}` })
979
+ ] }),
980
+ service.description && /* @__PURE__ */ jsx5("p", { className: "text-gray-600 text-sm mt-2", children: service.description })
981
+ ] });
982
+ }
983
+
984
+ // src/components/sections/Testimonials.tsx
985
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
986
+ function Testimonials({
987
+ testimonials,
988
+ title = "What Our Customers Say",
989
+ subtitle,
990
+ columns = 3,
991
+ showRatings = true,
992
+ variant = "cards",
993
+ limit,
994
+ className = ""
995
+ }) {
996
+ const displayedTestimonials = limit ? testimonials.slice(0, limit) : testimonials;
997
+ const gridCols = {
998
+ 1: "max-w-2xl mx-auto",
999
+ 2: "md:grid-cols-2 max-w-4xl mx-auto",
1000
+ 3: "md:grid-cols-2 lg:grid-cols-3"
1001
+ };
1002
+ return /* @__PURE__ */ jsx6("section", { className: `py-16 ${className}`, children: /* @__PURE__ */ jsxs6("div", { className: "container mx-auto px-4", children: [
1003
+ /* @__PURE__ */ jsxs6("div", { className: "text-center mb-12", children: [
1004
+ /* @__PURE__ */ jsx6("h2", { className: "text-3xl md:text-4xl font-bold text-gray-900 mb-4", children: title }),
1005
+ subtitle && /* @__PURE__ */ jsx6("p", { className: "text-lg text-gray-600 max-w-2xl mx-auto", children: subtitle })
1006
+ ] }),
1007
+ /* @__PURE__ */ jsx6("div", { className: `grid gap-6 ${gridCols[columns]}`, children: displayedTestimonials.map((testimonial) => /* @__PURE__ */ jsx6(
1008
+ TestimonialCard,
1009
+ {
1010
+ testimonial,
1011
+ showRating: showRatings,
1012
+ variant
1013
+ },
1014
+ testimonial.id || testimonial.name
1015
+ )) })
1016
+ ] }) });
1017
+ }
1018
+ function TestimonialCard({
1019
+ testimonial,
1020
+ showRating,
1021
+ variant
1022
+ }) {
1023
+ if (variant === "quotes") {
1024
+ return /* @__PURE__ */ jsxs6("div", { className: "text-center", children: [
1025
+ /* @__PURE__ */ jsx6(QuoteIcon, { className: "w-10 h-10 text-primary-200 mx-auto mb-4" }),
1026
+ /* @__PURE__ */ jsxs6("blockquote", { className: "text-lg text-gray-700 italic mb-4", children: [
1027
+ '"',
1028
+ testimonial.quote,
1029
+ '"'
1030
+ ] }),
1031
+ showRating && testimonial.rating && /* @__PURE__ */ jsx6(StarRating, { rating: testimonial.rating, className: "justify-center mb-2" }),
1032
+ /* @__PURE__ */ jsx6("div", { className: "font-semibold text-gray-900", children: testimonial.name }),
1033
+ testimonial.context && /* @__PURE__ */ jsx6("div", { className: "text-sm text-gray-500", children: testimonial.context })
1034
+ ] });
1035
+ }
1036
+ if (variant === "minimal") {
1037
+ return /* @__PURE__ */ jsxs6("div", { className: "border-l-4 border-primary-500 pl-4", children: [
1038
+ /* @__PURE__ */ jsxs6("blockquote", { className: "text-gray-700 mb-2", children: [
1039
+ '"',
1040
+ testimonial.quote,
1041
+ '"'
1042
+ ] }),
1043
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
1044
+ /* @__PURE__ */ jsx6("span", { className: "font-semibold text-gray-900", children: testimonial.name }),
1045
+ showRating && testimonial.rating && /* @__PURE__ */ jsx6(StarRating, { rating: testimonial.rating, size: 14 })
1046
+ ] })
1047
+ ] });
1048
+ }
1049
+ return /* @__PURE__ */ jsxs6("div", { className: "bg-white rounded-lg shadow p-6", children: [
1050
+ showRating && testimonial.rating && /* @__PURE__ */ jsx6(StarRating, { rating: testimonial.rating, className: "mb-3" }),
1051
+ /* @__PURE__ */ jsxs6("blockquote", { className: "text-gray-700 mb-4", children: [
1052
+ '"',
1053
+ testimonial.quote,
1054
+ '"'
1055
+ ] }),
1056
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center", children: [
1057
+ testimonial.imageUrl && /* @__PURE__ */ jsx6(
1058
+ "img",
1059
+ {
1060
+ src: testimonial.imageUrl,
1061
+ alt: testimonial.name,
1062
+ className: "w-10 h-10 rounded-full mr-3 object-cover"
1063
+ }
1064
+ ),
1065
+ /* @__PURE__ */ jsxs6("div", { children: [
1066
+ /* @__PURE__ */ jsx6("div", { className: "font-semibold text-gray-900", children: testimonial.name }),
1067
+ testimonial.context && /* @__PURE__ */ jsx6("div", { className: "text-sm text-gray-500", children: testimonial.context }),
1068
+ testimonial.source && /* @__PURE__ */ jsxs6("div", { className: "text-xs text-gray-400", children: [
1069
+ "via ",
1070
+ testimonial.source
1071
+ ] })
1072
+ ] })
1073
+ ] })
1074
+ ] });
1075
+ }
1076
+ function StarRating({
1077
+ rating,
1078
+ size = 18,
1079
+ className = ""
1080
+ }) {
1081
+ return /* @__PURE__ */ jsx6("div", { className: `flex ${className}`, "aria-label": `${rating} out of 5 stars`, children: [1, 2, 3, 4, 5].map((star) => /* @__PURE__ */ jsx6(
1082
+ StarIcon,
1083
+ {
1084
+ size,
1085
+ filled: star <= rating,
1086
+ className: star <= rating ? "text-yellow-400" : "text-gray-300"
1087
+ },
1088
+ star
1089
+ )) });
1090
+ }
1091
+ function QuoteIcon({ className }) {
1092
+ return /* @__PURE__ */ jsx6("svg", { className, fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx6("path", { d: "M14.017 21v-7.391c0-5.704 3.731-9.57 8.983-10.609l.995 2.151c-2.432.917-3.995 3.638-3.995 5.849h4v10h-9.983zm-14.017 0v-7.391c0-5.704 3.748-9.57 9-10.609l.996 2.151c-2.433.917-3.996 3.638-3.996 5.849h3.983v10h-9.983z" }) });
1093
+ }
1094
+
1095
+ // src/components/sections/FAQ.tsx
1096
+ import { useState as useState2 } from "react";
1097
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1098
+ function FAQ({
1099
+ items,
1100
+ title = "Frequently Asked Questions",
1101
+ subtitle,
1102
+ variant = "accordion",
1103
+ defaultOpen = 0,
1104
+ allowMultiple = false,
1105
+ className = ""
1106
+ }) {
1107
+ const initialOpen = Array.isArray(defaultOpen) ? defaultOpen : [defaultOpen];
1108
+ const [openItems, setOpenItems] = useState2(initialOpen);
1109
+ const toggleItem = (index) => {
1110
+ if (allowMultiple) {
1111
+ setOpenItems(
1112
+ (prev) => prev.includes(index) ? prev.filter((i) => i !== index) : [...prev, index]
1113
+ );
1114
+ } else {
1115
+ setOpenItems(
1116
+ (prev) => prev.includes(index) ? [] : [index]
1117
+ );
1118
+ }
1119
+ };
1120
+ if (variant === "cards") {
1121
+ return /* @__PURE__ */ jsx7("section", { className: `py-16 ${className}`, children: /* @__PURE__ */ jsxs7("div", { className: "container mx-auto px-4", children: [
1122
+ /* @__PURE__ */ jsx7(SectionHeader2, { title, subtitle }),
1123
+ /* @__PURE__ */ jsx7("div", { className: "grid md:grid-cols-2 gap-6 max-w-4xl mx-auto", children: items.map((item) => /* @__PURE__ */ jsx7(FAQCard, { item }, item.id || item.question)) })
1124
+ ] }) });
1125
+ }
1126
+ if (variant === "simple") {
1127
+ return /* @__PURE__ */ jsx7("section", { className: `py-16 ${className}`, children: /* @__PURE__ */ jsxs7("div", { className: "container mx-auto px-4", children: [
1128
+ /* @__PURE__ */ jsx7(SectionHeader2, { title, subtitle }),
1129
+ /* @__PURE__ */ jsx7("div", { className: "max-w-3xl mx-auto space-y-8", children: items.map((item) => /* @__PURE__ */ jsx7(FAQSimple, { item }, item.id || item.question)) })
1130
+ ] }) });
1131
+ }
1132
+ return /* @__PURE__ */ jsx7("section", { className: `py-16 bg-gray-50 ${className}`, children: /* @__PURE__ */ jsxs7("div", { className: "container mx-auto px-4", children: [
1133
+ /* @__PURE__ */ jsx7(SectionHeader2, { title, subtitle }),
1134
+ /* @__PURE__ */ jsx7("div", { className: "max-w-3xl mx-auto", children: items.map((item, index) => /* @__PURE__ */ jsx7(
1135
+ FAQAccordionItem,
1136
+ {
1137
+ item,
1138
+ isOpen: openItems.includes(index),
1139
+ onToggle: () => toggleItem(index)
1140
+ },
1141
+ item.id || item.question
1142
+ )) })
1143
+ ] }) });
1144
+ }
1145
+ function SectionHeader2({ title, subtitle }) {
1146
+ return /* @__PURE__ */ jsxs7("div", { className: "text-center mb-12", children: [
1147
+ /* @__PURE__ */ jsx7("h2", { className: "text-3xl md:text-4xl font-bold text-gray-900 mb-4", children: title }),
1148
+ subtitle && /* @__PURE__ */ jsx7("p", { className: "text-lg text-gray-600 max-w-2xl mx-auto", children: subtitle })
1149
+ ] });
1150
+ }
1151
+ function FAQAccordionItem({
1152
+ item,
1153
+ isOpen,
1154
+ onToggle
1155
+ }) {
1156
+ return /* @__PURE__ */ jsxs7("div", { className: "border-b border-gray-200 last:border-b-0", children: [
1157
+ /* @__PURE__ */ jsxs7(
1158
+ "button",
1159
+ {
1160
+ className: "w-full py-4 flex items-center justify-between text-left focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2 rounded",
1161
+ onClick: onToggle,
1162
+ "aria-expanded": isOpen,
1163
+ children: [
1164
+ /* @__PURE__ */ jsx7("span", { className: "text-lg font-medium text-gray-900 pr-4", children: item.question }),
1165
+ /* @__PURE__ */ jsx7(
1166
+ ChevronDownIcon,
1167
+ {
1168
+ size: 20,
1169
+ className: `flex-shrink-0 text-gray-500 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`
1170
+ }
1171
+ )
1172
+ ]
1173
+ }
1174
+ ),
1175
+ /* @__PURE__ */ jsx7(
1176
+ "div",
1177
+ {
1178
+ className: `overflow-hidden transition-all duration-200 ${isOpen ? "max-h-96 pb-4" : "max-h-0"}`,
1179
+ children: /* @__PURE__ */ jsx7("p", { className: "text-gray-600", children: item.answer })
1180
+ }
1181
+ )
1182
+ ] });
1183
+ }
1184
+ function FAQCard({ item }) {
1185
+ return /* @__PURE__ */ jsxs7("div", { className: "bg-white rounded-lg shadow p-6", children: [
1186
+ /* @__PURE__ */ jsx7("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: item.question }),
1187
+ /* @__PURE__ */ jsx7("p", { className: "text-gray-600", children: item.answer })
1188
+ ] });
1189
+ }
1190
+ function FAQSimple({ item }) {
1191
+ return /* @__PURE__ */ jsxs7("div", { children: [
1192
+ /* @__PURE__ */ jsx7("h3", { className: "text-lg font-semibold text-gray-900 mb-2", children: item.question }),
1193
+ /* @__PURE__ */ jsx7("p", { className: "text-gray-600", children: item.answer })
1194
+ ] });
1195
+ }
1196
+
1197
+ // src/components/sections/Hours.tsx
1198
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1199
+ var dayOrder = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"];
1200
+ var dayNames2 = {
1201
+ monday: "Monday",
1202
+ tuesday: "Tuesday",
1203
+ wednesday: "Wednesday",
1204
+ thursday: "Thursday",
1205
+ friday: "Friday",
1206
+ saturday: "Saturday",
1207
+ sunday: "Sunday"
1208
+ };
1209
+ var dayAbbrev = {
1210
+ monday: "Mon",
1211
+ tuesday: "Tue",
1212
+ wednesday: "Wed",
1213
+ thursday: "Thu",
1214
+ friday: "Fri",
1215
+ saturday: "Sat",
1216
+ sunday: "Sun"
1217
+ };
1218
+ function getTodayDay(timezone) {
1219
+ const now = timezone ? new Date((/* @__PURE__ */ new Date()).toLocaleString("en-US", { timeZone: timezone })) : /* @__PURE__ */ new Date();
1220
+ const jsDay = now.getDay();
1221
+ return dayOrder[(jsDay + 6) % 7];
1222
+ }
1223
+ function Hours({
1224
+ hours,
1225
+ title = "Hours",
1226
+ highlightToday = true,
1227
+ variant = "card",
1228
+ timezone,
1229
+ className = ""
1230
+ }) {
1231
+ const todayDay = getTodayDay(timezone);
1232
+ const sortedHours = [...hours].sort(
1233
+ (a, b) => dayOrder.indexOf(a.day) - dayOrder.indexOf(b.day)
1234
+ );
1235
+ if (variant === "inline") {
1236
+ return /* @__PURE__ */ jsx8("div", { className: `flex flex-wrap gap-4 ${className}`, children: sortedHours.map((entry) => /* @__PURE__ */ jsx8(
1237
+ HoursInlineItem,
1238
+ {
1239
+ entry,
1240
+ isToday: highlightToday && entry.day === todayDay
1241
+ },
1242
+ entry.day
1243
+ )) });
1244
+ }
1245
+ if (variant === "minimal") {
1246
+ return /* @__PURE__ */ jsx8("div", { className: `space-y-1 ${className}`, children: sortedHours.map((entry) => /* @__PURE__ */ jsx8(
1247
+ HoursMinimalItem,
1248
+ {
1249
+ entry,
1250
+ isToday: highlightToday && entry.day === todayDay
1251
+ },
1252
+ entry.day
1253
+ )) });
1254
+ }
1255
+ return /* @__PURE__ */ jsxs8("div", { className: `bg-white rounded-lg shadow p-6 ${className}`, children: [
1256
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center mb-4", children: [
1257
+ /* @__PURE__ */ jsx8(ClockIcon, { size: 24, className: "text-primary-600 mr-2" }),
1258
+ /* @__PURE__ */ jsx8("h3", { className: "text-xl font-semibold text-gray-900", children: title })
1259
+ ] }),
1260
+ /* @__PURE__ */ jsx8("div", { className: "space-y-2", children: sortedHours.map((entry) => /* @__PURE__ */ jsx8(
1261
+ HoursCardItem,
1262
+ {
1263
+ entry,
1264
+ isToday: highlightToday && entry.day === todayDay
1265
+ },
1266
+ entry.day
1267
+ )) })
1268
+ ] });
1269
+ }
1270
+ function HoursCardItem({ entry, isToday }) {
1271
+ return /* @__PURE__ */ jsxs8(
1272
+ "div",
1273
+ {
1274
+ className: `flex justify-between py-1 ${isToday ? "bg-primary-50 -mx-2 px-2 rounded font-medium" : ""}`,
1275
+ children: [
1276
+ /* @__PURE__ */ jsxs8("span", { className: isToday ? "text-primary-700" : "text-gray-600", children: [
1277
+ dayNames2[entry.day],
1278
+ isToday && /* @__PURE__ */ jsx8("span", { className: "ml-2 text-xs", children: "(Today)" })
1279
+ ] }),
1280
+ /* @__PURE__ */ jsx8("span", { className: isToday ? "text-primary-700" : "text-gray-900", children: entry.closed ? "Closed" : `${entry.open} - ${entry.close}` })
1281
+ ]
1282
+ }
1283
+ );
1284
+ }
1285
+ function HoursInlineItem({ entry, isToday }) {
1286
+ return /* @__PURE__ */ jsxs8(
1287
+ "div",
1288
+ {
1289
+ className: `text-center px-3 py-2 rounded ${isToday ? "bg-primary-100 ring-2 ring-primary-500" : "bg-gray-100"}`,
1290
+ children: [
1291
+ /* @__PURE__ */ jsx8("div", { className: `text-sm font-medium ${isToday ? "text-primary-700" : "text-gray-500"}`, children: dayAbbrev[entry.day] }),
1292
+ /* @__PURE__ */ jsx8("div", { className: `text-sm ${isToday ? "text-primary-900" : "text-gray-900"}`, children: entry.closed ? "Closed" : `${entry.open?.split(" ")[0]}-${entry.close?.split(" ")[0]}` })
1293
+ ]
1294
+ }
1295
+ );
1296
+ }
1297
+ function HoursMinimalItem({ entry, isToday }) {
1298
+ return /* @__PURE__ */ jsxs8("div", { className: `text-sm ${isToday ? "font-semibold text-primary-600" : "text-gray-600"}`, children: [
1299
+ /* @__PURE__ */ jsx8("span", { className: "inline-block w-20", children: dayAbbrev[entry.day] }),
1300
+ /* @__PURE__ */ jsx8("span", { children: entry.closed ? "Closed" : `${entry.open} - ${entry.close}` })
1301
+ ] });
1302
+ }
1303
+ function getTodayHours(hours, timezone) {
1304
+ const todayDay = getTodayDay(timezone);
1305
+ const todayHours = hours.find((h) => h.day === todayDay);
1306
+ if (!todayHours) return null;
1307
+ if (todayHours.closed) return "Closed today";
1308
+ return `${todayHours.open} - ${todayHours.close}`;
1309
+ }
1310
+ function isCurrentlyOpen(hours, timezone) {
1311
+ const todayDay = getTodayDay(timezone);
1312
+ const todayHours = hours.find((h) => h.day === todayDay);
1313
+ if (!todayHours || todayHours.closed) return false;
1314
+ if (!todayHours.open || !todayHours.close) return false;
1315
+ const now = timezone ? new Date((/* @__PURE__ */ new Date()).toLocaleString("en-US", { timeZone: timezone })) : /* @__PURE__ */ new Date();
1316
+ const currentMinutes = now.getHours() * 60 + now.getMinutes();
1317
+ const openMinutes = parseTimeToMinutes(todayHours.open);
1318
+ const closeMinutes = parseTimeToMinutes(todayHours.close);
1319
+ if (openMinutes === null || closeMinutes === null) return false;
1320
+ return currentMinutes >= openMinutes && currentMinutes < closeMinutes;
1321
+ }
1322
+ function parseTimeToMinutes(time) {
1323
+ const match = time.match(/(\d{1,2}):?(\d{2})?\s*(AM|PM)?/i);
1324
+ if (!match) return null;
1325
+ let hours = parseInt(match[1], 10);
1326
+ const minutes = parseInt(match[2] || "0", 10);
1327
+ const period = match[3]?.toUpperCase();
1328
+ if (period === "PM" && hours !== 12) hours += 12;
1329
+ if (period === "AM" && hours === 12) hours = 0;
1330
+ return hours * 60 + minutes;
1331
+ }
1332
+
1333
+ // src/components/sections/Gallery.tsx
1334
+ import { useState as useState3 } from "react";
1335
+ import { Fragment, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
1336
+ function Gallery({
1337
+ items,
1338
+ title = "Gallery",
1339
+ subtitle,
1340
+ columns = 3,
1341
+ variant = "grid",
1342
+ showCaptions = true,
1343
+ limit,
1344
+ className = ""
1345
+ }) {
1346
+ const displayedItems = limit ? items.slice(0, limit) : items;
1347
+ const [failedImages, setFailedImages] = useState3(/* @__PURE__ */ new Set());
1348
+ const handleImageError = (id) => {
1349
+ setFailedImages((prev) => new Set(prev).add(id));
1350
+ };
1351
+ const gridCols = {
1352
+ 2: "grid-cols-1 sm:grid-cols-2",
1353
+ 3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
1354
+ 4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4"
1355
+ };
1356
+ return /* @__PURE__ */ jsx9("section", { className: `py-16 ${className}`, children: /* @__PURE__ */ jsxs9("div", { className: "container mx-auto px-4", children: [
1357
+ (title || subtitle) && /* @__PURE__ */ jsxs9("div", { className: "text-center mb-12", children: [
1358
+ title && /* @__PURE__ */ jsx9("h2", { className: "text-3xl md:text-4xl font-bold text-gray-900 mb-4", children: title }),
1359
+ subtitle && /* @__PURE__ */ jsx9("p", { className: "text-lg text-gray-600 max-w-2xl mx-auto", children: subtitle })
1360
+ ] }),
1361
+ /* @__PURE__ */ jsx9("div", { className: `grid gap-4 ${gridCols[columns]}`, children: displayedItems.map((item) => {
1362
+ const itemId = item.id || item.imageUrl;
1363
+ const hasFailed = failedImages.has(itemId);
1364
+ return /* @__PURE__ */ jsx9(
1365
+ "div",
1366
+ {
1367
+ className: "group relative aspect-square overflow-hidden rounded-lg bg-gray-100",
1368
+ children: hasFailed ? /* @__PURE__ */ jsx9("div", { className: "absolute inset-0 flex items-center justify-center text-gray-400", children: /* @__PURE__ */ jsx9("span", { children: "Image unavailable" }) }) : /* @__PURE__ */ jsxs9(Fragment, { children: [
1369
+ /* @__PURE__ */ jsx9(
1370
+ "img",
1371
+ {
1372
+ src: item.imageUrl,
1373
+ alt: item.alt || "",
1374
+ loading: "lazy",
1375
+ className: "w-full h-full object-cover transition-transform duration-300 group-hover:scale-105",
1376
+ onError: () => handleImageError(itemId)
1377
+ }
1378
+ ),
1379
+ showCaptions && item.caption && /* @__PURE__ */ jsx9("div", { className: "absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300", children: /* @__PURE__ */ jsx9("div", { className: "absolute bottom-0 left-0 right-0 p-4", children: /* @__PURE__ */ jsx9("p", { className: "text-white text-sm", children: item.caption }) }) })
1380
+ ] })
1381
+ },
1382
+ itemId
1383
+ );
1384
+ }) })
1385
+ ] }) });
1386
+ }
1387
+
1388
+ // src/components/ui/Button.tsx
1389
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1390
+ function getButtonClasses(props) {
1391
+ const { variant = "primary", size = "md", fullWidth, disabled } = props;
1392
+ const baseClasses = [
1393
+ "inline-flex items-center justify-center",
1394
+ "font-medium",
1395
+ "transition-colors duration-200",
1396
+ "focus:outline-none focus:ring-2 focus:ring-offset-2",
1397
+ disabled ? "opacity-50 cursor-not-allowed" : "",
1398
+ fullWidth ? "w-full" : ""
1399
+ ];
1400
+ const variantClasses = {
1401
+ primary: "bg-primary-600 text-white hover:bg-primary-700 focus:ring-primary-500",
1402
+ secondary: "bg-primary-100 text-primary-700 hover:bg-primary-200 focus:ring-primary-500",
1403
+ outline: "border-2 border-primary-600 text-primary-600 hover:bg-primary-50 focus:ring-primary-500",
1404
+ ghost: "text-primary-600 hover:bg-primary-100 focus:ring-primary-500",
1405
+ link: "text-primary-600 hover:underline focus:ring-primary-500 p-0"
1406
+ };
1407
+ const sizeClasses = {
1408
+ sm: "text-sm px-3 py-1.5 rounded",
1409
+ md: "text-base px-4 py-2 rounded-md",
1410
+ lg: "text-lg px-6 py-3 rounded-lg"
1411
+ };
1412
+ return [
1413
+ ...baseClasses,
1414
+ variantClasses[variant],
1415
+ variant !== "link" ? sizeClasses[size] : ""
1416
+ ].filter(Boolean).join(" ");
1417
+ }
1418
+ function Button({
1419
+ variant = "primary",
1420
+ size = "md",
1421
+ fullWidth = false,
1422
+ loading = false,
1423
+ leftIcon,
1424
+ rightIcon,
1425
+ children,
1426
+ disabled,
1427
+ className = "",
1428
+ ...props
1429
+ }) {
1430
+ const classes = getButtonClasses({ variant, size, fullWidth, disabled: disabled || loading });
1431
+ return /* @__PURE__ */ jsx10(
1432
+ "button",
1433
+ {
1434
+ className: `${classes} ${className}`,
1435
+ disabled: disabled || loading,
1436
+ ...props,
1437
+ children: loading ? /* @__PURE__ */ jsx10(LoadingSpinner, { size }) : /* @__PURE__ */ jsxs10(Fragment2, { children: [
1438
+ leftIcon && /* @__PURE__ */ jsx10("span", { className: "mr-2", children: leftIcon }),
1439
+ children,
1440
+ rightIcon && /* @__PURE__ */ jsx10("span", { className: "ml-2", children: rightIcon })
1441
+ ] })
1442
+ }
1443
+ );
1444
+ }
1445
+ function LoadingSpinner({ size }) {
1446
+ const sizeClasses = {
1447
+ sm: "w-4 h-4",
1448
+ md: "w-5 h-5",
1449
+ lg: "w-6 h-6"
1450
+ };
1451
+ return /* @__PURE__ */ jsxs10(
1452
+ "svg",
1453
+ {
1454
+ className: `animate-spin ${sizeClasses[size || "md"]}`,
1455
+ xmlns: "http://www.w3.org/2000/svg",
1456
+ fill: "none",
1457
+ viewBox: "0 0 24 24",
1458
+ children: [
1459
+ /* @__PURE__ */ jsx10(
1460
+ "circle",
1461
+ {
1462
+ className: "opacity-25",
1463
+ cx: "12",
1464
+ cy: "12",
1465
+ r: "10",
1466
+ stroke: "currentColor",
1467
+ strokeWidth: "4"
1468
+ }
1469
+ ),
1470
+ /* @__PURE__ */ jsx10(
1471
+ "path",
1472
+ {
1473
+ className: "opacity-75",
1474
+ fill: "currentColor",
1475
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
1476
+ }
1477
+ )
1478
+ ]
1479
+ }
1480
+ );
1481
+ }
1482
+ function ButtonLink({
1483
+ variant = "primary",
1484
+ size = "md",
1485
+ fullWidth = false,
1486
+ leftIcon,
1487
+ rightIcon,
1488
+ children,
1489
+ className = "",
1490
+ ...props
1491
+ }) {
1492
+ const classes = getButtonClasses({ variant, size, fullWidth, disabled: false });
1493
+ return /* @__PURE__ */ jsxs10("a", { className: `${classes} ${className}`, ...props, children: [
1494
+ leftIcon && /* @__PURE__ */ jsx10("span", { className: "mr-2", children: leftIcon }),
1495
+ children,
1496
+ rightIcon && /* @__PURE__ */ jsx10("span", { className: "ml-2", children: rightIcon })
1497
+ ] });
1498
+ }
1499
+
1500
+ // src/components/ui/Card.tsx
1501
+ import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
1502
+ function getCardClasses(props) {
1503
+ const { variant = "default", padding = "md", hover = false } = props;
1504
+ const baseClasses = ["rounded-lg", "overflow-hidden"];
1505
+ const variantClasses = {
1506
+ default: "bg-white shadow",
1507
+ elevated: "bg-white shadow-lg",
1508
+ outlined: "bg-white border border-gray-200",
1509
+ filled: "bg-gray-50"
1510
+ };
1511
+ const paddingClasses = {
1512
+ none: "",
1513
+ sm: "p-3",
1514
+ md: "p-5",
1515
+ lg: "p-8"
1516
+ };
1517
+ const hoverClasses = hover ? "transition-all duration-200 hover:shadow-lg hover:-translate-y-1" : "";
1518
+ return [
1519
+ ...baseClasses,
1520
+ variantClasses[variant],
1521
+ paddingClasses[padding],
1522
+ hoverClasses
1523
+ ].filter(Boolean).join(" ");
1524
+ }
1525
+ function Card({
1526
+ variant = "default",
1527
+ padding = "md",
1528
+ hover = false,
1529
+ children,
1530
+ className = "",
1531
+ ...props
1532
+ }) {
1533
+ const classes = getCardClasses({ variant, padding, hover });
1534
+ return /* @__PURE__ */ jsx11("div", { className: `${classes} ${className}`, ...props, children });
1535
+ }
1536
+ function CardHeader({
1537
+ title,
1538
+ subtitle,
1539
+ action,
1540
+ children,
1541
+ className = "",
1542
+ ...props
1543
+ }) {
1544
+ return /* @__PURE__ */ jsxs11("div", { className: `flex items-start justify-between ${className}`, ...props, children: [
1545
+ /* @__PURE__ */ jsxs11("div", { children: [
1546
+ title && /* @__PURE__ */ jsx11("h3", { className: "text-lg font-semibold text-gray-900", children: title }),
1547
+ subtitle && /* @__PURE__ */ jsx11("p", { className: "mt-1 text-sm text-gray-500", children: subtitle }),
1548
+ children
1549
+ ] }),
1550
+ action && /* @__PURE__ */ jsx11("div", { className: "flex-shrink-0 ml-4", children: action })
1551
+ ] });
1552
+ }
1553
+ function CardBody({
1554
+ children,
1555
+ className = "",
1556
+ ...props
1557
+ }) {
1558
+ return /* @__PURE__ */ jsx11("div", { className: `mt-4 ${className}`, ...props, children });
1559
+ }
1560
+ function CardFooter({
1561
+ children,
1562
+ className = "",
1563
+ ...props
1564
+ }) {
1565
+ return /* @__PURE__ */ jsx11("div", { className: `mt-4 pt-4 border-t border-gray-100 ${className}`, ...props, children });
1566
+ }
1567
+ function CardImage({
1568
+ aspectRatio = "video",
1569
+ className = "",
1570
+ alt = "",
1571
+ ...props
1572
+ }) {
1573
+ const aspectClasses = {
1574
+ square: "aspect-square",
1575
+ video: "aspect-video",
1576
+ wide: "aspect-[2/1]",
1577
+ auto: ""
1578
+ };
1579
+ return /* @__PURE__ */ jsx11("div", { className: `-m-5 mb-4 ${aspectClasses[aspectRatio]} overflow-hidden`, children: /* @__PURE__ */ jsx11(
1580
+ "img",
1581
+ {
1582
+ className: `w-full h-full object-cover ${className}`,
1583
+ alt,
1584
+ ...props
1585
+ }
1586
+ ) });
1587
+ }
1588
+ export {
1589
+ BriefcaseIcon,
1590
+ Button,
1591
+ ButtonLink,
1592
+ CakeIcon,
1593
+ Card,
1594
+ CardBody,
1595
+ CardFooter,
1596
+ CardHeader,
1597
+ CardImage,
1598
+ CheckIcon,
1599
+ ChevronDownIcon,
1600
+ ChevronRightIcon,
1601
+ ClockIcon,
1602
+ FAQ,
1603
+ FacebookIcon,
1604
+ Footer,
1605
+ Gallery,
1606
+ Header,
1607
+ HeartIcon,
1608
+ Hero,
1609
+ Hours,
1610
+ Icon,
1611
+ InstagramIcon,
1612
+ MailIcon,
1613
+ MapPinIcon,
1614
+ MenuIcon,
1615
+ PhoneIcon,
1616
+ ScissorsIcon,
1617
+ Services,
1618
+ SparklesIcon,
1619
+ StarIcon,
1620
+ Testimonials,
1621
+ UtensilsIcon,
1622
+ WrenchIcon,
1623
+ XIcon,
1624
+ YelpIcon,
1625
+ getIcon,
1626
+ getTodayHours,
1627
+ iconMap,
1628
+ isCurrentlyOpen
1629
+ };
1630
+ //# sourceMappingURL=index.mjs.map