react-os-shell 1.1.2 → 1.3.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 (39) hide show
  1. package/README.md +1 -0
  2. package/dist/{Browser-5N6LVTRI.js → Browser-VTTA3X6R.js} +4 -3
  3. package/dist/{Browser-5N6LVTRI.js.map → Browser-VTTA3X6R.js.map} +1 -1
  4. package/dist/{Documents-PRL5FI5D.js → Documents-RRKY4LNJ.js} +4 -2
  5. package/dist/Documents-RRKY4LNJ.js.map +1 -0
  6. package/dist/{Files-267TXU2U.js → Files-QM7OERST.js} +7 -6
  7. package/dist/{Files-267TXU2U.js.map → Files-QM7OERST.js.map} +1 -1
  8. package/dist/{Notepad-XDZQKQM2.js → Notepad-7HBOCTJX.js} +83 -79
  9. package/dist/Notepad-7HBOCTJX.js.map +1 -0
  10. package/dist/Preview-S54JZBKK.js +9 -0
  11. package/dist/{Preview-DAKXTB6B.js.map → Preview-S54JZBKK.js.map} +1 -1
  12. package/dist/{Spreadsheet-YIA6BBV4.js → Spreadsheet-PRO6WI45.js} +4 -3
  13. package/dist/{Spreadsheet-YIA6BBV4.js.map → Spreadsheet-PRO6WI45.js.map} +1 -1
  14. package/dist/apps/index.d.ts +55 -1
  15. package/dist/apps/index.js +12 -11
  16. package/dist/apps/index.js.map +1 -1
  17. package/dist/{chunk-V7AIVKUC.js → chunk-BDGH2GKX.js} +4 -2
  18. package/dist/chunk-BDGH2GKX.js.map +1 -0
  19. package/dist/chunk-DLOIO7UD.js +81 -0
  20. package/dist/chunk-DLOIO7UD.js.map +1 -0
  21. package/dist/{chunk-5THABSPK.js → chunk-HQWHWS7V.js} +22 -8
  22. package/dist/chunk-HQWHWS7V.js.map +1 -0
  23. package/dist/{chunk-DKC2VDOI.js → chunk-T4USMWTS.js} +4 -2
  24. package/dist/chunk-T4USMWTS.js.map +1 -0
  25. package/dist/{chunk-YXFWXF5N.js → chunk-V2BMSY64.js} +5 -3
  26. package/dist/chunk-V2BMSY64.js.map +1 -0
  27. package/dist/{chunk-CDSIE534.js → chunk-WMOF4TAP.js} +4 -4
  28. package/dist/{chunk-CDSIE534.js.map → chunk-WMOF4TAP.js.map} +1 -1
  29. package/dist/index.js +7 -9
  30. package/dist/index.js.map +1 -1
  31. package/dist/styles.css +10 -0
  32. package/package.json +1 -1
  33. package/dist/Documents-PRL5FI5D.js.map +0 -1
  34. package/dist/Notepad-XDZQKQM2.js.map +0 -1
  35. package/dist/Preview-DAKXTB6B.js +0 -8
  36. package/dist/chunk-5THABSPK.js.map +0 -1
  37. package/dist/chunk-DKC2VDOI.js.map +0 -1
  38. package/dist/chunk-V7AIVKUC.js.map +0 -1
  39. package/dist/chunk-YXFWXF5N.js.map +0 -1
@@ -0,0 +1,81 @@
1
+ import { useWindowMenuItem, Modal } from './chunk-GWVVILYQ.js';
2
+ import { navIcons } from './chunk-ZF6AYO4G.js';
3
+ import { useState, useCallback, isValidElement, cloneElement } from 'react';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
5
+
6
+ // src/version.ts
7
+ var VERSION = "1.3.0" ;
8
+ var APP_VERSION = VERSION;
9
+ var BUILTIN_APP_INFO = {
10
+ spreadsheet: {
11
+ name: "Spreadsheets",
12
+ version: "1.1.0",
13
+ route: "/spreadsheet",
14
+ description: "Multi-sheet spreadsheet editor with CSV / TSV import and export."
15
+ },
16
+ notepad: {
17
+ name: "Notepad",
18
+ version: "1.0.0",
19
+ route: "/notepad",
20
+ description: "Color-coded notes with checklists, desktop stickies and entity autolinking."
21
+ },
22
+ documents: {
23
+ name: "Documents",
24
+ version: "1.0.0",
25
+ route: "/documents",
26
+ description: "Viewer and light editor for plain-text files and Word documents."
27
+ },
28
+ preview: {
29
+ name: "Preview",
30
+ version: "1.0.0",
31
+ route: "/preview",
32
+ description: "Viewer for PDF documents, images, DXF drawings and 3D models."
33
+ },
34
+ files: {
35
+ name: "Files",
36
+ version: "1.0.0",
37
+ route: "/files",
38
+ description: "Personal file manager with folders, uploads, quota and trash."
39
+ },
40
+ browser: {
41
+ name: "Browser",
42
+ version: "1.0.0",
43
+ route: "/browser",
44
+ description: "Minimal web browser with bookmarks, history and navigation bar."
45
+ }
46
+ };
47
+ var ABOUT_MENU_ICON = /* @__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: "M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" }) });
48
+ var FALLBACK_APP_ICON = /* @__PURE__ */ jsx("svg", { className: "h-9 w-9", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6.75A2.25 2.25 0 016 4.5h12a2.25 2.25 0 012.25 2.25v10.5A2.25 2.25 0 0118 19.5H6a2.25 2.25 0 01-2.25-2.25V6.75z M3.75 9h16.5" }) });
49
+ function AboutApp({ app }) {
50
+ const info = BUILTIN_APP_INFO[app];
51
+ const [open, setOpen] = useState(false);
52
+ const openDialog = useCallback(() => setOpen(true), []);
53
+ useWindowMenuItem(`About ${info.name}`, openDialog, ABOUT_MENU_ICON);
54
+ if (!open) return null;
55
+ const registered = navIcons[info.route];
56
+ const appIcon = isValidElement(registered) ? cloneElement(registered, { className: "h-9 w-9" }) : FALLBACK_APP_ICON;
57
+ return /* @__PURE__ */ jsx(Modal, { open: true, onClose: () => setOpen(false), title: `About ${info.name}`, size: "sm", compact: true, bodyScroll: false, autoHeight: true, dimensions: [320, 320], children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center text-center px-5 pt-5 pb-4", children: [
58
+ /* @__PURE__ */ jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl bg-gray-100 text-gray-600 shrink-0", children: appIcon }),
59
+ /* @__PURE__ */ jsx("h2", { className: "mt-3 text-lg font-bold text-gray-900", children: info.name }),
60
+ /* @__PURE__ */ jsxs("p", { className: "text-[11px] font-mono text-gray-400", children: [
61
+ "Version ",
62
+ info.version
63
+ ] }),
64
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-gray-500 leading-relaxed", children: info.description }),
65
+ /* @__PURE__ */ jsxs("div", { className: "mt-4 pt-3 border-t border-gray-200 w-full", children: [
66
+ /* @__PURE__ */ jsxs("p", { className: "text-[11px] text-gray-500", children: [
67
+ "Part of the ",
68
+ /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-700", children: "react-os-shell" }),
69
+ " desktop environment"
70
+ ] }),
71
+ /* @__PURE__ */ jsxs("p", { className: "mt-0.5 text-[10px] font-mono text-gray-400", children: [
72
+ "shell v",
73
+ VERSION
74
+ ] })
75
+ ] })
76
+ ] }) });
77
+ }
78
+
79
+ export { APP_VERSION, AboutApp, BUILTIN_APP_INFO, VERSION };
80
+ //# sourceMappingURL=chunk-DLOIO7UD.js.map
81
+ //# sourceMappingURL=chunk-DLOIO7UD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/version.ts","../src/apps/_about.tsx"],"names":[],"mappings":"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","file":"chunk-DLOIO7UD.js","sourcesContent":["declare const __PKG_VERSION__: string | undefined;\n\n/** Package version, injected by tsup at build time. Stays as an empty\n * string when the source is consumed without a build (e.g. tests). */\nexport const VERSION: string = typeof __PKG_VERSION__ === 'string' ? __PKG_VERSION__ : '';\n\n/** Legacy alias kept so existing consumers do not break. */\nexport const APP_VERSION = VERSION;\n","/**\n * Shared \"About\" dialog for the bundled apps.\n *\n * Each bundled app carries its own version (independent of the package\n * version) so app-level changes can be tracked without bumping every app at\n * once. `<AboutApp app=\"…\" />` registers an \"About <Name>\" item in the\n * window title menu and renders the dialog: app icon, name, app version and\n * the react-os-shell attribution + shell version.\n *\n * Bump an app's version in `BUILTIN_APP_INFO` whenever that app's behaviour\n * changes, alongside the package-level CHANGELOG entry.\n */\nimport { useCallback, useState, isValidElement, cloneElement, type ReactElement } from 'react';\nimport Modal, { useWindowMenuItem } from '../shell/Modal';\nimport { navIcons } from '../shell-config/nav';\nimport { VERSION } from '../version';\n\nexport interface BuiltinAppInfo {\n /** Display name — matches the window-registry label. */\n name: string;\n /** App version, independent of the package version. */\n version: string;\n /** One-line summary shown in the About dialog. */\n description: string;\n /** Registry route — used to look up the consumer-registered nav icon. */\n route: string;\n}\n\nexport const BUILTIN_APP_INFO = {\n spreadsheet: {\n name: 'Spreadsheets',\n version: '1.1.0',\n route: '/spreadsheet',\n description: 'Multi-sheet spreadsheet editor with CSV / TSV import and export.',\n },\n notepad: {\n name: 'Notepad',\n version: '1.0.0',\n route: '/notepad',\n description: 'Color-coded notes with checklists, desktop stickies and entity autolinking.',\n },\n documents: {\n name: 'Documents',\n version: '1.0.0',\n route: '/documents',\n description: 'Viewer and light editor for plain-text files and Word documents.',\n },\n preview: {\n name: 'Preview',\n version: '1.0.0',\n route: '/preview',\n description: 'Viewer for PDF documents, images, DXF drawings and 3D models.',\n },\n files: {\n name: 'Files',\n version: '1.0.0',\n route: '/files',\n description: 'Personal file manager with folders, uploads, quota and trash.',\n },\n browser: {\n name: 'Browser',\n version: '1.0.0',\n route: '/browser',\n description: 'Minimal web browser with bookmarks, history and navigation bar.',\n },\n} satisfies Record<string, BuiltinAppInfo>;\n\nexport type BuiltinAppId = keyof typeof BUILTIN_APP_INFO;\n\nconst ABOUT_MENU_ICON = (\n <svg className=\"h-4 w-4 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z\" />\n </svg>\n);\n\n// Generic window glyph shown when the consumer hasn't registered a nav icon\n// for the app's route (same fallback shape as the Modal title bar).\nconst FALLBACK_APP_ICON = (\n <svg className=\"h-9 w-9\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 6.75A2.25 2.25 0 016 4.5h12a2.25 2.25 0 012.25 2.25v10.5A2.25 2.25 0 0118 19.5H6a2.25 2.25 0 01-2.25-2.25V6.75z M3.75 9h16.5\" />\n </svg>\n);\n\n/** Registers \"About <Name>\" in the window title menu and renders the dialog.\n * Render anywhere inside the app's window. */\nexport default function AboutApp({ app }: { app: BuiltinAppId }) {\n const info = BUILTIN_APP_INFO[app];\n const [open, setOpen] = useState(false);\n const openDialog = useCallback(() => setOpen(true), []);\n useWindowMenuItem(`About ${info.name}`, openDialog, ABOUT_MENU_ICON);\n\n if (!open) return null;\n\n const registered = navIcons[info.route];\n const appIcon = isValidElement(registered)\n ? cloneElement(registered as ReactElement, { className: 'h-9 w-9' } as any)\n : FALLBACK_APP_ICON;\n\n return (\n <Modal open onClose={() => setOpen(false)} title={`About ${info.name}`} size=\"sm\" compact bodyScroll={false} autoHeight dimensions={[320, 320]}>\n <div className=\"flex flex-col items-center text-center px-5 pt-5 pb-4\">\n <div className=\"flex h-16 w-16 items-center justify-center rounded-2xl bg-gray-100 text-gray-600 shrink-0\">\n {appIcon}\n </div>\n <h2 className=\"mt-3 text-lg font-bold text-gray-900\">{info.name}</h2>\n <p className=\"text-[11px] font-mono text-gray-400\">Version {info.version}</p>\n <p className=\"mt-2 text-xs text-gray-500 leading-relaxed\">{info.description}</p>\n <div className=\"mt-4 pt-3 border-t border-gray-200 w-full\">\n <p className=\"text-[11px] text-gray-500\">\n Part of the <span className=\"font-medium text-gray-700\">react-os-shell</span> desktop environment\n </p>\n {VERSION && <p className=\"mt-0.5 text-[10px] font-mono text-gray-400\">shell v{VERSION}</p>}\n </div>\n </div>\n </Modal>\n );\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { AboutApp } from './chunk-DLOIO7UD.js';
1
2
  import { WindowTitle } from './chunk-GWVVILYQ.js';
