@myrjfa/ui 1.1.0 → 1.1.2

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 (154) hide show
  1. package/dist/chat/ChatMain.d.ts +3 -1
  2. package/dist/chat/ChatMain.d.ts.map +1 -1
  3. package/dist/chat/ChatMain.js +174 -145
  4. package/dist/chat/ChatSidebar.js +7 -8
  5. package/dist/chat/ConversationList.d.ts.map +1 -1
  6. package/dist/chat/ConversationList.js +20 -18
  7. package/dist/chat/ExpensePanel.d.ts +4 -1
  8. package/dist/chat/ExpensePanel.d.ts.map +1 -1
  9. package/dist/chat/ExpensePanel.js +215 -195
  10. package/dist/chat/MessageBubble.d.ts +5 -3
  11. package/dist/chat/MessageBubble.d.ts.map +1 -1
  12. package/dist/chat/MessageBubble.js +185 -103
  13. package/dist/chat/MessageInput.d.ts +8 -1
  14. package/dist/chat/MessageInput.d.ts.map +1 -1
  15. package/dist/chat/MessageInput.js +182 -165
  16. package/dist/chat/MilestonePanel.d.ts +4 -1
  17. package/dist/chat/MilestonePanel.d.ts.map +1 -1
  18. package/dist/chat/MilestonePanel.js +150 -150
  19. package/dist/chat/components/ParticipantSelector.d.ts +11 -0
  20. package/dist/chat/components/ParticipantSelector.d.ts.map +1 -0
  21. package/dist/chat/components/ParticipantSelector.js +17 -0
  22. package/dist/chat/components/SplitInputs.d.ts +11 -0
  23. package/dist/chat/components/SplitInputs.d.ts.map +1 -0
  24. package/dist/chat/components/SplitInputs.js +83 -0
  25. package/dist/chat/components/SplitTypeSelector.d.ts +8 -0
  26. package/dist/chat/components/SplitTypeSelector.d.ts.map +1 -0
  27. package/dist/chat/components/SplitTypeSelector.js +13 -0
  28. package/dist/chat/dialogs/AddMemberDialog.js +30 -90
  29. package/dist/chat/dialogs/CameraDialog.js +38 -86
  30. package/dist/chat/dialogs/CreatePollDialog.d.ts +8 -0
  31. package/dist/chat/dialogs/CreatePollDialog.d.ts.map +1 -0
  32. package/dist/chat/dialogs/CreatePollDialog.js +38 -0
  33. package/dist/chat/dialogs/ExpenseAnalyticsDialog.d.ts +19 -0
  34. package/dist/chat/dialogs/ExpenseAnalyticsDialog.d.ts.map +1 -0
  35. package/dist/chat/dialogs/ExpenseAnalyticsDialog.js +52 -0
  36. package/dist/chat/dialogs/GroupInfoDialog.d.ts.map +1 -1
  37. package/dist/chat/dialogs/GroupInfoDialog.js +55 -92
  38. package/dist/chat/dialogs/GroupInfoViewDialog.js +5 -6
  39. package/dist/chat/dialogs/NewChatDialog.d.ts.map +1 -1
  40. package/dist/chat/dialogs/NewChatDialog.js +49 -113
  41. package/dist/chat/dialogs/NewGroupDialog.d.ts.map +1 -1
  42. package/dist/chat/dialogs/NewGroupDialog.js +49 -92
  43. package/dist/chat/dialogs/ParticipantsDialog.d.ts.map +1 -1
  44. package/dist/chat/dialogs/ParticipantsDialog.js +68 -118
  45. package/dist/dashboard/action-buttons.js +4 -5
  46. package/dist/dashboard/app-sidebar.js +47 -129
  47. package/dist/dashboard/card-header.js +1 -2
  48. package/dist/dashboard/dashboard-components.js +3 -5
  49. package/dist/dashboard/data-table.d.ts +2 -1
  50. package/dist/dashboard/data-table.d.ts.map +1 -1
  51. package/dist/dashboard/data-table.js +21 -33
  52. package/dist/dashboard/nav-main.js +4 -5
  53. package/dist/dashboard/nav-secondary.js +2 -25
  54. package/dist/dashboard/stats-card.js +1 -2
  55. package/dist/dashboard/table.js +8 -54
  56. package/dist/header/mobile-nav-item.js +1 -2
  57. package/dist/header/mobile-navbar.js +8 -9
  58. package/dist/header/nav-item.js +1 -2
  59. package/dist/index.d.ts +6 -0
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +7 -1
  62. package/dist/main/footer.js +5 -9
  63. package/dist/main/navbar.js +55 -138
  64. package/dist/main/paginationBar.js +12 -14
  65. package/dist/main/portfolio/portfolioItem.js +1 -2
  66. package/dist/main/portfolio/portfolioPopup.js +16 -17
  67. package/dist/main/review-page.d.ts.map +1 -1
  68. package/dist/main/review-page.js +132 -199
  69. package/dist/misc/accordion.js +8 -34
  70. package/dist/misc/alert-dialog.js +22 -55
  71. package/dist/misc/alert.js +7 -32
  72. package/dist/misc/alertdialogclaude.js +50 -125
  73. package/dist/misc/avatar.js +6 -31
  74. package/dist/misc/badge.js +4 -27
  75. package/dist/misc/button.js +4 -27
  76. package/dist/misc/card.js +12 -40
  77. package/dist/misc/carousel.js +37 -61
  78. package/dist/misc/checkbox.js +2 -25
  79. package/dist/misc/command.js +18 -49
  80. package/dist/misc/datepicker.js +66 -76
  81. package/dist/misc/dialog.js +20 -52
  82. package/dist/misc/document-upload-button.d.ts +12 -0
  83. package/dist/misc/document-upload-button.d.ts.map +1 -0
  84. package/dist/misc/document-upload-button.js +27 -0
  85. package/dist/misc/dropdown-menu.js +30 -67
  86. package/dist/misc/empty-state.d.ts +10 -0
  87. package/dist/misc/empty-state.d.ts.map +1 -0
  88. package/dist/misc/empty-state.js +5 -0
  89. package/dist/misc/faq.js +2 -3
  90. package/dist/misc/file-preview.js +43 -97
  91. package/dist/misc/filter.d.ts.map +1 -1
  92. package/dist/misc/filter.js +18 -21
  93. package/dist/misc/filterBar.js +136 -160
  94. package/dist/misc/form.js +39 -60
  95. package/dist/misc/image-compressor.d.ts +29 -0
  96. package/dist/misc/image-compressor.d.ts.map +1 -0
  97. package/dist/misc/image-compressor.js +70 -0
  98. package/dist/misc/image-cropper.d.ts +10 -0
  99. package/dist/misc/image-cropper.d.ts.map +1 -0
  100. package/dist/misc/image-cropper.js +44 -0
  101. package/dist/misc/input.d.ts.map +1 -1
  102. package/dist/misc/input.js +2 -25
  103. package/dist/misc/label.js +2 -25
  104. package/dist/misc/line-carousel.js +3 -13
  105. package/dist/misc/multiImageUploader.d.ts +2 -1
  106. package/dist/misc/multiImageUploader.d.ts.map +1 -1
  107. package/dist/misc/multiImageUploader.js +26 -3
  108. package/dist/misc/newsLetter.js +19 -79
  109. package/dist/misc/notification.d.ts +1 -2
  110. package/dist/misc/notification.d.ts.map +1 -1
  111. package/dist/misc/notification.js +89 -125
  112. package/dist/misc/pagination.js +16 -45
  113. package/dist/misc/password-eye.js +2 -3
  114. package/dist/misc/popover.d.ts.map +1 -1
  115. package/dist/misc/popover.js +8 -34
  116. package/dist/misc/progress.js +2 -25
  117. package/dist/misc/pwa-install-button.d.ts +9 -0
  118. package/dist/misc/pwa-install-button.d.ts.map +1 -0
  119. package/dist/misc/pwa-install-button.js +158 -0
  120. package/dist/misc/scroll-area.js +5 -29
  121. package/dist/misc/searchBar.js +27 -31
  122. package/dist/misc/searchBox.js +18 -22
  123. package/dist/misc/select.d.ts.map +1 -1
  124. package/dist/misc/select.js +22 -54
  125. package/dist/misc/separator.js +2 -25
  126. package/dist/misc/share.js +48 -104
  127. package/dist/misc/sheet.js +21 -53
  128. package/dist/misc/sidebar.js +112 -153
  129. package/dist/misc/skeleton.d.ts +36 -1
  130. package/dist/misc/skeleton.d.ts.map +1 -1
  131. package/dist/misc/skeleton.js +41 -27
  132. package/dist/misc/slider.js +3 -26
  133. package/dist/misc/starRating.js +5 -15
  134. package/dist/misc/stateCard.js +7 -8
  135. package/dist/misc/switch.d.ts +5 -0
  136. package/dist/misc/switch.d.ts.map +1 -0
  137. package/dist/misc/switch.js +8 -0
  138. package/dist/misc/tabs.js +8 -34
  139. package/dist/misc/textarea.js +2 -25
  140. package/dist/misc/tile.js +32 -93
  141. package/dist/misc/tooltip.js +8 -34
  142. package/dist/misc/whatsapp-help.d.ts +9 -0
  143. package/dist/misc/whatsapp-help.d.ts.map +1 -0
  144. package/dist/misc/whatsapp-help.js +13 -0
  145. package/dist/profile/socialLink.d.ts +1 -1
  146. package/dist/profile/socialLink.d.ts.map +1 -1
  147. package/dist/profile/socialLink.js +53 -69
  148. package/dist/utils/permissions.d.ts +7 -0
  149. package/dist/utils/permissions.d.ts.map +1 -0
  150. package/dist/utils/permissions.js +38 -0
  151. package/package.json +6 -4
  152. package/dist/main/portfolio/temp-page.d.ts +0 -2
  153. package/dist/main/portfolio/temp-page.d.ts.map +0 -1
  154. package/dist/main/portfolio/temp-page.js +0 -102
