@pichetch08/trip-ui 0.1.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 (145) hide show
  1. package/README.md +46 -0
  2. package/dist/accordion.d.ts +18 -0
  3. package/dist/accordion.js +76 -0
  4. package/dist/agreement-modal.d.ts +16 -0
  5. package/dist/agreement-modal.js +67 -0
  6. package/dist/alert.d.ts +13 -0
  7. package/dist/alert.js +47 -0
  8. package/dist/auth-hero.d.ts +7 -0
  9. package/dist/auth-hero.js +63 -0
  10. package/dist/avatar.d.ts +21 -0
  11. package/dist/avatar.js +114 -0
  12. package/dist/badge.d.ts +13 -0
  13. package/dist/badge.js +36 -0
  14. package/dist/banner.d.ts +14 -0
  15. package/dist/banner.js +57 -0
  16. package/dist/breadcrumb.d.ts +15 -0
  17. package/dist/breadcrumb.js +37 -0
  18. package/dist/button.d.ts +15 -0
  19. package/dist/button.js +81 -0
  20. package/dist/card.d.ts +30 -0
  21. package/dist/card.js +66 -0
  22. package/dist/change-summary-modal.d.ts +35 -0
  23. package/dist/change-summary-modal.js +128 -0
  24. package/dist/channel-badge.d.ts +8 -0
  25. package/dist/channel-badge.js +17 -0
  26. package/dist/checkbox.d.ts +28 -0
  27. package/dist/checkbox.js +108 -0
  28. package/dist/chunk-ORMEWXMH.js +37 -0
  29. package/dist/color-picker.d.ts +15 -0
  30. package/dist/color-picker.js +159 -0
  31. package/dist/confirm-dialog.d.ts +23 -0
  32. package/dist/confirm-dialog.js +108 -0
  33. package/dist/copy-button.d.ts +13 -0
  34. package/dist/copy-button.js +69 -0
  35. package/dist/dashed-add-button.d.ts +8 -0
  36. package/dist/dashed-add-button.js +24 -0
  37. package/dist/data-table.d.ts +27 -0
  38. package/dist/data-table.js +152 -0
  39. package/dist/date-picker.d.ts +19 -0
  40. package/dist/date-picker.js +234 -0
  41. package/dist/date-range-picker.d.ts +25 -0
  42. package/dist/date-range-picker.js +456 -0
  43. package/dist/dev-auto-fill.d.ts +12 -0
  44. package/dist/dev-auto-fill.js +22 -0
  45. package/dist/divider.d.ts +10 -0
  46. package/dist/divider.js +44 -0
  47. package/dist/drawer.d.ts +16 -0
  48. package/dist/drawer.js +111 -0
  49. package/dist/dropdown-menu.d.ts +20 -0
  50. package/dist/dropdown-menu.js +94 -0
  51. package/dist/empty-state.d.ts +13 -0
  52. package/dist/empty-state.js +24 -0
  53. package/dist/file-upload.d.ts +32 -0
  54. package/dist/file-upload.js +212 -0
  55. package/dist/filter-tabs.d.ts +16 -0
  56. package/dist/filter-tabs.js +30 -0
  57. package/dist/footer-action-bar.d.ts +21 -0
  58. package/dist/footer-action-bar.js +95 -0
  59. package/dist/form-input.d.ts +16 -0
  60. package/dist/form-input.js +58 -0
  61. package/dist/form-textarea.d.ts +13 -0
  62. package/dist/form-textarea.js +41 -0
  63. package/dist/icon-button.d.ts +12 -0
  64. package/dist/icon-button.js +54 -0
  65. package/dist/icon-picker.d.ts +15 -0
  66. package/dist/icon-picker.js +311 -0
  67. package/dist/icon-wrapper.d.ts +15 -0
  68. package/dist/icon-wrapper.js +52 -0
  69. package/dist/image-upload.d.ts +24 -0
  70. package/dist/image-upload.js +122 -0
  71. package/dist/index.d.ts +71 -0
  72. package/dist/index.js +155 -0
  73. package/dist/kbd.d.ts +15 -0
  74. package/dist/kbd.js +27 -0
  75. package/dist/mobile-preview.d.ts +36 -0
  76. package/dist/mobile-preview.js +167 -0
  77. package/dist/modal.d.ts +19 -0
  78. package/dist/modal.js +110 -0
  79. package/dist/multi-select.d.ts +30 -0
  80. package/dist/multi-select.js +261 -0
  81. package/dist/number-input.d.ts +21 -0
  82. package/dist/number-input.js +129 -0
  83. package/dist/otp-input.d.ts +13 -0
  84. package/dist/otp-input.js +114 -0
  85. package/dist/page-header.d.ts +15 -0
  86. package/dist/page-header.js +43 -0
  87. package/dist/page-state.d.ts +14 -0
  88. package/dist/page-state.js +29 -0
  89. package/dist/pagination.d.ts +20 -0
  90. package/dist/pagination.js +87 -0
  91. package/dist/popover.d.ts +11 -0
  92. package/dist/popover.js +70 -0
  93. package/dist/preview-drawer.d.ts +33 -0
  94. package/dist/preview-drawer.js +74 -0
  95. package/dist/progress-bar.d.ts +15 -0
  96. package/dist/progress-bar.js +56 -0
  97. package/dist/qr-code-display.d.ts +10 -0
  98. package/dist/qr-code-display.js +43 -0
  99. package/dist/radio-group.d.ts +19 -0
  100. package/dist/radio-group.js +78 -0
  101. package/dist/rating.d.ts +12 -0
  102. package/dist/rating.js +123 -0
  103. package/dist/rich-editor.d.ts +13 -0
  104. package/dist/rich-editor.js +97 -0
  105. package/dist/search-bar.d.ts +14 -0
  106. package/dist/search-bar.js +64 -0
  107. package/dist/section-header.d.ts +12 -0
  108. package/dist/section-header.js +41 -0
  109. package/dist/segmented-control.d.ts +24 -0
  110. package/dist/segmented-control.js +38 -0
  111. package/dist/select-picker.d.ts +24 -0
  112. package/dist/select-picker.js +157 -0
  113. package/dist/skeleton.d.ts +14 -0
  114. package/dist/skeleton.js +53 -0
  115. package/dist/slider.d.ts +17 -0
  116. package/dist/slider.js +151 -0
  117. package/dist/spinner.d.ts +13 -0
  118. package/dist/spinner.js +38 -0
  119. package/dist/stat-card.d.ts +20 -0
  120. package/dist/stat-card.js +87 -0
  121. package/dist/stats-summary.d.ts +13 -0
  122. package/dist/stats-summary.js +28 -0
  123. package/dist/status-badge.d.ts +19 -0
  124. package/dist/status-badge.js +41 -0
  125. package/dist/stepper.d.ts +12 -0
  126. package/dist/stepper.js +89 -0
  127. package/dist/tabs.d.ts +18 -0
  128. package/dist/tabs.js +70 -0
  129. package/dist/tag.d.ts +23 -0
  130. package/dist/tag.js +158 -0
  131. package/dist/time-picker.d.ts +19 -0
  132. package/dist/time-picker.js +222 -0
  133. package/dist/timeline.d.ts +15 -0
  134. package/dist/timeline.js +49 -0
  135. package/dist/toast.d.ts +18 -0
  136. package/dist/toast.js +108 -0
  137. package/dist/toggle-switch.d.ts +12 -0
  138. package/dist/toggle-switch.js +34 -0
  139. package/dist/tooltip.d.ts +9 -0
  140. package/dist/tooltip.js +69 -0
  141. package/dist/trip-day-map-lazy.d.ts +15 -0
  142. package/dist/trip-day-map-lazy.js +16 -0
  143. package/dist/trip-day-map.d.ts +15 -0
  144. package/dist/trip-day-map.js +62 -0
  145. package/package.json +73 -0
