feat(tahuantinsuyu): fase 20 — accordion + lunar shift + CompositeModule + 90 ciudades
Cuatro features que cierran el set inicial de funcionalidades de
fase 1:
## D — Acordeón colapsable en el panel
Cuando hay 8 módulos en el panel se llenaba de cards. Ahora cada card
es expandible/colapsable por click en el header. Defaults:
- Natal siempre expanded
- Módulos con toggle "enabled" = true → expanded
- Resto → collapsed
El usuario puede forzar cualquiera vía override (collapse_overrides
HashMap). Chevron ▾/▸ a la izquierda del header. Hover sobre el
header lo resalta para invitar al click.
## B — Lunar return shift (navegación mensual)
PipelineRequest::PlanetaryReturn gana campo `shift_days: i64` (range
±180). El bridge lo suma a after_seconds del search anchor antes de
next_return. Para Solar return típicamente 0 (mantiene comportamiento).
Para Moon return, mover el slider ±28 días salta al retorno lunar
anterior o siguiente, permitiendo navegar mes a mes la lunación que
le toca al sujeto cumplido N años. PlanetaryReturnModule.controls()
agrega un slider "Shift días (lunar nav)". El badge del overlay
muestra "Moon return 38a +14d" cuando shift_days != 0. Helper
`planetary_return_request(body, age)` para callers que no necesitan
shift (zero default).
## C — CompositeModule
Carta compuesta (midpoint Davison) entre la natal del sujeto y otra
carta partner. Cada placement compuesto es el angular midpoint entre
los dos correspondientes. Engine: `PipelineRequest::Composite {
partner_chart: Box<Chart> }` + build_composite_overlay que llama
`eternal_astrology::composite()`. Renderiza placements en
`radii.composite = r * 0.32` (entre solar_arc 0.40 y aspects 0.24,
re-balanced). Módulo `composite::CompositeModule` con toggle +
ChartPicker (mismo patrón que synastry).
Shell: resolve_composite_partner reusa el fallback al primer hermano
del contacto, igual que synastry.
## A — 90 ciudades expandidas + dropdown scrollable
CITY_PRESETS pasa de 25 a 90 ciudades cubriendo:
- Latinoamérica (35): todas las capitales + grandes ciudades de AR/
VE/CO/PE/CL/EC/UY/PY/BO/MX/CU/PR/CR/PA/SV/GT/HN/NI/DO/BR
- España (5) + Europa (20): Madrid/Barcelona/Sevilla/Valencia/Bilbao
+ London/Paris/Berlin/München/Roma/Milano/Amsterdam/Bruxelles/Wien/
Zürich/Lisboa/Dublin/Stockholm/Oslo/København/Helsinki/Warszawa/
Praha/Budapest/Athina/İstanbul/Moskva
- USA + Canadá (12): NY/LA/Chicago/Miami/Houston/SF/Seattle/Boston/
DC + Toronto/Montreal/Vancouver
- Asia (16): Tokyo/Beijing/Shanghai/HK/Singapore/Seoul/Bangkok/
Jakarta/Manila/Mumbai/Delhi/Bangalore/Karachi/Tehran/Dubai/Tel Aviv
- África (6): Cairo/Lagos/Nairobi/Johannesburg/Cape Town/Casablanca
- Oceanía (3): Sydney/Melbourne/Auckland
El popup del dropdown ahora es scrollable (h=360px, overflow_y_scroll)
con id estable para no perder scroll position entre re-renders.
cargo check verde, 8 tests engine + 1 test modules (8 módulos
aplicables a ChartKind::Natal) verdes.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -165,31 +165,112 @@ struct CityPreset {
|
||||
}
|
||||
|
||||
const CITY_PRESETS: &[CityPreset] = &[
|
||||
// Latinoamérica
|
||||
CityPreset { name: "Buenos Aires, AR", lat: -34.6037, lon: -58.3816, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Córdoba, AR", lat: -31.4201, lon: -64.1888, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Rosario, AR", lat: -32.9587, lon: -60.6930, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Mendoza, AR", lat: -32.8908, lon: -68.8272, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Caracas, VE", lat: 10.4806, lon: -66.9036, tz_offset_minutes: -240 },
|
||||
CityPreset { name: "Maracaibo, VE", lat: 10.6427, lon: -71.6125, tz_offset_minutes: -240 },
|
||||
CityPreset { name: "Valencia, VE", lat: 10.1620, lon: -68.0078, tz_offset_minutes: -240 },
|
||||
CityPreset { name: "Bogotá, CO", lat: 4.7110, lon: -74.0721, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Medellín, CO", lat: 6.2442, lon: -75.5812, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Cali, CO", lat: 3.4516, lon: -76.5320, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Lima, PE", lat: -12.0464, lon: -77.0428, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Cusco, PE", lat: -13.5319, lon: -71.9675, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Santiago, CL", lat: -33.4489, lon: -70.6693, tz_offset_minutes: -240 },
|
||||
CityPreset { name: "Valparaíso, CL", lat: -33.0472, lon: -71.6127, tz_offset_minutes: -240 },
|
||||
CityPreset { name: "Quito, EC", lat: -0.1807, lon: -78.4678, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Guayaquil, EC", lat: -2.1709, lon: -79.9224, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Montevideo, UY", lat: -34.9011, lon: -56.1645, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Asunción, PY", lat: -25.2637, lon: -57.5759, tz_offset_minutes: -240 },
|
||||
CityPreset { name: "La Paz, BO", lat: -16.4897, lon: -68.1193, tz_offset_minutes: -240 },
|
||||
CityPreset { name: "Ciudad de México", lat: 19.4326, lon: -99.1332, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "Guadalajara, MX", lat: 20.6597, lon: -103.3496, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "Monterrey, MX", lat: 25.6866, lon: -100.3161, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "Habana, CU", lat: 23.1136, lon: -82.3666, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "San Juan, PR", lat: 18.4655, lon: -66.1057, tz_offset_minutes: -240 },
|
||||
CityPreset { name: "San José, CR", lat: 9.9281, lon: -84.0907, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "Panamá, PA", lat: 8.9824, lon: -79.5199, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "San Salvador, SV", lat: 13.6929, lon: -89.2182, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "Guatemala, GT", lat: 14.6349, lon: -90.5069, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "Tegucigalpa, HN", lat: 14.0723, lon: -87.1921, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "Managua, NI", lat: 12.1149, lon: -86.2362, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "Santo Domingo, DO", lat: 18.4861, lon: -69.9312, tz_offset_minutes: -240 },
|
||||
CityPreset { name: "São Paulo, BR", lat: -23.5505, lon: -46.6333, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Rio de Janeiro, BR", lat: -22.9068, lon: -43.1729, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Brasília, BR", lat: -15.8267, lon: -47.9218, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Salvador, BR", lat: -12.9777, lon: -38.5016, tz_offset_minutes: -180 },
|
||||
// España
|
||||
CityPreset { name: "Madrid, ES", lat: 40.4168, lon: -3.7038, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Barcelona, ES", lat: 41.3851, lon: 2.1734, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Sevilla, ES", lat: 37.3891, lon: -5.9845, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Valencia, ES", lat: 39.4699, lon: -0.3763, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Bilbao, ES", lat: 43.2630, lon: -2.9350, tz_offset_minutes: 60 },
|
||||
// Europa
|
||||
CityPreset { name: "London, UK", lat: 51.5074, lon: -0.1278, tz_offset_minutes: 0 },
|
||||
CityPreset { name: "Paris, FR", lat: 48.8566, lon: 2.3522, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Berlin, DE", lat: 52.5200, lon: 13.4050, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "München, DE", lat: 48.1351, lon: 11.5820, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Roma, IT", lat: 41.9028, lon: 12.4964, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Milano, IT", lat: 45.4642, lon: 9.1900, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Amsterdam, NL", lat: 52.3676, lon: 4.9041, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Bruxelles, BE", lat: 50.8503, lon: 4.3517, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Wien, AT", lat: 48.2082, lon: 16.3738, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Zürich, CH", lat: 47.3769, lon: 8.5417, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Lisboa, PT", lat: 38.7223, lon: -9.1393, tz_offset_minutes: 0 },
|
||||
CityPreset { name: "Dublin, IE", lat: 53.3498, lon: -6.2603, tz_offset_minutes: 0 },
|
||||
CityPreset { name: "Stockholm, SE", lat: 59.3293, lon: 18.0686, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Oslo, NO", lat: 59.9139, lon: 10.7522, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "København, DK", lat: 55.6761, lon: 12.5683, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Helsinki, FI", lat: 60.1699, lon: 24.9384, tz_offset_minutes: 120 },
|
||||
CityPreset { name: "Warszawa, PL", lat: 52.2297, lon: 21.0122, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Praha, CZ", lat: 50.0755, lon: 14.4378, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Budapest, HU", lat: 47.4979, lon: 19.0402, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Athina, GR", lat: 37.9838, lon: 23.7275, tz_offset_minutes: 120 },
|
||||
CityPreset { name: "İstanbul, TR", lat: 41.0082, lon: 28.9784, tz_offset_minutes: 180 },
|
||||
CityPreset { name: "Moskva, RU", lat: 55.7558, lon: 37.6173, tz_offset_minutes: 180 },
|
||||
// USA + Canada
|
||||
CityPreset { name: "New York, US", lat: 40.7128, lon: -74.0060, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Los Angeles, US", lat: 34.0522, lon: -118.2437, tz_offset_minutes: -480 },
|
||||
CityPreset { name: "Chicago, US", lat: 41.8781, lon: -87.6298, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "São Paulo, BR", lat: -23.5505, lon: -46.6333, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Rio de Janeiro, BR", lat: -22.9068, lon: -43.1729, tz_offset_minutes: -180 },
|
||||
CityPreset { name: "Miami, US", lat: 25.7617, lon: -80.1918, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Houston, US", lat: 29.7604, lon: -95.3698, tz_offset_minutes: -360 },
|
||||
CityPreset { name: "San Francisco, US", lat: 37.7749, lon: -122.4194, tz_offset_minutes: -480 },
|
||||
CityPreset { name: "Seattle, US", lat: 47.6062, lon: -122.3321, tz_offset_minutes: -480 },
|
||||
CityPreset { name: "Boston, US", lat: 42.3601, lon: -71.0589, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Washington DC", lat: 38.9072, lon: -77.0369, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Toronto, CA", lat: 43.6532, lon: -79.3832, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Montreal, CA", lat: 45.5017, lon: -73.5673, tz_offset_minutes: -300 },
|
||||
CityPreset { name: "Vancouver, CA", lat: 49.2827, lon: -123.1207, tz_offset_minutes: -480 },
|
||||
// Asia
|
||||
CityPreset { name: "Tokyo, JP", lat: 35.6762, lon: 139.6503, tz_offset_minutes: 540 },
|
||||
CityPreset { name: "Sydney, AU", lat: -33.8688, lon: 151.2093, tz_offset_minutes: 600 },
|
||||
CityPreset { name: "Beijing, CN", lat: 39.9042, lon: 116.4074, tz_offset_minutes: 480 },
|
||||
CityPreset { name: "Shanghai, CN", lat: 31.2304, lon: 121.4737, tz_offset_minutes: 480 },
|
||||
CityPreset { name: "Hong Kong", lat: 22.3193, lon: 114.1694, tz_offset_minutes: 480 },
|
||||
CityPreset { name: "Singapore", lat: 1.3521, lon: 103.8198, tz_offset_minutes: 480 },
|
||||
CityPreset { name: "Seoul, KR", lat: 37.5665, lon: 126.9780, tz_offset_minutes: 540 },
|
||||
CityPreset { name: "Bangkok, TH", lat: 13.7563, lon: 100.5018, tz_offset_minutes: 420 },
|
||||
CityPreset { name: "Jakarta, ID", lat: -6.2088, lon: 106.8456, tz_offset_minutes: 420 },
|
||||
CityPreset { name: "Manila, PH", lat: 14.5995, lon: 120.9842, tz_offset_minutes: 480 },
|
||||
CityPreset { name: "Mumbai, IN", lat: 19.0760, lon: 72.8777, tz_offset_minutes: 330 },
|
||||
CityPreset { name: "Delhi, IN", lat: 28.7041, lon: 77.1025, tz_offset_minutes: 330 },
|
||||
CityPreset { name: "Bangalore, IN", lat: 12.9716, lon: 77.5946, tz_offset_minutes: 330 },
|
||||
CityPreset { name: "Karachi, PK", lat: 24.8607, lon: 67.0011, tz_offset_minutes: 300 },
|
||||
CityPreset { name: "Tehran, IR", lat: 35.6892, lon: 51.3890, tz_offset_minutes: 210 },
|
||||
CityPreset { name: "Dubai, AE", lat: 25.2048, lon: 55.2708, tz_offset_minutes: 240 },
|
||||
CityPreset { name: "Tel Aviv, IL", lat: 32.0853, lon: 34.7818, tz_offset_minutes: 120 },
|
||||
// África
|
||||
CityPreset { name: "Cairo, EG", lat: 30.0444, lon: 31.2357, tz_offset_minutes: 120 },
|
||||
CityPreset { name: "Lagos, NG", lat: 6.5244, lon: 3.3792, tz_offset_minutes: 60 },
|
||||
CityPreset { name: "Nairobi, KE", lat: -1.2921, lon: 36.8219, tz_offset_minutes: 180 },
|
||||
CityPreset { name: "Johannesburg, ZA", lat: -26.2041, lon: 28.0473, tz_offset_minutes: 120 },
|
||||
CityPreset { name: "Cape Town, ZA", lat: -33.9249, lon: 18.4241, tz_offset_minutes: 120 },
|
||||
CityPreset { name: "Casablanca, MA", lat: 33.5731, lon: -7.5898, tz_offset_minutes: 60 },
|
||||
// Oceanía
|
||||
CityPreset { name: "Sydney, AU", lat: -33.8688, lon: 151.2093, tz_offset_minutes: 600 },
|
||||
CityPreset { name: "Melbourne, AU", lat: -37.8136, lon: 144.9631, tz_offset_minutes: 600 },
|
||||
CityPreset { name: "Auckland, NZ", lat: -36.8485, lon: 174.7633, tz_offset_minutes: 720 },
|
||||
];
|
||||
|
||||
impl EventEmitter<TreeEvent> for TahuantinsuyuTree {}
|
||||
@@ -1253,19 +1334,22 @@ fn render_chart_form(
|
||||
.child(div().flex_grow())
|
||||
.child(city_btn);
|
||||
let title_row = if picker_open {
|
||||
let popup_id: SharedString = SharedString::from("tts-form-city-popup");
|
||||
let mut popup = div()
|
||||
.id(gpui::ElementId::from(popup_id))
|
||||
.absolute()
|
||||
.top(px(36.0))
|
||||
.right(px(0.0))
|
||||
.min_w(px(220.0))
|
||||
.max_h(px(320.0))
|
||||
.min_w(px(240.0))
|
||||
.h(px(360.0))
|
||||
.py(px(4.0))
|
||||
.bg(theme.bg_panel_alt.clone())
|
||||
.border_1()
|
||||
.border_color(theme.border_strong)
|
||||
.rounded(px(6.0))
|
||||
.flex()
|
||||
.flex_col();
|
||||
.flex_col()
|
||||
.overflow_y_scroll();
|
||||
for preset in CITY_PRESETS.iter().copied() {
|
||||
let row_id: SharedString =
|
||||
SharedString::from(format!("tts-city-{}", preset.name));
|
||||
|
||||
Reference in New Issue
Block a user