react-os-shell 0.7.5 → 0.9.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.
package/dist/index.js CHANGED
@@ -1,10 +1,7 @@
1
- import { useEmailUnreadCount } from './chunk-PDFQNHW7.js';
2
- import { useMailAuth } from './chunk-VBFB3ZIN.js';
3
- export { setShellMailServer, useMailAuth } from './chunk-VBFB3ZIN.js';
4
- import { formatDate } from './chunk-NSU7OHPC.js';
5
- export { formatDate } from './chunk-NSU7OHPC.js';
1
+ import { formatDate } from './chunk-Y4QYGQKS.js';
2
+ export { formatDate } from './chunk-Y4QYGQKS.js';
6
3
  import { subscribePomo, getPomoSnapshot } from './chunk-MK3HLUO4.js';
7
- export { setShellTodoProvider } from './chunk-FTL7F4TM.js';
4
+ export { setShellTodoProvider } from './chunk-QTJ2CHJX.js';
8
5
  import { useShellPrefs } from './chunk-36VM54SC.js';
9
6
  export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
10
7
  import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-SUUADOG6.js';
@@ -14,7 +11,7 @@ import './chunk-KUIPWCTJ.js';
14
11
  import { toast_default } from './chunk-WIJ45SYD.js';
15
12
  export { toast_default as toast } from './chunk-WIJ45SYD.js';
16
13
  export { EditableGrid } from './chunk-ZETQWO2W.js';
17
- import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, WINDOW_REGISTRY, isPageEntry, ModalActions, useIsMobile, useModalActive, client_default, LoadingSpinner, setWindowPosition, ThumbCard, activateModal } from './chunk-3T6SQ4UO.js';
14
+ import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, WINDOW_REGISTRY, isPageEntry, useIsMobile, ModalActions, useModalActive, client_default, LoadingSpinner, setWindowPosition, ThumbCard, activateModal } from './chunk-3T6SQ4UO.js';
18
15
  export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-3T6SQ4UO.js';
19
16
  import { confirm } from './chunk-UBN4IUDE.js';
20
17
  export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-UBN4IUDE.js';
@@ -1403,7 +1400,7 @@ function WidgetManager({ open, onClose }) {
1403
1400
  }
1404
1401
 
1405
1402
  // src/version.ts
1406
- var VERSION = "0.7.5" ;
1403
+ var VERSION = "0.9.0" ;
1407
1404
  var APP_VERSION = VERSION;
1408
1405
 
1409
1406
  // src/changelog.ts
@@ -3012,221 +3009,6 @@ function useTheme() {
3012
3009
  }, [accentColor, customBgColor, customTitleColor, customWindowColor, customButtonColor]);
3013
3010
  return { theme: saved, resolved };
3014
3011
  }
