react-os-shell 0.9.0 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +2 -1
  2. package/dist/{Browser-WVSS64J6.js → Browser-W63A4RUT.js} +3 -3
  3. package/dist/{Browser-WVSS64J6.js.map → Browser-W63A4RUT.js.map} +1 -1
  4. package/dist/{Calculator-37EIFRDU.js → Calculator-Z2DAZD6K.js} +4 -4
  5. package/dist/{Calculator-37EIFRDU.js.map → Calculator-Z2DAZD6K.js.map} +1 -1
  6. package/dist/{CurrencyConverter-PWX3FKRK.js → CurrencyConverter-S6RQB3OJ.js} +4 -4
  7. package/dist/{CurrencyConverter-PWX3FKRK.js.map → CurrencyConverter-S6RQB3OJ.js.map} +1 -1
  8. package/dist/{Documents-W2DABIOW.js → Documents-VE5Z7DRX.js} +3 -3
  9. package/dist/{Documents-W2DABIOW.js.map → Documents-VE5Z7DRX.js.map} +1 -1
  10. package/dist/Files-5IXGRZKM.js +11 -0
  11. package/dist/{Files-XNAPEBFF.js.map → Files-5IXGRZKM.js.map} +1 -1
  12. package/dist/{Minesweeper-M6HIJYPL.js → Minesweeper-WVAFWKCZ.js} +3 -3
  13. package/dist/{Minesweeper-M6HIJYPL.js.map → Minesweeper-WVAFWKCZ.js.map} +1 -1
  14. package/dist/{Notepad-MXEQCIC7.js → Notepad-OLNPHKTT.js} +3 -3
  15. package/dist/{Notepad-MXEQCIC7.js.map → Notepad-OLNPHKTT.js.map} +1 -1
  16. package/dist/{PomodoroTimer-5K55K26A.js → PomodoroTimer-ZJYDPFCT.js} +4 -4
  17. package/dist/{PomodoroTimer-5K55K26A.js.map → PomodoroTimer-ZJYDPFCT.js.map} +1 -1
  18. package/dist/Preview-LTZOUTQ7.js +8 -0
  19. package/dist/{Preview-VMKMY6SY.js.map → Preview-LTZOUTQ7.js.map} +1 -1
  20. package/dist/Spreadsheet-VT3ZISIN.js +6 -0
  21. package/dist/{Spreadsheet-UZMNMLZH.js.map → Spreadsheet-VT3ZISIN.js.map} +1 -1
  22. package/dist/{Stock-ZXZOCSJD.js → Stock-DWESS6UC.js} +4 -4
  23. package/dist/{Stock-ZXZOCSJD.js.map → Stock-DWESS6UC.js.map} +1 -1
  24. package/dist/{Weather-R6ULA547.js → Weather-NJHYEKH3.js} +4 -4
  25. package/dist/{Weather-R6ULA547.js.map → Weather-NJHYEKH3.js.map} +1 -1
  26. package/dist/{WorldClock-HHIBQXUR.js → WorldClock-UJKD253K.js} +4 -4
  27. package/dist/{WorldClock-HHIBQXUR.js.map → WorldClock-UJKD253K.js.map} +1 -1
  28. package/dist/apps/index.d.ts +1 -1
  29. package/dist/apps/index.js +18 -18
  30. package/dist/{chunk-SUUADOG6.js → chunk-3SIZAHR6.js} +4 -4
  31. package/dist/{chunk-SUUADOG6.js.map → chunk-3SIZAHR6.js.map} +1 -1
  32. package/dist/{chunk-ZETQWO2W.js → chunk-66GIT3PM.js} +3 -3
  33. package/dist/{chunk-ZETQWO2W.js.map → chunk-66GIT3PM.js.map} +1 -1
  34. package/dist/{chunk-LWVRQWGV.js → chunk-BS7EHYBT.js} +3 -3
  35. package/dist/{chunk-LWVRQWGV.js.map → chunk-BS7EHYBT.js.map} +1 -1
  36. package/dist/{chunk-KJ5664G7.js → chunk-DMSHU2HJ.js} +3 -3
  37. package/dist/{chunk-KJ5664G7.js.map → chunk-DMSHU2HJ.js.map} +1 -1
  38. package/dist/{chunk-CDSFAXIS.js → chunk-EFNKEBDB.js} +4 -4
  39. package/dist/{chunk-CDSFAXIS.js.map → chunk-EFNKEBDB.js.map} +1 -1
  40. package/dist/{chunk-3T6SQ4UO.js → chunk-IMFUTSYY.js} +5 -5
  41. package/dist/chunk-IMFUTSYY.js.map +1 -0
  42. package/dist/index.d.ts +67 -15
  43. package/dist/index.js +131 -54
  44. package/dist/index.js.map +1 -1
  45. package/dist/{types-D_4ifuf-.d.ts → types-BYiS2cc8.d.ts} +5 -0
  46. package/package.json +1 -1
  47. package/dist/Files-XNAPEBFF.js +0 -11
  48. package/dist/Preview-VMKMY6SY.js +0 -8
  49. package/dist/Spreadsheet-UZMNMLZH.js +0 -6
  50. package/dist/chunk-3T6SQ4UO.js.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { W as WindowRegistry } from './types-D_4ifuf-.js';
