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