@@ -0,0 +1,71 @@
1
+ export { StatCard, StatCardTone } from './stat-card.js';
2
+ export { PageHeader } from './page-header.js';
3
+ export { EmptyState } from './empty-state.js';
4
+ export { Badge } from './badge.js';
5
+ export { SearchBar } from './search-bar.js';
6
+ export { FilterTab, FilterTabs } from './filter-tabs.js';
7
+ export { Pagination } from './pagination.js';
8
+ export { ConfirmDialog } from './confirm-dialog.js';
9
+ export { Column, DataTable } from './data-table.js';
10
+ export { ToastProvider, useToast } from './toast.js';
11
+ export { Drawer } from './drawer.js';
12
+ export { ToggleSwitch } from './toggle-switch.js';
13
+ export { ErrorState, LoadingState } from './page-state.js';
14
+ export { Banner, BannerVariant } from './banner.js';
15
+ export { Modal, ModalSize } from './modal.js';
16
+ export { RichEditor } from './rich-editor.js';
17
+ export { CardSkeleton, PageSkeleton, Skeleton, StatCardSkeleton, TableRowSkeleton } from './skeleton.js';
18
+ export { StatusBadge, StatusConfig, StatusTone } from './status-badge.js';
19
+ export { AppColor, IconWrapper, IconWrapperColor } from './icon-wrapper.js';
20
+ export { IconButton, IconButtonVariant } from './icon-button.js';
21
+ export { FormInput } from './form-input.js';
22
+ export { FormTextarea } from './form-textarea.js';
23
+ export { SectionHeader } from './section-header.js';
24
+ export { FooterActionBar } from './footer-action-bar.js';
25
+ export { DashedAddButton } from './dashed-add-button.js';
26
+ export { StatsSummary } from './stats-summary.js';
27
+ export { IconPicker } from './icon-picker.js';
28
+ export { AgreementModal } from './agreement-modal.js';
29
+ export { AuthHero } from './auth-hero.js';
30
+ export { ChangeEntry, ChangeSummaryModal } from './change-summary-modal.js';
31
+ export { ChannelBadge, FollowChannel } from './channel-badge.js';
32
+ export { DatePicker } from './date-picker.js';
33
+ export { DevAutoFill } from './dev-auto-fill.js';
34
+ export { MobilePreview } from './mobile-preview.js';
35
+ export { PreviewDrawer } from './preview-drawer.js';
36
+ export { QRCodeDisplay } from './qr-code-display.js';
37
+ export { SegmentedControl } from './segmented-control.js';
38
+ export { SelectOption, SelectPicker } from './select-picker.js';
39
+ export { TimePicker } from './time-picker.js';
40
+ export { MapActivity, TripDayMapLazy } from './trip-day-map-lazy.js';
41
+ export { Checkbox, CheckboxGroup } from './checkbox.js';
42
+ export { RadioGroup } from './radio-group.js';
43
+ export { Alert, AlertVariant } from './alert.js';
44
+ export { Breadcrumb, BreadcrumbItem } from './breadcrumb.js';
45
+ export { ProgressBar } from './progress-bar.js';
46
+ export { Avatar, AvatarGroup } from './avatar.js';
47
+ export { Rating } from './rating.js';
48
+ export { NumberInput } from './number-input.js';
49
+ export { Accordion, AccordionItem } from './accordion.js';
50
+ export { TabItem, Tabs } from './tabs.js';
51
+ export { DropdownItem, DropdownMenu } from './dropdown-menu.js';
52
+ export { Tag, TagGroup } from './tag.js';
53
+ export { Tooltip } from './tooltip.js';
54
+ export { StepItem, Stepper } from './stepper.js';
55
+ export { Timeline, TimelineItem } from './timeline.js';
56
+ export { OTPInput } from './otp-input.js';
57
+ export { Slider } from './slider.js';
58
+ export { ImageUpload } from './image-upload.js';
59
+ export { MultiSelect, MultiSelectOption } from './multi-select.js';
60
+ export { DateRangePicker } from './date-range-picker.js';
61
+ export { FullPageSpinner, Spinner } from './spinner.js';
62
+ export { Popover } from './popover.js';
63
+ export { FileUpload, UploadedFile } from './file-upload.js';
64
+ export { ColorPicker } from './color-picker.js';
65
+ export { Card, CardBody, CardFooter, CardHeader } from './card.js';
66
+ export { Divider } from './divider.js';
67
+ export { CopyButton } from './copy-button.js';
68
+ export { KBD, Shortcut } from './kbd.js';
69
+ export { Button, ButtonSize, ButtonVariant } from './button.js';
70
+ import 'react/jsx-runtime';
71
+ import 'react';
package/dist/index.js ADDED
@@ -0,0 +1,155 @@
1
+ import "./chunk-ORMEWXMH.js";
2
+ import { StatCard } from "./stat-card";
3
+ import { PageHeader } from "./page-header";
4
+ import { EmptyState } from "./empty-state";
5
+ import { Badge } from "./badge";
6
+ import { SearchBar } from "./search-bar";
7
+ import { FilterTabs } from "./filter-tabs";
8
+ import { Pagination } from "./pagination";
9
+ import { ConfirmDialog } from "./confirm-dialog";
10
+ import { DataTable } from "./data-table";
11
+ import { ToastProvider, useToast } from "./toast";
12
+ import { Drawer } from "./drawer";
13
+ import { ToggleSwitch } from "./toggle-switch";
14
+ import { LoadingState, ErrorState } from "./page-state";
15
+ import { Banner } from "./banner";
16
+ import { Modal } from "./modal";
17
+ import { RichEditor } from "./rich-editor";
18
+ import { Skeleton, CardSkeleton, TableRowSkeleton, StatCardSkeleton, PageSkeleton } from "./skeleton";
19
+ import { StatusBadge } from "./status-badge";
20
+ import { IconWrapper } from "./icon-wrapper";
21
+ import { IconButton } from "./icon-button";
22
+ import { FormInput } from "./form-input";
23
+ import { FormTextarea } from "./form-textarea";
24
+ import { SectionHeader } from "./section-header";
25
+ import { FooterActionBar } from "./footer-action-bar";
26
+ import { DashedAddButton } from "./dashed-add-button";
27
+ import { StatsSummary } from "./stats-summary";
28
+ import { IconPicker } from "./icon-picker";
29
+ import { AgreementModal } from "./agreement-modal";
30
+ import { AuthHero } from "./auth-hero";
31
+ import { ChangeSummaryModal } from "./change-summary-modal";
32
+ import { ChannelBadge } from "./channel-badge";
33
+ import { DatePicker } from "./date-picker";
34
+ import { DevAutoFill } from "./dev-auto-fill";
35
+ import { MobilePreview } from "./mobile-preview";
36
+ import { PreviewDrawer } from "./preview-drawer";
37
+ import { QRCodeDisplay } from "./qr-code-display";
38
+ import { SegmentedControl } from "./segmented-control";
39
+ import { SelectPicker } from "./select-picker";
40
+ import { TimePicker } from "./time-picker";
41
+ import { TripDayMapLazy } from "./trip-day-map-lazy";
42
+ import { Checkbox, CheckboxGroup } from "./checkbox";
43
+ import { RadioGroup } from "./radio-group";
44
+ import { Alert } from "./alert";
45
+ import { Breadcrumb } from "./breadcrumb";
46
+ import { ProgressBar } from "./progress-bar";
47
+ import { Avatar, AvatarGroup } from "./avatar";
48
+ import { Rating } from "./rating";
49
+ import { NumberInput } from "./number-input";
50
+ import { Accordion } from "./accordion";
51
+ import { Tabs } from "./tabs";
52
+ import { DropdownMenu } from "./dropdown-menu";
53
+ import { Tag, TagGroup } from "./tag";
54
+ import { Tooltip } from "./tooltip";
55
+ import { Stepper } from "./stepper";
56
+ import { Timeline } from "./timeline";
57
+ import { OTPInput } from "./otp-input";
58
+ import { Slider } from "./slider";
59
+ import { ImageUpload } from "./image-upload";
60
+ import { MultiSelect } from "./multi-select";
61
+ import { DateRangePicker } from "./date-range-picker";
62
+ import { Spinner, FullPageSpinner } from "./spinner";
63
+ import { Popover } from "./popover";
64
+ import { FileUpload } from "./file-upload";
65
+ import { ColorPicker } from "./color-picker";
66
+ import { Card, CardHeader, CardBody, CardFooter } from "./card";
67
+ import { Divider } from "./divider";
68
+ import { CopyButton } from "./copy-button";
69
+ import { KBD, Shortcut } from "./kbd";
70
+ import { Button } from "./button";
71
+ export {
72
+ Accordion,
73
+ AgreementModal,
74
+ Alert,
75
+ AuthHero,
76
+ Avatar,
77
+ AvatarGroup,
78
+ Badge,
79
+ Banner,
80
+ Breadcrumb,
81
+ Button,
82
+ Card,
83
+ CardBody,
84
+ CardFooter,
85
+ CardHeader,
86
+ CardSkeleton,
87
+ ChangeSummaryModal,
88
+ ChannelBadge,
89
+ Checkbox,
90
+ CheckboxGroup,
91
+ ColorPicker,
92
+ ConfirmDialog,
93
+ CopyButton,
94
+ DashedAddButton,
95
+ DataTable,
96
+ DatePicker,
97
+ DateRangePicker,
98
+ DevAutoFill,
99
+ Divider,
100
+ Drawer,
101
+ DropdownMenu,
102
+ EmptyState,
103
+ ErrorState,
104
+ FileUpload,
105
+ FilterTabs,
106
+ FooterActionBar,
107
+ FormInput,
108
+ FormTextarea,
109
+ FullPageSpinner,
110
+ IconButton,
111
+ IconPicker,
112
+ IconWrapper,
113
+ ImageUpload,
114
+ KBD,
115
+ LoadingState,
116
+ MobilePreview,
117
+ Modal,
118
+ MultiSelect,
119
+ NumberInput,
120
+ OTPInput,
121
+ PageHeader,
122
+ PageSkeleton,
123
+ Pagination,
124
+ Popover,
125
+ PreviewDrawer,
126
+ ProgressBar,
127
+ QRCodeDisplay,
128
+ RadioGroup,
129
+ Rating,
130
+ RichEditor,
131
+ SearchBar,
132
+ SectionHeader,
133
+ SegmentedControl,
134
+ SelectPicker,
135
+ Shortcut,
136
+ Skeleton,
137
+ Slider,
138
+ Spinner,
139
+ StatCard,
140
+ StatCardSkeleton,
141
+ StatsSummary,
142
+ StatusBadge,
143
+ Stepper,
144
+ TableRowSkeleton,
145
+ Tabs,
146
+ Tag,
147
+ TagGroup,
148
+ TimePicker,
149
+ Timeline,
150
+ ToastProvider,
151
+ ToggleSwitch,
152
+ Tooltip,
153
+ TripDayMapLazy,
154
+ useToast
155
+ };
package/dist/kbd.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import React__default from 'react';
3
+
4
+ interface KBDProps {
5
+ children: React__default.ReactNode;
6
+ size?: "sm" | "md";
7
+ }
8
+ declare function KBD({ children, size }: KBDProps): react_jsx_runtime.JSX.Element;
9
+ interface ShortcutProps {
10
+ keys: string[];
11
+ size?: "sm" | "md";
12
+ }
13
+ declare function Shortcut({ keys, size }: ShortcutProps): react_jsx_runtime.JSX.Element;
14
+
15
+ export { KBD, Shortcut };
package/dist/kbd.js ADDED
@@ -0,0 +1,27 @@
1
+ import "./chunk-ORMEWXMH.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import React from "react";
4
+ function KBD({ children, size = "md" }) {
5
+ const sizeClasses = size === "sm" ? "px-1.5 py-0.5 text-[10px]" : "px-2 py-1 text-xs";
6
+ return /* @__PURE__ */ jsx(
7
+ "kbd",
8
+ {
9
+ className: [
10
+ "inline-flex items-center justify-center font-mono font-semibold",
11
+ "bg-surface-container border border-outline-variant/40 border-b-2 border-b-outline-variant/70 rounded-md shadow-sm text-on-surface-variant",
12
+ sizeClasses
13
+ ].join(" "),
14
+ children
15
+ }
16
+ );
17
+ }
18
+ function Shortcut({ keys, size = "md" }) {
19
+ return /* @__PURE__ */ jsx("span", { className: "inline-flex items-center gap-1", children: keys.map((key, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
20
+ index > 0 && /* @__PURE__ */ jsx("span", { className: "text-xs text-on-surface-variant font-medium select-none", children: "+" }),
21
+ /* @__PURE__ */ jsx(KBD, { size, children: key })
22
+ ] }, index)) });
23
+ }
24
+ export {
25
+ KBD,
26
+ Shortcut
27
+ };
@@ -0,0 +1,36 @@
1
+ interface DayLite {
2
+ id: string;
3
+ title: string;
4
+ date: string | null;
5
+ coverImageUrl: string | null;
6
+ activities: {
7
+ id: string;
8
+ time: string | null;
9
+ name: string;
10
+ description: string | null;
11
+ emoji: string | null;
12
+ }[];
13
+ }
14
+ interface MobilePreviewProps {
15
+ title: string;
16
+ startDate: string;
17
+ endDate: string;
18
+ totalDays: number;
19
+ travelersCount: number;
20
+ coverImageUrl: string | null;
21
+ airlineName: string | null;
22
+ accommodationsCount: number;
23
+ countdownDays: number;
24
+ days: DayLite[];
25
+ activeDayIndex: number;
26
+ onActiveDayChange: (i: number) => void;
27
+ emptyText?: string;
28
+ previewLabel?: string;
29
+ countdownText?: (days: number) => string;
30
+ daysText?: string;
31
+ activitiesText?: string;
32
+ followLabel?: string;
33
+ }
34
+ declare function MobilePreview({ title, startDate, endDate, totalDays, travelersCount, coverImageUrl, airlineName, accommodationsCount, countdownDays, days, activeDayIndex, onActiveDayChange, emptyText, previewLabel, countdownText, daysText, activitiesText, followLabel, }: MobilePreviewProps): React.ReactNode;
35
+
36
+ export { MobilePreview };
@@ -0,0 +1,167 @@
1
+ "use client";
2
+ import "./chunk-ORMEWXMH.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ const DAY_GRADIENTS = [
5
+ "from-blue-600 to-indigo-700",
6
+ "from-rose-500 to-pink-600",
7
+ "from-emerald-500 to-teal-600",
8
+ "from-amber-500 to-orange-600",
9
+ "from-violet-500 to-purple-600",
10
+ "from-cyan-500 to-blue-600"
11
+ ];
12
+ const formatDateTH = (dateStr) => new Date(dateStr).toLocaleDateString("th-TH", { day: "numeric", month: "short" });
13
+ function MobilePreview({
14
+ title,
15
+ startDate,
16
+ endDate,
17
+ totalDays,
18
+ travelersCount,
19
+ coverImageUrl,
20
+ airlineName,
21
+ accommodationsCount,
22
+ countdownDays,
23
+ days,
24
+ activeDayIndex,
25
+ onActiveDayChange,
26
+ emptyText = "\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E01\u0E34\u0E08\u0E01\u0E23\u0E23\u0E21",
27
+ previewLabel = "\u0E15\u0E31\u0E27\u0E2D\u0E22\u0E48\u0E32\u0E07\u0E2B\u0E19\u0E49\u0E32\u0E15\u0E32\u0E1A\u0E19\u0E21\u0E37\u0E2D\u0E16\u0E37\u0E2D",
28
+ countdownText = (days2) => `\u0E2D\u0E35\u0E01 ${days2} \u0E27\u0E31\u0E19`,
29
+ daysText = "\u0E27\u0E31\u0E19",
30
+ activitiesText = "\u0E01\u0E34\u0E08\u0E01\u0E23\u0E23\u0E21",
31
+ followLabel = "\u2B50 \u0E15\u0E34\u0E14\u0E15\u0E32\u0E21\u0E17\u0E23\u0E34\u0E1B\u0E19\u0E35\u0E49"
32
+ }) {
33
+ var _a;
34
+ const currentDay = (_a = days[activeDayIndex]) != null ? _a : days[0];
35
+ return /* @__PURE__ */ jsxs("div", { className: "relative flex justify-center", "aria-label": previewLabel, children: [
36
+ /* @__PURE__ */ jsxs("div", { className: "absolute left-0 top-22 flex flex-col gap-2 z-10", style: { left: "-10px" }, children: [
37
+ /* @__PURE__ */ jsx("div", { className: "w-1 h-8 bg-slate-700 rounded-l-sm shadow-inner" }),
38
+ /* @__PURE__ */ jsx("div", { className: "w-1 h-13 bg-slate-700 rounded-l-sm shadow-inner" }),
39
+ /* @__PURE__ */ jsx("div", { className: "w-1 h-13 bg-slate-700 rounded-l-sm shadow-inner" })
40
+ ] }),
41
+ /* @__PURE__ */ jsx("div", { className: "absolute right-0 top-30 z-10", style: { right: "-10px" }, children: /* @__PURE__ */ jsx("div", { className: "w-1 h-18 bg-slate-700 rounded-r-sm shadow-inner" }) }),
42
+ /* @__PURE__ */ jsx(
43
+ "div",
44
+ {
45
+ className: "relative w-67.5 bg-linear-to-b from-slate-800 to-slate-900 rounded-[3.5rem] shadow-2xl",
46
+ style: {
47
+ padding: "12px",
48
+ boxShadow: "0 40px 80px -12px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.08), 0 0 0 1px rgba(0,0,0,0.4)"
49
+ },
50
+ children: /* @__PURE__ */ jsx("div", { className: "w-full h-full bg-black rounded-[2.8rem] overflow-hidden", style: { padding: "2px" }, children: /* @__PURE__ */ jsxs("div", { className: "w-full h-full bg-surface-container-lowest rounded-[2.6rem] overflow-hidden flex flex-col relative", style: { height: "556px" }, children: [
51
+ /* @__PURE__ */ jsxs("div", { className: "absolute top-0 left-0 right-0 h-10 flex items-end justify-between px-6 pb-1.5 z-30 pointer-events-none", children: [
52
+ /* @__PURE__ */ jsx("div", { className: "absolute top-2 left-1/2 -translate-x-1/2 w-20 h-5.5 bg-black rounded-full" }),
53
+ /* @__PURE__ */ jsx("span", { className: "text-[11px] font-semibold text-white z-10", children: "9:41" }),
54
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 z-10", children: [
55
+ /* @__PURE__ */ jsxs("svg", { width: "13", height: "10", viewBox: "0 0 13 10", fill: "currentColor", className: "text-white", children: [
56
+ /* @__PURE__ */ jsx("rect", { x: "0", y: "7", width: "2", height: "3", rx: "0.5" }),
57
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "5", width: "2", height: "5", rx: "0.5" }),
58
+ /* @__PURE__ */ jsx("rect", { x: "6", y: "3", width: "2", height: "7", rx: "0.5" }),
59
+ /* @__PURE__ */ jsx("rect", { x: "9", y: "1", width: "2", height: "9", rx: "0.5", opacity: "0.5" })
60
+ ] }),
61
+ /* @__PURE__ */ jsxs("svg", { width: "13", height: "10", viewBox: "0 0 13 10", fill: "currentColor", className: "text-white", children: [
62
+ /* @__PURE__ */ jsx("path", { d: "M6.5 7.5a1 1 0 1 1 0 2 1 1 0 0 1 0-2z" }),
63
+ /* @__PURE__ */ jsx("path", { d: "M3.8 5.2a3.8 3.8 0 0 1 5.4 0l-1 1a2.4 2.4 0 0 0-3.4 0l-1-1z" }),
64
+ /* @__PURE__ */ jsx("path", { d: "M1.5 3a6.2 6.2 0 0 1 10 0l-1 1a4.8 4.8 0 0 0-8 0l-1-1z", opacity: "0.5" })
65
+ ] }),
66
+ /* @__PURE__ */ jsxs("svg", { width: "22", height: "10", viewBox: "0 0 22 10", fill: "currentColor", className: "text-white", children: [
67
+ /* @__PURE__ */ jsx("rect", { x: "0.5", y: "0.5", width: "18", height: "9", rx: "2.5", stroke: "currentColor", strokeWidth: "1", fill: "none", opacity: "0.5" }),
68
+ /* @__PURE__ */ jsx("rect", { x: "19.5", y: "3", width: "2", height: "4", rx: "1", opacity: "0.5" }),
69
+ /* @__PURE__ */ jsx("rect", { x: "2", y: "2", width: "13", height: "6", rx: "1.5" })
70
+ ] })
71
+ ] })
72
+ ] }),
73
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", style: { scrollbarWidth: "none" }, children: [
74
+ /* @__PURE__ */ jsxs("div", { className: "relative h-52 w-full overflow-hidden", children: [
75
+ coverImageUrl ? /* @__PURE__ */ jsx("img", { className: "w-full h-full object-cover", src: coverImageUrl, alt: "" }) : /* @__PURE__ */ jsx("div", { className: "w-full h-full bg-linear-to-br from-blue-400 to-indigo-600" }),
76
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-linear-to-t from-black/85 via-black/30 to-transparent" }),
77
+ /* @__PURE__ */ jsxs("div", { className: "absolute bottom-0 left-0 right-0 p-4 text-white", children: [
78
+ countdownDays > 0 && /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-white/20 backdrop-blur-sm text-[8px] font-bold mb-1.5", children: [
79
+ /* @__PURE__ */ jsx("span", { className: "w-1.5 h-1.5 rounded-full bg-green-400 animate-pulse" }),
80
+ countdownText(countdownDays)
81
+ ] }),
82
+ /* @__PURE__ */ jsx("h3", { className: "text-[15px] font-extrabold leading-tight", children: title }),
83
+ /* @__PURE__ */ jsxs("p", { className: "text-[9px] text-white/75 mt-0.5", children: [
84
+ formatDateTH(startDate),
85
+ " \u2014 ",
86
+ formatDateTH(endDate),
87
+ " \xB7 ",
88
+ totalDays,
89
+ " ",
90
+ daysText
91
+ ] }),
92
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-1.5 mt-2 flex-wrap", children: [
93
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded-full bg-white/15 backdrop-blur-sm text-[7px] text-white/90", children: [
94
+ "\u{1F465} ",
95
+ travelersCount
96
+ ] }),
97
+ airlineName && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded-full bg-white/15 backdrop-blur-sm text-[7px] text-white/90", children: [
98
+ "\u2708\uFE0F ",
99
+ airlineName
100
+ ] }),
101
+ /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-0.5 px-1.5 py-0.5 rounded-full bg-white/15 backdrop-blur-sm text-[7px] text-white/90", children: [
102
+ "\u{1F3E8} ",
103
+ accommodationsCount
104
+ ] })
105
+ ] }),
106
+ /* @__PURE__ */ jsx("button", { type: "button", className: "mt-2.5 w-full py-1.5 rounded-full bg-linear-to-r from-primary to-blue-500 text-[9px] font-bold text-white flex items-center justify-center gap-1 shadow-lg", children: followLabel })
107
+ ] })
108
+ ] }),
109
+ /* @__PURE__ */ jsx("div", { className: "sticky top-0 z-10 bg-surface border-b border-outline-variant/20 px-3 py-2 flex gap-1.5 overflow-x-auto", style: { scrollbarWidth: "none" }, children: days.map((day, i) => /* @__PURE__ */ jsxs(
110
+ "button",
111
+ {
112
+ type: "button",
113
+ onClick: () => onActiveDayChange(i),
114
+ className: `shrink-0 px-2.5 py-1 rounded-lg text-[8px] font-bold whitespace-nowrap transition-all ${activeDayIndex === i ? "bg-primary text-white shadow-sm" : "bg-surface-container text-on-surface-variant"}`,
115
+ children: [
116
+ "D",
117
+ i + 1
118
+ ]
119
+ },
120
+ day.id
121
+ )) }),
122
+ currentDay && /* @__PURE__ */ jsx("div", { className: "px-3 py-3 space-y-3", children: /* @__PURE__ */ jsxs("div", { className: "rounded-2xl overflow-hidden border border-outline-variant/20 shadow-sm bg-surface", children: [
123
+ /* @__PURE__ */ jsxs("div", { className: `relative h-14 bg-linear-to-r ${DAY_GRADIENTS[activeDayIndex % DAY_GRADIENTS.length]} p-3 flex flex-col justify-end`, children: [
124
+ currentDay.coverImageUrl && /* @__PURE__ */ jsx("img", { className: "absolute inset-0 w-full h-full object-cover opacity-30 mix-blend-overlay", src: currentDay.coverImageUrl, alt: "" }),
125
+ /* @__PURE__ */ jsxs("div", { className: "relative flex items-center gap-2 text-white", children: [
126
+ /* @__PURE__ */ jsxs("div", { children: [
127
+ /* @__PURE__ */ jsx("p", { className: "text-[7px] font-medium text-white/70", children: currentDay.date && formatDateTH(currentDay.date) }),
128
+ /* @__PURE__ */ jsx("h4", { className: "text-[10px] font-extrabold leading-tight", children: currentDay.title || `Day ${activeDayIndex + 1}` })
129
+ ] }),
130
+ /* @__PURE__ */ jsxs("span", { className: "ml-auto bg-white/20 backdrop-blur-sm rounded-full px-1.5 py-0.5 text-[7px] font-bold text-white", children: [
131
+ currentDay.activities.length,
132
+ " ",
133
+ activitiesText
134
+ ] })
135
+ ] })
136
+ ] }),
137
+ /* @__PURE__ */ jsx("div", { className: "p-2.5 space-y-2", children: currentDay.activities.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-center text-[9px] text-on-surface-variant py-4", children: emptyText }) : currentDay.activities.map((act, actIdx) => /* @__PURE__ */ jsxs("div", { className: "flex gap-2 items-start", children: [
138
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center shrink-0", children: [
139
+ /* @__PURE__ */ jsx("div", { className: "w-2 h-2 rounded-full bg-primary mt-1" }),
140
+ actIdx < currentDay.activities.length - 1 && /* @__PURE__ */ jsx("div", { className: "w-px flex-1 min-h-3 bg-outline-variant/30" })
141
+ ] }),
142
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 pb-2", children: [
143
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
144
+ /* @__PURE__ */ jsx("span", { className: "text-sm leading-none", children: act.emoji || "\u{1F4CD}" }),
145
+ act.time && /* @__PURE__ */ jsx("span", { className: "text-[7px] font-bold text-primary bg-primary-container px-1 py-0.5 rounded", children: act.time })
146
+ ] }),
147
+ /* @__PURE__ */ jsx("p", { className: "text-[10px] font-bold text-on-surface leading-tight mt-0.5", children: act.name }),
148
+ act.description && /* @__PURE__ */ jsx("p", { className: "text-[8px] text-on-surface-variant line-clamp-1", children: act.description })
149
+ ] })
150
+ ] }, act.id)) })
151
+ ] }) })
152
+ ] }),
153
+ /* @__PURE__ */ jsxs("div", { className: "h-12 border-t border-outline-variant/20 bg-surface flex justify-around items-center px-6 shrink-0", children: [
154
+ /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-sm text-primary", style: { fontVariationSettings: "'FILL' 1" }, children: "home" }),
155
+ /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-sm text-on-surface-variant", children: "calendar_month" }),
156
+ /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-sm text-on-surface-variant", children: "map" }),
157
+ /* @__PURE__ */ jsx("span", { className: "material-symbols-outlined text-sm text-on-surface-variant", children: "chat" })
158
+ ] }),
159
+ /* @__PURE__ */ jsx("div", { className: "h-5 bg-surface flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-24 h-1 bg-on-surface rounded-full opacity-20" }) })
160
+ ] }) })
161
+ }
162
+ )
163
+ ] });
164
+ }
165
+ export {
166
+ MobilePreview
167
+ };
@@ -0,0 +1,19 @@
1
+ type ModalSize = "sm" | "md" | "lg" | "xl" | "full";
2
+ interface ModalProps {
3
+ open: boolean;
4
+ onClose: () => void;
5
+ size?: ModalSize;
6
+ title?: string;
7
+ subtitle?: React.ReactNode;
8
+ description?: string;
9
+ headerActions?: React.ReactNode;
10
+ blocking?: boolean;
11
+ hideCloseButton?: boolean;
12
+ children: React.ReactNode;
13
+ footer?: React.ReactNode;
14
+ className?: string;
15
+ closeAriaLabel?: string;
16
+ }
17
+ declare function Modal({ open, onClose, size, title, subtitle, description, headerActions, blocking, hideCloseButton, children, footer, className, closeAriaLabel, }: ModalProps): React.ReactNode;
18
+
19
+ export { Modal, type ModalSize };
package/dist/modal.js ADDED
@@ -0,0 +1,110 @@
1
+ "use client";
2
+ import "./chunk-ORMEWXMH.js";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { useEffect, useRef } from "react";
5
+ import { IconButton } from "./icon-button";
6
+ const SIZE_CLASS = {
7
+ sm: "max-w-sm",
8
+ md: "max-w-md",
9
+ lg: "max-w-lg",
10
+ xl: "max-w-4xl",
11
+ full: "max-w-6xl"
12
+ };
13
+ function Modal({
14
+ open,
15
+ onClose,
16
+ size = "md",
17
+ title,
18
+ subtitle,
19
+ description,
20
+ headerActions,
21
+ blocking = false,
22
+ hideCloseButton = false,
23
+ children,
24
+ footer,
25
+ className = "",
26
+ closeAriaLabel = "\u0E1B\u0E34\u0E14"
27
+ }) {
28
+ const dialogRef = useRef(null);
29
+ useEffect(() => {
30
+ if (!open) return;
31
+ const dialog = dialogRef.current;
32
+ const focusables = dialog == null ? void 0 : dialog.querySelectorAll(
33
+ 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
34
+ );
35
+ if (focusables && focusables.length > 0) {
36
+ focusables[0].focus();
37
+ }
38
+ const onKey = (e) => {
39
+ if (e.key === "Escape" && !blocking) {
40
+ e.preventDefault();
41
+ onClose();
42
+ return;
43
+ }
44
+ if (e.key !== "Tab" || !dialog) return;
45
+ const els = Array.from(
46
+ dialog.querySelectorAll(
47
+ 'button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'
48
+ )
49
+ );
50
+ if (els.length === 0) return;
51
+ const first = els[0], last = els[els.length - 1];
52
+ if (e.shiftKey && document.activeElement === first) {
53
+ e.preventDefault();
54
+ last.focus();
55
+ } else if (!e.shiftKey && document.activeElement === last) {
56
+ e.preventDefault();
57
+ first.focus();
58
+ }
59
+ };
60
+ window.addEventListener("keydown", onKey);
61
+ return () => window.removeEventListener("keydown", onKey);
62
+ }, [open, blocking, onClose]);
63
+ if (!open) return null;
64
+ const handleBackdrop = () => {
65
+ if (!blocking) onClose();
66
+ };
67
+ return /* @__PURE__ */ jsxs("div", { className: "fixed inset-0 z-100 flex items-center justify-center p-4", children: [
68
+ /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/50 cursor-pointer", onClick: handleBackdrop }),
69
+ /* @__PURE__ */ jsxs(
70
+ "div",
71
+ {
72
+ ref: dialogRef,
73
+ role: "dialog",
74
+ "aria-modal": "true",
75
+ "aria-labelledby": title ? "modal-title" : void 0,
76
+ "aria-describedby": description ? "modal-description" : void 0,
77
+ className: `relative bg-surface rounded-2xl shadow-2xl w-full ${SIZE_CLASS[size]} flex flex-col max-h-[90vh] overflow-hidden ${className}`,
78
+ onClick: (e) => e.stopPropagation(),
79
+ children: [
80
+ (title || headerActions || !hideCloseButton) && /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3 px-6 py-4 border-b border-outline-variant/40 shrink-0", children: [
81
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 pt-0.5", children: [
82
+ title && /* @__PURE__ */ jsx("h3", { id: "modal-title", className: "text-lg font-bold text-on-surface truncate", children: title }),
83
+ subtitle && /* @__PURE__ */ jsx("div", { className: "text-sm text-on-surface-variant mt-1 leading-relaxed", children: subtitle }),
84
+ description && /* @__PURE__ */ jsx("p", { id: "modal-description", className: "sr-only", children: description })
85
+ ] }),
86
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [
87
+ headerActions,
88
+ !hideCloseButton && /* @__PURE__ */ jsx(
89
+ IconButton,
90
+ {
91
+ icon: "close",
92
+ variant: "ghost",
93
+ size: "sm",
94
+ onClick: onClose,
95
+ disabled: blocking,
96
+ "aria-label": closeAriaLabel
97
+ }
98
+ )
99
+ ] })
100
+ ] }),
101
+ /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-y-auto px-6 py-5", children }),
102
+ footer && /* @__PURE__ */ jsx("div", { className: "px-6 py-4 border-t border-outline-variant/40 shrink-0", children: footer })
103
+ ]
104
+ }
105
+ )
106
+ ] });
107
+ }
108
+ export {
109
+ Modal
110
+ };
@@ -0,0 +1,30 @@
1
+ interface MultiSelectOption {
2
+ value: string;
3
+ label: string;
4
+ icon?: string;
5
+ }
6
+ interface MultiSelectProps {
7
+ label?: string;
8
+ value: string[];
9
+ onChange: (value: string[]) => void;
10
+ options: MultiSelectOption[];
11
+ placeholder?: string;
12
+ searchPlaceholder?: string;
13
+ selectAllText?: string;
14
+ clearAllText?: string;
15
+ emptyText?: string;
16
+ moreLabel?: string;
17
+ required?: boolean;
18
+ error?: string;
19
+ searchable?: boolean;
20
+ maxDisplay?: number;
21
+ icon?: string;
22
+ disabled?: boolean;
23
+ name?: string;
24
+ onOpen?: () => void;
25
+ onClose?: () => void;
26
+ removePillLabel?: (label: string) => string;
27
+ }
28
+ declare function MultiSelect({ label, value, onChange, options, placeholder, searchPlaceholder, selectAllText, clearAllText, emptyText, moreLabel, required, error, searchable, maxDisplay, icon, disabled, name, onOpen, onClose, removePillLabel, }: MultiSelectProps): React.ReactNode;
29
+
30
+ export { MultiSelect, type MultiSelectOption };