2
- export { M as ModalRegistryEntry, P as PageRegistryEntry, a as WindowRegistryEntry, i as isEntityEntry, b as isPageEntry, s as setShellWindowRegistry } from './types-D_4ifuf-.js';
1
+ import { W as WindowRegistry } from './types-BYiS2cc8.js';
2
+ export { M as ModalRegistryEntry, P as PageRegistryEntry, a as WindowRegistryEntry, i as isEntityEntry, b as isPageEntry, s as setShellWindowRegistry } from './types-BYiS2cc8.js';
3
3
  import * as react from 'react';
4
4
  import react__default, { ReactNode, CSSProperties, Dispatch, SetStateAction, RefObject } from 'react';
5
5
  import * as react_jsx_runtime from 'react/jsx-runtime';
@@ -200,6 +200,10 @@ interface ModalProps {
200
200
  * self-chromed apps like Preview, Files, Browser. Implies `bodyScroll: false`
201
201
  * — apps manage their own scrolling internally. */
202
202
  appStyle?: boolean;
203
+ /** Flush body: keeps the STANDARD full title bar and footer, but drops the
204
+ * body padding so the content sits flush to the window edges (e.g. a
205
+ * `<SidebarLayout>`). Implies `bodyScroll: false`. */
206
+ flushBody?: boolean;
203
207
  /** Auto-size height based on content. Window's height adapts to whatever the
204
208
  * body renders; combined with `autoMinHeight` to prevent collapse and capped
205
209
  * to the available viewport so nothing overflows the screen. Only set this
@@ -232,7 +236,7 @@ declare function setExposeHighlight(id: string | null): void;
232
236
  */
233
237
  declare function commitExposeHighlight(): void;
234
238
 
235
- declare function Modal({ open, onClose, title, icon, copyText, size, dirty, onNext, onPrev, footer, bodyScroll, onMinimize, initialBox, actions, actionsLeft, allowPinOnTop, initialPosition, widget, compact, appStyle, autoHeight, autoMinHeight, widgetMenu, dimensions, windowKey, openedFromKey, children }: ModalProps): react.ReactPortal | null;
239
+ declare function Modal({ open, onClose, title, icon, copyText, size, dirty, onNext, onPrev, footer, bodyScroll, onMinimize, initialBox, actions, actionsLeft, allowPinOnTop, initialPosition, widget, compact, appStyle, flushBody, autoHeight, autoMinHeight, widgetMenu, dimensions, windowKey, openedFromKey, children }: ModalProps): react.ReactPortal | null;
236
240
 
237
241
  /**
238
242
  * Unified popup menu component — used for all context menus, dropdowns, and flyouts.
@@ -450,6 +454,45 @@ interface EditableGridProps {
450
454
  */
451
455
  declare function EditableGrid({ columns, data, onChange, onColumnsChange, fixedRows, minRows, maxHeight, cellStyles, onFocusChange, onSelectionChange }: EditableGridProps): react_jsx_runtime.JSX.Element;
452
456
 
457
+ /**
458
+ * Two-pane layout with a drag-to-resize left sidebar.
459
+ *
460
+ * Renders flush (`h-full w-full`) — pair it with a `flushBody` window so the
461
+ * sidebar runs from just under the title bar to the very bottom with no
462
+ * surrounding padding. The user can drag the right edge of the sidebar to
463
+ * resize it; pass `storageKey` to persist that width across reopens, or
464
+ * double-click the handle to reset to `defaultWidth`.
465
+ *
466
+ * @example
467
+ * <SidebarLayout sidebar={<MyNav />} storageKey="todo.sidebarWidth">
468
+ * <MyContent />
469
+ * </SidebarLayout>
470
+ */
471
+ interface SidebarLayoutProps {
472
+ /** Content of the left sidebar pane. */
473
+ sidebar: ReactNode;
474
+ /** Content of the main pane (right of the sidebar). */
475
+ children: ReactNode;
476
+ /** localStorage key to persist the sidebar width across reopens. When set,
477
+ * the last dragged width is restored on mount. Omit for session-only width. */
478
+ storageKey?: string;
479
+ /** Initial sidebar width in px (used when nothing is persisted). Default 256. */
480
+ defaultWidth?: number;
481
+ /** Minimum sidebar width in px. Default 180. */
482
+ minWidth?: number;
483
+ /** Maximum sidebar width in px. Default 480. */
484
+ maxWidth?: number;
485
+ /** Extra classes for the outer flex row. */
486
+ className?: string;
487
+ /** Classes for the sidebar pane (background, border, …). The pane is a flex
488
+ * column that scrolls its own overflow. Defaults to a light-grey,
489
+ * right-bordered sidebar. */
490
+ sidebarClassName?: string;
491
+ /** Classes for the main content pane. Defaults to a white background. */
492
+ contentClassName?: string;
493
+ }
494
+ declare function SidebarLayout({ sidebar, children, storageKey, defaultWidth, minWidth, maxWidth, className, sidebarClassName, contentClassName, }: SidebarLayoutProps): react_jsx_runtime.JSX.Element;
495
+
453
496
  /** Generic notification shape consumed by the shell. Consumer-specific
454
497
  * fields live on `extra` (or just on additional properties — TS structural
455
498
  * typing is permissive). */
@@ -1025,15 +1068,19 @@ declare function EntityList<T>(props: EntityListProps<T>): react_jsx_runtime.JSX
1025
1068
  * library) and styled with the same Tailwind utilities + `grid-scroll` class the