3015
- var PRESETS = [
3016
- {
3017
- id: "fastmail",
3018
- label: "Fastmail",
3019
- imap: { host: "imap.fastmail.com", port: 993, secure: true },
3020
- smtp: { host: "smtp.fastmail.com", port: 465, secure: true },
3021
- caldav: "https://caldav.fastmail.com/"
3022
- },
3023
- {
3024
- id: "icloud",
3025
- label: "iCloud",
3026
- note: "Requires an app-specific password (appleid.apple.com).",
3027
- imap: { host: "imap.mail.me.com", port: 993, secure: true },
3028
- smtp: { host: "smtp.mail.me.com", port: 587, secure: false },
3029
- caldav: "https://caldav.icloud.com/"
3030
- },
3031
- {
3032
- id: "yahoo",
3033
- label: "Yahoo",
3034
- note: "Requires an app password (account.yahoo.com).",
3035
- imap: { host: "imap.mail.yahoo.com", port: 993, secure: true },
3036
- smtp: { host: "smtp.mail.yahoo.com", port: 465, secure: true },
3037
- caldav: "https://caldav.calendar.yahoo.com/"
3038
- },
3039
- {
3040
- id: "gmail",
3041
- label: "Gmail (app password required)",
3042
- note: "Enable 2FA and create an app password \u2014 Gmail rejects regular passwords for IMAP.",
3043
- imap: { host: "imap.gmail.com", port: 993, secure: true },
3044
- smtp: { host: "smtp.gmail.com", port: 465, secure: true }
3045
- },
3046
- {
3047
- id: "outlook",
3048
- label: "Outlook (app password required)",
3049
- note: "Modern auth not supported \u2014 generate an app password in Microsoft account settings.",
3050
- imap: { host: "outlook.office365.com", port: 993, secure: true },
3051
- smtp: { host: "smtp.office365.com", port: 587, secure: false }
3052
- },
3053
- {
3054
- id: "custom",
3055
- label: "Custom",
3056
- imap: { host: "", port: 993, secure: true },
3057
- smtp: { host: "", port: 465, secure: true }
3058
- }
3059
- ];
3060
- function MailConnectModal({ open, onClose }) {
3061
- const { isConnected, user, capabilities, login, logout, loading, error } = useMailAuth();
3062
- const [presetId, setPresetId] = useState("fastmail");
3063
- const preset = PRESETS.find((p) => p.id === presetId) || PRESETS[0];
3064
- const prefill = typeof window !== "undefined" ? localStorage.getItem("mail_login_prefill_email") || "" : "";
3065
- const [email, setEmail] = useState(prefill);
3066
- const [password, setPassword] = useState("");
3067
- const [imapHost, setImapHost] = useState(preset.imap.host);
3068
- const [imapPort, setImapPort] = useState(preset.imap.port);
3069
- const [imapSecure, setImapSecure] = useState(preset.imap.secure);
3070
- const [smtpHost, setSmtpHost] = useState(preset.smtp.host);
3071
- const [smtpPort, setSmtpPort] = useState(preset.smtp.port);
3072
- const [smtpSecure, setSmtpSecure] = useState(preset.smtp.secure);
3073
- const [caldavUrl, setCaldavUrl] = useState(preset.caldav || "");
3074
- const [localError, setLocalError] = useState(null);
3075
- useEffect(() => {
3076
- setImapHost(preset.imap.host);
3077
- setImapPort(preset.imap.port);
3078
- setImapSecure(preset.imap.secure);
3079
- setSmtpHost(preset.smtp.host);
3080
- setSmtpPort(preset.smtp.port);
3081
- setSmtpSecure(preset.smtp.secure);
3082
- setCaldavUrl(preset.caldav || "");
3083
- }, [preset]);
3084
- async function handleSubmit(e) {
3085
- e.preventDefault();
3086
- setLocalError(null);
3087
- if (!email || !password) {
3088
- setLocalError("Email and password are required");
3089
- return;
3090
- }
3091
- const payload = {
3092
- imap: { host: imapHost, port: imapPort, secure: imapSecure, user: email, pass: password },
3093
- smtp: { host: smtpHost, port: smtpPort, secure: smtpSecure, user: email, pass: password },
3094
- caldav: caldavUrl ? { serverUrl: caldavUrl, user: email, pass: password } : void 0
3095
- };
3096
- try {
3097
- await login(payload);
3098
- onClose();
3099
- } catch {
3100
- }
3101
- }
3102
- return /* @__PURE__ */ jsxs(Modal, { open, onClose, title: "Mail & Calendar", size: "md", children: [
3103
- isConnected ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
3104
- /* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-green-200 bg-green-50 p-4", children: [
3105
- /* @__PURE__ */ jsxs("p", { className: "text-sm font-medium text-green-900", children: [
3106
- "Connected as ",
3107
- user?.email
3108
- ] }),
3109
- /* @__PURE__ */ jsxs("p", { className: "text-xs text-green-700 mt-1", children: [
3110
- "IMAP: ok \xB7 SMTP: ok \xB7 CalDAV: ",
3111
- capabilities?.caldav ? "ok" : "not configured"
3112
- ] })
3113
- ] }),
3114
- /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500", children: "Disconnect to switch accounts. Credentials are not persisted to disk \u2014 restarting the bridge server signs you out." })
3115
- ] }) : /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
3116
- /* @__PURE__ */ jsxs("label", { className: "block", children: [
3117
- /* @__PURE__ */ jsx("span", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Provider" }),
3118
- /* @__PURE__ */ jsx(
3119
- "select",
3120
- {
3121
- value: presetId,
3122
- onChange: (e) => setPresetId(e.target.value),
3123
- className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm",
3124
- children: PRESETS.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.label }, p.id))
3125
- }
3126
- )
3127
- ] }),
3128
- preset.note && /* @__PURE__ */ jsx("p", { className: "text-[11px] text-amber-700 bg-amber-50 border border-amber-200 rounded p-2", children: preset.note }),
3129
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
3130
- /* @__PURE__ */ jsxs("label", { className: "block col-span-2", children: [
3131
- /* @__PURE__ */ jsx("span", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Email" }),
3132
- /* @__PURE__ */ jsx(
3133
- "input",
3134
- {
3135
- type: "email",
3136
- value: email,
3137
- onChange: (e) => setEmail(e.target.value),
3138
- autoComplete: "username",
3139
- className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
3140
- }
3141
- )
3142
- ] }),
3143
- /* @__PURE__ */ jsxs("label", { className: "block col-span-2", children: [
3144
- /* @__PURE__ */ jsx("span", { className: "block text-xs font-medium text-gray-700 mb-1", children: "Password" }),
3145
- /* @__PURE__ */ jsx(
3146
- "input",
3147
- {
3148
- type: "password",
3149
- value: password,
3150
- onChange: (e) => setPassword(e.target.value),
3151
- autoComplete: "current-password",
3152
- className: "w-full rounded-md border border-gray-300 px-3 py-2 text-sm"
3153
- }
3154
- )
3155
- ] })
3156
- ] }),
3157
- /* @__PURE__ */ jsxs("fieldset", { className: "border border-gray-200 rounded-md p-3", children: [
3158
- /* @__PURE__ */ jsx("legend", { className: "px-1 text-xs font-medium text-gray-600", children: "IMAP (incoming)" }),
3159
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
3160
- /* @__PURE__ */ jsxs("label", { className: "block col-span-2", children: [
3161
- /* @__PURE__ */ jsx("span", { className: "block text-[11px] text-gray-600 mb-1", children: "Host" }),
3162
- /* @__PURE__ */ jsx("input", { value: imapHost, onChange: (e) => setImapHost(e.target.value), className: "w-full rounded border border-gray-300 px-2 py-1 text-sm" })
3163
- ] }),
3164
- /* @__PURE__ */ jsxs("label", { className: "block", children: [
3165
- /* @__PURE__ */ jsx("span", { className: "block text-[11px] text-gray-600 mb-1", children: "Port" }),
3166
- /* @__PURE__ */ jsx("input", { type: "number", value: imapPort, onChange: (e) => setImapPort(Number(e.target.value)), className: "w-full rounded border border-gray-300 px-2 py-1 text-sm" })
3167
- ] }),
3168
- /* @__PURE__ */ jsxs("label", { className: "col-span-3 flex items-center gap-2 text-xs text-gray-600 mt-1", children: [
3169
- /* @__PURE__ */ jsx("input", { type: "checkbox", checked: imapSecure, onChange: (e) => setImapSecure(e.target.checked) }),
3170
- "Use TLS/SSL (recommended for port 993)"
3171
- ] })
3172
- ] })
3173
- ] }),
3174
- /* @__PURE__ */ jsxs("fieldset", { className: "border border-gray-200 rounded-md p-3", children: [
3175
- /* @__PURE__ */ jsx("legend", { className: "px-1 text-xs font-medium text-gray-600", children: "SMTP (outgoing)" }),
3176
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
3177
- /* @__PURE__ */ jsxs("label", { className: "block col-span-2", children: [
3178
- /* @__PURE__ */ jsx("span", { className: "block text-[11px] text-gray-600 mb-1", children: "Host" }),
3179
- /* @__PURE__ */ jsx("input", { value: smtpHost, onChange: (e) => setSmtpHost(e.target.value), className: "w-full rounded border border-gray-300 px-2 py-1 text-sm" })
3180
- ] }),
3181
- /* @__PURE__ */ jsxs("label", { className: "block", children: [
3182
- /* @__PURE__ */ jsx("span", { className: "block text-[11px] text-gray-600 mb-1", children: "Port" }),
3183
- /* @__PURE__ */ jsx("input", { type: "number", value: smtpPort, onChange: (e) => setSmtpPort(Number(e.target.value)), className: "w-full rounded border border-gray-300 px-2 py-1 text-sm" })
3184
- ] }),
3185
- /* @__PURE__ */ jsxs("label", { className: "col-span-3 flex items-center gap-2 text-xs text-gray-600 mt-1", children: [
3186
- /* @__PURE__ */ jsx("input", { type: "checkbox", checked: smtpSecure, onChange: (e) => setSmtpSecure(e.target.checked) }),
3187
- "Use TLS/SSL (recommended for port 465)"
3188
- ] })
3189
- ] })
3190
- ] }),
3191
- /* @__PURE__ */ jsxs("fieldset", { className: "border border-gray-200 rounded-md p-3", children: [
3192
- /* @__PURE__ */ jsx("legend", { className: "px-1 text-xs font-medium text-gray-600", children: "CalDAV (optional)" }),
3193
- /* @__PURE__ */ jsxs("label", { className: "block", children: [
3194
- /* @__PURE__ */ jsx("span", { className: "block text-[11px] text-gray-600 mb-1", children: "Server URL" }),
3195
- /* @__PURE__ */ jsx(
3196
- "input",
3197
- {
3198
- type: "url",
3199
- value: caldavUrl,
3200
- onChange: (e) => setCaldavUrl(e.target.value),
3201
- placeholder: "https://caldav.example.com/",
3202
- className: "w-full rounded border border-gray-300 px-2 py-1 text-sm"
3203
- }
3204
- )
3205
- ] }),
3206
- /* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-500 mt-1", children: "Leave blank to skip calendar setup." })
3207
- ] }),
3208
- (localError || error) && /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600 bg-red-50 border border-red-200 rounded p-2", children: localError || error })
3209
- ] }),
3210
- /* @__PURE__ */ jsx(ModalActions, { children: isConnected ? /* @__PURE__ */ jsx(
3211
- "button",
3212
- {
3213
- onClick: logout,
3214
- disabled: loading,
3215
- className: "inline-flex items-center gap-1.5 text-red-600 border border-red-200 bg-white px-4 py-2 text-sm font-medium rounded-lg hover:bg-red-50 disabled:opacity-50",
3216
- children: loading ? "Disconnecting\u2026" : "Disconnect"
3217
- }
3218
- ) : /* @__PURE__ */ jsx(
3219
- "button",
3220
- {
3221
- type: "button",
3222
- onClick: (e) => handleSubmit(e),
3223
- disabled: loading,
3224
- className: "inline-flex items-center gap-2 bg-gray-900 text-white px-5 py-2 text-sm font-medium rounded-lg hover:bg-gray-800 disabled:opacity-50",
3225
- children: loading ? "Connecting\u2026" : "Connect"
3226
- }
3227
- ) })
3228
- ] });
3229
- }
3230
3012
  function useClickOutside(ref, onClose) {
3231
3013
  useEffect(() => {
3232
3014
  const handler = (e) => {
@@ -4694,14 +4476,11 @@ function TaskbarClock() {
4694
4476
  const rect = buttonRef.current?.getBoundingClientRect();
4695
4477
  const right = rect ? Math.max(8, window.innerWidth - rect.right) : 8;
4696
4478
  const posStyle = taskbarPos === "top" ? { right, top: (rect?.bottom ?? 0) + 4 } : { right, bottom: window.innerHeight - (rect?.top ?? 0) + 4 };
4697
- return /* @__PURE__ */ jsx("div", { className: "fixed z-[300] rounded-lg border border-gray-200 bg-white shadow-xl", style: posStyle, children: /* @__PURE__ */ jsx(CalendarPopup, { now, onOpenCalendar: () => {
4698
- openPage("/calendar");
4699
- setOpen(false);
4700
- } }) });
4479
+ return /* @__PURE__ */ jsx("div", { className: "fixed z-[300] rounded-lg border border-gray-200 bg-white shadow-xl", style: posStyle, children: /* @__PURE__ */ jsx(CalendarPopup, { now }) });
4701
4480
  })()
4702
4481
  ] });
