react-os-shell 0.2.43 → 0.2.44
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-5ZCLRIRU.js → Browser-LSJORULM.js} +3 -3
- package/dist/{Browser-5ZCLRIRU.js.map → Browser-LSJORULM.js.map} +1 -1
- package/dist/{Calculator-OHL2AZ52.js → Calculator-ZKEH53OV.js} +4 -4
- package/dist/{Calculator-OHL2AZ52.js.map → Calculator-ZKEH53OV.js.map} +1 -1
- package/dist/{Calendar-6AHL3UJY.js → Calendar-4UQDQ3NT.js} +3 -3
- package/dist/{Calendar-6AHL3UJY.js.map → Calendar-4UQDQ3NT.js.map} +1 -1
- package/dist/{CurrencyConverter-XZVZ7XOF.js → CurrencyConverter-TXBFDFG2.js} +56 -50
- package/dist/CurrencyConverter-TXBFDFG2.js.map +1 -0
- package/dist/{Documents-IPVZ47JX.js → Documents-CQVIIFZV.js} +3 -3
- package/dist/{Documents-IPVZ47JX.js.map → Documents-CQVIIFZV.js.map} +1 -1
- package/dist/{Email-Z7FDKAFD.js → Email-HRBZUWPY.js} +3 -3
- package/dist/{Email-Z7FDKAFD.js.map → Email-HRBZUWPY.js.map} +1 -1
- package/dist/Files-ITIKVHIE.js +8 -0
- package/dist/{Files-KEHRZ2UY.js.map → Files-ITIKVHIE.js.map} +1 -1
- package/dist/{Minesweeper-NGN4O6C4.js → Minesweeper-QGUPDVRS.js} +3 -3
- package/dist/{Minesweeper-NGN4O6C4.js.map → Minesweeper-QGUPDVRS.js.map} +1 -1
- package/dist/{Notepad-W3YYZ3GS.js → Notepad-74CQPZCV.js} +3 -3
- package/dist/{Notepad-W3YYZ3GS.js.map → Notepad-74CQPZCV.js.map} +1 -1
- package/dist/PomodoroTimer-PRP5CZ3S.js +627 -0
- package/dist/PomodoroTimer-PRP5CZ3S.js.map +1 -0
- package/dist/Preview-4MBQI66Q.js +7 -0
- package/dist/{Preview-4354N46U.js.map → Preview-4MBQI66Q.js.map} +1 -1
- package/dist/{Spreadsheet-FCFII6DW.js → Spreadsheet-MKXPPSKV.js} +3 -3
- package/dist/{Spreadsheet-FCFII6DW.js.map → Spreadsheet-MKXPPSKV.js.map} +1 -1
- package/dist/Weather-YXSCSPQT.js +424 -0
- package/dist/Weather-YXSCSPQT.js.map +1 -0
- package/dist/WorldClock-QO5PVJQQ.js +250 -0
- package/dist/WorldClock-QO5PVJQQ.js.map +1 -0
- package/dist/apps/index.d.ts +6 -10
- package/dist/apps/index.js +18 -18
- package/dist/apps/index.js.map +1 -1
- package/dist/chunk-7CCHEEYC.js +94 -0
- package/dist/chunk-7CCHEEYC.js.map +1 -0
- package/dist/{chunk-T2NQXP2J.js → chunk-7M3BBAHQ.js} +10 -4
- package/dist/chunk-7M3BBAHQ.js.map +1 -0
- package/dist/{chunk-IY7JJVHR.js → chunk-DUUANLLE.js} +3 -3
- package/dist/{chunk-IY7JJVHR.js.map → chunk-DUUANLLE.js.map} +1 -1
- package/dist/chunk-MK3HLUO4.js +380 -0
- package/dist/chunk-MK3HLUO4.js.map +1 -0
- package/dist/{chunk-2SRU4BYH.js → chunk-MTLVXT2C.js} +4 -4
- package/dist/{chunk-2SRU4BYH.js.map → chunk-MTLVXT2C.js.map} +1 -1
- package/dist/{chunk-TVOBLSSV.js → chunk-UK2AA3J6.js} +3 -3
- package/dist/{chunk-TVOBLSSV.js.map → chunk-UK2AA3J6.js.map} +1 -1
- package/dist/index.d.ts +16 -1
- package/dist/index.js +4089 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/CurrencyConverter-XZVZ7XOF.js.map +0 -1
- package/dist/Files-KEHRZ2UY.js +0 -8
- package/dist/PomodoroTimer-T2J5NDJR.js +0 -196
- package/dist/PomodoroTimer-T2J5NDJR.js.map +0 -1
- package/dist/Preview-4354N46U.js +0 -7
- package/dist/Weather-XTADR7Z3.js +0 -266
- package/dist/Weather-XTADR7Z3.js.map +0 -1
- package/dist/WorldClock-OFK2EA2H.js +0 -126
- package/dist/WorldClock-OFK2EA2H.js.map +0 -1
- package/dist/chunk-7KZWBIDL.js +0 -4144
- package/dist/chunk-7KZWBIDL.js.map +0 -1
- package/dist/chunk-T2NQXP2J.js.map +0 -1
|
@@ -0,0 +1,627 @@
|
|
|
1
|
+
import { subscribePomo, getPomoSnapshot, setPomoDurations, setPomoAlarm, setPomoAlarmConfig, setPomoBehaviour, setPomoFocusSound, pomoSwitchMode, pomoPause, pomoStart, ALARM_OPTIONS, playAlarm, FOCUS_SOUND_OPTIONS, previewFocusSound } from './chunk-MK3HLUO4.js';
|
|
2
|
+
import { useShellPrefs } from './chunk-36VM54SC.js';
|
|
3
|
+
import './chunk-WIJ45SYD.js';
|
|
4
|
+
import { loadAppearance, WidgetSettingsModal } from './chunk-UK2AA3J6.js';
|
|
5
|
+
import { useWidgetSettings } from './chunk-7M3BBAHQ.js';
|
|
6
|
+
import './chunk-PLGHQ7QW.js';
|
|
7
|
+
import { useSyncExternalStore, useEffect, useState, useRef, useCallback } from 'react';
|
|
8
|
+
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
var POMO_SETTINGS_KEY = "pomodoro_appearance";
|
|
11
|
+
var TASKS_KEY = "pomodoro_tasks";
|
|
12
|
+
var ACTIVE_TASK_KEY = "pomodoro_active_task_id";
|
|
13
|
+
var MODE_LABELS = { focus: "Pomodoro", short: "Short Break", long: "Long Break" };
|
|
14
|
+
var MODE_COLORS = {
|
|
15
|
+
focus: "#0f172a",
|
|
16
|
+
// unused for the panel; only for focus-mode accents
|
|
17
|
+
short: "#508a52",
|
|
18
|
+
// muted green
|
|
19
|
+
long: "#5b7898"
|
|
20
|
+
// slate blue
|
|
21
|
+
};
|
|
22
|
+
function hexToRgba(hex, alpha) {
|
|
23
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
24
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
25
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
26
|
+
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
|
27
|
+
}
|
|
28
|
+
var DEFAULT_PREFS = {
|
|
29
|
+
focusMinutes: 25,
|
|
30
|
+
shortBreakMinutes: 5,
|
|
31
|
+
longBreakMinutes: 15,
|
|
32
|
+
autoStartBreaks: false,
|
|
33
|
+
autoStartPomodoros: false,
|
|
34
|
+
longBreakInterval: 4,
|
|
35
|
+
autoCheckTasks: true,
|
|
36
|
+
checkToBottom: true,
|
|
37
|
+
alarmSound: "bell",
|
|
38
|
+
alarmVolume: 100,
|
|
39
|
+
alarmRepeat: 1,
|
|
40
|
+
focusSound: "none",
|
|
41
|
+
focusVolume: 50
|
|
42
|
+
};
|
|
43
|
+
var intInRange = (v, min, max, fallback) => typeof v === "number" && isFinite(v) ? Math.max(min, Math.min(max, Math.round(v))) : fallback;
|
|
44
|
+
function readPrefs(raw) {
|
|
45
|
+
const p = raw && typeof raw === "object" ? raw : {};
|
|
46
|
+
return {
|
|
47
|
+
focusMinutes: intInRange(p.focusMinutes, 1, 120, DEFAULT_PREFS.focusMinutes),
|
|
48
|
+
shortBreakMinutes: intInRange(p.shortBreakMinutes, 1, 120, DEFAULT_PREFS.shortBreakMinutes),
|
|
49
|
+
longBreakMinutes: intInRange(p.longBreakMinutes, 1, 120, DEFAULT_PREFS.longBreakMinutes),
|
|
50
|
+
autoStartBreaks: typeof p.autoStartBreaks === "boolean" ? p.autoStartBreaks : DEFAULT_PREFS.autoStartBreaks,
|
|
51
|
+
autoStartPomodoros: typeof p.autoStartPomodoros === "boolean" ? p.autoStartPomodoros : DEFAULT_PREFS.autoStartPomodoros,
|
|
52
|
+
longBreakInterval: intInRange(p.longBreakInterval, 1, 20, DEFAULT_PREFS.longBreakInterval),
|
|
53
|
+
autoCheckTasks: typeof p.autoCheckTasks === "boolean" ? p.autoCheckTasks : DEFAULT_PREFS.autoCheckTasks,
|
|
54
|
+
checkToBottom: typeof p.checkToBottom === "boolean" ? p.checkToBottom : DEFAULT_PREFS.checkToBottom,
|
|
55
|
+
alarmSound: ALARM_OPTIONS.some((o) => o.id === p.alarmSound) ? p.alarmSound : DEFAULT_PREFS.alarmSound,
|
|
56
|
+
alarmVolume: intInRange(p.alarmVolume, 0, 100, DEFAULT_PREFS.alarmVolume),
|
|
57
|
+
alarmRepeat: intInRange(p.alarmRepeat, 1, 5, DEFAULT_PREFS.alarmRepeat),
|
|
58
|
+
focusSound: FOCUS_SOUND_OPTIONS.some((o) => o.id === p.focusSound) ? p.focusSound : DEFAULT_PREFS.focusSound,
|
|
59
|
+
focusVolume: intInRange(p.focusVolume, 0, 100, DEFAULT_PREFS.focusVolume)
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function loadTasks() {
|
|
63
|
+
try {
|
|
64
|
+
const raw = JSON.parse(localStorage.getItem(TASKS_KEY) || "[]");
|
|
65
|
+
if (Array.isArray(raw)) return raw;
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
return [];
|
|
69
|
+
}
|
|
70
|
+
function uid() {
|
|
71
|
+
return Math.random().toString(36).slice(2, 9);
|
|
72
|
+
}
|
|
73
|
+
var sortDoneToBottom = (arr) => {
|
|
74
|
+
const undone = [];
|
|
75
|
+
const done = [];
|
|
76
|
+
for (const t of arr) (t.done ? done : undone).push(t);
|
|
77
|
+
return [...undone, ...done];
|
|
78
|
+
};
|
|
79
|
+
function PomodoroTimer() {
|
|
80
|
+
const snap = useSyncExternalStore(subscribePomo, getPomoSnapshot, getPomoSnapshot);
|
|
81
|
+
const { prefs: shellPrefs, save: saveShellPrefs } = useShellPrefs();
|
|
82
|
+
const userPrefs = readPrefs(shellPrefs.pomodoro_settings);
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
setPomoDurations({
|
|
85
|
+
focus: userPrefs.focusMinutes * 60,
|
|
86
|
+
short: userPrefs.shortBreakMinutes * 60,
|
|
87
|
+
long: userPrefs.longBreakMinutes * 60
|
|
88
|
+
});
|
|
89
|
+
}, [userPrefs.focusMinutes, userPrefs.shortBreakMinutes, userPrefs.longBreakMinutes]);
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
setPomoAlarm(userPrefs.alarmSound);
|
|
92
|
+
setPomoAlarmConfig(userPrefs.alarmVolume, userPrefs.alarmRepeat);
|
|
93
|
+
}, [userPrefs.alarmSound, userPrefs.alarmVolume, userPrefs.alarmRepeat]);
|
|
94
|
+
useEffect(() => {
|
|
95
|
+
setPomoBehaviour({
|
|
96
|
+
autoStartBreaks: userPrefs.autoStartBreaks,
|
|
97
|
+
autoStartPomodoros: userPrefs.autoStartPomodoros,
|
|
98
|
+
longBreakInterval: userPrefs.longBreakInterval
|
|
99
|
+
});
|
|
100
|
+
}, [userPrefs.autoStartBreaks, userPrefs.autoStartPomodoros, userPrefs.longBreakInterval]);
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
setPomoFocusSound(userPrefs.focusSound, userPrefs.focusVolume);
|
|
103
|
+
}, [userPrefs.focusSound, userPrefs.focusVolume]);
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
if (typeof Notification !== "undefined" && Notification.permission === "default") {
|
|
106
|
+
try {
|
|
107
|
+
Notification.requestPermission();
|
|
108
|
+
} catch {
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}, []);
|
|
112
|
+
const [tasks, setTasks] = useState(loadTasks);
|
|
113
|
+
const [activeTaskId, setActiveTaskId] = useState(() => localStorage.getItem(ACTIVE_TASK_KEY));
|
|
114
|
+
const [adding, setAdding] = useState(false);
|
|
115
|
+
const [menuOpenId, setMenuOpenId] = useState(null);
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
try {
|
|
118
|
+
localStorage.setItem(TASKS_KEY, JSON.stringify(tasks));
|
|
119
|
+
} catch {
|
|
120
|
+
}
|
|
121
|
+
}, [tasks]);
|
|
122
|
+
useEffect(() => {
|
|
123
|
+
try {
|
|
124
|
+
if (activeTaskId) localStorage.setItem(ACTIVE_TASK_KEY, activeTaskId);
|
|
125
|
+
else localStorage.removeItem(ACTIVE_TASK_KEY);
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
}, [activeTaskId]);
|
|
129
|
+
useEffect(() => {
|
|
130
|
+
if (!menuOpenId) return;
|
|
131
|
+
const handler = () => setMenuOpenId(null);
|
|
132
|
+
const t = setTimeout(() => document.addEventListener("click", handler), 0);
|
|
133
|
+
return () => {
|
|
134
|
+
clearTimeout(t);
|
|
135
|
+
document.removeEventListener("click", handler);
|
|
136
|
+
};
|
|
137
|
+
}, [menuOpenId]);
|
|
138
|
+
const lastStreakRef = useRef(snap.streak);
|
|
139
|
+
useEffect(() => {
|
|
140
|
+
if (snap.streak > lastStreakRef.current) {
|
|
141
|
+
setTasks((prev) => {
|
|
142
|
+
const next = prev.map((t) => {
|
|
143
|
+
if (t.id !== activeTaskId) return t;
|
|
144
|
+
const completed = t.completed + 1;
|
|
145
|
+
const shouldAutoCheck = userPrefs.autoCheckTasks && completed >= t.estimated;
|
|
146
|
+
return { ...t, completed, done: t.done || shouldAutoCheck };
|
|
147
|
+
});
|
|
148
|
+
return userPrefs.checkToBottom ? sortDoneToBottom(next) : next;
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
lastStreakRef.current = snap.streak;
|
|
152
|
+
}, [snap.streak, activeTaskId, userPrefs.autoCheckTasks, userPrefs.checkToBottom]);
|
|
153
|
+
const addTask = (name, estimated) => {
|
|
154
|
+
const trimmed = name.trim();
|
|
155
|
+
if (!trimmed) return;
|
|
156
|
+
const t = { id: uid(), name: trimmed, estimated, completed: 0, done: false };
|
|
157
|
+
setTasks((prev) => [...prev, t]);
|
|
158
|
+
if (!activeTaskId) setActiveTaskId(t.id);
|
|
159
|
+
setAdding(false);
|
|
160
|
+
};
|
|
161
|
+
const removeTask = (id) => {
|
|
162
|
+
setTasks((prev) => prev.filter((t) => t.id !== id));
|
|
163
|
+
if (activeTaskId === id) setActiveTaskId(null);
|
|
164
|
+
setMenuOpenId(null);
|
|
165
|
+
};
|
|
166
|
+
const toggleDone = (id) => {
|
|
167
|
+
setTasks((prev) => {
|
|
168
|
+
const next = prev.map((t) => t.id === id ? { ...t, done: !t.done } : t);
|
|
169
|
+
return userPrefs.checkToBottom ? sortDoneToBottom(next) : next;
|
|
170
|
+
});
|
|
171
|
+
};
|
|
172
|
+
const totalCompleted = tasks.reduce((acc, t) => acc + t.completed, 0);
|
|
173
|
+
const totalEstimated = tasks.reduce((acc, t) => acc + Math.max(t.estimated, t.completed), 0);
|
|
174
|
+
const remainingPomos = tasks.reduce((acc, t) => t.done ? acc : acc + Math.max(0, t.estimated - t.completed), 0);
|
|
175
|
+
const remainingSecsFromTimer = snap.running && snap.mode === "focus" ? snap.remaining : 0;
|
|
176
|
+
const remainingSecs = remainingPomos * userPrefs.focusMinutes * 60 + remainingSecsFromTimer;
|
|
177
|
+
const finishAt = new Date(Date.now() + remainingSecs * 1e3);
|
|
178
|
+
const finishAtStr = finishAt.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", hour12: false });
|
|
179
|
+
const totalHours = (remainingSecs / 3600).toFixed(1);
|
|
180
|
+
const activeIdx = activeTaskId ? tasks.findIndex((t) => t.id === activeTaskId) : -1;
|
|
181
|
+
const activeTask = activeIdx >= 0 ? tasks[activeIdx] : null;
|
|
182
|
+
const mm = String(Math.floor(snap.remaining / 60)).padStart(2, "0");
|
|
183
|
+
const ss = String(snap.remaining % 60).padStart(2, "0");
|
|
184
|
+
const [appearance, setAppearance] = useState(() => loadAppearance(POMO_SETTINGS_KEY));
|
|
185
|
+
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
186
|
+
const [configAppearance, setConfigAppearance] = useState(appearance);
|
|
187
|
+
const [configPrefs, setConfigPrefs] = useState(userPrefs);
|
|
188
|
+
useWidgetSettings(useCallback(() => {
|
|
189
|
+
setConfigAppearance({ ...appearance });
|
|
190
|
+
setConfigPrefs({ ...userPrefs });
|
|
191
|
+
setSettingsOpen(true);
|
|
192
|
+
}, [appearance, userPrefs]));
|
|
193
|
+
const onSave = () => {
|
|
194
|
+
setAppearance(configAppearance);
|
|
195
|
+
localStorage.setItem(POMO_SETTINGS_KEY, JSON.stringify(configAppearance));
|
|
196
|
+
saveShellPrefs({ pomodoro_settings: configPrefs });
|
|
197
|
+
setSettingsOpen(false);
|
|
198
|
+
};
|
|
199
|
+
const isColored = snap.mode !== "focus";
|
|
200
|
+
const bg = MODE_COLORS[snap.mode];
|
|
201
|
+
const panelBg = isColored ? hexToRgba(bg, appearance.activeOpacity / 100) : `rgb(var(--taskbar-bg-rgb, 243 244 246) / ${appearance.activeOpacity / 100})`;
|
|
202
|
+
const tx = {
|
|
203
|
+
primary: isColored ? "text-white" : "text-gray-900",
|
|
204
|
+
secondary: isColored ? "text-white/85" : "text-gray-700",
|
|
205
|
+
muted: isColored ? "text-white/65" : "text-gray-500",
|
|
206
|
+
tabActive: isColored ? "bg-white/15 text-white" : "bg-gray-200 text-gray-900",
|
|
207
|
+
tabInactive: isColored ? "text-white/75 hover:bg-white/10" : "text-gray-500 hover:bg-gray-200",
|
|
208
|
+
divider: isColored ? "border-white/30" : "border-gray-200",
|
|
209
|
+
softDivider: isColored ? "border-white/20" : "border-gray-200",
|
|
210
|
+
iconBtn: isColored ? "bg-black/15 hover:bg-black/25 text-white/85" : "bg-gray-200 hover:bg-gray-300 text-gray-600",
|
|
211
|
+
addTaskBtn: isColored ? "border-white/45 text-white/90 hover:bg-white/[0.06]" : "border-gray-300 text-gray-500 hover:bg-gray-200/50"
|
|
212
|
+
};
|
|
213
|
+
const accentColor = isColored ? bg : "#0f172a";
|
|
214
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
215
|
+
/* @__PURE__ */ jsxs(
|
|
216
|
+
"div",
|
|
217
|
+
{
|
|
218
|
+
className: `flex flex-col h-full select-none rounded-2xl overflow-hidden transition-colors duration-300 ${tx.primary}`,
|
|
219
|
+
style: {
|
|
220
|
+
backgroundColor: panelBg,
|
|
221
|
+
backdropFilter: appearance.activeBlur > 0 ? `blur(${appearance.activeBlur}px)` : void 0
|
|
222
|
+
},
|
|
223
|
+
children: [
|
|
224
|
+
/* @__PURE__ */ jsx("div", { className: "px-3 pt-3 flex justify-center gap-1.5", children: ["focus", "short", "long"].map((m) => /* @__PURE__ */ jsx(
|
|
225
|
+
"button",
|
|
226
|
+
{
|
|
227
|
+
onClick: () => pomoSwitchMode(m),
|
|
228
|
+
className: `px-2.5 py-1 text-[13px] font-bold rounded transition-colors ${snap.mode === m ? tx.tabActive : tx.tabInactive}`,
|
|
229
|
+
children: MODE_LABELS[m]
|
|
230
|
+
},
|
|
231
|
+
m
|
|
232
|
+
)) }),
|
|
233
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center font-bold tabular-nums leading-none tracking-tight mt-3", style: { fontSize: "4.5rem" }, children: [
|
|
234
|
+
mm,
|
|
235
|
+
":",
|
|
236
|
+
ss
|
|
237
|
+
] }),
|
|
238
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-center mt-3 mb-2", children: /* @__PURE__ */ jsx(
|
|
239
|
+
"button",
|
|
240
|
+
{
|
|
241
|
+
onClick: () => snap.running ? pomoPause() : pomoStart(),
|
|
242
|
+
className: "bg-white px-12 py-2.5 rounded-md font-bold text-base shadow-[0_4px_0_rgba(0,0,0,0.12)] hover:shadow-[0_3px_0_rgba(0,0,0,0.12)] active:translate-y-1 active:shadow-none transition-all",
|
|
243
|
+
style: { color: accentColor, letterSpacing: "0.08em" },
|
|
244
|
+
children: snap.running ? "PAUSE" : "START"
|
|
245
|
+
}
|
|
246
|
+
) }),
|
|
247
|
+
/* @__PURE__ */ jsx("div", { className: "px-3 py-3 text-center", children: activeTask ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
248
|
+
/* @__PURE__ */ jsxs("div", { className: `text-xs leading-tight ${tx.muted}`, children: [
|
|
249
|
+
"#",
|
|
250
|
+
activeTask.completed + 1
|
|
251
|
+
] }),
|
|
252
|
+
/* @__PURE__ */ jsx("div", { className: `text-[15px] font-medium leading-tight truncate mt-0.5 ${tx.primary}`, children: activeTask.name })
|
|
253
|
+
] }) : /* @__PURE__ */ jsx("div", { className: `text-xs italic ${tx.muted}`, children: "No task selected" }) }),
|
|
254
|
+
/* @__PURE__ */ jsxs("div", { className: "px-3 mt-1 flex items-center justify-between", children: [
|
|
255
|
+
/* @__PURE__ */ jsx("h3", { className: `text-base font-bold tracking-tight ${tx.primary}`, children: "Tasks" }),
|
|
256
|
+
/* @__PURE__ */ jsx("button", { className: `rounded p-1 transition-colors ${tx.iconBtn}`, "aria-label": "Tasks menu", tabIndex: -1, children: /* @__PURE__ */ jsxs("svg", { className: "h-4 w-4", viewBox: "0 0 24 24", fill: "currentColor", children: [
|
|
257
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "5", r: "1.4" }),
|
|
258
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1.4" }),
|
|
259
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "19", r: "1.4" })
|
|
260
|
+
] }) })
|
|
261
|
+
] }),
|
|
262
|
+
/* @__PURE__ */ jsx("div", { className: `border-t mx-3 mt-2 ${tx.divider}` }),
|
|
263
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 px-3 py-3 space-y-2 overflow-y-auto", children: [
|
|
264
|
+
tasks.map((task) => {
|
|
265
|
+
const isActive = task.id === activeTaskId;
|
|
266
|
+
return /* @__PURE__ */ jsxs(
|
|
267
|
+
"div",
|
|
268
|
+
{
|
|
269
|
+
onClick: () => setActiveTaskId(task.id),
|
|
270
|
+
className: `bg-white text-gray-800 rounded-md flex items-center pr-2 py-2.5 shadow-sm cursor-pointer transition-shadow hover:shadow-md ${isActive ? "border-l-4 border-gray-700 pl-2" : "pl-3 border-l-4 border-transparent"}`,
|
|
271
|
+
children: [
|
|
272
|
+
/* @__PURE__ */ jsx(
|
|
273
|
+
"button",
|
|
274
|
+
{
|
|
275
|
+
onClick: (e) => {
|
|
276
|
+
e.stopPropagation();
|
|
277
|
+
toggleDone(task.id);
|
|
278
|
+
},
|
|
279
|
+
className: "shrink-0",
|
|
280
|
+
children: task.done ? /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", fill: "currentColor", viewBox: "0 0 20 20", style: { color: accentColor }, 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", fill: "none", stroke: "currentColor", strokeWidth: 2, viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }) })
|
|
281
|
+
}
|
|
282
|
+
),
|
|
283
|
+
/* @__PURE__ */ jsx("span", { className: `ml-3 flex-1 font-semibold truncate ${task.done ? "line-through text-gray-400" : "text-gray-800"}`, children: task.name }),
|
|
284
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm tabular-nums mr-1.5 shrink-0", children: [
|
|
285
|
+
/* @__PURE__ */ jsx("span", { className: "font-bold text-gray-500", children: task.completed }),
|
|
286
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-400", children: " / " }),
|
|
287
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-400", children: task.estimated })
|
|
288
|
+
] }),
|
|
289
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
290
|
+
/* @__PURE__ */ jsx(
|
|
291
|
+
"button",
|
|
292
|
+
{
|
|
293
|
+
onClick: (e) => {
|
|
294
|
+
e.stopPropagation();
|
|
295
|
+
setMenuOpenId(menuOpenId === task.id ? null : task.id);
|
|
296
|
+
},
|
|
297
|
+
className: "rounded p-1 bg-gray-100 hover:bg-gray-200",
|
|
298
|
+
children: /* @__PURE__ */ jsxs("svg", { className: "h-4 w-4 text-gray-500", viewBox: "0 0 24 24", fill: "currentColor", children: [
|
|
299
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "5", r: "1.4" }),
|
|
300
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "1.4" }),
|
|
301
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "19", r: "1.4" })
|
|
302
|
+
] })
|
|
303
|
+
}
|
|
304
|
+
),
|
|
305
|
+
menuOpenId === task.id && /* @__PURE__ */ jsx(
|
|
306
|
+
"div",
|
|
307
|
+
{
|
|
308
|
+
className: "absolute right-0 top-full mt-1 bg-white text-gray-800 rounded shadow-lg border border-gray-200 z-10 min-w-[110px] overflow-hidden",
|
|
309
|
+
onClick: (e) => e.stopPropagation(),
|
|
310
|
+
children: /* @__PURE__ */ jsx(
|
|
311
|
+
"button",
|
|
312
|
+
{
|
|
313
|
+
onClick: (e) => {
|
|
314
|
+
e.stopPropagation();
|
|
315
|
+
removeTask(task.id);
|
|
316
|
+
},
|
|
317
|
+
className: "block w-full px-3 py-1.5 text-sm text-left hover:bg-red-50 text-red-600",
|
|
318
|
+
children: "Delete"
|
|
319
|
+
}
|
|
320
|
+
)
|
|
321
|
+
}
|
|
322
|
+
)
|
|
323
|
+
] })
|
|
324
|
+
]
|
|
325
|
+
},
|
|
326
|
+
task.id
|
|
327
|
+
);
|
|
328
|
+
}),
|
|
329
|
+
!adding ? /* @__PURE__ */ jsxs(
|
|
330
|
+
"button",
|
|
331
|
+
{
|
|
332
|
+
onClick: () => setAdding(true),
|
|
333
|
+
className: `w-full border-2 border-dashed rounded-md py-3 font-semibold flex items-center justify-center gap-2 transition-colors ${tx.addTaskBtn}`,
|
|
334
|
+
children: [
|
|
335
|
+
/* @__PURE__ */ jsxs("svg", { className: "h-5 w-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
336
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
|
|
337
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", d: "M8 12h8M12 8v8" })
|
|
338
|
+
] }),
|
|
339
|
+
"Add Task"
|
|
340
|
+
]
|
|
341
|
+
}
|
|
342
|
+
) : /* @__PURE__ */ jsx(AddTaskForm, { onSubmit: addTask, onCancel: () => setAdding(false), accentColor })
|
|
343
|
+
] }),
|
|
344
|
+
/* @__PURE__ */ jsxs("div", { className: `border-t px-3 py-2.5 flex items-center justify-center gap-5 text-sm ${tx.softDivider}`, children: [
|
|
345
|
+
/* @__PURE__ */ jsxs("span", { className: tx.secondary, children: [
|
|
346
|
+
"Pomos: ",
|
|
347
|
+
/* @__PURE__ */ jsx("span", { className: `font-bold ${tx.primary}`, children: totalCompleted }),
|
|
348
|
+
/* @__PURE__ */ jsx("span", { className: tx.muted, children: " / " }),
|
|
349
|
+
/* @__PURE__ */ jsx("span", { className: `font-bold ${tx.primary}`, children: totalEstimated })
|
|
350
|
+
] }),
|
|
351
|
+
remainingSecs > 0 && /* @__PURE__ */ jsxs("span", { className: tx.secondary, children: [
|
|
352
|
+
"Finish At: ",
|
|
353
|
+
/* @__PURE__ */ jsx("span", { className: `font-bold ${tx.primary}`, children: finishAtStr }),
|
|
354
|
+
/* @__PURE__ */ jsxs("span", { className: tx.muted, children: [
|
|
355
|
+
" (",
|
|
356
|
+
totalHours,
|
|
357
|
+
"h)"
|
|
358
|
+
] })
|
|
359
|
+
] })
|
|
360
|
+
] })
|
|
361
|
+
]
|
|
362
|
+
}
|
|
363
|
+
),
|
|
364
|
+
/* @__PURE__ */ jsx(
|
|
365
|
+
PomodoroSettings,
|
|
366
|
+
{
|
|
367
|
+
open: settingsOpen,
|
|
368
|
+
onClose: () => setSettingsOpen(false),
|
|
369
|
+
onSave,
|
|
370
|
+
configAppearance,
|
|
371
|
+
setConfigAppearance,
|
|
372
|
+
configPrefs,
|
|
373
|
+
setConfigPrefs
|
|
374
|
+
}
|
|
375
|
+
)
|
|
376
|
+
] });
|
|
377
|
+
}
|
|
378
|
+
function PomodoroSettings({
|
|
379
|
+
open,
|
|
380
|
+
onClose,
|
|
381
|
+
onSave,
|
|
382
|
+
configAppearance,
|
|
383
|
+
setConfigAppearance,
|
|
384
|
+
configPrefs,
|
|
385
|
+
setConfigPrefs
|
|
386
|
+
}) {
|
|
387
|
+
const set = (k, v) => setConfigPrefs((p) => ({ ...p, [k]: v }));
|
|
388
|
+
return /* @__PURE__ */ jsxs(
|
|
389
|
+
WidgetSettingsModal,
|
|
390
|
+
{
|
|
391
|
+
open,
|
|
392
|
+
onClose,
|
|
393
|
+
title: "Pomodoro Settings",
|
|
394
|
+
appearance: configAppearance,
|
|
395
|
+
onAppearanceChange: setConfigAppearance,
|
|
396
|
+
onSave,
|
|
397
|
+
children: [
|
|
398
|
+
/* @__PURE__ */ jsxs(Section, { icon: /* @__PURE__ */ jsx(ClockIcon, {}), label: "TIMER", children: [
|
|
399
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
400
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-bold text-gray-800 mb-2", children: "Time (minutes)" }),
|
|
401
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-3", children: [
|
|
402
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Pomodoro", value: configPrefs.focusMinutes, onChange: (v) => set("focusMinutes", v), max: 120 }),
|
|
403
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Short Break", value: configPrefs.shortBreakMinutes, onChange: (v) => set("shortBreakMinutes", v), max: 120 }),
|
|
404
|
+
/* @__PURE__ */ jsx(NumberField, { label: "Long Break", value: configPrefs.longBreakMinutes, onChange: (v) => set("longBreakMinutes", v), max: 120 })
|
|
405
|
+
] })
|
|
406
|
+
] }),
|
|
407
|
+
/* @__PURE__ */ jsx(Row, { label: "Auto Start Breaks", children: /* @__PURE__ */ jsx(Toggle, { checked: configPrefs.autoStartBreaks, onChange: (v) => set("autoStartBreaks", v) }) }),
|
|
408
|
+
/* @__PURE__ */ jsx(Row, { label: "Auto Start Pomodoros", children: /* @__PURE__ */ jsx(Toggle, { checked: configPrefs.autoStartPomodoros, onChange: (v) => set("autoStartPomodoros", v) }) }),
|
|
409
|
+
/* @__PURE__ */ jsx(Row, { label: "Long Break interval", children: /* @__PURE__ */ jsx(NumberInput, { value: configPrefs.longBreakInterval, onChange: (v) => set("longBreakInterval", v), min: 1, max: 20, className: "w-14 text-center" }) })
|
|
410
|
+
] }),
|
|
411
|
+
/* @__PURE__ */ jsxs(Section, { icon: /* @__PURE__ */ jsx(TaskIcon, {}), label: "TASK", children: [
|
|
412
|
+
/* @__PURE__ */ jsx(
|
|
413
|
+
Row,
|
|
414
|
+
{
|
|
415
|
+
label: "Auto Check Tasks",
|
|
416
|
+
info: 'If you enable "Auto Check Tasks", the active task will be automatically checked when the actual pomodoro count reaches the estimated count.',
|
|
417
|
+
children: /* @__PURE__ */ jsx(Toggle, { checked: configPrefs.autoCheckTasks, onChange: (v) => set("autoCheckTasks", v) })
|
|
418
|
+
}
|
|
419
|
+
),
|
|
420
|
+
/* @__PURE__ */ jsx(
|
|
421
|
+
Row,
|
|
422
|
+
{
|
|
423
|
+
label: "Check to Bottom",
|
|
424
|
+
info: 'If you enable "Check to Bottom", the checked task will be automatically moved to the bottom of the task list.',
|
|
425
|
+
children: /* @__PURE__ */ jsx(Toggle, { checked: configPrefs.checkToBottom, onChange: (v) => set("checkToBottom", v) })
|
|
426
|
+
}
|
|
427
|
+
)
|
|
428
|
+
] }),
|
|
429
|
+
/* @__PURE__ */ jsxs(Section, { icon: /* @__PURE__ */ jsx(SpeakerIcon, {}), label: "SOUND", children: [
|
|
430
|
+
/* @__PURE__ */ jsx(Row, { label: "Alarm Sound", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
431
|
+
/* @__PURE__ */ jsx(
|
|
432
|
+
Dropdown,
|
|
433
|
+
{
|
|
434
|
+
value: configPrefs.alarmSound,
|
|
435
|
+
onChange: (v) => set("alarmSound", v),
|
|
436
|
+
options: ALARM_OPTIONS.map((o) => ({ id: o.id, label: o.label }))
|
|
437
|
+
}
|
|
438
|
+
),
|
|
439
|
+
configPrefs.alarmSound !== "off" && /* @__PURE__ */ jsx(
|
|
440
|
+
"button",
|
|
441
|
+
{
|
|
442
|
+
type: "button",
|
|
443
|
+
onClick: () => playAlarm(configPrefs.alarmSound, { volume: configPrefs.alarmVolume, repeat: 1 }),
|
|
444
|
+
className: "px-2 py-1 text-[11px] rounded border border-gray-300 text-gray-600 hover:bg-gray-100",
|
|
445
|
+
children: "Play"
|
|
446
|
+
}
|
|
447
|
+
)
|
|
448
|
+
] }) }),
|
|
449
|
+
/* @__PURE__ */ jsx(SliderRow, { value: configPrefs.alarmVolume, onChange: (v) => set("alarmVolume", v) }),
|
|
450
|
+
/* @__PURE__ */ jsx(Row, { label: "repeat", children: /* @__PURE__ */ jsx(NumberInput, { value: configPrefs.alarmRepeat, onChange: (v) => set("alarmRepeat", v), min: 1, max: 5, className: "w-14 text-center" }) }),
|
|
451
|
+
/* @__PURE__ */ jsx(Row, { label: "Focus Sound", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
452
|
+
/* @__PURE__ */ jsx(
|
|
453
|
+
Dropdown,
|
|
454
|
+
{
|
|
455
|
+
value: configPrefs.focusSound,
|
|
456
|
+
onChange: (v) => set("focusSound", v),
|
|
457
|
+
options: FOCUS_SOUND_OPTIONS
|
|
458
|
+
}
|
|
459
|
+
),
|
|
460
|
+
configPrefs.focusSound !== "none" && /* @__PURE__ */ jsx(
|
|
461
|
+
"button",
|
|
462
|
+
{
|
|
463
|
+
type: "button",
|
|
464
|
+
onClick: () => previewFocusSound(configPrefs.focusSound, configPrefs.focusVolume),
|
|
465
|
+
className: "px-2 py-1 text-[11px] rounded border border-gray-300 text-gray-600 hover:bg-gray-100",
|
|
466
|
+
children: "Play"
|
|
467
|
+
}
|
|
468
|
+
)
|
|
469
|
+
] }) }),
|
|
470
|
+
/* @__PURE__ */ jsx(SliderRow, { value: configPrefs.focusVolume, onChange: (v) => set("focusVolume", v) })
|
|
471
|
+
] })
|
|
472
|
+
]
|
|
473
|
+
}
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
function Section({ icon, label, children }) {
|
|
477
|
+
return /* @__PURE__ */ jsxs("div", { className: "border-t border-gray-200 pt-3 first:border-0 first:pt-0", children: [
|
|
478
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 mb-3 text-gray-400", children: [
|
|
479
|
+
icon,
|
|
480
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-bold tracking-[0.15em]", children: label })
|
|
481
|
+
] }),
|
|
482
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-3", children })
|
|
483
|
+
] });
|
|
484
|
+
}
|
|
485
|
+
function Row({ label, info, children }) {
|
|
486
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
487
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 min-w-0", children: [
|
|
488
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-gray-800", children: label }),
|
|
489
|
+
info && /* @__PURE__ */ jsx(InfoIcon, { title: info })
|
|
490
|
+
] }),
|
|
491
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0", children })
|
|
492
|
+
] });
|
|
493
|
+
}
|
|
494
|
+
function SliderRow({ value, onChange }) {
|
|
495
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-3", children: [
|
|
496
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-400 w-7 text-right tabular-nums", children: value }),
|
|
497
|
+
/* @__PURE__ */ jsx(
|
|
498
|
+
"input",
|
|
499
|
+
{
|
|
500
|
+
type: "range",
|
|
501
|
+
min: 0,
|
|
502
|
+
max: 100,
|
|
503
|
+
value,
|
|
504
|
+
onChange: (e) => onChange(parseInt(e.target.value, 10)),
|
|
505
|
+
className: "w-40 accent-blue-500"
|
|
506
|
+
}
|
|
507
|
+
)
|
|
508
|
+
] });
|
|
509
|
+
}
|
|
510
|
+
function NumberField({ label, value, onChange, min = 1, max = 99 }) {
|
|
511
|
+
return /* @__PURE__ */ jsxs("label", { className: "flex flex-col", children: [
|
|
512
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-gray-500 mb-1", children: label }),
|
|
513
|
+
/* @__PURE__ */ jsx(NumberInput, { value, onChange, min, max })
|
|
514
|
+
] });
|
|
515
|
+
}
|
|
516
|
+
function NumberInput({ value, onChange, min = 1, max = 99, className = "" }) {
|
|
517
|
+
return /* @__PURE__ */ jsx(
|
|
518
|
+
"input",
|
|
519
|
+
{
|
|
520
|
+
type: "number",
|
|
521
|
+
min,
|
|
522
|
+
max,
|
|
523
|
+
value,
|
|
524
|
+
onChange: (e) => onChange(Math.max(min, Math.min(max, parseInt(e.target.value, 10) || min))),
|
|
525
|
+
className: `bg-gray-100 border-0 rounded-md px-2 py-1.5 text-sm font-medium text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500 w-full ${className}`
|
|
526
|
+
}
|
|
527
|
+
);
|
|
528
|
+
}
|
|
529
|
+
function Dropdown({ value, onChange, options }) {
|
|
530
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
531
|
+
/* @__PURE__ */ jsx(
|
|
532
|
+
"select",
|
|
533
|
+
{
|
|
534
|
+
value,
|
|
535
|
+
onChange: (e) => onChange(e.target.value),
|
|
536
|
+
className: "appearance-none bg-gray-100 border-0 rounded-md pl-3 pr-8 py-1.5 text-sm font-medium text-gray-800 focus:outline-none focus:ring-2 focus:ring-blue-500 cursor-pointer",
|
|
537
|
+
children: options.map((o) => /* @__PURE__ */ jsx("option", { value: o.id, children: o.label }, o.id))
|
|
538
|
+
}
|
|
539
|
+
),
|
|
540
|
+
/* @__PURE__ */ jsx("svg", { className: "absolute right-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-gray-400 pointer-events-none", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 9l6 6 6-6" }) })
|
|
541
|
+
] });
|
|
542
|
+
}
|
|
543
|
+
function Toggle({ checked, onChange }) {
|
|
544
|
+
return /* @__PURE__ */ jsx(
|
|
545
|
+
"button",
|
|
546
|
+
{
|
|
547
|
+
type: "button",
|
|
548
|
+
role: "switch",
|
|
549
|
+
"aria-checked": checked,
|
|
550
|
+
onClick: () => onChange(!checked),
|
|
551
|
+
className: `relative inline-flex h-6 w-11 items-center rounded-full transition-colors ${checked ? "bg-emerald-500" : "bg-gray-300"}`,
|
|
552
|
+
children: /* @__PURE__ */ jsx("span", { className: `absolute h-5 w-5 rounded-full bg-white shadow transition-transform ${checked ? "translate-x-[22px]" : "translate-x-0.5"}` })
|
|
553
|
+
}
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
function InfoIcon({ title }) {
|
|
557
|
+
return /* @__PURE__ */ jsx("span", { title, className: "inline-flex items-center justify-center w-4 h-4 rounded-full bg-gray-300 text-white text-[10px] font-bold cursor-help", children: "i" });
|
|
558
|
+
}
|
|
559
|
+
function ClockIcon() {
|
|
560
|
+
return /* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
561
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
562
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 7v5l3 2" })
|
|
563
|
+
] });
|
|
564
|
+
}
|
|
565
|
+
function TaskIcon() {
|
|
566
|
+
return /* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
567
|
+
/* @__PURE__ */ jsx("rect", { x: "4", y: "4", width: "16", height: "16", rx: "2" }),
|
|
568
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9 12l2 2 4-4" })
|
|
569
|
+
] });
|
|
570
|
+
}
|
|
571
|
+
function SpeakerIcon() {
|
|
572
|
+
return /* @__PURE__ */ jsxs("svg", { className: "h-3.5 w-3.5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, children: [
|
|
573
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M11 5L6 9H2v6h4l5 4V5z" }),
|
|
574
|
+
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.5 8.5a5 5 0 010 7M19 5a9 9 0 010 14" })
|
|
575
|
+
] });
|
|
576
|
+
}
|
|
577
|
+
function AddTaskForm({ onSubmit, onCancel, accentColor }) {
|
|
578
|
+
const [name, setName] = useState("");
|
|
579
|
+
const [est, setEst] = useState(1);
|
|
580
|
+
const submit = () => onSubmit(name, est);
|
|
581
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-white text-gray-800 rounded-md p-3 shadow-md", children: [
|
|
582
|
+
/* @__PURE__ */ jsx(
|
|
583
|
+
"input",
|
|
584
|
+
{
|
|
585
|
+
autoFocus: true,
|
|
586
|
+
value: name,
|
|
587
|
+
onChange: (e) => setName(e.target.value),
|
|
588
|
+
placeholder: "What are you working on?",
|
|
589
|
+
onKeyDown: (e) => {
|
|
590
|
+
if (e.key === "Enter") submit();
|
|
591
|
+
if (e.key === "Escape") onCancel();
|
|
592
|
+
},
|
|
593
|
+
className: "w-full text-base font-medium bg-transparent border-0 outline-none placeholder-gray-400"
|
|
594
|
+
}
|
|
595
|
+
),
|
|
596
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mt-2", children: [
|
|
597
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-gray-500", children: "Est Pomodoros" }),
|
|
598
|
+
/* @__PURE__ */ jsx(
|
|
599
|
+
"input",
|
|
600
|
+
{
|
|
601
|
+
type: "number",
|
|
602
|
+
min: 1,
|
|
603
|
+
max: 20,
|
|
604
|
+
value: est,
|
|
605
|
+
onChange: (e) => setEst(Math.max(1, Math.min(20, parseInt(e.target.value, 10) || 1))),
|
|
606
|
+
className: "w-16 bg-gray-100 rounded px-2 py-1 text-sm text-right border-0 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
607
|
+
}
|
|
608
|
+
)
|
|
609
|
+
] }),
|
|
610
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2 mt-3 justify-end", children: [
|
|
611
|
+
/* @__PURE__ */ jsx("button", { onClick: onCancel, className: "px-3 py-1 text-sm text-gray-500 hover:bg-gray-100 rounded", children: "Cancel" }),
|
|
612
|
+
/* @__PURE__ */ jsx(
|
|
613
|
+
"button",
|
|
614
|
+
{
|
|
615
|
+
onClick: submit,
|
|
616
|
+
className: "px-4 py-1 text-sm font-semibold text-white rounded shadow-sm",
|
|
617
|
+
style: { backgroundColor: accentColor },
|
|
618
|
+
children: "Save"
|
|
619
|
+
}
|
|
620
|
+
)
|
|
621
|
+
] })
|
|
622
|
+
] });
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
export { PomodoroTimer as default };
|
|
626
|
+
//# sourceMappingURL=PomodoroTimer-PRP5CZ3S.js.map
|
|
627
|
+
//# sourceMappingURL=PomodoroTimer-PRP5CZ3S.js.map
|