1026
1069
  * shell already ships, so consumers get it for free.
1027
1070
  *
1028
- * Group items into columns with `columnOf`, render each card with `renderCard`,
1029
- * and handle moves with `onMove(id, toColumn)`. Drops only change a card's
1030
- * column; within-column order is presentational (optionally via `sortInColumn`).
1071
+ * Group items into columns with `columnOf`, render each card with `renderCard`.
1072
+ * Cards can be dragged **between** columns (to change which column they belong
1073
+ * to) and **within** a column (to reorder / prioritise). On drop, `onMove(id,
1074
+ * toColumn, toIndex)` fires — `toIndex` is the target position within `toColumn`
1075
+ * measured against that column's cards *excluding* the dragged one, so the
1076
+ * consumer can persist an order (e.g. midpoint between neighbours) that every
1077
+ * user then sees. Sort each column by that order via `sortInColumn`.
1031
1078
  *
1032
- * Drag affordance: as a card is dragged over a *different* column, the cards at
1033
- * and below the hovered position slide down (CSS transform transition) to open a
1034
- * gap the size of the dragged card, and the column highlights. The dragged card
1035
- * is dimmed. Insertion index tracks `dragenter` (once per card crossed) rather
1036
- * than `dragover` (every few ms) so the gap stays stable instead of oscillating.
1079
+ * Affordance: a blue **drop-line** shows exactly where the card will land
1080
+ * (between two cards, in either the source or a different column), and the
1081
+ * target column highlights. The dragged card dims. The insertion point tracks
1082
+ * `dragenter` (once per card crossed) so the line stays stable rather than
1083
+ * flickering.
1037
1084
  */
