react-os-shell 0.2.43 → 0.2.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/dist/{Browser-5ZCLRIRU.js → Browser-LSJORULM.js} +3 -3
  2. package/dist/{Browser-5ZCLRIRU.js.map → Browser-LSJORULM.js.map} +1 -1
  3. package/dist/{Calculator-OHL2AZ52.js → Calculator-ZKEH53OV.js} +4 -4
  4. package/dist/{Calculator-OHL2AZ52.js.map → Calculator-ZKEH53OV.js.map} +1 -1
  5. package/dist/{Calendar-6AHL3UJY.js → Calendar-4UQDQ3NT.js} +3 -3
  6. package/dist/{Calendar-6AHL3UJY.js.map → Calendar-4UQDQ3NT.js.map} +1 -1
  7. package/dist/{CurrencyConverter-XZVZ7XOF.js → CurrencyConverter-TXBFDFG2.js} +56 -50
  8. package/dist/CurrencyConverter-TXBFDFG2.js.map +1 -0
  9. package/dist/{Documents-IPVZ47JX.js → Documents-CQVIIFZV.js} +3 -3
  10. package/dist/{Documents-IPVZ47JX.js.map → Documents-CQVIIFZV.js.map} +1 -1
  11. package/dist/{Email-Z7FDKAFD.js → Email-HRBZUWPY.js} +3 -3
  12. package/dist/{Email-Z7FDKAFD.js.map → Email-HRBZUWPY.js.map} +1 -1
  13. package/dist/Files-ITIKVHIE.js +8 -0
  14. package/dist/{Files-KEHRZ2UY.js.map → Files-ITIKVHIE.js.map} +1 -1
  15. package/dist/{Minesweeper-NGN4O6C4.js → Minesweeper-QGUPDVRS.js} +3 -3
  16. package/dist/{Minesweeper-NGN4O6C4.js.map → Minesweeper-QGUPDVRS.js.map} +1 -1
  17. package/dist/{Notepad-W3YYZ3GS.js → Notepad-74CQPZCV.js} +3 -3
  18. package/dist/{Notepad-W3YYZ3GS.js.map → Notepad-74CQPZCV.js.map} +1 -1
  19. package/dist/PomodoroTimer-PRP5CZ3S.js +627 -0
  20. package/dist/PomodoroTimer-PRP5CZ3S.js.map +1 -0
  21. package/dist/Preview-4MBQI66Q.js +7 -0
  22. package/dist/{Preview-4354N46U.js.map → Preview-4MBQI66Q.js.map} +1 -1
  23. package/dist/{Spreadsheet-FCFII6DW.js → Spreadsheet-MKXPPSKV.js} +3 -3
  24. package/dist/{Spreadsheet-FCFII6DW.js.map → Spreadsheet-MKXPPSKV.js.map} +1 -1
  25. package/dist/Weather-YXSCSPQT.js +424 -0
  26. package/dist/Weather-YXSCSPQT.js.map +1 -0
  27. package/dist/WorldClock-QO5PVJQQ.js +250 -0
  28. package/dist/WorldClock-QO5PVJQQ.js.map +1 -0
  29. package/dist/apps/index.d.ts +6 -10
  30. package/dist/apps/index.js +18 -18
  31. package/dist/apps/index.js.map +1 -1
  32. package/dist/chunk-7CCHEEYC.js +94 -0
  33. package/dist/chunk-7CCHEEYC.js.map +1 -0
  34. package/dist/{chunk-T2NQXP2J.js → chunk-7M3BBAHQ.js} +10 -4
  35. package/dist/chunk-7M3BBAHQ.js.map +1 -0
  36. package/dist/{chunk-IY7JJVHR.js → chunk-DUUANLLE.js} +3 -3
  37. package/dist/{chunk-IY7JJVHR.js.map → chunk-DUUANLLE.js.map} +1 -1
  38. package/dist/chunk-MK3HLUO4.js +380 -0
  39. package/dist/chunk-MK3HLUO4.js.map +1 -0
  40. package/dist/{chunk-2SRU4BYH.js → chunk-MTLVXT2C.js} +4 -4
  41. package/dist/{chunk-2SRU4BYH.js.map → chunk-MTLVXT2C.js.map} +1 -1
  42. package/dist/{chunk-TVOBLSSV.js → chunk-UK2AA3J6.js} +3 -3
  43. package/dist/{chunk-TVOBLSSV.js.map → chunk-UK2AA3J6.js.map} +1 -1
  44. package/dist/index.d.ts +16 -1
  45. package/dist/index.js +4089 -11
  46. package/dist/index.js.map +1 -1
  47. package/package.json +1 -1
  48. package/dist/CurrencyConverter-XZVZ7XOF.js.map +0 -1
  49. package/dist/Files-KEHRZ2UY.js +0 -8
  50. package/dist/PomodoroTimer-T2J5NDJR.js +0 -196
  51. package/dist/PomodoroTimer-T2J5NDJR.js.map +0 -1
  52. package/dist/Preview-4354N46U.js +0 -7
  53. package/dist/Weather-XTADR7Z3.js +0 -266
  54. package/dist/Weather-XTADR7Z3.js.map +0 -1
  55. package/dist/WorldClock-OFK2EA2H.js +0 -126
  56. package/dist/WorldClock-OFK2EA2H.js.map +0 -1
  57. package/dist/chunk-7KZWBIDL.js +0 -4144
  58. package/dist/chunk-7KZWBIDL.js.map +0 -1
  59. package/dist/chunk-T2NQXP2J.js.map +0 -1
