react-os-shell 0.2.41 → 0.2.43

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.
@@ -1,4 +1,4 @@
1
- import { ALL_TIMEZONES } from './chunk-L7SQZFP3.js';
1
+ import { ALL_TIMEZONES } from './chunk-7KZWBIDL.js';
2
2
  import './chunk-PDFQNHW7.js';
3
3
  import './chunk-NSU7OHPC.js';
4
4
  import './chunk-46LICZUM.js';
@@ -30,6 +30,19 @@ function WorldClock() {
30
30
  setConfigAppearance({ ...appearance });
31
31
  setSettingsOpen(true);
32
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
+ };
33
46
  const fmtTime = (tz) => now.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", timeZone: tz });
34
47
  const fmtOffset = (tz) => {
35
48
  const parts = new Intl.DateTimeFormat("en", { timeZone: tz, timeZoneName: "shortOffset" }).formatToParts(now);
@@ -45,39 +58,38 @@ function WorldClock() {
45
58
  setSettingsOpen(false);
46
59
  };
47
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;
48
63
  return /* @__PURE__ */ jsxs(Fragment, { children: [
49
- /* @__PURE__ */ jsxs(
64
+ /* @__PURE__ */ jsx(
50
65
  "div",
51
66
  {
52
- className: "flex flex-col h-full rounded-lg",
67
+ className: "flex flex-col rounded-lg text-white overflow-hidden",
53
68
  style: {
54
- backgroundColor: `rgb(var(--window-content-rgb) / ${appearance.activeOpacity / 100})`,
69
+ minHeight: dynamicHeight,
70
+ backgroundColor: `rgba(15, 23, 42, ${appearance.activeOpacity / 100})`,
55
71
  backdropFilter: appearance.activeBlur > 0 ? `blur(${appearance.activeBlur}px)` : void 0
56
72
  },
57
- children: [
58
- /* @__PURE__ */ jsxs("div", { className: "px-3 pt-2.5 pb-2 border-b border-gray-200/50", children: [
59
- /* @__PURE__ */ jsx("p", { className: "text-[10px] font-medium text-gray-500 uppercase tracking-wide", children: "Local Time" }),
60
- /* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between mt-0.5", children: [
61
- /* @__PURE__ */ jsx("span", { className: "text-2xl font-semibold text-gray-800 tabular-nums", children: fmtTime(localTz) }),
62
- /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-400", children: fmtOffset(localTz) })
63
- ] }),
64
- /* @__PURE__ */ jsxs("p", { className: "text-[10px] text-gray-500 mt-0.5 truncate", children: [
65
- fmtDate(localTz),
66
- " \xB7 ",
67
- localTz.replace(/_/g, " ")
68
- ] })
69
- ] }),
70
- /* @__PURE__ */ jsxs("div", { className: "px-3 py-2 space-y-0.5 flex-1", children: [
71
- worldClocks.length === 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-400 text-center py-3", children: "No cities \u2014 right-click to add." }),
72
- worldClocks.map((tz) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between py-1.5 border-b border-gray-200/50 last:border-0", children: [
73
- /* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
74
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-800 truncate", children: labelFor(tz) }),
75
- /* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-400 tabular-nums", children: fmtOffset(tz) })
76
- ] }),
77
- /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-gray-700 tabular-nums shrink-0", children: fmtTime(tz) })
78
- ] }, tz))
79
- ] })
80
- ]
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
+ }) })
81
93
  }
82
94
  ),
83
95
  /* @__PURE__ */ jsx(
@@ -110,5 +122,5 @@ function WorldClock() {
110
122
  }
111
123
 
112
124
  export { WorldClock as default };
113
- //# sourceMappingURL=WorldClock-OAVNGMET.js.map
114
- //# sourceMappingURL=WorldClock-OAVNGMET.js.map
125
+ //# sourceMappingURL=WorldClock-OFK2EA2H.js.map
126
+ //# sourceMappingURL=WorldClock-OFK2EA2H.js.map
@@ -0,0 +1 @@
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"]}
@@ -54,10 +54,16 @@ declare function Checkers$1(): react_jsx_runtime.JSX.Element;
54
54
  declare function Chess$1(): react_jsx_runtime.JSX.Element;
55
55
 
56
56
  /**
57
- * World Clock widget — same shape as Currency / Weather. Theme-aware bg via
58
- * `--window-content-rgb`, settings opened via the right-click menu (no
59
- * inline "+ Add World Clock" button anymorethat lives in the
60
- * <WidgetSettingsModal> alongside the appearance sliders).
57
+ * World Clock widget — iOS-style city cards with a per-row day/night
58
+ * gradient that flips based on the local hour at each city. Day cards use
59
+ * a bright sky blue, night cards a deep navy same palette as the
60
+ * Weather widget so the two read as a set when stacked.
61
+ *
62
+ * Settings (city list + appearance sliders) live in the right-click menu
63
+ * via `useWidgetSettings` — there is no inline "+ Add World Clock"
64
+ * button. Translucency is applied as a background-color alpha on the
65
+ * outer panel (slate-900 base) so the row gradients stay vivid even at
66
+ * lower opacity.
61
67
  */
62
68
  declare function WorldClock$1(): react_jsx_runtime.JSX.Element;
63
69
 
@@ -12,7 +12,7 @@ var Weather = lazy(() => import('../Weather-XTADR7Z3.js'));
12
12
  var CurrencyConverter = lazy(() => import('../CurrencyConverter-XZVZ7XOF.js'));
13
13
  var PomodoroTimer = lazy(() => import('../PomodoroTimer-T2J5NDJR.js'));
14
14
  var Notepad = lazy(() => import('../Notepad-W3YYZ3GS.js'));
15
- var WorldClock = lazy(() => import('../WorldClock-OAVNGMET.js'));
15
+ var WorldClock = lazy(() => import('../WorldClock-OFK2EA2H.js'));
16
16
  var Chess = lazy(() => import('../Chess-C5BY45NA.js'));
17
17
  var Checkers = lazy(() => import('../Checkers-MIAHIKJH.js'));
18
18
  var Sudoku = lazy(() => import('../Sudoku-XHLYCEVT.js'));
@@ -668,7 +668,7 @@ function BugReportAnnotator({
668
668
  }
669
669
 
670
670
  // src/version.ts
671
- var VERSION = "0.2.41" ;
671
+ var VERSION = "0.2.43" ;
672
672
  var APP_VERSION = VERSION;
673
673
 
674
674
  // src/utils/reportBug.ts
@@ -3625,21 +3625,21 @@ function TaskbarClock() {
3625
3625
  const [now, setNow] = useState(/* @__PURE__ */ new Date());
3626
3626
  const [open, setOpen] = useState(false);
3627
3627
  const [adding, setAdding] = useState(false);
3628
- const [pinned, setPinned] = useState(false);
3629
3628
  const ref = useRef(null);
3630
3629
  const buttonRef = useRef(null);
3631
3630
  const { prefs, save } = useShellPrefs();
3631
+ const { openPage } = useWindowManager();
3632
3632
  const worldClocks = prefs.world_clocks || ["Europe/London", "Asia/Shanghai", "America/Los_Angeles", "America/New_York"];
3633
3633
  useEffect(() => {
3634
3634
  const t = setInterval(() => setNow(/* @__PURE__ */ new Date()), 1e4);
3635
3635
  return () => clearInterval(t);
3636
3636
  }, []);
3637
3637
  useClickOutside(ref, useCallback(() => {
3638
- if (open && !pinned) {
3638
+ if (open) {
3639
3639
  setOpen(false);
3640
3640
  setAdding(false);
3641
3641
  }
3642
- }, [open, pinned]));
3642
+ }, [open]));
3643
3643
  const fmtTime = (tz) => now.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit", timeZone: tz });
3644
3644
  const fmtDate = (tz) => now.toLocaleDateString(void 0, { weekday: "short", month: "short", day: "numeric", timeZone: tz });
3645
3645
  const fmtOffset = (tz) => {
@@ -3663,7 +3663,7 @@ function TaskbarClock() {
3663
3663
  /* @__PURE__ */ jsx("p", { className: "text-[11px] font-medium text-gray-800", children: now.toLocaleTimeString(void 0, { hour: "2-digit", minute: "2-digit" }) }),
3664
3664
  /* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-700", children: now.toLocaleDateString(void 0, { month: "short", day: "numeric", year: "numeric" }) })
3665
3665
  ] }),
3666
- open && !pinned && (() => {
3666
+ open && (() => {
3667
3667
  const taskbarPos = getComputedStyle(document.documentElement).getPropertyValue("--taskbar-position")?.trim() || "bottom";
3668
3668
  const rect = buttonRef.current?.getBoundingClientRect();
3669
3669
  const right = rect ? window.innerWidth - rect.right : 0;
@@ -3673,9 +3673,10 @@ function TaskbarClock() {
3673
3673
  "button",
3674
3674
  {
3675
3675
  onClick: () => {
3676
- setPinned(true);
3676
+ openPage("/world-clock");
3677
+ setOpen(false);
3677
3678
  },
3678
- title: "Pin as widget",
3679
+ title: "Open as widget",
3679
3680
  className: "absolute top-2 right-2 text-gray-300 hover:text-gray-600 transition-colors z-10",
3680
3681
  children: /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 3.75L8.25 10.5m0 0l-3-1.5L3 12.75l5.25 5.25 3.75-2.25-1.5-3L17.25 6M8.25 10.5l-3 3M17.25 6l3 3" }) })
3681
3682
  }
@@ -3698,42 +3699,7 @@ function TaskbarClock() {
3698
3699
  }
3699
3700
  )
3700
3701
  ] });
3701
- })(),
3702
- pinned && /* @__PURE__ */ jsx(
3703
- Modal,
3704
- {
3705
- open: true,
3706
- onClose: () => {
3707
- setPinned(false);
3708
- setOpen(false);
3709
- },
3710
- title: /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1.5", children: [
3711
- /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
3712
- "World Clock"
3713
- ] }),
3714
- size: "sm",
3715
- allowPinOnTop: true,
3716
- initialPosition: "top-right",
3717
- widget: true,
3718
- children: /* @__PURE__ */ jsx(
3719
- ClockContent,
3720
- {
3721
- localTz,
3722
- worldClocks,
3723
- now,
3724
- fmtTime,
3725
- fmtDate,
3726
- fmtOffset,
3727
- removeClock,
3728
- adding,
3729
- setAdding,
3730
- addClock,
3731
- availableToAdd,
3732
- showAdd: false
3733
- }
3734
- )
3735
- }
3736
- )
3702
+ })()
3737
3703
  ] });
3738
3704
  }
3739
3705
  function TaskbarContextMenu({ x, y, position, size, onChangePosition, onChangeSize, onClose, onReportBug }) {
@@ -4174,5 +4140,5 @@ function Layout({
4174
4140
  }
4175
4141
 
4176
4142
  export { ALL_TIMEZONES, ALT, ALT_SHIFT_D, ALT_SHIFT_E, ALT_SHIFT_N, BugReportConfigProvider, BugReportProvider, CMD_A, CMD_DOT, CMD_ENTER, CMD_K, CMD_S, Desktop, DesktopHostProvider, ENTER, GlobalSearch, Layout, MOD, NotificationBell, SHIFT, ShellAuthProvider, ShortcutHelp, StartMenu, VERSION, isMac, openBugReportDialog, reportBug, setShellAuthBridge, useBugReport, useClickOutside, useDesktopHost, useShellAuth };
4177
- //# sourceMappingURL=chunk-L7SQZFP3.js.map
4178
- //# sourceMappingURL=chunk-L7SQZFP3.js.map
4143
+ //# sourceMappingURL=chunk-7KZWBIDL.js.map
4144
+ //# sourceMappingURL=chunk-7KZWBIDL.js.map