react-os-shell 0.2.44 → 0.2.46

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/{Calendar-4UQDQ3NT.js → Calendar-PKRZ5MBU.js} +153 -54
  2. package/dist/Calendar-PKRZ5MBU.js.map +1 -0
  3. package/dist/{CurrencyConverter-TXBFDFG2.js → CurrencyConverter-5N44NZ6Z.js} +3 -3
  4. package/dist/{CurrencyConverter-TXBFDFG2.js.map → CurrencyConverter-5N44NZ6Z.js.map} +1 -1
  5. package/dist/{Email-HRBZUWPY.js → Email-CR6XS2AD.js} +4 -4
  6. package/dist/{Email-HRBZUWPY.js.map → Email-CR6XS2AD.js.map} +1 -1
  7. package/dist/{Files-ITIKVHIE.js → Files-CEID4TC3.js} +4 -4
  8. package/dist/{Files-ITIKVHIE.js.map → Files-CEID4TC3.js.map} +1 -1
  9. package/dist/{GeminiChat-ITU46EH4.js → GeminiChat-XTEBZIVK.js} +3 -3
  10. package/dist/{GeminiChat-ITU46EH4.js.map → GeminiChat-XTEBZIVK.js.map} +1 -1
  11. package/dist/{PomodoroTimer-PRP5CZ3S.js → PomodoroTimer-FHSOLF3O.js} +49 -49
  12. package/dist/PomodoroTimer-FHSOLF3O.js.map +1 -0
  13. package/dist/Preview-B5DUW2AR.js +7 -0
  14. package/dist/{Preview-4MBQI66Q.js.map → Preview-B5DUW2AR.js.map} +1 -1
  15. package/dist/TodoList-7JZ2SLDI.js +494 -0
  16. package/dist/TodoList-7JZ2SLDI.js.map +1 -0
  17. package/dist/{WorldClock-QO5PVJQQ.js → WorldClock-XHM7WAUV.js} +43 -97
  18. package/dist/WorldClock-XHM7WAUV.js.map +1 -0
  19. package/dist/apps/index.d.ts +4 -1
  20. package/dist/apps/index.js +14 -12
  21. package/dist/apps/index.js.map +1 -1
  22. package/dist/chunk-25L4DIKH.js +90 -0
  23. package/dist/chunk-25L4DIKH.js.map +1 -0
  24. package/dist/{chunk-62MVMTBT.js → chunk-5VXRBUEH.js} +20 -3
  25. package/dist/chunk-5VXRBUEH.js.map +1 -0
  26. package/dist/{chunk-MTLVXT2C.js → chunk-6AJUSDEM.js} +3 -3
  27. package/dist/{chunk-MTLVXT2C.js.map → chunk-6AJUSDEM.js.map} +1 -1
  28. package/dist/{chunk-46LICZUM.js → chunk-MVWEL34Y.js} +3 -2
  29. package/dist/chunk-MVWEL34Y.js.map +1 -0
  30. package/dist/{chunk-DUUANLLE.js → chunk-QBH7KERS.js} +482 -19
  31. package/dist/chunk-QBH7KERS.js.map +1 -0
  32. package/dist/index.js +3 -3
  33. package/dist/styles.css +6 -4
  34. package/package.json +1 -1
  35. package/dist/Calendar-4UQDQ3NT.js.map +0 -1
  36. package/dist/PomodoroTimer-PRP5CZ3S.js.map +0 -1
  37. package/dist/Preview-4MBQI66Q.js +0 -7
  38. package/dist/WorldClock-QO5PVJQQ.js.map +0 -1
  39. package/dist/chunk-46LICZUM.js.map +0 -1
  40. package/dist/chunk-62MVMTBT.js.map +0 -1
  41. package/dist/chunk-DUUANLLE.js.map +0 -1
@@ -8,77 +8,21 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
8
8
 
9
9
  var SETTINGS_KEY = "world_clock_appearance";
10
10
  var DEFAULT_CITIES = ["London", "Shanghai", "New York"];
11
- function AnalogClockWithMeridiem({ tz, now, size = 30 }) {
12
- let h24 = 0, m = 0;
11
+ function digitalTime(tz, now) {
13
12
  try {
14
13
  const parts = new Intl.DateTimeFormat("en-US", {
15
14
  timeZone: tz,
16
15
  hour: "numeric",
17
16
  minute: "2-digit",
18
- hour12: false
17
+ hour12: true
19
18
  }).formatToParts(now);
20
- h24 = parseInt(parts.find((p) => p.type === "hour")?.value || "0", 10);
21
- if (h24 === 24) h24 = 0;
22
- m = parseInt(parts.find((p) => p.type === "minute")?.value || "0", 10);
19
+ const h = parts.find((p) => p.type === "hour")?.value || "12";
20
+ const m = parts.find((p) => p.type === "minute")?.value || "00";
21
+ const ampm = (parts.find((p) => p.type === "dayPeriod")?.value || "").toUpperCase();
22
+ return { time: `${h}:${m}`, ampm };
23
23
  } catch {
24
+ return { time: "", ampm: "" };
24
25
  }
25
- const ampm = h24 >= 12 ? "PM" : "AM";
26
- const hourAngle = (h24 % 12 + m / 60) * 30 - 90;
27
- const minuteAngle = m * 6 - 90;
28
- const r = size / 2;
29
- const hLen = r * 0.52;
30
- const mLen = r * 0.78;
31
- const hRad = hourAngle * Math.PI / 180;
32
- const mRad = minuteAngle * Math.PI / 180;
33
- return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-0.5 shrink-0 text-gray-700", children: [
34
- /* @__PURE__ */ jsxs("svg", { width: size, height: size, viewBox: `0 0 ${size} ${size}`, style: { color: "currentColor" }, children: [
35
- /* @__PURE__ */ jsx(
36
- "circle",
37
- {
38
- cx: r,
39
- cy: r,
40
- r: r - 0.6,
41
- fill: "currentColor",
42
- fillOpacity: 0.05,
43
- stroke: "currentColor",
44
- strokeOpacity: 0.4,
45
- strokeWidth: 0.8
46
- }
47
- ),
48
- [0, 90, 180, 270].map((deg) => {
49
- const a = (deg - 90) * Math.PI / 180;
50
- const dx = r + Math.cos(a) * (r * 0.83);
51
- const dy = r + Math.sin(a) * (r * 0.83);
52
- return /* @__PURE__ */ jsx("circle", { cx: dx, cy: dy, r: 0.85, fill: "currentColor", fillOpacity: 0.55 }, deg);
53
- }),
54
- /* @__PURE__ */ jsx(
55
- "line",
56
- {
57
- x1: r,
58
- y1: r,
59
- x2: r + Math.cos(hRad) * hLen,
60
- y2: r + Math.sin(hRad) * hLen,
61
- stroke: "currentColor",
62
- strokeWidth: 1.6,
63
- strokeLinecap: "round"
64
- }
65
- ),
66
- /* @__PURE__ */ jsx(
67
- "line",
68
- {
69
- x1: r,
70
- y1: r,
71
- x2: r + Math.cos(mRad) * mLen,
72
- y2: r + Math.sin(mRad) * mLen,
73
- stroke: "currentColor",
74
- strokeWidth: 1.1,
75
- strokeLinecap: "round"
76
- }
77
- ),
78
- /* @__PURE__ */ jsx("circle", { cx: r, cy: r, r: 1.3, fill: "currentColor" })
79
- ] }),
80
- /* @__PURE__ */ jsx("span", { className: "text-[8.5px] font-medium tracking-[0.12em] text-gray-500", children: ampm })
81
- ] });
82
26
  }