@@ -1,56 +1,9 @@
1
1
  'use client';
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
- return new (P || (P = Promise))(function (resolve, reject) {
16
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
- step((generator = generator.apply(thisArg, _arguments || [])).next());
20
- });
21
- };
22
- var __generator = (this && this.__generator) || function (thisArg, body) {
23
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
24
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
- function verb(n) { return function (v) { return step([n, v]); }; }
26
- function step(op) {
27
- if (f) throw new TypeError("Generator is already executing.");
28
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
- if (y = 0, t) op = [op[0] & 2, t.value];
31
- switch (op[0]) {
32
- case 0: case 1: t = op; break;
33
- case 4: _.label++; return { value: op[1], done: false };
34
- case 5: _.label++; y = op[1]; op = [0]; continue;
35
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
- default:
37
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
- if (t[2]) _.ops.pop();
42
- _.trys.pop(); continue;
43
- }
44
- op = body.call(thisArg, _);
45
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
- }
48
- };
49
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
50
3
  import { Popover, PopoverContent, PopoverTrigger } from "@radix-ui/react-popover";
51
- import { toggleAllNotification, toggleNotification } from "@myrjfa/state/dist/lib/actions";
4
+ import { getNotifications, toggleAllNotification, toggleNotification } from "@myrjfa/state/dist/lib/actions/actions";
52
5
  import { formatTimestamp } from "@myrjfa/state/dist/lib/utils";
53
- import { Bell } from "lucide-react";
6
+ import { Bell, MessageCircle, CheckCircle2, Receipt, Users, AlertCircle, Megaphone, Briefcase, ShieldCheck, ShieldX, Package, ClipboardList } from "lucide-react";
54
7
  import { useRouter } from "next/navigation";
55
8
  import { useEffect, useState } from "react";
