@dreamtree-org/twreact-ui 1.3.0 → 1.3.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.
- package/README.md +179 -10
- package/ai-skills/dreamtree-ui.md +71 -12
- package/dist/ai-schema.json +452 -17
- package/dist/components/core/Accordion.d.ts.map +1 -1
- package/dist/components/core/Button.d.ts.map +1 -1
- package/dist/components/core/Checkbox.d.ts.map +1 -1
- package/dist/components/core/ColorPicker.d.ts.map +1 -1
- package/dist/components/core/DatePicker.d.ts.map +1 -1
- package/dist/components/core/DateRangePicker.d.ts.map +1 -1
- package/dist/components/core/Form.d.ts.map +1 -1
- package/dist/components/core/Input.d.ts.map +1 -1
- package/dist/components/core/LocationPicker.d.ts.map +1 -1
- package/dist/components/core/Popover.d.ts +4 -0
- package/dist/components/core/Popover.d.ts.map +1 -0
- package/dist/components/core/PriceRangePicker.d.ts.map +1 -1
- package/dist/components/core/ProgressBar.d.ts.map +1 -1
- package/dist/components/core/Radio.d.ts.map +1 -1
- package/dist/components/core/Rate.d.ts.map +1 -1
- package/dist/components/core/Select.d.ts.map +1 -1
- package/dist/components/core/Skeleton.d.ts.map +1 -1
- package/dist/components/core/Slider.d.ts +4 -0
- package/dist/components/core/Slider.d.ts.map +1 -0
- package/dist/components/core/SpeechToText.d.ts.map +1 -1
- package/dist/components/core/Switch.d.ts.map +1 -1
- package/dist/components/core/Table/ActionMenu.d.ts.map +1 -1
- package/dist/components/core/Table/ColumnMenu.d.ts +2 -1
- package/dist/components/core/Table/ColumnMenu.d.ts.map +1 -1
- package/dist/components/core/Table/MobileCard.d.ts +2 -2
- package/dist/components/core/Table/MobileCard.d.ts.map +1 -1
- package/dist/components/core/Table/Table.d.ts.map +1 -1
- package/dist/components/core/Table/TableRow.d.ts +4 -2
- package/dist/components/core/Table/TableRow.d.ts.map +1 -1
- package/dist/components/core/Tabs.d.ts.map +1 -1
- package/dist/components/core/Textarea.d.ts +4 -0
- package/dist/components/core/Textarea.d.ts.map +1 -0
- package/dist/components/core/ThreeDotPopover.d.ts.map +1 -1
- package/dist/components/core/Tooltip.d.ts.map +1 -1
- package/dist/components/feedback/Dialog.d.ts.map +1 -1
- package/dist/components/feedback/Drawer.d.ts +4 -0
- package/dist/components/feedback/Drawer.d.ts.map +1 -0
- package/dist/components/feedback/Toast.d.ts +14 -5
- package/dist/components/feedback/Toast.d.ts.map +1 -1
- package/dist/components/feedback/Tour.d.ts +4 -0
- package/dist/components/feedback/Tour.d.ts.map +1 -0
- package/dist/components/feedback/TourSpotlight.d.ts +9 -0
- package/dist/components/feedback/TourSpotlight.d.ts.map +1 -0
- package/dist/components/navigation/Breadcrumbs.d.ts.map +1 -1
- package/dist/components/navigation/FootNav.d.ts.map +1 -1
- package/dist/components/navigation/Navbar.d.ts.map +1 -1
- package/dist/components/navigation/Sidebar.d.ts +8 -2
- package/dist/components/navigation/Sidebar.d.ts.map +1 -1
- package/dist/components/utility/Badge.d.ts.map +1 -1
- package/dist/components/utility/FileUpload.d.ts.map +1 -1
- package/dist/components/utility/Sortable.d.ts +4 -0
- package/dist/components/utility/Sortable.d.ts.map +1 -0
- package/dist/esm/_vendor/object-assign/index.js +99 -0
- package/dist/esm/_vendor/prop-types/_vendor/react-is/cjs/react-is.development.js +190 -0
- package/dist/esm/_vendor/prop-types/_vendor/react-is/cjs/react-is.production.min.js +26 -0
- package/dist/esm/_vendor/prop-types/_vendor/react-is/index.js +19 -0
- package/dist/esm/_vendor/prop-types/checkPropTypes.js +115 -0
- package/dist/esm/_vendor/prop-types/factoryWithThrowingShims.js +74 -0
- package/dist/esm/_vendor/prop-types/factoryWithTypeCheckers.js +625 -0
- package/dist/esm/_vendor/prop-types/index.js +30 -0
- package/dist/esm/_vendor/prop-types/lib/ReactPropTypesSecret.js +21 -0
- package/dist/esm/_vendor/prop-types/lib/has.js +11 -0
- package/dist/esm/_virtual/_commonjsHelpers.js +5 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +329 -0
- package/dist/esm/_virtual/index.js +3 -0
- package/dist/esm/_virtual/index2.js +3 -0
- package/dist/esm/_virtual/react-is.development.js +3 -0
- package/dist/esm/_virtual/react-is.production.min.js +3 -0
- package/dist/esm/components/blocks/AppShell.js +205 -0
- package/dist/esm/components/blocks/ConfirmDialog.js +57 -0
- package/dist/esm/components/blocks/EmptyState.js +44 -0
- package/dist/esm/components/blocks/ErrorState.js +53 -0
- package/dist/esm/components/blocks/LoadingState.js +134 -0
- package/dist/esm/components/blocks/PageHeader.js +51 -0
- package/dist/esm/components/blocks/StatCard.js +79 -0
- package/dist/esm/components/blocks/StatusPill.js +55 -0
- package/dist/esm/components/core/Accordion.js +260 -0
- package/dist/esm/components/core/Button.js +59 -0
- package/dist/esm/components/core/Checkbox.js +188 -0
- package/dist/esm/components/core/ColorPicker.js +348 -0
- package/dist/esm/components/core/DatePicker.js +436 -0
- package/dist/esm/components/core/DateRangePicker.js +494 -0
- package/dist/esm/components/core/Form.js +522 -0
- package/dist/esm/components/core/Input.js +179 -0
- package/dist/esm/components/core/Loader.js +141 -0
- package/dist/esm/components/core/LocationPicker.js +161 -0
- package/dist/esm/components/core/Popover.js +171 -0
- package/dist/esm/components/core/PriceRangePicker.js +376 -0
- package/dist/esm/components/core/ProgressBar.js +152 -0
- package/dist/esm/components/core/Radio.js +156 -0
- package/dist/esm/components/core/Rate.js +197 -0
- package/dist/esm/components/core/RoundedTag.js +118 -0
- package/dist/esm/components/core/Select.js +857 -0
- package/dist/esm/components/core/Skeleton.js +100 -0
- package/dist/esm/components/core/Slider.js +134 -0
- package/dist/esm/components/core/SpeechToText.js +226 -0
- package/dist/esm/components/core/Switch.js +207 -0
- package/dist/esm/components/core/Table/ActionMenu.js +251 -0
- package/dist/esm/components/core/Table/ColumnMenu.js +55 -0
- package/dist/esm/components/core/Table/FieldInput.js +157 -0
- package/dist/esm/components/core/Table/MobileCard.js +187 -0
- package/dist/esm/components/core/Table/MobileFilters.js +72 -0
- package/dist/esm/components/core/Table/Pagination.js +157 -0
- package/dist/esm/components/core/Table/Table.js +1533 -0
- package/dist/esm/components/core/Table/TableRow.js +254 -0
- package/dist/esm/components/core/Table/constants.js +35 -0
- package/dist/esm/components/core/Table/helpers.js +124 -0
- package/dist/esm/components/core/Table/useClickOutside.js +26 -0
- package/dist/esm/components/core/Tabs.js +289 -0
- package/dist/esm/components/core/TextToSpeech.js +52 -0
- package/dist/esm/components/core/Textarea.js +125 -0
- package/dist/esm/components/core/ThreeDotPopover.js +160 -0
- package/dist/esm/components/core/Tooltip.js +372 -0
- package/dist/esm/components/feedback/Alert.js +96 -0
- package/dist/esm/components/feedback/Dialog.js +200 -0
- package/dist/esm/components/feedback/Drawer.js +171 -0
- package/dist/esm/components/feedback/Toast.js +362 -0
- package/dist/esm/components/feedback/Tour.js +214 -0
- package/dist/esm/components/feedback/TourSpotlight.js +71 -0
- package/dist/esm/components/navigation/Breadcrumbs.js +75 -0
- package/dist/esm/components/navigation/Dropdown.js +53 -0
- package/dist/esm/components/navigation/FootNav.js +51 -0
- package/dist/esm/components/navigation/Navbar.js +437 -0
- package/dist/esm/components/navigation/Sidebar.js +567 -0
- package/dist/esm/components/utility/Avatar.js +89 -0
- package/dist/esm/components/utility/Badge.js +47 -0
- package/dist/esm/components/utility/Card.js +85 -0
- package/dist/esm/components/utility/Carousel.js +97 -0
- package/dist/esm/components/utility/Condition.js +9 -0
- package/dist/esm/components/utility/FileUpload.js +177 -0
- package/dist/esm/components/utility/Pagination.js +111 -0
- package/dist/esm/components/utility/Sortable.js +190 -0
- package/dist/esm/components/utility/Stepper.js +101 -0
- package/dist/esm/hooks/useApi.js +169 -0
- package/dist/esm/hooks/useControllableState.js +32 -0
- package/dist/esm/hooks/useFocusTrap.js +85 -0
- package/dist/esm/hooks/useLatestRef.js +20 -0
- package/dist/esm/hooks/useMixins.js +100 -0
- package/dist/esm/hooks/useScrollLock.js +26 -0
- package/dist/esm/hooks/useSliderValues.js +135 -0
- package/dist/esm/hooks/useSortable.js +188 -0
- package/dist/esm/hooks/useTheme.js +53 -0
- package/dist/esm/hooks/useTourTarget.js +92 -0
- package/dist/esm/index.js +65 -0
- package/dist/esm/store/index.js +26 -0
- package/dist/esm/store/store.js +107 -0
- package/dist/esm/store/storeSlice.js +45 -0
- package/dist/esm/utils/cn.js +11 -0
- package/dist/esm/utils/emitter.js +169 -0
- package/dist/esm/utils/helpers.js +161 -0
- package/dist/esm/utils/position.js +134 -0
- package/dist/hooks/useApi.d.ts +2 -1
- package/dist/hooks/useApi.d.ts.map +1 -1
- package/dist/hooks/useControllableState.d.ts +11 -0
- package/dist/hooks/useControllableState.d.ts.map +1 -0
- package/dist/hooks/useFocusTrap.d.ts +15 -0
- package/dist/hooks/useFocusTrap.d.ts.map +1 -0
- package/dist/hooks/useLatestRef.d.ts +8 -0
- package/dist/hooks/useLatestRef.d.ts.map +1 -0
- package/dist/hooks/useMixins.d.ts.map +1 -1
- package/dist/hooks/useScrollLock.d.ts +2 -0
- package/dist/hooks/useScrollLock.d.ts.map +1 -0
- package/dist/hooks/useSliderValues.d.ts +43 -0
- package/dist/hooks/useSliderValues.d.ts.map +1 -0
- package/dist/hooks/useSortable.d.ts +32 -0
- package/dist/hooks/useSortable.d.ts.map +1 -0
- package/dist/hooks/useTheme.d.ts.map +1 -1
- package/dist/hooks/useTourTarget.d.ts +15 -0
- package/dist/hooks/useTourTarget.d.ts.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.esm.css +1 -1
- package/dist/index.esm.js +4800 -2212
- package/dist/index.js +4805 -2210
- package/dist/types/index.d.ts +193 -5
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/position.d.ts +30 -0
- package/dist/utils/position.d.ts.map +1 -0
- package/doc/README.md +7 -1
- package/mcp/catalog.snapshot.json +911 -212
- package/package.json +14 -2
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { objectWithoutProperties as _objectWithoutProperties, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
3
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import { cn } from '../../utils/cn.js';
|
|
5
|
+
import React, { useState, useCallback, useEffect } from 'react';
|
|
6
|
+
import { ChevronLeft, Search, LogIn, LogOut, X, Menu, User, Bell } from 'lucide-react';
|
|
7
|
+
import { Dropdown } from './Dropdown.js';
|
|
8
|
+
import Avatar from '../utility/Avatar.js';
|
|
9
|
+
import PropTypes from '../../_vendor/prop-types/index.js';
|
|
10
|
+
|
|
11
|
+
var _excluded = ["emitter", "content", "notifications"],
|
|
12
|
+
_excluded2 = ["emitter", "logo", "center", "items", "user", "notifications", "searchable", "onSearch", "leftIcon", "rightMenuContent", "onLeftIconClick", "onLoginClick", "onLogoutClick", "className", "onFetch", "isMobileOpen", "setIsMobileOpen"];
|
|
13
|
+
var NO_NOTIFICATIONS = [];
|
|
14
|
+
// Simplified Notifications, uses notifications from props and a single effect for fetch/update
|
|
15
|
+
var NotificationsDropdown = function NotificationsDropdown(_ref) {
|
|
16
|
+
var emitter = _ref.emitter,
|
|
17
|
+
_ref$notifications = _ref.notifications,
|
|
18
|
+
initialNotifications = _ref$notifications === void 0 ? NO_NOTIFICATIONS : _ref$notifications,
|
|
19
|
+
_ref$onFetch = _ref.onFetch,
|
|
20
|
+
onFetch = _ref$onFetch === void 0 ? function () {
|
|
21
|
+
return console.log("invoked onFetch notifications");
|
|
22
|
+
} : _ref$onFetch;
|
|
23
|
+
var _useState = useState(initialNotifications),
|
|
24
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
25
|
+
notifications = _useState2[0],
|
|
26
|
+
setNotifications = _useState2[1];
|
|
27
|
+
var onView = function onView() {
|
|
28
|
+
emitter.emit("notification:view", notifications);
|
|
29
|
+
};
|
|
30
|
+
var reloadNotifications = function reloadNotifications() {
|
|
31
|
+
onFetch({
|
|
32
|
+
setNotifications: setNotifications
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
var onMarkAsRead = function onMarkAsRead() {
|
|
36
|
+
emitter.emit("notification:markAsRead", notifications).then(reloadNotifications);
|
|
37
|
+
};
|
|
38
|
+
var onMarkAsUnread = function onMarkAsUnread() {
|
|
39
|
+
emitter.emit("notification:markAsUnread", notifications).then(reloadNotifications);
|
|
40
|
+
};
|
|
41
|
+
var onClearAll = function onClearAll() {
|
|
42
|
+
emitter.emit("notification:clearAll", notifications).then(reloadNotifications);
|
|
43
|
+
};
|
|
44
|
+
var onDelete = function onDelete() {
|
|
45
|
+
emitter.emit("notification:delete", notifications).then(reloadNotifications);
|
|
46
|
+
};
|
|
47
|
+
// Reset to the `notifications` prop when it changes (adjust-during-render
|
|
48
|
+
// pattern), then let onFetch refresh from the server.
|
|
49
|
+
var _useState3 = useState(initialNotifications),
|
|
50
|
+
_useState4 = _slicedToArray(_useState3, 2),
|
|
51
|
+
prevInitial = _useState4[0],
|
|
52
|
+
setPrevInitial = _useState4[1];
|
|
53
|
+
if (initialNotifications !== prevInitial) {
|
|
54
|
+
setPrevInitial(initialNotifications);
|
|
55
|
+
setNotifications(initialNotifications);
|
|
56
|
+
}
|
|
57
|
+
// Fetch notifications: initial mount or if initialNotifications changes
|
|
58
|
+
useEffect(function () {
|
|
59
|
+
onFetch({
|
|
60
|
+
setNotifications: setNotifications
|
|
61
|
+
});
|
|
62
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
63
|
+
}, [initialNotifications]);
|
|
64
|
+
var unreadCount = notifications.filter(function (n) {
|
|
65
|
+
return !n.read;
|
|
66
|
+
}).length;
|
|
67
|
+
// For simplicity, shows notifications in the dropdown, can be expanded
|
|
68
|
+
return jsx(Dropdown, {
|
|
69
|
+
trigger: jsxs("button", {
|
|
70
|
+
className: "relative rounded-md p-2 text-primary-400 hover:text-primary-500 hover:bg-gray-100",
|
|
71
|
+
"aria-label": "notifications",
|
|
72
|
+
children: [jsx(Bell, {
|
|
73
|
+
className: "h-5 w-5"
|
|
74
|
+
}), unreadCount > 0 && jsx("span", {
|
|
75
|
+
className: "absolute -top-1 -right-1 h-4 w-4 rounded-full bg-error-500 text-xs text-white flex items-center justify-center",
|
|
76
|
+
children: unreadCount
|
|
77
|
+
})]
|
|
78
|
+
}),
|
|
79
|
+
placement: "bottom-end",
|
|
80
|
+
children: jsxs("div", {
|
|
81
|
+
className: "py-2 min-w-56 max-h-80 overflow-y-auto",
|
|
82
|
+
children: [jsxs("div", {
|
|
83
|
+
className: "px-4 py-2 border-b border-gray-100 flex items-center justify-between",
|
|
84
|
+
children: [jsx("span", {
|
|
85
|
+
className: "font-medium text-primary-800 text-sm",
|
|
86
|
+
children: "Notifications"
|
|
87
|
+
}), jsx("button", {
|
|
88
|
+
className: "text-xs text-primary-400 hover:text-error-600",
|
|
89
|
+
onClick: function onClick() {
|
|
90
|
+
onClearAll();
|
|
91
|
+
setNotifications([]);
|
|
92
|
+
},
|
|
93
|
+
type: "button",
|
|
94
|
+
children: "Clear all"
|
|
95
|
+
})]
|
|
96
|
+
}), notifications.length === 0 ? jsx("div", {
|
|
97
|
+
className: "px-4 py-4 text-sm text-primary-500 text-center",
|
|
98
|
+
children: "No notifications"
|
|
99
|
+
}) : notifications.map(function (n) {
|
|
100
|
+
return jsxs("div", {
|
|
101
|
+
className: cn("flex items-start gap-3 px-4 py-2 hover:bg-gray-50 cursor-pointer group", !n.read ? "bg-primary-50" : ""),
|
|
102
|
+
onClick: function onClick() {
|
|
103
|
+
return onView();
|
|
104
|
+
},
|
|
105
|
+
children: [jsx("span", {
|
|
106
|
+
className: cn("h-2 w-2 mt-2 rounded-full", !n.read ? "bg-primary-500" : "bg-gray-300")
|
|
107
|
+
}), jsxs("div", {
|
|
108
|
+
className: "flex-1",
|
|
109
|
+
children: [jsx("div", {
|
|
110
|
+
className: "text-sm text-primary-800",
|
|
111
|
+
children: n.title
|
|
112
|
+
}), n.message && jsx("div", {
|
|
113
|
+
className: "text-xs text-primary-500",
|
|
114
|
+
children: n.message
|
|
115
|
+
}), jsxs("div", {
|
|
116
|
+
className: "flex gap-2 mt-1",
|
|
117
|
+
children: [!n.read ? jsx("button", {
|
|
118
|
+
onClick: function onClick(e) {
|
|
119
|
+
e.stopPropagation();
|
|
120
|
+
onMarkAsRead();
|
|
121
|
+
},
|
|
122
|
+
className: "text-xs text-primary-600 hover:underline",
|
|
123
|
+
children: "Mark as Read"
|
|
124
|
+
}) : jsx("button", {
|
|
125
|
+
onClick: function onClick(e) {
|
|
126
|
+
e.stopPropagation();
|
|
127
|
+
onMarkAsUnread();
|
|
128
|
+
},
|
|
129
|
+
className: "text-xs text-primary-400 hover:underline",
|
|
130
|
+
children: "Mark as Unread"
|
|
131
|
+
}), jsx("button", {
|
|
132
|
+
onClick: function onClick(e) {
|
|
133
|
+
e.stopPropagation();
|
|
134
|
+
onDelete();
|
|
135
|
+
},
|
|
136
|
+
className: "text-xs text-error-500 hover:underline",
|
|
137
|
+
children: "Delete"
|
|
138
|
+
})]
|
|
139
|
+
})]
|
|
140
|
+
})]
|
|
141
|
+
}, n.id);
|
|
142
|
+
})]
|
|
143
|
+
})
|
|
144
|
+
});
|
|
145
|
+
};
|
|
146
|
+
// Renders the (optional) right menu content, including notifications
|
|
147
|
+
var RightMenuContent = function RightMenuContent(_ref2) {
|
|
148
|
+
var emitter = _ref2.emitter;
|
|
149
|
+
_ref2.content;
|
|
150
|
+
var _ref2$notifications = _ref2.notifications,
|
|
151
|
+
notifications = _ref2$notifications === void 0 ? [] : _ref2$notifications,
|
|
152
|
+
props = _objectWithoutProperties(_ref2, _excluded);
|
|
153
|
+
return jsx("div", {
|
|
154
|
+
className: "relative",
|
|
155
|
+
children: jsx(NotificationsDropdown, _objectSpread2({
|
|
156
|
+
emitter: emitter,
|
|
157
|
+
notifications: notifications
|
|
158
|
+
}, props))
|
|
159
|
+
});
|
|
160
|
+
};
|
|
161
|
+
var styledClassNames = {
|
|
162
|
+
button: "rounded-md p-2 text-primary-400 hover:text-primary-500 hover:bg-gray-100",
|
|
163
|
+
mobileItem: "md:hidden",
|
|
164
|
+
icon: "h-6 w-6",
|
|
165
|
+
dropdown: "w-56 rounded-md border border-gray-200 bg-white py-1 shadow-lg"
|
|
166
|
+
};
|
|
167
|
+
var Navbar = /*#__PURE__*/React.forwardRef(function (_ref3, ref) {
|
|
168
|
+
var emitter = _ref3.emitter,
|
|
169
|
+
logo = _ref3.logo,
|
|
170
|
+
center = _ref3.center,
|
|
171
|
+
_ref3$items = _ref3.items,
|
|
172
|
+
items = _ref3$items === void 0 ? [] : _ref3$items,
|
|
173
|
+
user = _ref3.user,
|
|
174
|
+
_ref3$notifications = _ref3.notifications,
|
|
175
|
+
notifications = _ref3$notifications === void 0 ? [] : _ref3$notifications,
|
|
176
|
+
_ref3$searchable = _ref3.searchable,
|
|
177
|
+
searchable = _ref3$searchable === void 0 ? false : _ref3$searchable,
|
|
178
|
+
onSearch = _ref3.onSearch,
|
|
179
|
+
_ref3$leftIcon = _ref3.leftIcon,
|
|
180
|
+
leftIcon = _ref3$leftIcon === void 0 ? jsx(ChevronLeft, {}) : _ref3$leftIcon,
|
|
181
|
+
RightMenuContentProp = _ref3.rightMenuContent,
|
|
182
|
+
onLeftIconClick = _ref3.onLeftIconClick,
|
|
183
|
+
_ref3$onLoginClick = _ref3.onLoginClick,
|
|
184
|
+
onLoginClick = _ref3$onLoginClick === void 0 ? function () {
|
|
185
|
+
return console.log("invoked onLoginClick");
|
|
186
|
+
} : _ref3$onLoginClick,
|
|
187
|
+
_ref3$onLogoutClick = _ref3.onLogoutClick,
|
|
188
|
+
onLogoutClick = _ref3$onLogoutClick === void 0 ? function () {
|
|
189
|
+
return console.log("invoked onLogoutClick");
|
|
190
|
+
} : _ref3$onLogoutClick,
|
|
191
|
+
className = _ref3.className,
|
|
192
|
+
onFetch = _ref3.onFetch;
|
|
193
|
+
_ref3.isMobileOpen;
|
|
194
|
+
_ref3.setIsMobileOpen;
|
|
195
|
+
var props = _objectWithoutProperties(_ref3, _excluded2);
|
|
196
|
+
var _useState5 = useState(false),
|
|
197
|
+
_useState6 = _slicedToArray(_useState5, 2),
|
|
198
|
+
isMobileMenuOpen = _useState6[0],
|
|
199
|
+
setIsMobileMenuOpen = _useState6[1];
|
|
200
|
+
var _useState7 = useState(""),
|
|
201
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
202
|
+
searchTerm = _useState8[0],
|
|
203
|
+
setSearchTerm = _useState8[1];
|
|
204
|
+
var _useState9 = useState(typeof window !== "undefined" ? window.innerWidth < 768 : false),
|
|
205
|
+
_useState0 = _slicedToArray(_useState9, 2),
|
|
206
|
+
isMobile = _useState0[0],
|
|
207
|
+
setIsMobile = _useState0[1];
|
|
208
|
+
// Responsive flag update
|
|
209
|
+
var handleResize = useCallback(function () {
|
|
210
|
+
setIsMobile(window.innerWidth < 768);
|
|
211
|
+
}, []);
|
|
212
|
+
useEffect(function () {
|
|
213
|
+
window.addEventListener("resize", handleResize);
|
|
214
|
+
setIsMobile(window.innerWidth < 768);
|
|
215
|
+
return function () {
|
|
216
|
+
window.removeEventListener("resize", handleResize);
|
|
217
|
+
};
|
|
218
|
+
}, [handleResize]);
|
|
219
|
+
// Handle search submit
|
|
220
|
+
var handleSearch = function handleSearch(e) {
|
|
221
|
+
e.preventDefault();
|
|
222
|
+
onSearch === null || onSearch === void 0 || onSearch(searchTerm);
|
|
223
|
+
};
|
|
224
|
+
var handleLoginClick = function handleLoginClick() {
|
|
225
|
+
onLoginClick === null || onLoginClick === void 0 || onLoginClick();
|
|
226
|
+
};
|
|
227
|
+
var handleLogoutClick = function handleLogoutClick() {
|
|
228
|
+
onLogoutClick === null || onLogoutClick === void 0 || onLogoutClick();
|
|
229
|
+
};
|
|
230
|
+
// Render navigation items as either <a> or <button>
|
|
231
|
+
var renderNavItems = function renderNavItems() {
|
|
232
|
+
var asButtons = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
|
|
233
|
+
return jsx(Fragment, {
|
|
234
|
+
children: items.map(function (item) {
|
|
235
|
+
return item.href && !asButtons ? jsx("a", {
|
|
236
|
+
href: item.href,
|
|
237
|
+
className: cn("text-sm font-medium transition-colors", {
|
|
238
|
+
"text-primary-600": item.active,
|
|
239
|
+
"hover:text-primary-600": !item.active
|
|
240
|
+
}),
|
|
241
|
+
children: item.label
|
|
242
|
+
}, item.id) : jsx("button", {
|
|
243
|
+
onClick: function onClick() {
|
|
244
|
+
var _item$onClick;
|
|
245
|
+
(_item$onClick = item.onClick) === null || _item$onClick === void 0 || _item$onClick.call(item, item);
|
|
246
|
+
setIsMobileMenuOpen(false);
|
|
247
|
+
},
|
|
248
|
+
className: cn("block w-full text-left px-4 py-2 text-sm", {
|
|
249
|
+
"text-primary-600": item.active,
|
|
250
|
+
"hover:bg-gray-50": !item.active
|
|
251
|
+
}),
|
|
252
|
+
children: item.label
|
|
253
|
+
}, item.id);
|
|
254
|
+
})
|
|
255
|
+
});
|
|
256
|
+
};
|
|
257
|
+
// RightMenuContent: prefer prop if provided, else fallback
|
|
258
|
+
var RightMenuComponent = typeof RightMenuContentProp === "function" ? RightMenuContentProp : function (rest) {
|
|
259
|
+
return jsx(RightMenuContent, _objectSpread2({
|
|
260
|
+
emitter: emitter
|
|
261
|
+
}, rest));
|
|
262
|
+
};
|
|
263
|
+
return jsxs("nav", _objectSpread2(_objectSpread2({
|
|
264
|
+
ref: ref,
|
|
265
|
+
className: cn("bg-white border-b border-gray-200 px-4 sm:px-6 lg:px-8", className)
|
|
266
|
+
}, props), {}, {
|
|
267
|
+
children: [jsxs("div", {
|
|
268
|
+
className: "flex h-16 min-w-0 items-center justify-between gap-2 sm:gap-4",
|
|
269
|
+
children: [jsxs("div", {
|
|
270
|
+
className: "flex min-w-0 shrink items-center",
|
|
271
|
+
children: [leftIcon !== false && jsx("div", {
|
|
272
|
+
className: "mr-2 hidden md:block md:mr-4",
|
|
273
|
+
"aria-hidden": true
|
|
274
|
+
}), jsxs("div", {
|
|
275
|
+
className: "flex min-w-0 items-center",
|
|
276
|
+
children: [leftIcon !== false && jsx("button", {
|
|
277
|
+
onClick: onLeftIconClick,
|
|
278
|
+
className: "shrink-0 md:hidden rounded-md p-2 text-primary-400 hover:text-primary-500 hover:bg-gray-100",
|
|
279
|
+
"aria-label": "back",
|
|
280
|
+
children: leftIcon
|
|
281
|
+
}), logo && jsx("div", {
|
|
282
|
+
className: "ml-2 min-w-0 truncate sm:ml-4 md:ml-0",
|
|
283
|
+
children: logo
|
|
284
|
+
})]
|
|
285
|
+
})]
|
|
286
|
+
}), center && jsx("div", {
|
|
287
|
+
className: "flex min-w-0 flex-1 items-center justify-center",
|
|
288
|
+
"data-navbar-slot": "center",
|
|
289
|
+
children: center
|
|
290
|
+
}), items.length > 0 && jsx("div", {
|
|
291
|
+
className: "hidden md:flex md:shrink-0 md:items-center md:space-x-8",
|
|
292
|
+
children: renderNavItems(false)
|
|
293
|
+
}), jsxs("div", {
|
|
294
|
+
className: "flex shrink-0 items-center gap-1 sm:gap-4",
|
|
295
|
+
children: [searchable && jsx("form", {
|
|
296
|
+
onSubmit: handleSearch,
|
|
297
|
+
className: "hidden sm:block",
|
|
298
|
+
children: jsxs("div", {
|
|
299
|
+
className: "relative",
|
|
300
|
+
children: [jsx(Search, {
|
|
301
|
+
className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-primary-400"
|
|
302
|
+
}), jsx("input", {
|
|
303
|
+
type: "text",
|
|
304
|
+
placeholder: "Search...",
|
|
305
|
+
className: "w-64 rounded-md border border-gray-300 bg-white pl-10 pr-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent",
|
|
306
|
+
value: searchTerm,
|
|
307
|
+
onChange: function onChange(e) {
|
|
308
|
+
return setSearchTerm(e.target.value);
|
|
309
|
+
}
|
|
310
|
+
})]
|
|
311
|
+
})
|
|
312
|
+
}), jsx(RightMenuComponent, {
|
|
313
|
+
notifications: notifications,
|
|
314
|
+
onFetch: onFetch
|
|
315
|
+
}), !user && jsx("button", {
|
|
316
|
+
className: styledClassNames.button,
|
|
317
|
+
onClick: handleLoginClick,
|
|
318
|
+
"aria-label": "Sign in",
|
|
319
|
+
children: jsx(LogIn, {
|
|
320
|
+
className: styledClassNames.icon
|
|
321
|
+
})
|
|
322
|
+
}), user &&
|
|
323
|
+
// Secondary on phones: hidden below `sm` (it moves into the user
|
|
324
|
+
// menu as "Sign out") so the header fits a 390px viewport.
|
|
325
|
+
jsx("button", {
|
|
326
|
+
className: cn(styledClassNames.button, "hidden sm:inline-flex"),
|
|
327
|
+
onClick: handleLogoutClick,
|
|
328
|
+
"aria-label": "Sign out",
|
|
329
|
+
children: jsx(LogOut, {
|
|
330
|
+
className: styledClassNames.icon
|
|
331
|
+
})
|
|
332
|
+
}), jsx("div", {
|
|
333
|
+
className: "relative",
|
|
334
|
+
children: !user ? jsx("button", {
|
|
335
|
+
className: cn(styledClassNames.button, styledClassNames.mobileItem),
|
|
336
|
+
onClick: function onClick() {
|
|
337
|
+
return setIsMobileMenuOpen(function (s) {
|
|
338
|
+
return !s;
|
|
339
|
+
});
|
|
340
|
+
},
|
|
341
|
+
"aria-label": "menu",
|
|
342
|
+
children: isMobileMenuOpen ? jsx(X, {
|
|
343
|
+
className: styledClassNames.icon
|
|
344
|
+
}) : jsx(Menu, {
|
|
345
|
+
className: styledClassNames.icon
|
|
346
|
+
})
|
|
347
|
+
}) : jsx(Dropdown, {
|
|
348
|
+
trigger: jsx("button", {
|
|
349
|
+
className: styledClassNames.button,
|
|
350
|
+
"aria-label": "user menu",
|
|
351
|
+
children: user.avatar || user.name ?
|
|
352
|
+
// Image when `avatar` is set; otherwise initials from
|
|
353
|
+
// `name` (Avatar's own fallback logic).
|
|
354
|
+
jsx(Avatar, {
|
|
355
|
+
src: user.avatar || undefined,
|
|
356
|
+
name: user.name,
|
|
357
|
+
alt: user.name,
|
|
358
|
+
size: "sm"
|
|
359
|
+
}) : jsx(User, {
|
|
360
|
+
className: styledClassNames.icon
|
|
361
|
+
})
|
|
362
|
+
}),
|
|
363
|
+
placement: "bottom-end",
|
|
364
|
+
className: "z-50",
|
|
365
|
+
children: jsxs("div", {
|
|
366
|
+
className: styledClassNames.dropdown,
|
|
367
|
+
children: [jsxs("div", {
|
|
368
|
+
className: "px-4 py-2 border-b border-gray-200",
|
|
369
|
+
children: [jsx("p", {
|
|
370
|
+
className: "text-sm font-medium text-primary-900",
|
|
371
|
+
children: user.name
|
|
372
|
+
}), jsx("p", {
|
|
373
|
+
className: "text-xs text-primary-500",
|
|
374
|
+
children: user.email
|
|
375
|
+
})]
|
|
376
|
+
}), isMobile && jsx("div", {
|
|
377
|
+
className: "py-1",
|
|
378
|
+
children: renderNavItems(true)
|
|
379
|
+
}), user.menuItems && user.menuItems.length > 0 && jsx("div", {
|
|
380
|
+
className: "border-t border-gray-100",
|
|
381
|
+
children: user.menuItems.map(function (mi) {
|
|
382
|
+
return jsx("button", {
|
|
383
|
+
onClick: function onClick(e) {
|
|
384
|
+
var _mi$onClick;
|
|
385
|
+
return mi === null || mi === void 0 || (_mi$onClick = mi.onClick) === null || _mi$onClick === void 0 ? void 0 : _mi$onClick.call(mi, e);
|
|
386
|
+
},
|
|
387
|
+
className: "block w-full px-4 py-2 text-left text-sm hover:bg-gray-100",
|
|
388
|
+
children: mi.label
|
|
389
|
+
}, mi.id);
|
|
390
|
+
})
|
|
391
|
+
}), jsx("div", {
|
|
392
|
+
className: "border-t border-gray-100 sm:hidden",
|
|
393
|
+
children: jsxs("button", {
|
|
394
|
+
type: "button",
|
|
395
|
+
onClick: handleLogoutClick,
|
|
396
|
+
className: "flex w-full items-center gap-2 px-4 py-2 text-left text-sm hover:bg-gray-100",
|
|
397
|
+
children: [jsx(LogOut, {
|
|
398
|
+
className: "h-4 w-4",
|
|
399
|
+
"aria-hidden": "true"
|
|
400
|
+
}), "Sign out"]
|
|
401
|
+
})
|
|
402
|
+
})]
|
|
403
|
+
})
|
|
404
|
+
})
|
|
405
|
+
})]
|
|
406
|
+
})]
|
|
407
|
+
}), isMobileMenuOpen && !user && jsx("div", {
|
|
408
|
+
className: "md:hidden h-full",
|
|
409
|
+
children: jsx("div", {
|
|
410
|
+
className: "space-y-1 border-t border-gray-200 px-2 pt-4 pb-3",
|
|
411
|
+
children: items.map(function (item) {
|
|
412
|
+
return jsx("a", {
|
|
413
|
+
href: item.href,
|
|
414
|
+
className: cn("block rounded-md px-3 py-2 text-base font-medium", {
|
|
415
|
+
"bg-primary-50 text-primary-700": item.active,
|
|
416
|
+
"hover:bg-gray-50": !item.active
|
|
417
|
+
}),
|
|
418
|
+
children: item.label
|
|
419
|
+
}, item.id);
|
|
420
|
+
})
|
|
421
|
+
})
|
|
422
|
+
})]
|
|
423
|
+
}));
|
|
424
|
+
});
|
|
425
|
+
Navbar.displayName = "Navbar";
|
|
426
|
+
Navbar.propTypes = {
|
|
427
|
+
emitter: PropTypes.object.isRequired,
|
|
428
|
+
logo: PropTypes.node,
|
|
429
|
+
center: PropTypes.node,
|
|
430
|
+
items: PropTypes.array.isRequired,
|
|
431
|
+
user: PropTypes.object,
|
|
432
|
+
notifications: PropTypes.array,
|
|
433
|
+
searchable: PropTypes.bool,
|
|
434
|
+
onSearch: PropTypes.func
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
export { Navbar, Navbar as default };
|