react-os-shell 0.13.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Browser-W63A4RUT.js → Browser-M5Y3ENA7.js} +3 -3
- package/dist/{Browser-W63A4RUT.js.map → Browser-M5Y3ENA7.js.map} +1 -1
- package/dist/{Calculator-Z2DAZD6K.js → Calculator-DJYKVGOK.js} +4 -4
- package/dist/{Calculator-Z2DAZD6K.js.map → Calculator-DJYKVGOK.js.map} +1 -1
- package/dist/{CurrencyConverter-S6RQB3OJ.js → CurrencyConverter-ZJWZCO5U.js} +4 -4
- package/dist/{CurrencyConverter-S6RQB3OJ.js.map → CurrencyConverter-ZJWZCO5U.js.map} +1 -1
- package/dist/{Documents-VE5Z7DRX.js → Documents-2S4QPAI3.js} +3 -3
- package/dist/{Documents-VE5Z7DRX.js.map → Documents-2S4QPAI3.js.map} +1 -1
- package/dist/Files-V4SZKOGZ.js +12 -0
- package/dist/{Files-5IXGRZKM.js.map → Files-V4SZKOGZ.js.map} +1 -1
- package/dist/{Minesweeper-WVAFWKCZ.js → Minesweeper-YNXOWMIP.js} +3 -3
- package/dist/{Minesweeper-WVAFWKCZ.js.map → Minesweeper-YNXOWMIP.js.map} +1 -1
- package/dist/{Notepad-OLNPHKTT.js → Notepad-6JJ4RT3U.js} +111 -102
- package/dist/Notepad-6JJ4RT3U.js.map +1 -0
- package/dist/{PomodoroTimer-ZJYDPFCT.js → PomodoroTimer-HGPJ5R6V.js} +5 -6
- package/dist/PomodoroTimer-HGPJ5R6V.js.map +1 -0
- package/dist/Preview-KUAQIPBY.js +8 -0
- package/dist/{Preview-LTZOUTQ7.js.map → Preview-KUAQIPBY.js.map} +1 -1
- package/dist/Spreadsheet-TVP3SXT6.js +6 -0
- package/dist/{Spreadsheet-VT3ZISIN.js.map → Spreadsheet-TVP3SXT6.js.map} +1 -1
- package/dist/Stock-XLC3LZJV.js +152 -0
- package/dist/Stock-XLC3LZJV.js.map +1 -0
- package/dist/{Weather-NJHYEKH3.js → Weather-WH3URRSL.js} +4 -4
- package/dist/{Weather-NJHYEKH3.js.map → Weather-WH3URRSL.js.map} +1 -1
- package/dist/{WorldClock-UJKD253K.js → WorldClock-LJRWPGJW.js} +4 -4
- package/dist/{WorldClock-UJKD253K.js.map → WorldClock-LJRWPGJW.js.map} +1 -1
- package/dist/apps/index.d.ts +16 -4
- package/dist/apps/index.js +22 -23
- package/dist/apps/index.js.map +1 -1
- package/dist/chunk-4R4SXMDV.js +98 -0
- package/dist/chunk-4R4SXMDV.js.map +1 -0
- package/dist/{chunk-IMFUTSYY.js → chunk-4RXDOSKZ.js} +22 -5
- package/dist/chunk-4RXDOSKZ.js.map +1 -0
- package/dist/{chunk-MK3HLUO4.js → chunk-5X5LQNOX.js} +172 -3
- package/dist/chunk-5X5LQNOX.js.map +1 -0
- package/dist/{chunk-66GIT3PM.js → chunk-6DDVFASF.js} +3 -3
- package/dist/{chunk-66GIT3PM.js.map → chunk-6DDVFASF.js.map} +1 -1
- package/dist/{chunk-BS7EHYBT.js → chunk-7TG7VNJS.js} +3 -3
- package/dist/{chunk-BS7EHYBT.js.map → chunk-7TG7VNJS.js.map} +1 -1
- package/dist/{chunk-DMSHU2HJ.js → chunk-K354WXU5.js} +3 -3
- package/dist/{chunk-DMSHU2HJ.js.map → chunk-K354WXU5.js.map} +1 -1
- package/dist/chunk-UXEG2NRI.js +682 -0
- package/dist/chunk-UXEG2NRI.js.map +1 -0
- package/dist/chunk-VGTEM5RZ.js +89 -0
- package/dist/chunk-VGTEM5RZ.js.map +1 -0
- package/dist/index.d.ts +69 -2
- package/dist/index.js +305 -346
- package/dist/index.js.map +1 -1
- package/dist/styles.css +26 -2
- package/package.json +1 -1
- package/dist/Files-5IXGRZKM.js +0 -11
- package/dist/Notepad-OLNPHKTT.js.map +0 -1
- package/dist/PomodoroTimer-ZJYDPFCT.js.map +0 -1
- package/dist/Preview-LTZOUTQ7.js +0 -8
- package/dist/Spreadsheet-VT3ZISIN.js +0 -6
- package/dist/Stock-DWESS6UC.js +0 -234
- package/dist/Stock-DWESS6UC.js.map +0 -1
- package/dist/TodoList-26N6ZTLN.js +0 -309
- package/dist/TodoList-26N6ZTLN.js.map +0 -1
- package/dist/chunk-3SIZAHR6.js +0 -46
- package/dist/chunk-3SIZAHR6.js.map +0 -1
- package/dist/chunk-EFNKEBDB.js +0 -605
- package/dist/chunk-EFNKEBDB.js.map +0 -1
- package/dist/chunk-IMFUTSYY.js.map +0 -1
- package/dist/chunk-MK3HLUO4.js.map +0 -1
- package/dist/chunk-QTJ2CHJX.js +0 -174
- package/dist/chunk-QTJ2CHJX.js.map +0 -1
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
import { useTodoTasks } from './chunk-QTJ2CHJX.js';
|
|
2
|
-
import './chunk-36VM54SC.js';
|
|
3
|
-
import { confirm } from './chunk-UBN4IUDE.js';
|
|
4
|
-
import { useState, useMemo } from 'react';
|
|
5
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
-
|
|
7
|
-
var FILTERS = [
|
|
8
|
-
{ id: "today", label: "Today" },
|
|
9
|
-
{ id: "upcoming", label: "Upcoming" },
|
|
10
|
-
{ id: "all", label: "All" },
|
|
11
|
-
{ id: "done", label: "Done" }
|
|
12
|
-
];
|
|
13
|
-
function todayStr() {
|
|
14
|
-
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
15
|
-
}
|
|
16
|
-
function fmtDueLabel(due) {
|
|
17
|
-
const d = /* @__PURE__ */ new Date(due + "T00:00:00");
|
|
18
|
-
const today = /* @__PURE__ */ new Date();
|
|
19
|
-
today.setHours(0, 0, 0, 0);
|
|
20
|
-
const diffDays = Math.round((d.getTime() - today.getTime()) / (24 * 3600 * 1e3));
|
|
21
|
-
if (diffDays === 0) return "Today";
|
|
22
|
-
if (diffDays === 1) return "Tomorrow";
|
|
23
|
-
if (diffDays === -1) return "Yesterday";
|
|
24
|
-
if (diffDays > 0 && diffDays < 7) return d.toLocaleDateString(void 0, { weekday: "short" });
|
|
25
|
-
return d.toLocaleDateString(void 0, { month: "short", day: "numeric" });
|
|
26
|
-
}
|
|
27
|
-
function isOverdue(t) {
|
|
28
|
-
return !t.done && !!t.dueDate && t.dueDate < todayStr();
|
|
29
|
-
}
|
|
30
|
-
function TodoList() {
|
|
31
|
-
const { tasks, addTask, updateTask, removeTask, toggleDone } = useTodoTasks();
|
|
32
|
-
const [filter, setFilter] = useState("today");
|
|
33
|
-
const [editingId, setEditingId] = useState(null);
|
|
34
|
-
const [adding, setAdding] = useState(false);
|
|
35
|
-
const today = todayStr();
|
|
36
|
-
const visible = useMemo(() => {
|
|
37
|
-
const sorted = [...tasks].sort((a, b) => {
|
|
38
|
-
if (a.done !== b.done) return a.done ? 1 : -1;
|
|
39
|
-
const aOver = isOverdue(a), bOver = isOverdue(b);
|
|
40
|
-
if (aOver !== bOver) return aOver ? -1 : 1;
|
|
41
|
-
if (a.dueDate && b.dueDate && a.dueDate !== b.dueDate) return a.dueDate < b.dueDate ? -1 : 1;
|
|
42
|
-
if (!!a.dueDate !== !!b.dueDate) return a.dueDate ? -1 : 1;
|
|
43
|
-
return a.createdAt.localeCompare(b.createdAt);
|
|
44
|
-
});
|
|
45
|
-
if (filter === "today") return sorted.filter((t) => !t.done && (t.dueDate === today || isOverdue(t)));
|
|
46
|
-
if (filter === "upcoming") return sorted.filter((t) => !t.done && t.dueDate && t.dueDate > today);
|
|
47
|
-
if (filter === "done") return sorted.filter((t) => t.done);
|
|
48
|
-
return sorted;
|
|
49
|
-
}, [tasks, filter, today]);
|
|
50
|
-
const counts = useMemo(() => ({
|
|
51
|
-
today: tasks.filter((t) => !t.done && (t.dueDate === today || isOverdue(t))).length,
|
|
52
|
-
upcoming: tasks.filter((t) => !t.done && t.dueDate && t.dueDate > today).length,
|
|
53
|
-
all: tasks.filter((t) => !t.done).length,
|
|
54
|
-
done: tasks.filter((t) => t.done).length
|
|
55
|
-
}), [tasks, today]);
|
|
56
|
-
const handleAdd = (input) => {
|
|
57
|
-
addTask(input);
|
|
58
|
-
setAdding(false);
|
|
59
|
-
};
|
|
60
|
-
const handleToggle = (id) => {
|
|
61
|
-
toggleDone(id);
|
|
62
|
-
};
|
|
63
|
-
const handleEdit = (id, patch) => {
|
|
64
|
-
updateTask(id, patch);
|
|
65
|
-
};
|
|
66
|
-
const handleDelete = async (id) => {
|
|
67
|
-
const t = tasks.find((x) => x.id === id);
|
|
68
|
-
if (!t) return;
|
|
69
|
-
const ok = await confirm({
|
|
70
|
-
title: "Delete this task?",
|
|
71
|
-
message: `\u201C${t.name}\u201D will be removed from the Todo List and the Pomodoro widget. This can't be undone.`,
|
|
72
|
-
confirmLabel: "Delete",
|
|
73
|
-
variant: "danger"
|
|
74
|
-
});
|
|
75
|
-
if (!ok) return;
|
|
76
|
-
removeTask(id);
|
|
77
|
-
setEditingId(null);
|
|
78
|
-
};
|
|
79
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-full", children: [
|
|
80
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3 px-4 py-2 border-b border-gray-200 shrink-0", children: [
|
|
81
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: FILTERS.map((f) => {
|
|
82
|
-
const count = counts[f.id];
|
|
83
|
-
const active = filter === f.id;
|
|
84
|
-
return /* @__PURE__ */ jsxs(
|
|
85
|
-
"button",
|
|
86
|
-
{
|
|
87
|
-
onClick: () => setFilter(f.id),
|
|
88
|
-
className: `px-2.5 py-1 text-xs font-medium rounded-md transition-colors flex items-center gap-1.5 ${active ? "bg-blue-600 text-white" : "text-gray-600 hover:bg-gray-100"}`,
|
|
89
|
-
children: [
|
|
90
|
-
/* @__PURE__ */ jsx("span", { children: f.label }),
|
|
91
|
-
/* @__PURE__ */ jsx("span", { className: `text-[10px] tabular-nums ${active ? "text-white/80" : "text-gray-400"}`, children: count })
|
|
92
|
-
]
|
|
93
|
-
},
|
|
94
|
-
f.id
|
|
95
|
-
);
|
|
96
|
-
}) }),
|
|
97
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: /* @__PURE__ */ jsxs(
|
|
98
|
-
"button",
|
|
99
|
-
{
|
|
100
|
-
onClick: () => setAdding((a) => !a),
|
|
101
|
-
className: "flex items-center gap-1 px-2.5 py-1 text-xs font-medium rounded-md bg-blue-600 text-white hover:bg-blue-700",
|
|
102
|
-
children: [
|
|
103
|
-
/* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M12 5v14M5 12h14" }) }),
|
|
104
|
-
/* @__PURE__ */ jsx("span", { children: "Add" })
|
|
105
|
-
]
|
|
106
|
-
}
|
|
107
|
-
) })
|
|
108
|
-
] }),
|
|
109
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
110
|
-
adding && /* @__PURE__ */ jsx(AddTaskRow, { onSubmit: handleAdd, onCancel: () => setAdding(false) }),
|
|
111
|
-
visible.length === 0 && !adding && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-full text-center px-6 text-gray-400", children: [
|
|
112
|
-
/* @__PURE__ */ jsxs("svg", { className: "h-10 w-10 mb-2 text-gray-300", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, children: [
|
|
113
|
-
/* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2" }),
|
|
114
|
-
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 12l2 2 4-4" })
|
|
115
|
-
] }),
|
|
116
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm", children: filter === "done" ? "No completed tasks yet." : "Nothing here. Add a task to get started." })
|
|
117
|
-
] }),
|
|
118
|
-
visible.map((task) => /* @__PURE__ */ jsx(
|
|
119
|
-
TaskRow,
|
|
120
|
-
{
|
|
121
|
-
task,
|
|
122
|
-
editing: editingId === task.id,
|
|
123
|
-
onToggle: () => handleToggle(task.id),
|
|
124
|
-
onClick: () => setEditingId(editingId === task.id ? null : task.id),
|
|
125
|
-
onSave: (patch) => {
|
|
126
|
-
handleEdit(task.id, patch);
|
|
127
|
-
setEditingId(null);
|
|
128
|
-
},
|
|
129
|
-
onDelete: () => handleDelete(task.id),
|
|
130
|
-
onCancelEdit: () => setEditingId(null)
|
|
131
|
-
},
|
|
132
|
-
task.id
|
|
133
|
-
))
|
|
134
|
-
] })
|
|
135
|
-
] });
|
|
136
|
-
}
|
|
137
|
-
function TaskRow({ task, editing, onToggle, onClick, onSave, onDelete, onCancelEdit }) {
|
|
138
|
-
if (editing) {
|
|
139
|
-
return /* @__PURE__ */ jsx(EditDrawer, { task, onSave, onCancel: onCancelEdit, onDelete });
|
|
140
|
-
}
|
|
141
|
-
const dueLabel = task.dueDate ? fmtDueLabel(task.dueDate) : null;
|
|
142
|
-
const overdue = isOverdue(task);
|
|
143
|
-
const pomos = task.estimated || task.completed ? `${task.completed ?? 0}/${task.estimated ?? "?"}` : null;
|
|
144
|
-
return /* @__PURE__ */ jsxs(
|
|
145
|
-
"div",
|
|
146
|
-
{
|
|
147
|
-
onClick,
|
|
148
|
-
className: "flex items-center gap-3 px-4 py-2.5 border-b border-gray-200 cursor-pointer hover:bg-gray-50 transition-colors",
|
|
149
|
-
children: [
|
|
150
|
-
/* @__PURE__ */ jsx(
|
|
151
|
-
"button",
|
|
152
|
-
{
|
|
153
|
-
onClick: (e) => {
|
|
154
|
-
e.stopPropagation();
|
|
155
|
-
onToggle();
|
|
156
|
-
},
|
|
157
|
-
className: "shrink-0",
|
|
158
|
-
children: task.done ? /* @__PURE__ */ jsx("svg", { className: "h-5 w-5 text-blue-600", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx("path", { d: "M10 0a10 10 0 100 20 10 10 0 000-20zm-1 14.5l-4.5-4.5 1.4-1.4 3.1 3.1 6.1-6.1 1.4 1.4z" }) }) : /* @__PURE__ */ jsx("svg", { className: "h-5 w-5 text-gray-300 hover:text-gray-500", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }) })
|
|
159
|
-
}
|
|
160
|
-
),
|
|
161
|
-
/* @__PURE__ */ jsx("span", { className: `flex-1 text-sm truncate ${task.done ? "line-through text-gray-400" : "text-gray-800"}`, children: task.name || /* @__PURE__ */ jsx("span", { className: "italic text-gray-400", children: "(untitled)" }) }),
|
|
162
|
-
pomos && /* @__PURE__ */ jsxs("span", { className: "shrink-0 text-[11px] tabular-nums text-gray-500", title: "Pomodoros completed / estimated", children: [
|
|
163
|
-
"\u{1F345} ",
|
|
164
|
-
pomos
|
|
165
|
-
] }),
|
|
166
|
-
task.contextLabel && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[11px] font-medium px-1.5 py-0.5 rounded bg-purple-100 text-purple-700", title: task.contextLabel, children: task.contextLabel }),
|
|
167
|
-
dueLabel && /* @__PURE__ */ jsx("span", { className: `shrink-0 text-[11px] font-medium px-1.5 py-0.5 rounded ${overdue ? "bg-red-100 text-red-700" : task.dueDate === todayStr() ? "bg-blue-100 text-blue-700" : "bg-gray-100 text-gray-600"}`, children: dueLabel })
|
|
168
|
-
]
|
|
169
|
-
}
|
|
170
|
-
);
|
|
171
|
-
}
|
|
172
|
-
function EditDrawer({ task, onSave, onCancel, onDelete }) {
|
|
173
|
-
const [name, setName] = useState(task.name);
|
|
174
|
-
const [dueDate, setDueDate] = useState(task.dueDate || "");
|
|
175
|
-
const [estimated, setEstimated] = useState(task.estimated ?? 0);
|
|
176
|
-
const [notes, setNotes] = useState(task.notes || "");
|
|
177
|
-
const submit = () => onSave({
|
|
178
|
-
name: name.trim(),
|
|
179
|
-
dueDate: dueDate || void 0,
|
|
180
|
-
estimated: estimated > 0 ? estimated : void 0,
|
|
181
|
-
notes: notes.trim() || void 0
|
|
182
|
-
});
|
|
183
|
-
return /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-b border-gray-200 bg-gray-50", children: [
|
|
184
|
-
/* @__PURE__ */ jsx(
|
|
185
|
-
"input",
|
|
186
|
-
{
|
|
187
|
-
autoFocus: true,
|
|
188
|
-
value: name,
|
|
189
|
-
onChange: (e) => setName(e.target.value),
|
|
190
|
-
onKeyDown: (e) => {
|
|
191
|
-
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) submit();
|
|
192
|
-
if (e.key === "Escape") onCancel();
|
|
193
|
-
},
|
|
194
|
-
placeholder: "Task name",
|
|
195
|
-
className: "w-full text-sm font-medium bg-white border border-gray-200 rounded px-2 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
196
|
-
}
|
|
197
|
-
),
|
|
198
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2 mt-2", children: [
|
|
199
|
-
/* @__PURE__ */ jsxs("label", { className: "flex flex-col text-[10px] font-semibold text-gray-500 uppercase tracking-wide", children: [
|
|
200
|
-
"Due",
|
|
201
|
-
/* @__PURE__ */ jsx(
|
|
202
|
-
"input",
|
|
203
|
-
{
|
|
204
|
-
type: "date",
|
|
205
|
-
value: dueDate,
|
|
206
|
-
onChange: (e) => setDueDate(e.target.value),
|
|
207
|
-
className: "mt-0.5 text-sm bg-white border border-gray-200 rounded px-2 py-1 text-gray-800 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
208
|
-
}
|
|
209
|
-
)
|
|
210
|
-
] }),
|
|
211
|
-
/* @__PURE__ */ jsxs("label", { className: "flex flex-col text-[10px] font-semibold text-gray-500 uppercase tracking-wide", children: [
|
|
212
|
-
"Est. pomos",
|
|
213
|
-
/* @__PURE__ */ jsx(
|
|
214
|
-
"input",
|
|
215
|
-
{
|
|
216
|
-
type: "number",
|
|
217
|
-
min: 0,
|
|
218
|
-
max: 20,
|
|
219
|
-
value: estimated,
|
|
220
|
-
onChange: (e) => setEstimated(Math.max(0, Math.min(20, parseInt(e.target.value, 10) || 0))),
|
|
221
|
-
className: "mt-0.5 text-sm bg-white border border-gray-200 rounded px-2 py-1 text-gray-800 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
222
|
-
}
|
|
223
|
-
)
|
|
224
|
-
] })
|
|
225
|
-
] }),
|
|
226
|
-
/* @__PURE__ */ jsx(
|
|
227
|
-
"textarea",
|
|
228
|
-
{
|
|
229
|
-
value: notes,
|
|
230
|
-
onChange: (e) => setNotes(e.target.value),
|
|
231
|
-
placeholder: "Notes (optional)",
|
|
232
|
-
rows: 2,
|
|
233
|
-
className: "mt-2 w-full text-xs bg-white border border-gray-200 rounded px-2 py-1.5 text-gray-700 focus:outline-none focus:ring-1 focus:ring-blue-500 resize-none"
|
|
234
|
-
}
|
|
235
|
-
),
|
|
236
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mt-2", children: [
|
|
237
|
-
/* @__PURE__ */ jsx("button", { onClick: onDelete, className: "text-xs text-red-600 hover:text-red-700", children: "Delete" }),
|
|
238
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
239
|
-
/* @__PURE__ */ jsx("button", { onClick: onCancel, className: "px-3 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded", children: "Cancel" }),
|
|
240
|
-
/* @__PURE__ */ jsx("button", { onClick: submit, className: "px-3 py-1 text-xs font-semibold bg-blue-600 text-white rounded hover:bg-blue-700", children: "Save" })
|
|
241
|
-
] })
|
|
242
|
-
] })
|
|
243
|
-
] });
|
|
244
|
-
}
|
|
245
|
-
function AddTaskRow({ onSubmit, onCancel }) {
|
|
246
|
-
const [name, setName] = useState("");
|
|
247
|
-
const [dueDate, setDueDate] = useState("");
|
|
248
|
-
const [estimated, setEstimated] = useState(0);
|
|
249
|
-
const submit = () => {
|
|
250
|
-
const trimmed = name.trim();
|
|
251
|
-
if (!trimmed) return;
|
|
252
|
-
onSubmit({
|
|
253
|
-
name: trimmed,
|
|
254
|
-
dueDate: dueDate || void 0,
|
|
255
|
-
estimated: estimated > 0 ? estimated : void 0
|
|
256
|
-
});
|
|
257
|
-
};
|
|
258
|
-
return /* @__PURE__ */ jsxs("div", { className: "px-4 py-3 border-b border-gray-200 bg-blue-50/40", children: [
|
|
259
|
-
/* @__PURE__ */ jsx(
|
|
260
|
-
"input",
|
|
261
|
-
{
|
|
262
|
-
autoFocus: true,
|
|
263
|
-
value: name,
|
|
264
|
-
onChange: (e) => setName(e.target.value),
|
|
265
|
-
onKeyDown: (e) => {
|
|
266
|
-
if (e.key === "Enter") submit();
|
|
267
|
-
if (e.key === "Escape") onCancel();
|
|
268
|
-
},
|
|
269
|
-
placeholder: "What do you need to do?",
|
|
270
|
-
className: "w-full text-sm font-medium bg-white border border-gray-200 rounded px-2 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
271
|
-
}
|
|
272
|
-
),
|
|
273
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-2", children: [
|
|
274
|
-
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1.5 text-[10px] font-semibold text-gray-500 uppercase tracking-wide", children: [
|
|
275
|
-
"Due",
|
|
276
|
-
/* @__PURE__ */ jsx(
|
|
277
|
-
"input",
|
|
278
|
-
{
|
|
279
|
-
type: "date",
|
|
280
|
-
value: dueDate,
|
|
281
|
-
onChange: (e) => setDueDate(e.target.value),
|
|
282
|
-
className: "text-xs bg-white border border-gray-200 rounded px-1.5 py-0.5 text-gray-800 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
283
|
-
}
|
|
284
|
-
)
|
|
285
|
-
] }),
|
|
286
|
-
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-1.5 text-[10px] font-semibold text-gray-500 uppercase tracking-wide", children: [
|
|
287
|
-
"Est. pomos",
|
|
288
|
-
/* @__PURE__ */ jsx(
|
|
289
|
-
"input",
|
|
290
|
-
{
|
|
291
|
-
type: "number",
|
|
292
|
-
min: 0,
|
|
293
|
-
max: 20,
|
|
294
|
-
value: estimated,
|
|
295
|
-
onChange: (e) => setEstimated(Math.max(0, Math.min(20, parseInt(e.target.value, 10) || 0))),
|
|
296
|
-
className: "w-12 text-xs bg-white border border-gray-200 rounded px-1.5 py-0.5 text-right text-gray-800 focus:outline-none focus:ring-1 focus:ring-blue-500"
|
|
297
|
-
}
|
|
298
|
-
)
|
|
299
|
-
] }),
|
|
300
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
301
|
-
/* @__PURE__ */ jsx("button", { onClick: onCancel, className: "px-3 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded", children: "Cancel" }),
|
|
302
|
-
/* @__PURE__ */ jsx("button", { onClick: submit, className: "px-3 py-1 text-xs font-semibold bg-blue-600 text-white rounded hover:bg-blue-700", children: "Add" })
|
|
303
|
-
] })
|
|
304
|
-
] });
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
export { TodoList as default };
|
|
308
|
-
//# sourceMappingURL=TodoList-26N6ZTLN.js.map
|
|
309
|
-
//# sourceMappingURL=TodoList-26N6ZTLN.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/apps/TodoList.tsx"],"names":[],"mappings":"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","file":"TodoList-26N6ZTLN.js","sourcesContent":["import { useMemo, useState } from 'react';\nimport { useTodoTasks } from './_todoStore';\nimport type { TodoTask } from './_todoTypes';\nimport { confirm } from '../shell/ConfirmDialog';\n\ntype Filter = 'today' | 'upcoming' | 'all' | 'done';\n\nconst FILTERS: { id: Filter; label: string }[] = [\n { id: 'today', label: 'Today' },\n { id: 'upcoming', label: 'Upcoming' },\n { id: 'all', label: 'All' },\n { id: 'done', label: 'Done' },\n];\n\nfunction todayStr(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\nfunction fmtDueLabel(due: string): string {\n const d = new Date(due + 'T00:00:00');\n const today = new Date(); today.setHours(0, 0, 0, 0);\n const diffDays = Math.round((d.getTime() - today.getTime()) / (24 * 3600 * 1000));\n if (diffDays === 0) return 'Today';\n if (diffDays === 1) return 'Tomorrow';\n if (diffDays === -1) return 'Yesterday';\n if (diffDays > 0 && diffDays < 7) return d.toLocaleDateString(undefined, { weekday: 'short' });\n return d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' });\n}\n\nfunction isOverdue(t: TodoTask): boolean {\n return !t.done && !!t.dueDate && t.dueDate < todayStr();\n}\n\nexport default function TodoList() {\n const { tasks, addTask, updateTask, removeTask, toggleDone } = useTodoTasks();\n const [filter, setFilter] = useState<Filter>('today');\n const [editingId, setEditingId] = useState<string | null>(null);\n const [adding, setAdding] = useState(false);\n\n // ── Filtered view ──\n const today = todayStr();\n const visible = useMemo(() => {\n const sorted = [...tasks].sort((a, b) => {\n // Done tasks always sink to the bottom.\n if (a.done !== b.done) return a.done ? 1 : -1;\n // Overdue first, then today, then by due date, then by createdAt.\n const aOver = isOverdue(a), bOver = isOverdue(b);\n if (aOver !== bOver) return aOver ? -1 : 1;\n if (a.dueDate && b.dueDate && a.dueDate !== b.dueDate) return a.dueDate < b.dueDate ? -1 : 1;\n if (!!a.dueDate !== !!b.dueDate) return a.dueDate ? -1 : 1;\n return a.createdAt.localeCompare(b.createdAt);\n });\n if (filter === 'today') return sorted.filter(t => !t.done && (t.dueDate === today || isOverdue(t)));\n if (filter === 'upcoming') return sorted.filter(t => !t.done && t.dueDate && t.dueDate > today);\n if (filter === 'done') return sorted.filter(t => t.done);\n return sorted;\n }, [tasks, filter, today]);\n\n const counts = useMemo(() => ({\n today: tasks.filter(t => !t.done && (t.dueDate === today || isOverdue(t))).length,\n upcoming: tasks.filter(t => !t.done && t.dueDate && t.dueDate > today).length,\n all: tasks.filter(t => !t.done).length,\n done: tasks.filter(t => t.done).length,\n }), [tasks, today]);\n\n // ── Action handlers ──\n const handleAdd = (input: { name: string; dueDate?: string; estimated?: number }) => {\n addTask(input);\n setAdding(false);\n };\n\n const handleToggle = (id: string) => {\n toggleDone(id);\n };\n\n const handleEdit = (id: string, patch: Partial<TodoTask>) => {\n updateTask(id, patch);\n };\n\n const handleDelete = async (id: string) => {\n const t = tasks.find(x => x.id === id);\n if (!t) return;\n const ok = await confirm({\n title: 'Delete this task?',\n message: `“${t.name}” will be removed from the Todo List and the Pomodoro widget. This can't be undone.`,\n confirmLabel: 'Delete',\n variant: 'danger',\n });\n if (!ok) return;\n removeTask(id);\n setEditingId(null);\n };\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Header — filter pills + sync chip + add button */}\n <div className=\"flex items-center justify-between gap-3 px-4 py-2 border-b border-gray-200 shrink-0\">\n <div className=\"flex items-center gap-1\">\n {FILTERS.map(f => {\n const count = counts[f.id];\n const active = filter === f.id;\n return (\n <button key={f.id} onClick={() => setFilter(f.id)}\n className={`px-2.5 py-1 text-xs font-medium rounded-md transition-colors flex items-center gap-1.5 ${active ? 'bg-blue-600 text-white' : 'text-gray-600 hover:bg-gray-100'}`}>\n <span>{f.label}</span>\n <span className={`text-[10px] tabular-nums ${active ? 'text-white/80' : 'text-gray-400'}`}>{count}</span>\n </button>\n );\n })}\n </div>\n <div className=\"flex items-center gap-2\">\n <button onClick={() => setAdding(a => !a)}\n className=\"flex items-center gap-1 px-2.5 py-1 text-xs font-medium rounded-md bg-blue-600 text-white hover:bg-blue-700\">\n <svg className=\"h-3.5 w-3.5\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2.5}>\n <path strokeLinecap=\"round\" d=\"M12 5v14M5 12h14\" />\n </svg>\n <span>Add</span>\n </button>\n </div>\n </div>\n\n {/* List */}\n <div className=\"flex-1 overflow-y-auto\">\n {adding && (\n <AddTaskRow onSubmit={handleAdd} onCancel={() => setAdding(false)} />\n )}\n {visible.length === 0 && !adding && (\n <div className=\"flex flex-col items-center justify-center h-full text-center px-6 text-gray-400\">\n <svg className=\"h-10 w-10 mb-2 text-gray-300\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5}>\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"2\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M9 12l2 2 4-4\" />\n </svg>\n <p className=\"text-sm\">{filter === 'done' ? 'No completed tasks yet.' : 'Nothing here. Add a task to get started.'}</p>\n </div>\n )}\n {visible.map(task => (\n <TaskRow\n key={task.id}\n task={task}\n editing={editingId === task.id}\n onToggle={() => handleToggle(task.id)}\n onClick={() => setEditingId(editingId === task.id ? null : task.id)}\n onSave={(patch) => { handleEdit(task.id, patch); setEditingId(null); }}\n onDelete={() => handleDelete(task.id)}\n onCancelEdit={() => setEditingId(null)}\n />\n ))}\n </div>\n </div>\n );\n}\n\n// ─────────────────────────────────────────────────────────────────────\n// Row + add form\n// ─────────────────────────────────────────────────────────────────────\n\nfunction TaskRow({ task, editing, onToggle, onClick, onSave, onDelete, onCancelEdit }: {\n task: TodoTask;\n editing: boolean;\n onToggle: () => void;\n onClick: () => void;\n onSave: (patch: Partial<TodoTask>) => void;\n onDelete: () => void;\n onCancelEdit: () => void;\n}) {\n if (editing) {\n return <EditDrawer task={task} onSave={onSave} onCancel={onCancelEdit} onDelete={onDelete} />;\n }\n const dueLabel = task.dueDate ? fmtDueLabel(task.dueDate) : null;\n const overdue = isOverdue(task);\n const pomos = (task.estimated || task.completed)\n ? `${task.completed ?? 0}/${task.estimated ?? '?'}`\n : null;\n return (\n <div\n onClick={onClick}\n className=\"flex items-center gap-3 px-4 py-2.5 border-b border-gray-200 cursor-pointer hover:bg-gray-50 transition-colors\">\n <button onClick={(e) => { e.stopPropagation(); onToggle(); }}\n className=\"shrink-0\">\n {task.done ? (\n <svg className=\"h-5 w-5 text-blue-600\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path d=\"M10 0a10 10 0 100 20 10 10 0 000-20zm-1 14.5l-4.5-4.5 1.4-1.4 3.1 3.1 6.1-6.1 1.4 1.4z\" />\n </svg>\n ) : (\n <svg className=\"h-5 w-5 text-gray-300 hover:text-gray-500\" fill=\"none\" stroke=\"currentColor\" strokeWidth={2} viewBox=\"0 0 24 24\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n </svg>\n )}\n </button>\n <span className={`flex-1 text-sm truncate ${task.done ? 'line-through text-gray-400' : 'text-gray-800'}`}>\n {task.name || <span className=\"italic text-gray-400\">(untitled)</span>}\n </span>\n {pomos && (\n <span className=\"shrink-0 text-[11px] tabular-nums text-gray-500\" title=\"Pomodoros completed / estimated\">\n 🍅 {pomos}\n </span>\n )}\n {task.contextLabel && (\n <span className=\"shrink-0 text-[11px] font-medium px-1.5 py-0.5 rounded bg-purple-100 text-purple-700\" title={task.contextLabel}>\n {task.contextLabel}\n </span>\n )}\n {dueLabel && (\n <span className={`shrink-0 text-[11px] font-medium px-1.5 py-0.5 rounded ${overdue ? 'bg-red-100 text-red-700' : task.dueDate === todayStr() ? 'bg-blue-100 text-blue-700' : 'bg-gray-100 text-gray-600'}`}>\n {dueLabel}\n </span>\n )}\n </div>\n );\n}\n\nfunction EditDrawer({ task, onSave, onCancel, onDelete }: {\n task: TodoTask;\n onSave: (patch: Partial<TodoTask>) => void;\n onCancel: () => void;\n onDelete: () => void;\n}) {\n const [name, setName] = useState(task.name);\n const [dueDate, setDueDate] = useState(task.dueDate || '');\n const [estimated, setEstimated] = useState(task.estimated ?? 0);\n const [notes, setNotes] = useState(task.notes || '');\n\n const submit = () => onSave({\n name: name.trim(),\n dueDate: dueDate || undefined,\n estimated: estimated > 0 ? estimated : undefined,\n notes: notes.trim() || undefined,\n });\n\n return (\n <div className=\"px-4 py-3 border-b border-gray-200 bg-gray-50\">\n <input autoFocus value={name} onChange={e => setName(e.target.value)}\n onKeyDown={e => { if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) submit(); if (e.key === 'Escape') onCancel(); }}\n placeholder=\"Task name\"\n className=\"w-full text-sm font-medium bg-white border border-gray-200 rounded px-2 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500\" />\n <div className=\"grid grid-cols-2 gap-2 mt-2\">\n <label className=\"flex flex-col text-[10px] font-semibold text-gray-500 uppercase tracking-wide\">\n Due\n <input type=\"date\" value={dueDate} onChange={e => setDueDate(e.target.value)}\n className=\"mt-0.5 text-sm bg-white border border-gray-200 rounded px-2 py-1 text-gray-800 focus:outline-none focus:ring-1 focus:ring-blue-500\" />\n </label>\n <label className=\"flex flex-col text-[10px] font-semibold text-gray-500 uppercase tracking-wide\">\n Est. pomos\n <input type=\"number\" min={0} max={20} value={estimated}\n onChange={e => setEstimated(Math.max(0, Math.min(20, parseInt(e.target.value, 10) || 0)))}\n className=\"mt-0.5 text-sm bg-white border border-gray-200 rounded px-2 py-1 text-gray-800 focus:outline-none focus:ring-1 focus:ring-blue-500\" />\n </label>\n </div>\n <textarea value={notes} onChange={e => setNotes(e.target.value)}\n placeholder=\"Notes (optional)\"\n rows={2}\n className=\"mt-2 w-full text-xs bg-white border border-gray-200 rounded px-2 py-1.5 text-gray-700 focus:outline-none focus:ring-1 focus:ring-blue-500 resize-none\" />\n <div className=\"flex items-center justify-between mt-2\">\n <button onClick={onDelete} className=\"text-xs text-red-600 hover:text-red-700\">\n Delete\n </button>\n <div className=\"flex gap-2\">\n <button onClick={onCancel} className=\"px-3 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded\">Cancel</button>\n <button onClick={submit} className=\"px-3 py-1 text-xs font-semibold bg-blue-600 text-white rounded hover:bg-blue-700\">Save</button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction AddTaskRow({ onSubmit, onCancel }: {\n onSubmit: (input: { name: string; dueDate?: string; estimated?: number }) => void;\n onCancel: () => void;\n}) {\n const [name, setName] = useState('');\n const [dueDate, setDueDate] = useState('');\n const [estimated, setEstimated] = useState(0);\n\n const submit = () => {\n const trimmed = name.trim();\n if (!trimmed) return;\n onSubmit({\n name: trimmed,\n dueDate: dueDate || undefined,\n estimated: estimated > 0 ? estimated : undefined,\n });\n };\n\n return (\n <div className=\"px-4 py-3 border-b border-gray-200 bg-blue-50/40\">\n <input autoFocus value={name} onChange={e => setName(e.target.value)}\n onKeyDown={e => { if (e.key === 'Enter') submit(); if (e.key === 'Escape') onCancel(); }}\n placeholder=\"What do you need to do?\"\n className=\"w-full text-sm font-medium bg-white border border-gray-200 rounded px-2 py-1.5 focus:outline-none focus:ring-1 focus:ring-blue-500\" />\n <div className=\"flex items-center gap-2 mt-2\">\n <label className=\"flex items-center gap-1.5 text-[10px] font-semibold text-gray-500 uppercase tracking-wide\">\n Due\n <input type=\"date\" value={dueDate} onChange={e => setDueDate(e.target.value)}\n className=\"text-xs bg-white border border-gray-200 rounded px-1.5 py-0.5 text-gray-800 focus:outline-none focus:ring-1 focus:ring-blue-500\" />\n </label>\n <label className=\"flex items-center gap-1.5 text-[10px] font-semibold text-gray-500 uppercase tracking-wide\">\n Est. pomos\n <input type=\"number\" min={0} max={20} value={estimated}\n onChange={e => setEstimated(Math.max(0, Math.min(20, parseInt(e.target.value, 10) || 0)))}\n className=\"w-12 text-xs bg-white border border-gray-200 rounded px-1.5 py-0.5 text-right text-gray-800 focus:outline-none focus:ring-1 focus:ring-blue-500\" />\n </label>\n <div className=\"flex-1\" />\n <button onClick={onCancel} className=\"px-3 py-1 text-xs text-gray-600 hover:bg-gray-100 rounded\">Cancel</button>\n <button onClick={submit} className=\"px-3 py-1 text-xs font-semibold bg-blue-600 text-white rounded hover:bg-blue-700\">Add</button>\n </div>\n </div>\n );\n}\n"]}
|
package/dist/chunk-3SIZAHR6.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import { setPdfPreview } from './chunk-DMSHU2HJ.js';
|
|
2
|
-
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
3
|
-
import { setSpreadsheetPreview } from './chunk-66GIT3PM.js';
|
|
4
|
-
|
|
5
|
-
// src/utils/openPreviewFile.ts
|
|
6
|
-
var PREVIEW_OPENED_EVENT = "react-os-shell:preview-opened";
|
|
7
|
-
function getServer() {
|
|
8
|
-
const override = typeof window !== "undefined" && window.__REACT_OS_SHELL_FILE_SERVER__;
|
|
9
|
-
return (override || "http://localhost:4000").replace(/\/$/, "");
|
|
10
|
-
}
|
|
11
|
-
async function openPreviewFile(opts) {
|
|
12
|
-
const { filePath, filename, kind, onStaged } = opts;
|
|
13
|
-
try {
|
|
14
|
-
const res = await fetch(
|
|
15
|
-
`${getServer()}/api/file?path=${encodeURIComponent(filePath)}`,
|
|
16
|
-
{ credentials: "include" }
|
|
17
|
-
);
|
|
18
|
-
if (!res.ok) {
|
|
19
|
-
toast_default.error(`Download failed (${res.status})`);
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
const blob = await res.blob();
|
|
23
|
-
if (kind === "csv") {
|
|
24
|
-
const text = await blob.text();
|
|
25
|
-
setSpreadsheetPreview({ csv: text, filename });
|
|
26
|
-
onStaged?.("/spreadsheet");
|
|
27
|
-
} else {
|
|
28
|
-
const url = URL.createObjectURL(blob);
|
|
29
|
-
setPdfPreview({ url, filename, kind });
|
|
30
|
-
onStaged?.("/preview");
|
|
31
|
-
}
|
|
32
|
-
if (typeof window !== "undefined") {
|
|
33
|
-
window.dispatchEvent(new CustomEvent(PREVIEW_OPENED_EVENT, {
|
|
34
|
-
detail: { filePath, filename, kind }
|
|
35
|
-
}));
|
|
36
|
-
}
|
|
37
|
-
return true;
|
|
38
|
-
} catch (e) {
|
|
39
|
-
toast_default.error(e?.message || "Open failed");
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export { PREVIEW_OPENED_EVENT, openPreviewFile };
|
|
45
|
-
//# sourceMappingURL=chunk-3SIZAHR6.js.map
|
|
46
|
-
//# sourceMappingURL=chunk-3SIZAHR6.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/openPreviewFile.ts"],"names":[],"mappings":";;;;;AA6BO,IAAM,oBAAA,GAAuB;AAQpC,SAAS,SAAA,GAAY;AACnB,EAAA,MAAM,QAAA,GAAY,OAAO,MAAA,KAAW,WAAA,IAAgB,MAAA,CAAe,8BAAA;AACnE,EAAA,OAAA,CAAQ,QAAA,IAAY,uBAAA,EAAyB,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAChE;AAEA,eAAsB,gBAAgB,IAAA,EAA6C;AACjF,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,IAAA,EAAM,UAAS,GAAI,IAAA;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,MAAM,KAAA;AAAA,MAChB,GAAG,SAAA,EAAW,CAAA,eAAA,EAAkB,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAA;AAAA,MAC5D,EAAE,aAAa,SAAA;AAAU,KAC3B;AACA,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,aAAA,CAAM,KAAA,CAAM,CAAA,iBAAA,EAAoB,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AAC7C,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAI,SAAS,KAAA,EAAO;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,MAAA,qBAAA,CAAsB,EAAE,GAAA,EAAK,IAAA,EAAM,QAAA,EAAU,CAAA;AAC7C,MAAA,QAAA,GAAW,cAAc,CAAA;AAAA,IAC3B,CAAA,MAAO;AACL,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACpC,MAAA,aAAA,CAAc,EAAE,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,CAAA;AACrC,MAAA,QAAA,GAAW,UAAU,CAAA;AAAA,IACvB;AACA,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,WAAA,CAAiC,oBAAA,EAAsB;AAAA,QAC9E,MAAA,EAAQ,EAAE,QAAA,EAAU,QAAA,EAAU,IAAA;AAAK,OACpC,CAAC,CAAA;AAAA,IACJ;AACA,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,CAAA,EAAQ;AACf,IAAA,aAAA,CAAM,KAAA,CAAM,CAAA,EAAG,OAAA,IAAW,aAAa,CAAA;AACvC,IAAA,OAAO,KAAA;AAAA,EACT;AACF","file":"chunk-3SIZAHR6.js","sourcesContent":["/**\n * Fetch a file from the user's file-server and route it into the right\n * preview window. Shared by the Files app and the desktop Documents\n * folder's shortcut click-through.\n *\n * On success, dispatches `react-os-shell:preview-opened` so Desktop can\n * record the file as a shortcut without this util needing access to the\n * prefs adapter.\n */\nimport toast from '../shell/toast';\nimport { setPdfPreview } from '../apps/Preview';\nimport { setSpreadsheetPreview } from '../apps/Spreadsheet';\n\nexport type PreviewFileKind = 'pdf' | 'dxf' | '3d' | 'image' | 'csv';\n\nexport interface OpenPreviewFileOpts {\n /** Server-relative path, e.g. \"/reports/Q1.pdf\". */\n filePath: string;\n /** Display name (also used as the download filename). */\n filename: string;\n /** Which viewer to route into. CSV opens in Spreadsheet; the rest open in Preview. */\n kind: PreviewFileKind;\n /** Optional callback invoked after staging the preview, with the route to\n * open (e.g. '/preview' or '/spreadsheet'). The caller is responsible\n * for actually opening the page since the window manager hook is\n * React-scoped. */\n onStaged?: (route: '/preview' | '/spreadsheet') => void;\n}\n\nexport const PREVIEW_OPENED_EVENT = 'react-os-shell:preview-opened';\n\nexport interface PreviewOpenedDetail {\n filePath: string;\n filename: string;\n kind: PreviewFileKind;\n}\n\nfunction getServer() {\n const override = (typeof window !== 'undefined' && (window as any).__REACT_OS_SHELL_FILE_SERVER__) as string | undefined;\n return (override || 'http://localhost:4000').replace(/\\/$/, '');\n}\n\nexport async function openPreviewFile(opts: OpenPreviewFileOpts): Promise<boolean> {\n const { filePath, filename, kind, onStaged } = opts;\n try {\n const res = await fetch(\n `${getServer()}/api/file?path=${encodeURIComponent(filePath)}`,\n { credentials: 'include' },\n );\n if (!res.ok) {\n toast.error(`Download failed (${res.status})`);\n return false;\n }\n const blob = await res.blob();\n if (kind === 'csv') {\n const text = await blob.text();\n setSpreadsheetPreview({ csv: text, filename });\n onStaged?.('/spreadsheet');\n } else {\n const url = URL.createObjectURL(blob);\n setPdfPreview({ url, filename, kind });\n onStaged?.('/preview');\n }\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent<PreviewOpenedDetail>(PREVIEW_OPENED_EVENT, {\n detail: { filePath, filename, kind },\n }));\n }\n return true;\n } catch (e: any) {\n toast.error(e?.message || 'Open failed');\n return false;\n }\n}\n"]}
|