@pichetch08/trip-ui 0.1.0 → 0.2.1

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 (167) hide show
  1. package/dist/{accordion.js → components/shared/accordion.js} +1 -1
  2. package/dist/{agreement-modal.js → components/shared/agreement-modal.js} +1 -1
  3. package/dist/{alert.js → components/shared/alert.js} +1 -1
  4. package/dist/{auth-hero.js → components/shared/auth-hero.js} +1 -1
  5. package/dist/{avatar.js → components/shared/avatar.js} +1 -1
  6. package/dist/{badge.js → components/shared/badge.js} +1 -1
  7. package/dist/{banner.js → components/shared/banner.js} +1 -1
  8. package/dist/{breadcrumb.js → components/shared/breadcrumb.js} +1 -1
  9. package/dist/{button.js → components/shared/button.js} +1 -1
  10. package/dist/{card.js → components/shared/card.js} +1 -1
  11. package/dist/{change-summary-modal.js → components/shared/change-summary-modal.js} +1 -1
  12. package/dist/{channel-badge.js → components/shared/channel-badge.js} +1 -1
  13. package/dist/{checkbox.js → components/shared/checkbox.js} +1 -1
  14. package/dist/{color-picker.js → components/shared/color-picker.js} +1 -1
  15. package/dist/{confirm-dialog.js → components/shared/confirm-dialog.js} +1 -1
  16. package/dist/{copy-button.js → components/shared/copy-button.js} +1 -1
  17. package/dist/{dashed-add-button.js → components/shared/dashed-add-button.js} +1 -1
  18. package/dist/{data-table.js → components/shared/data-table.js} +1 -1
  19. package/dist/{date-picker.js → components/shared/date-picker.js} +1 -1
  20. package/dist/{date-range-picker.js → components/shared/date-range-picker.js} +1 -1
  21. package/dist/{dev-auto-fill.js → components/shared/dev-auto-fill.js} +1 -1
  22. package/dist/{divider.js → components/shared/divider.js} +1 -1
  23. package/dist/{drawer.js → components/shared/drawer.js} +1 -1
  24. package/dist/{dropdown-menu.js → components/shared/dropdown-menu.js} +1 -1
  25. package/dist/{empty-state.js → components/shared/empty-state.js} +1 -1
  26. package/dist/{file-upload.js → components/shared/file-upload.js} +1 -1
  27. package/dist/{filter-tabs.js → components/shared/filter-tabs.js} +1 -1
  28. package/dist/{footer-action-bar.js → components/shared/footer-action-bar.js} +1 -1
  29. package/dist/{form-input.js → components/shared/form-input.js} +1 -1
  30. package/dist/{form-textarea.js → components/shared/form-textarea.js} +1 -1
  31. package/dist/{icon-button.js → components/shared/icon-button.js} +1 -1
  32. package/dist/{icon-picker.js → components/shared/icon-picker.js} +1 -1
  33. package/dist/{icon-wrapper.js → components/shared/icon-wrapper.js} +1 -1
  34. package/dist/{image-upload.js → components/shared/image-upload.js} +1 -1
  35. package/dist/{index.d.ts → components/shared/index.d.ts} +11 -0
  36. package/dist/{index.js → components/shared/index.js} +51 -1
  37. package/dist/{kbd.js → components/shared/kbd.js} +1 -1
  38. package/dist/{mobile-preview.js → components/shared/mobile-preview.js} +1 -1
  39. package/dist/{modal.js → components/shared/modal.js} +1 -1
  40. package/dist/{multi-select.js → components/shared/multi-select.js} +1 -1
  41. package/dist/{number-input.js → components/shared/number-input.js} +1 -1
  42. package/dist/{otp-input.js → components/shared/otp-input.js} +1 -1
  43. package/dist/{page-header.js → components/shared/page-header.js} +1 -1
  44. package/dist/{page-state.js → components/shared/page-state.js} +1 -1
  45. package/dist/{pagination.js → components/shared/pagination.js} +1 -1
  46. package/dist/{popover.js → components/shared/popover.js} +1 -1
  47. package/dist/{preview-drawer.js → components/shared/preview-drawer.js} +1 -1
  48. package/dist/{progress-bar.js → components/shared/progress-bar.js} +1 -1
  49. package/dist/{qr-code-display.js → components/shared/qr-code-display.js} +1 -1
  50. package/dist/{radio-group.js → components/shared/radio-group.js} +1 -1
  51. package/dist/{rating.js → components/shared/rating.js} +1 -1
  52. package/dist/{rich-editor.js → components/shared/rich-editor.js} +1 -1
  53. package/dist/{search-bar.js → components/shared/search-bar.js} +1 -1
  54. package/dist/{section-header.js → components/shared/section-header.js} +1 -1
  55. package/dist/{segmented-control.js → components/shared/segmented-control.js} +1 -1
  56. package/dist/{select-picker.js → components/shared/select-picker.js} +1 -1
  57. package/dist/{skeleton.js → components/shared/skeleton.js} +1 -1
  58. package/dist/{slider.js → components/shared/slider.js} +1 -1
  59. package/dist/{spinner.js → components/shared/spinner.js} +1 -1
  60. package/dist/{stat-card.js → components/shared/stat-card.js} +1 -1
  61. package/dist/{stats-summary.js → components/shared/stats-summary.js} +1 -1
  62. package/dist/{status-badge.js → components/shared/status-badge.js} +1 -1
  63. package/dist/{stepper.js → components/shared/stepper.js} +1 -1
  64. package/dist/{tabs.js → components/shared/tabs.js} +1 -1
  65. package/dist/{tag.js → components/shared/tag.js} +1 -1
  66. package/dist/{time-picker.js → components/shared/time-picker.js} +1 -1
  67. package/dist/{timeline.js → components/shared/timeline.js} +1 -1
  68. package/dist/{toast.js → components/shared/toast.js} +1 -1
  69. package/dist/{toggle-switch.js → components/shared/toggle-switch.js} +1 -1
  70. package/dist/{tooltip.js → components/shared/tooltip.js} +1 -1
  71. package/dist/{trip-day-map-lazy.d.ts → components/shared/trip-day-map-lazy.d.ts} +6 -0
  72. package/dist/{trip-day-map-lazy.js → components/shared/trip-day-map-lazy.js} +2 -2
  73. package/dist/components/shared/trip-day-map.d.ts +28 -0
  74. package/dist/components/shared/trip-day-map.js +146 -0
  75. package/dist/components/trip/acknowledge-banner.d.ts +9 -0
  76. package/dist/components/trip/acknowledge-banner.js +47 -0
  77. package/dist/components/trip/activity-item.d.ts +8 -0
  78. package/dist/components/trip/activity-item.js +174 -0
  79. package/dist/components/trip/company-footer.d.ts +9 -0
  80. package/dist/components/trip/company-footer.js +99 -0
  81. package/dist/components/trip/countdown-badge.d.ts +7 -0
  82. package/dist/components/trip/countdown-badge.js +39 -0
  83. package/dist/components/trip/day-card.d.ts +8 -0
  84. package/dist/components/trip/day-card.js +62 -0
  85. package/dist/components/trip/emergency-card.d.ts +8 -0
  86. package/dist/components/trip/emergency-card.js +34 -0
  87. package/dist/components/trip/index.d.ts +9 -0
  88. package/dist/components/trip/index.js +19 -0
  89. package/dist/components/trip/info-badge.d.ts +8 -0
  90. package/dist/components/trip/info-badge.js +21 -0
  91. package/dist/components/trip/sticky-day-nav.d.ts +10 -0
  92. package/dist/components/trip/sticky-day-nav.js +36 -0
  93. package/dist/types/trip.d.ts +111 -0
  94. package/dist/types/trip.js +0 -0
  95. package/dist/utils/trip-utils.d.ts +29 -0
  96. package/dist/utils/trip-utils.js +166 -0
  97. package/package.json +17 -8
  98. package/dist/trip-day-map.d.ts +0 -15
  99. package/dist/trip-day-map.js +0 -62
  100. /package/dist/{accordion.d.ts → components/shared/accordion.d.ts} +0 -0
  101. /package/dist/{agreement-modal.d.ts → components/shared/agreement-modal.d.ts} +0 -0
  102. /package/dist/{alert.d.ts → components/shared/alert.d.ts} +0 -0
  103. /package/dist/{auth-hero.d.ts → components/shared/auth-hero.d.ts} +0 -0
  104. /package/dist/{avatar.d.ts → components/shared/avatar.d.ts} +0 -0
  105. /package/dist/{badge.d.ts → components/shared/badge.d.ts} +0 -0
  106. /package/dist/{banner.d.ts → components/shared/banner.d.ts} +0 -0
  107. /package/dist/{breadcrumb.d.ts → components/shared/breadcrumb.d.ts} +0 -0
  108. /package/dist/{button.d.ts → components/shared/button.d.ts} +0 -0
  109. /package/dist/{card.d.ts → components/shared/card.d.ts} +0 -0
  110. /package/dist/{change-summary-modal.d.ts → components/shared/change-summary-modal.d.ts} +0 -0
  111. /package/dist/{channel-badge.d.ts → components/shared/channel-badge.d.ts} +0 -0
  112. /package/dist/{checkbox.d.ts → components/shared/checkbox.d.ts} +0 -0
  113. /package/dist/{color-picker.d.ts → components/shared/color-picker.d.ts} +0 -0
  114. /package/dist/{confirm-dialog.d.ts → components/shared/confirm-dialog.d.ts} +0 -0
  115. /package/dist/{copy-button.d.ts → components/shared/copy-button.d.ts} +0 -0
  116. /package/dist/{dashed-add-button.d.ts → components/shared/dashed-add-button.d.ts} +0 -0
  117. /package/dist/{data-table.d.ts → components/shared/data-table.d.ts} +0 -0
  118. /package/dist/{date-picker.d.ts → components/shared/date-picker.d.ts} +0 -0
  119. /package/dist/{date-range-picker.d.ts → components/shared/date-range-picker.d.ts} +0 -0
  120. /package/dist/{dev-auto-fill.d.ts → components/shared/dev-auto-fill.d.ts} +0 -0
  121. /package/dist/{divider.d.ts → components/shared/divider.d.ts} +0 -0
  122. /package/dist/{drawer.d.ts → components/shared/drawer.d.ts} +0 -0
  123. /package/dist/{dropdown-menu.d.ts → components/shared/dropdown-menu.d.ts} +0 -0
  124. /package/dist/{empty-state.d.ts → components/shared/empty-state.d.ts} +0 -0
  125. /package/dist/{file-upload.d.ts → components/shared/file-upload.d.ts} +0 -0
  126. /package/dist/{filter-tabs.d.ts → components/shared/filter-tabs.d.ts} +0 -0
  127. /package/dist/{footer-action-bar.d.ts → components/shared/footer-action-bar.d.ts} +0 -0
  128. /package/dist/{form-input.d.ts → components/shared/form-input.d.ts} +0 -0
  129. /package/dist/{form-textarea.d.ts → components/shared/form-textarea.d.ts} +0 -0
  130. /package/dist/{icon-button.d.ts → components/shared/icon-button.d.ts} +0 -0
  131. /package/dist/{icon-picker.d.ts → components/shared/icon-picker.d.ts} +0 -0
  132. /package/dist/{icon-wrapper.d.ts → components/shared/icon-wrapper.d.ts} +0 -0
  133. /package/dist/{image-upload.d.ts → components/shared/image-upload.d.ts} +0 -0
  134. /package/dist/{kbd.d.ts → components/shared/kbd.d.ts} +0 -0
  135. /package/dist/{mobile-preview.d.ts → components/shared/mobile-preview.d.ts} +0 -0
  136. /package/dist/{modal.d.ts → components/shared/modal.d.ts} +0 -0
  137. /package/dist/{multi-select.d.ts → components/shared/multi-select.d.ts} +0 -0
  138. /package/dist/{number-input.d.ts → components/shared/number-input.d.ts} +0 -0
  139. /package/dist/{otp-input.d.ts → components/shared/otp-input.d.ts} +0 -0
  140. /package/dist/{page-header.d.ts → components/shared/page-header.d.ts} +0 -0
  141. /package/dist/{page-state.d.ts → components/shared/page-state.d.ts} +0 -0
  142. /package/dist/{pagination.d.ts → components/shared/pagination.d.ts} +0 -0
  143. /package/dist/{popover.d.ts → components/shared/popover.d.ts} +0 -0
  144. /package/dist/{preview-drawer.d.ts → components/shared/preview-drawer.d.ts} +0 -0
  145. /package/dist/{progress-bar.d.ts → components/shared/progress-bar.d.ts} +0 -0
  146. /package/dist/{qr-code-display.d.ts → components/shared/qr-code-display.d.ts} +0 -0
  147. /package/dist/{radio-group.d.ts → components/shared/radio-group.d.ts} +0 -0
  148. /package/dist/{rating.d.ts → components/shared/rating.d.ts} +0 -0
  149. /package/dist/{rich-editor.d.ts → components/shared/rich-editor.d.ts} +0 -0
  150. /package/dist/{search-bar.d.ts → components/shared/search-bar.d.ts} +0 -0
  151. /package/dist/{section-header.d.ts → components/shared/section-header.d.ts} +0 -0
  152. /package/dist/{segmented-control.d.ts → components/shared/segmented-control.d.ts} +0 -0
  153. /package/dist/{select-picker.d.ts → components/shared/select-picker.d.ts} +0 -0
  154. /package/dist/{skeleton.d.ts → components/shared/skeleton.d.ts} +0 -0
  155. /package/dist/{slider.d.ts → components/shared/slider.d.ts} +0 -0
  156. /package/dist/{spinner.d.ts → components/shared/spinner.d.ts} +0 -0
  157. /package/dist/{stat-card.d.ts → components/shared/stat-card.d.ts} +0 -0
  158. /package/dist/{stats-summary.d.ts → components/shared/stats-summary.d.ts} +0 -0
  159. /package/dist/{status-badge.d.ts → components/shared/status-badge.d.ts} +0 -0
  160. /package/dist/{stepper.d.ts → components/shared/stepper.d.ts} +0 -0
  161. /package/dist/{tabs.d.ts → components/shared/tabs.d.ts} +0 -0
  162. /package/dist/{tag.d.ts → components/shared/tag.d.ts} +0 -0
  163. /package/dist/{time-picker.d.ts → components/shared/time-picker.d.ts} +0 -0
  164. /package/dist/{timeline.d.ts → components/shared/timeline.d.ts} +0 -0
  165. /package/dist/{toast.d.ts → components/shared/toast.d.ts} +0 -0
  166. /package/dist/{toggle-switch.d.ts → components/shared/toggle-switch.d.ts} +0 -0
  167. /package/dist/{tooltip.d.ts → components/shared/tooltip.d.ts} +0 -0