83
27
  function WorldClock() {
84
28
  const { prefs, save } = useShellPrefs();
@@ -149,51 +93,53 @@ function WorldClock() {
149
93
  /* @__PURE__ */ jsx(
150
94
  "div",
151
95
  {
152
- className: "rounded-2xl overflow-hidden",
96
+ className: "h-full",
153
97
  style: {
154
98
  backgroundColor: `rgb(var(--taskbar-bg-rgb, 243 244 246) / ${appearance.activeOpacity / 100})`,
155
99
  backdropFilter: appearance.activeBlur > 0 ? `blur(${appearance.activeBlur}px)` : void 0
156
100
  },
157
- children: /* @__PURE__ */ jsxs("div", { className: "px-1 py-1", children: [
101
+ children: /* @__PURE__ */ jsxs("div", { className: "divide-y divide-gray-200", children: [
158
102
  loading && cities.every((c) => !data[c]) && /* @__PURE__ */ jsx("div", { className: "px-3 py-6 text-center text-xs text-gray-500", children: "Loading\u2026" }),
159
- cities.map((cityName, i) => {
103
+ cities.map((cityName) => {
160
104
  const w = data[cityName];
161
105
  const tz = AVAILABLE_CITIES[cityName]?.tz ?? "UTC";
162
- const last = i === cities.length - 1;
106
+ const { time, ampm } = digitalTime(tz, now);
163
107
  if (!w) {
164
- return /* @__PURE__ */ jsxs("div", { className: `flex items-center gap-3 px-3 py-3 ${last ? "" : "border-b border-gray-200"}`, children: [
165
- /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
166
- /* @__PURE__ */ jsx("div", { className: "text-[15px] font-semibold tracking-tight leading-tight truncate text-gray-900", children: cityName }),
167
- /* @__PURE__ */ jsx("div", { className: "text-[11px] text-gray-500 leading-tight", children: "\u2026" })
108
+ return /* @__PURE__ */ jsxs("div", { className: "px-4 py-3", children: [
109
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-2", children: [
110
+ /* @__PURE__ */ jsx("span", { className: "text-[15px] font-semibold tracking-tight text-gray-900 truncate", children: cityName }),
111
+ /* @__PURE__ */ jsxs("span", { className: "tabular-nums text-[13px] font-medium text-gray-500", children: [
112
+ time,
113
+ /* @__PURE__ */ jsx("span", { className: "text-[9px] ml-0.5 opacity-70", children: ampm })
114
+ ] })
168
115
  ] }),
169
- /* @__PURE__ */ jsx(AnalogClockWithMeridiem, { tz, now })
116
+ /* @__PURE__ */ jsx("div", { className: "text-[11px] text-gray-400 mt-1", children: "Loading weather\u2026" })
170
117
  ] }, cityName);
171
118
  }
172
119
  const [condition, emoji] = getCondition(w.code, w.isDay);
173
- return /* @__PURE__ */ jsxs(
174
- "div",
175
- {
176
- className: `flex items-center gap-3 px-3 py-3 ${last ? "" : "border-b border-gray-200"}`,
177
- children: [
178
- /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
179
- /* @__PURE__ */ jsx("div", { className: "text-[15px] font-semibold tracking-tight leading-tight truncate text-gray-900", children: cityName }),
180
- /* @__PURE__ */ jsx("div", { className: "text-[11px] text-gray-500 leading-tight truncate mt-0.5", children: condition })
120
+ return /* @__PURE__ */ jsxs("div", { className: "px-4 py-3", children: [
121
+ /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-2", children: [
122
+ /* @__PURE__ */ jsx("span", { className: "text-[15px] font-semibold tracking-tight text-gray-900 truncate", children: cityName }),
123
+ /* @__PURE__ */ jsx("span", { className: "text-[26px] font-extralight leading-none tabular-nums tracking-tight text-gray-900 shrink-0", children: formatTemp(w.temp) })
124
+ ] }),
125
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 mt-1.5 text-[11px]", children: [
126
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 min-w-0 text-gray-500", children: [
127
+ /* @__PURE__ */ jsx("span", { className: "text-base leading-none shrink-0", children: emoji }),
128
+ /* @__PURE__ */ jsxs("span", { className: "tabular-nums font-semibold text-gray-700 shrink-0", children: [
129
+ time,
130
+ /* @__PURE__ */ jsx("span", { className: "text-[9px] font-medium ml-0.5 opacity-70", children: ampm })
181
131
  ] }),
182
- /* @__PURE__ */ jsx(AnalogClockWithMeridiem, { tz, now }),
183
- /* @__PURE__ */ jsx("span", { className: "text-[22px] leading-none shrink-0", children: emoji }),
184
- /* @__PURE__ */ jsxs("div", { className: "text-right shrink-0 min-w-[52px]", children: [
185
- /* @__PURE__ */ jsx("div", { className: "text-[22px] font-extralight leading-none tabular-nums tracking-tight text-gray-900", children: formatTemp(w.temp) }),
186
- /* @__PURE__ */ jsxs("div", { className: "text-[10px] text-gray-500 tabular-nums mt-1", children: [
187
- "H:",
188
- formatTemp(w.high),
189
- " L:",
190
- formatTemp(w.low)
191
- ] })
192
- ] })
193
- ]
194
- },
195
- cityName
196
- );
132
+ /* @__PURE__ */ jsx("span", { className: "text-gray-300 shrink-0", children: "\xB7" }),
133
+ /* @__PURE__ */ jsx("span", { className: "truncate", children: condition })
134
+ ] }),
135
+ /* @__PURE__ */ jsxs("span", { className: "tabular-nums text-gray-500 shrink-0", children: [
136
+ "H:",
137
+ formatTemp(w.high),
138
+ " L:",
139
+ formatTemp(w.low)
140
+ ] })
141
+ ] })
142
+ ] }, cityName);
197
143
  })
198
144
  ] })
199
145
  }
@@ -246,5 +192,5 @@ function WorldClock() {
246
192
  }
247
193
 
248
194
  export { WorldClock as default };
