efficient-shell 4.137.0 → 4.145.0

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 (176) hide show
  1. package/LICENSE +6 -17
  2. package/README.md +80 -12
  3. package/dist/Browser-24YNRTKT.js +43 -0
  4. package/dist/Calculator-LER6KUQC.js +29 -0
  5. package/dist/ConfirmDialog-GAYETRMG.js +1 -0
  6. package/dist/CurrencyConverter-Y35GFDFF.js +21 -0
  7. package/dist/Documents-7FYX2CGT.js +52 -0
  8. package/dist/Files-RZOML2N6.js +89 -0
  9. package/dist/Notepad-VVDCBDUA.js +25 -0
  10. package/dist/PdfViewer-CvLb2j_l.d.ts +40 -0
  11. package/dist/PdfViewer-ZCT3PYXU.js +1 -0
  12. package/dist/PomodoroTimer-VAM3AJOX.js +99 -0
  13. package/dist/Preview-HZ37D7QJ.js +187 -0
  14. package/dist/Sidebar-CVF7C6BO.js +23 -0
  15. package/dist/Spreadsheet-6WX3P6AB.js +37 -0
  16. package/dist/Stock-AUWI3TUX.js +16 -0
  17. package/dist/Weather-HU75TH7T.js +60 -0
  18. package/dist/WorldClock-T64MDRMJ.js +32 -0
  19. package/dist/apps/index.d.ts +3 -23
  20. package/dist/apps/index.js +1 -151
  21. package/dist/brand.css +1 -1
  22. package/dist/chunk-2RHMSFZV.js +9 -0
  23. package/dist/chunk-4FS742BM.js +1 -0
  24. package/dist/chunk-57MIENLJ.js +1 -0
  25. package/dist/chunk-7DAQ3WVP.js +106 -0
  26. package/dist/chunk-BR22X7E5.js +1 -0
  27. package/dist/chunk-BUTSU7FO.js +1 -0
  28. package/dist/chunk-CVTOZCM3.js +24 -0
  29. package/dist/chunk-D65T4H6J.js +1 -0
  30. package/dist/chunk-ESL5TDNA.js +1 -0
  31. package/dist/chunk-FBDZGO3V.js +1 -0
  32. package/dist/chunk-FHTLC7HH.js +1 -0
  33. package/dist/chunk-GDSGXDET.js +34 -0
  34. package/dist/chunk-I55UMU3R.js +6 -0
  35. package/dist/chunk-KKOHUQPF.js +1 -0
  36. package/dist/chunk-L7TEFXIS.js +69 -0
  37. package/dist/chunk-LVDRBRYU.js +1 -0
  38. package/dist/chunk-LVFMK5OQ.js +29 -0
  39. package/dist/chunk-LWLCNQY7.js +1 -0
  40. package/dist/chunk-MAIHBBWT.js +1 -0
  41. package/dist/chunk-MU5H2CDL.js +2 -0
  42. package/dist/chunk-NBBOFQPL.js +947 -0
  43. package/dist/chunk-NPJH5MD7.js +13 -0
  44. package/dist/chunk-OCSOMMY2.js +1 -0
  45. package/dist/chunk-PH3PRIFP.js +5 -0
  46. package/dist/chunk-RJ4LACFH.js +9 -0
  47. package/dist/chunk-SLCR26NK.js +4 -0
  48. package/dist/chunk-TFKB2WEB.js +19 -0
  49. package/dist/chunk-TR6PLN7W.js +1 -0
  50. package/dist/chunk-TWV42Q3K.js +1 -0
  51. package/dist/chunk-UB22J6EF.js +1 -0
  52. package/dist/chunk-UB4JIOLD.js +2 -0
  53. package/dist/chunk-V453E4KU.js +11 -0
  54. package/dist/chunk-VTVSMRFX.js +1 -0
  55. package/dist/file-intake/index.js +1 -4
  56. package/dist/{index-DVI9DMSu.d.ts → index-NhR7frRu.d.ts} +189 -17
  57. package/dist/index.d.ts +2 -2
  58. package/dist/index.js +639 -7473
  59. package/dist/map/index.d.ts +266 -13
  60. package/dist/map/index.js +22 -540
  61. package/dist/markdown/index.js +6 -184
  62. package/dist/markup/index.js +1 -135
  63. package/dist/page-tabs/index.js +21 -709
  64. package/dist/pdf/index.d.ts +9 -0
  65. package/dist/pdf/index.js +2 -0
  66. package/dist/sounds-OMHXVVQ4.js +1 -0
  67. package/dist/ui/index.d.ts +1 -1
  68. package/dist/ui/index.js +1 -19
  69. package/dist/ui.css +7 -0
  70. package/package.json +9 -3
  71. package/dist/Browser-ZNX4WFUH.js +0 -482
  72. package/dist/Browser-ZNX4WFUH.js.map +0 -1
  73. package/dist/Calculator-6FGNKOXU.js +0 -192
  74. package/dist/Calculator-6FGNKOXU.js.map +0 -1
  75. package/dist/ConfirmDialog-NPQMIGUR.js +0 -4
  76. package/dist/ConfirmDialog-NPQMIGUR.js.map +0 -1
  77. package/dist/CurrencyConverter-FF7EXRYL.js +0 -236
  78. package/dist/CurrencyConverter-FF7EXRYL.js.map +0 -1
  79. package/dist/Documents-H3R7XSBH.js +0 -441
  80. package/dist/Documents-H3R7XSBH.js.map +0 -1
  81. package/dist/Files-ZHJIAUC2.js +0 -805
  82. package/dist/Files-ZHJIAUC2.js.map +0 -1
  83. package/dist/Notepad-VE7ISWRQ.js +0 -410
  84. package/dist/Notepad-VE7ISWRQ.js.map +0 -1
  85. package/dist/PdfViewer-SQBFYAGW.js +0 -5
  86. package/dist/PdfViewer-SQBFYAGW.js.map +0 -1
  87. package/dist/PomodoroTimer-IR3WREED.js +0 -633
  88. package/dist/PomodoroTimer-IR3WREED.js.map +0 -1
  89. package/dist/Preview-DAQGRNRM.js +0 -2959
  90. package/dist/Preview-DAQGRNRM.js.map +0 -1
  91. package/dist/Sidebar-YW6H4NDJ.js +0 -291
  92. package/dist/Sidebar-YW6H4NDJ.js.map +0 -1
  93. package/dist/Spreadsheet-HOCPHJOC.js +0 -519
  94. package/dist/Spreadsheet-HOCPHJOC.js.map +0 -1
  95. package/dist/Stock-LVRQPURG.js +0 -158
  96. package/dist/Stock-LVRQPURG.js.map +0 -1
  97. package/dist/Weather-LZQGVDJL.js +0 -431
  98. package/dist/Weather-LZQGVDJL.js.map +0 -1
  99. package/dist/WorldClock-XPD7WOZT.js +0 -202
  100. package/dist/WorldClock-XPD7WOZT.js.map +0 -1
  101. package/dist/apps/index.js.map +0 -1
  102. package/dist/chunk-5O42JXQE.js +0 -26
  103. package/dist/chunk-5O42JXQE.js.map +0 -1
  104. package/dist/chunk-5RPTS3BT.js +0 -70
  105. package/dist/chunk-5RPTS3BT.js.map +0 -1
  106. package/dist/chunk-6XJEJWNJ.js +0 -61
  107. package/dist/chunk-6XJEJWNJ.js.map +0 -1
  108. package/dist/chunk-7CCHEEYC.js +0 -94
  109. package/dist/chunk-7CCHEEYC.js.map +0 -1
  110. package/dist/chunk-BE7FZOFU.js +0 -17
  111. package/dist/chunk-BE7FZOFU.js.map +0 -1
  112. package/dist/chunk-COWYSHG2.js +0 -79
  113. package/dist/chunk-COWYSHG2.js.map +0 -1
  114. package/dist/chunk-D7PYW2QS.js +0 -265
  115. package/dist/chunk-D7PYW2QS.js.map +0 -1
  116. package/dist/chunk-DVZWYWSD.js +0 -26
  117. package/dist/chunk-DVZWYWSD.js.map +0 -1
  118. package/dist/chunk-E7TB6WD2.js +0 -153
  119. package/dist/chunk-E7TB6WD2.js.map +0 -1
  120. package/dist/chunk-FIHOGVUP.js +0 -416
  121. package/dist/chunk-FIHOGVUP.js.map +0 -1
  122. package/dist/chunk-GA35NEND.js +0 -56
  123. package/dist/chunk-GA35NEND.js.map +0 -1
  124. package/dist/chunk-HUBJAUGG.js +0 -316
  125. package/dist/chunk-HUBJAUGG.js.map +0 -1
  126. package/dist/chunk-I2TAAJHS.js +0 -465
  127. package/dist/chunk-I2TAAJHS.js.map +0 -1
  128. package/dist/chunk-ICTRCKUE.js +0 -3710
  129. package/dist/chunk-ICTRCKUE.js.map +0 -1
  130. package/dist/chunk-IPXN646P.js +0 -14
  131. package/dist/chunk-IPXN646P.js.map +0 -1
  132. package/dist/chunk-IRWSRJ4K.js +0 -48
  133. package/dist/chunk-IRWSRJ4K.js.map +0 -1
  134. package/dist/chunk-JOPU6WPY.js +0 -504
  135. package/dist/chunk-JOPU6WPY.js.map +0 -1
  136. package/dist/chunk-MGGY74RY.js +0 -14
  137. package/dist/chunk-MGGY74RY.js.map +0 -1
  138. package/dist/chunk-PVPPAWVM.js +0 -46
  139. package/dist/chunk-PVPPAWVM.js.map +0 -1
  140. package/dist/chunk-R7QGMK6N.js +0 -102
  141. package/dist/chunk-R7QGMK6N.js.map +0 -1
  142. package/dist/chunk-RT6DSB5Y.js +0 -143
  143. package/dist/chunk-RT6DSB5Y.js.map +0 -1
  144. package/dist/chunk-TRCWINHF.js +0 -105
  145. package/dist/chunk-TRCWINHF.js.map +0 -1
  146. package/dist/chunk-TW7LPMVR.js +0 -16
  147. package/dist/chunk-TW7LPMVR.js.map +0 -1
  148. package/dist/chunk-UTYKLGGT.js +0 -195
  149. package/dist/chunk-UTYKLGGT.js.map +0 -1
  150. package/dist/chunk-VNJJCH5A.js +0 -822
  151. package/dist/chunk-VNJJCH5A.js.map +0 -1
  152. package/dist/chunk-XJHZWSKV.js +0 -1103
  153. package/dist/chunk-XJHZWSKV.js.map +0 -1
  154. package/dist/chunk-Y3GYJ7YR.js +0 -549
  155. package/dist/chunk-Y3GYJ7YR.js.map +0 -1
  156. package/dist/chunk-YA4EE7ST.js +0 -14107
  157. package/dist/chunk-YA4EE7ST.js.map +0 -1
  158. package/dist/chunk-YDHXWCCJ.js +0 -145
  159. package/dist/chunk-YDHXWCCJ.js.map +0 -1
  160. package/dist/chunk-YE6GUDGP.js +0 -548
  161. package/dist/chunk-YE6GUDGP.js.map +0 -1
  162. package/dist/chunk-YNKK7NE3.js +0 -171
  163. package/dist/chunk-YNKK7NE3.js.map +0 -1
  164. package/dist/chunk-YPO6RDMX.js +0 -20
  165. package/dist/chunk-YPO6RDMX.js.map +0 -1
  166. package/dist/chunk-ZS7PMGUW.js +0 -7
  167. package/dist/chunk-ZS7PMGUW.js.map +0 -1
  168. package/dist/file-intake/index.js.map +0 -1
  169. package/dist/index.js.map +0 -1
  170. package/dist/map/index.js.map +0 -1
  171. package/dist/markdown/index.js.map +0 -1
  172. package/dist/markup/index.js.map +0 -1
  173. package/dist/page-tabs/index.js.map +0 -1
  174. package/dist/sounds-NT4DEZGD.js +0 -3
  175. package/dist/sounds-NT4DEZGD.js.map +0 -1
  176. package/dist/ui/index.js.map +0 -1