2
3
  import { useRef, useState, useEffect, useCallback, useMemo } from 'react';
3
4
  import { createPortal } from 'react-dom';
@@ -928,6 +929,9 @@ function Spreadsheet() {
928
929
  return () => window.removeEventListener("keydown", handler);
929
930
  }, [undo]);
930
931
  const [title, setTitle] = useState(initialPreview?.title ?? "Untitled");
932
+ const [emailHandler, setEmailHandler] = useState(
933
+ () => consumedRef.current?.data.onEmail
934
+ );
931
935
  useEffect(() => {
932
936
  const myToken = consumedRef.current?.token;
933
937
  if (myToken == null) return;
@@ -939,6 +943,7 @@ function Spreadsheet() {
939
943
  setSheets([sheet]);
940
944
  setActiveIdx(0);
941
945
  setTitle(detail.data.filename.replace(/\.(csv|tsv|txt)$/i, ""));
946
+ setEmailHandler(() => detail.data.onEmail);
942
947
  };
943
948
  window.addEventListener(SPREADSHEET_EVENT_NAME, handler);
944
949
  return () => window.removeEventListener(SPREADSHEET_EVENT_NAME, handler);
@@ -1028,13 +1033,13 @@ function Spreadsheet() {
1028
1033
  data: makeEmptyData(DEFAULT_ROWS, DEFAULT_COLS)
1029
1034
  });
1030
1035
  };