56
9
  import { FaSpinner } from "react-icons/fa6";
@@ -59,89 +12,100 @@ import { Button } from "./button";
59
12
  import { Card, CardHeader, CardTitle } from "./card";
60
13
  import { ScrollArea } from "./scroll-area";
61
14
  import { MobileNavItem } from "../header/mobile-nav-item";
62
- var NOTIF_LIMIT_FOR_BELL = 10;
63
- var getNotificationIcon = function (type) {
15
+ const NOTIF_LIMIT_FOR_BELL = 10;
16
+ const getNotificationIcon = (notif) => {
17
+ const type = notif.type || "general";
64
18
  switch (type) {
65
- case "false":
66
- return _jsx("div", { className: "w-2 h-2 rounded-full bg-green-500 mt-2" });
19
+ case "new_message":
20
+ return _jsx(MessageCircle, { className: "w-4 h-4 text-blue-500 mt-0.5 flex-shrink-0" });
21
+ case "milestone_completed":
22
+ return _jsx(CheckCircle2, { className: "w-4 h-4 text-green-500 mt-0.5 flex-shrink-0" });
23
+ case "expense_added":
24
+ return _jsx(Receipt, { className: "w-4 h-4 text-orange-500 mt-0.5 flex-shrink-0" });
25
+ case "group_invite":
26
+ return _jsx(Users, { className: "w-4 h-4 text-purple-500 mt-0.5 flex-shrink-0" });
27
+ case "mention":
28
+ return _jsx(Megaphone, { className: "w-4 h-4 text-yellow-500 mt-0.5 flex-shrink-0" });
29
+ case "application_received":
30
+ case "application_status":
31
+ case "application_shortlisted":
32
+ return _jsx(Briefcase, { className: "w-4 h-4 text-indigo-500 mt-0.5 flex-shrink-0" });
33
+ case "id_verified":
34
+ return _jsx(ShieldCheck, { className: "w-4 h-4 text-emerald-500 mt-0.5 flex-shrink-0" });
35
+ case "id_rejected":
36
+ return _jsx(ShieldX, { className: "w-4 h-4 text-red-500 mt-0.5 flex-shrink-0" });
37
+ case "package_enquiry":
38
+ return _jsx(Package, { className: "w-4 h-4 text-cyan-500 mt-0.5 flex-shrink-0" });
39
+ case "opportunity_assigned":
40
+ return _jsx(ClipboardList, { className: "w-4 h-4 text-amber-500 mt-0.5 flex-shrink-0" });
41
+ case "system":
42
+ return _jsx(AlertCircle, { className: "w-4 h-4 text-gray-500 mt-0.5 flex-shrink-0" });
67
43
  default:
68
- return _jsx("div", { className: "w-2 h-2 rounded-full bg-gray-500 mt-2" });
44
+ return _jsx("div", { className: `w-2.5 h-2.5 rounded-full mt-1.5 flex-shrink-0 ${!notif.read ? "bg-blue-500" : "bg-gray-300"}` });
69
45
  }
70
46
  };
71
- export function NotificationBell(_a) {
72
- var _this = this;
73
- var id = _a.id, navItemColor = _a.navItemColor;
74
- var _b = useState([]), notifs = _b[0], setNotifs = _b[1];
75
- var _c = useState(0), unreadCount = _c[0], setUnreadCount = _c[1];
76
- var _d = useState(null), loadingNotifId = _d[0], setLoadingNotifId = _d[1];
77
- var router = useRouter();
78
- useEffect(function () {
79
- var fetchData = function () { return __awaiter(_this, void 0, void 0, function () {
80
- return __generator(this, function (_a) {
81
- if (!id)
82
- return [2 /*return*/];
83
- return [2 /*return*/];
84
- });
85
- }); };
86
- fetchData();
87
- }, [id]);
88
- var handleMarkAllNotifRead = function () { return __awaiter(_this, void 0, void 0, function () {
89
- var response;
90
- return __generator(this, function (_a) {
91
- switch (_a.label) {
92
- case 0: return [4 /*yield*/, toggleAllNotification(true)];
93
- case 1:
94
- response = _a.sent();
95
- if (!(response === null || response === void 0 ? void 0 : response.error)) return [3 /*break*/, 3];
96
- return [4 /*yield*/, showAlert(response.error)];
97
- case 2:
98
- _a.sent();
99
- return [3 /*break*/, 4];
100
- case 3:
101
- setNotifs(notifs.map(function (notif) { return (__assign(__assign({}, notif), { read: true })); }));
102
- setUnreadCount(0);
103
- console.log("marked");
104
- _a.label = 4;
105
- case 4: return [2 /*return*/];
47
+ export function NotificationBell({ navItemColor }) {
48
+ const [notifs, setNotifs] = useState([]);
49
+ const [unreadCount, setUnreadCount] = useState(0);
50
+ const [loadingNotifId, setLoadingNotifId] = useState(null);
51
+ const [isOpen, setIsOpen] = useState(false);
52
+ const router = useRouter();
53
+ const fetchData = async () => {
54
+ try {
55
+ const response = await getNotifications(NOTIF_LIMIT_FOR_BELL);
56
+ if (response && !response.error) {
57
+ setNotifs(response.notifs || []);
58
+ setUnreadCount(response.unreadCount || 0);
106
59
  }
107
- });
108
- }); };
109
- var handleNotifClick = function (notif) { return __awaiter(_this, void 0, void 0, function () {
110
- var response, url;
111
- return __generator(this, function (_a) {
112
- switch (_a.label) {
113
- case 0:
114
- if (loadingNotifId)
115
- return [2 /*return*/];
116
- if (!!notif.read) return [3 /*break*/, 4];
117
- setLoadingNotifId(notif._id);
118
- return [4 /*yield*/, toggleNotification(notif._id, true)];
119
- case 1:
120
- response = _a.sent();
121
- if (!(response === null || response === void 0 ? void 0 : response.error)) return [3 /*break*/, 3];
122
- return [4 /*yield*/, showAlert(response.error)];
123
- case 2:
124
- _a.sent();
125
- return [3 /*break*/, 4];
126
- case 3:
127
- setNotifs(notifs.map(function (n) {
128
- return n._id === notif._id ? __assign(__assign({}, n), { read: true }) : n;
129
- }));
130
- setUnreadCount(unreadCount - 1);
131
- console.log("read notification");
132
- _a.label = 4;
133
- case 4:
134
- setLoadingNotifId(null);
135
- url = notif.url;
136
- return [2 /*return*/, url && router.push(url)];
60
+ }
61
+ catch (err) {
62
+ console.error("Failed to fetch notifications:", err);
63
+ }
64
+ };
65
+ // Re-fetch when popover opens
66
+ useEffect(() => {
67
+ if (isOpen)
68
+ fetchData();
69
+ }, [isOpen]);
70
+ const handleMarkAllNotifRead = async () => {
71
+ const response = await toggleAllNotification(true);
72
+ if (response === null || response === void 0 ? void 0 : response.error) {
73
+ await showAlert(response.error);
74
+ }
75
+ else {
76
+ setNotifs(notifs.map((notif) => ({
77
+ ...notif, read: true
78
+ })));
79
+ setUnreadCount(0);
80
+ }
81
+ };
82
+ const handleNotifClick = async (notif) => {
83
+ if (loadingNotifId)
84
+ return;
85
+ if (!notif.read) {
86
+ setLoadingNotifId(notif._id);
87
+ const response = await toggleNotification(notif._id, true);
88
+ if (response === null || response === void 0 ? void 0 : response.error) {
89
+ await showAlert(response.error);
137
90
  }
138
- });
139
- }); };
91
+ else {
92
+ setNotifs(notifs.map((n) => n._id === notif._id ? { ...n, read: true } : n));
93
+ setUnreadCount(Math.max(0, unreadCount - 1));
94
+ }
95
+ }
96
+ setLoadingNotifId(null);
97
+ // Navigate to the link or URL
98
+ const url = notif.link;
99
+ if (url) {
100
+ setIsOpen(false);
101
+ router.push(url);
102
+ }
103
+ };
140
104
  if (notifs == null)
141
- return _jsx(FaSpinner, {});
142
- return _jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("div", { className: "relative cursor-pointer ".concat(navItemColor, " transition-colors"), "aria-label": "Notification Bell", children: [_jsx(Bell, { className: "h-5 w-5" }), unreadCount > 0 && (_jsx("span", { className: "absolute -top-1.5 -right-1.5 flex h-4 min-w-[1rem] items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold text-white", children: unreadCount > 99 ? "99+" : unreadCount }))] }) }), _jsx(PopoverContent, { className: "w-96 p-0 mt-3 bg-white rounded-lg shadow-lg", align: "end", sideOffset: 5, children: _jsxs(Card, { className: "border-0 shadow-none", children: [_jsx(CardHeader, { className: "px-8", children: _jsxs("div", { className: "flex justify-between items-center", children: [_jsx(CardTitle, { className: "text-lg font-medium", children: "Notifications" }), notifs.length != 0 && _jsx(Button, { variant: "ghost", size: "sm", className: "text-xs text-blue-600 hover:text-blue-800", onClick: function () {
143
- handleMarkAllNotifRead();
144
- }, children: "Mark all as read" })] }) }), _jsx(ScrollArea, { className: "h-80 w-full rounded-md", children: _jsx("div", { className: "px-2", children: notifs.length === 0 ? (_jsx("div", { className: "text-center text-sm text-gray-500 py-30", children: "You're all caught up \uD83C\uDF89" })) : (notifs.map(function (notif) { return (_jsxs("div", { className: "flex items-start gap-3 p-2 pb-1 mt-1 hover:bg-gray-50 rounded-lg transition-colors ".concat(!notif.read ? "bg-blue-50/50" : "", " ").concat(loadingNotifId === notif._id ? "opacity-50 pointer-events-none" : ""), onClick: function () { return handleNotifClick(notif); }, children: [_jsx("div", { className: "flex-shrink-0 mt-1", children: getNotificationIcon(notif.read.toString()) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("p", { className: "text-sm ".concat(!notif.read ? "font-medium" : "text-gray-600"), children: notif.message }), _jsx("p", { className: "text-xs text-gray-500 mt-1", children: formatTimestamp(notif.timestamp) })] }), !notif.read && (_jsx("div", { className: "flex-shrink-0", children: _jsx("div", { className: "w-2 h-2 rounded-full bg-blue-500" }) }))] }, notif._id)); })) }) }), notifs.length > NOTIF_LIMIT_FOR_BELL && _jsx("div", { className: "px-3 pt-2 border-t border-gray-100", children: _jsx(Button, { variant: "ghost", className: "w-full text-blue-600 hover:text-blue-800 hover:bg-blue-50 text-sm", onClick: function () { router.push("/inbox"); }, children: "View all notifications" }) })] }) })] });
105
+ return _jsx(FaSpinner, { className: "animate-spin" });
106
+ return _jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs("div", { className: `relative cursor-pointer ${navItemColor} transition-colors`, "aria-label": "Notification Bell", children: [_jsx(Bell, { className: "h-5 w-5" }), unreadCount > 0 && (_jsx("span", { className: "absolute -top-1.5 -right-1.5 flex h-4 min-w-[1rem] items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold text-white animate-pulse", children: unreadCount > 99 ? "99+" : unreadCount }))] }) }), _jsx(PopoverContent, { className: "w-96 p-0 mt-3 bg-white dark:bg-gray-900 rounded-xl shadow-xl border border-gray-100 dark:border-gray-800", align: "end", sideOffset: 5, children: _jsxs(Card, { className: "border-0 shadow-none bg-transparent", children: [_jsx(CardHeader, { className: "px-5 pb-2", children: _jsxs("div", { className: "flex justify-between items-center", children: [_jsx(CardTitle, { className: "text-base font-semibold", children: "Notifications" }), notifs.length > 0 && unreadCount > 0 && (_jsx(Button, { variant: "ghost", size: "sm", className: "text-xs text-teal-600 hover:text-teal-800 dark:text-teal-400", onClick: handleMarkAllNotifRead, children: "Mark all as read" }))] }) }), _jsx(ScrollArea, { className: "h-80 w-full", children: _jsx("div", { className: "px-2 pb-2", children: notifs.length === 0 ? (_jsxs("div", { className: "flex flex-col items-center justify-center py-16 text-gray-400", children: [_jsx(Bell, { className: "w-10 h-10 mb-3 opacity-30" }), _jsx("p", { className: "text-sm", children: "You're all caught up \uD83C\uDF89" })] })) : (notifs.map((notif) => (_jsxs("div", { className: `flex items-start gap-3 p-3 rounded-lg cursor-pointer transition-all duration-200 hover:bg-gray-50 dark:hover:bg-gray-800/50 ${!notif.read
107
+ ? "bg-teal-50/50 dark:bg-teal-900/10 border-l-2 border-teal-500"
108
+ : "border-l-2 border-transparent"} ${loadingNotifId === notif._id ? "opacity-50 pointer-events-none" : ""}`, onClick: () => handleNotifClick(notif), children: [_jsx("div", { className: "flex-shrink-0 mt-0.5", children: getNotificationIcon(notif) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("p", { className: `text-sm leading-snug ${!notif.read ? "font-medium text-gray-900 dark:text-white" : "text-gray-600 dark:text-gray-400"}`, children: notif.message }), _jsxs("div", { className: "flex items-center gap-2 mt-1", children: [_jsx("p", { className: "text-[11px] text-gray-400", children: notif.timestamp ? formatTimestamp(notif.timestamp) : "" }), notif.type && notif.type !== "general" && (_jsx("span", { className: "text-[10px] px-1.5 py-0.5 rounded-full bg-gray-100 dark:bg-gray-800 text-gray-500 dark:text-gray-400", children: notif.type.replace(/_/g, " ") }))] })] }), !notif.read && (_jsx("div", { className: "flex-shrink-0 mt-2", children: _jsx("div", { className: "w-2 h-2 rounded-full bg-teal-500" }) }))] }, notif._id)))) }) }), notifs.length > NOTIF_LIMIT_FOR_BELL && (_jsx("div", { className: "px-3 py-2 border-t border-gray-100 dark:border-gray-800", children: _jsx(Button, { variant: "ghost", className: "w-full text-teal-600 hover:text-teal-800 hover:bg-teal-50 dark:text-teal-400 dark:hover:bg-teal-900/20 text-sm", onClick: () => { setIsOpen(false); router.push("/inbox"); }, children: "View all notifications" }) }))] }) })] });
145
109
  }