@@ -1,94 +0,0 @@
1
- // src/apps/_weatherData.ts
2
- var WMO = {
3
- 0: ["Clear Sky", "\u2600\uFE0F", "\u{1F319}", "from-sky-400 to-blue-500", "from-indigo-900 to-slate-950"],
4
- 1: ["Mainly Clear", "\u{1F324}\uFE0F", "\u{1F319}", "from-sky-400 to-blue-500", "from-indigo-900 to-slate-950"],
5
- 2: ["Partly Cloudy", "\u26C5", "\u2601\uFE0F", "from-sky-400 to-blue-400", "from-indigo-800 to-slate-900"],
6
- 3: ["Overcast", "\u2601\uFE0F", "\u2601\uFE0F", "from-gray-400 to-gray-500", "from-gray-700 to-slate-900"],
7
- 45: ["Foggy", "\u{1F32B}\uFE0F", "\u{1F32B}\uFE0F", "from-gray-400 to-gray-500", "from-gray-700 to-slate-800"],
8
- 48: ["Foggy", "\u{1F32B}\uFE0F", "\u{1F32B}\uFE0F", "from-gray-400 to-gray-500", "from-gray-700 to-slate-800"],
9
- 51: ["Light Drizzle", "\u{1F326}\uFE0F", "\u{1F327}\uFE0F", "from-gray-400 to-blue-500", "from-gray-700 to-indigo-900"],
10
- 53: ["Drizzle", "\u{1F327}\uFE0F", "\u{1F327}\uFE0F", "from-gray-500 to-blue-600", "from-gray-700 to-indigo-900"],
11
- 55: ["Heavy Drizzle", "\u{1F327}\uFE0F", "\u{1F327}\uFE0F", "from-gray-500 to-blue-600", "from-gray-700 to-indigo-900"],
12
- 61: ["Light Rain", "\u{1F326}\uFE0F", "\u{1F327}\uFE0F", "from-gray-400 to-blue-500", "from-gray-700 to-indigo-900"],
13
- 63: ["Rain", "\u{1F327}\uFE0F", "\u{1F327}\uFE0F", "from-gray-500 to-blue-600", "from-gray-700 to-indigo-900"],
14
- 65: ["Heavy Rain", "\u{1F327}\uFE0F", "\u{1F327}\uFE0F", "from-gray-600 to-blue-700", "from-gray-700 to-indigo-950"],
15
- 71: ["Light Snow", "\u{1F328}\uFE0F", "\u{1F328}\uFE0F", "from-blue-200 to-blue-400", "from-blue-800 to-slate-900"],
16
- 73: ["Snow", "\u2744\uFE0F", "\u2744\uFE0F", "from-blue-300 to-blue-500", "from-blue-800 to-slate-900"],
17
- 75: ["Heavy Snow", "\u2744\uFE0F", "\u2744\uFE0F", "from-blue-400 to-blue-600", "from-blue-800 to-slate-900"],
18
- 80: ["Rain Showers", "\u{1F327}\uFE0F", "\u{1F327}\uFE0F", "from-gray-500 to-blue-600", "from-gray-700 to-indigo-900"],
19
- 82: ["Heavy Showers", "\u{1F327}\uFE0F", "\u{1F327}\uFE0F", "from-gray-600 to-blue-700", "from-gray-700 to-indigo-950"],
20
- 95: ["Thunderstorm", "\u26C8\uFE0F", "\u26C8\uFE0F", "from-gray-700 to-indigo-800", "from-gray-800 to-indigo-950"],
21
- 96: ["Thunderstorm", "\u26C8\uFE0F", "\u26C8\uFE0F", "from-gray-700 to-indigo-800", "from-gray-800 to-indigo-950"],
22
- 99: ["Thunderstorm", "\u26C8\uFE0F", "\u26C8\uFE0F", "from-gray-700 to-indigo-900", "from-gray-800 to-indigo-950"]
23
- };
24
- var getCondition = (code, isDay = true) => {
25
- const entry = WMO[code] || ["Unknown", "\u2753", "\u2753", "from-gray-400 to-gray-500", "from-gray-700 to-slate-800"];
26
- return [entry[0], isDay ? entry[1] : entry[2], isDay ? entry[3] : entry[4]];
27
- };
28
- var AVAILABLE_CITIES = {
29
- "Sydney": { lat: -33.8688, lon: 151.2093, tz: "Australia/Sydney" },
30
- "Melbourne": { lat: -37.8136, lon: 144.9631, tz: "Australia/Melbourne" },
31
- "Auckland": { lat: -36.8485, lon: 174.7633, tz: "Pacific/Auckland" },
32
- "Tokyo": { lat: 35.6762, lon: 139.6503, tz: "Asia/Tokyo" },
33
- "Shanghai": { lat: 31.2304, lon: 121.4737, tz: "Asia/Shanghai" },
34
- "Hong Kong": { lat: 22.3193, lon: 114.1694, tz: "Asia/Hong_Kong" },
35
- "Singapore": { lat: 1.3521, lon: 103.8198, tz: "Asia/Singapore" },
36
- "Bangkok": { lat: 13.7563, lon: 100.5018, tz: "Asia/Bangkok" },
37
- "Mumbai": { lat: 19.076, lon: 72.8777, tz: "Asia/Kolkata" },
38
- "Dubai": { lat: 25.2048, lon: 55.2708, tz: "Asia/Dubai" },
39
- "Berlin": { lat: 52.52, lon: 13.405, tz: "Europe/Berlin" },
40
- "Paris": { lat: 48.8566, lon: 2.3522, tz: "Europe/Paris" },
41
- "London": { lat: 51.5074, lon: -0.1278, tz: "Europe/London" },
42
- "New York": { lat: 40.7128, lon: -74.006, tz: "America/New_York" },
43
- "Miami": { lat: 25.7617, lon: -80.1918, tz: "America/New_York" },
44
- "Toronto": { lat: 43.6532, lon: -79.3832, tz: "America/Toronto" },
45
- "Chicago": { lat: 41.8781, lon: -87.6298, tz: "America/Chicago" },
46
- "Los Angeles": { lat: 34.0522, lon: -118.2437, tz: "America/Los_Angeles" }
47
- };
48
- var WEATHER_CACHE_KEY = "weather_local_cache";
49
- var WEATHER_CACHE_TTL = 30 * 60 * 1e3;
50
- function readCache() {
51
- try {
52
- return JSON.parse(localStorage.getItem(WEATHER_CACHE_KEY) || "{}");
53
- } catch {
54
- return {};
55
- }
56
- }
57
- function writeCache(c) {
58
- try {
59
- localStorage.setItem(WEATHER_CACHE_KEY, JSON.stringify(c));
60
- } catch {
61
- }
62
- }
63
- async function fetchCityWeather(cityName, force = false) {
64
- const coords = AVAILABLE_CITIES[cityName];
65
- if (!coords) return null;
66
- if (!force) {
67
- const cached = readCache()[cityName];
68
- if (cached && Date.now() - cached.ts < WEATHER_CACHE_TTL) return cached.data;
69
- }
70
- try {
71
- const res = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${coords.lat}&longitude=${coords.lon}&current=temperature_2m,weather_code,is_day&daily=temperature_2m_max,temperature_2m_min&forecast_days=1&timezone=auto`);
72
- const w = await res.json();
73
- const cw = {
74
- city: cityName,
75
- temp: Math.round(w.current.temperature_2m),
76
- code: w.current.weather_code,
77
- high: Math.round(w.daily.temperature_2m_max[0]),
78
- low: Math.round(w.daily.temperature_2m_min[0]),
79
- isDay: w.current.is_day === 1,
80
- timezone: w.timezone || "UTC"
81
- };
82
- const c = readCache();
83
- c[cityName] = { data: cw, ts: Date.now() };
84
- writeCache(c);
85
- return cw;
86
- } catch {
87
- return null;
88
- }
89
- }
90
- var toFahrenheit = (c) => Math.round(c * 9 / 5 + 32);
91
-
92
- export { AVAILABLE_CITIES, fetchCityWeather, getCondition, toFahrenheit };
93
- //# sourceMappingURL=chunk-7CCHEEYC.js.map
94
- //# sourceMappingURL=chunk-7CCHEEYC.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/apps/_weatherData.ts"],"names":[],"mappings":"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","file":"chunk-7CCHEEYC.js","sourcesContent":["/**\n * Shared weather data — used by Weather (single-city tile with animations)\n * and WorldClock (multi-city list with per-row weather + day/night via the\n * emoji). Single source of truth for the WMO code map, the supported city\n * coordinates, and the localStorage cache so both widgets share fetched\n * data.\n */\n\n// [condition, day emoji, night emoji, day gradient, night gradient]\nexport const WMO: Record<number, [string, string, string, string, string]> = {\n 0: ['Clear Sky', '☀️', '🌙', 'from-sky-400 to-blue-500', 'from-indigo-900 to-slate-950'],\n 1: ['Mainly Clear', '🌤️', '🌙', 'from-sky-400 to-blue-500', 'from-indigo-900 to-slate-950'],\n 2: ['Partly Cloudy', '⛅', '☁️', 'from-sky-400 to-blue-400', 'from-indigo-800 to-slate-900'],\n 3: ['Overcast', '☁️', '☁️', 'from-gray-400 to-gray-500', 'from-gray-700 to-slate-900'],\n 45: ['Foggy', '🌫️', '🌫️', 'from-gray-400 to-gray-500', 'from-gray-700 to-slate-800'],\n 48: ['Foggy', '🌫️', '🌫️', 'from-gray-400 to-gray-500', 'from-gray-700 to-slate-800'],\n 51: ['Light Drizzle', '🌦️', '🌧️', 'from-gray-400 to-blue-500', 'from-gray-700 to-indigo-900'],\n 53: ['Drizzle', '🌧️', '🌧️', 'from-gray-500 to-blue-600', 'from-gray-700 to-indigo-900'],\n 55: ['Heavy Drizzle', '🌧️', '🌧️', 'from-gray-500 to-blue-600', 'from-gray-700 to-indigo-900'],\n 61: ['Light Rain', '🌦️', '🌧️', 'from-gray-400 to-blue-500', 'from-gray-700 to-indigo-900'],\n 63: ['Rain', '🌧️', '🌧️', 'from-gray-500 to-blue-600', 'from-gray-700 to-indigo-900'],\n 65: ['Heavy Rain', '🌧️', '🌧️', 'from-gray-600 to-blue-700', 'from-gray-700 to-indigo-950'],\n 71: ['Light Snow', '🌨️', '🌨️', 'from-blue-200 to-blue-400', 'from-blue-800 to-slate-900'],\n 73: ['Snow', '❄️', '❄️', 'from-blue-300 to-blue-500', 'from-blue-800 to-slate-900'],\n 75: ['Heavy Snow', '❄️', '❄️', 'from-blue-400 to-blue-600', 'from-blue-800 to-slate-900'],\n 80: ['Rain Showers', '🌧️', '🌧️', 'from-gray-500 to-blue-600', 'from-gray-700 to-indigo-900'],\n 82: ['Heavy Showers', '🌧️', '🌧️', 'from-gray-600 to-blue-700', 'from-gray-700 to-indigo-950'],\n 95: ['Thunderstorm', '⛈️', '⛈️', 'from-gray-700 to-indigo-800', 'from-gray-800 to-indigo-950'],\n 96: ['Thunderstorm', '⛈️', '⛈️', 'from-gray-700 to-indigo-800', 'from-gray-800 to-indigo-950'],\n 99: ['Thunderstorm', '⛈️', '⛈️', 'from-gray-700 to-indigo-900', 'from-gray-800 to-indigo-950'],\n};\n\nexport const getCondition = (code: number, isDay = true): [string, string, string] => {\n const entry = WMO[code] || ['Unknown', '❓', '❓', 'from-gray-400 to-gray-500', 'from-gray-700 to-slate-800'];\n return [entry[0], isDay ? entry[1] : entry[2], isDay ? entry[3] : entry[4]];\n};\n\nexport const AVAILABLE_CITIES: Record<string, { lat: number; lon: number; tz: string }> = {\n 'Sydney': { lat: -33.8688, lon: 151.2093, tz: 'Australia/Sydney' },\n 'Melbourne': { lat: -37.8136, lon: 144.9631, tz: 'Australia/Melbourne' },\n 'Auckland': { lat: -36.8485, lon: 174.7633, tz: 'Pacific/Auckland' },\n 'Tokyo': { lat: 35.6762, lon: 139.6503, tz: 'Asia/Tokyo' },\n 'Shanghai': { lat: 31.2304, lon: 121.4737, tz: 'Asia/Shanghai' },\n 'Hong Kong': { lat: 22.3193, lon: 114.1694, tz: 'Asia/Hong_Kong' },\n 'Singapore': { lat: 1.3521, lon: 103.8198, tz: 'Asia/Singapore' },\n 'Bangkok': { lat: 13.7563, lon: 100.5018, tz: 'Asia/Bangkok' },\n 'Mumbai': { lat: 19.0760, lon: 72.8777, tz: 'Asia/Kolkata' },\n 'Dubai': { lat: 25.2048, lon: 55.2708, tz: 'Asia/Dubai' },\n 'Berlin': { lat: 52.5200, lon: 13.4050, tz: 'Europe/Berlin' },\n 'Paris': { lat: 48.8566, lon: 2.3522, tz: 'Europe/Paris' },\n 'London': { lat: 51.5074, lon: -0.1278, tz: 'Europe/London' },\n 'New York': { lat: 40.7128, lon: -74.0060, tz: 'America/New_York' },\n 'Miami': { lat: 25.7617, lon: -80.1918, tz: 'America/New_York' },\n 'Toronto': { lat: 43.6532, lon: -79.3832, tz: 'America/Toronto' },\n 'Chicago': { lat: 41.8781, lon: -87.6298, tz: 'America/Chicago' },\n 'Los Angeles': { lat: 34.0522, lon: -118.2437, tz: 'America/Los_Angeles' },\n};\n\nexport const WEATHER_CACHE_KEY = 'weather_local_cache';\nexport const WEATHER_CACHE_TTL = 30 * 60 * 1000;\n\nexport interface CityWeather {\n city: string;\n temp: number;\n code: number;\n high: number;\n low: number;\n isDay: boolean;\n timezone: string;\n}\n\nexport interface WeatherCacheEntry { data: CityWeather; ts: number }\ntype WeatherCache = Record<string, WeatherCacheEntry>;\n\nfunction readCache(): WeatherCache {\n try { return JSON.parse(localStorage.getItem(WEATHER_CACHE_KEY) || '{}'); } catch { return {}; }\n}\nfunction writeCache(c: WeatherCache) {\n try { localStorage.setItem(WEATHER_CACHE_KEY, JSON.stringify(c)); } catch {}\n}\n\n/** Fetch a city's current weather + today's high/low, with a 30-min\n * localStorage cache shared across widgets. */\nexport async function fetchCityWeather(cityName: string, force = false): Promise<CityWeather | null> {\n const coords = AVAILABLE_CITIES[cityName];\n if (!coords) return null;\n if (!force) {\n const cached = readCache()[cityName];\n if (cached && Date.now() - cached.ts < WEATHER_CACHE_TTL) return cached.data;\n }\n try {\n const res = await fetch(`https://api.open-meteo.com/v1/forecast?latitude=${coords.lat}&longitude=${coords.lon}&current=temperature_2m,weather_code,is_day&daily=temperature_2m_max,temperature_2m_min&forecast_days=1&timezone=auto`);\n const w = await res.json();\n const cw: CityWeather = {\n city: cityName,\n temp: Math.round(w.current.temperature_2m),\n code: w.current.weather_code,\n high: Math.round(w.daily.temperature_2m_max[0]),\n low: Math.round(w.daily.temperature_2m_min[0]),\n isDay: w.current.is_day === 1,\n timezone: w.timezone || 'UTC',\n };\n const c = readCache();\n c[cityName] = { data: cw, ts: Date.now() };\n writeCache(c);\n return cw;\n } catch {\n return null;\n }\n}\n\nexport const toFahrenheit = (c: number) => Math.round(c * 9 / 5 + 32);\n"]}
@@ -1,17 +0,0 @@
1
- import { requestFilesTrashView } from './chunk-YNKK7NE3.js';
2
-
3
- // src/apps/_filesShared.ts
4
- var filesDemoTree = null;
5
- function setFilesDemoTree(tree) {
6
- filesDemoTree = tree;
7
- }
8
- function getFilesDemoTree() {
9
- return filesDemoTree;
10
- }
11
- function openFilesInTrashMode() {
12
- requestFilesTrashView();
13
- }
14
-
15
- export { getFilesDemoTree, openFilesInTrashMode, setFilesDemoTree };
16
- //# sourceMappingURL=chunk-BE7FZOFU.js.map
17
- //# sourceMappingURL=chunk-BE7FZOFU.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/apps/_filesShared.ts"],"names":[],"mappings":";;;AAwBA,IAAI,aAAA,GAAwC,IAAA;AAErC,SAAS,iBAAiB,IAAA,EAA8B;AAC7D,EAAA,aAAA,GAAgB,IAAA;AAClB;AAGO,SAAS,gBAAA,GAA2C;AACzD,EAAA,OAAO,aAAA;AACT;AAKO,SAAS,oBAAA,GAAuB;AACrC,EAAA,qBAAA,EAAsB;AACxB","file":"chunk-BE7FZOFU.js","sourcesContent":["/**\n * Files app config — the tiny consumer-facing surface of the Files app\n * (demo-tree injection + trash-mode open). Lives apart from Files.tsx so\n * importing these from `efficient-shell/apps` never drags the Files\n * implementation into a host's startup bundle; the Files window component\n * stays behind its React.lazy dynamic import.\n */\nimport { requestFilesTrashView } from '../shell/desktopIcons';\n\n/**\n * Demo filesystem. When a consumer (e.g. the demo app) injects a static tree\n * via `setFilesDemoTree`, Files browses it in-memory — no file server needed.\n * Browse-only: upload / new-folder / rename / delete / trash are hidden while a\n * demo tree is set. Consumers with a real file server never call it, so their\n * behaviour is unchanged.\n */\nexport interface FilesDemoNode {\n name: string;\n kind: 'file' | 'folder';\n size?: number;\n modifiedAt?: string;\n children?: FilesDemoNode[];\n}\n\nlet filesDemoTree: FilesDemoNode[] | null = null;\n\nexport function setFilesDemoTree(tree: FilesDemoNode[] | null) {\n filesDemoTree = tree;\n}\n\n/** @internal Current injected demo tree, if any — read by Files.tsx. */\nexport function getFilesDemoTree(): FilesDemoNode[] | null {\n return filesDemoTree;\n}\n\n// Side-channel for opening Files on a specific view (trash, desktop folder).\n// The flag + event plumbing lives in shell/desktopIcons.tsx; this wrapper is\n// kept because consumers import it from the package.\nexport function openFilesInTrashMode() {\n requestFilesTrashView();\n}\n"]}
@@ -1,79 +0,0 @@
1
- import { useWindowMenuItem, Modal } from './chunk-ICTRCKUE.js';
2
- import { navIcons } from './chunk-GA35NEND.js';
3
- import { VERSION } from './chunk-ZS7PMGUW.js';
4
- import { useState, useCallback, isValidElement, cloneElement } from 'react';
5
- import { jsx, jsxs } from 'react/jsx-runtime';
6
-
7
- var BUILTIN_APP_INFO = {
8
- spreadsheet: {
9
- name: "Spreadsheets",
10
- version: "1.1.3",
11
- route: "/spreadsheet",
12
- description: "Multi-sheet spreadsheet editor with CSV / TSV import and export."
13
- },
14
- notepad: {
15
- name: "Notepad",
16
- version: "1.0.0",
17
- route: "/notepad",
18
- description: "Color-coded notes with checklists, desktop stickies and entity autolinking."
19
- },
20
- documents: {
21
- name: "Documents",
22
- version: "1.1.0",
23
- route: "/documents",
24
- description: "Letter-page editor for Word documents and plain-text files \u2014 images, lists, alignment."
25
- },
26
- preview: {
27
- name: "Preview",
28
- version: "1.3.2",
29
- route: "/preview",
30
- description: "Viewer for PDF documents, images, DXF drawings and 3D models \u2014 CAD-style measuring with object snap and an AutoCAD-like command bar."
31
- },
32
- files: {
33
- name: "Files",
34
- version: "1.1.0",
35
- route: "/files",
36
- description: "Personal file manager with folders, uploads, quota, trash and desktop shortcut folders."
37
- },
38
- browser: {
39
- name: "Browser",
40
- version: "1.0.1",
41
- route: "/browser",
42
- description: "Minimal web browser with bookmarks, history and navigation bar."
43
- }
44
- };
45
- var ABOUT_MENU_ICON = /* @__PURE__ */ jsx("svg", { className: "h-4 w-4 text-gray-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z" }) });
46
- var FALLBACK_APP_ICON = /* @__PURE__ */ jsx("svg", { className: "h-9 w-9", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6.75A2.25 2.25 0 016 4.5h12a2.25 2.25 0 012.25 2.25v10.5A2.25 2.25 0 0118 19.5H6a2.25 2.25 0 01-2.25-2.25V6.75z M3.75 9h16.5" }) });
47
- function AboutApp({ app }) {
48
- const info = BUILTIN_APP_INFO[app];
49
- const [open, setOpen] = useState(false);
50
- const openDialog = useCallback(() => setOpen(true), []);
51
- useWindowMenuItem(`About ${info.name}`, openDialog, ABOUT_MENU_ICON);
52
- if (!open) return null;
53
- const registered = navIcons[info.route];
54
- const appIcon = isValidElement(registered) ? cloneElement(registered, { className: "h-9 w-9" }) : FALLBACK_APP_ICON;
55
- return /* @__PURE__ */ jsx(Modal, { open: true, onClose: () => setOpen(false), title: `About ${info.name}`, size: "sm", compact: true, bodyScroll: false, autoHeight: true, dimensions: [320, 320], children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center text-center px-5 pt-5 pb-4", children: [
56
- /* @__PURE__ */ jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-2xl bg-gray-100 text-gray-600 shrink-0", children: appIcon }),
57
- /* @__PURE__ */ jsx("h2", { className: "mt-3 text-lg font-bold text-gray-900", children: info.name }),
58
- /* @__PURE__ */ jsxs("p", { className: "text-[11px] font-mono text-gray-400", children: [
59
- "Version ",
60
- info.version
61
- ] }),
62
- /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-gray-500 leading-relaxed", children: info.description }),
63
- /* @__PURE__ */ jsxs("div", { className: "mt-4 pt-3 border-t border-gray-200 w-full", children: [
64
- /* @__PURE__ */ jsxs("p", { className: "text-[11px] text-gray-500", children: [
65
- "Part of the ",
66
- /* @__PURE__ */ jsx("span", { className: "font-medium text-gray-700", children: "efficient-shell" }),
67
- " desktop environment"
68
- ] }),
69
- VERSION && /* @__PURE__ */ jsxs("p", { className: "mt-0.5 text-[10px] font-mono text-gray-400", children: [
70
- "shell v",
71
- VERSION
72
- ] })
73
- ] })
74
- ] }) });
75
- }
76
-
77
- export { AboutApp, BUILTIN_APP_INFO };
78
- //# sourceMappingURL=chunk-COWYSHG2.js.map
79
- //# sourceMappingURL=chunk-COWYSHG2.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/apps/_about.tsx"],"names":[],"mappings":"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","file":"chunk-COWYSHG2.js","sourcesContent":["/**\n * Shared \"About\" dialog for the bundled apps.\n *\n * Each bundled app carries its own version (independent of the package\n * version) so app-level changes can be tracked without bumping every app at\n * once. `<AboutApp app=\"…\" />` registers an \"About <Name>\" item in the\n * window title menu and renders the dialog: app icon, name, app version and\n * the efficient-shell attribution + shell version.\n *\n * Bump an app's version in `BUILTIN_APP_INFO` whenever that app's behaviour\n * changes, alongside the package-level CHANGELOG entry.\n */\nimport { useCallback, useState, isValidElement, cloneElement, type ReactElement } from 'react';\nimport Modal, { useWindowMenuItem } from '../shell/Modal';\nimport { navIcons } from '../shell-config/nav';\nimport { VERSION } from '../version';\n\nexport interface BuiltinAppInfo {\n /** Display name — matches the window-registry label. */\n name: string;\n /** App version, independent of the package version. */\n version: string;\n /** One-line summary shown in the About dialog. */\n description: string;\n /** Registry route — used to look up the consumer-registered nav icon. */\n route: string;\n}\n\nexport const BUILTIN_APP_INFO = {\n spreadsheet: {\n name: 'Spreadsheets',\n version: '1.1.3',\n route: '/spreadsheet',\n description: 'Multi-sheet spreadsheet editor with CSV / TSV import and export.',\n },\n notepad: {\n name: 'Notepad',\n version: '1.0.0',\n route: '/notepad',\n description: 'Color-coded notes with checklists, desktop stickies and entity autolinking.',\n },\n documents: {\n name: 'Documents',\n version: '1.1.0',\n route: '/documents',\n description: 'Letter-page editor for Word documents and plain-text files — images, lists, alignment.',\n },\n preview: {\n name: 'Preview',\n version: '1.3.2',\n route: '/preview',\n description: 'Viewer for PDF documents, images, DXF drawings and 3D models — CAD-style measuring with object snap and an AutoCAD-like command bar.',\n },\n files: {\n name: 'Files',\n version: '1.1.0',\n route: '/files',\n description: 'Personal file manager with folders, uploads, quota, trash and desktop shortcut folders.',\n },\n browser: {\n name: 'Browser',\n version: '1.0.1',\n route: '/browser',\n description: 'Minimal web browser with bookmarks, history and navigation bar.',\n },\n} satisfies Record<string, BuiltinAppInfo>;\n\nexport type BuiltinAppId = keyof typeof BUILTIN_APP_INFO;\n\nconst ABOUT_MENU_ICON = (\n <svg className=\"h-4 w-4 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z\" />\n </svg>\n);\n\n// Generic window glyph shown when the consumer hasn't registered a nav icon\n// for the app's route (same fallback shape as the Modal title bar).\nconst FALLBACK_APP_ICON = (\n <svg className=\"h-9 w-9\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 6.75A2.25 2.25 0 016 4.5h12a2.25 2.25 0 012.25 2.25v10.5A2.25 2.25 0 0118 19.5H6a2.25 2.25 0 01-2.25-2.25V6.75z M3.75 9h16.5\" />\n </svg>\n);\n\n/** Registers \"About <Name>\" in the window title menu and renders the dialog.\n * Render anywhere inside the app's window. */\nexport default function AboutApp({ app }: { app: BuiltinAppId }) {\n const info = BUILTIN_APP_INFO[app];\n const [open, setOpen] = useState(false);\n const openDialog = useCallback(() => setOpen(true), []);\n useWindowMenuItem(`About ${info.name}`, openDialog, ABOUT_MENU_ICON);\n\n if (!open) return null;\n\n const registered = navIcons[info.route];\n const appIcon = isValidElement(registered)\n ? cloneElement(registered as ReactElement, { className: 'h-9 w-9' } as any)\n : FALLBACK_APP_ICON;\n\n return (\n <Modal open onClose={() => setOpen(false)} title={`About ${info.name}`} size=\"sm\" compact bodyScroll={false} autoHeight dimensions={[320, 320]}>\n <div className=\"flex flex-col items-center text-center px-5 pt-5 pb-4\">\n <div className=\"flex h-16 w-16 items-center justify-center rounded-2xl bg-gray-100 text-gray-600 shrink-0\">\n {appIcon}\n </div>\n <h2 className=\"mt-3 text-lg font-bold text-gray-900\">{info.name}</h2>\n <p className=\"text-[11px] font-mono text-gray-400\">Version {info.version}</p>\n <p className=\"mt-2 text-xs text-gray-500 leading-relaxed\">{info.description}</p>\n <div className=\"mt-4 pt-3 border-t border-gray-200 w-full\">\n <p className=\"text-[11px] text-gray-500\">\n Part of the <span className=\"font-medium text-gray-700\">efficient-shell</span> desktop environment\n </p>\n {VERSION && <p className=\"mt-0.5 text-[10px] font-mono text-gray-400\">shell v{VERSION}</p>}\n </div>\n </div>\n </Modal>\n );\n}\n"]}
@@ -1,265 +0,0 @@
1
- // src/utils/sounds.ts
2
- var audioCtx = null;
3
- function getCtx() {
4
- if (!audioCtx) audioCtx = new AudioContext();
5
- return audioCtx;
6
- }
7
- function tone(freq, dur, type = "sine", vol = 0.15) {
8
- try {
9
- const ctx = getCtx();
10
- const osc = ctx.createOscillator();
11
- const gain = ctx.createGain();
12
- osc.type = type;
13
- osc.frequency.value = freq;
14
- gain.gain.value = vol;
15
- gain.gain.exponentialRampToValueAtTime(1e-3, ctx.currentTime + dur);
16
- osc.connect(gain);
17
- gain.connect(ctx.destination);
18
- osc.start();
19
- osc.stop(ctx.currentTime + dur);
20
- } catch {
21
- }
22
- }
23
- var classic = {
24
- label: "Classic",
25
- success: () => {
26
- tone(523, 0.1, "sine", 0.1);
27
- setTimeout(() => tone(659, 0.1, "sine", 0.1), 100);
28
- setTimeout(() => tone(784, 0.15, "sine", 0.1), 200);
29
- },
30
- error: () => {
31
- tone(200, 0.15, "sawtooth", 0.08);
32
- setTimeout(() => tone(180, 0.15, "sawtooth", 0.08), 150);
33
- },
34
- notification: () => {
35
- tone(880, 0.08, "sine", 0.12);
36
- setTimeout(() => tone(1100, 0.12, "sine", 0.1), 100);
37
- },
38
- startup: () => {
39
- tone(392, 0.15, "sine", 0.08);
40
- setTimeout(() => tone(523, 0.15, "sine", 0.08), 150);
41
- setTimeout(() => tone(659, 0.15, "sine", 0.08), 300);
42
- setTimeout(() => tone(784, 0.25, "sine", 0.1), 450);
43
- },
44
- logout: () => {
45
- tone(784, 0.15, "sine", 0.08);
46
- setTimeout(() => tone(659, 0.15, "sine", 0.08), 150);
47
- setTimeout(() => tone(523, 0.15, "sine", 0.08), 300);
48
- setTimeout(() => tone(392, 0.25, "sine", 0.06), 450);
49
- },
50
- click: () => {
51
- tone(800, 0.05, "square", 0.05);
52
- },
53
- timerDone: () => {
54
- for (let i = 0; i < 3; i++) {
55
- setTimeout(() => tone(1e3, 0.15, "sine", 0.12), i * 300);
56
- setTimeout(() => tone(800, 0.15, "sine", 0.1), i * 300 + 150);
57
- }
58
- }
59
- };
60
- var minimal = {
61
- label: "Minimal",
62
- success: () => {
63
- tone(1200, 0.06, "sine", 0.08);
64
- },
65
- error: () => {
66
- tone(300, 0.1, "triangle", 0.06);
67
- },
68
- notification: () => {
69
- tone(900, 0.06, "sine", 0.08);
70
- },
71
- startup: () => {
72
- tone(600, 0.12, "sine", 0.06);
73
- setTimeout(() => tone(900, 0.15, "sine", 0.06), 120);
74
- },
75
- click: () => {
76
- tone(1e3, 0.03, "sine", 0.03);
77
- },
78
- timerDone: () => {
79
- tone(1e3, 0.2, "sine", 0.1);
80
- setTimeout(() => tone(1e3, 0.2, "sine", 0.1), 400);
81
- },
82
- logout: () => {
83
- tone(900, 0.1, "sine", 0.06);
84
- setTimeout(() => tone(600, 0.15, "sine", 0.05), 120);
85
- }
86
- };
87
- var retro = {
88
- label: "Retro",
89
- success: () => {
90
- tone(440, 0.08, "square", 0.08);
91
- setTimeout(() => tone(550, 0.08, "square", 0.08), 80);
92
- setTimeout(() => tone(660, 0.08, "square", 0.08), 160);
93
- setTimeout(() => tone(880, 0.12, "square", 0.1), 240);
94
- },
95
- error: () => {
96
- tone(150, 0.2, "square", 0.06);
97
- setTimeout(() => tone(100, 0.3, "square", 0.06), 200);
98
- },
99
- notification: () => {
100
- tone(660, 0.06, "square", 0.08);
101
- setTimeout(() => tone(880, 0.06, "square", 0.08), 80);
102
- setTimeout(() => tone(660, 0.06, "square", 0.08), 160);
103
- },
104
- startup: () => {
105
- [262, 330, 392, 523].forEach((f, i) => setTimeout(() => tone(f, 0.1, "square", 0.07), i * 100));
106
- },
107
- click: () => {
108
- tone(600, 0.03, "square", 0.06);
109
- },
110
- timerDone: () => {
111
- for (let i = 0; i < 4; i++) setTimeout(() => tone(880, 0.1, "square", 0.1), i * 200);
112
- },
113
- logout: () => {
114
- [523, 392, 330, 262].forEach((f, i) => setTimeout(() => tone(f, 0.1, "square", 0.07), i * 100));
115
- }
116
- };
117
- var soft = {
118
- label: "Soft",
119
- success: () => {
120
- tone(700, 0.2, "sine", 0.06);
121
- setTimeout(() => tone(900, 0.25, "sine", 0.06), 200);
122
- },
123
- error: () => {
124
- tone(250, 0.2, "sine", 0.05);
125
- },
126
- notification: () => {
127
- tone(600, 0.15, "triangle", 0.06);
128
- setTimeout(() => tone(800, 0.2, "triangle", 0.05), 180);
129
- },
130
- startup: () => {
131
- tone(400, 0.3, "sine", 0.05);
132
- setTimeout(() => tone(500, 0.3, "sine", 0.05), 300);
133
- setTimeout(() => tone(600, 0.4, "sine", 0.06), 600);
134
- },
135
- click: () => {
136
- tone(500, 0.04, "triangle", 0.03);
137
- },
138
- timerDone: () => {
139
- tone(700, 0.3, "triangle", 0.08);
140
- setTimeout(() => tone(700, 0.3, "triangle", 0.08), 500);
141
- setTimeout(() => tone(900, 0.4, "triangle", 0.08), 1e3);
142
- },
143
- logout: () => {
144
- tone(600, 0.3, "sine", 0.05);
145
- setTimeout(() => tone(400, 0.4, "sine", 0.04), 300);
146
- }
147
- };
148
- var arcade = {
149
- label: "Arcade",
150
- success: () => {
151
- [523, 659, 784, 1047].forEach((f, i) => setTimeout(() => tone(f, 0.06, "square", 0.07), i * 60));
152
- },
153
- error: () => {
154
- tone(100, 0.3, "sawtooth", 0.06);
155
- setTimeout(() => tone(80, 0.4, "sawtooth", 0.05), 200);
156
- },
157
- notification: () => {
158
- tone(1047, 0.05, "square", 0.08);
159
- setTimeout(() => tone(784, 0.05, "square", 0.08), 60);
160
- setTimeout(() => tone(1047, 0.08, "square", 0.1), 120);
161
- },
162
- startup: () => {
163
- [262, 330, 392, 523, 659, 784].forEach((f, i) => setTimeout(() => tone(f, 0.08, "square", 0.06), i * 80));
164
- },
165
- click: () => {
166
- tone(1200, 0.02, "square", 0.05);
167
- },
168
- timerDone: () => {
169
- for (let i = 0; i < 5; i++) setTimeout(() => tone(1200, 0.05, "square", 0.1), i * 120);
170
- },
171
- logout: () => {
172
- [784, 659, 523, 392, 262].forEach((f, i) => setTimeout(() => tone(f, 0.06, "square", 0.06), i * 60));
173
- }
174
- };
175
- var silent = {
176
- label: "Silent",
177
- success: () => {
178
- },
179
- error: () => {
180
- },
181
- notification: () => {
182
- },
183
- startup: () => {
184
- },
185
- click: () => {
186
- },
187
- timerDone: () => {
188
- },
189
- logout: () => {
190
- }
191
- };
192
- var SOUND_PACKS = { classic, minimal, retro, soft, arcade, silent };
193
- var SOUND_PACK_KEYS = Object.keys(SOUND_PACKS);
194
- var SOUND_TYPES = ["click", "success", "error", "notification", "startup", "timerDone", "logout"];
195
- var SOUND_TYPE_LABELS = {
196
- click: "Click",
197
- success: "Success",
198
- error: "Error",
199
- notification: "Notification",
200
- startup: "Startup",
201
- timerDone: "Timer",
202
- logout: "Logout"
203
- };
204
- var STORAGE_KEY = "erp_sound_config";
205
- function soundsEnabled() {
206
- return localStorage.getItem("erp_sounds") !== "false";
207
- }
208
- function toggleSounds() {
209
- const next = !soundsEnabled();
210
- localStorage.setItem("erp_sounds", String(next));
211
- return next;
212
- }
213
- function getSoundConfig() {
214
- try {
215
- const stored = JSON.parse(localStorage.getItem(STORAGE_KEY) || "");
216
- if (stored && typeof stored === "object") return { click: "classic", success: "classic", error: "classic", notification: "classic", startup: "classic", timerDone: "classic", logout: "classic", ...stored };
217
- } catch {
218
- }
219
- return { click: "classic", success: "classic", error: "classic", notification: "classic", startup: "classic", timerDone: "classic", logout: "classic" };
220
- }
221
- function setSoundForType(soundType, packKey) {
222
- const config = getSoundConfig();
223
- config[soundType] = packKey;
224
- localStorage.setItem(STORAGE_KEY, JSON.stringify(config));
225
- }
226
- function setAllSounds(packKey) {
227
- const config = {};
228
- SOUND_TYPES.forEach((t) => {
229
- config[t] = packKey;
230
- });
231
- localStorage.setItem(STORAGE_KEY, JSON.stringify(config));
232
- }
233
- function getPackForType(soundType) {
234
- const config = getSoundConfig();
235
- return SOUND_PACKS[config[soundType]] || classic;
236
- }
237
- function playClick() {
238
- if (soundsEnabled()) getPackForType("click").click();
239
- }
240
- function playSuccess() {
241
- if (soundsEnabled()) getPackForType("success").success();
242
- }
243
- function playError() {
244
- if (soundsEnabled()) getPackForType("error").error();
245
- }
246
- function playNotification() {
247
- if (soundsEnabled()) getPackForType("notification").notification();
248
- }
249
- function playStartup() {
250
- if (soundsEnabled()) getPackForType("startup").startup();
251
- }
252
- function playTimerDone() {
253
- if (soundsEnabled()) getPackForType("timerDone").timerDone();
254
- }
255
- function playLogout() {
256
- if (soundsEnabled()) getPackForType("logout").logout();
257
- }
258
- function previewSound(packKey, sound) {
259
- const pack = SOUND_PACKS[packKey];
260
- if (pack && typeof pack[sound] === "function") pack[sound]();
261
- }
262
-
263
- export { SOUND_PACKS, SOUND_PACK_KEYS, SOUND_TYPES, SOUND_TYPE_LABELS, getSoundConfig, playClick, playError, playLogout, playNotification, playStartup, playSuccess, playTimerDone, previewSound, setAllSounds, setSoundForType, soundsEnabled, toggleSounds };
264
- //# sourceMappingURL=chunk-D7PYW2QS.js.map
265
- //# sourceMappingURL=chunk-D7PYW2QS.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/sounds.ts"],"names":[],"mappings":"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","file":"chunk-D7PYW2QS.js","sourcesContent":["/**\n * Custom sound effects using Web Audio API.\n * Multiple sound packs — user can choose in Customization > Desktop.\n */\n\nlet audioCtx: AudioContext | null = null;\n\nfunction getCtx(): AudioContext {\n if (!audioCtx) audioCtx = new AudioContext();\n return audioCtx;\n}\n\nfunction tone(freq: number, dur: number, type: OscillatorType = 'sine', vol = 0.15) {\n try {\n const ctx = getCtx();\n const osc = ctx.createOscillator();\n const gain = ctx.createGain();\n osc.type = type;\n osc.frequency.value = freq;\n gain.gain.value = vol;\n gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + dur);\n osc.connect(gain);\n gain.connect(ctx.destination);\n osc.start();\n osc.stop(ctx.currentTime + dur);\n } catch { /* Audio not available */ }\n}\n\nfunction delay(ms: number) { return new Promise(r => setTimeout(r, ms)); }\n\n// ── Sound Pack Definitions ──\n\ninterface SoundPack {\n label: string;\n success: () => void;\n error: () => void;\n notification: () => void;\n startup: () => void;\n click: () => void;\n timerDone: () => void;\n logout: () => void;\n}\n\nconst classic: SoundPack = {\n label: 'Classic',\n success: () => { tone(523, 0.1, 'sine', 0.1); setTimeout(() => tone(659, 0.1, 'sine', 0.1), 100); setTimeout(() => tone(784, 0.15, 'sine', 0.1), 200); },\n error: () => { tone(200, 0.15, 'sawtooth', 0.08); setTimeout(() => tone(180, 0.15, 'sawtooth', 0.08), 150); },\n notification: () => { tone(880, 0.08, 'sine', 0.12); setTimeout(() => tone(1100, 0.12, 'sine', 0.1), 100); },\n startup: () => { tone(392, 0.15, 'sine', 0.08); setTimeout(() => tone(523, 0.15, 'sine', 0.08), 150); setTimeout(() => tone(659, 0.15, 'sine', 0.08), 300); setTimeout(() => tone(784, 0.25, 'sine', 0.1), 450); },\n logout: () => { tone(784, 0.15, 'sine', 0.08); setTimeout(() => tone(659, 0.15, 'sine', 0.08), 150); setTimeout(() => tone(523, 0.15, 'sine', 0.08), 300); setTimeout(() => tone(392, 0.25, 'sine', 0.06), 450); },\n click: () => { tone(800, 0.05, 'square', 0.05); },\n timerDone: () => { for (let i = 0; i < 3; i++) { setTimeout(() => tone(1000, 0.15, 'sine', 0.12), i * 300); setTimeout(() => tone(800, 0.15, 'sine', 0.1), i * 300 + 150); } },\n};\n\nconst minimal: SoundPack = {\n label: 'Minimal',\n success: () => { tone(1200, 0.06, 'sine', 0.08); },\n error: () => { tone(300, 0.1, 'triangle', 0.06); },\n notification: () => { tone(900, 0.06, 'sine', 0.08); },\n startup: () => { tone(600, 0.12, 'sine', 0.06); setTimeout(() => tone(900, 0.15, 'sine', 0.06), 120); },\n click: () => { tone(1000, 0.03, 'sine', 0.03); },\n timerDone: () => { tone(1000, 0.2, 'sine', 0.1); setTimeout(() => tone(1000, 0.2, 'sine', 0.1), 400); },\n logout: () => { tone(900, 0.1, 'sine', 0.06); setTimeout(() => tone(600, 0.15, 'sine', 0.05), 120); },\n};\n\nconst retro: SoundPack = {\n label: 'Retro',\n success: () => { tone(440, 0.08, 'square', 0.08); setTimeout(() => tone(550, 0.08, 'square', 0.08), 80); setTimeout(() => tone(660, 0.08, 'square', 0.08), 160); setTimeout(() => tone(880, 0.12, 'square', 0.1), 240); },\n error: () => { tone(150, 0.2, 'square', 0.06); setTimeout(() => tone(100, 0.3, 'square', 0.06), 200); },\n notification: () => { tone(660, 0.06, 'square', 0.08); setTimeout(() => tone(880, 0.06, 'square', 0.08), 80); setTimeout(() => tone(660, 0.06, 'square', 0.08), 160); },\n startup: () => { [262, 330, 392, 523].forEach((f, i) => setTimeout(() => tone(f, 0.1, 'square', 0.07), i * 100)); },\n click: () => { tone(600, 0.03, 'square', 0.06); },\n timerDone: () => { for (let i = 0; i < 4; i++) setTimeout(() => tone(880, 0.1, 'square', 0.1), i * 200); },\n logout: () => { [523, 392, 330, 262].forEach((f, i) => setTimeout(() => tone(f, 0.1, 'square', 0.07), i * 100)); },\n};\n\nconst soft: SoundPack = {\n label: 'Soft',\n success: () => { tone(700, 0.2, 'sine', 0.06); setTimeout(() => tone(900, 0.25, 'sine', 0.06), 200); },\n error: () => { tone(250, 0.2, 'sine', 0.05); },\n notification: () => { tone(600, 0.15, 'triangle', 0.06); setTimeout(() => tone(800, 0.2, 'triangle', 0.05), 180); },\n startup: () => { tone(400, 0.3, 'sine', 0.05); setTimeout(() => tone(500, 0.3, 'sine', 0.05), 300); setTimeout(() => tone(600, 0.4, 'sine', 0.06), 600); },\n click: () => { tone(500, 0.04, 'triangle', 0.03); },\n timerDone: () => { tone(700, 0.3, 'triangle', 0.08); setTimeout(() => tone(700, 0.3, 'triangle', 0.08), 500); setTimeout(() => tone(900, 0.4, 'triangle', 0.08), 1000); },\n logout: () => { tone(600, 0.3, 'sine', 0.05); setTimeout(() => tone(400, 0.4, 'sine', 0.04), 300); },\n};\n\nconst arcade: SoundPack = {\n label: 'Arcade',\n success: () => { [523, 659, 784, 1047].forEach((f, i) => setTimeout(() => tone(f, 0.06, 'square', 0.07), i * 60)); },\n error: () => { tone(100, 0.3, 'sawtooth', 0.06); setTimeout(() => tone(80, 0.4, 'sawtooth', 0.05), 200); },\n notification: () => { tone(1047, 0.05, 'square', 0.08); setTimeout(() => tone(784, 0.05, 'square', 0.08), 60); setTimeout(() => tone(1047, 0.08, 'square', 0.1), 120); },\n startup: () => { [262, 330, 392, 523, 659, 784].forEach((f, i) => setTimeout(() => tone(f, 0.08, 'square', 0.06), i * 80)); },\n click: () => { tone(1200, 0.02, 'square', 0.05); },\n timerDone: () => { for (let i = 0; i < 5; i++) setTimeout(() => tone(1200, 0.05, 'square', 0.1), i * 120); },\n logout: () => { [784, 659, 523, 392, 262].forEach((f, i) => setTimeout(() => tone(f, 0.06, 'square', 0.06), i * 60)); },\n};\n\nconst silent: SoundPack = {\n label: 'Silent',\n success: () => {}, error: () => {}, notification: () => {},\n startup: () => {}, click: () => {}, timerDone: () => {}, logout: () => {},\n};\n\nexport const SOUND_PACKS: Record<string, SoundPack> = { classic, minimal, retro, soft, arcade, silent };\n\n/** All pack keys including silent */\nexport const SOUND_PACK_KEYS = Object.keys(SOUND_PACKS) as string[];\n\n// ── Sound types ──\nexport const SOUND_TYPES = ['click', 'success', 'error', 'notification', 'startup', 'timerDone', 'logout'] as const;\nexport type SoundType = typeof SOUND_TYPES[number];\n\nexport const SOUND_TYPE_LABELS: Record<SoundType, string> = {\n click: 'Click', success: 'Success', error: 'Error',\n notification: 'Notification', startup: 'Startup', timerDone: 'Timer', logout: 'Logout',\n};\n\n// ── State: per-sound pack selection ──\n\nconst STORAGE_KEY = 'erp_sound_config';\n\nexport function soundsEnabled(): boolean {\n return localStorage.getItem('erp_sounds') !== 'false';\n}\n\nexport function toggleSounds(): boolean {\n const next = !soundsEnabled();\n localStorage.setItem('erp_sounds', String(next));\n return next;\n}\n\n/** Get the per-sound configuration: { click: 'classic', success: 'retro', ... } */\nexport function getSoundConfig(): Record<SoundType, string> {\n try {\n const stored = JSON.parse(localStorage.getItem(STORAGE_KEY) || '');\n if (stored && typeof stored === 'object') return { click: 'classic', success: 'classic', error: 'classic', notification: 'classic', startup: 'classic', timerDone: 'classic', logout: 'classic', ...stored };\n } catch {}\n return { click: 'classic', success: 'classic', error: 'classic', notification: 'classic', startup: 'classic', timerDone: 'classic', logout: 'classic' };\n}\n\n/** Set the pack for a specific sound type */\nexport function setSoundForType(soundType: SoundType, packKey: string) {\n const config = getSoundConfig();\n config[soundType] = packKey;\n localStorage.setItem(STORAGE_KEY, JSON.stringify(config));\n}\n\n/** Set all sounds to a specific pack */\nexport function setAllSounds(packKey: string) {\n const config: Record<string, string> = {};\n SOUND_TYPES.forEach(t => { config[t] = packKey; });\n localStorage.setItem(STORAGE_KEY, JSON.stringify(config));\n}\n\nfunction getPackForType(soundType: SoundType): SoundPack {\n const config = getSoundConfig();\n return SOUND_PACKS[config[soundType]] || classic;\n}\n\n// ── Public API ──\n\nexport function playClick() { if (soundsEnabled()) getPackForType('click').click(); }\nexport function playSuccess() { if (soundsEnabled()) getPackForType('success').success(); }\nexport function playError() { if (soundsEnabled()) getPackForType('error').error(); }\nexport function playNotification() { if (soundsEnabled()) getPackForType('notification').notification(); }\nexport function playStartup() { if (soundsEnabled()) getPackForType('startup').startup(); }\nexport function playTimerDone() { if (soundsEnabled()) getPackForType('timerDone').timerDone(); }\nexport function playLogout() { if (soundsEnabled()) getPackForType('logout').logout(); }\n\n/** Preview a specific sound from a specific pack (ignores enabled state) */\nexport function previewSound(packKey: string, sound: SoundType) {\n const pack = SOUND_PACKS[packKey];\n if (pack && typeof pack[sound] === 'function') (pack[sound] as () => void)();\n}\n"]}
@@ -1,26 +0,0 @@
1
- // src/apps/_previewStage.ts
2
- var PDF_PREVIEW_UPDATE_EVENT = "react-os-shell:pdf-preview-update";
3
- var pending = null;
4
- var nextToken = 0;
5
- function setPdfPreview(data) {
6
- const token = ++nextToken;
7
- const stage = { token, data };
8
- pending = stage;
9
- return {
10
- update(next) {
11
- if (pending === stage) stage.data = next;
12
- if (typeof window === "undefined") return;
13
- window.dispatchEvent(new CustomEvent(PDF_PREVIEW_UPDATE_EVENT, { detail: { token, data: next } }));
14
- }
15
- };
16
- }
17
- function peekPdfPreviewStage() {
18
- return pending;
19
- }
20
- function claimPdfPreviewStage(stage) {
21
- if (pending === stage) pending = null;
22
- }
23
-
24
- export { PDF_PREVIEW_UPDATE_EVENT, claimPdfPreviewStage, peekPdfPreviewStage, setPdfPreview };
25
- //# sourceMappingURL=chunk-DVZWYWSD.js.map
26
- //# sourceMappingURL=chunk-DVZWYWSD.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/apps/_previewStage.ts"],"names":[],"mappings":";AA+CO,IAAM,wBAAA,GAA2B;AAaxC,IAAI,OAAA,GAAkC,IAAA;AACtC,IAAI,SAAA,GAAY,CAAA;AAKT,SAAS,cAAc,IAAA,EAAwC;AACpE,EAAA,MAAM,QAAQ,EAAE,SAAA;AAChB,EAAA,MAAM,KAAA,GAAyB,EAAE,KAAA,EAAO,IAAA,EAAK;AAC7C,EAAA,OAAA,GAAU,KAAA;AACV,EAAA,OAAO;AAAA,IACL,OAAO,IAAA,EAAsB;AAY3B,MAAA,IAAI,OAAA,KAAY,KAAA,EAAO,KAAA,CAAM,IAAA,GAAO,IAAA;AACpC,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,WAAA,CAAY,wBAAA,EAA0B,EAAE,MAAA,EAAQ,EAAE,KAAA,EAAO,IAAA,EAAM,IAAA,EAAK,EAAG,CAAC,CAAA;AAAA,IACnG;AAAA,GACF;AACF;AAGO,SAAS,mBAAA,GAA8C;AAC5D,EAAA,OAAO,OAAA;AACT;AAKO,SAAS,qBAAqB,KAAA,EAA8B;AACjE,EAAA,IAAI,OAAA,KAAY,OAAO,OAAA,GAAU,IAAA;AACnC","file":"chunk-DVZWYWSD.js","sourcesContent":["/**\n * PDF Preview staging — the tiny consumer-facing surface of the Preview app.\n *\n * Lives apart from Preview.tsx so importing `setPdfPreview` (from\n * `efficient-shell/apps` or shell internals like PdfActionButton /\n * openPreviewFile) never drags the viewer implementation — and its static\n * pdfjs-dist import — into a host's startup bundle. The Preview window\n * component stays behind its React.lazy dynamic import and drains the stage\n * on mount via the @internal peek/claim helpers below.\n */\n\nexport interface PdfPreviewData {\n /** Object URL or remote URL of the PDF. Blob URLs are revoked when the window unmounts.\n * Leave blank when staging a `converting: true` placeholder; call `handle.update({...})`\n * on the handle returned by `setPdfPreview` once conversion finishes. */\n url?: string;\n /** Display name (and download filename). */\n filename: string;\n /** Renderer to use. Defaults to `'pdf'`. `'dxf'` requires the consumer to\n * have `dxf-viewer` installed (it's an optional peer dep). `'image'`\n * renders an `<img>` for raster screenshots / photos. `'3d'` covers\n * STEP / STL / OBJ / GLTF / 3MF / IGES via the optional\n * `online-3d-viewer` peer dep. */\n kind?: 'pdf' | 'dxf' | 'image' | '3d';\n /** Optional download handler — replaces the built-in \"save URL as filename\" if supplied. */\n onDownload?: () => void;\n /** Optional email handler — only shown when supplied. */\n onEmail?: () => void;\n /** Show a progress placeholder while the consumer fetches/converts the file. */\n converting?: boolean;\n /** Headline shown on the converting placeholder (e.g. \"CONVERTING DWG FILE\"). */\n convertingMessage?: string;\n}\n\n/** Handle returned by `setPdfPreview`. Holds the identity of the staged\n * payload so a later `.update()` only targets the window that picked it up\n * (not every open Preview, which would clobber unrelated windows). */\nexport interface PdfPreviewHandle {\n /** Replace the data shown in the window that consumed this staging. Safe to\n * call before that window exists — an update that lands while the payload\n * is still staged replaces the staged payload, so the window opens on the\n * resolved file instead of the placeholder it was staged with.\n * No-op only once the window that consumed the staging has been closed. */\n update(next: PdfPreviewData): void;\n}\n\n/** @internal Event carrying `.update()` payloads to the claiming window. */\nexport const PDF_PREVIEW_UPDATE_EVENT = 'react-os-shell:pdf-preview-update';\n\n/** @internal Staged payload awaiting the next Preview window mount.\n *\n * `data` is MUTABLE and deliberately so: `update()` rewrites it in place\n * while the stage is still unclaimed. Restaging a fresh object instead would\n * break the identity that `claimPdfPreviewStage` and the claimant's own\n * `consumedRef` are holding. */\nexport interface PendingPdfStage {\n token: number;\n data: PdfPreviewData;\n}\n\nlet pending: PendingPdfStage | null = null;\nlet nextToken = 0;\n\n/** Stage a PDF for the next Preview window mount. The returned handle's\n * `update()` method swaps content in *that* specific window only — use it\n * to replace a `converting: true` placeholder with the resolved file. */\nexport function setPdfPreview(data: PdfPreviewData): PdfPreviewHandle {\n const token = ++nextToken;\n const stage: PendingPdfStage = { token, data };\n pending = stage;\n return {\n update(next: PdfPreviewData) {\n // The window is opened by `openPage('/preview')` and Preview is a lazy\n // chunk, so a consumer that resolves quickly — a cached PDF, a fast\n // endpoint, a second preview in the same session — can call this before\n // any window has mounted to listen. The event is fire-and-forget, so on\n // its own it would be dropped and the window would open on the\n // placeholder and sit there for ever. Rewrite the stage as well while it\n // is still ours: whoever drains it next gets the current payload.\n //\n // `pending === stage` is exactly \"no window has claimed this yet\".\n // Claiming and binding the listener happen in the same commit (see\n // Preview.tsx), so there is no third state where both paths miss.\n if (pending === stage) stage.data = next;\n if (typeof window === 'undefined') return;\n window.dispatchEvent(new CustomEvent(PDF_PREVIEW_UPDATE_EVENT, { detail: { token, data: next } }));\n },\n };\n}\n\n/** @internal Render-phase peek — see Preview.tsx for the drain protocol. */\nexport function peekPdfPreviewStage(): PendingPdfStage | null {\n return pending;\n}\n\n/** @internal Commit-phase claim. The identity check keeps a payload staged\n * *after* the claimant's render-phase peek available for the window it\n * belongs to. */\nexport function claimPdfPreviewStage(stage: PendingPdfStage): void {\n if (pending === stage) pending = null;\n}\n"]}