1038
1085
  interface KanbanColumn {
1039
1086
  /** Stable column key — what `columnOf` returns and `onMove` receives. */
@@ -1049,12 +1096,17 @@ interface KanbanProps<T> {
1049
1096
  columns: KanbanColumn[];
1050
1097
  columnOf: (item: T) => string;
1051
1098
  getId: (item: T) => string;
1052
- /** Called when a card is dropped on a column (its own `value`). */
1053
- onMove: (id: string, toColumn: string) => void;
1099
+ /**
1100
+ * Fired on drop. `toColumn` is the destination column's `value`; `toIndex` is
1101
+ * the target position within that column measured against its cards
1102
+ * **excluding** the dragged card (0 = top). A same-column drop that wouldn't
1103
+ * change the order is not reported.
1104
+ */
1105
+ onMove: (id: string, toColumn: string, toIndex: number) => void;
1054
1106
  /** Inner card content — the card chrome (border, padding, hover) is provided. */
1055
1107
  renderCard: (item: T) => ReactNode;
1056
1108
  onCardClick?: (item: T) => void;
1057
- /** Optional comparator for ordering within a column. */
1109
+ /** Comparator for ordering within a column — sort by the persisted order field. */
1058
1110
  sortInColumn?: (a: T, b: T) => number;
1059
1111
  isLoading?: boolean;
1060
1112
  loadingText?: string;
@@ -1381,4 +1433,4 @@ declare function useNewHotkey(callback: () => void): void;
1381
1433
  */
1382
1434
  declare function useEditHotkey(callback: (() => void) | null): void;
1383
1435
 
1384
- export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, type BugReport, type BugReportConfig, BugReportConfigProvider, BugReportDetail, type BugReportExtraField, type BugReportExtraSelectField, BugReportProvider, type BugReportSubmission, type BugReportSubmitPayload, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CancelButton, type CellStyle, type ChangelogEntry, type ColumnDef, ConfirmProvider, CopyButton, Customization, type CustomizationOmitSection, type CustomizationProps, DEV_BANNER_TEXT, Desktop, type DesktopHostConfig, DesktopHostProvider, DevIndicator, DocFavStar, ENTER, EditableGrid, type EditableGridProps, type EntityFetcher, EntityList, type EntityListColumn, type EntityListProps, GLASS_DIVIDER, GLASS_INPUT_BG, GlobalSearch, type GridColumn, HelpCenter, type HelpCenterDoc, type HelpCenterProps, Kanban, type KanbanColumn, type KanbanProps, Layout, type LayoutProps, ListFooter, MOD, Markdown, type MarkdownProps, Modal, ModalActions, NotificationBell, type NotificationsConfig, type PaginatedResponse, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, type ReportType, ResizableTable, SHIFT, type SearchConfig, type SearchProvider, type SearchResult, type SemanticGroup, type ShellAuth, ShellAuthProvider, ShellEntityFetcherProvider, type ShellNotification, type ShellPrefsAdapter, ShellPrefsProvider, ShortcutHelp, type SortState, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, type StickyEntityRef, type StickyResolver, SystemPreferences, type SystemPreferencesProps, type SystemPreferencesSection, type TodoProvider, type TodoTask, VERSION, WidgetManager, WindowManagerProvider, WindowRegistry, WindowTitle, applyDevTitle, commitExposeHighlight, confirm, confirmDestructive, createWindowRegistry, exitExposeMode, formatDate, getActiveWindowRoute, getExposeHighlight, getWindowPosition, glassStyle, isDevEnv, isMac, openBugReportDialog, prompt, reportBug, setExposeHighlight, setShellApiClient, setShellAuthBridge, setShellNavIcons, setShellTodoProvider, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toast, toggleExposeMode, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useLocalStoragePrefs, useModalActive, useNewHotkey, useShellAuth, useShellEntityFetcher, useShellPrefs, useSort, useTableNav, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
1436
+ export { ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BehaviorPanel, type BugReport, type BugReportConfig, BugReportConfigProvider, BugReportDetail, type BugReportExtraField, type BugReportExtraSelectField, BugReportProvider, type BugReportSubmission, type BugReportSubmitPayload, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, CancelButton, type CellStyle, type ChangelogEntry, type ColumnDef, ConfirmProvider, CopyButton, Customization, type CustomizationOmitSection, type CustomizationProps, DEV_BANNER_TEXT, Desktop, type DesktopHostConfig, DesktopHostProvider, DevIndicator, DocFavStar, ENTER, EditableGrid, type EditableGridProps, type EntityFetcher, EntityList, type EntityListColumn, type EntityListProps, GLASS_DIVIDER, GLASS_INPUT_BG, GlobalSearch, type GridColumn, HelpCenter, type HelpCenterDoc, type HelpCenterProps, Kanban, type KanbanColumn, type KanbanProps, Layout, type LayoutProps, ListFooter, MOD, Markdown, type MarkdownProps, Modal, ModalActions, NotificationBell, type NotificationsConfig, type PaginatedResponse, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, type ReportType, ResizableTable, SHIFT, type SearchConfig, type SearchProvider, type SearchResult, type SemanticGroup, type ShellAuth, ShellAuthProvider, ShellEntityFetcherProvider, type ShellNotification, type ShellPrefsAdapter, ShellPrefsProvider, ShortcutHelp, SidebarLayout, type SidebarLayoutProps, type SortState, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, type StickyEntityRef, type StickyResolver, SystemPreferences, type SystemPreferencesProps, type SystemPreferencesSection, type TodoProvider, type TodoTask, VERSION, WidgetManager, WindowManagerProvider, WindowRegistry, WindowTitle, applyDevTitle, commitExposeHighlight, confirm, confirmDestructive, createWindowRegistry, exitExposeMode, formatDate, getActiveWindowRoute, getExposeHighlight, getWindowPosition, glassStyle, isDevEnv, isMac, openBugReportDialog, prompt, reportBug, setExposeHighlight, setShellApiClient, setShellAuthBridge, setShellNavIcons, setShellTodoProvider, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toast, toggleExposeMode, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useLocalStoragePrefs, useModalActive, useNewHotkey, useShellAuth, useShellEntityFetcher, useShellPrefs, useSort, useTableNav, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
package/dist/index.js CHANGED
@@ -4,22 +4,22 @@ import { subscribePomo, getPomoSnapshot } from './chunk-MK3HLUO4.js';
4
4
  export { setShellTodoProvider } from './chunk-QTJ2CHJX.js';
5
5
  import { useShellPrefs } from './chunk-36VM54SC.js';
6
6
  export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
7
- import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-SUUADOG6.js';
7
+ import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-3SIZAHR6.js';
8
8
  import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, setSoundForType, previewSound, setAllSounds, playLogout } from './chunk-D7PYW2QS.js';
9
- import { setPdfPreview } from './chunk-KJ5664G7.js';
9
+ import { setPdfPreview } from './chunk-DMSHU2HJ.js';
10
10
  import './chunk-KUIPWCTJ.js';
11
11
  import { toast_default } from './chunk-WIJ45SYD.js';
12
12
  export { toast_default as toast } from './chunk-WIJ45SYD.js';
13
- export { EditableGrid } from './chunk-ZETQWO2W.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';
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';
13
+ export { EditableGrid } from './chunk-66GIT3PM.js';
14
+ import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, WINDOW_REGISTRY, isPageEntry, useIsMobile, ModalActions, useModalActive, client_default, LoadingSpinner, setWindowPosition, ThumbCard, activateModal } from './chunk-IMFUTSYY.js';
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-IMFUTSYY.js';
16
16
  import { confirm } from './chunk-UBN4IUDE.js';
17
17
  export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-UBN4IUDE.js';
18
18
  import { useAuth, useShellAuth } from './chunk-ADJ3CERD.js';
19
19
  export { ShellAuthProvider, setShellAuthBridge, useShellAuth } from './chunk-ADJ3CERD.js';
20
20
  import { glassStyle, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons } from './chunk-ZF6AYO4G.js';
21
21
  export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-ZF6AYO4G.js';
22
- import { createContext, lazy, useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement, useSyncExternalStore } from 'react';
22
+ import { createContext, lazy, useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect, useContext, Suspense, isValidElement, cloneElement, Fragment as Fragment$1, useSyncExternalStore } from 'react';
23
23
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
24
24
  import { Dialog, DialogBackdrop, DialogPanel, DialogTitle } from '@headlessui/react';
25
25
  import { createPortal } from 'react-dom';
@@ -560,6 +560,78 @@ function HelpCenter({
560
560
  ] }) : /* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center px-6 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: loading ? "Loading\u2026" : "Pick a help article from the left." }) }) })
561
561
  ] });
562
562
  }
563
+ var clamp = (n, lo, hi) => Math.min(Math.max(n, lo), hi);
564
+ function SidebarLayout({
565
+ sidebar,
566
+ children,
567
+ storageKey,
568
+ defaultWidth = 256,
569
+ minWidth = 180,
570
+ maxWidth = 480,
571
+ className = "",
572
+ sidebarClassName = "border-r border-gray-200 bg-gray-50",
573
+ contentClassName = "bg-white"
574
+ }) {
575
+ const [width, setWidth] = useState(() => {
576
+ if (storageKey && typeof window !== "undefined") {
577
+ const saved = window.localStorage.getItem(storageKey);
578
+ const n = saved ? parseInt(saved, 10) : NaN;
579
+ if (!Number.isNaN(n)) return clamp(n, minWidth, maxWidth);
580
+ }
581
+ return clamp(defaultWidth, minWidth, maxWidth);
582
+ });
583
+ const dragRef = useRef(null);
584
+ const onMove = useCallback((e) => {
585
+ const d = dragRef.current;
586
+ if (!d) return;
587
+ setWidth(clamp(d.startWidth + (e.clientX - d.startX), minWidth, maxWidth));
588
+ }, [minWidth, maxWidth]);
589
+ const onUp = useCallback(() => {
590
+ dragRef.current = null;
591
+ window.removeEventListener("pointermove", onMove);
592
+ window.removeEventListener("pointerup", onUp);
593
+ document.body.style.removeProperty("cursor");
594
+ document.body.style.removeProperty("user-select");
595
+ }, [onMove]);
596
+ const startDrag = useCallback((e) => {
597
+ e.preventDefault();
598
+ dragRef.current = { startX: e.clientX, startWidth: width };
599
+ window.addEventListener("pointermove", onMove);
600
+ window.addEventListener("pointerup", onUp);
601
+ document.body.style.cursor = "col-resize";
602
+ document.body.style.userSelect = "none";
603
+ }, [width, onMove, onUp]);
604
+ useEffect(() => {
605
+ if (!storageKey) return;
606
+ const id = window.setTimeout(() => {
607
+ try {
608
+ window.localStorage.setItem(storageKey, String(Math.round(width)));
609
+ } catch {
610
+ }
611
+ }, 200);
612
+ return () => window.clearTimeout(id);
613
+ }, [width, storageKey]);
614
+ useEffect(() => () => {
615
+ window.removeEventListener("pointermove", onMove);
616
+ window.removeEventListener("pointerup", onUp);
617
+ }, [onMove, onUp]);
618
+ return /* @__PURE__ */ jsxs("div", { className: `flex h-full w-full overflow-hidden ${className}`, children: [
619
+ /* @__PURE__ */ jsxs("div", { className: "relative flex h-full shrink-0 flex-col", style: { width }, children: [
620
+ /* @__PURE__ */ jsx("div", { className: `flex h-full flex-col overflow-y-auto ${sidebarClassName}`, children: sidebar }),
621
+ /* @__PURE__ */ jsx(
622
+ "div",
623
+ {
624
+ onPointerDown: startDrag,
625
+ onDoubleClick: () => setWidth(clamp(defaultWidth, minWidth, maxWidth)),
626
+ title: "Drag to resize \xB7 double-click to reset",
627
+ className: "group absolute inset-y-0 right-0 z-10 w-2 cursor-col-resize",
628
+ children: /* @__PURE__ */ jsx("div", { className: "absolute inset-y-0 right-0 w-px bg-transparent transition-colors group-hover:bg-blue-400" })
629
+ }
630
+ )
631
+ ] }),
632
+ /* @__PURE__ */ jsx("div", { className: `flex min-w-0 flex-1 flex-col ${contentClassName}`, children })
633
+ ] });
634
+ }
563
635
  function timeAgo(dateStr) {
564
636
  const diff = Date.now() - new Date(dateStr).getTime();
565
637
  const mins = Math.floor(diff / 6e4);
@@ -1400,7 +1472,7 @@ function WidgetManager({ open, onClose }) {
1400
1472
  }
1401
1473
 
1402
1474
  // src/version.ts
1403
- var VERSION = "0.9.0" ;
1475
+ var VERSION = "0.11.0" ;
1404
1476
  var APP_VERSION = VERSION;
1405
1477
 
1406
1478
  // src/changelog.ts
@@ -6273,8 +6345,6 @@ function Kanban({
6273
6345
  columnEmptyText = "Drop here"
6274
6346
  }) {
6275
6347
  const [dragId, setDragId] = useState(null);
6276
- const [fromCol, setFromCol] = useState(null);
6277
- const [gap, setGap] = useState(0);
6278
6348
  const [over, setOver] = useState(null);
6279
6349
  const grouped = useMemo(() => {
6280
6350
  const map = {};
@@ -6285,27 +6355,36 @@ function Kanban({
6285
6355
  }, [items, columns, columnOf, sortInColumn]);
6286
6356
  const reset = () => {
6287
6357
  setDragId(null);
6288
- setFromCol(null);
6289
6358
  setOver(null);
6290
6359
  };
6291
- const isActive = (col) => over !== null && over.col === col && fromCol !== col;
6360
+ const commitMove = (col) => {
6361
+ if (dragId && over && over.col === col) {
6362
+ const colItems = grouped[col] ?? [];
6363
+ const dp = colItems.findIndex((it) => getId(it) === dragId);
6364
+ const sameCol = dp !== -1;
6365
+ const noop = sameCol && (over.index === dp || over.index === dp + 1);
6366
+ if (!noop) {
6367
+ const toIndex = sameCol && over.index > dp ? over.index - 1 : over.index;
6368
+ onMove(dragId, col, toIndex);
6369
+ }
6370
+ }
6371
+ reset();
6372
+ };
6292
6373
  if (isLoading) return /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-500 p-4", children: loadingText });
6293
6374
  if (items.length === 0) {
6294
6375
  return /* @__PURE__ */ jsx(Fragment, { children: emptyState ?? /* @__PURE__ */ jsx("div", { className: "text-sm text-gray-500 p-4", children: "No items." }) });
6295
6376
  }
6296
6377
  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
6378
  const colItems = grouped[col.value] ?? [];
6298
- const active = isActive(col.value);
6379
+ const isOver = over !== null && over.col === col.value;
6380
+ const dp = dragId !== null ? colItems.findIndex((it) => getId(it) === dragId) : -1;
6381
+ const lineAt = isOver && !(dp !== -1 && (over.index === dp || over.index === dp + 1)) ? over.index : -1;
6299
6382
  return /* @__PURE__ */ jsxs(
6300
6383
  "div",
6301
6384
  {
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"}`,
6385
+ className: `flex flex-col w-72 shrink-0 rounded-xl bg-gray-50 border transition-colors ${isOver ? "border-blue-400 ring-2 ring-blue-300/60" : "border-gray-200"}`,
6303
6386
  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
- },
6387
+ onDrop: () => commitMove(col.value),
6309
6388
  children: [
6310
6389
  /* @__PURE__ */ jsxs(
6311
6390
  "div",
@@ -6324,48 +6403,46 @@ function Kanban({
6324
6403
  "div",
6325
6404
  {
6326
6405
  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" },
6406
+ onDragEnter: () => setOver(
6407
+ (prev) => prev && prev.col === col.value && prev.index === colItems.length ? prev : { col: col.value, index: colItems.length }
6408
+ ),
6328
6409
  children: [
6329
6410
  colItems.map((item, index) => {
6330
6411
  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
- );
6412
+ const isDragged = id === dragId;
6413
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [
6414
+ lineAt === index && /* @__PURE__ */ jsx("div", { className: "h-0.5 rounded-full bg-blue-500", "aria-hidden": true }),
6415
+ /* @__PURE__ */ jsx(
6416
+ "div",
6417
+ {
6418
+ draggable: true,
6419
+ onDragStart: (e) => {
6420
+ setDragId(id);
6421
+ try {
6422
+ e.dataTransfer.effectAllowed = "move";
6423
+ } catch {
6424
+ }
6425
+ },
6426
+ onDragEnter: (e) => {
6427
+ e.stopPropagation();
6428
+ setOver(
6429
+ (prev) => prev && prev.col === col.value && prev.index === index ? prev : { col: col.value, index }
6430
+ );
6431
+ },
6432
+ onDragEnd: reset,
6433
+ onClick: onCardClick ? () => onCardClick(item) : void 0,
6434
+ style: dragId === null ? void 0 : { opacity: isDragged ? 0.4 : 1, transition: "opacity 120ms ease" },
6435
+ className: `rounded-lg bg-white border border-gray-200 p-3 shadow-sm hover:border-blue-400 hover:shadow transition ${onCardClick ? "cursor-pointer" : ""}`,
6436
+ children: renderCard(item)
6437
+ }
6438
+ )
6439
+ ] }, id);
6364
6440
  }),
6441
+ colItems.length > 0 && lineAt === colItems.length && /* @__PURE__ */ jsx("div", { className: "h-0.5 rounded-full bg-blue-500", "aria-hidden": true }),
6365
6442
  colItems.length === 0 && /* @__PURE__ */ jsx(
6366
6443
  "div",
6367
6444
  {
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"}`,
6445
+ className: `text-[11px] text-center rounded-lg transition-all duration-150 ${isOver ? "border-2 border-dashed border-blue-300 bg-blue-50/50 text-blue-400 py-8" : "text-gray-400 py-6"}`,
6369
6446
  children: columnEmptyText
6370
6447
  }
6371
6448
  )
@@ -6494,6 +6571,6 @@ function useEditHotkey(callback) {
6494
6571
  }, [callback, isActive]);
6495
6572
  }
6496
6573
 
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 };
6574
+ 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, SidebarLayout, SoundsPanel, StartMenu, StatusBadge, StatusBadgeProvider, SystemPreferences, VERSION, WidgetManager, applyDevTitle, createWindowRegistry, isDevEnv, isMac, openBugReportDialog, reportBug, useBugReport, useClickOutside, useColumnConfig, useDesktopHost, useEditHotkey, useInfiniteScroll, useNewHotkey, useShellEntityFetcher, useSort, useTableNav };
6498
6575
  //# sourceMappingURL=index.js.map
6499
6576
  //# sourceMappingURL=index.js.map