249
- //# sourceMappingURL=WorldClock-QO5PVJQQ.js.map
250
- //# sourceMappingURL=WorldClock-QO5PVJQQ.js.map
195
+ //# sourceMappingURL=WorldClock-XHM7WAUV.js.map
196
+ //# sourceMappingURL=WorldClock-XHM7WAUV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/apps/WorldClock.tsx"],"names":[],"mappings":"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","file":"WorldClock-XHM7WAUV.js","sourcesContent":["import { useState, useEffect, useCallback } from 'react';\nimport { useWidgetSettings } from '../shell/Modal';\nimport WidgetSettingsModal, { loadAppearance, type WidgetAppearance } from '../shell/WidgetSettingsModal';\nimport { useShellPrefs } from '../shell/ShellPrefs';\nimport { AVAILABLE_CITIES, fetchCityWeather, getCondition, toFahrenheit, type CityWeather } from './_weatherData';\n\nconst SETTINGS_KEY = 'world_clock_appearance';\nconst DEFAULT_CITIES = ['London', 'Shanghai', 'New York'];\n\ninterface WeatherPrefs { useFahrenheit: boolean }\n\n/**\n * Resolve the local time for the supplied IANA timezone into a digital\n * `12:34` + `AM` / `PM` pair. Used by the World Clock rows.\n */\nfunction digitalTime(tz: string, now: Date): { time: string; ampm: string } {\n try {\n const parts = new Intl.DateTimeFormat('en-US', {\n timeZone: tz, hour: 'numeric', minute: '2-digit', hour12: true,\n }).formatToParts(now);\n const h = parts.find(p => p.type === 'hour')?.value || '12';\n const m = parts.find(p => p.type === 'minute')?.value || '00';\n const ampm = (parts.find(p => p.type === 'dayPeriod')?.value || '').toUpperCase();\n return { time: `${h}:${m}`, ampm };\n } catch { return { time: '', ampm: '' }; }\n}\n\n/**\n * World Clock widget — multi-city list. Each row pairs a tiny analogue\n * clock (minimal-style: ring, four cardinal dots, two hands) with the\n * city's current weather. The weather emoji doubles as a day/night cue\n * (☀ vs 🌙 for clear, the same icons for everything else). Reads the\n * shared Open-Meteo cache so it doesn't re-hit the API when the Weather\n * widget already has the data.\n */\nexport default function WorldClock() {\n const { prefs, save } = useShellPrefs();\n const [appearance, setAppearance] = useState(() => loadAppearance(SETTINGS_KEY));\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [configCities, setConfigCities] = useState<string[]>([]);\n const [configAppearance, setConfigAppearance] = useState<WidgetAppearance>(appearance);\n\n const wxPrefs: WeatherPrefs = {\n useFahrenheit: !!(prefs.weather_prefs as WeatherPrefs | undefined)?.useFahrenheit,\n };\n const [configWxPrefs, setConfigWxPrefs] = useState(wxPrefs);\n\n // Tick once every 30 s so the analogue minute-hands drift smoothly. We\n // don't show seconds so faster polling is wasted re-renders.\n const [now, setNow] = useState(() => new Date());\n useEffect(() => {\n const t = setInterval(() => setNow(new Date()), 30 * 1000);\n return () => clearInterval(t);\n }, []);\n\n // Resolve the saved city list and migrate the legacy IANA-timezone\n // format (`Europe/London`) over to the new city-name format\n // (`London`).\n const tzToCity: Record<string, string> = Object.fromEntries(\n Object.entries(AVAILABLE_CITIES).map(([city, info]) => [info.tz, city])\n );\n const rawClocks = prefs.world_clocks as string[] | undefined;\n const cities: string[] = (() => {\n if (!Array.isArray(rawClocks) || rawClocks.length === 0) return DEFAULT_CITIES;\n const out: string[] = [];\n for (const v of rawClocks) {\n const asCity = AVAILABLE_CITIES[v] ? v : tzToCity[v];\n if (asCity && !out.includes(asCity)) out.push(asCity);\n }\n return out.length ? out : DEFAULT_CITIES;\n })();\n\n const [data, setData] = useState<Record<string, CityWeather>>({});\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n (async () => {\n const next: Record<string, CityWeather> = {};\n await Promise.all(cities.map(async c => {\n const w = await fetchCityWeather(c);\n if (w) next[c] = w;\n }));\n if (!cancelled) { setData(next); setLoading(false); }\n })();\n return () => { cancelled = true; };\n }, [cities.join(',')]);\n\n useWidgetSettings(useCallback(() => {\n setConfigCities([...cities]);\n setConfigAppearance({ ...appearance });\n setConfigWxPrefs({ ...wxPrefs });\n setSettingsOpen(true);\n }, [cities.join(','), appearance, wxPrefs.useFahrenheit]));\n\n const saveSettings = () => {\n if (configCities.length === 0) return;\n save({\n world_clocks: configCities,\n weather_prefs: { ...(prefs.weather_prefs as object | undefined ?? {}), useFahrenheit: configWxPrefs.useFahrenheit },\n });\n setAppearance(configAppearance);\n localStorage.setItem(SETTINGS_KEY, JSON.stringify(configAppearance));\n setSettingsOpen(false);\n };\n\n const formatTemp = (c: number) => wxPrefs.useFahrenheit ? `${toFahrenheit(c)}°` : `${c}°`;\n\n return (\n <>\n {/* Theme-aware panel — same colour as the taskbar so all dashboard\n * widgets read as a coordinated set across light and dark themes.\n * Rows use `divide-y` rather than per-row border classes so the\n * last row never paints a stray separator line at the panel's\n * bottom edge. */}\n <div className=\"h-full\"\n style={{\n backgroundColor: `rgb(var(--taskbar-bg-rgb, 243 244 246) / ${appearance.activeOpacity / 100})`,\n backdropFilter: appearance.activeBlur > 0 ? `blur(${appearance.activeBlur}px)` : undefined,\n }}>\n <div className=\"divide-y divide-gray-200\">\n {loading && cities.every(c => !data[c]) && (\n <div className=\"px-3 py-6 text-center text-xs text-gray-500\">Loading…</div>\n )}\n {cities.map((cityName) => {\n const w = data[cityName];\n const tz = AVAILABLE_CITIES[cityName]?.tz ?? 'UTC';\n const { time, ampm } = digitalTime(tz, now);\n if (!w) {\n return (\n <div key={cityName} className=\"px-4 py-3\">\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-[15px] font-semibold tracking-tight text-gray-900 truncate\">{cityName}</span>\n <span className=\"tabular-nums text-[13px] font-medium text-gray-500\">{time}<span className=\"text-[9px] ml-0.5 opacity-70\">{ampm}</span></span>\n </div>\n <div className=\"text-[11px] text-gray-400 mt-1\">Loading weather…</div>\n </div>\n );\n }\n const [condition, emoji] = getCondition(w.code, w.isDay);\n return (\n <div key={cityName} className=\"px-4 py-3\">\n {/* Top — city name on the left, big temperature on the right. */}\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-[15px] font-semibold tracking-tight text-gray-900 truncate\">{cityName}</span>\n <span className=\"text-[26px] font-extralight leading-none tabular-nums tracking-tight text-gray-900 shrink-0\">{formatTemp(w.temp)}</span>\n </div>\n\n {/* Bottom — emoji · digital time · condition on the left;\n H/L on the right. */}\n <div className=\"flex items-center justify-between gap-2 mt-1.5 text-[11px]\">\n <div className=\"flex items-center gap-1.5 min-w-0 text-gray-500\">\n <span className=\"text-base leading-none shrink-0\">{emoji}</span>\n <span className=\"tabular-nums font-semibold text-gray-700 shrink-0\">\n {time}<span className=\"text-[9px] font-medium ml-0.5 opacity-70\">{ampm}</span>\n </span>\n <span className=\"text-gray-300 shrink-0\">·</span>\n <span className=\"truncate\">{condition}</span>\n </div>\n <span className=\"tabular-nums text-gray-500 shrink-0\">H:{formatTemp(w.high)} L:{formatTemp(w.low)}</span>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n\n <WidgetSettingsModal open={settingsOpen} onClose={() => setSettingsOpen(false)} title=\"World Clock Settings\"\n appearance={configAppearance} onAppearanceChange={setConfigAppearance} onSave={saveSettings}>\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-2\">Display</h3>\n <div className=\"flex items-center gap-3 mb-2\">\n <span className=\"text-sm text-gray-600 w-24\">Temperature</span>\n <div className=\"flex gap-1\">\n {([{ key: false, label: '°C' }, { key: true, label: '°F' }] as const).map(o => (\n <button key={String(o.key)} onClick={() => setConfigWxPrefs(p => ({ ...p, useFahrenheit: o.key }))}\n className={`px-3 py-1 text-xs font-medium rounded-lg border transition-colors ${configWxPrefs.useFahrenheit === o.key ? 'bg-blue-600 text-white border-blue-600' : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'}`}>\n {o.label}\n </button>\n ))}\n </div>\n </div>\n <p className=\"text-[10px] text-gray-400 mt-1\">Shared with the Weather widget.</p>\n </div>\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-2\">Cities</h3>\n <div className=\"grid grid-cols-2 gap-1 max-h-56 overflow-y-auto\">\n {Object.keys(AVAILABLE_CITIES).map(name => (\n <label key={name} className=\"flex items-center gap-2 text-sm py-1 cursor-pointer hover:bg-gray-50 rounded px-2\">\n <input type=\"checkbox\" checked={configCities.includes(name)}\n onChange={() => setConfigCities(prev => prev.includes(name) ? prev.filter(c => c !== name) : [...prev, name])}\n className=\"rounded border-gray-300 text-blue-600 focus:ring-blue-500 h-3.5 w-3.5\" />\n {name}\n </label>\n ))}\n </div>\n </div>\n </WidgetSettingsModal>\n </>\n );\n}\n"]}
@@ -53,6 +53,8 @@ declare function Checkers$1(): react_jsx_runtime.JSX.Element;
53
53
 
54
54
  declare function Chess$1(): react_jsx_runtime.JSX.Element;
55
55
 