4703
4482
  }
4704
- function CalendarPopup({ now, onOpenCalendar }) {
4483
+ function CalendarPopup({ now }) {
4705
4484
  const [month, setMonth] = useState(() => new Date(now.getFullYear(), now.getMonth(), 1));
4706
4485
  const monthLabel = month.toLocaleDateString(void 0, { month: "long", year: "numeric" });
4707
4486
  const fullDate = now.toLocaleDateString(void 0, { weekday: "long", month: "long", day: "numeric" });
@@ -4748,18 +4527,7 @@ function CalendarPopup({ now, onOpenCalendar }) {
4748
4527
  },
4749
4528
  i
4750
4529
  );
4751
- }) }),
4752
- /* @__PURE__ */ jsx("div", { className: "mt-2 pt-2 border-t border-gray-100", children: /* @__PURE__ */ jsxs(
4753
- "button",
4754
- {
4755
- onClick: onOpenCalendar,
4756
- className: "w-full text-[11px] font-medium text-gray-500 hover:text-blue-600 hover:bg-blue-50 rounded py-1 transition-colors flex items-center justify-center gap-1.5",
4757
- children: [
4758
- /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.8, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5" }) }),
4759
- "Open Calendar"
4760
- ]
4761
- }
4762
- ) })
4530
+ }) })
4763
4531
  ] });