146
110
  export function MobileNotificationBell() {
147
111
  return (_jsx(MobileNavItem, { icon: _jsx("div", { className: "relative", children: _jsx(Bell, { className: "h-5 w-5" }) }), label: "Notifications", href: "/inbox" }));
@@ -1,59 +1,30 @@
1
- var __assign = (this && this.__assign) || function () {
2
- __assign = Object.assign || function(t) {
3
- for (var s, i = 1, n = arguments.length; i < n; i++) {
4
- s = arguments[i];
5
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
- t[p] = s[p];
7
- }
8
- return t;
9
- };
10
- return __assign.apply(this, arguments);
11
- };
12
- var __rest = (this && this.__rest) || function (s, e) {
13
- var t = {};
14
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
15
- t[p] = s[p];
16
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
17
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
18
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
19
- t[p[i]] = s[p[i]];
20
- }
21
- return t;
22
- };
23
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
24
2
  import { cn } from "@myrjfa/state/dist/lib/utils";
25
3
  import { ChevronLeftIcon, ChevronRightIcon, MoreHorizontalIcon, } from "lucide-react";
26
4
  import Link from "next/link";
27
5
  import { buttonVariants } from "./button";
28
- function Pagination(_a) {
29
- var className = _a.className, props = __rest(_a, ["className"]);
30
- return (_jsx("nav", __assign({ role: "navigation", "aria-label": "pagination", "data-slot": "pagination", className: cn("mx-auto flex w-full justify-center", className) }, props)));
6
+ function Pagination({ className, ...props }) {
7
+ return (_jsx("nav", { role: "navigation", "aria-label": "pagination", "data-slot": "pagination", className: cn("mx-auto flex w-full justify-center", className), ...props }));
31
8
  }
32
- function PaginationContent(_a) {
33
- var className = _a.className, props = __rest(_a, ["className"]);
34
- return (_jsx("ul", __assign({ "data-slot": "pagination-content", className: cn("flex flex-row items-center gap-1", className) }, props)));
9
+ function PaginationContent({ className, ...props }) {
10
+ return (_jsx("ul", { "data-slot": "pagination-content", className: cn("flex flex-row items-center gap-1", className), ...props }));
35
11
  }
36
- function PaginationItem(_a) {
37
- var props = __rest(_a, []);
38
- return _jsx("li", __assign({ "data-slot": "pagination-item" }, props));
12
+ function PaginationItem({ ...props }) {
13
+ return _jsx("li", { "data-slot": "pagination-item", ...props });
39
14
  }
40
- function PaginationLink(_a) {
41
- var className = _a.className, isActive = _a.isActive, _b = _a.size, size = _b === void 0 ? "icon" : _b, props = __rest(_a, ["className", "isActive", "size"]);
42
- return (_jsx(Link, __assign({ "aria-current": isActive ? "page" : undefined, "data-slot": "pagination-link", "data-active": isActive, className: cn(buttonVariants({
15
+ function PaginationLink({ className, isActive, size = "icon", ...props }) {
16
+ return (_jsx(Link, { "aria-current": isActive ? "page" : undefined, "data-slot": "pagination-link", "data-active": isActive, className: cn(buttonVariants({
43
17
  variant: isActive ? "outline" : "ghost",
44
- size: size,
45
- }), className) }, props)));
18
+ size,
19
+ }), className), ...props }));
46
20
  }
47
- function PaginationPrevious(_a) {
48
- var className = _a.className, props = __rest(_a, ["className"]);
49
- return (_jsxs(PaginationLink, __assign({ "aria-label": "Go to previous page", size: "default", className: cn("gap-1 px-2.5 sm:pl-2.5", className) }, props, { children: [_jsx(ChevronLeftIcon, {}), _jsx("span", { className: "hidden sm:block", children: "Previous" })] })));
21
+ function PaginationPrevious({ className, ...props }) {
22
+ return (_jsxs(PaginationLink, { "aria-label": "Go to previous page", size: "default", className: cn("gap-1 px-2.5 sm:pl-2.5", className), ...props, children: [_jsx(ChevronLeftIcon, {}), _jsx("span", { className: "hidden sm:block", children: "Previous" })] }));
50
23
  }
51
- function PaginationNext(_a) {
52
- var className = _a.className, props = __rest(_a, ["className"]);
53
- return (_jsxs(PaginationLink, __assign({ "aria-label": "Go to next page", size: "default", className: cn("gap-1 px-2.5 sm:pr-2.5", className) }, props, { children: [_jsx("span", { className: "hidden sm:block", children: "Next" }), _jsx(ChevronRightIcon, {})] })));
24
+ function PaginationNext({ className, ...props }) {
25
+ return (_jsxs(PaginationLink, { "aria-label": "Go to next page", size: "default", className: cn("gap-1 px-2.5 sm:pr-2.5", className), ...props, children: [_jsx("span", { className: "hidden sm:block", children: "Next" }), _jsx(ChevronRightIcon, {})] }));
54
26
  }
55
- function PaginationEllipsis(_a) {
56
- var className = _a.className, props = __rest(_a, ["className"]);
57
- return (_jsxs("span", __assign({ "aria-hidden": true, "data-slot": "pagination-ellipsis", className: cn("flex size-9 items-center justify-center", className) }, props, { children: [_jsx(MoreHorizontalIcon, { className: "size-4" }), _jsx("span", { className: "sr-only", children: "More pages" })] })));
27
+ function PaginationEllipsis({ className, ...props }) {
28
+ return (_jsxs("span", { "aria-hidden": true, "data-slot": "pagination-ellipsis", className: cn("flex size-9 items-center justify-center", className), ...props, children: [_jsx(MoreHorizontalIcon, { className: "size-4" }), _jsx("span", { className: "sr-only", children: "More pages" })] }));
58
29
  }
59
30
  export { Pagination, PaginationContent, PaginationLink, PaginationItem, PaginationPrevious, PaginationNext, PaginationEllipsis, };
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { EyeIcon, EyeOffIcon } from 'lucide-react';
3
3
  import { Button } from './button';
4
- export default function PasswordEye(_a) {
5
- var showPassword = _a.showPassword, setShowPassword = _a.setShowPassword;
6
- return (_jsx(Button, { type: 'button', variant: "ghost", onMouseDown: function () { return setShowPassword(function (prev) { return !prev; }); }, onTouchStart: function () { return setShowPassword(function (prev) { return !prev; }); }, onTouchEnd: function () { return setShowPassword(function (prev) { return !prev; }); }, className: "absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500", children: showPassword ? _jsx(EyeOffIcon, {}) : _jsx(EyeIcon, {}) }));
4
+ export default function PasswordEye({ showPassword, setShowPassword }) {
5
+ return (_jsx(Button, { type: 'button', variant: "ghost", onMouseDown: () => setShowPassword(prev => !prev), onTouchStart: () => setShowPassword(prev => !prev), onTouchEnd: () => setShowPassword(prev => !prev), className: "absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-500", children: showPassword ? _jsx(EyeOffIcon, {}) : _jsx(EyeIcon, {}) }));
7
6
  }
@@ -1 +1 @@
1
- {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../src/misc/popover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAI3D,iBAAS,OAAO,CAAC,EACf,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,IAAI,CAAC,2CAEpD;AAED,iBAAS,cAAc,CAAC,EACtB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,2CAEvD;AAED,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,KAAgB,EAChB,UAAc,EACd,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,2CAevD;AAED,iBAAS,aAAa,CAAC,EACrB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,MAAM,CAAC,2CAEtD;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA"}
1
+ {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../src/misc/popover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,gBAAgB,MAAM,yBAAyB,CAAA;AAI3D,iBAAS,OAAO,CAAC,EACf,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,IAAI,CAAC,2CAEpD;AAED,iBAAS,cAAc,CAAC,EACtB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,2CAEvD;AAED,iBAAS,cAAc,CAAC,EACtB,SAAS,EACT,KAAgB,EAChB,UAAc,EACd,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,OAAO,CAAC,2CAgBvD;AAED,iBAAS,aAAa,CAAC,EACrB,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,gBAAgB,CAAC,MAAM,CAAC,2CAEtD;AAED,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,CAAA"}
@@ -1,43 +1,17 @@
1
1
  "use client";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __rest = (this && this.__rest) || function (s, e) {
14
- var t = {};
15
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16
- t[p] = s[p];
17
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
18
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20
- t[p[i]] = s[p[i]];
21
- }
22
- return t;
23
- };
24
2
  import { jsx as _jsx } from "react/jsx-runtime";
25
3
  import * as PopoverPrimitive from "@radix-ui/react-popover";
26
4
  import { cn } from "@myrjfa/state/dist/lib/utils";
27
- function Popover(_a) {
28
- var props = __rest(_a, []);
29
- return _jsx(PopoverPrimitive.Root, __assign({ "data-slot": "popover" }, props));
5
+ function Popover({ ...props }) {
6
+ return _jsx(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
30
7
  }
31
- function PopoverTrigger(_a) {
32
- var props = __rest(_a, []);
33
- return _jsx(PopoverPrimitive.Trigger, __assign({ "data-slot": "popover-trigger" }, props));
8
+ function PopoverTrigger({ ...props }) {
9
+ return _jsx(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
34
10
  }
35
- function PopoverContent(_a) {
36
- var className = _a.className, _b = _a.align, align = _b === void 0 ? "center" : _b, _c = _a.sideOffset, sideOffset = _c === void 0 ? 4 : _c, props = __rest(_a, ["className", "align", "sideOffset"]);
37
- return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, __assign({ "data-slot": "popover-content", align: align, sideOffset: sideOffset, className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-full min-w-[12rem] rounded-md border p-4 shadow-md outline-hidden", className) }, props)) }));
11
+ function PopoverContent({ className, align = "center", sideOffset = 4, ...props }) {
12
+ return (_jsx(PopoverPrimitive.Portal, { children: _jsx(PopoverPrimitive.Content, { "data-slot": "popover-content", align: align, sideOffset: sideOffset, className: cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-[310] w-full min-w-[12rem] rounded-md border p-4 shadow-md outline-hidden touch-pan-y overflow-y-auto pointer-events-auto", className), onWheel: (e) => e.stopPropagation(), ...props }) }));
38
13
  }
39
- function PopoverAnchor(_a) {
40
- var props = __rest(_a, []);
41
- return _jsx(PopoverPrimitive.Anchor, __assign({ "data-slot": "popover-anchor" }, props));
14
+ function PopoverAnchor({ ...props }) {
15
+ return _jsx(PopoverPrimitive.Anchor, { "data-slot": "popover-anchor", ...props });
42
16
  }
43
17
  export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
@@ -1,31 +1,8 @@
1
1
  "use client";
2
- var __assign = (this && this.__assign) || function () {
3
- __assign = Object.assign || function(t) {
4
- for (var s, i = 1, n = arguments.length; i < n; i++) {
5
- s = arguments[i];
6
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
- t[p] = s[p];
8
- }
9
- return t;
10
- };
11
- return __assign.apply(this, arguments);
12
- };
13
- var __rest = (this && this.__rest) || function (s, e) {
14
- var t = {};
15
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
16
- t[p] = s[p];
17
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
18
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
19
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
20
- t[p[i]] = s[p[i]];
21
- }
22
- return t;
23
- };
24
2
  import { jsx as _jsx } from "react/jsx-runtime";
25
3
  import * as ProgressPrimitive from "@radix-ui/react-progress";
26
4
  import { cn } from "@myrjfa/state/dist/lib/utils";
27
- function Progress(_a) {
28
- var className = _a.className, value = _a.value, props = __rest(_a, ["className", "value"]);
29
- return (_jsx(ProgressPrimitive.Root, __assign({ "data-slot": "progress", className: cn("bg-primary/20 relative h-2 w-full overflow-hidden rounded-full", className) }, props, { children: _jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: "bg-primary h-full w-full flex-1 transition-all", style: { transform: "translateX(-".concat(100 - (value || 0), "%)") } }) })));
5
+ function Progress({ className, value, ...props }) {
6
+ return (_jsx(ProgressPrimitive.Root, { "data-slot": "progress", className: cn("bg-primary/20 relative h-2 w-full overflow-hidden rounded-full", className), ...props, children: _jsx(ProgressPrimitive.Indicator, { "data-slot": "progress-indicator", className: "bg-primary h-full w-full flex-1 transition-all", style: { transform: `translateX(-${100 - (value || 0)}%)` } }) }));
30
7
  }
31
8
  export { Progress };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * #9 — Floating PWA Install Button
3
+ * Premium banner aligned with Trippeaze brand.
4
+ * - Only shows on mobile (beforeinstallprompt)
5
+ * - Auto-hides after 10 s
6
+ * - Animated entrance / exit
7
+ */
8
+ export declare function PwaInstallButton(): import("react/jsx-runtime").JSX.Element | null;
9
+ //# sourceMappingURL=pwa-install-button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pwa-install-button.d.ts","sourceRoot":"","sources":["../../src/misc/pwa-install-button.tsx"],"names":[],"mappings":"AAKA;;;;;;GAMG;AACH,wBAAgB,gBAAgB,mDA0M/B"}
@@ -0,0 +1,158 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import Image from 'next/image';
5
+ /**
6
+ * #9 — Floating PWA Install Button
7
+ * Premium banner aligned with Trippeaze brand.
8
+ * - Only shows on mobile (beforeinstallprompt)
9
+ * - Auto-hides after 10 s
10
+ * - Animated entrance / exit
11
+ */
12
+ export function PwaInstallButton() {
13
+ const [show, setShow] = useState(false);
14
+ const [hiding, setHiding] = useState(false);
15
+ const promptRef = useRef(null);
16
+ const timerRef = useRef(null);
17
+ const dismiss = () => {
18
+ setHiding(true);
19
+ setTimeout(() => setShow(false), 350);
20
+ };
21
+ useEffect(() => {
22
+ const isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
23
+ if (!isMobile)
24
+ return;
25
+ const handler = (e) => {
26
+ e.preventDefault();
27
+ promptRef.current = e;
28
+ setShow(true);
29
+ setHiding(false);
30
+ timerRef.current = setTimeout(dismiss, 10000);
31
+ };
32
+ window.addEventListener('beforeinstallprompt', handler);
33
+ return () => {
34
+ window.removeEventListener('beforeinstallprompt', handler);
35
+ if (timerRef.current)
36
+ clearTimeout(timerRef.current);
37
+ };
38
+ }, []);
39
+ const handleInstall = async () => {
40
+ if (!promptRef.current)
41
+ return;
42
+ if (timerRef.current)
43
+ clearTimeout(timerRef.current);
44
+ promptRef.current.prompt();
45
+ const { outcome } = await promptRef.current.userChoice;
46
+ if (outcome === 'accepted')
47
+ dismiss();
48
+ };
49
+ if (!show)
50
+ return null;
51
+ return (_jsxs(_Fragment, { children: [_jsx("style", { children: `
52
+ @keyframes tpz-slide-up {
53
+ from { opacity: 0; transform: translateX(-50%) translateY(20px); }
54
+ to { opacity: 1; transform: translateX(-50%) translateY(0); }
55
+ }
56
+ @keyframes tpz-slide-down {
57
+ from { opacity: 1; transform: translateX(-50%) translateY(0); }
58
+ to { opacity: 0; transform: translateX(-50%) translateY(20px); }
59
+ }
60
+ @keyframes tpz-orbit {
61
+ from { transform: rotate(0deg) translateX(22px) rotate(0deg); }
62
+ to { transform: rotate(360deg) translateX(22px) rotate(-360deg); }
63
+ }
64
+ @keyframes tpz-shimmer {
65
+ 0% { background-position: -200% center; }
66
+ 100% { background-position: 200% center; }
67
+ }
68
+ ` }), _jsxs("div", { style: {
69
+ position: 'fixed',
70
+ bottom: '88px',
71
+ left: '50%',
72
+ transform: 'translateX(-50%)',
73
+ zIndex: 9999,
74
+ animation: hiding
75
+ ? 'tpz-slide-down 0.35s cubic-bezier(.4,0,.2,1) forwards'
76
+ : 'tpz-slide-up 0.4s cubic-bezier(.16,1,.3,1) forwards',
77
+ // Prevent layout shift during animation
78
+ willChange: 'transform, opacity',
79
+ }, children: [_jsx("div", { style: {
80
+ position: 'absolute',
81
+ inset: '-3px',
82
+ borderRadius: '9999px',
83
+ background: 'linear-gradient(135deg, #f97316, #fb923c, #22d3ee, #0891b2)',
84
+ opacity: 0.3,
85
+ filter: 'blur(8px)',
86
+ zIndex: 0,
87
+ } }), _jsxs("button", { onClick: handleInstall, style: {
88
+ position: 'relative',
89
+ zIndex: 1,
90
+ display: 'flex',
91
+ alignItems: 'center',
92
+ gap: '10px',
93
+ padding: '10px 18px 10px 12px',
94
+ borderRadius: '9999px',
95
+ border: '1px solid rgba(0,0,0,0.06)',
96
+ background: 'linear-gradient(135deg, #ffffff 0%, #f8fafc 100%)',
97
+ boxShadow: '0 12px 32px rgba(0,0,0,0.12), inset 0 1px 0 rgba(255,255,255,0.9)',
98
+ cursor: 'pointer',
99
+ whiteSpace: 'nowrap',
100
+ backdropFilter: 'blur(8px)',
101
+ }, children: [_jsx("div", { style: {
102
+ width: '36px',
103
+ height: '36px',
104
+ borderRadius: '50%',
105
+ overflow: 'hidden',
106
+ flexShrink: 0,
107
+ boxShadow: '0 2px 8px rgba(249,115,22,0.2)',
108
+ }, children: _jsx(Image, { src: "/images/logoicon.webp", alt: "Trippeaze", width: 36, height: 36, style: { objectFit: 'cover' } }) }), _jsxs("div", { style: { display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: '1px' }, children: [_jsx("span", { style: {
109
+ fontSize: '11px',
110
+ fontWeight: 500,
111
+ letterSpacing: '0.08em',
112
+ textTransform: 'uppercase',
113
+ color: '#64748b',
114
+ lineHeight: 1,
115
+ }, children: "Get the app" }), _jsx("span", { style: {
116
+ fontSize: '15px',
117
+ fontWeight: 700,
118
+ letterSpacing: '-0.01em',
119
+ lineHeight: 1.2,
120
+ // Shimmer text using logo colors
121
+ background: 'linear-gradient(90deg, #fb923c, #fbbf24, #22d3ee, #fb923c)',
122
+ backgroundSize: '200% auto',
123
+ WebkitBackgroundClip: 'text',
124
+ WebkitTextFillColor: 'transparent',
125
+ backgroundClip: 'text',
126
+ animation: 'tpz-shimmer 3s linear infinite',
127
+ }, children: "Install Trippeaze" })] }), _jsx("div", { style: {
128
+ marginLeft: '4px',
129
+ width: '28px',
130
+ height: '28px',
131
+ borderRadius: '50%',
132
+ background: 'linear-gradient(135deg, #f97316, #dc2626)',
133
+ display: 'flex',
134
+ alignItems: 'center',
135
+ justifyContent: 'center',
136
+ flexShrink: 0,
137
+ boxShadow: '0 2px 8px rgba(249,115,22,0.5)',
138
+ }, children: _jsx("svg", { width: "14", height: "14", viewBox: "0 0 14 14", fill: "none", children: _jsx("path", { d: "M7 2v7M4 6.5l3 3 3-3M2.5 11h9", stroke: "white", strokeWidth: "1.7", strokeLinecap: "round", strokeLinejoin: "round" }) }) })] }), _jsx("button", { onClick: (e) => { e.stopPropagation(); dismiss(); }, "aria-label": "Dismiss", style: {
139
+ position: 'absolute',
140
+ top: '-6px',
141
+ right: '-6px',
142
+ zIndex: 2,
143
+ width: '20px',
144
+ height: '20px',
145
+ borderRadius: '50%',
146
+ background: '#ffffff',
147
+ border: '1px solid rgba(0,0,0,0.1)',
148
+ color: '#64748b',
149
+ fontSize: '11px',
150
+ lineHeight: '20px',
151
+ textAlign: 'center',
152
+ cursor: 'pointer',
153
+ display: 'flex',
154
+ alignItems: 'center',
155
+ justifyContent: 'center',
156
+ boxShadow: '0 2px 6px rgba(0,0,0,0.1)',
157
+ }, children: "\u2715" })] })] }));
158
+ }