react-os-shell 0.2.27 → 0.2.32

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 (48) hide show
  1. package/dist/{Browser-FZTIGZJH.js → Browser-5ZCLRIRU.js} +3 -3
  2. package/dist/{Browser-FZTIGZJH.js.map → Browser-5ZCLRIRU.js.map} +1 -1
  3. package/dist/{Calculator-4J7SP6HW.js → Calculator-OHL2AZ52.js} +4 -4
  4. package/dist/{Calculator-4J7SP6HW.js.map → Calculator-OHL2AZ52.js.map} +1 -1
  5. package/dist/{Calendar-QCQJEO2E.js → Calendar-6AHL3UJY.js} +3 -3
  6. package/dist/{Calendar-QCQJEO2E.js.map → Calendar-6AHL3UJY.js.map} +1 -1
  7. package/dist/{CurrencyConverter-WP6KZMEU.js → CurrencyConverter-XZVZ7XOF.js} +4 -4
  8. package/dist/{CurrencyConverter-WP6KZMEU.js.map → CurrencyConverter-XZVZ7XOF.js.map} +1 -1
  9. package/dist/{Documents-SWUWWRRB.js → Documents-IPVZ47JX.js} +3 -3
  10. package/dist/{Documents-SWUWWRRB.js.map → Documents-IPVZ47JX.js.map} +1 -1
  11. package/dist/{Email-ERTPCJOX.js → Email-Z7FDKAFD.js} +4 -4
  12. package/dist/{Email-ERTPCJOX.js.map → Email-Z7FDKAFD.js.map} +1 -1
  13. package/dist/Files-KEHRZ2UY.js +8 -0
  14. package/dist/{Files-3ZGMJXTR.js.map → Files-KEHRZ2UY.js.map} +1 -1
  15. package/dist/ImageAnnotator-CTTMAY5Z.js +4 -0
  16. package/dist/ImageAnnotator-CTTMAY5Z.js.map +1 -0
  17. package/dist/{Minesweeper-WVKECHOL.js → Minesweeper-NGN4O6C4.js} +3 -3
  18. package/dist/{Minesweeper-WVKECHOL.js.map → Minesweeper-NGN4O6C4.js.map} +1 -1
  19. package/dist/{Notepad-I5QTIZDV.js → Notepad-W3YYZ3GS.js} +3 -3
  20. package/dist/{Notepad-I5QTIZDV.js.map → Notepad-W3YYZ3GS.js.map} +1 -1
  21. package/dist/{PomodoroTimer-DGAITQZR.js → PomodoroTimer-T2J5NDJR.js} +4 -4
  22. package/dist/{PomodoroTimer-DGAITQZR.js.map → PomodoroTimer-T2J5NDJR.js.map} +1 -1
  23. package/dist/Preview-4354N46U.js +7 -0
  24. package/dist/{Preview-S7AGTRVP.js.map → Preview-4354N46U.js.map} +1 -1
  25. package/dist/{Spreadsheet-R2VRFGAS.js → Spreadsheet-FCFII6DW.js} +3 -3
  26. package/dist/{Spreadsheet-R2VRFGAS.js.map → Spreadsheet-FCFII6DW.js.map} +1 -1
  27. package/dist/{Weather-KZPNE4TY.js → Weather-JZHYW5XF.js} +4 -4
  28. package/dist/{Weather-KZPNE4TY.js.map → Weather-JZHYW5XF.js.map} +1 -1
  29. package/dist/apps/index.js +17 -16
  30. package/dist/apps/index.js.map +1 -1
  31. package/dist/{chunk-3DJAOGL7.js → chunk-2SRU4BYH.js} +4 -4
  32. package/dist/{chunk-3DJAOGL7.js.map → chunk-2SRU4BYH.js.map} +1 -1
  33. package/dist/{chunk-6PX6HT6T.js → chunk-IY7JJVHR.js} +6 -970
  34. package/dist/chunk-IY7JJVHR.js.map +1 -0
  35. package/dist/chunk-KUIPWCTJ.js +999 -0
  36. package/dist/chunk-KUIPWCTJ.js.map +1 -0
  37. package/dist/{chunk-I7GRSFIL.js → chunk-T2NQXP2J.js} +27 -5
  38. package/dist/chunk-T2NQXP2J.js.map +1 -0
  39. package/dist/{chunk-EQ3MNYLX.js → chunk-TVOBLSSV.js} +3 -3
  40. package/dist/{chunk-EQ3MNYLX.js.map → chunk-TVOBLSSV.js.map} +1 -1
  41. package/dist/index.d.ts +12 -3
  42. package/dist/index.js +131 -31
  43. package/dist/index.js.map +1 -1
  44. package/package.json +1 -1
  45. package/dist/Files-3ZGMJXTR.js +0 -7
  46. package/dist/Preview-S7AGTRVP.js +0 -6
  47. package/dist/chunk-6PX6HT6T.js.map +0 -1
  48. package/dist/chunk-I7GRSFIL.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { Modal } from './chunk-I7GRSFIL.js';