4764
4532
  }
4765
4533
  function TaskbarContextMenu({ x, y, position, size, onChangePosition, onChangeSize, onClose, onReportBug }) {
@@ -4827,14 +4595,12 @@ function Layout({
4827
4595
  categories = startMenuCategories,
4828
4596
  notifications,
4829
4597
  search,
4830
- taskbarTrayLeft,
4831
- showMail = true
4598
+ taskbarTrayLeft
4832
4599
  } = {}) {
4833
4600
  const bugReport = useBugReport();
4834
4601
  const { user, logout, hasAnyPerm } = useAuth();
4835
4602
  const { openPage, openEntity, openWindows } = useWindowManager();
4836
4603
  const [menuOpen, setMenuOpen] = useState(false);
4837
- useEmailUnreadCount();
4838
4604
  const isMobile = useIsMobile();
4839
4605
  const profile = user || {};
4840
4606
  useTheme();
@@ -4893,14 +4659,7 @@ function Layout({
4893
4659
  const [balloonDismissed, setBalloonDismissed] = useState(false);
4894
4660
  const [isFullscreen, setIsFullscreen] = useState(!!document.fullscreenElement);
4895
4661
  const [taskbarMenu, setTaskbarMenu] = useState(null);
4896
- const [mailConnectOpen, setMailConnectOpen] = useState(false);
4897
- const { isConnected: mailConnected } = useMailAuth();
4898
4662
  const [showLogout, setShowLogout] = useState(false);
4899
- useEffect(() => {
4900
- const handler = () => setMailConnectOpen(true);
4901
- window.addEventListener("open-mail-connect", handler);
4902
- return () => window.removeEventListener("open-mail-connect", handler);
4903
- }, []);
4904
4663
  const savePref = useCallback((key, value) => {
4905
4664
  savePrefs({ [key]: value });
4906
4665
  }, [savePrefs]);
@@ -5158,18 +4917,9 @@ function Layout({
5158
4917
  /* @__PURE__ */ jsx("div", { id: "taskbar-windows", className: `flex-1 flex ${isVerticalTaskbar ? "flex-col items-center gap-1 min-h-0 overflow-y-auto w-full" : "items-center gap-1.5 min-w-0 overflow-x-auto"}` }),
5159
4918
  /* @__PURE__ */ jsx("div", { className: isVerticalTaskbar ? "h-px w-6 bg-gray-300 my-1" : "w-px h-6 bg-gray-300 mx-1" }),
5160
4919
  isVerticalTaskbar ? (
5161
- /* Vertical: clock + mail-connect + bell evenly spaced */
4920
+ /* Vertical: clock + bell evenly spaced */
5162
4921
  /* @__PURE__ */ jsx("div", { className: "w-full px-2", children: /* @__PURE__ */ jsxs("div", { className: `flex items-center justify-center gap-2 ${taskbarPosition === "right" ? "flex-row-reverse" : ""}`, children: [
5163
4922
  /* @__PURE__ */ jsx(TaskbarClock, {}),
5164
- showMail && /* @__PURE__ */ jsx(
5165
- "button",
5166
- {
5167
- onClick: () => setMailConnectOpen(true),
5168
- title: mailConnected ? "Mail & Calendar Connected" : "Connect Mail & Calendar",
5169
- className: `shrink-0 rounded-md p-1.5 transition-colors ${mailConnected ? "hover:bg-green-50 text-green-600" : "text-gray-500 hover:text-gray-900 hover:bg-gray-200"}`,
5170
- children: /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, children: /* @__PURE__ */ jsx("path", { d: "M3 7l9 6 9-6M5 5h14a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2z", strokeLinecap: "round", strokeLinejoin: "round" }) })
5171
- }
5172
- ),
5173
4923
  /* @__PURE__ */ jsx(TaskbarPomodoro, {}),
5174
4924
  taskbarTrayLeft,
5175
4925
  notifications && /* @__PURE__ */ jsx(NotificationBell, { ...notifications, popDirection: taskbarPosition === "right" ? "left" : "right" })
@@ -5180,15 +4930,6 @@ function Layout({
5180
4930
  /* @__PURE__ */ jsx(TaskbarPomodoro, {}),
5181
4931
  taskbarTrayLeft,
5182
4932
  notifications && /* @__PURE__ */ jsx(NotificationBell, { ...notifications }),
5183
- showMail && /* @__PURE__ */ jsx(
5184
- "button",
5185
- {
5186
- onClick: () => setMailConnectOpen(true),
5187
- title: mailConnected ? "Mail & Calendar Connected" : "Connect Mail & Calendar",
5188
- className: `shrink-0 rounded-md p-2 transition-colors ${mailConnected ? "hover:bg-green-50 text-green-600" : "text-gray-500 hover:text-gray-900 hover:bg-gray-200"}`,
5189
- children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, children: /* @__PURE__ */ jsx("path", { d: "M3 7l9 6 9-6M5 5h14a2 2 0 012 2v10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2z", strokeLinecap: "round", strokeLinejoin: "round" }) })
5190
- }
5191
- ),
5192
4933
  /* @__PURE__ */ jsx(TaskbarClock, {})
5193
4934
  ] })
5194
4935
  )
@@ -5217,8 +4958,7 @@ function Layout({
5217
4958
  }
5218
4959
  ),
5219
4960
  /* @__PURE__ */ jsx(GlobalSearch, { ...search }),
5220
- /* @__PURE__ */ jsx(ShortcutHelp, {}),
5221
- /* @__PURE__ */ jsx(MailConnectModal, { open: mailConnectOpen, onClose: () => setMailConnectOpen(false) })
4961
+ /* @__PURE__ */ jsx(ShortcutHelp, {})
5222
4962
  ] });
5223
4963
  }
5224
4964
  var THEMES = [
@@ -6518,6 +6258,126 @@ function EntityList(props) {
6518
6258
  }
6519
6259
  ) }) });