1036
+ const serializeCSV = () => data.filter((row) => row.some((c) => c.trim())).map((row) => row.map((cell) => {
1037
+ if (cell.includes(",") || cell.includes('"') || cell.includes("\n"))
1038
+ return `"${cell.replace(/"/g, '""')}"`;
1039
+ return cell;
1040
+ }).join(",")).join("\n");
1031
1041
  const exportCSV = () => {
1032
- const csv = data.filter((row) => row.some((c) => c.trim())).map((row) => row.map((cell) => {
1033
- if (cell.includes(",") || cell.includes('"') || cell.includes("\n"))
1034
- return `"${cell.replace(/"/g, '""')}"`;
1035
- return cell;
1036
- }).join(",")).join("\n");
1037
- const blob = new Blob([csv], { type: "text/csv" });
1042
+ const blob = new Blob([serializeCSV()], { type: "text/csv" });
1038
1043
  const url = URL.createObjectURL(blob);
1039
1044
  const a = document.createElement("a");
1040
1045
  a.href = url;
@@ -1087,6 +1092,7 @@ function Spreadsheet() {
1087
1092
  const filledCount = data.reduce((c, row) => c + row.filter((cell) => cell.trim()).length, 0);
1088
1093
  return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "flex flex-col h-full", children: [
1089
1094
  /* @__PURE__ */ jsx(WindowTitle, { title: `${truncateForTitle(title || "Untitled")} - Spreadsheets` }),
1095
+ /* @__PURE__ */ jsx(AboutApp, { app: "spreadsheet" }),
1090
1096
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-3 py-2 border-b border-gray-200 bg-gray-50 shrink-0", children: [
1091
1097
  editingTitle ? /* @__PURE__ */ jsx(
1092
1098
  "input",
@@ -1120,6 +1126,14 @@ function Spreadsheet() {
1120
1126
  children: "Save CSV"
1121
1127
  }
1122
1128
  ),
1129
+ emailHandler && /* @__PURE__ */ jsx(
1130
+ "button",
1131
+ {
1132
+ onClick: () => emailHandler(serializeCSV(), `${title || "spreadsheet"}.csv`),
1133
+ className: "text-xs text-gray-600 hover:text-gray-900 px-2 py-1 rounded hover:bg-gray-200 transition-colors",
1134
+ children: "Email"
1135
+ }
1136
+ ),
1123
1137
  /* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-gray-300" }),
1124
1138
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1125
1139
  /* @__PURE__ */ jsx(
@@ -1294,5 +1308,5 @@ function Spreadsheet() {
1294
1308
  }
1295
1309
 
1296
1310
  export { EditableGrid, Spreadsheet, setSpreadsheetPreview };
1297
- //# sourceMappingURL=chunk-5THABSPK.js.map
1298
- //# sourceMappingURL=chunk-5THABSPK.js.map
1311
+ //# sourceMappingURL=chunk-HQWHWS7V.js.map
1312
+ //# sourceMappingURL=chunk-HQWHWS7V.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/shell/EditableGrid.tsx","../src/apps/Spreadsheet.tsx"],"names":["useRef","useEffect","useState","useCallback","jsxs","jsx","Fragment"],"mappings":"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","file":"chunk-HQWHWS7V.js","sourcesContent":["import { useState, useRef, useCallback, useEffect, useMemo } from 'react';\nimport { createPortal } from 'react-dom';\n\nexport interface GridColumn {\n key: string;\n title: string;\n width?: number;\n readOnly?: boolean;\n align?: 'left' | 'right' | 'center';\n}\n\nexport type CellStyle = {\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n fontSize?: 'sm' | 'base' | 'lg' | 'xl';\n};\n\nexport interface EditableGridProps {\n columns: GridColumn[];\n data: string[][];\n onChange: (data: string[][]) => void;\n onColumnsChange?: (columns: GridColumn[]) => void;\n /** Fixed row count — disables add/delete rows */\n fixedRows?: boolean;\n minRows?: number;\n maxHeight?: string;\n /** Per-cell text styling, keyed by `${row}:${col}`. */\n cellStyles?: Record<string, CellStyle>;\n /** Notifies the parent when the focused/edited cell changes. */\n onFocusChange?: (pos: { row: number; col: number } | null) => void;\n /** Notifies the parent when the selection rectangle changes. */\n onSelectionChange?: (sel: { anchor: { row: number; col: number }; end: { row: number; col: number } } | null) => void;\n}\n\ninterface CellPos { row: number; col: number }\n\nfunction rangeContains(anchor: CellPos, end: CellPos, row: number, col: number): boolean {\n const r1 = Math.min(anchor.row, end.row), r2 = Math.max(anchor.row, end.row);\n const c1 = Math.min(anchor.col, end.col), c2 = Math.max(anchor.col, end.col);\n return row >= r1 && row <= r2 && col >= c1 && col <= c2;\n}\n\n/**\n * Lightweight editable grid with spreadsheet-like features:\n * - Click + drag to select a range of cells\n * - Ctrl+C / Cmd+C to copy selection as tab-delimited text\n * - Multi-cell paste from spreadsheets (Ctrl+V)\n * - Tab/Enter/Arrow keyboard navigation\n */\nexport default function EditableGrid({ columns, data, onChange, onColumnsChange, fixedRows = false, minRows = 15, maxHeight = '260px', cellStyles, onFocusChange, onSelectionChange }: EditableGridProps) {\n const tableRef = useRef<HTMLTableElement>(null);\n const [focus, setFocus] = useState<CellPos | null>(null);\n useEffect(() => { onFocusChange?.(focus); }, [focus, onFocusChange]);\n\n // Column resize state\n const [colWidths, setColWidths] = useState<Record<number, number>>({});\n const resizing = useRef<{ col: number; startX: number; startW: number } | null>(null);\n\n // Row resize state\n const [rowHeights, setRowHeights] = useState<Record<number, number>>({});\n const rowResizing = useRef<{ row: number; startY: number; startH: number } | null>(null);\n\n // Drag reorder state\n const [dragRow, setDragRow] = useState<number | null>(null);\n const [dragOverRow, setDragOverRow] = useState<number | null>(null);\n const [dragCol, setDragCol] = useState<number | null>(null);\n const [dragOverCol, setDragOverCol] = useState<number | null>(null);\n const [editingCell, setEditingCell] = useState<CellPos | null>(null);\n\n // Range selection state\n const [selAnchor, setSelAnchor] = useState<CellPos | null>(null);\n const [selEnd, setSelEnd] = useState<CellPos | null>(null);\n useEffect(() => {\n onSelectionChange?.(selAnchor && selEnd ? { anchor: selAnchor, end: selEnd } : null);\n }, [selAnchor, selEnd, onSelectionChange]);\n const dragging = useRef(false);\n\n // Fill handle state\n const [fillTarget, setFillTarget] = useState<CellPos | null>(null);\n const filling = useRef(false);\n const selRefForFill = useRef<{ a: CellPos | null; e: CellPos | null }>({ a: null, e: null });\n selRefForFill.current = { a: selAnchor, e: selEnd };\n\n const hasRange = selAnchor && selEnd && (selAnchor.row !== selEnd.row || selAnchor.col !== selEnd.col);\n\n // Ensure minimum rows\n const rows = [...data];\n if (!fixedRows) {\n while (rows.length < minRows) rows.push(Array(columns.length).fill(''));\n }\n\n const updateCell = useCallback((row: number, col: number, value: string) => {\n const next = rows.map(r => [...r]);\n while (next.length <= row) next.push(Array(columns.length).fill(''));\n while (next[row].length < columns.length) next[row].push('');\n next[row][col] = value;\n onChange(next);\n }, [rows, columns.length, onChange]);\n\n // Mouse drag selection\n const handleMouseDown = useCallback((e: React.MouseEvent, row: number, col: number) => {\n if (e.button !== 0) return;\n // Commit the currently focused cell's value before moving\n const active = document.activeElement as HTMLElement;\n if (active?.dataset?.row && active?.dataset?.col) {\n const ar = parseInt(active.dataset.row);\n const ac = parseInt(active.dataset.col);\n const val = active.textContent || '';\n if (val !== (rows[ar]?.[ac] || '')) {\n const next = rows.map(r => [...r]);\n if (next[ar]) { next[ar][ac] = val; onChange(next); }\n }\n }\n dragging.current = true;\n if (e.shiftKey && selAnchor) {\n // Shift+click: extend selection from anchor to clicked cell\n setSelEnd({ row, col });\n } else {\n setSelAnchor({ row, col });\n setSelEnd({ row, col });\n }\n }, [rows, onChange, selAnchor]);\n\n const handleMouseEnter = useCallback((row: number, col: number) => {\n if (dragging.current) {\n setSelEnd({ row, col });\n }\n }, []);\n\n useEffect(() => {\n const handleMouseUp = () => { dragging.current = false; };\n window.addEventListener('mouseup', handleMouseUp);\n return () => window.removeEventListener('mouseup', handleMouseUp);\n }, []);\n\n // Copy selection with Ctrl+C / Cmd+C\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (!(e.ctrlKey || e.metaKey) || e.key !== 'c') return;\n if (!selAnchor || !selEnd) return;\n // Don't intercept if user has text selected within a cell\n const nativeSel = window.getSelection();\n if (nativeSel && nativeSel.toString().length > 0 && !hasRange) return;\n\n const r1 = Math.min(selAnchor.row, selEnd.row), r2 = Math.max(selAnchor.row, selEnd.row);\n const c1 = Math.min(selAnchor.col, selEnd.col), c2 = Math.max(selAnchor.col, selEnd.col);\n\n const text = [];\n for (let r = r1; r <= r2; r++) {\n const rowCells = [];\n for (let c = c1; c <= c2; c++) {\n rowCells.push(rows[r]?.[c] || '');\n }\n text.push(rowCells.join('\\t'));\n }\n const tsv = text.join('\\n');\n if (tsv) {\n e.preventDefault();\n navigator.clipboard.writeText(tsv);\n }\n };\n window.addEventListener('keydown', handler);\n return () => window.removeEventListener('keydown', handler);\n }, [selAnchor, selEnd, rows, hasRange]);\n\n // Global paste — works even when cell is selected but not editing\n useEffect(() => {\n const handler = (e: ClipboardEvent) => {\n if (!focus) return;\n // Don't intercept if already in an editable element\n const active = document.activeElement as HTMLElement;\n if (active?.isContentEditable) return;\n // Only intercept if focus is inside our grid\n if (!tableRef.current?.contains(active)) return;\n\n const text = e.clipboardData?.getData('text/plain');\n if (!text) return;\n\n e.preventDefault();\n const pastedRows = text.split('\\n').filter(l => l).map(line => line.split('\\t'));\n const next = rows.map(r => [...r]);\n\n for (let r = 0; r < pastedRows.length; r++) {\n const targetRow = focus.row + r;\n while (next.length <= targetRow) next.push(Array(columns.length).fill(''));\n while (next[targetRow].length < columns.length) next[targetRow].push('');\n for (let c = 0; c < pastedRows[r].length; c++) {\n const targetCol = focus.col + c;\n if (targetCol >= columns.length) break;\n if (columns[targetCol].readOnly) continue;\n next[targetRow][targetCol] = pastedRows[r][c].trim();\n }\n }\n onChange(next);\n\n // Select the pasted range\n setSelAnchor({ row: focus.row, col: focus.col });\n setSelEnd({ row: Math.min(focus.row + pastedRows.length - 1, next.length - 1), col: Math.min(focus.col + (pastedRows[0]?.length || 1) - 1, columns.length - 1) });\n };\n window.addEventListener('paste', handler);\n return () => window.removeEventListener('paste', handler);\n }, [focus, rows, columns, onChange]);\n\n // Handle paste — supports multi-cell paste from spreadsheets (when in edit mode)\n const handlePaste = useCallback((e: React.ClipboardEvent, startRow: number, startCol: number) => {\n const text = e.clipboardData.getData('text/plain');\n if (!text) return;\n\n const pastedRows = text.split('\\n').map(line => line.split('\\t'));\n if (pastedRows.length <= 1 && pastedRows[0]?.length <= 1) return;\n\n e.preventDefault();\n const next = rows.map(r => [...r]);\n\n for (let r = 0; r < pastedRows.length; r++) {\n const targetRow = startRow + r;\n while (next.length <= targetRow) next.push(Array(columns.length).fill(''));\n while (next[targetRow].length < columns.length) next[targetRow].push('');\n for (let c = 0; c < pastedRows[r].length; c++) {\n const targetCol = startCol + c;\n if (targetCol >= columns.length) break;\n if (columns[targetCol].readOnly) continue;\n next[targetRow][targetCol] = pastedRows[r][c].trim();\n }\n }\n\n onChange(next);\n }, [rows, columns, onChange]);\n\n // Handle keyboard navigation\n const handleKeyDown = useCallback((e: React.KeyboardEvent, row: number, col: number) => {\n let nextRow = row;\n let nextCol = col;\n\n if (e.key === 'Tab') {\n e.preventDefault();\n nextCol = e.shiftKey ? col - 1 : col + 1;\n if (nextCol >= columns.length) { nextCol = 0; nextRow = row + 1; }\n if (nextCol < 0) { nextCol = columns.length - 1; nextRow = row - 1; }\n } else if (e.key === 'Enter') {\n e.preventDefault();\n nextRow = e.shiftKey ? row - 1 : row + 1;\n } else if (e.key === 'ArrowDown') {\n e.preventDefault();\n nextRow = row + 1;\n } else if (e.key === 'ArrowUp') {\n e.preventDefault();\n nextRow = row - 1;\n } else if (e.key === 'ArrowLeft') {\n e.preventDefault();\n nextCol = col - 1;\n } else if (e.key === 'ArrowRight') {\n e.preventDefault();\n nextCol = col + 1;\n } else if (e.key === 'Delete' || e.key === 'Backspace') {\n const target = e.target as HTMLElement;\n // While editing, only intercept when the whole cell text is selected.\n if (target.isContentEditable) {\n if (target.textContent && window.getSelection()?.toString() === target.textContent) {\n e.preventDefault();\n updateCell(row, col, '');\n }\n return;\n }\n // Not editing — clear the selection range (or just this cell).\n e.preventDefault();\n if (selAnchor && selEnd) {\n const r1 = Math.min(selAnchor.row, selEnd.row), r2 = Math.max(selAnchor.row, selEnd.row);\n const c1 = Math.min(selAnchor.col, selEnd.col), c2 = Math.max(selAnchor.col, selEnd.col);\n const next = rows.map(r => [...r]);\n for (let r = r1; r <= r2; r++) for (let c = c1; c <= c2; c++) {\n if (next[r] && !columns[c]?.readOnly) next[r][c] = '';\n }\n onChange(next);\n } else {\n updateCell(row, col, '');\n }\n return;\n } else {\n return;\n }\n\n // Skip read-only columns\n while (nextCol >= 0 && nextCol < columns.length && columns[nextCol].readOnly) {\n nextCol += e.key === 'Tab' && e.shiftKey ? -1 : 1;\n }\n\n if (nextRow >= 0 && nextRow < rows.length && nextCol >= 0 && nextCol < columns.length) {\n const cell = tableRef.current?.querySelector(`[data-row=\"${nextRow}\"][data-col=\"${nextCol}\"]`) as HTMLElement;\n if (cell) {\n cell.focus({ preventScroll: true });\n cell.scrollIntoView({ block: 'nearest', inline: 'nearest' });\n setFocus({ row: nextRow, col: nextCol });\n setEditingCell(null);\n setSelAnchor({ row: nextRow, col: nextCol });\n setSelEnd({ row: nextRow, col: nextCol });\n }\n }\n }, [columns, rows, rows.length, updateCell, selAnchor, selEnd, onChange]);\n\n // Add rows when typing in the last row\n const ensureRows = useCallback((row: number) => {\n if (fixedRows) return;\n if (row >= rows.length - 2) {\n const next = rows.map(r => [...r]);\n for (let i = 0; i < 5; i++) next.push(Array(columns.length).fill(''));\n onChange(next);\n }\n }, [fixedRows, rows, columns.length, onChange]);\n\n // Context menu\n const [ctxMenu, setCtxMenu] = useState<{ x: number; y: number; items: { label: string; onClick: () => void }[] } | null>(null);\n\n // Close context menu on click outside\n useEffect(() => {\n if (!ctxMenu) return;\n const handler = () => setCtxMenu(null);\n window.addEventListener('pointerdown', handler);\n return () => window.removeEventListener('pointerdown', handler);\n }, [ctxMenu]);\n\n const insertRow = useCallback((at: number) => {\n const next = rows.map(r => [...r]);\n next.splice(at, 0, Array(columns.length).fill(''));\n onChange(next);\n }, [rows, columns.length, onChange]);\n\n const deleteRow = useCallback((at: number) => {\n if (rows.length <= 1) return;\n const next = rows.filter((_, i) => i !== at);\n onChange(next);\n }, [rows, onChange]);\n\n const insertCol = useCallback((at: number) => {\n const next = rows.map(r => { const nr = [...r]; nr.splice(at, 0, ''); return nr; });\n onChange(next);\n }, [rows, onChange]);\n\n const deleteCol = useCallback((at: number) => {\n if (columns.length <= 1) return;\n const next = rows.map(r => { const nr = [...r]; nr.splice(at, 1); return nr; });\n onChange(next);\n }, [rows, columns.length, onChange]);\n\n const handleRowCtx = useCallback((e: React.MouseEvent, ri: number) => {\n e.preventDefault();\n if (fixedRows) return;\n setCtxMenu({ x: e.clientX, y: e.clientY, items: [\n { label: `Insert row above`, onClick: () => { insertRow(ri); setCtxMenu(null); } },\n { label: `Insert row below`, onClick: () => { insertRow(ri + 1); setCtxMenu(null); } },\n { label: `Delete row ${ri + 1}`, onClick: () => { deleteRow(ri); setCtxMenu(null); } },\n ]});\n }, [fixedRows, insertRow, deleteRow]);\n\n const handleColCtx = useCallback((e: React.MouseEvent, ci: number) => {\n e.preventDefault();\n if (fixedRows) return;\n setCtxMenu({ x: e.clientX, y: e.clientY, items: [\n { label: `Insert column left`, onClick: () => { insertCol(ci); setCtxMenu(null); } },\n { label: `Insert column right`, onClick: () => { insertCol(ci + 1); setCtxMenu(null); } },\n { label: `Delete column ${columns[ci]?.title || ci + 1}`, onClick: () => { deleteCol(ci); setCtxMenu(null); } },\n ]});\n }, [fixedRows, columns, insertCol, deleteCol]);\n\n // Column resize\n const getColWidth = (ci: number) => colWidths[ci] ?? columns[ci]?.width ?? 150;\n\n useEffect(() => {\n const handleMouseMove = (e: MouseEvent) => {\n if (!resizing.current) return;\n const diff = e.clientX - resizing.current.startX;\n const newW = Math.max(40, resizing.current.startW + diff);\n setColWidths(prev => ({ ...prev, [resizing.current!.col]: newW }));\n };\n const handleMouseUp = () => {\n if (resizing.current && onColumnsChange) {\n const updated = columns.map((c, i) => ({ ...c, width: colWidths[i] ?? c.width }));\n updated[resizing.current.col] = { ...updated[resizing.current.col], width: colWidths[resizing.current.col] ?? columns[resizing.current.col].width };\n onColumnsChange(updated);\n }\n resizing.current = null;\n document.body.style.cursor = '';\n };\n window.addEventListener('mousemove', handleMouseMove);\n window.addEventListener('mouseup', handleMouseUp);\n return () => { window.removeEventListener('mousemove', handleMouseMove); window.removeEventListener('mouseup', handleMouseUp); };\n }, [columns, colWidths, onColumnsChange]);\n\n const startColResize = (e: React.MouseEvent, ci: number) => {\n e.preventDefault();\n e.stopPropagation();\n resizing.current = { col: ci, startX: e.clientX, startW: getColWidth(ci) };\n document.body.style.cursor = 'col-resize';\n };\n\n // Row resize\n const getRowHeight = (ri: number) => rowHeights[ri] ?? 28;\n useEffect(() => {\n const handleMove = (e: MouseEvent) => {\n if (!rowResizing.current) return;\n const diff = e.clientY - rowResizing.current.startY;\n const newH = Math.max(20, rowResizing.current.startH + diff);\n setRowHeights(prev => ({ ...prev, [rowResizing.current!.row]: newH }));\n };\n const handleUp = () => { rowResizing.current = null; document.body.style.cursor = ''; };\n window.addEventListener('mousemove', handleMove);\n window.addEventListener('mouseup', handleUp);\n return () => { window.removeEventListener('mousemove', handleMove); window.removeEventListener('mouseup', handleUp); };\n }, []);\n const startRowResize = (e: React.MouseEvent, ri: number) => {\n e.preventDefault();\n e.stopPropagation();\n rowResizing.current = { row: ri, startY: e.clientY, startH: getRowHeight(ri) };\n document.body.style.cursor = 'row-resize';\n };\n\n // Auto-fit column to the widest cell content (data + header).\n const autoFitColumn = useCallback((ci: number) => {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n ctx.font = '12px ui-monospace, SFMono-Regular, Menlo, monospace';\n let maxW = 0;\n for (const row of rows) {\n const plain = String(row[ci] ?? '').replace(/<[^>]*>/g, '');\n const w = ctx.measureText(plain).width;\n if (w > maxW) maxW = w;\n }\n const headerW = ctx.measureText(columns[ci]?.title ?? '').width;\n if (headerW > maxW) maxW = headerW;\n const finalW = Math.max(40, Math.ceil(maxW + 24));\n setColWidths(prev => ({ ...prev, [ci]: finalW }));\n if (onColumnsChange) {\n const updated = columns.map((c, i) => ({ ...c, width: i === ci ? finalW : (colWidths[i] ?? c.width) }));\n onColumnsChange(updated);\n }\n }, [rows, columns, colWidths, onColumnsChange]);\n\n // Auto-fit row — reset to the default height (cells use whitespace-nowrap so\n // a single row line is the natural fit).\n const autoFitRow = useCallback((ri: number) => {\n setRowHeights(prev => { const next = { ...prev }; delete next[ri]; return next; });\n }, []);\n\n // Fill handle — drag the small square at the bottom-right of the selection\n // to copy / extrapolate values into adjacent cells.\n const applyFill = useCallback((target: CellPos) => {\n const { a: sa, e: se } = selRefForFill.current;\n if (!sa || !se) return;\n const r1 = Math.min(sa.row, se.row);\n const r2 = Math.max(sa.row, se.row);\n const c1 = Math.min(sa.col, se.col);\n const c2 = Math.max(sa.col, se.col);\n\n let nr1 = r1, nr2 = r2, nc1 = c1, nc2 = c2;\n if (target.row > r2) nr2 = target.row;\n else if (target.row < r1) nr1 = target.row;\n if (target.col > c2) nc2 = target.col;\n else if (target.col < c1) nc1 = target.col;\n\n const selH = r2 - r1 + 1;\n const selW = c2 - c1 + 1;\n const next = rows.map(r => [...r]);\n while (next.length <= nr2) next.push(Array(columns.length).fill(''));\n for (const row of next) while (row.length <= nc2) row.push('');\n\n // Detect a 1-d numeric arithmetic sequence so vertical/horizontal drags\n // continue the series instead of repeating the pattern.\n function asSeries(values: string[]): { step: number } | null {\n const nums = values.map(v => parseFloat(v));\n if (nums.length < 2 || nums.some(n => Number.isNaN(n))) return null;\n const step = nums[1] - nums[0];\n for (let i = 2; i < nums.length; i++) {\n if (Math.abs((nums[i] - nums[i - 1]) - step) > 1e-9) return null;\n }\n return { step };\n }\n\n for (let r = nr1; r <= nr2; r++) {\n for (let c = nc1; c <= nc2; c++) {\n if (r >= r1 && r <= r2 && c >= c1 && c <= c2) continue; // inside original\n let value: string;\n if (selW === 1 && nc1 === c1 && nc2 === c2) {\n // Vertical fill (same column as selection).\n const colVals = Array.from({ length: selH }, (_, i) => next[r1 + i]?.[c] ?? '');\n const series = asSeries(colVals);\n if (series) {\n const last = parseFloat(next[r2]?.[c] ?? '0');\n const first = parseFloat(next[r1]?.[c] ?? '0');\n const offset = r > r2 ? r - r2 : -(r1 - r);\n value = String((r > r2 ? last : first) + series.step * offset);\n } else {\n const dr = ((r - r1) % selH + selH) % selH;\n value = next[r1 + dr]?.[c] ?? '';\n }\n } else if (selH === 1 && nr1 === r1 && nr2 === r2) {\n // Horizontal fill (same row as selection).\n const rowVals = Array.from({ length: selW }, (_, i) => next[r]?.[c1 + i] ?? '');\n const series = asSeries(rowVals);\n if (series) {\n const last = parseFloat(next[r]?.[c2] ?? '0');\n const first = parseFloat(next[r]?.[c1] ?? '0');\n const offset = c > c2 ? c - c2 : -(c1 - c);\n value = String((c > c2 ? last : first) + series.step * offset);\n } else {\n const dc = ((c - c1) % selW + selW) % selW;\n value = next[r]?.[c1 + dc] ?? '';\n }\n } else {\n // 2-d fill — tile the selection rectangle.\n const dr = ((r - r1) % selH + selH) % selH;\n const dc = ((c - c1) % selW + selW) % selW;\n value = next[r1 + dr]?.[c1 + dc] ?? '';\n }\n next[r][c] = value;\n }\n }\n\n onChange(next);\n setSelAnchor({ row: nr1, col: nc1 });\n setSelEnd({ row: nr2, col: nc2 });\n }, [rows, columns.length, onChange]);\n\n useEffect(() => {\n const handleMove = (e: MouseEvent) => {\n if (!filling.current) return;\n const el = document.elementFromPoint(e.clientX, e.clientY);\n const inner = (el as HTMLElement)?.closest?.('[data-row][data-col]') as HTMLElement | null;\n if (!inner) return;\n const r = parseInt(inner.dataset.row!);\n const c = parseInt(inner.dataset.col!);\n setFillTarget({ row: r, col: c });\n };\n const handleUp = () => {\n if (filling.current && fillTarget) applyFill(fillTarget);\n filling.current = false;\n setFillTarget(null);\n document.body.style.cursor = '';\n };\n window.addEventListener('mousemove', handleMove);\n window.addEventListener('mouseup', handleUp);\n return () => {\n window.removeEventListener('mousemove', handleMove);\n window.removeEventListener('mouseup', handleUp);\n };\n }, [fillTarget, applyFill]);\n\n const startFill = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n filling.current = true;\n document.body.style.cursor = 'crosshair';\n };\n\n // Row drag reorder\n const handleRowDragStart = (ri: number) => setDragRow(ri);\n const handleRowDragOver = (e: React.DragEvent, ri: number) => { e.preventDefault(); setDragOverRow(ri); };\n const handleRowDrop = (ri: number) => {\n if (dragRow === null || dragRow === ri) { setDragRow(null); setDragOverRow(null); return; }\n const next = rows.map(r => [...r]);\n const [moved] = next.splice(dragRow, 1);\n next.splice(ri, 0, moved);\n onChange(next);\n setDragRow(null);\n setDragOverRow(null);\n };\n\n // Column drag reorder\n const handleColDragStart = (ci: number) => setDragCol(ci);\n const handleColDragOver = (e: React.DragEvent, ci: number) => { e.preventDefault(); setDragOverCol(ci); };\n const handleColDrop = (ci: number) => {\n if (dragCol === null || dragCol === ci) { setDragCol(null); setDragOverCol(null); return; }\n const next = rows.map(r => {\n const nr = [...r];\n const [moved] = nr.splice(dragCol, 1);\n nr.splice(ci, 0, moved);\n return nr;\n });\n onChange(next);\n if (onColumnsChange) {\n const newCols = [...columns];\n const [moved] = newCols.splice(dragCol, 1);\n newCols.splice(ci, 0, moved);\n onColumnsChange(newCols);\n }\n setDragCol(null);\n setDragOverCol(null);\n };\n\n // Virtual scrolling — only render visible rows + buffer\n const ROW_HEIGHT = 28;\n const BUFFER = 20;\n const containerRef = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState(0);\n const [containerHeight, setContainerHeight] = useState(800);\n\n // Measure actual container height\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const measure = () => setContainerHeight(el.clientHeight || 800);\n measure();\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n return () => observer.disconnect();\n }, []);\n\n // Only virtualize if there are many rows (>100), otherwise render all\n const useVirtualization = rows.length > 100;\n const visibleStart = useVirtualization ? Math.max(0, Math.floor(scrollTop / ROW_HEIGHT) - BUFFER) : 0;\n const visibleEnd = useVirtualization ? Math.min(rows.length, Math.ceil((scrollTop + containerHeight) / ROW_HEIGHT) + BUFFER) : rows.length;\n const visibleRows = useMemo(() => rows.slice(visibleStart, visibleEnd), [rows, visibleStart, visibleEnd]);\n const topPad = visibleStart * ROW_HEIGHT;\n const bottomPad = (rows.length - visibleEnd) * ROW_HEIGHT;\n\n const thCls = 'px-2 py-1.5 text-left text-xs font-medium text-gray-500 uppercase bg-gray-100 border-b border-r border-gray-200 select-none';\n const tdCls = 'px-0 py-0 border-b border-r border-gray-200 text-sm';\n\n return (\n <div ref={containerRef} className=\"border border-gray-300 rounded overflow-scroll grid-scroll\"\n style={{ maxHeight, height: maxHeight }}\n onScroll={(e) => setScrollTop((e.target as HTMLElement).scrollTop)}>\n <table ref={tableRef} className=\"border-collapse select-none\" style={{ tableLayout: 'fixed', minWidth: 36 + columns.reduce((s, c) => s + (getColWidth(columns.indexOf(c))), 0) }}>\n <colgroup>\n <col style={{ width: 36 }} />\n {columns.map((c, ci) => <col key={c.key} style={{ width: getColWidth(ci) }} />)}\n </colgroup>\n <thead className=\"sticky top-0 z-10\">\n <tr>\n <th className={thCls + ' text-center w-9 cursor-pointer hover:bg-gray-200'}\n onClick={() => { setSelAnchor({ row: 0, col: 0 }); setSelEnd({ row: rows.length - 1, col: columns.length - 1 }); }}\n title=\"Select all\">#</th>\n {columns.map((c, ci) => {\n const colSelected = selAnchor && selEnd && Math.min(selAnchor.col, selEnd.col) <= ci && ci <= Math.max(selAnchor.col, selEnd.col)\n && Math.min(selAnchor.row, selEnd.row) === 0 && Math.max(selAnchor.row, selEnd.row) === rows.length - 1;\n return (\n <th key={c.key} className={`${thCls} cursor-pointer hover:bg-gray-200 relative${colSelected ? ' !bg-blue-200' : ''}${dragOverCol === ci ? ' !bg-blue-100' : ''}`}\n style={{ width: getColWidth(ci) }}\n draggable\n onDragStart={() => handleColDragStart(ci)}\n onDragOver={(e) => handleColDragOver(e, ci)}\n onDrop={() => handleColDrop(ci)}\n onDragEnd={() => { setDragCol(null); setDragOverCol(null); }}\n onClick={(e) => {\n if (e.shiftKey && selAnchor) {\n setSelEnd({ row: rows.length - 1, col: ci });\n } else {\n setSelAnchor({ row: 0, col: ci }); setSelEnd({ row: rows.length - 1, col: ci });\n }\n }}\n onContextMenu={(e) => handleColCtx(e, ci)}>\n {c.title}\n {/* Resize handle — thin edge, wider hover target */}\n <div className=\"absolute -right-1 top-0 bottom-0 w-2 cursor-col-resize z-20\"\n onMouseDown={(e) => startColResize(e, ci)}\n onDoubleClick={(e) => { e.stopPropagation(); autoFitColumn(ci); }}\n title=\"Drag to resize · double-click to auto-fit\"\n />\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {topPad > 0 && <tr style={{ height: topPad }} />}\n {visibleRows.map((row, vi) => {\n const ri = visibleStart + vi;\n const rowSelected = selAnchor && selEnd && Math.min(selAnchor.row, selEnd.row) <= ri && ri <= Math.max(selAnchor.row, selEnd.row)\n && Math.min(selAnchor.col, selEnd.col) === 0 && Math.max(selAnchor.col, selEnd.col) === columns.length - 1;\n return (\n <tr key={ri} style={{ height: getRowHeight(ri) }}>\n <td className={`relative px-1 py-1 text-center text-[10px] text-gray-400 border-b border-r border-gray-200 bg-gray-50 select-none cursor-pointer hover:bg-gray-200${rowSelected ? ' !bg-blue-200 !text-gray-700' : ''}${dragOverRow === ri ? ' !bg-blue-100' : ''}`}\n draggable\n onDragStart={() => handleRowDragStart(ri)}\n onDragOver={(e) => handleRowDragOver(e, ri)}\n onDrop={() => handleRowDrop(ri)}\n onDragEnd={() => { setDragRow(null); setDragOverRow(null); }}\n onClick={(e) => {\n if (e.shiftKey && selAnchor) {\n setSelEnd({ row: ri, col: columns.length - 1 });\n } else {\n setSelAnchor({ row: ri, col: 0 }); setSelEnd({ row: ri, col: columns.length - 1 });\n }\n }}\n onContextMenu={(e) => handleRowCtx(e, ri)}>\n {ri + 1}\n {/* Row resize handle — slim bar at the bottom of the row header */}\n <div className=\"absolute -bottom-1 left-0 right-0 h-2 cursor-row-resize z-20\"\n onMouseDown={(e) => startRowResize(e, ri)}\n onDoubleClick={(e) => { e.stopPropagation(); autoFitRow(ri); }}\n title=\"Drag to resize · double-click to auto-fit\"\n />\n </td>\n {columns.map((col, ci) => {\n const inRange = selAnchor && selEnd && rangeContains(selAnchor, selEnd, ri, ci);\n const isEditing = editingCell?.row === ri && editingCell?.col === ci && !col.readOnly;\n const isFocused = focus?.row === ri && focus?.col === ci;\n const cellStyle = cellStyles?.[`${ri}:${ci}`];\n const selR2 = selAnchor && selEnd ? Math.max(selAnchor.row, selEnd.row) : -1;\n const selC2 = selAnchor && selEnd ? Math.max(selAnchor.col, selEnd.col) : -1;\n const isFillCorner = selAnchor && selEnd && ri === selR2 && ci === selC2;\n const inFillPreview = filling.current && fillTarget && selAnchor && selEnd && (() => {\n const r1 = Math.min(selAnchor.row, selEnd.row), r2 = Math.max(selAnchor.row, selEnd.row);\n const c1 = Math.min(selAnchor.col, selEnd.col), c2 = Math.max(selAnchor.col, selEnd.col);\n let nr1 = r1, nr2 = r2, nc1 = c1, nc2 = c2;\n if (fillTarget.row > r2) nr2 = fillTarget.row; else if (fillTarget.row < r1) nr1 = fillTarget.row;\n if (fillTarget.col > c2) nc2 = fillTarget.col; else if (fillTarget.col < c1) nc1 = fillTarget.col;\n return ri >= nr1 && ri <= nr2 && ci >= nc1 && ci <= nc2 && !(ri >= r1 && ri <= r2 && ci >= c1 && ci <= c2);\n })();\n const fontSizeCls = cellStyle?.fontSize === 'sm' ? 'text-[11px]'\n : cellStyle?.fontSize === 'lg' ? 'text-sm'\n : cellStyle?.fontSize === 'xl' ? 'text-base'\n : 'text-xs';\n const styleCls = `${cellStyle?.bold ? ' font-bold' : ''}${cellStyle?.italic ? ' italic' : ''}${cellStyle?.underline ? ' underline' : ''}`;\n return (\n <td key={ci}\n className={`relative ${tdCls}${col.readOnly ? ' bg-gray-50 text-gray-500 cursor-default' : ' cursor-cell'}${inRange ? ' !bg-blue-100' : ''}${isFocused && !inRange ? ' ring-2 ring-inset ring-blue-400' : ''}${inFillPreview ? ' !bg-blue-50 ring-1 ring-inset ring-blue-300' : ''}`}\n onMouseDown={(e) => {\n // td-level handler so clicks anywhere in the cell (incl. borders) select.\n if (e.target === e.currentTarget) {\n handleMouseDown(e, ri, ci);\n const inner = e.currentTarget.querySelector<HTMLElement>('[data-row][data-col]');\n inner?.focus();\n }\n }}\n onMouseEnter={() => handleMouseEnter(ri, ci)}\n onClick={(e) => {\n if (e.target === e.currentTarget) {\n const inner = e.currentTarget.querySelector<HTMLElement>('[data-row][data-col]');\n inner?.focus();\n }\n }}\n onDoubleClick={(e) => {\n if (e.target === e.currentTarget && !col.readOnly) setEditingCell({ row: ri, col: ci });\n }}>\n <div\n contentEditable={isEditing}\n suppressContentEditableWarning\n tabIndex={0}\n data-row={ri}\n data-col={ci}\n className={`w-full h-full px-2 py-1 outline-none whitespace-nowrap overflow-hidden ${\n col.align === 'right' ? 'text-right' : col.align === 'center' ? 'text-center' : ''\n } ${col.readOnly ? 'cursor-default' : 'cursor-cell'} font-mono ${fontSizeCls}${styleCls}`}\n onMouseDown={(e) => handleMouseDown(e, ri, ci)}\n onMouseEnter={() => handleMouseEnter(ri, ci)}\n onDoubleClick={() => { if (!col.readOnly) setEditingCell({ row: ri, col: ci }); }}\n onFocus={() => {\n setFocus({ row: ri, col: ci });\n if (!dragging.current) {\n setSelAnchor({ row: ri, col: ci });\n setSelEnd({ row: ri, col: ci });\n }\n }}\n onBlur={(e) => {\n const val = e.currentTarget.textContent || '';\n if (val !== (row[ci] || '')) updateCell(ri, ci, val);\n setEditingCell(null);\n }}\n onInput={() => ensureRows(ri)}\n onPaste={(e) => handlePaste(e, ri, ci)}\n onKeyDown={(e) => {\n // Start editing on any printable key — clear cell and type\n if (!isEditing && !col.readOnly && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\n e.preventDefault();\n updateCell(ri, ci, e.key);\n setEditingCell({ row: ri, col: ci });\n // Place cursor at end after React re-renders\n requestAnimationFrame(() => {\n const el = tableRef.current?.querySelector(`[data-row=\"${ri}\"][data-col=\"${ci}\"]`) as HTMLElement;\n if (el) {\n el.focus();\n const range = document.createRange();\n range.selectNodeContents(el);\n range.collapse(false);\n const sel = window.getSelection();\n sel?.removeAllRanges();\n sel?.addRange(range);\n }\n });\n return;\n }\n handleKeyDown(e, ri, ci);\n }}\n dangerouslySetInnerHTML={{ __html: row[ci] || '' }}\n />\n {isFillCorner && (\n <div\n onMouseDown={startFill}\n title=\"Drag to fill\"\n className=\"absolute -bottom-[3px] -right-[3px] w-[7px] h-[7px] bg-blue-500 border border-white cursor-crosshair z-30 hover:bg-blue-600\"\n />\n )}\n </td>\n );\n })}\n </tr>\n );\n })}\n {bottomPad > 0 && <tr style={{ height: bottomPad }} />}\n </tbody>\n </table>\n\n {/* Context menu — portalled to body to avoid overflow clipping */}\n {ctxMenu && createPortal(\n <>\n <div className=\"fixed inset-0 z-[200]\" onPointerDown={() => setCtxMenu(null)} />\n <div className=\"fixed z-[201] bg-white rounded-lg shadow-lg border border-gray-200 py-1 min-w-[160px]\"\n style={{ left: ctxMenu.x, top: ctxMenu.y }}>\n {ctxMenu.items.map((item, i) => (\n <button key={i} onPointerDown={e => { e.stopPropagation(); item.onClick(); }}\n className=\"w-full text-left px-3 py-1.5 text-sm text-gray-700 hover:bg-gray-100\">\n {item.label}\n </button>\n ))}\n </div>\n </>,\n document.body\n )}\n </div>\n );\n}\n","import { useState, useCallback, useEffect, useRef } from 'react';\nimport EditableGrid from '../shell/EditableGrid';\nimport type { GridColumn, CellStyle } from '../shell/EditableGrid';\nimport { WindowTitle } from '../shell/Modal';\nimport AboutApp from './_about';\n\nconst TITLE_DISPLAY_MAX = 24;\nfunction truncateForTitle(s: string) {\n return s.length > TITLE_DISPLAY_MAX ? `${s.slice(0, TITLE_DISPLAY_MAX - 1)}…` : s;\n}\n\nconst ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst DEFAULT_COLS = 10;\nconst DEFAULT_ROWS = 30;\n\nfunction colLabel(i: number): string {\n if (i < 26) return ALPHA[i];\n return ALPHA[Math.floor(i / 26) - 1] + ALPHA[i % 26];\n}\n\nfunction makeColumns(count: number): GridColumn[] {\n return Array.from({ length: count }, (_, i) => ({\n key: `col_${i}`,\n title: colLabel(i),\n width: 100,\n }));\n}\n\nfunction makeEmptyData(rows: number, cols: number): string[][] {\n return Array.from({ length: rows }, () => Array(cols).fill(''));\n}\n\ninterface Sheet {\n id: string;\n name: string;\n columns: GridColumn[];\n data: string[][];\n /** Per-cell text styling. Key: `${row}:${col}`. */\n cellStyles?: Record<string, CellStyle>;\n}\n\nfunction newSheet(name: string): Sheet {\n return {\n id: crypto.randomUUID(),\n name,\n columns: makeColumns(DEFAULT_COLS),\n data: makeEmptyData(DEFAULT_ROWS, DEFAULT_COLS),\n cellStyles: {},\n };\n}\n\nfunction parseCSV(text: string): string[][] {\n return text.split('\\n').map(line => {\n if (line.includes('\\t')) return line.split('\\t').map(s => s.trim());\n const parts: string[] = [];\n let current = '';\n let inQuotes = false;\n for (const ch of line) {\n if (ch === '\"') { inQuotes = !inQuotes; continue; }\n if (ch === ',' && !inQuotes) { parts.push(current.trim()); current = ''; continue; }\n current += ch;\n }\n parts.push(current.trim());\n return parts;\n }).filter(r => r.some(c => c.trim()));\n}\n\n/** Build a single padded sheet from CSV/TSV text. Shared by file import and\n * the `setSpreadsheetPreview` external-load path. */\nfunction sheetFromCSV(text: string, sheetName: string): Sheet | null {\n const parsed = parseCSV(text);\n if (parsed.length === 0) return null;\n const maxCols = Math.max(DEFAULT_COLS, parsed.reduce((m, r) => Math.max(m, r.length), 0));\n const padded = parsed.map(r => { while (r.length < maxCols) r.push(''); return r; });\n while (padded.length < DEFAULT_ROWS) padded.push(Array(maxCols).fill(''));\n return { id: crypto.randomUUID(), name: sheetName, columns: makeColumns(maxCols), data: padded, cellStyles: {} };\n}\n\nexport interface SpreadsheetPreviewData {\n /** CSV text (comma- or tab-separated). */\n csv: string;\n /** Display name; the title strips a trailing `.csv`/`.tsv`/`.txt`. */\n filename: string;\n /** When provided, the toolbar shows an Email button that calls back with the\n * sheet serialized as CSV at click time (edits included) and a filename\n * derived from the current title. */\n onEmail?: (csv: string, filename: string) => void;\n}\n\nconst SPREADSHEET_EVENT_NAME = 'react-os-shell:spreadsheet-preview-update';\n\n/** Handle returned by `setSpreadsheetPreview`. Holds the identity of the\n * staged payload so a later `.update()` only targets the window that picked\n * it up — opening a second Spreadsheet never clobbers the first. */\nexport interface SpreadsheetPreviewHandle {\n /** Replace the data shown in the window that consumed this staging.\n * No-op if no window ever consumed it, or if that window has been closed. */\n update(next: SpreadsheetPreviewData): void;\n}\n\ninterface PendingSpreadsheetStage {\n token: number;\n data: SpreadsheetPreviewData;\n}\n\nlet pendingSpreadsheet: PendingSpreadsheetStage | null = null;\nlet nextSpreadsheetToken = 0;\n\n/** Stage CSV content for the next Spreadsheet window mount. The returned\n * handle's `update()` method swaps content in *that* specific window only. */\nexport function setSpreadsheetPreview(data: SpreadsheetPreviewData): SpreadsheetPreviewHandle {\n const token = ++nextSpreadsheetToken;\n pendingSpreadsheet = { token, data };\n return {\n update(next: SpreadsheetPreviewData) {\n if (typeof window === 'undefined') return;\n window.dispatchEvent(new CustomEvent(SPREADSHEET_EVENT_NAME, { detail: { token, data: next } }));\n },\n };\n}\n\nexport default function Spreadsheet() {\n const containerRef = useRef<HTMLDivElement>(null);\n // One-shot drain: this instance claims whatever was staged and stores the\n // token so it can recognise later `.update()` calls aimed at it. The render\n // phase only PEEKS — under React 18 concurrent rendering a render pass can\n // be discarded and replayed (the first mount of this lazy component\n // suspends on its chunk), and a destructive read here would let the\n // discarded pass swallow the payload, leaving the committed window empty.\n // The stage is cleared in the mount effect below (commit phase) instead.\n const consumedRef = useRef<PendingSpreadsheetStage | null | undefined>(undefined);\n if (consumedRef.current === undefined) {\n consumedRef.current = pendingSpreadsheet;\n }\n useEffect(() => {\n // Claim the stage for real once mounted. The identity check keeps a\n // payload staged *after* our render-phase peek (e.g. a second preview\n // opened in quick succession) available for the window it belongs to.\n if (consumedRef.current !== null && pendingSpreadsheet === consumedRef.current) {\n pendingSpreadsheet = null;\n }\n }, []);\n const initialPreview = (() => {\n const p = consumedRef.current;\n if (!p) return null;\n const sheet = sheetFromCSV(p.data.csv, 'Sheet 1');\n if (!sheet) return null;\n const titleName = p.data.filename.replace(/\\.(csv|tsv|txt)$/i, '');\n return { sheet, title: titleName };\n })();\n const [sheets, setSheets] = useState<Sheet[]>(initialPreview ? [initialPreview.sheet] : [newSheet('Sheet 1')]);\n const [activeIdx, setActiveIdx] = useState(0);\n\n // Undo history — push a snapshot whenever sheets change, except when the\n // change came from undo itself.\n const undoStackRef = useRef<Sheet[][]>([]);\n const lastCommittedRef = useRef<Sheet[]>(sheets);\n const skipRecordRef = useRef(false);\n useEffect(() => {\n if (skipRecordRef.current) {\n skipRecordRef.current = false;\n } else if (lastCommittedRef.current !== sheets) {\n undoStackRef.current.push(lastCommittedRef.current);\n if (undoStackRef.current.length > 50) undoStackRef.current.shift();\n }\n lastCommittedRef.current = sheets;\n }, [sheets]);\n const undo = useCallback(() => {\n const prev = undoStackRef.current.pop();\n if (!prev) return;\n skipRecordRef.current = true;\n setSheets(prev);\n }, []);\n useEffect(() => {\n const handler = (e: KeyboardEvent) => {\n if (!containerRef.current?.contains(document.activeElement) && !containerRef.current?.matches(':focus-within')) return;\n const isUndo = (e.ctrlKey || e.metaKey) && !e.shiftKey && (e.key === 'z' || e.key === 'Z');\n if (isUndo) {\n e.preventDefault();\n undo();\n }\n };\n window.addEventListener('keydown', handler);\n return () => window.removeEventListener('keydown', handler);\n }, [undo]);\n const [title, setTitle] = useState(initialPreview?.title ?? 'Untitled');\n const [emailHandler, setEmailHandler] = useState<SpreadsheetPreviewData['onEmail']>(\n () => consumedRef.current?.data.onEmail,\n );\n\n // Only respond to update events whose token matches our claim.\n useEffect(() => {\n const myToken = consumedRef.current?.token;\n if (myToken == null) return;\n const handler = (e: Event) => {\n const detail = (e as CustomEvent<PendingSpreadsheetStage>).detail;\n if (!detail || detail.token !== myToken) return;\n const sheet = sheetFromCSV(detail.data.csv, 'Sheet 1');\n if (!sheet) return;\n setSheets([sheet]);\n setActiveIdx(0);\n setTitle(detail.data.filename.replace(/\\.(csv|tsv|txt)$/i, ''));\n setEmailHandler(() => detail.data.onEmail);\n };\n window.addEventListener(SPREADSHEET_EVENT_NAME, handler);\n return () => window.removeEventListener(SPREADSHEET_EVENT_NAME, handler);\n }, []);\n const [editingTitle, setEditingTitle] = useState(false);\n const [editingTab, setEditingTab] = useState<number | null>(null);\n const [tabName, setTabName] = useState('');\n const fileRef = useRef<HTMLInputElement>(null);\n const [addColCount, setAddColCount] = useState('1');\n const [addRowCount, setAddRowCount] = useState('10');\n\n const active = sheets[activeIdx] || sheets[0];\n const data = active.data;\n const columns = active.columns;\n const cellStyles = active.cellStyles ?? {};\n const [focusedCell, setFocusedCell] = useState<{ row: number; col: number } | null>(null);\n const [selection, setSelection] = useState<{ anchor: { row: number; col: number }; end: { row: number; col: number } } | null>(null);\n\n // Cells affected by toolbar actions: full selection rectangle if non-empty,\n // otherwise the single focused cell.\n const targetCells = useCallback((): { row: number; col: number }[] => {\n if (selection) {\n const r1 = Math.min(selection.anchor.row, selection.end.row);\n const r2 = Math.max(selection.anchor.row, selection.end.row);\n const c1 = Math.min(selection.anchor.col, selection.end.col);\n const c2 = Math.max(selection.anchor.col, selection.end.col);\n const cells: { row: number; col: number }[] = [];\n for (let r = r1; r <= r2; r++) for (let c = c1; c <= c2; c++) cells.push({ row: r, col: c });\n return cells;\n }\n return focusedCell ? [focusedCell] : [];\n }, [selection, focusedCell]);\n\n const toggleCellStyle = useCallback((key: keyof CellStyle, value?: any) => {\n const cells = targetCells();\n if (cells.length === 0) return;\n setSheets(prev => prev.map((s, i) => {\n if (i !== activeIdx) return s;\n const styles = { ...(s.cellStyles ?? {}) };\n // For toggles, derive the new state from the FIRST cell so the whole\n // selection ends up consistent (rather than each cell flipping\n // independently).\n const firstKey = `${cells[0].row}:${cells[0].col}`;\n const desired = value !== undefined ? value : !((styles[firstKey] ?? {})[key] as any);\n for (const { row, col } of cells) {\n const k = `${row}:${col}`;\n styles[k] = { ...(styles[k] ?? {}), [key]: desired };\n }\n return { ...s, cellStyles: styles };\n }));\n }, [targetCells, activeIdx]);\n\n const headCell = selection ? { row: selection.anchor.row, col: selection.anchor.col } : focusedCell;\n const focusedStyle: CellStyle = headCell ? (cellStyles[`${headCell.row}:${headCell.col}`] ?? {}) : {};\n const hasTarget = !!headCell;\n\n const updateActiveSheet = useCallback((update: Partial<Sheet>) => {\n setSheets(prev => prev.map((s, i) => i === activeIdx ? { ...s, ...update } : s));\n }, [activeIdx]);\n\n const handleChange = useCallback((newData: string[][]) => {\n // Sync column count if rows were inserted/deleted with different column counts\n const maxCols = newData.reduce((m, r) => Math.max(m, r.length), 0);\n if (maxCols !== columns.length) {\n updateActiveSheet({ data: newData, columns: makeColumns(maxCols) });\n } else {\n updateActiveSheet({ data: newData });\n }\n }, [updateActiveSheet, columns.length]);\n\n // Tab management\n const addSheet = () => {\n const name = `Sheet ${sheets.length + 1}`;\n setSheets(prev => [...prev, newSheet(name)]);\n setActiveIdx(sheets.length);\n };\n\n const removeSheet = (idx: number) => {\n if (sheets.length <= 1) return;\n setSheets(prev => prev.filter((_, i) => i !== idx));\n if (activeIdx >= idx && activeIdx > 0) setActiveIdx(activeIdx - 1);\n };\n\n const renameSheet = (idx: number, name: string) => {\n setSheets(prev => prev.map((s, i) => i === idx ? { ...s, name } : s));\n setEditingTab(null);\n };\n\n // Add columns to active sheet\n const addColumns = (count: number) => {\n const newColCount = columns.length + count;\n updateActiveSheet({\n columns: makeColumns(newColCount),\n data: data.map(row => [...row, ...Array(count).fill('')]),\n });\n };\n\n // Add rows to active sheet\n const addRows = (count: number) => {\n updateActiveSheet({\n data: [...data, ...Array.from({ length: count }, () => Array(columns.length).fill(''))],\n });\n };\n\n // Clear active sheet\n const handleClear = () => {\n updateActiveSheet({\n columns: makeColumns(DEFAULT_COLS),\n data: makeEmptyData(DEFAULT_ROWS, DEFAULT_COLS),\n });\n };\n\n // Serialize the active sheet (current edits included) as CSV\n const serializeCSV = () => data\n .filter(row => row.some(c => c.trim()))\n .map(row => row.map(cell => {\n if (cell.includes(',') || cell.includes('\"') || cell.includes('\\n'))\n return `\"${cell.replace(/\"/g, '\"\"')}\"`;\n return cell;\n }).join(','))\n .join('\\n');\n\n // Export as CSV\n const exportCSV = () => {\n const blob = new Blob([serializeCSV()], { type: 'text/csv' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `${title || 'spreadsheet'}.csv`;\n a.click();\n URL.revokeObjectURL(url);\n };\n\n // Import CSV / XLSX\n const importFile = async (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const name = file.name.replace(/\\.(csv|tsv|txt|xlsx|xls|ods)$/i, '');\n\n if (/\\.(xlsx|xls|ods)$/i.test(file.name)) {\n // XLSX — dynamic import\n const byteArr = new Uint8Array(await file.arrayBuffer());\n const XLSX = await import('xlsx');\n const wb = XLSX.read(byteArr, { type: 'array' });\n const newSheets: Sheet[] = wb.SheetNames.map(sn => {\n const rows: string[][] = XLSX.utils.sheet_to_json(wb.Sheets[sn], { header: 1, defval: '' });\n const maxCols = Math.max(DEFAULT_COLS, rows.reduce((m, r) => Math.max(m, r.length), 0));\n const padded = rows.map(r => { const nr = r.map(c => String(c ?? '')); while (nr.length < maxCols) nr.push(''); return nr; });\n while (padded.length < DEFAULT_ROWS) padded.push(Array(maxCols).fill(''));\n return { id: crypto.randomUUID(), name: sn, columns: makeColumns(maxCols), data: padded };\n });\n setSheets(newSheets);\n setActiveIdx(0);\n setTitle(name);\n } else {\n // CSV/TSV\n const text = await file.text();\n const parsed = parseCSV(text);\n if (parsed.length === 0) return;\n const maxCols = Math.max(DEFAULT_COLS, parsed.reduce((m, r) => Math.max(m, r.length), 0));\n const padded = parsed.map(r => { while (r.length < maxCols) r.push(''); return r; });\n while (padded.length < DEFAULT_ROWS) padded.push(Array(maxCols).fill(''));\n updateActiveSheet({ columns: makeColumns(maxCols), data: padded });\n setTitle(name);\n }\n\n if (fileRef.current) fileRef.current.value = '';\n };\n\n // Stats\n const allNums: number[] = [];\n data.forEach(row => row.forEach(cell => {\n const v = parseFloat(cell);\n if (!isNaN(v) && cell.trim()) allNums.push(v);\n }));\n const filledCount = data.reduce((c, row) => c + row.filter(cell => cell.trim()).length, 0);\n\n return (\n <div ref={containerRef} className=\"flex flex-col h-full\">\n <WindowTitle title={`${truncateForTitle(title || 'Untitled')} - Spreadsheets`} />\n <AboutApp app=\"spreadsheet\" />\n {/* Toolbar */}\n <div className=\"flex items-center gap-2 px-3 py-2 border-b border-gray-200 bg-gray-50 shrink-0\">\n {editingTitle ? (\n <input type=\"text\" value={title} onChange={e => setTitle(e.target.value)}\n onBlur={() => setEditingTitle(false)}\n onKeyDown={e => { if (e.key === 'Enter') setEditingTitle(false); }}\n autoFocus\n className=\"text-sm font-medium text-gray-900 border border-gray-300 rounded px-2 py-0.5 w-40 focus:border-blue-500 focus:ring-blue-500\" />\n ) : (\n <button onClick={() => setEditingTitle(true)} className=\"text-sm font-medium text-gray-900 hover:text-blue-600 truncate max-w-[200px]\" title=\"Click to rename\">\n {title || 'Untitled'}\n </button>\n )}\n\n <div className=\"h-4 w-px bg-gray-300\" />\n\n <input ref={fileRef} type=\"file\" accept=\".csv,.tsv,.txt,.xlsx,.xls,.ods\" onChange={importFile} className=\"hidden\" />\n <button onClick={() => fileRef.current?.click()}\n className=\"text-xs text-gray-600 hover:text-gray-900 px-2 py-1 rounded hover:bg-gray-200 transition-colors\">\n Open\n </button>\n <button onClick={exportCSV}\n className=\"text-xs text-gray-600 hover:text-gray-900 px-2 py-1 rounded hover:bg-gray-200 transition-colors\">\n Save CSV\n </button>\n {emailHandler && (\n <button onClick={() => emailHandler(serializeCSV(), `${title || 'spreadsheet'}.csv`)}\n className=\"text-xs text-gray-600 hover:text-gray-900 px-2 py-1 rounded hover:bg-gray-200 transition-colors\">\n Email\n </button>\n )}\n\n <div className=\"h-4 w-px bg-gray-300\" />\n\n <div className=\"flex items-center gap-1\">\n <input type=\"number\" min=\"1\" max=\"50\" value={addColCount} onChange={e => setAddColCount(e.target.value)}\n className=\"w-10 text-xs text-center border border-gray-300 rounded px-1 py-0.5 focus:border-blue-500 focus:ring-blue-500\" />\n <button onClick={() => addColumns(parseInt(addColCount) || 1)}\n className=\"text-xs text-gray-600 hover:text-gray-900 px-2 py-1 rounded hover:bg-gray-200 transition-colors\">\n + Col\n </button>\n </div>\n <div className=\"flex items-center gap-1\">\n <input type=\"number\" min=\"1\" max=\"500\" value={addRowCount} onChange={e => setAddRowCount(e.target.value)}\n className=\"w-10 text-xs text-center border border-gray-300 rounded px-1 py-0.5 focus:border-blue-500 focus:ring-blue-500\" />\n <button onClick={() => addRows(parseInt(addRowCount) || 10)}\n className=\"text-xs text-gray-600 hover:text-gray-900 px-2 py-1 rounded hover:bg-gray-200 transition-colors\">\n + Row\n </button>\n </div>\n\n <div className=\"h-4 w-px bg-gray-300\" />\n\n <button onClick={handleClear}\n className=\"text-xs text-gray-600 hover:text-gray-900 px-2 py-1 rounded hover:bg-gray-200 transition-colors\">\n Clear\n </button>\n\n <div className=\"h-4 w-px bg-gray-300\" />\n\n {/* Font style panel — applies to the focused cell. */}\n <div className=\"flex items-center gap-0.5\" title={hasTarget ? '' : 'Click a cell first'}>\n <button onClick={() => toggleCellStyle('bold')} disabled={!hasTarget}\n className={`px-2 py-1 text-xs rounded transition-colors font-bold ${focusedStyle.bold ? 'bg-blue-100 text-blue-700' : 'text-gray-600 hover:bg-gray-200'} disabled:opacity-40 disabled:cursor-not-allowed`}>\n B\n </button>\n <button onClick={() => toggleCellStyle('italic')} disabled={!hasTarget}\n className={`px-2 py-1 text-xs rounded transition-colors italic ${focusedStyle.italic ? 'bg-blue-100 text-blue-700' : 'text-gray-600 hover:bg-gray-200'} disabled:opacity-40 disabled:cursor-not-allowed`}>\n I\n </button>\n <button onClick={() => toggleCellStyle('underline')} disabled={!hasTarget}\n className={`px-2 py-1 text-xs rounded transition-colors underline ${focusedStyle.underline ? 'bg-blue-100 text-blue-700' : 'text-gray-600 hover:bg-gray-200'} disabled:opacity-40 disabled:cursor-not-allowed`}>\n U\n </button>\n <select\n value={focusedStyle.fontSize ?? 'base'}\n onChange={e => toggleCellStyle('fontSize', e.target.value)}\n disabled={!hasTarget}\n className=\"ml-1 text-xs border border-gray-300 rounded px-1 py-0.5 bg-white disabled:opacity-40 disabled:cursor-not-allowed\">\n <option value=\"sm\">XS</option>\n <option value=\"base\">S</option>\n <option value=\"lg\">M</option>\n <option value=\"xl\">L</option>\n </select>\n </div>\n </div>\n\n {/* Grid */}\n <div className=\"flex-1 min-h-0\">\n <EditableGrid\n columns={columns}\n data={data}\n onChange={handleChange}\n onColumnsChange={(newCols) => updateActiveSheet({ columns: newCols })}\n cellStyles={cellStyles}\n onFocusChange={setFocusedCell}\n onSelectionChange={setSelection}\n minRows={DEFAULT_ROWS}\n maxHeight=\"100%\"\n />\n </div>\n\n {/* Sheet tabs + status bar */}\n <div className=\"flex items-center border-t border-gray-200 bg-gray-50 shrink-0\">\n <div className=\"flex items-center gap-0.5 px-1 py-1 overflow-x-auto flex-1 min-w-0\">\n {sheets.map((sheet, idx) => (\n <button key={sheet.id}\n onClick={() => setActiveIdx(idx)}\n onDoubleClick={() => { setEditingTab(idx); setTabName(sheet.name); }}\n onContextMenu={e => { e.preventDefault(); if (sheets.length > 1) removeSheet(idx); }}\n className={`px-3 py-1 text-xs font-medium rounded-b whitespace-nowrap transition-colors ${\n idx === activeIdx\n ? 'bg-white text-blue-700 border border-t-0 border-gray-300 -mt-px relative z-10'\n : 'text-gray-500 hover:text-gray-700 hover:bg-gray-100'\n }`}>\n {editingTab === idx ? (\n <input type=\"text\" value={tabName} onChange={e => setTabName(e.target.value)}\n onBlur={() => renameSheet(idx, tabName || sheet.name)}\n onKeyDown={e => { if (e.key === 'Enter') renameSheet(idx, tabName || sheet.name); if (e.key === 'Escape') setEditingTab(null); }}\n onClick={e => e.stopPropagation()}\n autoFocus\n className=\"w-20 text-xs border border-blue-400 rounded px-1 py-0 focus:ring-0 focus:outline-none\" />\n ) : sheet.name}\n </button>\n ))}\n <button onClick={addSheet} className=\"px-2 py-1 text-xs text-gray-400 hover:text-gray-600 hover:bg-gray-100 rounded\" title=\"Add sheet\">+</button>\n </div>\n\n <div className=\"flex items-center gap-4 px-3 py-1 text-xs text-gray-500 shrink-0 border-l border-gray-200\">\n <span>{filledCount} cells</span>\n {allNums.length > 0 && (\n <>\n <span>Sum: {allNums.reduce((s, v) => s + v, 0).toLocaleString(undefined, { maximumFractionDigits: 2 })}</span>\n <span>Avg: {(allNums.reduce((s, v) => s + v, 0) / allNums.length).toLocaleString(undefined, { maximumFractionDigits: 2 })}</span>\n </>\n )}\n <span>{data.length} × {columns.length}</span>\n </div>\n </div>\n </div>\n );\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { AboutApp } from './chunk-DLOIO7UD.js';
1
2
  import { WindowTitle } from './chunk-GWVVILYQ.js';
2
3
  import { confirm } from './chunk-UBN4IUDE.js';
3
4
  import { useRef, useEffect, useState } from 'react';
@@ -187,6 +188,7 @@ function Browser() {
187
188
  const btn = "p-1.5 rounded hover:bg-gray-200 transition-colors text-gray-600 disabled:opacity-30";
188
189
  return /* @__PURE__ */ jsxs("div", { className: "relative flex flex-col h-full bg-white", children: [
189
190
  /* @__PURE__ */ jsx(WindowTitle, { title: `Browser - ${titleFromUrl(url)}` }),
191
+ /* @__PURE__ */ jsx(AboutApp, { app: "browser" }),
190
192
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5 border-b border-gray-200 bg-gray-50 shrink-0", children: [
191
193
  /* @__PURE__ */ jsx("button", { onClick: back, disabled: !canBack, className: btn, title: "Back", children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.75 19.5L8.25 12l7.5-7.5" }) }) }),
192
194
  /* @__PURE__ */ jsx("button", { onClick: forward, disabled: !canForward, className: btn, title: "Forward", children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" }) }) }),
@@ -433,5 +435,5 @@ function BrowserBody({
433
435
  }
434
436
 
435
437
  export { Browser, setBrowserStartUrl };
436
- //# sourceMappingURL=chunk-DKC2VDOI.js.map
437
- //# sourceMappingURL=chunk-DKC2VDOI.js.map
438
+ //# sourceMappingURL=chunk-T4USMWTS.js.map
439
+ //# sourceMappingURL=chunk-T4USMWTS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/apps/Browser.tsx"],"names":[],"mappings":"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","file":"chunk-T4USMWTS.js","sourcesContent":["/**\n * Browser — minimal iframe-backed web browser app.\n *\n * URL bar with back / forward / refresh, navigable bookmark bar\n * (persisted to localStorage), and a graceful \"open in new tab\"\n * escape hatch since most major sites refuse iframe embedding via\n * X-Frame-Options or Content-Security-Policy.\n */\nimport { useEffect, useRef, useState } from 'react';\nimport { WindowTitle } from '../shell/Modal';\nimport { confirm } from '../shell/ConfirmDialog';\nimport AboutApp from './_about';\n\ninterface Bookmark {\n label: string;\n url: string;\n}\n\nconst BOOKMARKS_KEY = 'react-os-shell:browser-bookmarks';\nconst HOMEPAGE_KEY = 'react-os-shell:browser-homepage';\nconst DEFAULT_HOMEPAGE = 'https://en.wikipedia.org/wiki/Main_Page';\nconst DEFAULT_BOOKMARKS: Bookmark[] = [\n { label: 'Wikipedia', url: 'https://en.wikipedia.org/wiki/Main_Page' },\n { label: 'MDN', url: 'https://developer.mozilla.org' },\n { label: 'Example', url: 'https://example.com' },\n];\n\nfunction normalizeUrl(input: string): string {\n let s = input.trim();\n if (!s) return '';\n // Already a URL? Otherwise treat as a search query (DuckDuckGo, no tracking).\n if (/^[a-z][a-z0-9+.-]*:\\/\\//i.test(s)) return s;\n if (/^[\\w.-]+\\.[a-z]{2,}(\\/.*)?$/i.test(s)) return 'https://' + s;\n return 'https://duckduckgo.com/?q=' + encodeURIComponent(s);\n}\n\n// Sites known to refuse iframe embedding via X-Frame-Options or CSP. There's\n// no workaround inside an iframe — the browser blocks the load. We keep a\n// list so we can short-circuit to a friendly \"open in new tab\" panel\n// instead of letting the browser's blank \"refused to connect\" error\n// through. Subdomain match: `mail.google.com` matches `google.com`.\nconst BLOCKED_HOSTS = [\n 'google.com', 'gmail.com', 'youtube.com',\n 'facebook.com', 'instagram.com', 'whatsapp.com',\n 'twitter.com', 'x.com',\n 'github.com', 'gitlab.com',\n 'linkedin.com', 'reddit.com', 'pinterest.com',\n 'amazon.com', 'amazon.ca', 'amazon.co.uk',\n 'apple.com', 'icloud.com',\n 'microsoft.com', 'outlook.com', 'live.com', 'office.com',\n 'netflix.com', 'spotify.com',\n 'paypal.com', 'stripe.com',\n 'chat.openai.com', 'chatgpt.com', 'claude.ai',\n];\n\nfunction hostIsBlocked(href: string): boolean {\n try {\n const host = new URL(href).hostname.toLowerCase();\n return BLOCKED_HOSTS.some(b => host === b || host.endsWith('.' + b));\n } catch { return false; }\n}\n\nfunction loadBookmarks(): Bookmark[] {\n if (typeof window === 'undefined') return DEFAULT_BOOKMARKS;\n try {\n const raw = localStorage.getItem(BOOKMARKS_KEY);\n if (!raw) return DEFAULT_BOOKMARKS;\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed) && parsed.every(b => typeof b?.url === 'string')) return parsed;\n } catch {}\n return DEFAULT_BOOKMARKS;\n}\n\ninterface PendingStartUrl {\n token: number;\n url: string;\n}\n\nlet pendingStartUrl: PendingStartUrl | null = null;\nlet nextStartToken = 0;\n\n/** Stage a URL for the next Browser window mount — pair with\n * `openPage('/browser')`. Used by \"open this link in the Browser\" flows\n * (e.g. links inside an email body). */\nexport function setBrowserStartUrl(url: string): void {\n pendingStartUrl = { token: ++nextStartToken, url };\n}\n\nfunction loadHomepage(): string {\n if (typeof window === 'undefined') return DEFAULT_HOMEPAGE;\n return localStorage.getItem(HOMEPAGE_KEY) || DEFAULT_HOMEPAGE;\n}\n\nexport default function Browser() {\n // One-shot drain of a staged start URL. The render phase only PEEKS — under\n // React 18 concurrent rendering the first render pass of this lazy component\n // can be discarded and replayed, so a destructive read here would lose the\n // payload (see Spreadsheet/Preview). The stage is cleared in the mount\n // effect below.\n const consumedRef = useRef<PendingStartUrl | null | undefined>(undefined);\n if (consumedRef.current === undefined) {\n consumedRef.current = pendingStartUrl;\n }\n useEffect(() => {\n if (consumedRef.current !== null && pendingStartUrl === consumedRef.current) {\n pendingStartUrl = null;\n }\n }, []);\n const startUrl = consumedRef.current ? normalizeUrl(consumedRef.current.url) : '';\n\n const [homepage, setHomepage] = useState(loadHomepage);\n const [url, setUrl] = useState(startUrl || homepage);\n const [inputUrl, setInputUrl] = useState(url);\n const [history, setHistory] = useState<string[]>([url]);\n const [historyIdx, setHistoryIdx] = useState(0);\n const [iframeKey, setIframeKey] = useState(0);\n const [bookmarks, setBookmarks] = useState<Bookmark[]>(loadBookmarks);\n const [showHelp, setShowHelp] = useState(false);\n // Inline \"name this bookmark\" popover state. Populated when the user\n // clicks the star icon to add — replaces the native window.prompt().\n const [bookmarkDraft, setBookmarkDraft] = useState<string | null>(null);\n const bookmarkInputRef = useRef<HTMLInputElement>(null);\n const iframeRef = useRef<HTMLIFrameElement>(null);\n\n // Persist bookmarks.\n useEffect(() => {\n try { localStorage.setItem(BOOKMARKS_KEY, JSON.stringify(bookmarks)); } catch {}\n }, [bookmarks]);\n\n const navigate = (next: string) => {\n const n = normalizeUrl(next);\n if (!n) return;\n setUrl(n);\n setInputUrl(n);\n // Truncate forward history when navigating from a back state.\n setHistory(h => {\n const trimmed = h.slice(0, historyIdx + 1);\n trimmed.push(n);\n return trimmed;\n });\n setHistoryIdx(i => i + 1);\n setShowHelp(false);\n };\n\n const back = () => {\n if (historyIdx > 0) {\n const next = historyIdx - 1;\n setHistoryIdx(next);\n setUrl(history[next]);\n setInputUrl(history[next]);\n setShowHelp(false);\n }\n };\n\n const forward = () => {\n if (historyIdx < history.length - 1) {\n const next = historyIdx + 1;\n setHistoryIdx(next);\n setUrl(history[next]);\n setInputUrl(history[next]);\n setShowHelp(false);\n }\n };\n\n const refresh = () => setIframeKey(k => k + 1);\n\n const goHome = () => navigate(homepage);\n\n const openExternal = () => {\n if (typeof window !== 'undefined') window.open(url, '_blank', 'noopener,noreferrer');\n };\n\n const openBookmarkPopover = () => {\n setBookmarkDraft(titleFromUrl(url));\n // Focus + select happens in a useEffect once the input is mounted.\n };\n\n const commitBookmark = () => {\n const label = bookmarkDraft?.trim();\n if (!label) { setBookmarkDraft(null); return; }\n setBookmarks(b => [...b, { label, url }]);\n setBookmarkDraft(null);\n };\n\n // Auto-focus + select the popover input when it opens, and dismiss on\n // outside click.\n useEffect(() => {\n if (bookmarkDraft === null) return;\n bookmarkInputRef.current?.focus();\n bookmarkInputRef.current?.select();\n const onDocClick = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target?.closest('[data-bookmark-popover]')) setBookmarkDraft(null);\n };\n // Defer one tick so the click that opened the popover doesn't close it.\n const t = setTimeout(() => document.addEventListener('mousedown', onDocClick), 0);\n return () => {\n clearTimeout(t);\n document.removeEventListener('mousedown', onDocClick);\n };\n }, [bookmarkDraft !== null]);\n\n const removeBookmark = (i: number) => {\n setBookmarks(b => b.filter((_, idx) => idx !== i));\n };\n\n const setAsHomepage = () => {\n setHomepage(url);\n try { localStorage.setItem(HOMEPAGE_KEY, url); } catch {}\n };\n\n const onSubmitUrl = (e: React.FormEvent) => {\n e.preventDefault();\n navigate(inputUrl);\n };\n\n const canBack = historyIdx > 0;\n const canForward = historyIdx < history.length - 1;\n const isBookmarked = bookmarks.some(b => b.url === url);\n const btn = 'p-1.5 rounded hover:bg-gray-200 transition-colors text-gray-600 disabled:opacity-30';\n\n return (\n <div className=\"relative flex flex-col h-full bg-white\">\n <WindowTitle title={`Browser - ${titleFromUrl(url)}`} />\n <AboutApp app=\"browser\" />\n\n {/* Top toolbar */}\n <div className=\"flex items-center gap-1 px-2 py-1.5 border-b border-gray-200 bg-gray-50 shrink-0\">\n <button onClick={back} disabled={!canBack} className={btn} title=\"Back\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M15.75 19.5L8.25 12l7.5-7.5\" /></svg>\n </button>\n <button onClick={forward} disabled={!canForward} className={btn} title=\"Forward\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M8.25 4.5l7.5 7.5-7.5 7.5\" /></svg>\n </button>\n <button onClick={refresh} className={btn} title=\"Refresh\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.023 9.348h4.992V4.356M2.985 19.644v-4.992h4.992M3.05 9.348a9 9 0 0114.85-3.36L21.015 9.348m0 5.304a9 9 0 01-14.85 3.36l-3.115-3.36\" /></svg>\n </button>\n <button onClick={goHome} className={btn} title=\"Home\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M2.25 12l8.954-8.955a1.5 1.5 0 012.122 0l8.954 8.955M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25\" /></svg>\n </button>\n\n <form onSubmit={onSubmitUrl} className=\"flex-1 flex items-center mx-1\">\n <div className=\"flex items-center w-full bg-white border border-gray-300 rounded focus-within:border-blue-400 focus-within:ring-1 focus-within:ring-blue-200\">\n <span className=\"px-2 text-gray-400 text-xs\">{url.startsWith('https://') ? '🔒' : '⚠️'}</span>\n <input\n type=\"text\"\n value={inputUrl}\n onChange={(e) => setInputUrl(e.target.value)}\n onFocus={(e) => e.target.select()}\n className=\"flex-1 px-1 py-1 text-sm bg-transparent outline-none font-mono\"\n spellCheck={false}\n placeholder=\"Enter URL or search…\"\n />\n {url !== inputUrl && (\n <button\n type=\"button\"\n onClick={() => setInputUrl(url)}\n className=\"px-1.5 text-[10px] text-gray-400 hover:text-gray-700\"\n title=\"Reset to current URL\"\n >×</button>\n )}\n </div>\n </form>\n\n <button\n data-bookmark-popover\n onClick={() => isBookmarked\n ? removeBookmark(bookmarks.findIndex(b => b.url === url))\n : openBookmarkPopover()}\n className={btn + ' ' + (isBookmarked ? 'text-yellow-500' : '')}\n title={isBookmarked ? 'Remove bookmark' : 'Add bookmark'}\n >\n <svg className=\"h-4 w-4\" fill={isBookmarked ? 'currentColor' : 'none'} viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z\" />\n </svg>\n </button>\n <button onClick={openExternal} className={btn} title=\"Open in new tab\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-7.5-9L21 3m0 0v6m0-6L9.75 14.25\" /></svg>\n </button>\n <button onClick={() => setShowHelp(s => !s)} className={btn} title=\"Embedding help\">\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z\" /></svg>\n </button>\n </div>\n\n {/* Inline \"name this bookmark\" popover. Anchored to the right of the\n toolbar (where the star icon lives) so the visual flow matches\n how the user just clicked. Renders inside the panel so it\n inherits the window's z-stacking. */}\n {bookmarkDraft !== null && (\n <div\n data-bookmark-popover\n className=\"absolute right-3 top-12 z-30 w-72 bg-white border border-gray-200 rounded-md shadow-lg p-3\"\n >\n <div className=\"text-[11px] font-semibold uppercase tracking-wide text-gray-500 mb-1\">Bookmark this page</div>\n <div className=\"text-[11px] text-gray-400 truncate mb-2 font-mono\" title={url}>{url}</div>\n <input\n ref={bookmarkInputRef}\n type=\"text\"\n value={bookmarkDraft}\n onChange={(e) => setBookmarkDraft(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') commitBookmark();\n else if (e.key === 'Escape') setBookmarkDraft(null);\n }}\n placeholder=\"Name\"\n className=\"w-full text-sm px-2 py-1.5 border border-gray-300 rounded focus:outline-none focus:border-blue-400 focus:ring-1 focus:ring-blue-200\"\n />\n <div className=\"flex justify-end gap-1 mt-2\">\n <button\n onClick={() => setBookmarkDraft(null)}\n className=\"px-2 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded\"\n >Cancel</button>\n <button\n onClick={commitBookmark}\n disabled={!bookmarkDraft.trim()}\n className=\"px-2 py-1 text-xs bg-blue-500 text-white rounded hover:bg-blue-600 disabled:opacity-40\"\n >Save</button>\n </div>\n </div>\n )}\n\n {/* Bookmarks bar */}\n <div className=\"flex items-center gap-0.5 px-2 py-1 border-b border-gray-200 bg-white shrink-0 overflow-x-auto\">\n {bookmarks.length === 0 && (\n <span className=\"text-[11px] text-gray-400 italic px-2\">No bookmarks yet — star the address bar to add one.</span>\n )}\n {bookmarks.map((b, i) => (\n <button\n key={i}\n onClick={() => navigate(b.url)}\n onContextMenu={async (e) => {\n e.preventDefault();\n const ok = await confirm({\n title: 'Remove bookmark',\n message: `\"${b.label}\" will be removed from your bookmarks.`,\n confirmLabel: 'Remove',\n variant: 'danger',\n });\n if (ok) removeBookmark(i);\n }}\n className=\"flex items-center gap-1.5 px-2 py-0.5 rounded text-[12px] text-gray-700 hover:bg-gray-100 whitespace-nowrap\"\n title={`${b.url}\\n(right-click to remove)`}\n >\n <img\n src={`https://icons.duckduckgo.com/ip3/${new URL(b.url).hostname}.ico`}\n alt=\"\"\n className=\"h-3.5 w-3.5\"\n onError={(e) => { (e.target as HTMLImageElement).style.visibility = 'hidden'; }}\n />\n {b.label}\n </button>\n ))}\n <div className=\"flex-1\" />\n <button\n onClick={setAsHomepage}\n className=\"px-2 py-0.5 text-[11px] text-gray-500 hover:text-gray-800\"\n title=\"Set current page as homepage\"\n >Set as home</button>\n </div>\n\n {/* Iframe area */}\n <div className=\"flex-1 relative min-h-0 bg-gray-50\">\n <BrowserBody\n url={url}\n iframeKey={iframeKey}\n iframeRef={iframeRef}\n openExternal={openExternal}\n showHelp={showHelp}\n dismissHelp={() => setShowHelp(false)}\n />\n </div>\n </div>\n );\n}\n\nfunction titleFromUrl(u: string): string {\n try {\n const url = new URL(u);\n return url.hostname.replace(/^www\\./, '');\n } catch {\n return u;\n }\n}\n\nfunction BrowserBody({\n url,\n iframeKey,\n iframeRef,\n openExternal,\n showHelp,\n dismissHelp,\n}: {\n url: string;\n iframeKey: number;\n iframeRef: React.RefObject<HTMLIFrameElement | null>;\n openExternal: () => void;\n showHelp: boolean;\n dismissHelp: () => void;\n}) {\n // If the user dismisses the blocked-site panel, allow them to attempt\n // the iframe load anyway. Reset the override whenever URL changes.\n const [forceTry, setForceTry] = useState(false);\n useEffect(() => { setForceTry(false); }, [url]);\n\n const blocked = hostIsBlocked(url) && !forceTry;\n\n if (blocked) {\n return (\n <div className=\"absolute inset-0 flex items-center justify-center bg-white p-8\">\n <div className=\"max-w-md text-center\">\n <svg className=\"h-14 w-14 mx-auto text-gray-300 mb-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M18.364 18.364A9 9 0 005.636 5.636m12.728 12.728L5.636 5.636m12.728 12.728L21 21M5.636 5.636L3 3m9 9a9 9 0 110-18 9 9 0 010 18z\" />\n </svg>\n <h3 className=\"text-base font-semibold text-gray-800 mb-1\">\n {titleFromUrl(url)} can't be embedded\n </h3>\n <p className=\"text-sm text-gray-500 mb-4\">\n This site sends an <span className=\"font-mono text-xs\">X-Frame-Options</span>{' '}\n or <span className=\"font-mono text-xs\">Content-Security-Policy</span> header\n that refuses iframe embedding. The browser blocks the load before our app\n can do anything about it.\n </p>\n <div className=\"flex flex-col items-center gap-2\">\n <button\n onClick={openExternal}\n className=\"px-4 py-2 bg-blue-500 text-white text-sm rounded hover:bg-blue-600 inline-flex items-center gap-2\"\n >\n <svg className=\"h-4 w-4\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-7.5-9L21 3m0 0v6m0-6L9.75 14.25\" />\n </svg>\n Open in a new tab\n </button>\n <button\n onClick={() => setForceTry(true)}\n className=\"text-xs text-gray-500 hover:text-gray-800 underline\"\n >\n Try loading it here anyway\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <>\n <iframe\n key={iframeKey + url}\n ref={iframeRef as React.RefObject<HTMLIFrameElement>}\n src={url}\n className=\"absolute inset-0 w-full h-full bg-white\"\n // Sandboxing keeps embedded pages from messing with the parent\n // window state. allow-same-origin lets sites that *do* allow\n // embedding actually behave normally; allow-scripts is needed\n // for any modern site.\n sandbox=\"allow-scripts allow-forms allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-modals\"\n referrerPolicy=\"no-referrer-when-downgrade\"\n />\n\n {showHelp && (\n <div className=\"absolute top-2 right-2 max-w-sm bg-white border border-gray-200 rounded-md shadow-lg p-3 text-xs text-gray-700 z-10\">\n <div className=\"font-medium text-gray-900 mb-1\">Why is this page blank?</div>\n <p className=\"mb-2\">\n Most major sites (Google, GitHub, banks, news) refuse to be embedded in\n an iframe via <span className=\"font-mono\">X-Frame-Options</span> or\n Content Security Policy. There's no workaround — the browser blocks the\n load before our app can do anything.\n </p>\n <p>\n Hit the <span className=\"font-medium\">↗</span> button to open the page in\n a real new tab. Sites that <em>do</em> allow embedding (Wikipedia, MDN,\n docs sites, your own apps) work fine in here.\n </p>\n <button\n onClick={dismissHelp}\n className=\"mt-2 text-[11px] text-blue-600 hover:underline\"\n >Got it</button>\n </div>\n )}\n </>\n );\n}\n"]}