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.
- package/LICENSE +6 -17
- package/README.md +80 -12
- package/dist/Browser-24YNRTKT.js +43 -0
- package/dist/Calculator-LER6KUQC.js +29 -0
- package/dist/ConfirmDialog-GAYETRMG.js +1 -0
- package/dist/CurrencyConverter-Y35GFDFF.js +21 -0
- package/dist/Documents-7FYX2CGT.js +52 -0
- package/dist/Files-RZOML2N6.js +89 -0
- package/dist/Notepad-VVDCBDUA.js +25 -0
- package/dist/PdfViewer-CvLb2j_l.d.ts +40 -0
- package/dist/PdfViewer-ZCT3PYXU.js +1 -0
- package/dist/PomodoroTimer-VAM3AJOX.js +99 -0
- package/dist/Preview-HZ37D7QJ.js +187 -0
- package/dist/Sidebar-CVF7C6BO.js +23 -0
- package/dist/Spreadsheet-6WX3P6AB.js +37 -0
- package/dist/Stock-AUWI3TUX.js +16 -0
- package/dist/Weather-HU75TH7T.js +60 -0
- package/dist/WorldClock-T64MDRMJ.js +32 -0
- package/dist/apps/index.d.ts +3 -23
- package/dist/apps/index.js +1 -151
- package/dist/brand.css +1 -1
- package/dist/chunk-2RHMSFZV.js +9 -0
- package/dist/chunk-4FS742BM.js +1 -0
- package/dist/chunk-57MIENLJ.js +1 -0
- package/dist/chunk-7DAQ3WVP.js +106 -0
- package/dist/chunk-BR22X7E5.js +1 -0
- package/dist/chunk-BUTSU7FO.js +1 -0
- package/dist/chunk-CVTOZCM3.js +24 -0
- package/dist/chunk-D65T4H6J.js +1 -0
- package/dist/chunk-ESL5TDNA.js +1 -0
- package/dist/chunk-FBDZGO3V.js +1 -0
- package/dist/chunk-FHTLC7HH.js +1 -0
- package/dist/chunk-GDSGXDET.js +34 -0
- package/dist/chunk-I55UMU3R.js +6 -0
- package/dist/chunk-KKOHUQPF.js +1 -0
- package/dist/chunk-L7TEFXIS.js +69 -0
- package/dist/chunk-LVDRBRYU.js +1 -0
- package/dist/chunk-LVFMK5OQ.js +29 -0
- package/dist/chunk-LWLCNQY7.js +1 -0
- package/dist/chunk-MAIHBBWT.js +1 -0
- package/dist/chunk-MU5H2CDL.js +2 -0
- package/dist/chunk-NBBOFQPL.js +947 -0
- package/dist/chunk-NPJH5MD7.js +13 -0
- package/dist/chunk-OCSOMMY2.js +1 -0
- package/dist/chunk-PH3PRIFP.js +5 -0
- package/dist/chunk-RJ4LACFH.js +9 -0
- package/dist/chunk-SLCR26NK.js +4 -0
- package/dist/chunk-TFKB2WEB.js +19 -0
- package/dist/chunk-TR6PLN7W.js +1 -0
- package/dist/chunk-TWV42Q3K.js +1 -0
- package/dist/chunk-UB22J6EF.js +1 -0
- package/dist/chunk-UB4JIOLD.js +2 -0
- package/dist/chunk-V453E4KU.js +11 -0
- package/dist/chunk-VTVSMRFX.js +1 -0
- package/dist/file-intake/index.js +1 -4
- package/dist/{index-DVI9DMSu.d.ts → index-NhR7frRu.d.ts} +189 -17
- package/dist/index.d.ts +2 -2
- package/dist/index.js +639 -7473
- package/dist/map/index.d.ts +266 -13
- package/dist/map/index.js +22 -540
- package/dist/markdown/index.js +6 -184
- package/dist/markup/index.js +1 -135
- package/dist/page-tabs/index.js +21 -709
- package/dist/pdf/index.d.ts +9 -0
- package/dist/pdf/index.js +2 -0
- package/dist/sounds-OMHXVVQ4.js +1 -0
- package/dist/ui/index.d.ts +1 -1
- package/dist/ui/index.js +1 -19
- package/dist/ui.css +7 -0
- package/package.json +9 -3
- package/dist/Browser-ZNX4WFUH.js +0 -482
- package/dist/Browser-ZNX4WFUH.js.map +0 -1
- package/dist/Calculator-6FGNKOXU.js +0 -192
- package/dist/Calculator-6FGNKOXU.js.map +0 -1
- package/dist/ConfirmDialog-NPQMIGUR.js +0 -4
- package/dist/ConfirmDialog-NPQMIGUR.js.map +0 -1
- package/dist/CurrencyConverter-FF7EXRYL.js +0 -236
- package/dist/CurrencyConverter-FF7EXRYL.js.map +0 -1
- package/dist/Documents-H3R7XSBH.js +0 -441
- package/dist/Documents-H3R7XSBH.js.map +0 -1
- package/dist/Files-ZHJIAUC2.js +0 -805
- package/dist/Files-ZHJIAUC2.js.map +0 -1
- package/dist/Notepad-VE7ISWRQ.js +0 -410
- package/dist/Notepad-VE7ISWRQ.js.map +0 -1
- package/dist/PdfViewer-SQBFYAGW.js +0 -5
- package/dist/PdfViewer-SQBFYAGW.js.map +0 -1
- package/dist/PomodoroTimer-IR3WREED.js +0 -633
- package/dist/PomodoroTimer-IR3WREED.js.map +0 -1
- package/dist/Preview-DAQGRNRM.js +0 -2959
- package/dist/Preview-DAQGRNRM.js.map +0 -1
- package/dist/Sidebar-YW6H4NDJ.js +0 -291
- package/dist/Sidebar-YW6H4NDJ.js.map +0 -1
- package/dist/Spreadsheet-HOCPHJOC.js +0 -519
- package/dist/Spreadsheet-HOCPHJOC.js.map +0 -1
- package/dist/Stock-LVRQPURG.js +0 -158
- package/dist/Stock-LVRQPURG.js.map +0 -1
- package/dist/Weather-LZQGVDJL.js +0 -431
- package/dist/Weather-LZQGVDJL.js.map +0 -1
- package/dist/WorldClock-XPD7WOZT.js +0 -202
- package/dist/WorldClock-XPD7WOZT.js.map +0 -1
- package/dist/apps/index.js.map +0 -1
- package/dist/chunk-5O42JXQE.js +0 -26
- package/dist/chunk-5O42JXQE.js.map +0 -1
- package/dist/chunk-5RPTS3BT.js +0 -70
- package/dist/chunk-5RPTS3BT.js.map +0 -1
- package/dist/chunk-6XJEJWNJ.js +0 -61
- package/dist/chunk-6XJEJWNJ.js.map +0 -1
- package/dist/chunk-7CCHEEYC.js +0 -94
- package/dist/chunk-7CCHEEYC.js.map +0 -1
- package/dist/chunk-BE7FZOFU.js +0 -17
- package/dist/chunk-BE7FZOFU.js.map +0 -1
- package/dist/chunk-COWYSHG2.js +0 -79
- package/dist/chunk-COWYSHG2.js.map +0 -1
- package/dist/chunk-D7PYW2QS.js +0 -265
- package/dist/chunk-D7PYW2QS.js.map +0 -1
- package/dist/chunk-DVZWYWSD.js +0 -26
- package/dist/chunk-DVZWYWSD.js.map +0 -1
- package/dist/chunk-E7TB6WD2.js +0 -153
- package/dist/chunk-E7TB6WD2.js.map +0 -1
- package/dist/chunk-FIHOGVUP.js +0 -416
- package/dist/chunk-FIHOGVUP.js.map +0 -1
- package/dist/chunk-GA35NEND.js +0 -56
- package/dist/chunk-GA35NEND.js.map +0 -1
- package/dist/chunk-HUBJAUGG.js +0 -316
- package/dist/chunk-HUBJAUGG.js.map +0 -1
- package/dist/chunk-I2TAAJHS.js +0 -465
- package/dist/chunk-I2TAAJHS.js.map +0 -1
- package/dist/chunk-ICTRCKUE.js +0 -3710
- package/dist/chunk-ICTRCKUE.js.map +0 -1
- package/dist/chunk-IPXN646P.js +0 -14
- package/dist/chunk-IPXN646P.js.map +0 -1
- package/dist/chunk-IRWSRJ4K.js +0 -48
- package/dist/chunk-IRWSRJ4K.js.map +0 -1
- package/dist/chunk-JOPU6WPY.js +0 -504
- package/dist/chunk-JOPU6WPY.js.map +0 -1
- package/dist/chunk-MGGY74RY.js +0 -14
- package/dist/chunk-MGGY74RY.js.map +0 -1
- package/dist/chunk-PVPPAWVM.js +0 -46
- package/dist/chunk-PVPPAWVM.js.map +0 -1
- package/dist/chunk-R7QGMK6N.js +0 -102
- package/dist/chunk-R7QGMK6N.js.map +0 -1
- package/dist/chunk-RT6DSB5Y.js +0 -143
- package/dist/chunk-RT6DSB5Y.js.map +0 -1
- package/dist/chunk-TRCWINHF.js +0 -105
- package/dist/chunk-TRCWINHF.js.map +0 -1
- package/dist/chunk-TW7LPMVR.js +0 -16
- package/dist/chunk-TW7LPMVR.js.map +0 -1
- package/dist/chunk-UTYKLGGT.js +0 -195
- package/dist/chunk-UTYKLGGT.js.map +0 -1
- package/dist/chunk-VNJJCH5A.js +0 -822
- package/dist/chunk-VNJJCH5A.js.map +0 -1
- package/dist/chunk-XJHZWSKV.js +0 -1103
- package/dist/chunk-XJHZWSKV.js.map +0 -1
- package/dist/chunk-Y3GYJ7YR.js +0 -549
- package/dist/chunk-Y3GYJ7YR.js.map +0 -1
- package/dist/chunk-YA4EE7ST.js +0 -14107
- package/dist/chunk-YA4EE7ST.js.map +0 -1
- package/dist/chunk-YDHXWCCJ.js +0 -145
- package/dist/chunk-YDHXWCCJ.js.map +0 -1
- package/dist/chunk-YE6GUDGP.js +0 -548
- package/dist/chunk-YE6GUDGP.js.map +0 -1
- package/dist/chunk-YNKK7NE3.js +0 -171
- package/dist/chunk-YNKK7NE3.js.map +0 -1
- package/dist/chunk-YPO6RDMX.js +0 -20
- package/dist/chunk-YPO6RDMX.js.map +0 -1
- package/dist/chunk-ZS7PMGUW.js +0 -7
- package/dist/chunk-ZS7PMGUW.js.map +0 -1
- package/dist/file-intake/index.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/map/index.js.map +0 -1
- package/dist/markdown/index.js.map +0 -1
- package/dist/markup/index.js.map +0 -1
- package/dist/page-tabs/index.js.map +0 -1
- package/dist/sounds-NT4DEZGD.js +0 -3
- package/dist/sounds-NT4DEZGD.js.map +0 -1
- package/dist/ui/index.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/apps/Weather.tsx"],"names":["parts","h","m","t"],"mappings":"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","file":"Weather-LZQGVDJL.js","sourcesContent":["import { useState, useEffect, useCallback } from 'react';\nimport { useWidgetSettings } from '../shell/Modal';\nimport WidgetSettingsModal, { loadAppearance, type WidgetAppearance } from '../shell/WidgetSettingsModal';\nimport { useShellPrefs } from '../shell/ShellPrefs';\nimport { AVAILABLE_CITIES, fetchCityWeather, getCondition, toFahrenheit, type CityWeather } from './_weatherData';\n\nconst STORAGE_KEY = 'weather_city';\nconst LEGACY_KEY = 'weather_cities';\nconst SETTINGS_KEY = 'weather_appearance';\n\ninterface WeatherPrefs { useFahrenheit: boolean; showLocalTime: boolean; use24Hour: boolean }\nconst DEFAULT_PREFS: WeatherPrefs = { useFahrenheit: false, showLocalTime: true, use24Hour: false };\n\nfunction detectLocalCity(): string {\n try {\n const userTz = Intl.DateTimeFormat().resolvedOptions().timeZone;\n for (const [name, info] of Object.entries(AVAILABLE_CITIES)) {\n if (info.tz === userTz) return name;\n }\n } catch {}\n return 'London';\n}\n\nfunction loadCity(): string {\n const v = typeof localStorage !== 'undefined' ? localStorage.getItem(STORAGE_KEY) : null;\n if (v && AVAILABLE_CITIES[v]) return v;\n try {\n const arr = JSON.parse(localStorage.getItem(LEGACY_KEY) || '');\n if (Array.isArray(arr) && arr[0] && AVAILABLE_CITIES[arr[0]]) {\n localStorage.setItem(STORAGE_KEY, arr[0]);\n return arr[0];\n }\n } catch {}\n return detectLocalCity();\n}\n\nconst toF = toFahrenheit;\n\nfunction getTimeInTz(timezone: string, use24Hour = false): string {\n try {\n if (use24Hour) {\n const parts = new Intl.DateTimeFormat('en-US', { timeZone: timezone, hour: 'numeric', minute: '2-digit', hour12: false }).formatToParts(new Date());\n const h = parseInt(parts.find(p => p.type === 'hour')?.value || '0');\n const m = parseInt(parts.find(p => p.type === 'minute')?.value || '0');\n return `${String(h).padStart(2, '0')}:${String(m).padStart(2, '0')}`;\n }\n const parts = new Intl.DateTimeFormat('en-US', { timeZone: timezone, hour: 'numeric', minute: '2-digit', hour12: true }).formatToParts(new Date());\n const h = parseInt(parts.find(p => p.type === 'hour')?.value || '12');\n const m = parseInt(parts.find(p => p.type === 'minute')?.value || '0');\n const period = parts.find(p => p.type === 'dayPeriod')?.value || '';\n return `${h}:${String(m).padStart(2, '0')} ${period}`;\n } catch { return ''; }\n}\n\n/**\n * Effect keyframes — tuned for a ~110 px-tall card so drops/flakes fall\n * across the full height before recycling. Multiple snow/rain variants\n * give the impression of independent particles instead of a hypnotic\n * lock-step pattern.\n */\nconst WX_KEYFRAMES = `\n@keyframes wx-rain-a { 0% { transform: translate(0,-20px); opacity: 0; } 10% { opacity: 0.95; } 100% { transform: translate(8px,140px); opacity: 0; } }\n@keyframes wx-rain-b { 0% { transform: translate(0,-20px); opacity: 0; } 12% { opacity: 0.85; } 100% { transform: translate(12px,140px); opacity: 0; } }\n@keyframes wx-rain-c { 0% { transform: translate(0,-20px); opacity: 0; } 10% { opacity: 1; } 100% { transform: translate(5px,140px); opacity: 0; } }\n@keyframes wx-snow-a { 0% { transform: translate(0,-12px) rotate(0deg); opacity: 0; } 10% { opacity: 0.9; } 50% { transform: translate(10px,55px) rotate(180deg); } 100% { transform: translate(-4px,140px) rotate(360deg); opacity: 0; } }\n@keyframes wx-snow-b { 0% { transform: translate(0,-12px) rotate(0deg); opacity: 0; } 10% { opacity: 0.85; } 50% { transform: translate(-12px,55px) rotate(-180deg); } 100% { transform: translate(6px,140px) rotate(-360deg); opacity: 0; } }\n@keyframes wx-snow-c { 0% { transform: translate(0,-12px); opacity: 0; } 10% { opacity: 0.7; } 100% { transform: translate(2px,140px); opacity: 0; } }\n@keyframes wx-drift-cloud { 0% { transform: translateX(-40%); } 100% { transform: translateX(140%); } }\n@keyframes wx-twinkle { 0%, 100% { opacity: 0.25; transform: scale(1); } 50% { opacity: 1; transform: scale(1.6); } }\n@keyframes wx-flash { 0%, 86%, 100% { opacity: 0; } 87% { opacity: 0.95; } 88% { opacity: 0.15; } 89% { opacity: 0.85; } 90% { opacity: 0; } }\n@keyframes wx-bolt { 0%, 86%, 90%, 100% { opacity: 0; } 87% { opacity: 1; } 89% { opacity: 0.85; } }\n@keyframes wx-sun-pulse { 0%, 100% { transform: scale(1); opacity: 0.65; } 50% { transform: scale(1.12); opacity: 0.95; } }\n@keyframes wx-sun-rays { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }\n@keyframes wx-fog-drift { 0% { transform: translateX(-25%); opacity: 0.3; } 50% { opacity: 0.65; } 100% { transform: translateX(25%); opacity: 0.3; } }\n@keyframes wx-shooting-star { 0%, 95% { opacity: 0; transform: translate(0,0) scale(0); } 96% { opacity: 1; transform: translate(0,0) scale(1); } 100% { opacity: 0; transform: translate(40px,30px) scale(1); } }\n`;\n\nfunction SunEffect() {\n // Defined yellow-orange disc with halo + slowly-rotating ray sprite.\n return (\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n <div className=\"absolute -top-5 -right-5 w-24 h-24\" style={{ animation: 'wx-sun-rays 70s linear infinite' }}>\n <svg viewBox=\"0 0 100 100\" className=\"w-full h-full\">\n {Array.from({ length: 12 }).map((_, i) => (\n <rect key={i} x={49} y={3} width={2} height={14} rx={1}\n fill=\"rgba(255, 232, 130, 0.55)\"\n transform={`rotate(${i * 30} 50 50)`} />\n ))}\n </svg>\n </div>\n <div className=\"absolute top-1 right-1 w-10 h-10 rounded-full\"\n style={{\n background: 'radial-gradient(circle at 35% 35%, #fff8cc 0%, #ffd84a 55%, #ff9e2a 100%)',\n boxShadow: '0 0 18px 5px rgba(255, 200, 80, 0.55)',\n animation: 'wx-sun-pulse 4.5s ease-in-out infinite',\n }} />\n </div>\n );\n}\n\nfunction NightStarsEffect() {\n // Crescent moon (outer warm circle + offset dark circle to carve out the\n // bite) and a sparse scatter of stars twinkling at independent rates.\n // One slow-cycle shooting star adds a moment of motion without\n // distracting.\n const stars = Array.from({ length: 16 }).map((_, i) => ({\n left: `${(i * 53 + 11) % 95}%`,\n top: `${(i * 37 + 9) % 78}%`,\n size: 1 + ((i * 13) % 3),\n delay: `${(i * 0.41) % 4}s`,\n duration: `${2.5 + ((i * 7) % 5) * 0.6}s`,\n }));\n return (\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n {/* Crescent moon */}\n <div className=\"absolute top-1 right-1\">\n <svg viewBox=\"0 0 40 40\" className=\"w-9 h-9\" style={{ filter: 'drop-shadow(0 0 6px rgba(255,250,220,0.4))' }}>\n <defs>\n <radialGradient id=\"wx-moon-grad\" cx=\"35%\" cy=\"35%\">\n <stop offset=\"0\" stopColor=\"#fffae0\" />\n <stop offset=\"1\" stopColor=\"#d4c98a\" />\n </radialGradient>\n </defs>\n <circle cx={20} cy={20} r={13} fill=\"url(#wx-moon-grad)\" />\n <circle cx={26} cy={16} r={11} fill=\"rgba(15,23,42,1)\" />\n </svg>\n </div>\n {stars.map((s, i) => (\n <div key={i} className=\"absolute rounded-full bg-white\"\n style={{\n left: s.left, top: s.top, width: s.size, height: s.size,\n animation: `wx-twinkle ${s.duration} ease-in-out ${s.delay} infinite`,\n }} />\n ))}\n {/* Shooting star — appears once every ~12s */}\n <div className=\"absolute\" style={{ left: '15%', top: '20%', animation: 'wx-shooting-star 12s ease-out infinite' }}>\n <div className=\"w-12 h-px\"\n style={{ background: 'linear-gradient(to right, transparent, rgba(255,255,255,0.95))', boxShadow: '0 0 4px rgba(255,255,255,0.8)' }} />\n </div>\n </div>\n );\n}\n\nfunction CloudsEffect({ tone = 'light' as 'light' | 'dark' }) {\n const fill = tone === 'light' ? 'rgba(255,255,255,0.78)' : 'rgba(220,228,240,0.45)';\n const Cloud = ({ scale = 1 }) => (\n <svg viewBox=\"0 0 120 50\" className=\"w-32 h-12\" style={{ transform: `scale(${scale})`, filter: 'blur(0.6px)' }}>\n <ellipse cx={28} cy={36} rx={18} ry={11} fill={fill} />\n <ellipse cx={50} cy={28} rx={22} ry={15} fill={fill} />\n <ellipse cx={75} cy={32} rx={20} ry={12} fill={fill} />\n <ellipse cx={95} cy={38} rx={15} ry={9} fill={fill} />\n </svg>\n );\n return (\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n <div className=\"absolute\" style={{ top: '8%', animation: 'wx-drift-cloud 42s linear infinite' }}><Cloud scale={0.9} /></div>\n <div className=\"absolute\" style={{ top: '40%', animation: 'wx-drift-cloud 60s linear -22s infinite', opacity: 0.85 }}><Cloud scale={1.25} /></div>\n <div className=\"absolute\" style={{ top: '68%', animation: 'wx-drift-cloud 78s linear -45s infinite', opacity: 0.7 }}><Cloud scale={0.75} /></div>\n </div>\n );\n}\n\nfunction RainEffect({ heavy = false }: { heavy?: boolean }) {\n const count = heavy ? 26 : 16;\n const variants = ['wx-rain-a', 'wx-rain-b', 'wx-rain-c'];\n const drops = Array.from({ length: count }).map((_, i) => ({\n left: `${(i * 100 / count + (i * 11) % 7) % 100}%`,\n delay: `${(i * 0.087) % 1.3}s`,\n height: `${12 + (i % 4) * 5}px`,\n duration: `${0.7 + (i % 3) * 0.18}s`,\n variant: variants[i % variants.length],\n }));\n return (\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n {drops.map((d, i) => (\n <div key={i} className=\"absolute\"\n style={{\n left: d.left, top: '-20px',\n width: '1px', height: d.height,\n background: 'linear-gradient(180deg, rgba(180,210,255,0) 0%, rgba(220,235,255,0.85) 90%, rgba(255,255,255,0.95) 100%)',\n transform: 'rotate(8deg)',\n animation: `${d.variant} ${d.duration} linear ${d.delay} infinite`,\n transformOrigin: 'top',\n }} />\n ))}\n </div>\n );\n}\n\nfunction SnowEffect() {\n const variants = ['wx-snow-a', 'wx-snow-b', 'wx-snow-c'];\n const flakes = Array.from({ length: 16 }).map((_, i) => ({\n left: `${(i * 100 / 16 + (i * 13) % 5) % 100}%`,\n delay: `${(i * 0.43) % 5}s`,\n duration: `${4.5 + (i % 5)}s`,\n size: 3 + (i % 4) * 1.4,\n opacity: 0.65 + ((i * 7) % 4) * 0.08,\n variant: variants[i % variants.length],\n }));\n return (\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n {flakes.map((f, i) => (\n <div key={i} className=\"absolute rounded-full bg-white\"\n style={{\n left: f.left, top: '-12px',\n width: f.size, height: f.size,\n opacity: f.opacity,\n boxShadow: '0 0 4px rgba(255,255,255,0.65)',\n animation: `${f.variant} ${f.duration} linear ${f.delay} infinite`,\n }} />\n ))}\n </div>\n );\n}\n\nfunction ThunderEffect() {\n return (\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n <RainEffect heavy />\n {/* Sharp double-flash overlay */}\n <div className=\"absolute inset-0 bg-white\" style={{ animation: 'wx-flash 6s ease-out infinite' }} />\n {/* Lightning bolt — visible only during the flash peaks */}\n <div className=\"absolute inset-y-0 right-1/3 flex items-center justify-center pointer-events-none\"\n style={{ animation: 'wx-bolt 6s ease-out infinite' }}>\n <svg viewBox=\"0 0 18 60\" className=\"h-4/5\"\n style={{ filter: 'drop-shadow(0 0 6px rgba(255, 240, 150, 0.95)) drop-shadow(0 0 14px rgba(255, 220, 90, 0.7))' }}>\n <path d=\"M11 0 L2 28 L8 30 L4 60 L16 24 L9 22 Z\"\n fill=\"rgba(255, 250, 200, 0.98)\"\n stroke=\"rgba(255, 255, 255, 0.9)\" strokeWidth={0.3} />\n </svg>\n </div>\n </div>\n );\n}\n\nfunction FogEffect() {\n return (\n <div className=\"absolute inset-0 overflow-hidden pointer-events-none\">\n {Array.from({ length: 4 }).map((_, i) => (\n <div key={i} className=\"absolute left-0 right-0\"\n style={{\n top: `${10 + i * 22}%`,\n height: '14px',\n background: 'linear-gradient(to right, rgba(255,255,255,0) 0%, rgba(255,255,255,0.55) 50%, rgba(255,255,255,0) 100%)',\n filter: 'blur(2px)',\n animation: `wx-fog-drift ${10 + i * 3}s ease-in-out ${i * 0.7}s infinite alternate`,\n }} />\n ))}\n </div>\n );\n}\n\nfunction WeatherEffect({ code, isDay }: { code: number; isDay: boolean }) {\n if (code === 0 || code === 1) return isDay ? <SunEffect /> : <NightStarsEffect />;\n if (code === 2) return (\n <>\n {isDay ? <SunEffect /> : <NightStarsEffect />}\n <CloudsEffect tone={isDay ? 'light' : 'dark'} />\n </>\n );\n if (code === 3) return <CloudsEffect tone={isDay ? 'light' : 'dark'} />;\n if (code === 45 || code === 48) return <FogEffect />;\n if ([51, 53, 61, 80, 81].includes(code)) return <RainEffect />;\n if ([55, 63, 65, 82].includes(code)) return <RainEffect heavy />;\n if ([71, 73, 75].includes(code)) return <SnowEffect />;\n if ([95, 96, 99].includes(code)) return <ThunderEffect />;\n return null;\n}\n\nexport default function Weather() {\n const [city, setCity] = useState(loadCity);\n const [appearance, setAppearance] = useState(() => loadAppearance(SETTINGS_KEY));\n const [data, setData] = useState<CityWeather | null>(null);\n const [loading, setLoading] = useState(true);\n const [, setTick] = useState(0);\n useEffect(() => { const t = setInterval(() => setTick(n => n + 1), 60000); return () => clearInterval(t); }, []);\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [configCity, setConfigCity] = useState(city);\n const [configAppearance, setConfigAppearance] = useState<WidgetAppearance>(appearance);\n\n const { prefs: shellPrefs, save: saveShellPrefs } = useShellPrefs();\n const prefs: WeatherPrefs = { ...DEFAULT_PREFS, ...(shellPrefs.weather_prefs as WeatherPrefs | undefined ?? {}) };\n const [configPrefs, setConfigPrefs] = useState<WeatherPrefs>(prefs);\n\n useWidgetSettings(useCallback(() => {\n setConfigCity(city);\n setConfigAppearance({ ...appearance });\n setConfigPrefs({ ...prefs });\n setSettingsOpen(true);\n }, [city, appearance, prefs]));\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n fetchCityWeather(city).then(w => {\n if (cancelled) return;\n setData(w);\n setLoading(false);\n });\n return () => { cancelled = true; };\n }, [city]);\n\n const saveSettings = () => {\n setCity(configCity);\n setAppearance(configAppearance);\n saveShellPrefs({ weather_prefs: configPrefs });\n localStorage.setItem(STORAGE_KEY, configCity);\n localStorage.setItem(SETTINGS_KEY, JSON.stringify(configAppearance));\n setSettingsOpen(false);\n };\n\n const t = (c: number) => prefs.useFahrenheit ? `${toF(c)}°F` : `${c}°`;\n\n // Half-height — tile is now ~110 px tall. Effect keyframes are tuned for\n // this so drops/flakes traverse the full height before recycling.\n const TILE_HEIGHT = 110;\n\n if (loading && !data) {\n return <div className=\"flex items-center justify-center h-full bg-gradient-to-b from-sky-400 to-blue-500 rounded-lg text-white/80 text-xs\" style={{ minHeight: TILE_HEIGHT }}>Loading…</div>;\n }\n if (!data) {\n return <div className=\"flex items-center justify-center h-full bg-slate-700 rounded-lg text-white/80 text-xs\" style={{ minHeight: TILE_HEIGHT }}>Couldn't load weather</div>;\n }\n\n const [condition, emoji, gradient] = getCondition(data.code, data.isDay);\n\n return (\n <>\n <style>{WX_KEYFRAMES}</style>\n <div className=\"rounded-lg overflow-hidden\"\n style={{\n backgroundColor: `rgba(15, 23, 42, ${appearance.activeOpacity / 100})`,\n backdropFilter: appearance.activeBlur > 0 ? `blur(${appearance.activeBlur}px)` : undefined,\n }}>\n <div className={`relative rounded-lg overflow-hidden text-white bg-gradient-to-br ${gradient}`} style={{ height: TILE_HEIGHT }}>\n {/* Animated effects */}\n <WeatherEffect code={data.code} isDay={data.isDay} />\n\n {/* Compact two-row content */}\n <div className=\"relative z-10 px-3 py-2.5 flex flex-col h-full justify-between\">\n {/* Top: city + time | temp */}\n <div className=\"flex items-start justify-between gap-2\">\n <div className=\"min-w-0 flex-1\">\n <div className=\"text-base font-semibold leading-tight truncate drop-shadow-sm\">{data.city}</div>\n {prefs.showLocalTime && (\n <div className=\"text-[10px] opacity-90 leading-tight tabular-nums drop-shadow-sm\">\n {getTimeInTz(data.timezone, prefs.use24Hour)}\n </div>\n )}\n </div>\n <div className=\"text-3xl font-extralight leading-none tracking-tight tabular-nums shrink-0 drop-shadow-sm\">\n {t(data.temp)}\n </div>\n </div>\n\n {/* Bottom: condition | H/L */}\n <div className=\"flex items-end justify-between gap-2\">\n <div className=\"flex items-center gap-1.5 min-w-0\">\n <span className=\"text-lg leading-none drop-shadow-sm\">{emoji}</span>\n <span className=\"text-[11px] font-medium drop-shadow-sm truncate\">{condition}</span>\n </div>\n <span className=\"text-[10px] opacity-90 tabular-nums drop-shadow-sm shrink-0\">H:{t(data.high)} L:{t(data.low)}</span>\n </div>\n </div>\n </div>\n </div>\n\n <WidgetSettingsModal open={settingsOpen} onClose={() => setSettingsOpen(false)} title=\"Weather Settings\"\n appearance={configAppearance} onAppearanceChange={setConfigAppearance} onSave={saveSettings}>\n <div className=\"space-y-3\">\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-2\">Display</h3>\n <div className=\"flex items-center gap-3 mb-2\">\n <span className=\"text-sm text-gray-600 w-24\">Temperature</span>\n <div className=\"flex gap-1\">\n {([{ key: false, label: '°C' }, { key: true, label: '°F' }] as const).map(o => (\n <button key={String(o.key)} onClick={() => setConfigPrefs(p => ({ ...p, useFahrenheit: o.key }))}\n className={`px-3 py-1 text-xs font-medium rounded-lg border transition-colors ${configPrefs.useFahrenheit === o.key ? 'bg-blue-600 text-white border-blue-600' : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'}`}>\n {o.label}\n </button>\n ))}\n </div>\n </div>\n <div className=\"flex items-center gap-3 mb-2\">\n <span className=\"text-sm text-gray-600 w-24\">Time Format</span>\n <div className=\"flex gap-1\">\n {([{ key: false, label: 'AM/PM' }, { key: true, label: '24H' }] as const).map(o => (\n <button key={String(o.key)} onClick={() => setConfigPrefs(p => ({ ...p, use24Hour: o.key }))}\n className={`px-3 py-1 text-xs font-medium rounded-lg border transition-colors ${configPrefs.use24Hour === o.key ? 'bg-blue-600 text-white border-blue-600' : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'}`}>\n {o.label}\n </button>\n ))}\n </div>\n </div>\n <label className=\"flex items-center gap-2 cursor-pointer\">\n <input type=\"checkbox\" checked={configPrefs.showLocalTime} onChange={e => setConfigPrefs(p => ({ ...p, showLocalTime: e.target.checked }))}\n className=\"rounded border-gray-300 text-blue-600 h-3.5 w-3.5\" />\n <span className=\"text-sm text-gray-600\">Show local time</span>\n </label>\n </div>\n </div>\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-2\">City</h3>\n <select value={configCity} onChange={e => setConfigCity(e.target.value)}\n className=\"w-full bg-gray-50 border border-gray-200 rounded px-2 py-1.5 text-sm focus:outline-none focus:ring-1 focus:ring-blue-500\">\n {Object.keys(AVAILABLE_CITIES).map(name => (\n <option key={name} value={name}>{name}</option>\n ))}\n </select>\n <p className=\"mt-1 text-[10px] text-gray-400\">Auto-detected from your timezone; change if needed.</p>\n </div>\n </WidgetSettingsModal>\n </>\n );\n}\n"]}
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
import { AVAILABLE_CITIES, fetchCityWeather, getCondition, toFahrenheit } from './chunk-7CCHEEYC.js';
|
|
2
|
-
import { loadAppearance, WidgetSettingsModal } from './chunk-E7TB6WD2.js';
|
|
3
|
-
import { useWidgetSettings } from './chunk-ICTRCKUE.js';
|
|
4
|
-
import './chunk-GA35NEND.js';
|
|
5
|
-
import { useShellPrefs } from './chunk-HUBJAUGG.js';
|
|
6
|
-
import './chunk-RT6DSB5Y.js';
|
|
7
|
-
import './chunk-JOPU6WPY.js';
|
|
8
|
-
import './chunk-I2TAAJHS.js';
|
|
9
|
-
import './chunk-6XJEJWNJ.js';
|
|
10
|
-
import './chunk-YE6GUDGP.js';
|
|
11
|
-
import './chunk-IPXN646P.js';
|
|
12
|
-
import './chunk-IRWSRJ4K.js';
|
|
13
|
-
import { useState, useEffect, useCallback } from 'react';
|
|
14
|
-
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
15
|
-
|
|
16
|
-
var SETTINGS_KEY = "world_clock_appearance";
|
|
17
|
-
var DEFAULT_CITIES = ["London", "Shanghai", "New York"];
|
|
18
|
-
function digitalTime(tz, now) {
|
|
19
|
-
try {
|
|
20
|
-
const parts = new Intl.DateTimeFormat("en-US", {
|
|
21
|
-
timeZone: tz,
|
|
22
|
-
hour: "numeric",
|
|
23
|
-
minute: "2-digit",
|
|
24
|
-
hour12: true
|
|
25
|
-
}).formatToParts(now);
|
|
26
|
-
const h = parts.find((p) => p.type === "hour")?.value || "12";
|
|
27
|
-
const m = parts.find((p) => p.type === "minute")?.value || "00";
|
|
28
|
-
const ampm = (parts.find((p) => p.type === "dayPeriod")?.value || "").toUpperCase();
|
|
29
|
-
return { time: `${h}:${m}`, ampm };
|
|
30
|
-
} catch {
|
|
31
|
-
return { time: "", ampm: "" };
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function WorldClock() {
|
|
35
|
-
const { prefs, save } = useShellPrefs();
|
|
36
|
-
const [appearance, setAppearance] = useState(() => loadAppearance(SETTINGS_KEY));
|
|
37
|
-
const [settingsOpen, setSettingsOpen] = useState(false);
|
|
38
|
-
const [configCities, setConfigCities] = useState([]);
|
|
39
|
-
const [configAppearance, setConfigAppearance] = useState(appearance);
|
|
40
|
-
const wxPrefs = {
|
|
41
|
-
useFahrenheit: !!prefs.weather_prefs?.useFahrenheit
|
|
42
|
-
};
|
|
43
|
-
const [configWxPrefs, setConfigWxPrefs] = useState(wxPrefs);
|
|
44
|
-
const [now, setNow] = useState(() => /* @__PURE__ */ new Date());
|
|
45
|
-
useEffect(() => {
|
|
46
|
-
const t = setInterval(() => setNow(/* @__PURE__ */ new Date()), 30 * 1e3);
|
|
47
|
-
return () => clearInterval(t);
|
|
48
|
-
}, []);
|
|
49
|
-
const tzToCity = Object.fromEntries(
|
|
50
|
-
Object.entries(AVAILABLE_CITIES).map(([city, info]) => [info.tz, city])
|
|
51
|
-
);
|
|
52
|
-
const rawClocks = prefs.world_clocks;
|
|
53
|
-
const cities = (() => {
|
|
54
|
-
if (!Array.isArray(rawClocks) || rawClocks.length === 0) return DEFAULT_CITIES;
|
|
55
|
-
const out = [];
|
|
56
|
-
for (const v of rawClocks) {
|
|
57
|
-
const asCity = AVAILABLE_CITIES[v] ? v : tzToCity[v];
|
|
58
|
-
if (asCity && !out.includes(asCity)) out.push(asCity);
|
|
59
|
-
}
|
|
60
|
-
return out.length ? out : DEFAULT_CITIES;
|
|
61
|
-
})();
|
|
62
|
-
const [data, setData] = useState({});
|
|
63
|
-
const [loading, setLoading] = useState(true);
|
|
64
|
-
useEffect(() => {
|
|
65
|
-
let cancelled = false;
|
|
66
|
-
setLoading(true);
|
|
67
|
-
(async () => {
|
|
68
|
-
const next = {};
|
|
69
|
-
await Promise.all(cities.map(async (c) => {
|
|
70
|
-
const w = await fetchCityWeather(c);
|
|
71
|
-
if (w) next[c] = w;
|
|
72
|
-
}));
|
|
73
|
-
if (!cancelled) {
|
|
74
|
-
setData(next);
|
|
75
|
-
setLoading(false);
|
|
76
|
-
}
|
|
77
|
-
})();
|
|
78
|
-
return () => {
|
|
79
|
-
cancelled = true;
|
|
80
|
-
};
|
|
81
|
-
}, [cities.join(",")]);
|
|
82
|
-
useWidgetSettings(useCallback(() => {
|
|
83
|
-
setConfigCities([...cities]);
|
|
84
|
-
setConfigAppearance({ ...appearance });
|
|
85
|
-
setConfigWxPrefs({ ...wxPrefs });
|
|
86
|
-
setSettingsOpen(true);
|
|
87
|
-
}, [cities.join(","), appearance, wxPrefs.useFahrenheit]));
|
|
88
|
-
const saveSettings = () => {
|
|
89
|
-
if (configCities.length === 0) return;
|
|
90
|
-
save({
|
|
91
|
-
world_clocks: configCities,
|
|
92
|
-
weather_prefs: { ...prefs.weather_prefs ?? {}, useFahrenheit: configWxPrefs.useFahrenheit }
|
|
93
|
-
});
|
|
94
|
-
setAppearance(configAppearance);
|
|
95
|
-
localStorage.setItem(SETTINGS_KEY, JSON.stringify(configAppearance));
|
|
96
|
-
setSettingsOpen(false);
|
|
97
|
-
};
|
|
98
|
-
const formatTemp = (c) => wxPrefs.useFahrenheit ? `${toFahrenheit(c)}\xB0` : `${c}\xB0`;
|
|
99
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
100
|
-
/* @__PURE__ */ jsx(
|
|
101
|
-
"div",
|
|
102
|
-
{
|
|
103
|
-
style: {
|
|
104
|
-
backgroundColor: `rgb(var(--taskbar-bg-rgb, 243 244 246) / ${appearance.activeOpacity / 100})`,
|
|
105
|
-
backdropFilter: appearance.activeBlur > 0 ? `blur(${appearance.activeBlur}px)` : void 0
|
|
106
|
-
},
|
|
107
|
-
children: /* @__PURE__ */ jsxs("div", { className: "divide-y divide-gray-200", children: [
|
|
108
|
-
loading && cities.every((c) => !data[c]) && /* @__PURE__ */ jsx("div", { className: "px-3 py-6 text-center text-xs text-gray-500", children: "Loading\u2026" }),
|
|
109
|
-
cities.map((cityName) => {
|
|
110
|
-
const w = data[cityName];
|
|
111
|
-
const tz = AVAILABLE_CITIES[cityName]?.tz ?? "UTC";
|
|
112
|
-
const { time, ampm } = digitalTime(tz, now);
|
|
113
|
-
if (!w) {
|
|
114
|
-
return /* @__PURE__ */ jsxs("div", { className: "px-4 py-3", children: [
|
|
115
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
116
|
-
/* @__PURE__ */ jsx("span", { className: "text-[15px] font-semibold tracking-tight text-gray-900 truncate", children: cityName }),
|
|
117
|
-
/* @__PURE__ */ jsxs("span", { className: "tabular-nums text-[13px] font-medium text-gray-500", children: [
|
|
118
|
-
time,
|
|
119
|
-
/* @__PURE__ */ jsx("span", { className: "text-[9px] ml-0.5 opacity-70", children: ampm })
|
|
120
|
-
] })
|
|
121
|
-
] }),
|
|
122
|
-
/* @__PURE__ */ jsx("div", { className: "text-[11px] text-gray-400 mt-1", children: "Loading weather\u2026" })
|
|
123
|
-
] }, cityName);
|
|
124
|
-
}
|
|
125
|
-
const [condition, emoji] = getCondition(w.code, w.isDay);
|
|
126
|
-
return /* @__PURE__ */ jsxs("div", { className: "px-4 py-3", children: [
|
|
127
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline justify-between gap-2", children: [
|
|
128
|
-
/* @__PURE__ */ jsx("span", { className: "text-[15px] font-semibold tracking-tight text-gray-900 truncate", children: cityName }),
|
|
129
|
-
/* @__PURE__ */ jsx("span", { className: "text-[26px] font-extralight leading-none tabular-nums tracking-tight text-gray-900 shrink-0", children: formatTemp(w.temp) })
|
|
130
|
-
] }),
|
|
131
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2 mt-1.5 text-[11px]", children: [
|
|
132
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 min-w-0 text-gray-500", children: [
|
|
133
|
-
/* @__PURE__ */ jsx("span", { className: "text-base leading-none shrink-0", children: emoji }),
|
|
134
|
-
/* @__PURE__ */ jsxs("span", { className: "tabular-nums font-semibold text-gray-700 shrink-0", children: [
|
|
135
|
-
time,
|
|
136
|
-
/* @__PURE__ */ jsx("span", { className: "text-[9px] font-medium ml-0.5 opacity-70", children: ampm })
|
|
137
|
-
] }),
|
|
138
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-300 shrink-0", children: "\xB7" }),
|
|
139
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: condition })
|
|
140
|
-
] }),
|
|
141
|
-
/* @__PURE__ */ jsxs("span", { className: "tabular-nums text-gray-500 shrink-0", children: [
|
|
142
|
-
"H:",
|
|
143
|
-
formatTemp(w.high),
|
|
144
|
-
" L:",
|
|
145
|
-
formatTemp(w.low)
|
|
146
|
-
] })
|
|
147
|
-
] })
|
|
148
|
-
] }, cityName);
|
|
149
|
-
})
|
|
150
|
-
] })
|
|
151
|
-
}
|
|
152
|
-
),
|
|
153
|
-
/* @__PURE__ */ jsxs(
|
|
154
|
-
WidgetSettingsModal,
|
|
155
|
-
{
|
|
156
|
-
open: settingsOpen,
|
|
157
|
-
onClose: () => setSettingsOpen(false),
|
|
158
|
-
title: "World Clock Settings",
|
|
159
|
-
appearance: configAppearance,
|
|
160
|
-
onAppearanceChange: setConfigAppearance,
|
|
161
|
-
onSave: saveSettings,
|
|
162
|
-
children: [
|
|
163
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
164
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700 mb-2", children: "Display" }),
|
|
165
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-2", children: [
|
|
166
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-gray-600 w-24", children: "Temperature" }),
|
|
167
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-1", children: [{ key: false, label: "\xB0C" }, { key: true, label: "\xB0F" }].map((o) => /* @__PURE__ */ jsx(
|
|
168
|
-
"button",
|
|
169
|
-
{
|
|
170
|
-
onClick: () => setConfigWxPrefs((p) => ({ ...p, useFahrenheit: o.key })),
|
|
171
|
-
className: `px-3 py-1 text-xs font-medium rounded-lg border transition-colors ${configWxPrefs.useFahrenheit === o.key ? "bg-blue-600 text-white border-blue-600" : "bg-white text-gray-700 border-gray-300 hover:bg-gray-50"}`,
|
|
172
|
-
children: o.label
|
|
173
|
-
},
|
|
174
|
-
String(o.key)
|
|
175
|
-
)) })
|
|
176
|
-
] }),
|
|
177
|
-
/* @__PURE__ */ jsx("p", { className: "text-[10px] text-gray-400 mt-1", children: "Shared with the Weather widget." })
|
|
178
|
-
] }),
|
|
179
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
180
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-gray-700 mb-2", children: "Cities" }),
|
|
181
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-1 max-h-56 overflow-y-auto", children: Object.keys(AVAILABLE_CITIES).map((name) => /* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm py-1 cursor-pointer hover:bg-gray-50 rounded px-2", children: [
|
|
182
|
-
/* @__PURE__ */ jsx(
|
|
183
|
-
"input",
|
|
184
|
-
{
|
|
185
|
-
type: "checkbox",
|
|
186
|
-
checked: configCities.includes(name),
|
|
187
|
-
onChange: () => setConfigCities((prev) => prev.includes(name) ? prev.filter((c) => c !== name) : [...prev, name]),
|
|
188
|
-
className: "rounded border-gray-300 text-blue-600 focus:ring-blue-500 h-3.5 w-3.5"
|
|
189
|
-
}
|
|
190
|
-
),
|
|
191
|
-
name
|
|
192
|
-
] }, name)) })
|
|
193
|
-
] })
|
|
194
|
-
]
|
|
195
|
-
}
|
|
196
|
-
)
|
|
197
|
-
] });
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export { WorldClock as default };
|
|
201
|
-
//# sourceMappingURL=WorldClock-XPD7WOZT.js.map
|
|
202
|
-
//# sourceMappingURL=WorldClock-XPD7WOZT.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/apps/WorldClock.tsx"],"names":[],"mappings":"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","file":"WorldClock-XPD7WOZT.js","sourcesContent":["import { useState, useEffect, useCallback } from 'react';\nimport { useWidgetSettings } from '../shell/Modal';\nimport WidgetSettingsModal, { loadAppearance, type WidgetAppearance } from '../shell/WidgetSettingsModal';\nimport { useShellPrefs } from '../shell/ShellPrefs';\nimport { AVAILABLE_CITIES, fetchCityWeather, getCondition, toFahrenheit, type CityWeather } from './_weatherData';\n\nconst SETTINGS_KEY = 'world_clock_appearance';\nconst DEFAULT_CITIES = ['London', 'Shanghai', 'New York'];\n\ninterface WeatherPrefs { useFahrenheit: boolean }\n\n/**\n * Resolve the local time for the supplied IANA timezone into a digital\n * `12:34` + `AM` / `PM` pair. Used by the World Clock rows.\n */\nfunction digitalTime(tz: string, now: Date): { time: string; ampm: string } {\n try {\n const parts = new Intl.DateTimeFormat('en-US', {\n timeZone: tz, hour: 'numeric', minute: '2-digit', hour12: true,\n }).formatToParts(now);\n const h = parts.find(p => p.type === 'hour')?.value || '12';\n const m = parts.find(p => p.type === 'minute')?.value || '00';\n const ampm = (parts.find(p => p.type === 'dayPeriod')?.value || '').toUpperCase();\n return { time: `${h}:${m}`, ampm };\n } catch { return { time: '', ampm: '' }; }\n}\n\n/**\n * World Clock widget — multi-city list. Each row pairs a tiny analogue\n * clock (minimal-style: ring, four cardinal dots, two hands) with the\n * city's current weather. The weather emoji doubles as a day/night cue\n * (☀ vs 🌙 for clear, the same icons for everything else). Reads the\n * shared Open-Meteo cache so it doesn't re-hit the API when the Weather\n * widget already has the data.\n */\nexport default function WorldClock() {\n const { prefs, save } = useShellPrefs();\n const [appearance, setAppearance] = useState(() => loadAppearance(SETTINGS_KEY));\n const [settingsOpen, setSettingsOpen] = useState(false);\n const [configCities, setConfigCities] = useState<string[]>([]);\n const [configAppearance, setConfigAppearance] = useState<WidgetAppearance>(appearance);\n\n const wxPrefs: WeatherPrefs = {\n useFahrenheit: !!(prefs.weather_prefs as WeatherPrefs | undefined)?.useFahrenheit,\n };\n const [configWxPrefs, setConfigWxPrefs] = useState(wxPrefs);\n\n // Tick once every 30 s so the analogue minute-hands drift smoothly. We\n // don't show seconds so faster polling is wasted re-renders.\n const [now, setNow] = useState(() => new Date());\n useEffect(() => {\n const t = setInterval(() => setNow(new Date()), 30 * 1000);\n return () => clearInterval(t);\n }, []);\n\n // Resolve the saved city list and migrate the legacy IANA-timezone\n // format (`Europe/London`) over to the new city-name format\n // (`London`).\n const tzToCity: Record<string, string> = Object.fromEntries(\n Object.entries(AVAILABLE_CITIES).map(([city, info]) => [info.tz, city])\n );\n const rawClocks = prefs.world_clocks as string[] | undefined;\n const cities: string[] = (() => {\n if (!Array.isArray(rawClocks) || rawClocks.length === 0) return DEFAULT_CITIES;\n const out: string[] = [];\n for (const v of rawClocks) {\n const asCity = AVAILABLE_CITIES[v] ? v : tzToCity[v];\n if (asCity && !out.includes(asCity)) out.push(asCity);\n }\n return out.length ? out : DEFAULT_CITIES;\n })();\n\n const [data, setData] = useState<Record<string, CityWeather>>({});\n const [loading, setLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n setLoading(true);\n (async () => {\n const next: Record<string, CityWeather> = {};\n await Promise.all(cities.map(async c => {\n const w = await fetchCityWeather(c);\n if (w) next[c] = w;\n }));\n if (!cancelled) { setData(next); setLoading(false); }\n })();\n return () => { cancelled = true; };\n }, [cities.join(',')]);\n\n useWidgetSettings(useCallback(() => {\n setConfigCities([...cities]);\n setConfigAppearance({ ...appearance });\n setConfigWxPrefs({ ...wxPrefs });\n setSettingsOpen(true);\n }, [cities.join(','), appearance, wxPrefs.useFahrenheit]));\n\n const saveSettings = () => {\n if (configCities.length === 0) return;\n save({\n world_clocks: configCities,\n weather_prefs: { ...(prefs.weather_prefs as object | undefined ?? {}), useFahrenheit: configWxPrefs.useFahrenheit },\n });\n setAppearance(configAppearance);\n localStorage.setItem(SETTINGS_KEY, JSON.stringify(configAppearance));\n setSettingsOpen(false);\n };\n\n const formatTemp = (c: number) => wxPrefs.useFahrenheit ? `${toFahrenheit(c)}°` : `${c}°`;\n\n return (\n <>\n {/* Theme-aware panel — same colour as the taskbar so all dashboard\n * widgets read as a coordinated set across light and dark themes.\n * Rows use `divide-y` rather than per-row border classes so the\n * last row never paints a stray separator line at the panel's\n * bottom edge. */}\n <div\n style={{\n backgroundColor: `rgb(var(--taskbar-bg-rgb, 243 244 246) / ${appearance.activeOpacity / 100})`,\n backdropFilter: appearance.activeBlur > 0 ? `blur(${appearance.activeBlur}px)` : undefined,\n }}>\n <div className=\"divide-y divide-gray-200\">\n {loading && cities.every(c => !data[c]) && (\n <div className=\"px-3 py-6 text-center text-xs text-gray-500\">Loading…</div>\n )}\n {cities.map((cityName) => {\n const w = data[cityName];\n const tz = AVAILABLE_CITIES[cityName]?.tz ?? 'UTC';\n const { time, ampm } = digitalTime(tz, now);\n if (!w) {\n return (\n <div key={cityName} className=\"px-4 py-3\">\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-[15px] font-semibold tracking-tight text-gray-900 truncate\">{cityName}</span>\n <span className=\"tabular-nums text-[13px] font-medium text-gray-500\">{time}<span className=\"text-[9px] ml-0.5 opacity-70\">{ampm}</span></span>\n </div>\n <div className=\"text-[11px] text-gray-400 mt-1\">Loading weather…</div>\n </div>\n );\n }\n const [condition, emoji] = getCondition(w.code, w.isDay);\n return (\n <div key={cityName} className=\"px-4 py-3\">\n {/* Top — city name on the left, big temperature on the right. */}\n <div className=\"flex items-baseline justify-between gap-2\">\n <span className=\"text-[15px] font-semibold tracking-tight text-gray-900 truncate\">{cityName}</span>\n <span className=\"text-[26px] font-extralight leading-none tabular-nums tracking-tight text-gray-900 shrink-0\">{formatTemp(w.temp)}</span>\n </div>\n\n {/* Bottom — emoji · digital time · condition on the left;\n H/L on the right. */}\n <div className=\"flex items-center justify-between gap-2 mt-1.5 text-[11px]\">\n <div className=\"flex items-center gap-1.5 min-w-0 text-gray-500\">\n <span className=\"text-base leading-none shrink-0\">{emoji}</span>\n <span className=\"tabular-nums font-semibold text-gray-700 shrink-0\">\n {time}<span className=\"text-[9px] font-medium ml-0.5 opacity-70\">{ampm}</span>\n </span>\n <span className=\"text-gray-300 shrink-0\">·</span>\n <span className=\"truncate\">{condition}</span>\n </div>\n <span className=\"tabular-nums text-gray-500 shrink-0\">H:{formatTemp(w.high)} L:{formatTemp(w.low)}</span>\n </div>\n </div>\n );\n })}\n </div>\n </div>\n\n <WidgetSettingsModal open={settingsOpen} onClose={() => setSettingsOpen(false)} title=\"World Clock Settings\"\n appearance={configAppearance} onAppearanceChange={setConfigAppearance} onSave={saveSettings}>\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-2\">Display</h3>\n <div className=\"flex items-center gap-3 mb-2\">\n <span className=\"text-sm text-gray-600 w-24\">Temperature</span>\n <div className=\"flex gap-1\">\n {([{ key: false, label: '°C' }, { key: true, label: '°F' }] as const).map(o => (\n <button key={String(o.key)} onClick={() => setConfigWxPrefs(p => ({ ...p, useFahrenheit: o.key }))}\n className={`px-3 py-1 text-xs font-medium rounded-lg border transition-colors ${configWxPrefs.useFahrenheit === o.key ? 'bg-blue-600 text-white border-blue-600' : 'bg-white text-gray-700 border-gray-300 hover:bg-gray-50'}`}>\n {o.label}\n </button>\n ))}\n </div>\n </div>\n <p className=\"text-[10px] text-gray-400 mt-1\">Shared with the Weather widget.</p>\n </div>\n <div>\n <h3 className=\"text-sm font-semibold text-gray-700 mb-2\">Cities</h3>\n <div className=\"grid grid-cols-2 gap-1 max-h-56 overflow-y-auto\">\n {Object.keys(AVAILABLE_CITIES).map(name => (\n <label key={name} className=\"flex items-center gap-2 text-sm py-1 cursor-pointer hover:bg-gray-50 rounded px-2\">\n <input type=\"checkbox\" checked={configCities.includes(name)}\n onChange={() => setConfigCities(prev => prev.includes(name) ? prev.filter(c => c !== name) : [...prev, name])}\n className=\"rounded border-gray-300 text-blue-600 focus:ring-blue-500 h-3.5 w-3.5\" />\n {name}\n </label>\n ))}\n </div>\n </div>\n </WidgetSettingsModal>\n </>\n );\n}\n"]}
|
package/dist/apps/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/apps/openAttachment.ts","../../src/apps/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAkDA,SAAS,MAAM,IAAA,EAAsB;AACnC,EAAA,MAAM,IAAI,4BAAA,CAA6B,IAAA,CAAA,CAAM,IAAA,IAAQ,EAAA,EAAI,MAAM,CAAA;AAC/D,EAAA,OAAO,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,CAAE,aAAY,GAAI,EAAA;AAClC;AAEA,IAAM,qCAAqB,IAAI,GAAA,CAAI,CAAC,KAAA,EAAO,KAAK,CAAC,CAAA;AACjD,IAAM,mBAAA,uBAA0B,GAAA,CAAI,CAAC,QAAQ,KAAA,EAAO,MAAA,EAAQ,KAAK,CAAC,CAAA;AAClE,IAAM,SAAA,mBAAY,IAAI,GAAA,CAAI,CAAC,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,MAAM,CAAC,CAAA;AACrF,IAAM,UAAA,mBAAa,IAAI,GAAA,CAAI,CAAC,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ,KAAK,CAAC,CAAA;AAGtF,SAAS,eAAe,SAAA,EAAkE;AAC/F,EAAA,MAAM,GAAA,GAAM,MAAM,SAAS,CAAA;AAC3B,EAAA,IAAI,GAAA,KAAQ,OAAO,OAAO,KAAA;AAC1B,EAAA,IAAI,GAAA,KAAQ,OAAO,OAAO,KAAA;AAC1B,EAAA,IAAI,kBAAA,CAAmB,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,KAAA;AACxC,EAAA,IAAI,SAAA,CAAU,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,OAAA;AAC/B,EAAA,IAAI,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA,EAAG,OAAO,IAAA;AAChC,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,aAAa,GAAA,EAAa;AACjC,EAAA,MAAA,CAAO,IAAA,CAAK,GAAA,EAAK,QAAA,EAAU,qBAAqB,CAAA;AAClD;AAEA,eAAe,QAAA,CAAS,GAAA,EAAa,IAAA,EAA6B,GAAA,EAA0C;AAC1G,EAAA,IAAI,IAAA,CAAK,WAAW,OAAA,CAAQ,MAAM,KAAK,SAAA,CAAU,GAAG,GAAG,IAAA,EAAK;AAC5D,EAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,GAAG,CAAA;AAC3B,EAAA,IAAI,CAAC,IAAI,EAAA,EAAI,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,GAAA,CAAI,MAAM,CAAA,CAAE,CAAA;AAC1D,EAAA,OAAO,IAAI,IAAA,EAAK;AAClB;AAEA,SAAS,SAAA,CAAU,KAAc,QAAA,EAA0B;AACzD,EAAA,MAAM,OAAA,GAAU,GAAA,YAAe,KAAA,GAAQ,GAAA,CAAI,OAAA,GAAU,EAAA;AACrD,EAAA,OAAO,OAAA,IAAW,QAAA;AACpB;AAUA,eAAsB,cAAA,CACpB,GAAA,EACA,QAAA,EACA,IAAA,GAA8B,EAAC,EAChB;AACf,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,IAAO,EAAA;AACxB,EAAA,MAAM,QAAA,GAAW,KAAK,QAAA,IAAY,YAAA;AAClC,EAAA,IAAI,CAAC,GAAA,IAAO,CAAC,IAAA,CAAK,SAAA,EAAW;AAC3B,IAAA,aAAA,CAAM,MAAM,uCAAuC,CAAA;AACnD,IAAA;AAAA,EACF;AACA,EAAA,MAAM,IAAA,GAAO,cAAA,CAAe,QAAQ,CAAA,IAAK,eAAe,GAAG,CAAA;AAE3D,EAAA,IAAI,SAAS,KAAA,EAAO;AAClB,IAAA,IAAI;AACF,MAAA,qBAAA,CAAsB,EAAE,KAAK,MAAM,QAAA,CAAS,KAAK,IAAA,EAAM,GAAG,CAAA,EAAG,QAAA,EAAU,CAAA;AACvE,MAAA,QAAA,CAAS,cAAc,CAAA;AAAA,IACzB,CAAA,CAAA,MAAQ;AACN,MAAA,aAAA,CAAM,MAAM,iEAA4D,CAAA;AACxE,MAAA,IAAI,GAAA,eAAkB,GAAG,CAAA;AAAA,IAC3B;AACA,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,mBAAA,CAAoB,IAAI,KAAA,CAAM,QAAQ,KAAK,KAAA,CAAM,GAAG,CAAC,CAAA,EAAG;AAG1D,IAAA,aAAA,CAAM,MAAM,kFAAkF,CAAA;AAC9F,IAAA,IAAI,GAAA,eAAkB,GAAG,CAAA;AACzB,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,IAAA,EAAM;AAET,IAAA,IAAI,CAAC,GAAA,EAAK;AACR,MAAA,aAAA,CAAM,MAAM,uCAAuC,CAAA;AACnD,MAAA;AAAA,IACF;AACA,IAAA,aAAA,CAAM,KAAK,sEAAiE,CAAA;AAC5E,IAAA,YAAA,CAAa,GAAG,CAAA;AAChB,IAAA;AAAA,EACF;AAEA,EAAA,IAAI,CAAC,KAAK,SAAA,EAAW;AACnB,IAAA,aAAA,CAAc,EAAE,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,CAAA;AACrC,IAAA,QAAA,CAAS,UAAU,CAAA;AACnB,IAAA;AAAA,EACF;AAKA,EAAA,MAAM,SAAS,aAAA,CAAc;AAAA,IAC3B,QAAA;AAAA,IAAU,IAAA;AAAA,IAAM,UAAA,EAAY,IAAA;AAAA,IAC5B,iBAAA,EAAmB,KAAK,cAAA,IAAkB;AAAA,GAC3C,CAAA;AACD,EAAA,QAAA,CAAS,UAAU,CAAA;AACnB,EAAA,IAAI;AACF,IAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,SAAA,CAAU,GAAG,CAAA;AACrC,IAAA,MAAA,CAAO,MAAA,CAAO,EAAE,GAAA,EAAK,GAAA,CAAI,gBAAgB,IAAI,CAAA,EAAG,QAAA,EAAU,IAAA,EAAM,CAAA;AAAA,EAClE,SAAS,GAAA,EAAK;AACZ,IAAA,MAAA,CAAO,MAAA,CAAO;AAAA,MACZ,QAAA;AAAA,MAAU,IAAA;AAAA,MAAM,UAAA,EAAY,KAAA;AAAA,MAC5B,iBAAA,EAAmB,SAAA,CAAU,GAAA,EAAK,2BAA2B;AAAA,KAC9D,CAAA;AAAA,EACH;AACF;;;AC3IA,IAAM,UAAA,GAAa,IAAA,CAAK,MAAM,OAAO,2BAAc,CAAC;AACpD,IAAM,WAAA,GAAc,IAAA,CAAK,MAAM,OAAO,4BAAe,CAAC;AACtD,IAAM,OAAA,GAAU,IAAA,CAAK,MAAM,OAAO,wBAAW,CAAC;AAC9C,IAAM,iBAAA,GAAoB,IAAA,CAAK,MAAM,OAAO,kCAAqB,CAAC;AAClE,IAAM,aAAA,GAAgB,IAAA,CAAK,MAAM,OAAO,8BAAiB,CAAC;AAC1D,IAAM,OAAA,GAAU,IAAA,CAAK,MAAM,OAAO,wBAAW,CAAC;AAC9C,IAAM,UAAA,GAAa,IAAA,CAAK,MAAM,OAAO,2BAAc,CAAC;AACpD,IAAM,KAAA,GAAQ,IAAA,CAAK,MAAM,OAAO,sBAAS,CAAC;AAG1C,IAAM,OAAA,GAAU,IAAA,CAAK,MAAM,OAAO,wBAAW,CAAC;AAM9C,IAAM,SAAA,GAAY,IAAA,CAAK,MAAM,OAAO,0BAAa,CAAC;AAClD,IAAM,SAAA,GAAY,IAAA,CAAK,MAAM,OAAO,0BAAa,CAAC;AAClD,IAAM,KAAA,GAAQ,IAAA,CAAK,MAAM,OAAO,sBAAS,CAAC;AAG1C,IAAM,OAAA,GAAU,IAAA,CAAK,MAAM,OAAO,wBAAW,CAAC;AAEvC,IAAM,WAAA,GAA8B;AAAA,EACzC,eAAe,EAAE,SAAA,EAAW,YAAY,KAAA,EAAO,YAAA,EAAc,MAAM,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,OAAA,EAAS,MAAM,MAAA,EAAQ,IAAA,EAAM,YAAY,CAAC,GAAA,EAAK,GAAG,CAAA,EAAE;AAAA,EAClJ,cAAA,EAAgB,EAAE,SAAA,EAAW,WAAA,EAAa,KAAA,EAAO,cAAA,EAAgB,IAAA,EAAM,KAAA,EAAO,QAAA,EAAU,IAAA,EAAM,aAAA,EAAe,IAAA,EAAK;AAAA,EAClH,UAAA,EAAY,EAAE,SAAA,EAAW,OAAA,EAAS,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,SAAA,EAAW,IAAA,EAAK;AAAA,EACrG,YAAY,EAAE,SAAA,EAAW,SAAS,KAAA,EAAO,SAAA,EAAW,MAAM,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,MAAA,EAAQ,MAAM,UAAA,EAAY,IAAA,EAAM,YAAY,CAAC,GAAA,EAAK,GAAG,CAAA,EAAE;AAAA,EACtI,aAAa,EAAE,SAAA,EAAW,mBAAmB,KAAA,EAAO,oBAAA,EAAsB,MAAM,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,MAAA,EAAQ,MAAM,UAAA,EAAY,IAAA,EAAM,YAAY,CAAC,GAAA,EAAK,GAAG,CAAA,EAAE;AAAA,EAC5J,aAAa,EAAE,SAAA,EAAW,aAAA,EAAe,KAAA,EAAO,kBAAkB,IAAA,EAAM,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,QAAQ,IAAA,EAAM,UAAA,EAAY,CAAC,GAAA,EAAK,GAAG,CAAA,EAAE;AAAA,EAClI,gBAAgB,EAAE,SAAA,EAAW,YAAY,KAAA,EAAO,aAAA,EAAe,MAAM,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,MAAA,EAAQ,MAAM,UAAA,EAAY,IAAA,EAAM,YAAY,CAAC,GAAA,EAAK,GAAG,CAAA,EAAE;AAAA,EACjJ,UAAU,EAAE,SAAA,EAAW,OAAO,KAAA,EAAO,QAAA,EAAU,MAAM,IAAA,EAAM,OAAA,EAAS,IAAA,EAAM,MAAA,EAAQ,MAAM,UAAA,EAAY,IAAA,EAAM,YAAY,CAAC,GAAA,EAAK,GAAG,CAAA;AACjI;AAEO,IAAM,YAAA,GAA+B;AAAA,EAC1C,UAAA,EAAY,EAAE,SAAA,EAAW,OAAA,EAAS,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,QAAA,EAAU,IAAA,EAAM,aAAA,EAAe,IAAA,EAAK;AAAA,EACrG,YAAA,EAAc,EAAE,SAAA,EAAW,SAAA,EAAW,KAAA,EAAO,WAAA,EAAa,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,aAAA,EAAe,IAAA,EAAK;AAAA,EAC1G,QAAA,EAAU,EAAE,SAAA,EAAW,KAAA,EAAO,OAAO,OAAA,EAAS,IAAA,EAAM,IAAA,EAAM,QAAA,EAAU,IAAA;AACtE;AAEO,IAAM,OAAA,GAA0B;AAAA,EACrC,UAAA,EAAY,EAAE,SAAA,EAAW,OAAA,EAAS,KAAA,EAAO,SAAA,EAAW,IAAA,EAAM,KAAA,EAAO,QAAA,EAAU,IAAA,EAAM,aAAA,EAAe,IAAA;AAClG;AAEO,IAAM,WAAA,GAA8B;AAAA,EACzC,GAAG,WAAA;AAAA,EACH,GAAG,YAAA;AAAA,EACH,GAAG;AACL","file":"index.js","sourcesContent":["/**\n * Route a stored file into the app that can read it — Preview for PDFs,\n * images, drawings and 3D models, Spreadsheet for CSV/TSV — instead of handing\n * it to a browser tab (harness UI-18).\n *\n * Lifted from the admin portal, where it had routed email and CRM-note\n * attachments since 2026-09; the customer, supplier and dealer portals needed\n * the same decision table for their own attachments, and a fourth copy of a\n * classification this specific is exactly what drifts.\n *\n * Two transports, because stored-file URLs differ by deployment:\n *\n * - By default the viewer is given the URL and fetches it itself. Fine where\n * the file is same-origin with the page.\n * - Pass `fetchBlob` where it is not. A presigned/CDN URL is cross-origin to\n * the portal, so the viewer's own fetch fails (\"Failed to fetch\") even\n * though the URL opens perfectly in a tab; the caller's API client pulls\n * the bytes instead, and the window shows a placeholder until they land.\n *\n * Binary workbooks (xlsx, ods) stay downloads on purpose: previewing one means\n * parsing untrusted bytes in the host's own origin.\n */\nimport toast from '../shell/toast';\nimport { setPdfPreview } from './_previewStage';\nimport { setSpreadsheetPreview } from './_spreadsheetStage';\n\n/** Minimal attachment shape — a filename and where the bytes are. */\nexport interface OpenableAttachment {\n filename?: string | null;\n /** `null` where the serializer could not address the stored file; treated\n * exactly like a missing one, so a caller need not narrow before calling. */\n url?: string | null;\n}\n\n/** `useWindowManager().openPage`. */\nexport type OpenPage = (path: string) => void;\n\nexport interface OpenAttachmentOptions {\n /**\n * Fetch the bytes yourself — for a URL the page cannot fetch (presigned/CDN)\n * or one that needs an Authorization header. Called only for a file a viewer\n * can render; the window opens on `loadingMessage` and swaps in the result.\n * Reject with an Error whose message the reader should see.\n */\n fetchBlob?: (att: OpenableAttachment) => Promise<Blob>;\n /** Placeholder headline while `fetchBlob` runs. Default: \"LOADING FILE\". */\n loadingMessage?: string;\n}\n\n/** Lower-case file extension (no dot) from a name or URL, '' if none. */\nfunction extOf(name: string): string {\n const m = /\\.([a-z0-9]+)(?:[?#].*)?$/i.exec((name || '').trim());\n return m ? m[1].toLowerCase() : '';\n}\n\nconst DELIMITED_TEXT_EXT = new Set(['csv', 'tsv']);\nconst BINARY_WORKBOOK_EXT = new Set(['xlsx', 'xls', 'xlsm', 'ods']);\nconst IMAGE_EXT = new Set(['png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', 'svg', 'avif']);\nconst THREED_EXT = new Set(['step', 'stp', 'stl', 'obj', 'gltf', 'glb', '3mf', 'iges', 'igs']);\n\n/** Which viewer renders this file, or `null` for one neither app can show. */\nexport function attachmentKind(nameOrUrl: string): 'pdf' | 'image' | '3d' | 'dxf' | 'csv' | null {\n const ext = extOf(nameOrUrl);\n if (ext === 'pdf') return 'pdf';\n if (ext === 'dxf') return 'dxf';\n if (DELIMITED_TEXT_EXT.has(ext)) return 'csv';\n if (IMAGE_EXT.has(ext)) return 'image';\n if (THREED_EXT.has(ext)) return '3d';\n return null;\n}\n\nfunction openInNewTab(url: string) {\n window.open(url, '_blank', 'noopener,noreferrer');\n}\n\nasync function readText(url: string, opts: OpenAttachmentOptions, att: OpenableAttachment): Promise<string> {\n if (opts.fetchBlob) return (await opts.fetchBlob(att)).text();\n const res = await fetch(url);\n if (!res.ok) throw new Error(`fetch failed: ${res.status}`);\n return res.text();\n}\n\nfunction errorText(err: unknown, fallback: string): string {\n const message = err instanceof Error ? err.message : '';\n return message || fallback;\n}\n\n/**\n * Open `att` in the shell app that can read it. `openPage` comes from\n * `useWindowManager()`.\n *\n * Resolves once the file has been handed to a window (or opened in a tab); it\n * never throws — a failure is shown to the reader, in the viewer when one is\n * already open for the file and as a toast when there is nothing to show it in.\n */\nexport async function openAttachment(\n att: OpenableAttachment,\n openPage: OpenPage,\n opts: OpenAttachmentOptions = {},\n): Promise<void> {\n const url = att?.url || '';\n const filename = att?.filename || 'attachment';\n if (!url && !opts.fetchBlob) {\n toast.error('This attachment has no download link.');\n return;\n }\n const kind = attachmentKind(filename) ?? attachmentKind(url);\n\n if (kind === 'csv') {\n try {\n setSpreadsheetPreview({ csv: await readText(url, opts, att), filename });\n openPage('/spreadsheet');\n } catch {\n toast.error('Could not open the spreadsheet — opening the file instead.');\n if (url) openInNewTab(url);\n }\n return;\n }\n\n if (BINARY_WORKBOOK_EXT.has(extOf(filename) || extOf(url))) {\n // Parsing an untrusted workbook in the host's own origin is not worth a\n // preview; the reader gets the file itself.\n toast.error('Spreadsheet preview is unavailable for this file type. Opening the file instead.');\n if (url) openInNewTab(url);\n return;\n }\n\n if (!kind) {\n // No viewer renders docx / txt / zip — say so rather than appear to fail.\n if (!url) {\n toast.error('This attachment has no download link.');\n return;\n }\n toast.info('Opening this file outside the app — no viewer can show it here.');\n openInNewTab(url);\n return;\n }\n\n if (!opts.fetchBlob) {\n setPdfPreview({ url, filename, kind });\n openPage('/preview');\n return;\n }\n\n // The viewer cannot fetch this URL itself: open it on a placeholder and swap\n // the bytes in, so a slow file is visibly loading and a failed one says why\n // in the window the reader is already looking at.\n const handle = setPdfPreview({\n filename, kind, converting: true,\n convertingMessage: opts.loadingMessage || 'LOADING FILE',\n });\n openPage('/preview');\n try {\n const blob = await opts.fetchBlob(att);\n handle.update({ url: URL.createObjectURL(blob), filename, kind });\n } catch (err) {\n handle.update({\n filename, kind, converting: false,\n convertingMessage: errorText(err, 'Failed to load this file.'),\n });\n }\n}\n","/**\n * Bundled apps — pre-built window registry entries for the 12 apps that ship\n * with `efficient-shell`. Consumers compose them into their own registry via\n * `createWindowRegistry`:\n *\n * import { createWindowRegistry } from 'efficient-shell';\n * import { bundledApps } from 'efficient-shell/apps';\n * import { erpEntities } from './shell-config';\n *\n * const windows = createWindowRegistry(bundledApps, erpEntities);\n *\n * Subsets are also exported (`utilityApps`, `documentApps`, `webApps`) so a\n * consumer can pick-and-choose without importing every component.\n *\n * NOTE: Notepad requires consumer-supplied persistence for stored content.\n * WorldClock uses `useShellPrefs()` so it lives in `bundledApps`; without a\n * consumer-supplied prefs adapter the city list won't survive a reload.\n */\nimport { lazy } from 'react';\nimport type { WindowRegistry } from '../windowRegistry/types';\n\n// ── Utility apps ──\nconst Calculator = lazy(() => import('./Calculator'));\nconst Spreadsheet = lazy(() => import('./Spreadsheet'));\nconst Weather = lazy(() => import('./Weather'));\nconst CurrencyConverter = lazy(() => import('./CurrencyConverter'));\nconst PomodoroTimer = lazy(() => import('./PomodoroTimer'));\nconst Notepad = lazy(() => import('./Notepad'));\nconst WorldClock = lazy(() => import('./WorldClock'));\nconst Stock = lazy(() => import('./Stock'));\n\n// ── Document apps ──\nconst Preview = lazy(() => import('./Preview'));\n/** The PDF reader out of the Preview window, for embedding in a pane of your\n * own (a preview beside a form, a document tab). Lazy for the same reason\n * every app here is: its static `pdfjs-dist` import must not land in a host's\n * startup bundle — so render it inside a `<Suspense>`, and give it a parent\n * with a resolved height. See `PdfViewerProps` for `fit`. */\nconst PdfViewer = lazy(() => import('./PdfViewer'));\nconst Documents = lazy(() => import('./Documents'));\nconst Files = lazy(() => import('./Files'));\n\n// ── Web ──\nconst Browser = lazy(() => import('./Browser'));\n\nexport const utilityApps: WindowRegistry = {\n '/calculator': { component: Calculator, label: 'Calculator', size: 'sm', allowPinOnTop: true, utility: true, widget: true, dimensions: [280, 420] },\n '/spreadsheet': { component: Spreadsheet, label: 'Spreadsheets', size: '2xl', appStyle: true, multiInstance: true },\n '/notepad': { component: Notepad, label: 'Notepad', size: 'lg', allowPinOnTop: true, flushBody: true },\n '/weather': { component: Weather, label: 'Weather', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 400] },\n '/currency': { component: CurrencyConverter, label: 'Currency Converter', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 480] },\n '/pomodoro': { component: PomodoroTimer, label: 'Pomodoro Timer', size: 'sm', utility: true, widget: true, dimensions: [320, 600] },\n '/world-clock': { component: WorldClock, label: 'World Clock', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 480] },\n '/stock': { component: Stock, label: 'Stocks', size: 'sm', utility: true, widget: true, autoHeight: true, dimensions: [320, 360] },\n};\n\nexport const documentApps: WindowRegistry = {\n '/preview': { component: Preview, label: 'Preview', size: '2xl', appStyle: true, multiInstance: true },\n '/documents': { component: Documents, label: 'Documents', size: 'xl', appStyle: true, multiInstance: true },\n '/files': { component: Files, label: 'Files', size: 'xl', appStyle: true },\n};\n\nexport const webApps: WindowRegistry = {\n '/browser': { component: Browser, label: 'Browser', size: '2xl', appStyle: true, multiInstance: true },\n};\n\nexport const bundledApps: WindowRegistry = {\n ...utilityApps,\n ...documentApps,\n ...webApps,\n};\n\nexport {\n Calculator,\n Spreadsheet,\n Notepad,\n Weather,\n CurrencyConverter,\n PomodoroTimer,\n WorldClock,\n Stock,\n Preview,\n PdfViewer,\n Documents,\n Files,\n Browser,\n};\n\nexport { BUILTIN_APP_INFO } from './_about';\nexport type { BuiltinAppId, BuiltinAppInfo } from './_about';\n// Setters/config live in small standalone modules (not the app-implementation\n// files) so importing them here never drags an app chunk — most notably\n// Preview's static pdfjs-dist import — into a host's startup bundle.\nexport { setPdfPreview } from './_previewStage';\nexport { setSpreadsheetPreview } from './_spreadsheetStage';\n// Routes a stored file to whichever of the two can read it (UI-18). Same\n// module family for the same reason: it imports the stages, not the apps.\nexport { openAttachment, attachmentKind } from './openAttachment';\nexport type { OpenableAttachment, OpenAttachmentOptions, OpenPage } from './openAttachment';\nexport { setBrowserStartUrl } from './_browserStage';\nexport { openFilesInTrashMode, setFilesDemoTree } from './_filesShared';\nexport type { FilesDemoNode } from './_filesShared';\nexport type { PdfPreviewData, PdfPreviewHandle } from './_previewStage';\n// Type-only, so this re-export is erased at build and never pulls the module.\nexport type { PdfViewerProps } from './PdfViewer';\nexport type { SpreadsheetPreviewData, SpreadsheetPreviewHandle } from './_spreadsheetStage';\n"]}
|
package/dist/chunk-5O42JXQE.js
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
// src/apps/_spreadsheetStage.ts
|
|
2
|
-
var SPREADSHEET_PREVIEW_UPDATE_EVENT = "react-os-shell:spreadsheet-preview-update";
|
|
3
|
-
var pendingSpreadsheet = null;
|
|
4
|
-
var nextSpreadsheetToken = 0;
|
|
5
|
-
function setSpreadsheetPreview(data) {
|
|
6
|
-
const token = ++nextSpreadsheetToken;
|
|
7
|
-
const stage = { token, data };
|
|
8
|
-
pendingSpreadsheet = stage;
|
|
9
|
-
return {
|
|
10
|
-
update(next) {
|
|
11
|
-
if (pendingSpreadsheet === stage) stage.data = next;
|
|
12
|
-
if (typeof window === "undefined") return;
|
|
13
|
-
window.dispatchEvent(new CustomEvent(SPREADSHEET_PREVIEW_UPDATE_EVENT, { detail: { token, data: next } }));
|
|
14
|
-
}
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
function peekSpreadsheetPreviewStage() {
|
|
18
|
-
return pendingSpreadsheet;
|
|
19
|
-
}
|
|
20
|
-
function claimSpreadsheetPreviewStage(stage) {
|
|
21
|
-
if (pendingSpreadsheet === stage) pendingSpreadsheet = null;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export { SPREADSHEET_PREVIEW_UPDATE_EVENT, claimSpreadsheetPreviewStage, peekSpreadsheetPreviewStage, setSpreadsheetPreview };
|
|
25
|
-
//# sourceMappingURL=chunk-5O42JXQE.js.map
|
|
26
|
-
//# sourceMappingURL=chunk-5O42JXQE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/apps/_spreadsheetStage.ts"],"names":[],"mappings":";AAiCO,IAAM,gCAAA,GAAmC;AAahD,IAAI,kBAAA,GAAqD,IAAA;AACzD,IAAI,oBAAA,GAAuB,CAAA;AAIpB,SAAS,sBAAsB,IAAA,EAAwD;AAC5F,EAAA,MAAM,QAAQ,EAAE,oBAAA;AAChB,EAAA,MAAM,KAAA,GAAiC,EAAE,KAAA,EAAO,IAAA,EAAK;AACrD,EAAA,kBAAA,GAAqB,KAAA;AACrB,EAAA,OAAO;AAAA,IACL,OAAO,IAAA,EAA8B;AAMnC,MAAA,IAAI,kBAAA,KAAuB,KAAA,EAAO,KAAA,CAAM,IAAA,GAAO,IAAA;AAC/C,MAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,WAAA,CAAY,gCAAA,EAAkC,EAAE,MAAA,EAAQ,EAAE,KAAA,EAAO,IAAA,EAAM,IAAA,EAAK,EAAG,CAAC,CAAA;AAAA,IAC3G;AAAA,GACF;AACF;AAGO,SAAS,2BAAA,GAA8D;AAC5E,EAAA,OAAO,kBAAA;AACT;AAKO,SAAS,6BAA6B,KAAA,EAAsC;AACjF,EAAA,IAAI,kBAAA,KAAuB,OAAO,kBAAA,GAAqB,IAAA;AACzD","file":"chunk-5O42JXQE.js","sourcesContent":["/**\n * Spreadsheet staging — the tiny consumer-facing surface of the Spreadsheets\n * app. Lives apart from Spreadsheet.tsx so importing `setSpreadsheetPreview`\n * (from `efficient-shell/apps` or shell internals like openPreviewFile) never\n * drags the grid implementation into a host's startup bundle. The Spreadsheet\n * window component stays behind its React.lazy dynamic import and drains the\n * stage on mount via the @internal peek/claim helpers below.\n */\n\nexport interface SpreadsheetPreviewData {\n /** CSV text (comma- or tab-separated). */\n csv: string;\n /** Display name; the title strips a trailing `.csv`/`.tsv`/`.txt`. */\n filename: string;\n /** When provided, the toolbar shows an Email button that calls back with the\n * sheet serialized as CSV at click time (edits included) and a filename\n * derived from the current title. */\n onEmail?: (csv: string, filename: string) => void;\n}\n\n/** Handle returned by `setSpreadsheetPreview`. Holds the identity of the\n * staged payload so a later `.update()` only targets the window that picked\n * it up — opening a second Spreadsheet never clobbers the first. */\nexport interface SpreadsheetPreviewHandle {\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 sheet instead of whatever it was staged with.\n * No-op only once the window that consumed the staging has been closed. */\n update(next: SpreadsheetPreviewData): void;\n}\n\n/** @internal Event carrying `.update()` payloads to the claiming window. */\nexport const SPREADSHEET_PREVIEW_UPDATE_EVENT = 'react-os-shell:spreadsheet-preview-update';\n\n/** @internal Staged payload awaiting the next Spreadsheet 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 `claimSpreadsheetPreviewStage` and the claimant's\n * own `consumedRef` are holding. */\nexport interface PendingSpreadsheetStage {\n token: number;\n data: SpreadsheetPreviewData;\n}\n\nlet pendingSpreadsheet: PendingSpreadsheetStage | null = null;\nlet nextSpreadsheetToken = 0;\n\n/** Stage CSV content for the next Spreadsheet window mount. The returned\n * handle's `update()` method swaps content in *that* specific window only. */\nexport function setSpreadsheetPreview(data: SpreadsheetPreviewData): SpreadsheetPreviewHandle {\n const token = ++nextSpreadsheetToken;\n const stage: PendingSpreadsheetStage = { token, data };\n pendingSpreadsheet = stage;\n return {\n update(next: SpreadsheetPreviewData) {\n // Same delivery gap the Preview stage has (see _previewStage.ts): the\n // window is a lazy chunk, so a consumer that resolves quickly can call\n // this before any window has mounted to hear the event, and the payload\n // would be dropped. Rewrite the stage as well while it is still ours —\n // `pendingSpreadsheet === stage` is exactly \"nobody has claimed it yet\".\n if (pendingSpreadsheet === stage) stage.data = next;\n if (typeof window === 'undefined') return;\n window.dispatchEvent(new CustomEvent(SPREADSHEET_PREVIEW_UPDATE_EVENT, { detail: { token, data: next } }));\n },\n };\n}\n\n/** @internal Render-phase peek — see Spreadsheet.tsx for the drain protocol. */\nexport function peekSpreadsheetPreviewStage(): PendingSpreadsheetStage | null {\n return pendingSpreadsheet;\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 claimSpreadsheetPreviewStage(stage: PendingSpreadsheetStage): void {\n if (pendingSpreadsheet === stage) pendingSpreadsheet = null;\n}\n"]}
|
package/dist/chunk-5RPTS3BT.js
DELETED
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { useShellStrings } from './chunk-YE6GUDGP.js';
|
|
2
|
-
import { Fragment } from 'react';
|
|
3
|
-
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
-
|
|
5
|
-
var DEFAULT_SEPARATOR = /* @__PURE__ */ jsx("svg", { className: "h-3.5 w-3.5 shrink-0 text-gray-300", viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": true, children: /* @__PURE__ */ jsx(
|
|
6
|
-
"path",
|
|
7
|
-
{
|
|
8
|
-
fillRule: "evenodd",
|
|
9
|
-
d: "M7.21 14.77a.75.75 0 0 1 .02-1.06L11.168 10 7.23 6.29a.75.75 0 1 1 1.04-1.08l4.5 4.25a.75.75 0 0 1 0 1.08l-4.5 4.25a.75.75 0 0 1-1.06-.02Z",
|
|
10
|
-
clipRule: "evenodd"
|
|
11
|
-
}
|
|
12
|
-
) });
|
|
13
|
-
var CRUMB_LINK = "inline-flex min-w-0 items-center gap-1 truncate rounded px-1 -mx-1 text-gray-500 transition-colors hover:text-gray-900 hover:underline rosh-focus-ring focus-visible:ring-2 focus-visible:ring-[color:var(--rosh-focus-ring-solid)]";
|
|
14
|
-
function Breadcrumbs({ items, separator, maxItems = 0, className }) {
|
|
15
|
-
const strings = useShellStrings().breadcrumbs;
|
|
16
|
-
if (items.length === 0) return null;
|
|
17
|
-
const sep = separator ?? DEFAULT_SEPARATOR;
|
|
18
|
-
const crumbs = [];
|
|
19
|
-
const lastIndex = items.length - 1;
|
|
20
|
-
if (maxItems > 0 && items.length > maxItems && maxItems >= 2) {
|
|
21
|
-
const tailCount = Math.max(1, maxItems - 1);
|
|
22
|
-
crumbs.push({ kind: "item", item: items[0], isLast: false });
|
|
23
|
-
crumbs.push({ kind: "ellipsis" });
|
|
24
|
-
for (let i = items.length - tailCount; i <= lastIndex; i++) {
|
|
25
|
-
crumbs.push({ kind: "item", item: items[i], isLast: i === lastIndex });
|
|
26
|
-
}
|
|
27
|
-
} else {
|
|
28
|
-
items.forEach((item, i) => crumbs.push({ kind: "item", item, isLast: i === lastIndex }));
|
|
29
|
-
}
|
|
30
|
-
return /* @__PURE__ */ jsx("nav", { "aria-label": strings.label, className: `min-w-0 ${className ?? ""}`, children: /* @__PURE__ */ jsx("ol", { className: "flex items-center gap-1.5 text-sm", children: crumbs.map((crumb, i) => /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
31
|
-
i > 0 && /* @__PURE__ */ jsx("li", { "aria-hidden": true, className: "flex items-center", children: sep }),
|
|
32
|
-
/* @__PURE__ */ jsx("li", { className: "flex min-w-0 items-center", children: crumb.kind === "ellipsis" ? /* @__PURE__ */ jsx("span", { className: "px-0.5 text-gray-400 select-none", "aria-label": strings.hidden, children: "\u2026" }) : crumb.isLast || !(crumb.item.href || crumb.item.onClick) ? /* @__PURE__ */ jsxs(
|
|
33
|
-
"span",
|
|
34
|
-
{
|
|
35
|
-
"aria-current": crumb.isLast ? "page" : void 0,
|
|
36
|
-
className: `inline-flex min-w-0 items-center gap-1 truncate ${crumb.isLast ? "font-medium text-gray-900" : "text-gray-500"}`,
|
|
37
|
-
children: [
|
|
38
|
-
crumb.item.icon,
|
|
39
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: crumb.item.label })
|
|
40
|
-
]
|
|
41
|
-
}
|
|
42
|
-
) : crumb.item.href ? /* @__PURE__ */ jsxs(
|
|
43
|
-
"a",
|
|
44
|
-
{
|
|
45
|
-
href: crumb.item.href,
|
|
46
|
-
onClick: crumb.item.onClick,
|
|
47
|
-
className: CRUMB_LINK,
|
|
48
|
-
children: [
|
|
49
|
-
crumb.item.icon,
|
|
50
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: crumb.item.label })
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
) : /* @__PURE__ */ jsxs(
|
|
54
|
-
"button",
|
|
55
|
-
{
|
|
56
|
-
type: "button",
|
|
57
|
-
onClick: crumb.item.onClick,
|
|
58
|
-
className: CRUMB_LINK,
|
|
59
|
-
children: [
|
|
60
|
-
crumb.item.icon,
|
|
61
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: crumb.item.label })
|
|
62
|
-
]
|
|
63
|
-
}
|
|
64
|
-
) })
|
|
65
|
-
] }, i)) }) });
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export { Breadcrumbs };
|
|
69
|
-
//# sourceMappingURL=chunk-5RPTS3BT.js.map
|
|
70
|
-
//# sourceMappingURL=chunk-5RPTS3BT.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shell/Breadcrumbs.tsx"],"names":[],"mappings":"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","file":"chunk-5RPTS3BT.js","sourcesContent":["import { Fragment } from 'react';\nimport type { MouseEvent, ReactNode } from 'react';\nimport { useShellStrings } from './strings';\n\n/**\n * Generic breadcrumb trail. Self-contained and styled with the same Tailwind\n * utilities the shell already ships, so consumers get it for free.\n *\n * Pass an ordered list of `items` from root → current. Every crumb except the\n * last renders as a button when it has an `onClick`; the last crumb is treated\n * as the current location — rendered inert with `aria-current=\"page\"`. When the\n * trail is long, set `maxItems` to collapse the middle into an ellipsis\n * (`first … last-n` ), keeping the first and the tail visible.\n */\nexport interface BreadcrumbItem {\n /** Visible label. */\n label: ReactNode;\n /** Optional leading icon (typically a 3.5×3.5 svg). */\n icon?: ReactNode;\n /**\n * Navigate to this crumb. Omitted on the current (last) crumb.\n *\n * Receives the event, which is what makes `href` usable from a routed app:\n * the handler calls `preventDefault()` on a plain click and hands the\n * navigation to its router, while ctrl/middle/right clicks fall through to\n * the browser untouched. Without the argument an anchor could only ever do a\n * full page load, which is the thing a single-page app is avoiding.\n */\n onClick?: (event: MouseEvent<HTMLAnchorElement | HTMLButtonElement>) => void;\n /**\n * Where this crumb goes, when it is a real destination.\n *\n * A routed app needs this rather than `onClick` alone: an `<a href>` can be\n * middle-clicked into a new tab, copied, and read off the status bar before\n * committing to it — none of which a button offers, however well it behaves\n * once pressed. Given both, the anchor still calls `onClick`, so a client-side\n * router can intercept the plain-click case and leave the rest to the browser.\n */\n href?: string;\n}\n\nexport interface BreadcrumbsProps {\n items: BreadcrumbItem[];\n /** Node rendered between crumbs. Defaults to a chevron. */\n separator?: ReactNode;\n /** Collapse the middle to an ellipsis when there are more than this many\n * crumbs. `0` (default) never collapses. */\n maxItems?: number;\n className?: string;\n}\n\nconst DEFAULT_SEPARATOR = (\n <svg className=\"h-3.5 w-3.5 shrink-0 text-gray-300\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden>\n <path\n fillRule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 0 1 .02-1.06L11.168 10 7.23 6.29a.75.75 0 1 1 1.04-1.08l4.5 4.25a.75.75 0 0 1 0 1.08l-4.5 4.25a.75.75 0 0 1-1.06-.02Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n);\n\n/** Shared by the anchor and the button forms so the two cannot drift apart. */\nconst CRUMB_LINK =\n 'inline-flex min-w-0 items-center gap-1 truncate rounded px-1 -mx-1 text-gray-500 ' +\n 'transition-colors hover:text-gray-900 hover:underline rosh-focus-ring focus-visible:ring-2 focus-visible:ring-[color:var(--rosh-focus-ring-solid)]';\n\ntype Crumb = { kind: 'item'; item: BreadcrumbItem; isLast: boolean } | { kind: 'ellipsis' };\n\nexport default function Breadcrumbs({ items, separator, maxItems = 0, className }: BreadcrumbsProps) {\n const strings = useShellStrings().breadcrumbs;\n if (items.length === 0) return null;\n const sep = separator ?? DEFAULT_SEPARATOR;\n\n // Build the display list, collapsing the middle if `maxItems` is exceeded.\n const crumbs: Crumb[] = [];\n const lastIndex = items.length - 1;\n if (maxItems > 0 && items.length > maxItems && maxItems >= 2) {\n const tailCount = Math.max(1, maxItems - 1); // keep the first + this many from the end\n crumbs.push({ kind: 'item', item: items[0], isLast: false });\n crumbs.push({ kind: 'ellipsis' });\n for (let i = items.length - tailCount; i <= lastIndex; i++) {\n crumbs.push({ kind: 'item', item: items[i], isLast: i === lastIndex });\n }\n } else {\n items.forEach((item, i) => crumbs.push({ kind: 'item', item, isLast: i === lastIndex }));\n }\n\n return (\n <nav aria-label={strings.label} className={`min-w-0 ${className ?? ''}`}>\n <ol className=\"flex items-center gap-1.5 text-sm\">\n {crumbs.map((crumb, i) => (\n <Fragment key={i}>\n {i > 0 && <li aria-hidden className=\"flex items-center\">{sep}</li>}\n <li className=\"flex min-w-0 items-center\">\n {crumb.kind === 'ellipsis' ? (\n <span className=\"px-0.5 text-gray-400 select-none\" aria-label={strings.hidden}>…</span>\n ) : crumb.isLast || !(crumb.item.href || crumb.item.onClick) ? (\n <span\n aria-current={crumb.isLast ? 'page' : undefined}\n className={`inline-flex min-w-0 items-center gap-1 truncate ${\n crumb.isLast ? 'font-medium text-gray-900' : 'text-gray-500'\n }`}\n >\n {crumb.item.icon}\n <span className=\"truncate\">{crumb.item.label}</span>\n </span>\n ) : crumb.item.href ? (\n <a\n href={crumb.item.href}\n onClick={crumb.item.onClick}\n className={CRUMB_LINK}\n >\n {crumb.item.icon}\n <span className=\"truncate\">{crumb.item.label}</span>\n </a>\n ) : (\n <button\n type=\"button\"\n onClick={crumb.item.onClick}\n className={CRUMB_LINK}\n >\n {crumb.item.icon}\n <span className=\"truncate\">{crumb.item.label}</span>\n </button>\n )}\n </li>\n </Fragment>\n ))}\n </ol>\n </nav>\n );\n}\n"]}
|
package/dist/chunk-6XJEJWNJ.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { rootIsDark } from './chunk-IPXN646P.js';
|
|
2
|
-
|
|
3
|
-
// src/utils/glass.ts
|
|
4
|
-
function getMenuOpacity() {
|
|
5
|
-
try {
|
|
6
|
-
const val = getComputedStyle(document.documentElement).getPropertyValue("--menu-opacity")?.trim();
|
|
7
|
-
if (val) return parseFloat(val);
|
|
8
|
-
} catch {
|
|
9
|
-
}
|
|
10
|
-
return 0.95;
|
|
11
|
-
}
|
|
12
|
-
var isDarkTheme = rootIsDark;
|
|
13
|
-
function reduceTransparency() {
|
|
14
|
-
try {
|
|
15
|
-
return document.documentElement.classList.contains("rosh-reduce-transparency");
|
|
16
|
-
} catch {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
function tint(colour, alpha) {
|
|
21
|
-
const steps = Math.round(Math.min(1, Math.max(0, alpha)) * 255);
|
|
22
|
-
return `color-mix(in srgb, ${colour} ${+(steps / 255 * 100).toFixed(4)}%, transparent)`;
|
|
23
|
-
}
|
|
24
|
-
function glassStyle(opacity) {
|
|
25
|
-
const o = opacity ?? getMenuOpacity();
|
|
26
|
-
if (reduceTransparency()) {
|
|
27
|
-
return {
|
|
28
|
-
background: "var(--rosh-glass-surface)",
|
|
29
|
-
border: "1px solid var(--rosh-glass-solid-border)",
|
|
30
|
-
boxShadow: "var(--rosh-glass-solid-shadow)"
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
const surface = "var(--rosh-glass-surface)";
|
|
34
|
-
const mid = "var(--rosh-glass-surface-mid)";
|
|
35
|
-
if (isDarkTheme()) {
|
|
36
|
-
return {
|
|
37
|
-
background: `linear-gradient(135deg in srgb, ${tint(surface, o * 0.85)} 0%, ${tint(mid, o * 0.75)} 50%, ${tint(surface, o * 0.85)} 100%)`,
|
|
38
|
-
backdropFilter: "blur(40px) saturate(1.6)",
|
|
39
|
-
WebkitBackdropFilter: "blur(40px) saturate(1.6)",
|
|
40
|
-
border: "1px solid var(--rosh-glass-border)",
|
|
41
|
-
boxShadow: "var(--rosh-glass-shadow)"
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
return {
|
|
45
|
-
background: `linear-gradient(135deg in srgb, ${tint(surface, o * 0.85)} 0%, ${tint(mid, o * 0.65)} 50%, ${tint(surface, o * 0.75)} 100%)`,
|
|
46
|
-
backdropFilter: "blur(40px) saturate(1.8)",
|
|
47
|
-
WebkitBackdropFilter: "blur(40px) saturate(1.8)",
|
|
48
|
-
border: "1px solid var(--rosh-glass-border)",
|
|
49
|
-
boxShadow: "var(--rosh-glass-shadow)"
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
function glassFill(opacity) {
|
|
53
|
-
if (reduceTransparency()) return "var(--rosh-glass-surface)";
|
|
54
|
-
return tint("var(--rosh-glass-surface)", (opacity ?? getMenuOpacity()) * 0.85);
|
|
55
|
-
}
|
|
56
|
-
var GLASS_DIVIDER = "border-white/20";
|
|
57
|
-
var GLASS_INPUT_BG = "glass-input-bg";
|
|
58
|
-
|
|
59
|
-
export { GLASS_DIVIDER, GLASS_INPUT_BG, glassFill, glassStyle };
|
|
60
|
-
//# sourceMappingURL=chunk-6XJEJWNJ.js.map
|
|
61
|
-
//# sourceMappingURL=chunk-6XJEJWNJ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/glass.ts"],"names":[],"mappings":";;;AAIA,SAAS,cAAA,GAAyB;AAChC,EAAA,IAAI;AACF,IAAA,MAAM,GAAA,GAAM,iBAAiB,QAAA,CAAS,eAAe,EAAE,gBAAA,CAAiB,gBAAgB,GAAG,IAAA,EAAK;AAChG,IAAA,IAAI,GAAA,EAAK,OAAO,UAAA,CAAW,GAAG,CAAA;AAAA,EAChC,CAAA,CAAA,MAAQ;AAAA,EAAC;AACT,EAAA,OAAO,IAAA;AACT;AAGA,IAAM,WAAA,GAAc,UAAA;AAKpB,SAAS,kBAAA,GAA8B;AACrC,EAAA,IAAI;AACF,IAAA,OAAO,QAAA,CAAS,eAAA,CAAgB,SAAA,CAAU,QAAA,CAAS,0BAA0B,CAAA;AAAA,EAC/E,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAgBA,SAAS,IAAA,CAAK,QAAgB,KAAA,EAAuB;AACnD,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAK,CAAC,CAAA,GAAI,GAAG,CAAA;AAC9D,EAAA,OAAO,CAAA,mBAAA,EAAsB,MAAM,CAAA,CAAA,EAAI,CAAA,CAAG,QAAQ,GAAA,GAAO,GAAA,EAAK,OAAA,CAAQ,CAAC,CAAC,CAAA,eAAA,CAAA;AAC1E;AAgBO,SAAS,WAAW,OAAA,EAAiC;AAC1D,EAAA,MAAM,CAAA,GAAI,WAAW,cAAA,EAAe;AACpC,EAAA,IAAI,oBAAmB,EAAG;AAQxB,IAAA,OAAO;AAAA,MACL,UAAA,EAAY,2BAAA;AAAA,MACZ,MAAA,EAAQ,0CAAA;AAAA,MACR,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AAIA,EAAA,MAAM,OAAA,GAAU,2BAAA;AAChB,EAAA,MAAM,GAAA,GAAM,+BAAA;AACZ,EAAA,IAAI,aAAY,EAAG;AAIjB,IAAA,OAAO;AAAA,MACL,YAAY,CAAA,gCAAA,EAAmC,IAAA,CAAK,SAAS,CAAA,GAAI,IAAI,CAAC,CAAA,KAAA,EAAQ,IAAA,CAAK,GAAA,EAAK,CAAA,GAAI,IAAI,CAAC,CAAA,MAAA,EAAS,KAAK,OAAA,EAAS,CAAA,GAAI,IAAI,CAAC,CAAA,MAAA,CAAA;AAAA,MACjI,cAAA,EAAgB,0BAAA;AAAA,MAChB,oBAAA,EAAsB,0BAAA;AAAA,MACtB,MAAA,EAAQ,oCAAA;AAAA,MACR,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,YAAY,CAAA,gCAAA,EAAmC,IAAA,CAAK,SAAS,CAAA,GAAI,IAAI,CAAC,CAAA,KAAA,EAAQ,IAAA,CAAK,GAAA,EAAK,CAAA,GAAI,IAAI,CAAC,CAAA,MAAA,EAAS,KAAK,OAAA,EAAS,CAAA,GAAI,IAAI,CAAC,CAAA,MAAA,CAAA;AAAA,IACjI,cAAA,EAAgB,0BAAA;AAAA,IAChB,oBAAA,EAAsB,0BAAA;AAAA,IACtB,MAAA,EAAQ,oCAAA;AAAA,IACR,SAAA,EAAW;AAAA,GACb;AACF;AAoBO,SAAS,UAAU,OAAA,EAA0B;AAClD,EAAA,IAAI,kBAAA,IAAsB,OAAO,2BAAA;AACjC,EAAA,OAAO,IAAA,CAAK,2BAAA,EAAA,CAA8B,OAAA,IAAW,cAAA,MAAoB,IAAI,CAAA;AAC/E;AAGO,IAAM,aAAA,GAAgB;AAKtB,IAAM,cAAA,GAAiB","file":"chunk-6XJEJWNJ.js","sourcesContent":["import type { CSSProperties } from 'react';\nimport { rootIsDark } from './rootTheme';\n\n/** Read the system menu opacity from CSS custom property set by Layout */\nfunction getMenuOpacity(): number {\n try {\n const val = getComputedStyle(document.documentElement).getPropertyValue('--menu-opacity')?.trim();\n if (val) return parseFloat(val);\n } catch {}\n return 0.95;\n}\n\n// `data-theme=\"dark\"` or a `dark` class on <html>, as ui.css reads it.\nconst isDarkTheme = rootIsDark;\n\n/** Whether the \"Reduce transparency\" preference is active (root class set by\n * Layout). When on, glass surfaces render solid + blur-free — the blur is the\n * GPU-expensive part, and dropping it is the point of the setting. */\nfunction reduceTransparency(): boolean {\n try {\n return document.documentElement.classList.contains('rosh-reduce-transparency');\n } catch {\n return false;\n }\n}\n\n/**\n * `colour` at `alpha` (0–1) of its own opacity — what `rgba(r,g,b,alpha)` was,\n * for a colour that is a token rather than three channels. `rgba()` cannot take\n * a variable for its channels; `color-mix()` with `transparent` can, and in\n * sRGB it is exactly that colour at that alpha (the mix is premultiplied, so\n * the channels come back unchanged).\n *\n * The alpha is rounded to a 255th first. An `rgba()` is a legacy colour, which\n * the engine stores with an 8-bit alpha; a `color-mix()` result keeps a float\n * one, and across a gradient the two land a rounding step apart on a few\n * percent of pixels. Rounding here puts the stops where the `rgba()` ones were,\n * and the gradient is pixel-identical to the one this replaced — measured in\n * Chromium against the previous release's output, light and dark.\n */\nfunction tint(colour: string, alpha: number): string {\n const steps = Math.round(Math.min(1, Math.max(0, alpha)) * 255);\n return `color-mix(in srgb, ${colour} ${+((steps / 255) * 100).toFixed(4)}%, transparent)`;\n}\n\n/** Frosted glass style — shared across all menus, popups, and glass UI elements.\n * Reads --menu-opacity CSS variable set by the theme system, and adapts the\n * base tint to dark mode so menus don't stay light-cream when text is light.\n *\n * Every colour is a token from ui.css (\"Kit colours\" there), so a host can\n * restyle the popups without forking this: the surface they are tinted from\n * (`--rosh-glass-surface`, which reads `--surface`), the stop across the middle,\n * the edge and the depth. Each token's default is the literal this function\n * used to write, in both themes. The numbers stay here — the alphas follow\n * `--menu-opacity`, which is read per call, and the blur differs by theme.\n *\n * To make every popup SOLID in the host's own surface colour, put\n * `rosh-reduce-transparency` on <html>: the branch below then paints one opaque\n * `--rosh-glass-surface`, and the stylesheet drops every backdrop blur. */\nexport function glassStyle(opacity?: number): CSSProperties {\n const o = opacity ?? getMenuOpacity();\n if (reduceTransparency()) {\n // Reduce-transparency: a fully opaque, blur-free surface. No\n // backdrop-filter (the expensive part on low-end GPUs) and a solid\n // background so menus/popups stay legible over any wallpaper. The global\n // stylesheet rule also strips backdrop-filter, but returning a solid\n // background here is what keeps the surface from reading as washed-out\n // translucent glass with the blur gone. One branch for both themes: the\n // tokens carry the dark values themselves.\n return {\n background: 'var(--rosh-glass-surface)',\n border: '1px solid var(--rosh-glass-solid-border)',\n boxShadow: 'var(--rosh-glass-solid-shadow)',\n };\n }\n // `in srgb` on both gradients: once any stop is a non-legacy colour — and a\n // `color-mix()` result is one — a gradient interpolates in Oklab by default,\n // where the `rgba()` stops it replaced were interpolated in sRGB.\n const surface = 'var(--rosh-glass-surface)';\n const mid = 'var(--rosh-glass-surface-mid)';\n if (isDarkTheme()) {\n // Dark frosted glass — the dark `--surface` (Catppuccin's #1e1e2e) with\n // `--surface-sunken` across the middle, a subtle gradient and a lighter\n // inner highlight.\n return {\n background: `linear-gradient(135deg in srgb, ${tint(surface, o * 0.85)} 0%, ${tint(mid, o * 0.75)} 50%, ${tint(surface, o * 0.85)} 100%)`,\n backdropFilter: 'blur(40px) saturate(1.6)',\n WebkitBackdropFilter: 'blur(40px) saturate(1.6)',\n border: '1px solid var(--rosh-glass-border)',\n boxShadow: 'var(--rosh-glass-shadow)',\n };\n }\n return {\n background: `linear-gradient(135deg in srgb, ${tint(surface, o * 0.85)} 0%, ${tint(mid, o * 0.65)} 50%, ${tint(surface, o * 0.75)} 100%)`,\n backdropFilter: 'blur(40px) saturate(1.8)',\n WebkitBackdropFilter: 'blur(40px) saturate(1.8)',\n border: '1px solid var(--rosh-glass-border)',\n boxShadow: 'var(--rosh-glass-shadow)',\n };\n}\n\n/**\n * The same glass as ONE flat colour, for a piece too small to be a surface of\n * its own: `Tooltip`'s arrow.\n *\n * Under `rosh-reduce-transparency` it is exactly what `glassStyle()` paints,\n * one opaque `--rosh-glass-surface`, so an arrow on a solid bubble is the\n * bubble's own colour and the join is exact.\n *\n * Frosted, `glassStyle()` is a gradient of that surface at three alphas over a\n * 40px backdrop blur, and neither half suits a 6px triangle. A gradient\n * repeated across a 10px box is not the bubble's gradient at the spot the\n * arrow touches, just a smaller copy of all of it. And a backdrop blur of its\n * own is a second full blur pass (the expensive part, per the branch above)\n * to frost a few pixels a reader sees for a moment. So it is the surface at\n * the alpha the gradient STARTS from, `o × 0.85`: the bubble's most opaque\n * stop, so the arrow never reads as a hole cut in it, still following\n * `--menu-opacity` and the theme as the bubble does.\n */\nexport function glassFill(opacity?: number): string {\n if (reduceTransparency()) return 'var(--rosh-glass-surface)';\n return tint('var(--rosh-glass-surface)', (opacity ?? getMenuOpacity()) * 0.85);\n}\n\n/** Glass divider border color */\nexport const GLASS_DIVIDER = 'border-white/20';\n\n/** Glass input/search bar background — declared in styles.css so it can adapt\n * to dark mode (a flat `bg-white/15` reads as a too-bright tile on the dark\n * glass gradient). */\nexport const GLASS_INPUT_BG = 'glass-input-bg';\n"]}
|