6520
6260
  }
6261
+ function Kanban({
6262
+ items,
6263
+ columns,
6264
+ columnOf,
6265
+ getId,
6266
+ onMove,
6267
+ renderCard,
6268
+ onCardClick,
6269
+ sortInColumn,
6270
+ isLoading = false,
6271
+ loadingText = "Loading\u2026",
6272
+ emptyState,
6273
+ columnEmptyText = "Drop here"
6274
+ }) {
6275
+ const [dragId, setDragId] = useState(null);
6276
+ const [fromCol, setFromCol] = useState(null);
6277
+ const [gap, setGap] = useState(0);
6278
+ const [over, setOver] = useState(null);
6279
+ const grouped = useMemo(() => {
6280
+ const map = {};
6281
+ for (const c of columns) map[c.value] = [];
6282
+ for (const it of items) (map[columnOf(it)] ??= []).push(it);
6283
+ if (sortInColumn) for (const k of Object.keys(map)) map[k].sort(sortInColumn);
6284
+ return map;
6285
+ }, [items, columns, columnOf, sortInColumn]);
6286
+ const reset = () => {
6287
+ setDragId(null);
6288
+ setFromCol(null);
6289
+ setOver(null);
6290
+ };
6291
+ const isActive = (col) => over !== null && over.col === col && fromCol !== col;
6292
+ if (isLoading) return /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-500 p-4", children: loadingText });
6293
+ if (items.length === 0) {
6294
+ return /* @__PURE__ */ jsx(Fragment, { children: emptyState ?? /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-500 p-4", children: "No items." }) });
6295
+ }
6296
+ return /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-x-auto grid-scroll", children: /* @__PURE__ */ jsx("div", { className: "flex gap-3 h-full min-w-max pb-2", children: columns.map((col) => {
6297
+ const colItems = grouped[col.value] ?? [];
6298
+ const active = isActive(col.value);
6299
+ return /* @__PURE__ */ jsxs(
6300
+ "div",
6301
+ {
6302
+ className: `flex flex-col w-72 shrink-0 rounded-xl bg-gray-50 border transition-colors ${active ? "border-blue-400 ring-2 ring-blue-300/60" : "border-gray-200"}`,
6303
+ onDragOver: (e) => e.preventDefault(),
6304
+ onDragEnter: () => setOver((prev) => prev && prev.col === col.value ? prev : { col: col.value, index: colItems.length }),
6305
+ onDrop: () => {
6306
+ if (dragId) onMove(dragId, col.value);
6307
+ reset();
6308
+ },
6309
+ children: [
6310
+ /* @__PURE__ */ jsxs(
6311
+ "div",
6312
+ {
6313
+ className: `flex items-center justify-between px-3 py-2 rounded-t-xl text-sm font-medium ${col.accent ?? "text-gray-700 bg-gray-100"}`,
6314
+ children: [
6315
+ /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-2", children: [
6316
+ /* @__PURE__ */ jsx("span", { className: `h-2 w-2 rounded-full ${col.dot ?? "bg-gray-400"}` }),
6317
+ col.label
6318
+ ] }),
6319
+ /* @__PURE__ */ jsx("span", { className: "text-xs opacity-70", children: colItems.length })
6320
+ ]
6321
+ }
6322
+ ),
6323
+ /* @__PURE__ */ jsxs(
6324
+ "div",
6325
+ {
6326
+ className: "flex-1 overflow-y-auto p-2 space-y-2 min-h-[120px]",
6327
+ style: { paddingBottom: active ? gap + 8 : 8, transition: "padding-bottom 160ms ease" },
6328
+ children: [
6329
+ colItems.map((item, index) => {
6330
+ const id = getId(item);
6331
+ const shift = active && over !== null && index >= over.index ? gap : 0;
6332
+ const style = dragId === null ? {} : {
6333
+ transform: `translateY(${shift}px)`,
6334
+ transition: "transform 160ms cubic-bezier(0.2, 0, 0, 1), opacity 120ms ease",
6335
+ opacity: id === dragId ? 0.4 : 1
6336
+ };
6337
+ return /* @__PURE__ */ jsx(
6338
+ "div",
6339
+ {
6340
+ draggable: true,
6341
+ onDragStart: (e) => {
6342
+ setDragId(id);
6343
+ setFromCol(col.value);
6344
+ setGap(Math.round(e.currentTarget.getBoundingClientRect().height) + 8);
6345
+ try {
6346
+ e.dataTransfer.effectAllowed = "move";
6347
+ } catch {
6348
+ }
6349
+ },
6350
+ onDragEnter: (e) => {
6351
+ e.stopPropagation();
6352
+ setOver(
6353
+ (prev) => prev && prev.col === col.value && prev.index === index ? prev : { col: col.value, index }
6354
+ );
6355
+ },
6356
+ onDragEnd: reset,
6357
+ onClick: onCardClick ? () => onCardClick(item) : void 0,
6358
+ style,
6359
+ className: `rounded-lg bg-white border border-gray-200 p-3 shadow-sm hover:border-blue-400 hover:shadow transition ${onCardClick ? "cursor-pointer" : ""}`,
6360
+ children: renderCard(item)
6361
+ },
6362
+ id
6363
+ );
6364
+ }),
6365
+ colItems.length === 0 && /* @__PURE__ */ jsx(
6366
+ "div",
6367
+ {
6368
+ className: `text-[11px] text-center rounded-lg transition-all duration-150 ${active ? "border-2 border-dashed border-blue-300 bg-blue-50/50 text-blue-400 py-8" : "text-gray-400 py-6"}`,
6369
+ children: columnEmptyText
6370
+ }
6371
+ )
6372
+ ]
6373
+ }
6374
+ )
6375
+ ]
6376
+ },
6377
+ col.value
6378
+ );
6379
+ }) }) });
6380
+ }
6521
6381
  function useInfiniteScroll({
6522
6382
  queryKey,
6523
6383
  fetchFn,
@@ -6634,6 +6494,6 @@ function useEditHotkey(callback) {
6634
6494
  }, [callback, isActive]);
6635
6495
  }