1
+ import { Modal } from './chunk-T2NQXP2J.js';
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
3
 
4
4
  var DEFAULT_APPEARANCE = { activeOpacity: 70, inactiveOpacity: 50, activeBlur: 0, inactiveBlur: 0 };
@@ -138,5 +138,5 @@ function WidgetSettingsModal({ open, onClose, title, appearance, onAppearanceCha
138
138
  }
139
139
 
140
140
  export { WidgetSettingsModal, loadAppearance };
141
- //# sourceMappingURL=chunk-EQ3MNYLX.js.map
142
- //# sourceMappingURL=chunk-EQ3MNYLX.js.map
141
+ //# sourceMappingURL=chunk-TVOBLSSV.js.map
142
+ //# sourceMappingURL=chunk-TVOBLSSV.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/shell/WidgetSettingsModal.tsx"],"names":[],"mappings":"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","file":"chunk-EQ3MNYLX.js","sourcesContent":["import Modal from './Modal';\n\nexport interface WidgetAppearance {\n activeOpacity: number;\n inactiveOpacity: number;\n activeBlur: number;\n inactiveBlur: number;\n}\n\nexport const DEFAULT_APPEARANCE: WidgetAppearance = { activeOpacity: 70, inactiveOpacity: 50, activeBlur: 0, inactiveBlur: 0 };\n\nexport function loadAppearance(key: string): WidgetAppearance {\n try {\n const saved = JSON.parse(localStorage.getItem(key) || '');\n // Migrate old single `blur` field to activeBlur/inactiveBlur\n if (saved.blur != null && saved.activeBlur == null) {\n saved.activeBlur = saved.blur;\n saved.inactiveBlur = saved.blur;\n delete saved.blur;\n }\n return { ...DEFAULT_APPEARANCE, ...saved };\n }\n catch { return DEFAULT_APPEARANCE; }\n}\n\n/** Reusable settings modal for widgets — renders appearance sliders + optional extra content above */\nexport default function WidgetSettingsModal({ open, onClose, title, appearance, onAppearanceChange, onSave, children }: {\n open: boolean;\n onClose: () => void;\n title: string;\n appearance: WidgetAppearance;\n onAppearanceChange: (a: WidgetAppearance) => void;\n onSave: () => void;\n children?: React.ReactNode;\n}) {\n if (!open) return null;\n\n const inp = 'w-full h-1.5 rounded-full appearance-none bg-gray-200 cursor-pointer accent-blue-500';\n const lbl = 'flex items-center justify-between text-xs text-gray-500';\n\n return (\n <div onPointerDown={e => e.stopPropagation()} onContextMenu={e => e.stopPropagation()}>\n <Modal open={open} onClose={onClose} title={title} size=\"sm\">\n <div className=\"space-y-4\">\n {children}\n\n {/* Appearance */}\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-3\">Appearance</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <div className=\"text-xs font-medium text-gray-600 mb-2\">Active</div>\n <div className=\"space-y-2\">\n <div>\n <div className={lbl}><span>Opacity</span><span>{appearance.activeOpacity}%</span></div>\n <input type=\"range\" min={20} max={100} value={appearance.activeOpacity}\n onChange={e => onAppearanceChange({ ...appearance, activeOpacity: +e.target.value })} className={inp} />\n </div>\n <div>\n <div className={lbl}><span>Blur</span><span>{appearance.activeBlur}px</span></div>\n <input type=\"range\" min={0} max={20} value={appearance.activeBlur}\n onChange={e => onAppearanceChange({ ...appearance, activeBlur: +e.target.value })} className={inp} />\n </div>\n </div>\n </div>\n <div>\n <div className=\"text-xs font-medium text-gray-600 mb-2\">Inactive</div>\n <div className=\"space-y-2\">\n <div>\n <div className={lbl}><span>Opacity</span><span>{appearance.inactiveOpacity}%</span></div>\n <input type=\"range\" min={20} max={100} value={appearance.inactiveOpacity}\n onChange={e => onAppearanceChange({ ...appearance, inactiveOpacity: +e.target.value })} className={inp} />\n </div>\n <div>\n <div className={lbl}><span>Blur</span><span>{appearance.inactiveBlur}px</span></div>\n <input type=\"range\" min={0} max={20} value={appearance.inactiveBlur}\n onChange={e => onAppearanceChange({ ...appearance, inactiveBlur: +e.target.value })} className={inp} />\n </div>\n </div>\n </div>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex gap-2 pt-2\">\n <button onClick={onSave}\n className=\"flex-1 text-sm font-medium py-2 rounded-lg bg-blue-600 text-white hover:bg-blue-700 transition\">Save</button>\n <button onClick={onClose}\n className=\"flex-1 text-sm font-medium py-2 rounded-lg border border-gray-300 text-gray-600 hover:bg-gray-50 transition\">Cancel</button>\n </div>\n </div>\n </Modal>\n </div>\n );\n}\n"]}
1
+ {"version":3,"sources":["../src/shell/WidgetSettingsModal.tsx"],"names":[],"mappings":"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","file":"chunk-TVOBLSSV.js","sourcesContent":["import Modal from './Modal';\n\nexport interface WidgetAppearance {\n activeOpacity: number;\n inactiveOpacity: number;\n activeBlur: number;\n inactiveBlur: number;\n}\n\nexport const DEFAULT_APPEARANCE: WidgetAppearance = { activeOpacity: 70, inactiveOpacity: 50, activeBlur: 0, inactiveBlur: 0 };\n\nexport function loadAppearance(key: string): WidgetAppearance {\n try {\n const saved = JSON.parse(localStorage.getItem(key) || '');\n // Migrate old single `blur` field to activeBlur/inactiveBlur\n if (saved.blur != null && saved.activeBlur == null) {\n saved.activeBlur = saved.blur;\n saved.inactiveBlur = saved.blur;\n delete saved.blur;\n }\n return { ...DEFAULT_APPEARANCE, ...saved };\n }\n catch { return DEFAULT_APPEARANCE; }\n}\n\n/** Reusable settings modal for widgets — renders appearance sliders + optional extra content above */\nexport default function WidgetSettingsModal({ open, onClose, title, appearance, onAppearanceChange, onSave, children }: {\n open: boolean;\n onClose: () => void;\n title: string;\n appearance: WidgetAppearance;\n onAppearanceChange: (a: WidgetAppearance) => void;\n onSave: () => void;\n children?: React.ReactNode;\n}) {\n if (!open) return null;\n\n const inp = 'w-full h-1.5 rounded-full appearance-none bg-gray-200 cursor-pointer accent-blue-500';\n const lbl = 'flex items-center justify-between text-xs text-gray-500';\n\n return (\n <div onPointerDown={e => e.stopPropagation()} onContextMenu={e => e.stopPropagation()}>\n <Modal open={open} onClose={onClose} title={title} size=\"sm\">\n <div className=\"space-y-4\">\n {children}\n\n {/* Appearance */}\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-3\">Appearance</h3>\n <div className=\"grid grid-cols-2 gap-4\">\n <div>\n <div className=\"text-xs font-medium text-gray-600 mb-2\">Active</div>\n <div className=\"space-y-2\">\n <div>\n <div className={lbl}><span>Opacity</span><span>{appearance.activeOpacity}%</span></div>\n <input type=\"range\" min={20} max={100} value={appearance.activeOpacity}\n onChange={e => onAppearanceChange({ ...appearance, activeOpacity: +e.target.value })} className={inp} />\n </div>\n <div>\n <div className={lbl}><span>Blur</span><span>{appearance.activeBlur}px</span></div>\n <input type=\"range\" min={0} max={20} value={appearance.activeBlur}\n onChange={e => onAppearanceChange({ ...appearance, activeBlur: +e.target.value })} className={inp} />\n </div>\n </div>\n </div>\n <div>\n <div className=\"text-xs font-medium text-gray-600 mb-2\">Inactive</div>\n <div className=\"space-y-2\">\n <div>\n <div className={lbl}><span>Opacity</span><span>{appearance.inactiveOpacity}%</span></div>\n <input type=\"range\" min={20} max={100} value={appearance.inactiveOpacity}\n onChange={e => onAppearanceChange({ ...appearance, inactiveOpacity: +e.target.value })} className={inp} />\n </div>\n <div>\n <div className={lbl}><span>Blur</span><span>{appearance.inactiveBlur}px</span></div>\n <input type=\"range\" min={0} max={20} value={appearance.inactiveBlur}\n onChange={e => onAppearanceChange({ ...appearance, inactiveBlur: +e.target.value })} className={inp} />\n </div>\n </div>\n </div>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex gap-2 pt-2\">\n <button onClick={onSave}\n className=\"flex-1 text-sm font-medium py-2 rounded-lg bg-blue-600 text-white hover:bg-blue-700 transition\">Save</button>\n <button onClick={onClose}\n className=\"flex-1 text-sm font-medium py-2 rounded-lg border border-gray-300 text-gray-600 hover:bg-gray-50 transition\">Cancel</button>\n </div>\n </div>\n </Modal>\n </div>\n );\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -329,14 +329,16 @@ interface NotificationBellProps extends NotificationsConfig {
329
329
  declare function NotificationBell({ useUnreadCount, list, markRead, markAllRead, onItemClick, onViewAll, popDirection, }: NotificationBellProps): react_jsx_runtime.JSX.Element;
330
330
 
331
331
  /**
332
- * Bug report review dialog — shows the captured screenshot and lets the user
333
- * add a quick description before sending.
332
+ * Feedback dialog — shows the captured screenshot and lets the user pick
333
+ * Bug or Suggestion and add a quick description before sending.
334
334
  *
335
335
  * Triggered imperatively from utils/reportBug.ts via openBugReportDialog().
336
336
  * The Provider is mounted once at the App root.
337
337
  */
338
+ type ReportType = 'bug' | 'suggestion';
338
339
  interface BugReportSubmission {
339
340
  description: string;
341
+ reportType: ReportType;
340
342
  }
341
343
  /** Generic bug-report record shape consumed by the shell's list/detail UI. */
342
344
  interface BugReport {
@@ -348,6 +350,7 @@ interface BugReport {
348
350
  user_agent?: string;
349
351
  viewport?: string;
350
352
  description?: string;
353
+ report_type?: ReportType;
351
354
  is_resolved: boolean;
352
355
  resolution_note?: string;
353
356
  created_at: string;
@@ -360,6 +363,7 @@ interface BugReportSubmitPayload {
360
363
  url: string;
361
364
  userAgent: string;
362
365
  viewport: string;
366
+ reportType: ReportType;
363
367
  }
364
368
  /** Config bundle for the bug-report subsystem. Consumer-supplied; the shell
365
369
  * never calls a hardcoded URL. */
@@ -376,6 +380,10 @@ interface BugReportConfig {
376
380
  }>;
377
381
  /** Mark a report resolved or reopened, with an optional admin note. */
378
382
  resolve?: (id: string, is_resolved: boolean, resolution_note?: string) => Promise<BugReport>;
383
+ /** Permanently delete a report. When omitted the Delete button in
384
+ * `<BugReportDetail>` is hidden — the consumer's permission system
385
+ * decides whether to expose the capability at all. */
386
+ delete?: (id: string) => Promise<void>;
379
387
  }
380
388
  declare function BugReportConfigProvider({ value, children }: {
381
389
  value: BugReportConfig;
@@ -392,9 +400,10 @@ declare function BugReportProvider({ children }: {
392
400
 
393
401
  interface Props {
394
402
  report: BugReport;
403
+ /** Called after a successful delete so the parent window can close itself. */
395
404
  onClose?: () => void;
396
405
  }
397
- declare function BugReportDetail({ report }: Props): react_jsx_runtime.JSX.Element;
406
+ declare function BugReportDetail({ report, onClose }: Props): react_jsx_runtime.JSX.Element;
398
407
 
399
408
  type SemanticGroup = 'success' | 'active' | 'queued' | 'info' | 'pending' | 'warning' | 'danger' | 'draft' | 'neutral';
400
409
  declare function StatusBadgeProvider({ groups, children, }: {
package/dist/index.js CHANGED
@@ -5,13 +5,15 @@ import { useGoogleAuth } from './chunk-46LICZUM.js';
5
5
  import { useShellPrefs } from './chunk-36VM54SC.js';
6
6
  export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
7
7
  import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, playLogout, setSoundForType, previewSound, setAllSounds } from './chunk-D7PYW2QS.js';
8
- import { setPdfPreview } from './chunk-6PX6HT6T.js';
8
+ import { setPdfPreview } from './chunk-IY7JJVHR.js';
9
+ import './chunk-KUIPWCTJ.js';
9
10
  import { toast_default } from './chunk-WIJ45SYD.js';
10
11
  export { toast_default as toast } from './chunk-WIJ45SYD.js';
11
- import { useWindowManager, glassStyle, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, startMenuCategories, useIsMobile, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons, ModalActions, useModalActive, WINDOW_REGISTRY, isPageEntry, LoadingSpinner, ThumbCard, activateModal } from './chunk-I7GRSFIL.js';
12
- export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, glassStyle, isEntityEntry, isPageEntry, setShellApiClient, setShellNavIcons, setShellWindowRegistry, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-I7GRSFIL.js';
12
+ import { useWindowManager, glassStyle, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, startMenuCategories, useIsMobile, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons, ModalActions, useModalActive, WINDOW_REGISTRY, isPageEntry, LoadingSpinner, ThumbCard, activateModal } from './chunk-T2NQXP2J.js';
13
+ export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, glassStyle, isEntityEntry, isPageEntry, setShellApiClient, setShellNavIcons, setShellWindowRegistry, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-T2NQXP2J.js';
14
+ import { confirm } from './chunk-PLGHQ7QW.js';
13
15
  export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-PLGHQ7QW.js';
14
- import { createContext, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, isValidElement, cloneElement, useSyncExternalStore, useMemo, Suspense } from 'react';
16
+ import { createContext, lazy, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement, useSyncExternalStore, useMemo } from 'react';
15
17
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
16
18
  import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
17
19
  import { createPortal } from 'react-dom';
@@ -479,10 +481,13 @@ function BugReportProvider({ children }) {
479
481
  const [screenshot, setScreenshot] = useState(null);
480
482
  const [previewUrl, setPreviewUrl] = useState(null);
481
483
  const [description, setDescription] = useState("");
484
+ const [reportType, setReportType] = useState("bug");
485
+ const [annotating, setAnnotating] = useState(false);
482
486
  const resolveRef = useRef();
483
487
  const openFn = useCallback((s) => {
484
488
  setScreenshot(s);
485
489
  setDescription("");
490
+ setReportType("bug");
486
491
  setOpen(true);
487
492
  return new Promise((resolve) => {
488
493
  resolveRef.current = resolve;
@@ -502,23 +507,62 @@ function BugReportProvider({ children }) {
502
507
  }, [screenshot]);
503
508
  const handleSubmit = () => {
504
509
  setOpen(false);
505
- resolveRef.current?.({ description: description.trim() });
510
+ resolveRef.current?.({ description: description.trim(), reportType });
506
511
  };
507
512
  const handleCancel = () => {
508
513
  setOpen(false);
509
514
  resolveRef.current?.(null);
510
515
  };
516
+ const isBug = reportType === "bug";
511
517
  return /* @__PURE__ */ jsxs(Fragment, { children: [
512
518
  children,
513
519
  /* @__PURE__ */ jsxs(Dialog, { open, onClose: handleCancel, className: "relative z-[9999]", children: [
514
520
  /* @__PURE__ */ jsx(DialogBackdrop, { className: "fixed inset-0 bg-black/40" }),
515
521
  /* @__PURE__ */ jsx("div", { className: "fixed inset-0 flex items-center justify-center p-4", children: /* @__PURE__ */ jsxs(DialogPanel, { className: "w-full max-w-2xl rounded-lg bg-white p-6 shadow-xl", children: [
516
- /* @__PURE__ */ jsx(DialogTitle, { className: "text-base font-semibold text-gray-900", children: "Report a bug" }),
522
+ /* @__PURE__ */ jsx(DialogTitle, { className: "text-base font-semibold text-gray-900", children: "Suggestion or Bug" }),
517
523
  /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-gray-500", children: "A screenshot of your current view will be sent to the admin team." }),
518
- previewUrl && /* @__PURE__ */ jsx("div", { className: "mt-4 rounded-md border border-gray-200 overflow-hidden bg-gray-50 max-h-64", children: /* @__PURE__ */ jsx("img", { src: previewUrl, alt: "Screenshot preview", className: "w-full h-auto max-h-64 object-contain" }) }),
524
+ /* @__PURE__ */ jsxs("div", { className: "mt-4 inline-flex rounded-lg border border-gray-300 bg-gray-50 p-0.5", children: [
525
+ /* @__PURE__ */ jsx(
526
+ "button",
527
+ {
528
+ type: "button",
529
+ onClick: () => setReportType("bug"),
530
+ className: `px-3 py-1 text-sm font-medium rounded-md transition-colors ${isBug ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
531
+ children: "Bug"
532
+ }
533
+ ),
534
+ /* @__PURE__ */ jsx(
535
+ "button",
536
+ {
537
+ type: "button",
538
+ onClick: () => setReportType("suggestion"),
539
+ className: `px-3 py-1 text-sm font-medium rounded-md transition-colors ${!isBug ? "bg-white text-gray-900 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
540
+ children: "Suggestion"
541
+ }
542
+ )
543
+ ] }),
544
+ previewUrl && /* @__PURE__ */ jsxs("div", { className: "mt-4", children: [
545
+ /* @__PURE__ */ jsxs("div", { className: "relative rounded-md border border-gray-200 overflow-hidden bg-gray-50 max-h-64", children: [
546
+ /* @__PURE__ */ jsx("img", { src: previewUrl, alt: "Screenshot preview", className: "w-full h-auto max-h-64 object-contain" }),
547
+ /* @__PURE__ */ jsxs(
548
+ "button",
549
+ {
550
+ type: "button",
551
+ onClick: () => setAnnotating(true),
552
+ className: "absolute top-2 right-2 inline-flex items-center gap-1 px-2.5 py-1 rounded-md bg-white/95 backdrop-blur border border-gray-200 shadow-sm text-xs font-medium text-gray-700 hover:bg-white",
553
+ title: "Mark up the screenshot \u2014 circle, arrow, mosaic, text\u2026",
554
+ children: [
555
+ /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.7, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125" }) }),
556
+ "Annotate"
557
+ ]
558
+ }
559
+ )
560
+ ] }),
561
+ /* @__PURE__ */ jsx("p", { className: "mt-1 text-[11px] text-gray-400", children: "Click Annotate to mark up the screenshot before sending." })
562
+ ] }),
519
563
  !previewUrl && /* @__PURE__ */ jsx("div", { className: "mt-4 rounded-md border border-dashed border-gray-300 px-4 py-6 text-center text-sm text-gray-500", children: "Screenshot capture failed \u2014 your description will still be sent." }),
520
564
  /* @__PURE__ */ jsxs("label", { className: "mt-4 block text-sm font-medium text-gray-700", children: [
521
- "What went wrong?",
565
+ isBug ? "What went wrong?" : "What's your suggestion?",
522
566
  /* @__PURE__ */ jsx("span", { className: "font-normal text-gray-400 ml-1", children: "(optional)" })
523
567
  ] }),
524
568
  /* @__PURE__ */ jsx(
@@ -530,7 +574,7 @@ function BugReportProvider({ children }) {
530
574
  onKeyDown: (e) => {
531
575
  if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) handleSubmit();
532
576
  },
533
- placeholder: "Briefly describe the issue, what you were doing, what you expected to happen\u2026",
577
+ placeholder: isBug ? "Briefly describe the issue, what you were doing, what you expected to happen\u2026" : "Briefly describe what would make this better\u2026",
534
578
  rows: 3,
535
579
  className: "mt-1 w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:ring-1 focus:ring-blue-500 focus:outline-none resize-none"
536
580
  }
@@ -551,33 +595,54 @@ function BugReportProvider({ children }) {
551
595
  type: "button",
552
596
  onClick: handleSubmit,
553
597
  className: "bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 text-sm font-medium rounded-lg",
554
- children: "Send Report"
598
+ children: "Send"
555
599
  }
556
600
  )
557
601
  ] })
558
602
  ] }) })
559
- ] })
603
+ ] }),
604
+ annotating && previewUrl && /* @__PURE__ */ jsx(
605
+ BugReportAnnotator,
606
+ {
607
+ src: previewUrl,
608
+ onApply: (blob) => {
609
+ setScreenshot(blob);
610
+ setAnnotating(false);
611
+ },
612
+ onCancel: () => setAnnotating(false)
613
+ }
614
+ )
560
615
  ] });
561
616
  }
617
+ var LazyImageAnnotator = lazy(() => import('./ImageAnnotator-CTTMAY5Z.js'));
618
+ function BugReportAnnotator({
619
+ src,
620
+ onApply,
621
+ onCancel
622
+ }) {
623
+ return /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-[10000] bg-black/60 backdrop-blur-sm flex flex-col", children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center text-sm text-white/80", children: "Loading editor\u2026" }), children: /* @__PURE__ */ jsx("div", { className: "flex-1 m-4 rounded-lg overflow-hidden bg-white shadow-2xl", children: /* @__PURE__ */ jsx(LazyImageAnnotator, { src, filename: "screenshot.png", onApply, onCancel }) }) }) });
624
+ }
562
625
  function StatePill({ resolved }) {
563
626
  return /* @__PURE__ */ jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${resolved ? "bg-green-100 text-green-800" : "bg-yellow-100 text-yellow-800"}`, children: resolved ? "Resolved" : "Open" });
564
627
  }
565
- function BugReportDetail({ report }) {
628
+ function BugReportDetail({ report, onClose }) {
566
629
  const qc = useQueryClient();
567
630
  const config = useBugReport();
568
631
  const { openPage } = useWindowManager();
569
632
  const [resolveOpen, setResolveOpen] = useState(false);
570
633
  const [note, setNote] = useState("");
634
+ const kind = report.report_type === "suggestion" ? "suggestion" : "bug";
635
+ const Kind = kind === "suggestion" ? "Suggestion" : "Bug";
571
636
  const openScreenshot = () => {
572
637
  if (!report.screenshot_url) return;
573
- const filename = `bug-report-${report.id}-screenshot.png`;
638
+ const filename = `${kind}-${report.id}-screenshot.png`;
574
639
  setPdfPreview({ url: report.screenshot_url, filename, kind: "image" });
575
640
  openPage("/preview");
576
641
  };
577
642
  const resolve = useMutation({
578
643
  mutationFn: ({ is_resolved, resolution_note }) => {
579
644
  if (!config?.resolve) {
580
- return Promise.reject(new Error("Bug report resolve is not configured."));
645
+ return Promise.reject(new Error("Resolve is not configured."));
581
646
  }
582
647
  return config.resolve(report.id, is_resolved, resolution_note);
583
648
  },
@@ -587,8 +652,31 @@ function BugReportDetail({ report }) {
587
652
  setResolveOpen(false);
588
653
  setNote("");
589
654
  },
590
- meta: { success: (d) => d.is_resolved ? "Bug report marked resolved." : "Bug report reopened." }
655
+ meta: { success: (d) => d.is_resolved ? `${Kind} marked resolved.` : `${Kind} reopened.` }
591
656
  });
657
+ const del = useMutation({
658
+ mutationFn: () => {
659
+ if (!config?.delete) return Promise.reject(new Error("Delete is not configured."));
660
+ return config.delete(report.id);
661
+ },
662
+ onSuccess: () => {
663
+ qc.invalidateQueries({ queryKey: ["bug-reports"] });
664
+ qc.removeQueries({ queryKey: ["entity", "bug_report", report.id] });
665
+ onClose?.();
666
+ },
667
+ meta: { success: () => `${Kind} deleted.` }
668
+ });
669
+ const handleDelete = async () => {
670
+ const ok = await confirm({
671
+ title: `Delete this ${kind}?`,
672
+ message: "This is permanent and cannot be undone.",
673
+ confirmLabel: "Delete",
674
+ cancelLabel: "Keep",
675
+ variant: "danger"
676
+ });
677
+ if (!ok) return;
678
+ del.mutate();
679
+ };
592
680
  const handleAction = () => {
593
681
  if (report.is_resolved) {
594
682
  resolve.mutate({ is_resolved: false, resolution_note: "" });
@@ -627,16 +715,27 @@ function BugReportDetail({ report }) {
627
715
  className: "w-full rounded-lg border border-gray-200 hover:border-blue-400 transition-colors"
628
716
  }
629
717
  ) }) : /* @__PURE__ */ jsx("div", { className: "rounded-lg border border-dashed border-gray-300 p-6 text-center text-sm text-gray-400", children: "No screenshot was captured for this report." }),
630
- config?.resolve && /* @__PURE__ */ jsx("div", { className: "flex justify-end pt-2 border-t border-gray-200", children: /* @__PURE__ */ jsx(
631
- "button",
632
- {
633
- onClick: handleAction,
634
- disabled: resolve.isPending,
635
- className: `px-3 py-1.5 text-sm rounded-lg font-medium transition-colors ${report.is_resolved ? "bg-white border border-gray-300 text-gray-700 hover:bg-gray-50" : "bg-blue-600 text-white hover:bg-blue-700"}`,
636
- children: resolve.isPending ? "..." : report.is_resolved ? "Reopen" : "Mark Resolved"
637
- }
638
- ) }),
639
- /* @__PURE__ */ jsx(Modal, { open: resolveOpen, onClose: () => !resolve.isPending && setResolveOpen(false), title: `Resolve ${report.report_code}`, size: "md", compact: true, children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
718
+ (config?.resolve || config?.delete) && /* @__PURE__ */ jsxs("div", { className: "flex justify-end items-center gap-2 pt-2 border-t border-gray-200", children: [
719
+ config?.delete && /* @__PURE__ */ jsx(
720
+ "button",
721
+ {
722
+ onClick: handleDelete,
723
+ disabled: del.isPending || resolve.isPending,
724
+ className: "px-3 py-1.5 text-sm rounded-lg font-medium transition-colors bg-white border border-red-300 text-red-700 hover:bg-red-50 disabled:opacity-50 mr-auto",
725
+ children: del.isPending ? "Deleting\u2026" : "Delete"
726
+ }
727
+ ),
728
+ config?.resolve && /* @__PURE__ */ jsx(
729
+ "button",
730
+ {
731
+ onClick: handleAction,
732
+ disabled: resolve.isPending || del.isPending,
733
+ className: `px-3 py-1.5 text-sm rounded-lg font-medium transition-colors ${report.is_resolved ? "bg-white border border-gray-300 text-gray-700 hover:bg-gray-50" : "bg-blue-600 text-white hover:bg-blue-700"}`,
734
+ children: resolve.isPending ? "..." : report.is_resolved ? "Reopen" : "Mark Resolved"
735
+ }
736
+ )
737
+ ] }),
738
+ /* @__PURE__ */ jsx(Modal, { open: resolveOpen, onClose: () => !resolve.isPending && setResolveOpen(false), title: `Resolve ${report.report_code ?? Kind}`, size: "md", compact: true, children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
640
739
  /* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-600", children: [
641
740
  "Add a short note for ",
642
741
  report.reporter_name || "the reporter",
@@ -706,7 +805,7 @@ function StatusBadge({ status }) {
706
805
  }
707
806
 
708
807
  // src/version.ts
709
- var VERSION = "0.2.27" ;
808
+ var VERSION = "0.2.31" ;
710
809
  var APP_VERSION = VERSION;
711
810
 
712
811
  // src/changelog.ts
@@ -751,11 +850,12 @@ async function reportBug(submit) {
751
850
  screenshot: screenshot ?? void 0,
752
851
  url: window.location.href,
753
852
  userAgent: navigator.userAgent,
754
- viewport: `${window.innerWidth}x${window.innerHeight}`
853
+ viewport: `${window.innerWidth}x${window.innerHeight}`,
854
+ reportType: submission.reportType
755
855
  });
756
- toast_default.success("Bug report sent to admins.");
856
+ toast_default.success(submission.reportType === "bug" ? "Bug sent to admins." : "Suggestion sent to admins.");
757
857
  } catch (err) {
758
- toast_default.error(err?.response?.data?.detail || "Failed to send bug report.");
858
+ toast_default.error(err?.response?.data?.detail || "Failed to send.");
759
859
  }
760
860
  }
761
861
  var ENTITY_ICON_COLORS = {
@@ -1916,7 +2016,7 @@ function Desktop({ profile }) {
1916
2016
  reportBug(bugReport.submit);
1917
2017
  }, children: [
1918
2018
  /* @__PURE__ */ jsx("svg", { className: "h-4 w-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z" }) }),
1919
- "Report Bug"
2019
+ "Suggestion or Bug"
1920
2020
  ] })
1921
2021
  ] })
1922
2022
  ] }),
@@ -3820,7 +3920,7 @@ function TaskbarContextMenu({ x, y, position, size, onChangePosition, onChangeSi
3820
3920
  style: { width: "calc(100% - 8px)" },
3821
3921
  children: [
3822
3922
  /* @__PURE__ */ jsx("span", { className: "w-3.5 shrink-0" }),
3823
- "Report Bug"
3923
+ "Suggestion or Bug"
3824
3924
  ]
3825
3925
  }
3826
3926
  )