@@ -1,126 +0,0 @@
1
- import { ALL_TIMEZONES } from './chunk-7KZWBIDL.js';
2
- import './chunk-PDFQNHW7.js';
3
- import './chunk-NSU7OHPC.js';
4
- import './chunk-46LICZUM.js';
5
- import { useShellPrefs } from './chunk-36VM54SC.js';
6
- import './chunk-D7PYW2QS.js';
7
- import './chunk-WIJ45SYD.js';
8
- import { loadAppearance, WidgetSettingsModal } from './chunk-TVOBLSSV.js';
9
- import { useWidgetSettings } from './chunk-T2NQXP2J.js';
10
- import './chunk-PLGHQ7QW.js';
11
- import { useState, useEffect, useCallback } from 'react';
12
- import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
13
-
14
- var DEFAULT_CLOCKS = ["Europe/London", "Asia/Shanghai", "America/Los_Angeles", "America/New_York"];
15
- var SETTINGS_KEY = "world_clock_appearance";
16
- function WorldClock() {
17
- const [now, setNow] = useState(/* @__PURE__ */ new Date());
18
- const [appearance, setAppearance] = useState(() => loadAppearance(SETTINGS_KEY));
19
- const [settingsOpen, setSettingsOpen] = useState(false);
20
- const [configClocks, setConfigClocks] = useState([]);
21
- const [configAppearance, setConfigAppearance] = useState(appearance);
22
- const { prefs, save } = useShellPrefs();
23
- const worldClocks = prefs.world_clocks ?? DEFAULT_CLOCKS;
24
- useEffect(() => {
25
- const t = setInterval(() => setNow(/* @__PURE__ */ new Date()), 1e4);
26
- return () => clearInterval(t);
27
- }, []);
28
- useWidgetSettings(useCallback(() => {
29
- setConfigClocks([...worldClocks]);
30
- setConfigAppearance({ ...appearance });
31
- setSettingsOpen(true);
32
- }, [worldClocks, appearance]));
33
- const hourIn = (tz) => {
34
- try {
35
- const parts = new Intl.DateTimeFormat("en-US", { timeZone: tz, hour: "numeric", hour12: false }).formatToParts(now);
36
- const h = parseInt(parts.find((p) => p.type === "hour")?.value || "0", 10);
37
- return h === 24 ? 0 : h;
38
- } catch {
39
- return 12;
40
- }
41
- };
42
- const isDay = (tz) => {
43
- const h = hourIn(tz);
44
- return h >= 6 && h < 18;
45
- };
46
- const fmtTime = (tz) => now.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", timeZone: tz });
47
- const fmtOffset = (tz) => {
48
- const parts = new Intl.DateTimeFormat("en", { timeZone: tz, timeZoneName: "shortOffset" }).formatToParts(now);
49
- return parts.find((p) => p.type === "timeZoneName")?.value || "";
50
- };
51
- const fmtDate = (tz) => now.toLocaleDateString(void 0, { weekday: "short", month: "short", day: "numeric", timeZone: tz });
52
- const localTz = typeof localStorage !== "undefined" && localStorage.getItem("user_timezone") || Intl.DateTimeFormat().resolvedOptions().timeZone;
53
- const saveSettings = () => {
54
- if (configClocks.length === 0) return;
55
- save({ world_clocks: configClocks });
56
- setAppearance(configAppearance);
57
- localStorage.setItem(SETTINGS_KEY, JSON.stringify(configAppearance));
58
- setSettingsOpen(false);
59
- };
60
- const labelFor = (tz) => ALL_TIMEZONES.find((t) => t.tz === tz)?.label || tz.split("/").pop()?.replace(/_/g, " ") || tz;
61
- const cards = [{ tz: localTz, isLocal: true }, ...worldClocks.map((tz) => ({ tz, isLocal: false }))];
62
- const dynamicHeight = 96 + worldClocks.length * 84 + 16;
63
- return /* @__PURE__ */ jsxs(Fragment, { children: [
64
- /* @__PURE__ */ jsx(
65
- "div",
66
- {
67
- className: "flex flex-col rounded-lg text-white overflow-hidden",
68
- style: {
69
- minHeight: dynamicHeight,
70
- backgroundColor: `rgba(15, 23, 42, ${appearance.activeOpacity / 100})`,
71
- backdropFilter: appearance.activeBlur > 0 ? `blur(${appearance.activeBlur}px)` : void 0
72
- },
73
- children: /* @__PURE__ */ jsx("div", { className: "flex-1 flex flex-col gap-2 p-2", children: cards.map(({ tz, isLocal }) => {
74
- const day = isDay(tz);
75
- const rowBg = day ? "bg-gradient-to-br from-sky-400 via-sky-300 to-sky-500" : "bg-gradient-to-br from-slate-800 via-blue-950 to-slate-900";
76
- const sub = isLocal ? `${fmtDate(tz)} \xB7 ${tz.replace(/_/g, " ")}` : `${fmtDate(tz)} \xB7 ${fmtOffset(tz)}`;
77
- return /* @__PURE__ */ jsxs(
78
- "div",
79
- {
80
- className: `rounded-2xl px-4 py-3 flex items-center justify-between gap-3 ${rowBg}`,
81
- children: [
82
- /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
83
- isLocal && /* @__PURE__ */ jsx("div", { className: "text-[10px] uppercase tracking-wide opacity-80 mb-0.5", children: "Local Time" }),
84
- /* @__PURE__ */ jsx("div", { className: "text-base font-semibold leading-tight truncate", children: labelFor(tz) }),
85
- /* @__PURE__ */ jsx("div", { className: "text-[10px] opacity-90 truncate mt-0.5", children: sub })
86
- ] }),
87
- /* @__PURE__ */ jsx("div", { className: `${isLocal ? "text-3xl" : "text-2xl"} font-extralight leading-none tracking-tight tabular-nums shrink-0`, children: fmtTime(tz) })
88
- ]
89
- },
90
- (isLocal ? "local-" : "") + tz
91
- );
92
- }) })
93
- }
94
- ),
95
- /* @__PURE__ */ jsx(
96
- WidgetSettingsModal,
97
- {
98
- open: settingsOpen,
99
- onClose: () => setSettingsOpen(false),
100
- title: "World Clock Settings",
101
- appearance: configAppearance,
102
- onAppearanceChange: setConfigAppearance,
103
- onSave: saveSettings,
104
- children: /* @__PURE__ */ jsxs("div", { children: [
105
- /* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700 mb-2", children: "Cities" }),
106
- /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-1 max-h-56 overflow-y-auto", children: ALL_TIMEZONES.filter((t) => t.tz !== localTz).map(({ tz, label }) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm py-1 cursor-pointer hover:bg-gray-50 rounded px-2", children: [
107
- /* @__PURE__ */ jsx(
108
- "input",
109
- {
110
- type: "checkbox",
111
- checked: configClocks.includes(tz),
112
- onChange: () => setConfigClocks((prev) => prev.includes(tz) ? prev.filter((t) => t !== tz) : [...prev, tz]),
113
- className: "rounded border-gray-300 text-blue-600 focus:ring-blue-500 h-3.5 w-3.5"
114
- }
115
- ),
116
- label
117
- ] }, tz)) })
118
- ] })
119
- }
120
- )
121
- ] });
122
- }
123
-
124
- export { WorldClock as default };
125
- //# sourceMappingURL=WorldClock-OFK2EA2H.js.map
126
- //# sourceMappingURL=WorldClock-OFK2EA2H.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/apps/WorldClock.tsx"],"names":[],"mappings":"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","file":"WorldClock-OFK2EA2H.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 { ALL_TIMEZONES } from '../shell/Layout';\n\nconst DEFAULT_CLOCKS = ['Europe/London', 'Asia/Shanghai', 'America/Los_Angeles', 'America/New_York'];\nconst SETTINGS_KEY = 'world_clock_appearance';\n\n/**\n * World Clock widget — iOS-style city cards with a per-row day/night\n * gradient that flips based on the local hour at each city. Day cards use\n * a bright sky blue, night cards a deep navy — same palette as the\n * Weather widget so the two read as a set when stacked.\n *\n * Settings (city list + appearance sliders) live in the right-click menu\n * via `useWidgetSettings` — there is no inline \"+ Add World Clock\"\n * button. Translucency is applied as a background-color alpha on the\n * outer panel (slate-900 base) so the row gradients stay vivid even at\n * lower opacity.\n */\nexport default function WorldClock() {\n const [now, setNow] = useState(new Date());\n const [appearance, setAppearance] = useState(() => loadAppearance(SETTINGS_KEY));\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [configClocks, setConfigClocks] = useState<string[]>([]);\n const [configAppearance, setConfigAppearance] = useState<WidgetAppearance>(appearance);\n\n const { prefs, save } = useShellPrefs();\n const worldClocks: string[] = (prefs.world_clocks as string[] | undefined) ?? DEFAULT_CLOCKS;\n\n useEffect(() => {\n const t = setInterval(() => setNow(new Date()), 10000);\n return () => clearInterval(t);\n }, []);\n\n useWidgetSettings(useCallback(() => {\n setConfigClocks([...worldClocks]);\n setConfigAppearance({ ...appearance });\n setSettingsOpen(true);\n }, [worldClocks, appearance]));\n\n /** Local hour (0–23) at the given timezone — used to flip day/night. */\n const hourIn = (tz: string): number => {\n try {\n const parts = new Intl.DateTimeFormat('en-US', { timeZone: tz, hour: 'numeric', hour12: false }).formatToParts(now);\n const h = parseInt(parts.find(p => p.type === 'hour')?.value || '0', 10);\n // `hourCycle: h23` would be cleanest but isn't universally supported;\n // `hour12: false` returns 24 for midnight on some Node versions, so\n // normalize that to 0.\n return h === 24 ? 0 : h;\n } catch { return 12; }\n };\n /** Crude sunrise/sunset proxy — good enough for \"should this card look\n * bright or dark.\" Real solar calc would need the city's latitude. */\n const isDay = (tz: string) => { const h = hourIn(tz); return h >= 6 && h < 18; };\n\n const fmtTime = (tz: string) => now.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', timeZone: tz });\n const fmtOffset = (tz: string) => {\n const parts = new Intl.DateTimeFormat('en', { timeZone: tz, timeZoneName: 'shortOffset' }).formatToParts(now);\n return parts.find(p => p.type === 'timeZoneName')?.value || '';\n };\n const fmtDate = (tz: string) => now.toLocaleDateString(undefined, { weekday: 'short', month: 'short', day: 'numeric', timeZone: tz });\n\n const localTz = (typeof localStorage !== 'undefined' && localStorage.getItem('user_timezone'))\n || Intl.DateTimeFormat().resolvedOptions().timeZone;\n\n const saveSettings = () => {\n if (configClocks.length === 0) return;\n save({ world_clocks: configClocks });\n setAppearance(configAppearance);\n localStorage.setItem(SETTINGS_KEY, JSON.stringify(configAppearance));\n setSettingsOpen(false);\n };\n\n const labelFor = (tz: string) =>\n ALL_TIMEZONES.find(t => t.tz === tz)?.label\n || tz.split('/').pop()?.replace(/_/g, ' ')\n || tz;\n\n // Local time gets the \"featured\" card at the top, then the user's chosen\n // cities. Each card is its own day/night-coloured tile sitting on the\n // panel's slate backdrop with `gap-2` between cards — same idiom as\n // Weather.\n const cards = [{ tz: localTz, isLocal: true }, ...worldClocks.map(tz => ({ tz, isLocal: false }))];\n\n // Card heights: featured local-time card is taller (3 lines + larger\n // time), each city card is ~76 px. Plus the panel's p-2 padding.\n const dynamicHeight = 96 /* local card */ + worldClocks.length * 84 /* city cards */ + 16;\n\n return (\n <>\n <div className=\"flex flex-col rounded-lg text-white overflow-hidden\"\n style={{\n minHeight: dynamicHeight,\n backgroundColor: `rgba(15, 23, 42, ${appearance.activeOpacity / 100})`,\n backdropFilter: appearance.activeBlur > 0 ? `blur(${appearance.activeBlur}px)` : undefined,\n }}>\n <div className=\"flex-1 flex flex-col gap-2 p-2\">\n {cards.map(({ tz, isLocal }) => {\n const day = isDay(tz);\n const rowBg = day\n ? 'bg-gradient-to-br from-sky-400 via-sky-300 to-sky-500'\n : 'bg-gradient-to-br from-slate-800 via-blue-950 to-slate-900';\n const sub = isLocal\n ? `${fmtDate(tz)} · ${tz.replace(/_/g, ' ')}`\n : `${fmtDate(tz)} · ${fmtOffset(tz)}`;\n return (\n <div key={(isLocal ? 'local-' : '') + tz}\n className={`rounded-2xl px-4 py-3 flex items-center justify-between gap-3 ${rowBg}`}>\n <div className=\"min-w-0 flex-1\">\n {isLocal && (\n <div className=\"text-[10px] uppercase tracking-wide opacity-80 mb-0.5\">Local Time</div>\n )}\n <div className=\"text-base font-semibold leading-tight truncate\">{labelFor(tz)}</div>\n <div className=\"text-[10px] opacity-90 truncate mt-0.5\">{sub}</div>\n </div>\n <div className={`${isLocal ? 'text-3xl' : 'text-2xl'} font-extralight leading-none tracking-tight tabular-nums shrink-0`}>\n {fmtTime(tz)}\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\">Cities</h3>\n <div className=\"grid grid-cols-2 gap-1 max-h-56 overflow-y-auto\">\n {ALL_TIMEZONES.filter(t => t.tz !== localTz).map(({ tz, label }) => (\n <label key={tz} className=\"flex items-center gap-2 text-sm py-1 cursor-pointer hover:bg-gray-50 rounded px-2\">\n <input type=\"checkbox\" checked={configClocks.includes(tz)}\n onChange={() => setConfigClocks(prev => prev.includes(tz) ? prev.filter(t => t !== tz) : [...prev, tz])}\n className=\"rounded border-gray-300 text-blue-600 focus:ring-blue-500 h-3.5 w-3.5\" />\n {label}\n </label>\n ))}\n </div>\n </div>\n </WidgetSettingsModal>\n </>\n );\n}\n"]}