6636
6496
 
6637
- export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, BugReportConfigProvider, BugReportDetail, BugReportProvider, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Customization, DEV_BANNER_TEXT, Desktop, DesktopHostProvider, DevIndicator, ENTER, EntityList, GlobalSearch, HelpCenter, Layout, ListFooter, MOD, MailConnectModal, Markdown, NotificationBell, ResizableTable, SHIFT, ShellEntityFetcherProvider, ShortcutHelp, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, SystemPreferences, VERSION, WidgetManager, applyDevTitle, createWindowRegistry, isDevEnv, isMac, openBugReportDialog, reportBug, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
6497
+ export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, BugReportConfigProvider, BugReportDetail, BugReportProvider, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Customization, DEV_BANNER_TEXT, Desktop, DesktopHostProvider, DevIndicator, ENTER, EntityList, GlobalSearch, HelpCenter, Kanban, Layout, ListFooter, MOD, Markdown, NotificationBell, ResizableTable, SHIFT, ShellEntityFetcherProvider, ShortcutHelp, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, SystemPreferences, VERSION, WidgetManager, applyDevTitle, createWindowRegistry, isDevEnv, isMac, openBugReportDialog, reportBug, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
6638
6498
  //# sourceMappingURL=index.js.map
6639
6499
  //# sourceMappingURL=index.js.map