56
+ declare function TodoList$1(): react_jsx_runtime.JSX.Element;
57
+
56
58
  /**
57
59
  * World Clock widget — multi-city list. Each row pairs a tiny analogue
58
60
  * clock (minimal-style: ring, four cardinal dots, two hands) with the
@@ -82,6 +84,7 @@ declare const CurrencyConverter: react.LazyExoticComponent<typeof CurrencyConver
82
84
  declare const PomodoroTimer: react.LazyExoticComponent<typeof PomodoroTimer$1>;
83
85
  declare const Notepad: react.LazyExoticComponent<typeof Notepad$1>;
84
86
  declare const WorldClock: react.LazyExoticComponent<typeof WorldClock$1>;
87
+ declare const TodoList: react.LazyExoticComponent<typeof TodoList$1>;
85
88
  declare const Chess: react.LazyExoticComponent<typeof Chess$1>;
86
89
  declare const Checkers: react.LazyExoticComponent<typeof Checkers$1>;
87
90
  declare const Sudoku: react.LazyExoticComponent<typeof Sudoku$1>;
@@ -102,4 +105,4 @@ declare const documentApps: WindowRegistry;
102
105
  declare const webApps: WindowRegistry;
103
106
  declare const bundledApps: WindowRegistry;
104
107
 
105
- export { Browser, Calculator, Calendar, Checkers, Chess, CurrencyConverter, Documents, Email, Files, Game2048, GeminiChat, Minesweeper, Notepad, type PdfPreviewData, PomodoroTimer, Preview, Spreadsheet, Sudoku, Tetris, Weather, WorldClock, bundledApps, documentApps, gameApps, googleApps, openFilesInTrashMode, setPdfPreview, utilityApps, webApps };
108
+ export { Browser, Calculator, Calendar, Checkers, Chess, CurrencyConverter, Documents, Email, Files, Game2048, GeminiChat, Minesweeper, Notepad, type PdfPreviewData, PomodoroTimer, Preview, Spreadsheet, Sudoku, Tetris, TodoList, Weather, WorldClock, bundledApps, documentApps, gameApps, googleApps, openFilesInTrashMode, setPdfPreview, utilityApps, webApps };
@@ -1,5 +1,5 @@
1
- export { openFilesInTrashMode } from '../chunk-MTLVXT2C.js';
2
- export { setPdfPreview } from '../chunk-DUUANLLE.js';
1
+ export { openFilesInTrashMode } from '../chunk-6AJUSDEM.js';
2
+ export { setPdfPreview } from '../chunk-QBH7KERS.js';
3
3
  import '../chunk-KUIPWCTJ.js';
4
4
  import '../chunk-WIJ45SYD.js';
5
5
  import '../chunk-7M3BBAHQ.js';
@@ -9,22 +9,23 @@ import { lazy } from 'react';
9
9
  var Calculator = lazy(() => import('../Calculator-ZKEH53OV.js'));
10
10
  var Spreadsheet = lazy(() => import('../Spreadsheet-MKXPPSKV.js'));
11
11
  var Weather = lazy(() => import('../Weather-YXSCSPQT.js'));
12
- var CurrencyConverter = lazy(() => import('../CurrencyConverter-TXBFDFG2.js'));
13
- var PomodoroTimer = lazy(() => import('../PomodoroTimer-PRP5CZ3S.js'));
12
+ var CurrencyConverter = lazy(() => import('../CurrencyConverter-5N44NZ6Z.js'));
13
+ var PomodoroTimer = lazy(() => import('../PomodoroTimer-FHSOLF3O.js'));
14
14
  var Notepad = lazy(() => import('../Notepad-74CQPZCV.js'));
15
- var WorldClock = lazy(() => import('../WorldClock-QO5PVJQQ.js'));
15
+ var WorldClock = lazy(() => import('../WorldClock-XHM7WAUV.js'));
16
+ var TodoList = lazy(() => import('../TodoList-7JZ2SLDI.js'));
16
17
  var Chess = lazy(() => import('../Chess-C5BY45NA.js'));
17
18
  var Checkers = lazy(() => import('../Checkers-MIAHIKJH.js'));
18
19
  var Sudoku = lazy(() => import('../Sudoku-XHLYCEVT.js'));
19
20
  var Tetris = lazy(() => import('../Tetris-ZHCZYL24.js'));
20
21
  var Game2048 = lazy(() => import('../Game2048-3RH3ELRD.js'));
21
22
  var Minesweeper = lazy(() => import('../Minesweeper-QGUPDVRS.js'));
22
- var Email = lazy(() => import('../Email-HRBZUWPY.js'));
23
- var GeminiChat = lazy(() => import('../GeminiChat-ITU46EH4.js'));
24
- var Calendar = lazy(() => import('../Calendar-4UQDQ3NT.js'));
25
- var Preview = lazy(() => import('../Preview-4MBQI66Q.js'));
23
+ var Email = lazy(() => import('../Email-CR6XS2AD.js'));
24
+ var GeminiChat = lazy(() => import('../GeminiChat-XTEBZIVK.js'));
25
+ var Calendar = lazy(() => import('../Calendar-PKRZ5MBU.js'));
26
+ var Preview = lazy(() => import('../Preview-B5DUW2AR.js'));
26
27
  var Documents = lazy(() => import('../Documents-CQVIIFZV.js'));
27
- var Files = lazy(() => import('../Files-ITIKVHIE.js'));
28
+ var Files = lazy(() => import('../Files-CEID4TC3.js'));
28
29
  var Browser = lazy(() => import('../Browser-LSJORULM.js'));
29
30
  var utilityApps = {
30
31
  "/calculator": { component: Calculator, label: "Calculator", size: "sm", allowPinOnTop: true, utility: true, widget: true, autoHeight: true, dimensions: [280, 420] },
@@ -33,7 +34,8 @@ var utilityApps = {
33
34
  "/weather": { component: Weather, label: "Weather", size: "sm", utility: true, widget: true, autoHeight: true, dimensions: [320, 400] },
34
35
  "/currency": { component: CurrencyConverter, label: "Currency Converter", size: "sm", utility: true, widget: true, autoHeight: true, dimensions: [320, 480] },
35
36
  "/pomodoro": { component: PomodoroTimer, label: "Pomodoro Timer", size: "sm", utility: true, widget: true, autoHeight: true, dimensions: [320, 600] },
36
- "/world-clock": { component: WorldClock, label: "World Clock", size: "sm", utility: true, widget: true, autoHeight: true, dimensions: [320, 480] }
37
+ "/world-clock": { component: WorldClock, label: "World Clock", size: "sm", utility: true, widget: true, autoHeight: true, dimensions: [320, 480] },
38
+ "/todo": { component: TodoList, label: "Todo List", size: "md", dimensions: [560, 640] }
37
39
  };
38
40
  var gameApps = {
39
41
  "/chess": { component: Chess, label: "Chess", size: "lg", compact: true },
@@ -64,6 +66,6 @@ var bundledApps = {
64
66
  ...webApps
65
67
  };
66
68
 
67
- export { Browser, Calculator, Calendar, Checkers, Chess, CurrencyConverter, Documents, Email, Files, Game2048, GeminiChat, Minesweeper, Notepad, PomodoroTimer, Preview, Spreadsheet, Sudoku, Tetris, Weather, WorldClock, bundledApps, documentApps, gameApps, googleApps, utilityApps, webApps };
69
+ export { Browser, Calculator, Calendar, Checkers, Chess, CurrencyConverter, Documents, Email, Files, Game2048, GeminiChat, Minesweeper, Notepad, PomodoroTimer, Preview, Spreadsheet, Sudoku, Tetris, TodoList, Weather, WorldClock, bundledApps, documentApps, gameApps, googleApps, utilityApps, webApps };
68
70
  //# sourceMappingURL=index.js.map
69
71
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/apps/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Bundled apps — pre-built window registry entries for the 16 apps that ship\n * with `react-os-shell`. Consumers compose them into their own registry via\n * `createWindowRegistry`:\n *\n * import { createWindowRegistry } from 'react-os-shell';\n * import { bundledApps } from 'react-os-shell/apps';\n * import { erpEntities } from './shell-config';\n *\n * const windows = createWindowRegistry(bundledApps, erpEntities);\n *\n * Subsets are also exported (`utilityApps`, `gameApps`, `googleApps`) so a\n * consumer can pick-and-choose without importing every component.\n *\n * NOTE: 3 apps require consumer-supplied persistence (Calendar / Notepad for\n * stored content, Minesweeper for leaderboard). They're exported individually\n * but absent from `bundledApps` — wire the prefs provider to opt them in.\n * WorldClock uses `useShellPrefs()` so it lives in `bundledApps`; without a\n * consumer-supplied prefs adapter the city list won't survive a reload.\n */\nimport { lazy } from 'react';\nimport type { WindowRegistry } from '../windowRegistry/types';\n\n// ── Utility apps ──\nconst Calculator = lazy(() => import('./Calculator'));\nconst Spreadsheet = lazy(() => import('./Spreadsheet'));\nconst Weather = lazy(() => import('./Weather'));\nconst CurrencyConverter = lazy(() => import('./CurrencyConverter'));\nconst PomodoroTimer = lazy(() => import('./PomodoroTimer'));\nconst Notepad = lazy(() => import('./Notepad'));\nconst WorldClock = lazy(() => import('./WorldClock'));\n\n// ── Games ──\nconst Chess = lazy(() => import('./Chess'));\nconst Checkers = lazy(() => import('./Checkers'));\nconst Sudoku = lazy(() => import('./Sudoku'));\nconst Tetris = lazy(() => import('./Tetris'));\nconst Game2048 = lazy(() => import('./Game2048'));\nconst Minesweeper = lazy(() => import('./Minesweeper'));\n\n// ── Google apps ──\nconst Email = lazy(() => import('./Email'));\nconst GeminiChat = lazy(() => import('./GeminiChat'));\nconst Calendar = lazy(() => import('./Calendar'));\n\n// ── Document apps ──\nconst Preview = lazy(() => import('./Preview'));\nconst Documents = lazy(() => import('./Documents'));\nconst Files = lazy(() => import('./Files'));\n\n// ── Web ──\nconst Browser = lazy(() => import('./Browser'));\n\nexport const utilityApps: WindowRegistry = {\n '/calculator': { component: Calculator, label: 'Calculator', size: 'sm', allowPinOnTop: true, utility: true, widget: true, autoHeight: true, dimensions: [280, 420] },\n '/spreadsheet': { component: Spreadsheet, label: 'Spreadsheets', size: '2xl', appStyle: true, multiInstance: true },\n '/notepad': { component: Notepad, label: 'Notepad', size: 'lg', allowPinOnTop: true },\n '/weather': { component: Weather, label: 'Weather', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 400] },\n '/currency': { component: CurrencyConverter, label: 'Currency Converter', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 480] },\n '/pomodoro': { component: PomodoroTimer, label: 'Pomodoro Timer', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 600] },\n '/world-clock': { component: WorldClock, label: 'World Clock', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 480] },\n};\n\nexport const gameApps: WindowRegistry = {\n '/chess': { component: Chess, label: 'Chess', size: 'lg', compact: true },\n '/checkers': { component: Checkers, label: 'Checkers', size: 'lg', compact: true },\n '/sudoku': { component: Sudoku, label: 'Sudoku', size: 'sm', compact: true, dimensions: [360, 535] },\n '/tetris': { component: Tetris, label: 'Tetris', size: 'md', compact: true, dimensions: [452, 618] },\n '/2048': { component: Game2048, label: '2048', size: 'sm', compact: true },\n '/minesweeper': { component: Minesweeper, label: 'Minesweeper', size: 'sm', compact: true },\n};\n\nexport const googleApps: WindowRegistry = {\n '/email': { component: Email, label: 'Email', size: '2xl', appStyle: true },\n '/gemini': { component: GeminiChat, label: 'Gemini AI', size: 'lg' },\n '/calendar': { component: Calendar, label: 'Calendar', size: 'xl' },\n};\n\nexport const documentApps: WindowRegistry = {\n '/preview': { component: Preview, label: 'Preview', size: '2xl', appStyle: true, multiInstance: true },\n '/documents': { component: Documents, label: 'Documents', size: 'xl', appStyle: true, multiInstance: true },\n '/files': { component: Files, label: 'Files', size: 'xl', appStyle: true },\n};\n\nexport const webApps: WindowRegistry = {\n '/browser': { component: Browser, label: 'Browser', size: '2xl', appStyle: true, multiInstance: true },\n};\n\nexport const bundledApps: WindowRegistry = {\n ...utilityApps,\n ...gameApps,\n ...googleApps,\n ...documentApps,\n ...webApps,\n};\n\nexport {\n Calculator,\n Spreadsheet,\n Notepad,\n Weather,\n CurrencyConverter,\n PomodoroTimer,\n WorldClock,\n Chess,\n Checkers,\n Sudoku,\n Tetris,\n Game2048,\n Minesweeper,\n Email,\n GeminiChat,\n Calendar,\n Preview,\n Documents,\n Files,\n Browser,\n};\n\nexport { setPdfPreview } from './Preview';\nexport { openFilesInTrashMode } from './Files';\nexport type { PdfPreviewData } from './Preview';\n"]}
1
+ {"version":3,"sources":["../../src/apps/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Bundled apps — pre-built window registry entries for the 16 apps that ship\n * with `react-os-shell`. Consumers compose them into their own registry via\n * `createWindowRegistry`:\n *\n * import { createWindowRegistry } from 'react-os-shell';\n * import { bundledApps } from 'react-os-shell/apps';\n * import { erpEntities } from './shell-config';\n *\n * const windows = createWindowRegistry(bundledApps, erpEntities);\n *\n * Subsets are also exported (`utilityApps`, `gameApps`, `googleApps`) so a\n * consumer can pick-and-choose without importing every component.\n *\n * NOTE: 3 apps require consumer-supplied persistence (Calendar / Notepad for\n * stored content, Minesweeper for leaderboard). They're exported individually\n * but absent from `bundledApps` — wire the prefs provider to opt them in.\n * WorldClock uses `useShellPrefs()` so it lives in `bundledApps`; without a\n * consumer-supplied prefs adapter the city list won't survive a reload.\n */\nimport { lazy } from 'react';\nimport type { WindowRegistry } from '../windowRegistry/types';\n\n// ── Utility apps ──\nconst Calculator = lazy(() => import('./Calculator'));\nconst Spreadsheet = lazy(() => import('./Spreadsheet'));\nconst Weather = lazy(() => import('./Weather'));\nconst CurrencyConverter = lazy(() => import('./CurrencyConverter'));\nconst PomodoroTimer = lazy(() => import('./PomodoroTimer'));\nconst Notepad = lazy(() => import('./Notepad'));\nconst WorldClock = lazy(() => import('./WorldClock'));\nconst TodoList = lazy(() => import('./TodoList'));\n\n// ── Games ──\nconst Chess = lazy(() => import('./Chess'));\nconst Checkers = lazy(() => import('./Checkers'));\nconst Sudoku = lazy(() => import('./Sudoku'));\nconst Tetris = lazy(() => import('./Tetris'));\nconst Game2048 = lazy(() => import('./Game2048'));\nconst Minesweeper = lazy(() => import('./Minesweeper'));\n\n// ── Google apps ──\nconst Email = lazy(() => import('./Email'));\nconst GeminiChat = lazy(() => import('./GeminiChat'));\nconst Calendar = lazy(() => import('./Calendar'));\n\n// ── Document apps ──\nconst Preview = lazy(() => import('./Preview'));\nconst Documents = lazy(() => import('./Documents'));\nconst Files = lazy(() => import('./Files'));\n\n// ── Web ──\nconst Browser = lazy(() => import('./Browser'));\n\nexport const utilityApps: WindowRegistry = {\n '/calculator': { component: Calculator, label: 'Calculator', size: 'sm', allowPinOnTop: true, utility: true, widget: true, autoHeight: true, dimensions: [280, 420] },\n '/spreadsheet': { component: Spreadsheet, label: 'Spreadsheets', size: '2xl', appStyle: true, multiInstance: true },\n '/notepad': { component: Notepad, label: 'Notepad', size: 'lg', allowPinOnTop: true },\n '/weather': { component: Weather, label: 'Weather', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 400] },\n '/currency': { component: CurrencyConverter, label: 'Currency Converter', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 480] },\n '/pomodoro': { component: PomodoroTimer, label: 'Pomodoro Timer', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 600] },\n '/world-clock': { component: WorldClock, label: 'World Clock', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 480] },\n '/todo': { component: TodoList, label: 'Todo List', size: 'md', dimensions: [560, 640] },\n};\n\nexport const gameApps: WindowRegistry = {\n '/chess': { component: Chess, label: 'Chess', size: 'lg', compact: true },\n '/checkers': { component: Checkers, label: 'Checkers', size: 'lg', compact: true },\n '/sudoku': { component: Sudoku, label: 'Sudoku', size: 'sm', compact: true, dimensions: [360, 535] },\n '/tetris': { component: Tetris, label: 'Tetris', size: 'md', compact: true, dimensions: [452, 618] },\n '/2048': { component: Game2048, label: '2048', size: 'sm', compact: true },\n '/minesweeper': { component: Minesweeper, label: 'Minesweeper', size: 'sm', compact: true },\n};\n\nexport const googleApps: WindowRegistry = {\n '/email': { component: Email, label: 'Email', size: '2xl', appStyle: true },\n '/gemini': { component: GeminiChat, label: 'Gemini AI', size: 'lg' },\n '/calendar': { component: Calendar, label: 'Calendar', size: 'xl' },\n};\n\nexport const documentApps: WindowRegistry = {\n '/preview': { component: Preview, label: 'Preview', size: '2xl', appStyle: true, multiInstance: true },\n '/documents': { component: Documents, label: 'Documents', size: 'xl', appStyle: true, multiInstance: true },\n '/files': { component: Files, label: 'Files', size: 'xl', appStyle: true },\n};\n\nexport const webApps: WindowRegistry = {\n '/browser': { component: Browser, label: 'Browser', size: '2xl', appStyle: true, multiInstance: true },\n};\n\nexport const bundledApps: WindowRegistry = {\n ...utilityApps,\n ...gameApps,\n ...googleApps,\n ...documentApps,\n ...webApps,\n};\n\nexport {\n Calculator,\n Spreadsheet,\n Notepad,\n Weather,\n CurrencyConverter,\n PomodoroTimer,\n WorldClock,\n TodoList,\n Chess,\n Checkers,\n Sudoku,\n Tetris,\n Game2048,\n Minesweeper,\n Email,\n GeminiChat,\n Calendar,\n Preview,\n Documents,\n Files,\n Browser,\n};\n\nexport { setPdfPreview } from './Preview';\nexport { openFilesInTrashMode } from './Files';\nexport type { PdfPreviewData } from './Preview';\n"]}
@@ -0,0 +1,90 @@
1
+ import { useShellPrefs } from './chunk-36VM54SC.js';
2
+ import { useMemo, useCallback } from 'react';
3
+
4
+ var POMODORO_LEGACY_KEY = "pomodoro_tasks";
5
+ var POMODORO_LEGACY_MIGRATED_FLAG = "pomodoro_tasks_migrated";
6
+ function uid() {
7
+ return Math.random().toString(36).slice(2, 11);
8
+ }
9
+ function nowIso() {
10
+ return (/* @__PURE__ */ new Date()).toISOString();
11
+ }
12
+ function useTodoTasks() {
13
+ const { prefs, save } = useShellPrefs();
14
+ const tasks = useMemo(() => {
15
+ const raw = prefs.todo_tasks;
16
+ return Array.isArray(raw) ? raw : [];
17
+ }, [prefs.todo_tasks]);
18
+ const writeTasks = useCallback((next) => {
19
+ save({ todo_tasks: next });
20
+ }, [save]);
21
+ const addTask = useCallback((input) => {
22
+ const id = uid();
23
+ const ts = nowIso();
24
+ const task = {
25
+ done: false,
26
+ ...input,
27
+ // Ensure name is trimmed and id/timestamps overwrite anything the
28
+ // caller might have passed in.
29
+ name: input.name.trim(),
30
+ id,
31
+ createdAt: ts,
32
+ updatedAt: ts
33
+ };
34
+ writeTasks([...tasks, task]);
35
+ return id;
36
+ }, [tasks, writeTasks]);
37
+ const updateTask = useCallback((id, patch) => {
38
+ const next = tasks.map((t) => t.id === id ? { ...t, ...patch, id: t.id, updatedAt: nowIso() } : t);
39
+ writeTasks(next);
40
+ }, [tasks, writeTasks]);
41
+ const removeTask = useCallback((id) => {
42
+ writeTasks(tasks.filter((t) => t.id !== id));
43
+ }, [tasks, writeTasks]);
44
+ const toggleDone = useCallback((id) => {
45
+ const target = tasks.find((t) => t.id === id);
46
+ if (!target) return;
47
+ updateTask(id, { done: !target.done });
48
+ }, [tasks, updateTask]);
49
+ return { tasks, addTask, updateTask, removeTask, toggleDone, setAllTasks: writeTasks };
50
+ }
51
+ function migratePomodoroTasksOnce(currentTasks, setAllTasks) {
52
+ try {
53
+ if (localStorage.getItem(POMODORO_LEGACY_MIGRATED_FLAG)) return;
54
+ const raw = localStorage.getItem(POMODORO_LEGACY_KEY);
55
+ if (!raw) {
56
+ localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, "1");
57
+ return;
58
+ }
59
+ const legacy = JSON.parse(raw);
60
+ if (!Array.isArray(legacy) || legacy.length === 0) {
61
+ localStorage.removeItem(POMODORO_LEGACY_KEY);
62
+ localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, "1");
63
+ return;
64
+ }
65
+ const ts = nowIso();
66
+ const migrated = legacy.filter((t) => typeof t?.name === "string").map((t) => ({
67
+ id: t.id || uid(),
68
+ name: String(t.name),
69
+ done: !!t.done,
70
+ estimated: typeof t.estimated === "number" ? t.estimated : void 0,
71
+ completed: typeof t.completed === "number" ? t.completed : void 0,
72
+ createdAt: ts,
73
+ updatedAt: ts
74
+ }));
75
+ const existingIds = new Set(currentTasks.map((t) => t.id));
76
+ const additions = migrated.filter((t) => !existingIds.has(t.id));
77
+ setAllTasks([...additions, ...currentTasks]);
78
+ localStorage.removeItem(POMODORO_LEGACY_KEY);
79
+ localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, "1");
80
+ } catch {
81
+ try {
82
+ localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, "1");
83
+ } catch {
84
+ }
85
+ }
86
+ }
87
+
88
+ export { migratePomodoroTasksOnce, useTodoTasks };
89
+ //# sourceMappingURL=chunk-25L4DIKH.js.map
90
+ //# sourceMappingURL=chunk-25L4DIKH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/apps/_todoStore.ts"],"names":[],"mappings":"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","file":"chunk-25L4DIKH.js","sourcesContent":["/**\n * Shared task store — wraps `useShellPrefs()` so the Todo List app, the\n * Pomodoro widget, and the Calendar app all read/write the same array\n * at `prefs.todo_tasks`. Mutations bump `updatedAt` so Google-Tasks\n * sync (when enabled) can use last-write-wins conflict resolution.\n *\n * `migratePomodoroTasksOnce()` is a one-shot escape hatch: when the\n * Pomodoro widget mounts the first time after this refactor, it copies\n * any existing tasks from the legacy `localStorage.pomodoro_tasks` key\n * into the shared store and removes the old key. After that mount it's\n * a no-op.\n */\n\nimport { useCallback, useMemo } from 'react';\nimport { useShellPrefs } from '../shell/ShellPrefs';\nimport type { TodoTask } from './_todoTypes';\n\nconst POMODORO_LEGACY_KEY = 'pomodoro_tasks';\nconst POMODORO_LEGACY_MIGRATED_FLAG = 'pomodoro_tasks_migrated';\n\nfunction uid(): string {\n return Math.random().toString(36).slice(2, 11);\n}\n\nfunction nowIso(): string {\n return new Date().toISOString();\n}\n\nexport interface UseTodoTasks {\n tasks: TodoTask[];\n /** Add a new task. Returns the id of the freshly-added task. */\n addTask: (input: Partial<Omit<TodoTask, 'id' | 'createdAt' | 'updatedAt'>> & { name: string }) => string;\n /** Patch any subset of fields on a task by id. `updatedAt` is auto-bumped. */\n updateTask: (id: string, patch: Partial<TodoTask>) => void;\n /** Remove a task by id. Used by both Pomodoro's kebab menu and TodoList's delete action. */\n removeTask: (id: string) => void;\n /** Flip `done`. Same as `updateTask(id, { done: !done })` but faster to type at call sites. */\n toggleDone: (id: string) => void;\n /** Replace the entire list. Used by Google Tasks sync after a pull. */\n setAllTasks: (tasks: TodoTask[]) => void;\n}\n\nexport function useTodoTasks(): UseTodoTasks {\n const { prefs, save } = useShellPrefs();\n const tasks: TodoTask[] = useMemo(() => {\n const raw = prefs.todo_tasks;\n return Array.isArray(raw) ? (raw as TodoTask[]) : [];\n }, [prefs.todo_tasks]);\n\n const writeTasks = useCallback((next: TodoTask[]) => {\n save({ todo_tasks: next });\n }, [save]);\n\n const addTask = useCallback<UseTodoTasks['addTask']>((input) => {\n const id = uid();\n const ts = nowIso();\n const task: TodoTask = {\n done: false,\n ...input,\n // Ensure name is trimmed and id/timestamps overwrite anything the\n // caller might have passed in.\n name: input.name.trim(),\n id,\n createdAt: ts,\n updatedAt: ts,\n };\n writeTasks([...tasks, task]);\n return id;\n }, [tasks, writeTasks]);\n\n const updateTask = useCallback<UseTodoTasks['updateTask']>((id, patch) => {\n const next = tasks.map(t => t.id === id ? { ...t, ...patch, id: t.id, updatedAt: nowIso() } : t);\n writeTasks(next);\n }, [tasks, writeTasks]);\n\n const removeTask = useCallback<UseTodoTasks['removeTask']>((id) => {\n writeTasks(tasks.filter(t => t.id !== id));\n }, [tasks, writeTasks]);\n\n const toggleDone = useCallback<UseTodoTasks['toggleDone']>((id) => {\n const target = tasks.find(t => t.id === id);\n if (!target) return;\n updateTask(id, { done: !target.done });\n }, [tasks, updateTask]);\n\n return { tasks, addTask, updateTask, removeTask, toggleDone, setAllTasks: writeTasks };\n}\n\n/**\n * One-time migration: pull any tasks the Pomodoro widget previously\n * persisted to `localStorage.pomodoro_tasks` into the shared store.\n * Called from PomodoroTimer's mount effect — safe to invoke on every\n * mount, since the migrated flag stays set after the first run.\n *\n * Pass `setAllTasks` from `useTodoTasks()` so the migration can fold\n * the legacy entries in alongside any tasks the user has already added\n * elsewhere (i.e. via the new TodoList app).\n */\nexport function migratePomodoroTasksOnce(\n currentTasks: TodoTask[],\n setAllTasks: (next: TodoTask[]) => void,\n): void {\n try {\n if (localStorage.getItem(POMODORO_LEGACY_MIGRATED_FLAG)) return;\n const raw = localStorage.getItem(POMODORO_LEGACY_KEY);\n if (!raw) {\n localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1');\n return;\n }\n const legacy: Array<{ id?: string; name?: string; estimated?: number; completed?: number; done?: boolean }>\n = JSON.parse(raw);\n if (!Array.isArray(legacy) || legacy.length === 0) {\n localStorage.removeItem(POMODORO_LEGACY_KEY);\n localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1');\n return;\n }\n const ts = nowIso();\n const migrated: TodoTask[] = legacy\n .filter(t => typeof t?.name === 'string')\n .map(t => ({\n id: t.id || uid(),\n name: String(t.name),\n done: !!t.done,\n estimated: typeof t.estimated === 'number' ? t.estimated : undefined,\n completed: typeof t.completed === 'number' ? t.completed : undefined,\n createdAt: ts,\n updatedAt: ts,\n }));\n // Fold migrated tasks in first so the legacy list keeps its position\n // ahead of anything the user added via the new app.\n const existingIds = new Set(currentTasks.map(t => t.id));\n const additions = migrated.filter(t => !existingIds.has(t.id));\n setAllTasks([...additions, ...currentTasks]);\n localStorage.removeItem(POMODORO_LEGACY_KEY);\n localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1');\n } catch {\n // Don't block startup on corrupt localStorage — just mark it migrated.\n try { localStorage.setItem(POMODORO_LEGACY_MIGRATED_FLAG, '1'); } catch {}\n }\n}\n"]}
@@ -81,7 +81,24 @@ function getDemoCalendarEvents() {
81
81
  function isDemoMode() {
82
82
  return typeof window !== "undefined" && window.__REACT_OS_SHELL_DEMO_MODE__ === true;
83
83
  }
84
+ function getDemoTasks() {
85
+ const now = /* @__PURE__ */ new Date();
86
+ const ts = now.toISOString();
87
+ const dateAt = (dayOffset) => {
88
+ const d = new Date(now);
89
+ d.setDate(now.getDate() + dayOffset);
90
+ return d.toISOString().split("T")[0];
91
+ };
92
+ return [
93
+ { id: "demo-todo-1", name: "Review pull request", done: false, dueDate: dateAt(0), estimated: 2, completed: 1, createdAt: ts, updatedAt: ts },
94
+ { id: "demo-todo-2", name: "Draft the Q2 retrospective", done: false, dueDate: dateAt(0), estimated: 3, completed: 0, createdAt: ts, updatedAt: ts },
95
+ { id: "demo-todo-3", name: "Buy birthday card for Maya", done: false, dueDate: dateAt(2), createdAt: ts, updatedAt: ts },
96
+ { id: "demo-todo-4", name: "Update onboarding doc", done: false, dueDate: dateAt(5), estimated: 4, completed: 0, createdAt: ts, updatedAt: ts },
97
+ { id: "demo-todo-5", name: "Reply to investor email", done: true, estimated: 1, completed: 1, createdAt: ts, updatedAt: ts },
98
+ { id: "demo-todo-6", name: 'Read "Working in Public"', done: false, createdAt: ts, updatedAt: ts }
99
+ ];
100
+ }
84
101
 
85
- export { getDemoCalendarEvents, getDemoEmails, isDemoMode };
86
- //# sourceMappingURL=chunk-62MVMTBT.js.map
87
- //# sourceMappingURL=chunk-62MVMTBT.js.map
102
+ export { getDemoCalendarEvents, getDemoEmails, getDemoTasks, isDemoMode };
103
+ //# sourceMappingURL=chunk-5VXRBUEH.js.map
104
+ //# sourceMappingURL=chunk-5VXRBUEH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/apps/google-demo-fixtures.ts"],"names":[],"mappings":"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","file":"chunk-5VXRBUEH.js","sourcesContent":["/**\n * Demo-mode fixtures for the Google apps (Email, Calendar). Used when\n * `window.__REACT_OS_SHELL_DEMO_MODE__ === true` so the demo deployment\n * can show populated UIs without requiring a Google OAuth Client ID.\n *\n * Imported only by the demo-mode renderers — the real Gmail/Calendar\n * code paths never touch this file.\n */\n\nexport interface DemoEmail {\n id: string;\n from: string;\n subject: string;\n snippet: string;\n body: string;\n receivedAt: string; // relative to now\n unread: boolean;\n}\n\n// Shape matches Calendar.tsx's CalendarEvent so demo fixtures can be\n// dropped straight into its events list without translation.\nexport interface DemoCalendarEvent {\n id: string;\n title: string;\n date: string; // YYYY-MM-DD\n start_time?: string; // HH:MM\n end_time?: string; // HH:MM\n color: string; // matches the COLORS keys in Calendar.tsx\n description?: string;\n}\n\n// Shape matches TodoTask in `_todoTypes.ts` — used by the Todo List app's\n// demo-mode fallback when the user hasn't connected Google.\nexport interface DemoTodoTask {\n id: string;\n name: string;\n done: boolean;\n dueDate?: string; // YYYY-MM-DD\n estimated?: number;\n completed?: number;\n notes?: string;\n createdAt: string;\n updatedAt: string;\n}\n\nexport function getDemoEmails(): DemoEmail[] {\n const now = Date.now();\n const m = (mins: number) => new Date(now - mins * 60_000).toISOString();\n return [\n {\n id: 'demo-1',\n from: 'Calendar <calendar-noreply@example.com>',\n subject: 'Reminder: Design review at 3:00 PM',\n snippet: 'You have a design review starting in 30 minutes with the platform team…',\n body: 'You have a design review starting in 30 minutes with the platform team. Agenda is in the doc — please skim before joining.',\n receivedAt: m(15),\n unread: true,\n },\n {\n id: 'demo-2',\n from: 'Sam Patel <sam@example.com>',\n subject: 'Re: STEP file from procurement',\n snippet: \"Got it — I'll drop the file in the shared folder by EOD. Let me know if the cap thickness needs to change.\",\n body: \"Got it — I'll drop the file in the shared folder by EOD. Let me know if the cap thickness needs to change.\\n\\nThanks,\\nSam\",\n receivedAt: m(85),\n unread: true,\n },\n {\n id: 'demo-3',\n from: 'GitHub <noreply@github.com>',\n subject: '[react-os-shell] PR #42 ready for review',\n snippet: 'A new pull request has been opened in your repository react-os-shell.',\n body: 'A new pull request has been opened in your repository react-os-shell.\\n\\n#42: feat(preview): capped section view\\n\\nView on GitHub: https://github.com/...',\n receivedAt: m(180),\n unread: false,\n },\n {\n id: 'demo-4',\n from: 'Stripe <noreply@stripe.com>',\n subject: 'Your Stripe payout has been processed',\n snippet: 'Your payout of $1,247.32 has been deposited to your bank account.',\n body: 'Your payout of $1,247.32 has been deposited to your bank account ending in 4242.\\n\\nView details in your Dashboard.',\n receivedAt: m(310),\n unread: false,\n },\n {\n id: 'demo-5',\n from: 'Maya Lin <maya.lin@example.com>',\n subject: 'Lunch tomorrow?',\n snippet: 'I have a couple options open — that ramen place on 4th, or the new Korean place near you?',\n body: 'I have a couple options open — that ramen place on 4th, or the new Korean place near you? 12:30?',\n receivedAt: m(720),\n unread: false,\n },\n {\n id: 'demo-6',\n from: 'AWS Billing <no-reply@aws.amazon.com>',\n subject: 'Your monthly AWS invoice',\n snippet: 'Your invoice for the period ending Apr 30 is now available.',\n body: 'Your invoice for the period ending April 30 is now available in the AWS console. Total: $84.21.',\n receivedAt: m(1440),\n unread: false,\n },\n ];\n}\n\n// 6 events scattered across the current week. The dates are recomputed\n// relative to \"now\" each time the function runs, so the demo always\n// feels current.\nexport function getDemoCalendarEvents(): DemoCalendarEvent[] {\n const now = new Date();\n const dayOfWeek = now.getDay();\n const weekStart = new Date(now);\n weekStart.setDate(now.getDate() - dayOfWeek);\n const dateAt = (dayOffset: number) => {\n const d = new Date(weekStart);\n d.setDate(weekStart.getDate() + dayOffset);\n return d.toISOString().split('T')[0];\n };\n return [\n { id: 'demo-event-1', title: 'Standup', date: dateAt(1), start_time: '09:30', end_time: '10:00', color: 'blue' },\n { id: 'demo-event-2', title: 'Design review', date: dateAt(2), start_time: '15:00', end_time: '16:00', color: 'purple', description: 'Platform team — Conference Room B' },\n { id: 'demo-event-3', title: 'Lunch with Maya', date: dateAt(3), start_time: '12:30', end_time: '13:30', color: 'orange', description: 'Ramen on 4th' },\n { id: 'demo-event-4', title: '1:1 with manager',date: dateAt(3), start_time: '16:00', end_time: '16:30', color: 'green' },\n { id: 'demo-event-5', title: 'Sprint planning', date: dateAt(4), start_time: '10:00', end_time: '11:30', color: 'pink' },\n { id: 'demo-event-6', title: 'Focus time', date: dateAt(5), start_time: '14:00', end_time: '17:00', color: 'gray' },\n ];\n}\n\nexport function isDemoMode(): boolean {\n return typeof window !== 'undefined' && (window as any).__REACT_OS_SHELL_DEMO_MODE__ === true;\n}\n\n// Demo Todo tasks. Mix of completed / pending / due-today items so the\n// Todo List app, the Pomodoro widget, and the Calendar deadline badge\n// all have something to render in demo mode without a Google sign-in.\nexport function getDemoTasks(): DemoTodoTask[] {\n const now = new Date();\n const ts = now.toISOString();\n const dateAt = (dayOffset: number) => {\n const d = new Date(now);\n d.setDate(now.getDate() + dayOffset);\n return d.toISOString().split('T')[0];\n };\n return [\n { id: 'demo-todo-1', name: 'Review pull request', done: false, dueDate: dateAt(0), estimated: 2, completed: 1, createdAt: ts, updatedAt: ts },\n { id: 'demo-todo-2', name: 'Draft the Q2 retrospective', done: false, dueDate: dateAt(0), estimated: 3, completed: 0, createdAt: ts, updatedAt: ts },\n { id: 'demo-todo-3', name: 'Buy birthday card for Maya', done: false, dueDate: dateAt(2), createdAt: ts, updatedAt: ts },\n { id: 'demo-todo-4', name: 'Update onboarding doc', done: false, dueDate: dateAt(5), estimated: 4, completed: 0, createdAt: ts, updatedAt: ts },\n { id: 'demo-todo-5', name: 'Reply to investor email', done: true, estimated: 1, completed: 1, createdAt: ts, updatedAt: ts },\n { id: 'demo-todo-6', name: 'Read \"Working in Public\"', done: false, createdAt: ts, updatedAt: ts },\n ];\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { setPdfPreview } from './chunk-DUUANLLE.js';
1
+ import { setPdfPreview } from './chunk-QBH7KERS.js';
2
2
  import { toast_default } from './chunk-WIJ45SYD.js';
3
3
  import { useWindowManager, WindowTitle } from './chunk-7M3BBAHQ.js';
4
4
  import { confirm, prompt } from './chunk-PLGHQ7QW.js';
@@ -609,5 +609,5 @@ function Files() {
609
609
  }
610
610
 
611
611
  export { Files, openFilesInTrashMode };
612
- //# sourceMappingURL=chunk-MTLVXT2C.js.map
613
- //# sourceMappingURL=chunk-MTLVXT2C.js.map
612
+ //# sourceMappingURL=chunk-6AJUSDEM.js.map
613
+ //# sourceMappingURL=chunk-6AJUSDEM.js.map