@@ -0,0 +1,39 @@
1
+ "use client";
2
+ import "../../chunk-ORMEWXMH.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useEffect, useState } from "react";
5
+ import { getDaysUntil } from "../../utils/trip-utils";
6
+ function CountdownBadge({ startDate, endDate }) {
7
+ const [daysUntil, setDaysUntil] = useState(getDaysUntil(startDate));
8
+ useEffect(() => {
9
+ const timer = setInterval(() => {
10
+ setDaysUntil(getDaysUntil(startDate));
11
+ }, 6e4);
12
+ return () => clearInterval(timer);
13
+ }, [startDate]);
14
+ const now = /* @__PURE__ */ new Date();
15
+ const start = new Date(startDate);
16
+ const end = new Date(endDate);
17
+ if (now > end) {
18
+ return /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2 rounded-full bg-white/20 px-4 py-2 text-sm font-medium text-white backdrop-blur-sm", children: /* @__PURE__ */ jsx("span", { children: "\u0E17\u0E23\u0E34\u0E1B\u0E08\u0E1A\u0E41\u0E25\u0E49\u0E27" }) });
19
+ }
20
+ if (now >= start && now <= end) {
21
+ const currentDay = Math.ceil((now.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24)) + 1;
22
+ const totalDays = Math.ceil((end.getTime() - start.getTime()) / (1e3 * 60 * 60 * 24)) + 1;
23
+ return /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2 rounded-full bg-success/90 px-4 py-2 text-sm font-bold text-white backdrop-blur-sm", children: /* @__PURE__ */ jsxs("span", { children: [
24
+ "Day ",
25
+ currentDay,
26
+ " of ",
27
+ totalDays,
28
+ " \u2014 \u0E27\u0E31\u0E19\u0E19\u0E35\u0E49!"
29
+ ] }) });
30
+ }
31
+ return /* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-2 rounded-full bg-white/20 px-4 py-2 text-sm font-bold text-white backdrop-blur-sm", children: /* @__PURE__ */ jsxs("span", { children: [
32
+ "\u0E2D\u0E35\u0E01 ",
33
+ daysUntil,
34
+ " \u0E27\u0E31\u0E19! \u{1F389}"
35
+ ] }) });
36
+ }
37
+ export {
38
+ CountdownBadge
39
+ };
@@ -0,0 +1,8 @@
1
+ import { Day } from '../../types/trip.js';
2
+
3
+ type DayCardProps = {
4
+ day: Day;
5
+ };
6
+ declare function DayCard({ day }: DayCardProps): React.JSX.Element;
7
+
8
+ export { DayCard };
@@ -0,0 +1,62 @@
1
+ "use client";
2
+ import "../../chunk-ORMEWXMH.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { cn, getDayGradientClass, formatDateShort, detectMapProviderFromActivities, buildRouteUrl, getRouteButtonLabel } from "../../utils/trip-utils";
5
+ import { ActivityItem } from "./activity-item";
6
+ function DayCard({ day }) {
7
+ const gradientClass = getDayGradientClass(day.dayNumber);
8
+ const activitiesWithMaps = day.activities.filter((a) => a.mapsLink);
9
+ const provider = detectMapProviderFromActivities(activitiesWithMaps);
10
+ const places = activitiesWithMaps.map((a) => a.placeName);
11
+ const routeUrl = buildRouteUrl(places, provider);
12
+ return /* @__PURE__ */ jsxs("div", { id: `day-${day.dayNumber}`, className: "scroll-mt-16", children: [
13
+ /* @__PURE__ */ jsxs("div", { className: cn("relative overflow-hidden rounded-t-2xl", gradientClass), children: [
14
+ day.coverImageUrl && /* @__PURE__ */ jsx(
15
+ "img",
16
+ {
17
+ src: day.coverImageUrl,
18
+ alt: day.title,
19
+ className: "absolute inset-0 h-full w-full object-cover opacity-30 mix-blend-overlay"
20
+ }
21
+ ),
22
+ /* @__PURE__ */ jsx("div", { className: "relative px-5 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
23
+ /* @__PURE__ */ jsxs("div", { children: [
24
+ /* @__PURE__ */ jsxs("p", { className: "text-xs font-medium text-white/70", children: [
25
+ "Day ",
26
+ day.dayNumber,
27
+ " \u2014 ",
28
+ formatDateShort(day.date)
29
+ ] }),
30
+ /* @__PURE__ */ jsxs("h3", { className: "mt-0.5 text-lg font-bold text-white", children: [
31
+ day.subtitle,
32
+ " ",
33
+ day.title
34
+ ] })
35
+ ] }),
36
+ /* @__PURE__ */ jsxs("span", { className: "rounded-full bg-white/20 px-3 py-1 text-xs font-medium text-white", children: [
37
+ day.activities.length,
38
+ " \u0E01\u0E34\u0E08\u0E01\u0E23\u0E23\u0E21"
39
+ ] })
40
+ ] }) })
41
+ ] }),
42
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3 rounded-b-2xl border border-t-0 border-border bg-guest-card-bg p-4", children: [
43
+ day.activities.map((activity) => /* @__PURE__ */ jsx(ActivityItem, { activity }, activity.id)),
44
+ routeUrl && /* @__PURE__ */ jsxs(
45
+ "a",
46
+ {
47
+ href: routeUrl,
48
+ target: "_blank",
49
+ rel: "noopener noreferrer",
50
+ className: "flex items-center justify-center gap-2 rounded-xl border-2 border-dashed border-primary/30 bg-primary-50 py-3 text-sm font-medium text-primary transition-colors hover:border-primary hover:bg-primary-100",
51
+ children: [
52
+ /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-sm", children: "map" }),
53
+ getRouteButtonLabel(provider)
54
+ ]
55
+ }
56
+ )
57
+ ] })
58
+ ] });
59
+ }
60
+ export {
61
+ DayCard
62
+ };
@@ -0,0 +1,8 @@
1
+ import { EmergencyContact } from '../../types/trip.js';
2
+
3
+ type EmergencyCardProps = {
4
+ contacts: EmergencyContact[];
5
+ };
6
+ declare function EmergencyCard({ contacts }: EmergencyCardProps): React.JSX.Element;
7
+
8
+ export { EmergencyCard };
@@ -0,0 +1,34 @@
1
+ import "../../chunk-ORMEWXMH.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ function EmergencyCard({ contacts }) {
4
+ return /* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-border bg-white p-5", children: [
5
+ /* @__PURE__ */ jsx("h3", { className: "mb-3 text-base font-bold text-foreground", children: "\u{1F198} \u0E40\u0E1A\u0E2D\u0E23\u0E4C\u0E09\u0E38\u0E01\u0E40\u0E09\u0E34\u0E19" }),
6
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: contacts.map((contact) => /* @__PURE__ */ jsxs(
7
+ "div",
8
+ {
9
+ className: "flex items-center justify-between rounded-xl bg-muted px-4 py-3",
10
+ children: [
11
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
12
+ /* @__PURE__ */ jsx("span", { className: "text-lg", children: contact.icon }),
13
+ /* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-foreground", children: contact.name })
14
+ ] }),
15
+ /* @__PURE__ */ jsxs(
16
+ "a",
17
+ {
18
+ href: `tel:${contact.phone}`,
19
+ className: "inline-flex items-center gap-1.5 rounded-full bg-primary px-3 py-1.5 text-xs font-medium text-white transition-colors hover:bg-primary-dark",
20
+ children: [
21
+ /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-xs", children: "call" }),
22
+ contact.phone
23
+ ]
24
+ }
25
+ )
26
+ ]
27
+ },
28
+ contact.phone
29
+ )) })
30
+ ] });
31
+ }
32
+ export {
33
+ EmergencyCard
34
+ };
@@ -0,0 +1,9 @@
1
+ export { AcknowledgeBanner } from './acknowledge-banner.js';
2
+ export { ActivityItem } from './activity-item.js';
3
+ export { CompanyFooter } from './company-footer.js';
4
+ export { CountdownBadge } from './countdown-badge.js';
5
+ export { DayCard } from './day-card.js';
6
+ export { EmergencyCard } from './emergency-card.js';
7
+ export { InfoBadge } from './info-badge.js';
8
+ export { StickyDayNav } from './sticky-day-nav.js';
9
+ import '../../types/trip.js';
@@ -0,0 +1,19 @@
1
+ import "../../chunk-ORMEWXMH.js";
2
+ import { AcknowledgeBanner } from "./acknowledge-banner";
3
+ import { ActivityItem } from "./activity-item";
4
+ import { CompanyFooter } from "./company-footer";
5
+ import { CountdownBadge } from "./countdown-badge";
6
+ import { DayCard } from "./day-card";
7
+ import { EmergencyCard } from "./emergency-card";
8
+ import { InfoBadge } from "./info-badge";
9
+ import { StickyDayNav } from "./sticky-day-nav";
10
+ export {
11
+ AcknowledgeBanner,
12
+ ActivityItem,
13
+ CompanyFooter,
14
+ CountdownBadge,
15
+ DayCard,
16
+ EmergencyCard,
17
+ InfoBadge,
18
+ StickyDayNav
19
+ };
@@ -0,0 +1,8 @@
1
+ type InfoBadgeProps = {
2
+ icon: string;
3
+ label: string;
4
+ className?: string;
5
+ };
6
+ declare function InfoBadge({ icon, label, className }: InfoBadgeProps): React.JSX.Element;
7
+
8
+ export { InfoBadge };
@@ -0,0 +1,21 @@
1
+ import "../../chunk-ORMEWXMH.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { cn } from "../../utils/trip-utils";
4
+ function InfoBadge({ icon, label, className }) {
5
+ return /* @__PURE__ */ jsxs(
6
+ "div",
7
+ {
8
+ className: cn(
9
+ "glass-card inline-flex items-center gap-1.5 rounded-full border border-white/20 px-3 py-1.5 text-xs font-medium text-white",
10
+ className
11
+ ),
12
+ children: [
13
+ /* @__PURE__ */ jsx("span", { children: icon }),
14
+ /* @__PURE__ */ jsx("span", { children: label })
15
+ ]
16
+ }
17
+ );
18
+ }
19
+ export {
20
+ InfoBadge
21
+ };
@@ -0,0 +1,10 @@
1
+ import { Day } from '../../types/trip.js';
2
+
3
+ type StickyDayNavProps = {
4
+ days: Day[];
5
+ activeDay: number;
6
+ onDayClick: (dayNumber: number) => void;
7
+ };
8
+ declare function StickyDayNav({ days, activeDay, onDayClick }: StickyDayNavProps): React.JSX.Element;
9
+
10
+ export { StickyDayNav };
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ import "../../chunk-ORMEWXMH.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useRef } from "react";
5
+ import { cn } from "../../utils/trip-utils";
6
+ function StickyDayNav({ days, activeDay, onDayClick }) {
7
+ const scrollRef = useRef(null);
8
+ return /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-40 border-b border-border bg-white/95 backdrop-blur-sm", children: /* @__PURE__ */ jsx(
9
+ "div",
10
+ {
11
+ ref: scrollRef,
12
+ className: "hide-scrollbar flex gap-1 overflow-x-auto px-4 py-2",
13
+ children: days.map((day) => /* @__PURE__ */ jsxs(
14
+ "button",
15
+ {
16
+ onClick: () => onDayClick(day.dayNumber),
17
+ className: cn(
18
+ "shrink-0 rounded-full px-4 py-2 text-sm font-medium transition-all",
19
+ activeDay === day.dayNumber ? "bg-primary text-white shadow-md" : "bg-muted text-muted-foreground hover:bg-primary-100 hover:text-primary"
20
+ ),
21
+ children: [
22
+ /* @__PURE__ */ jsx("span", { className: "mr-1", children: day.subtitle.split(" ")[0] }),
23
+ /* @__PURE__ */ jsxs("span", { children: [
24
+ "D",
25
+ day.dayNumber
26
+ ] })
27
+ ]
28
+ },
29
+ day.id
30
+ ))
31
+ }
32
+ ) });
33
+ }
34
+ export {
35
+ StickyDayNav
36
+ };
@@ -0,0 +1,111 @@
1
+ type AirlineInfo = {
2
+ airline: string;
3
+ flightNumber: string;
4
+ departureTime: string;
5
+ arrivalTime: string;
6
+ departureAirport: string;
7
+ arrivalAirport: string;
8
+ type: "departure" | "return" | "transit";
9
+ };
10
+ type Accommodation = {
11
+ name: string;
12
+ address: string;
13
+ phone: string;
14
+ checkIn: string;
15
+ checkOut: string;
16
+ nights: number;
17
+ };
18
+ type EmergencyContact = {
19
+ name: string;
20
+ phone: string;
21
+ icon: string;
22
+ sortOrder: number;
23
+ };
24
+ type Activity = {
25
+ id: string;
26
+ time: string;
27
+ name: string;
28
+ description: string;
29
+ type: "attraction" | "restaurant" | "hotel" | "transport" | "shopping" | "other";
30
+ placeName: string;
31
+ mapsLink: string;
32
+ imageUrl: string;
33
+ imageUrls?: string[];
34
+ emoji: string;
35
+ sortOrder: number;
36
+ isNew?: boolean;
37
+ isChanged?: boolean;
38
+ };
39
+ type Day = {
40
+ id: string;
41
+ dayNumber: number;
42
+ title: string;
43
+ subtitle: string;
44
+ coverImageUrl: string;
45
+ date: string;
46
+ activities: Activity[];
47
+ };
48
+ type Company = {
49
+ name: string;
50
+ logoUrl: string;
51
+ phone: string;
52
+ lineId: string;
53
+ facebook: string;
54
+ instagram: string;
55
+ website: string;
56
+ tatLicense: string;
57
+ };
58
+ type PendingChange = {
59
+ changelogId: string;
60
+ summaryText: string;
61
+ changes: {
62
+ type: "add" | "update" | "delete";
63
+ description: string;
64
+ }[];
65
+ createdAt: string;
66
+ };
67
+ type Changelog = {
68
+ id: string;
69
+ version: number;
70
+ summaryText: string;
71
+ changes: {
72
+ type: "add" | "update" | "delete";
73
+ description: string;
74
+ }[];
75
+ createdAt: string;
76
+ acknowledgedAt: string | null;
77
+ };
78
+ type ChecklistItem = {
79
+ id: string;
80
+ label: string;
81
+ isRequired: boolean;
82
+ sortOrder: number;
83
+ };
84
+ type TripPlan = {
85
+ id: string;
86
+ title: string;
87
+ slug: string;
88
+ destination: string;
89
+ startDate: string;
90
+ endDate: string;
91
+ coverImageUrl: string;
92
+ travelersCount: number;
93
+ language: string;
94
+ airlineInfo: AirlineInfo[];
95
+ accommodations: Accommodation[];
96
+ emergencyContacts: EmergencyContact[];
97
+ checklistItems: ChecklistItem[];
98
+ notes: string;
99
+ status: "draft" | "published" | "unpublished";
100
+ days: Day[];
101
+ company: Company;
102
+ followerCount: number;
103
+ pendingChange: PendingChange | null;
104
+ changelogs: Changelog[];
105
+ /** Free plan = true, paid plans = false. Renders "Powered by TripApp" badge. */
106
+ showWatermark?: boolean;
107
+ /** Additional language codes this trip has translations for. */
108
+ supportedLanguages?: string[];
109
+ };
110
+
111
+ export type { Accommodation, Activity, AirlineInfo, Changelog, ChecklistItem, Company, Day, EmergencyContact, PendingChange, TripPlan };
File without changes
@@ -0,0 +1,29 @@
1
+ import { ClassValue } from 'clsx';
2
+
3
+ declare function cn(...inputs: ClassValue[]): string;
4
+ declare function formatDate(date: Date | string, locale?: string): string;
5
+ declare function formatDateShort(date: Date | string, locale?: string): string;
6
+ declare function formatDateRange(start: string, end: string): string;
7
+ declare function getDaysUntil(date: string): number;
8
+ declare function getTripDuration(start: string, end: string): number;
9
+ declare function getDayGradientClass(dayNumber: number): string;
10
+ type ActivityType = "attraction" | "restaurant" | "hotel" | "transport" | "shopping" | "other";
11
+ declare function getActivityTypeStyle(type: string): {
12
+ bg: string;
13
+ text: string;
14
+ border: string;
15
+ };
16
+ declare function getActivityEmoji(emoji: string | undefined, type: string): string;
17
+ declare function getDayEmoji(subtitle: string | undefined, dayIndex: number): string;
18
+ type MapProvider = "google" | "baidu" | "amap" | "apple" | "unknown";
19
+ declare function detectMapProvider(mapsLink: string): MapProvider;
20
+ declare function detectMapProviderFromActivities(activities: {
21
+ mapsLink: string;
22
+ placeName: string;
23
+ }[]): MapProvider;
24
+ declare function buildRouteUrl(places: string[], provider: MapProvider): string | null;
25
+ declare function getMapProviderLabel(provider: MapProvider): string;
26
+ declare function getMapButtonLabel(provider: MapProvider): string;
27
+ declare function getRouteButtonLabel(provider: MapProvider): string;
28
+
29
+ export { type ActivityType, type MapProvider, buildRouteUrl, cn, detectMapProvider, detectMapProviderFromActivities, formatDate, formatDateRange, formatDateShort, getActivityEmoji, getActivityTypeStyle, getDayEmoji, getDayGradientClass, getDaysUntil, getMapButtonLabel, getMapProviderLabel, getRouteButtonLabel, getTripDuration };
@@ -0,0 +1,166 @@
1
+ import "../chunk-ORMEWXMH.js";
2
+ import { clsx } from "clsx";
3
+ import { twMerge } from "tailwind-merge";
4
+ function cn(...inputs) {
5
+ return twMerge(clsx(inputs));
6
+ }
7
+ function formatDate(date, locale = "th-TH") {
8
+ return new Intl.DateTimeFormat(locale, {
9
+ weekday: "long",
10
+ day: "numeric",
11
+ month: "long",
12
+ year: "numeric"
13
+ }).format(new Date(date));
14
+ }
15
+ function formatDateShort(date, locale = "th-TH") {
16
+ return new Intl.DateTimeFormat(locale, {
17
+ day: "numeric",
18
+ month: "short"
19
+ }).format(new Date(date));
20
+ }
21
+ function formatDateRange(start, end) {
22
+ const s = new Date(start);
23
+ const e = new Date(end);
24
+ const sMonth = s.toLocaleDateString("en-US", { month: "short" });
25
+ const eMonth = e.toLocaleDateString("en-US", { month: "short" });
26
+ const year = e.getFullYear();
27
+ if (sMonth === eMonth) {
28
+ return `${s.getDate()} \u2013 ${e.getDate()} ${sMonth} ${year}`;
29
+ }
30
+ return `${s.getDate()} ${sMonth} \u2013 ${e.getDate()} ${eMonth} ${year}`;
31
+ }
32
+ function getDaysUntil(date) {
33
+ const target = new Date(date);
34
+ const now = /* @__PURE__ */ new Date();
35
+ const diff = target.getTime() - now.getTime();
36
+ return Math.ceil(diff / (1e3 * 60 * 60 * 24));
37
+ }
38
+ function getTripDuration(start, end) {
39
+ const s = new Date(start);
40
+ const e = new Date(end);
41
+ return Math.ceil((e.getTime() - s.getTime()) / (1e3 * 60 * 60 * 24)) + 1;
42
+ }
43
+ function getDayGradientClass(dayNumber) {
44
+ const index = (dayNumber - 1) % 8 + 1;
45
+ return `day-gradient-${index}`;
46
+ }
47
+ const ACTIVITY_TYPE_STYLES = {
48
+ attraction: { bg: "bg-blue-50", text: "text-blue-600", border: "border-blue-200" },
49
+ restaurant: { bg: "bg-orange-50", text: "text-orange-600", border: "border-orange-200" },
50
+ transport: { bg: "bg-slate-50", text: "text-slate-500", border: "border-slate-200" },
51
+ shopping: { bg: "bg-fuchsia-50", text: "text-fuchsia-600", border: "border-fuchsia-200" },
52
+ hotel: { bg: "bg-teal-50", text: "text-teal-600", border: "border-teal-200" },
53
+ other: { bg: "bg-violet-50", text: "text-violet-600", border: "border-violet-200" }
54
+ };
55
+ function getActivityTypeStyle(type) {
56
+ var _a;
57
+ return (_a = ACTIVITY_TYPE_STYLES[type]) != null ? _a : ACTIVITY_TYPE_STYLES.other;
58
+ }
59
+ const ACTIVITY_TYPE_EMOJI = {
60
+ attraction: "\u{1F3DB}\uFE0F",
61
+ restaurant: "\u{1F37D}\uFE0F",
62
+ hotel: "\u{1F3E8}",
63
+ transport: "\u{1F68C}",
64
+ shopping: "\u{1F6CD}\uFE0F",
65
+ other: "\u{1F4CC}"
66
+ };
67
+ function getActivityEmoji(emoji, type) {
68
+ var _a;
69
+ if (emoji == null ? void 0 : emoji.trim()) return emoji;
70
+ return (_a = ACTIVITY_TYPE_EMOJI[type]) != null ? _a : "\u{1F4CC}";
71
+ }
72
+ const DAY_EMOJIS = ["\u{1F305}", "\u{1F5FA}\uFE0F", "\u{1F3D6}\uFE0F", "\u{1F306}", "\u{1F304}", "\u{1F3AD}", "\u{1F3D4}\uFE0F", "\u2728"];
73
+ function getDayEmoji(subtitle, dayIndex) {
74
+ var _a, _b;
75
+ const first = (_a = subtitle == null ? void 0 : subtitle.trim().split(" ")[0]) != null ? _a : "";
76
+ if (first && !/^[a-zA-Z0-9]/.test(first)) return first;
77
+ return (_b = DAY_EMOJIS[dayIndex % DAY_EMOJIS.length]) != null ? _b : "\u{1F4C5}";
78
+ }
79
+ function detectMapProvider(mapsLink) {
80
+ if (!mapsLink) return "unknown";
81
+ if (mapsLink.includes("google.com/maps") || mapsLink.includes("maps.google.com")) return "google";
82
+ if (mapsLink.includes("map.baidu.com") || mapsLink.includes("baidu.com/map")) return "baidu";
83
+ if (mapsLink.includes("amap.com") || mapsLink.includes("gaode.com")) return "amap";
84
+ if (mapsLink.includes("maps.apple.com")) return "apple";
85
+ return "unknown";
86
+ }
87
+ function detectMapProviderFromActivities(activities) {
88
+ const withLink = activities.filter((a) => a.mapsLink);
89
+ const first = withLink[0];
90
+ if (!first) return "unknown";
91
+ return detectMapProvider(first.mapsLink);
92
+ }
93
+ function buildRouteUrl(places, provider) {
94
+ if (places.length < 2) return null;
95
+ const origin = places[0];
96
+ const destination = places[places.length - 1];
97
+ const waypoints = places.slice(1, -1);
98
+ switch (provider) {
99
+ case "google":
100
+ return `https://www.google.com/maps/dir/${places.map(encodeURIComponent).join("/")}`;
101
+ case "baidu":
102
+ return `https://map.baidu.com/direction?origin=${encodeURIComponent(origin)}&destination=${encodeURIComponent(destination)}${waypoints.length > 0 ? `&viaPoints=${waypoints.map(encodeURIComponent).join("|")}` : ""}&mode=transit&coord_type=keyword`;
103
+ case "amap":
104
+ return `https://uri.amap.com/navigation?from=${encodeURIComponent(origin)}&to=${encodeURIComponent(destination)}&mode=bus&coordinate=keyword`;
105
+ case "apple":
106
+ return `https://maps.apple.com/?dirflg=r&saddr=${encodeURIComponent(origin)}&daddr=${encodeURIComponent(destination)}`;
107
+ default:
108
+ return `https://www.google.com/maps/dir/${places.map(encodeURIComponent).join("/")}`;
109
+ }
110
+ }
111
+ function getMapProviderLabel(provider) {
112
+ switch (provider) {
113
+ case "google":
114
+ return "Google Maps";
115
+ case "baidu":
116
+ return "\u767E\u5EA6\u5730\u56FE";
117
+ case "amap":
118
+ return "\u9AD8\u5FB7\u5730\u56FE";
119
+ case "apple":
120
+ return "Apple Maps";
121
+ default:
122
+ return "\u0E41\u0E1C\u0E19\u0E17\u0E35\u0E48";
123
+ }
124
+ }
125
+ function getMapButtonLabel(provider) {
126
+ switch (provider) {
127
+ case "baidu":
128
+ return "\u0E40\u0E1B\u0E34\u0E14\u0E41\u0E1C\u0E19\u0E17\u0E35\u0E48 (\u767E\u5EA6)";
129
+ case "amap":
130
+ return "\u0E40\u0E1B\u0E34\u0E14\u0E41\u0E1C\u0E19\u0E17\u0E35\u0E48 (\u9AD8\u5FB7)";
131
+ case "apple":
132
+ return "\u0E40\u0E1B\u0E34\u0E14\u0E41\u0E1C\u0E19\u0E17\u0E35\u0E48 (Apple)";
133
+ default:
134
+ return "\u0E40\u0E1B\u0E34\u0E14\u0E41\u0E1C\u0E19\u0E17\u0E35\u0E48";
135
+ }
136
+ }
137
+ function getRouteButtonLabel(provider) {
138
+ switch (provider) {
139
+ case "baidu":
140
+ return "\u0E14\u0E39\u0E40\u0E2A\u0E49\u0E19\u0E17\u0E32\u0E07\u0E17\u0E31\u0E49\u0E07\u0E27\u0E31\u0E19 (\u767E\u5EA6\u5730\u56FE)";
141
+ case "amap":
142
+ return "\u0E14\u0E39\u0E40\u0E2A\u0E49\u0E19\u0E17\u0E32\u0E07\u0E17\u0E31\u0E49\u0E07\u0E27\u0E31\u0E19 (\u9AD8\u5FB7\u5730\u56FE)";
143
+ case "apple":
144
+ return "\u0E14\u0E39\u0E40\u0E2A\u0E49\u0E19\u0E17\u0E32\u0E07\u0E17\u0E31\u0E49\u0E07\u0E27\u0E31\u0E19 (Apple Maps)";
145
+ default:
146
+ return "\u0E14\u0E39\u0E40\u0E2A\u0E49\u0E19\u0E17\u0E32\u0E07\u0E17\u0E31\u0E49\u0E07\u0E27\u0E31\u0E19";
147
+ }
148
+ }
149
+ export {
150
+ buildRouteUrl,
151
+ cn,
152
+ detectMapProvider,
153
+ detectMapProviderFromActivities,
154
+ formatDate,
155
+ formatDateRange,
156
+ formatDateShort,
157
+ getActivityEmoji,
158
+ getActivityTypeStyle,
159
+ getDayEmoji,
160
+ getDayGradientClass,
161
+ getDaysUntil,
162
+ getMapButtonLabel,
163
+ getMapProviderLabel,
164
+ getRouteButtonLabel,
165
+ getTripDuration
166
+ };
package/package.json CHANGED
@@ -1,18 +1,25 @@
1
1
  {
2
2
  "name": "@pichetch08/trip-ui",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
4
4
  "description": "Trip UI — shared React component library built with Tailwind v4 and Material Design 3 tokens",
5
5
  "author": "pichetch08",
6
6
  "license": "MIT",
7
- "keywords": ["react", "tailwind", "material-design", "ui", "components", "trip"],
7
+ "keywords": [
8
+ "react",
9
+ "tailwind",
10
+ "material-design",
11
+ "ui",
12
+ "components",
13
+ "trip"
14
+ ],
8
15
  "type": "module",
9
- "main": "./dist/index.js",
10
- "module": "./dist/index.js",
11
- "types": "./dist/index.d.ts",
16
+ "main": "./dist/components/shared/index.js",
17
+ "module": "./dist/components/shared/index.js",
18
+ "types": "./dist/components/shared/index.d.ts",
12
19
  "exports": {
13
20
  ".": {
14
- "import": "./dist/index.js",
15
- "types": "./dist/index.d.ts"
21
+ "import": "./dist/components/shared/index.js",
22
+ "types": "./dist/components/shared/index.d.ts"
16
23
  }
17
24
  },
18
25
  "files": [
@@ -33,7 +40,9 @@
33
40
  "tailwind-merge": ">=3"
34
41
  },
35
42
  "peerDependenciesMeta": {
36
- "next": { "optional": true }
43
+ "next": {
44
+ "optional": true
45
+ }
37
46
  },
38
47
  "dependencies": {
39
48
  "leaflet": "^1.9.4",
@@ -1,15 +0,0 @@
1
- import * as react_jsx_runtime from 'react/jsx-runtime';
2
-
3
- interface MapActivity {
4
- name: string;
5
- lat: number;
6
- lng: number;
7
- time?: string | null;
8
- }
9
- interface TripDayMapProps {
10
- activities: MapActivity[];
11
- height?: string;
12
- }
13
- declare function TripDayMap({ activities, height }: TripDayMapProps): react_jsx_runtime.JSX.Element | null;
14
-
15
- export { type MapActivity, TripDayMap };