panchang-ts 2.0.1 → 2.1.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/README.md CHANGED
@@ -139,6 +139,37 @@ console.log(amanta.chandramasa.name); // Amanta month name
139
139
  console.log(amanta.chandramasa.system); // "amanta"
140
140
  ```
141
141
 
142
+ ### Regional Festival Filtering
143
+
144
+ The `region` option scopes regional festival variants to one Indian state.
145
+ Pan-Indian festivals (Diwali, Holi, Raksha Bandhan, the canonical
146
+ `sankranti` event, …) emit regardless.
147
+
148
+ ```typescript
149
+ // Default — every regional variant emits on Makar Sankranti day:
150
+ const all = getDailyPanchang(jan14, chennai, { timezone: 330 });
151
+ all.festivals.map(f => f.name);
152
+ // → ["Sankranti", "Makar Sankranti", "Pongal", "Uttarayan",
153
+ // "Magh Bihu", "Ayyappa Makara Jyothi"]
154
+
155
+ // Scope to Tamil Nadu — drops Bihu/Ayyappa/Uttarayan:
156
+ const tn = getDailyPanchang(jan14, chennai, { timezone: 330, region: 'tamil-nadu' });
157
+ tn.festivals.map(f => f.name);
158
+ // → ["Sankranti", "Makar Sankranti", "Pongal"]
159
+
160
+ // Lohri fires on the Hindu day BEFORE Makara transit, scoped to Punjab/
161
+ // Haryana/Himachal — no extra wiring required, just the region option:
162
+ const lohri = getDailyPanchang(jan13, amritsar, { timezone: 330, region: 'punjab' });
163
+ lohri.festivals.some(f => f.name === 'Lohri'); // true
164
+
165
+ // Pre-v2.1 region values still work but log a one-shot deprecation warning:
166
+ getDailyPanchang(date, loc, { timezone: 330, region: 'tamil' });
167
+ // console.warn: [panchang-ts] FestivalRegion 'tamil' is deprecated;
168
+ // use 'tamil-nadu'. Legacy value will be removed in v3.
169
+ ```
170
+
171
+ See [`FestivalRegion`](#types) for the full state-slug list (21 states + `'nepal'`).
172
+
142
173
  ---
143
174
 
144
175
  ## Features
@@ -158,12 +189,13 @@ Rahu Kalam, Gulika Kalam, Yamaganda, Panchaka detection, Bhadra Kala (Vishti kar
158
189
  ### Special Yogas & Festivals
159
190
  Amrit Siddhi, Sarvartha Siddhi, Ravi Pushya, Guru Pushya yoga detection.
160
191
 
161
- **60+ festivals** spanning pan-Indian, regional, and classical observances:
192
+ **80+ festivals** spanning pan-Indian, regional, and classical observances:
162
193
 
163
194
  - **Ekadashi** — 26 named variants (Putrada, Shat Tila, Nirjala, Devshayani, etc.) with **Smarta / Vaishnava split** via Dashami-viddha rule; Smarta fast emits a `deferralDate` for Dwadashi.
164
195
  - **Pradosha** — 7 weekday-qualified variants (Som Pradosh, Bhauma Pradosh, Shani Pradosh, etc.) firing on both Shukla & Krishna paksha.
165
- - **Sankranti** — transit-based solar-month boundary detection plus regional variants (**Pongal**, **Vishu**, **Baisakhi**, **Magh Bihu**, **Ayyappa Makara Jyothi**) scoped by the `region` option.
196
+ - **Sankranti** — transit-based solar-month boundary detection plus regional variants (**Pongal**, **Vishu**, **Baisakhi**, **Pohela Boishakh**, **Bohag Bihu**, **Magh Bihu**, **Kati Bihu**, **Uttarayan**, **Ayyappa Makara Jyothi**, **Raja Sankranti**, **Harela**, **Sair**, **Singh Sankranti**) scoped by the `region` option. **Lohri** fires on the Hindu day immediately preceding Makara Sankranti under Punjab/Haryana/Himachal scopes.
166
197
  - **Canonical-time classical festivals** — Ganesh Chaturthi (madhyahna), Shivaratri (nishita), Diwali, Holi, Raksha Bandhan (Bhadra-aware, suppressed when Bhadra straddles Purnima), Karva Chauth (chandrodaya), Janmashtami, Dussehra, Navaratri, Ram Navami, Hanuman Jayanti, **Akshaya Tritiya & Parashurama Jayanti** (madhyahna-vyapini, co-emitted on Vaishakha Shukla Tritiya), Makar Sankranti.
198
+ - **Regional festivals (v2.1)** — **Gudi Padwa** (Maharashtra/Goa), **Gangaur** (Rajasthan), **Karaga** (Karnataka), **Bonalu** (Telangana, recurring Sundays in Ashadha), **Varamahalakshmi** (last Friday of Shravana Shukla before Purnima, Karnataka/AP/Telangana/Tamil Nadu), **Bathukamma** (Telangana — Engili Pula + Saddula markers), **Hariyali / Kajari / Hartalika Teej**, **Govardhan Puja**, **Bhai Dooj**, **Phagli** (Himachal), **Jagannath Rath Yatra** (pan-Indian, Ashadha Shukla Dwitiya), **Raja Parba** 3-day arc (Odisha — Pahili / Sankranti / Basi) — all filtered by per-state allow-lists on the rule.
167
199
  - **Regional & seasonal** — Chhath (4-day sequence), Vat Savitri, Upakarma (3 shakha variants via nakshatra+chandraMasa), Onam (nakshatra+solarMasa).
168
200
  - **Monthly observances** — Masik Shivaratri, Vinayaka Chaturthi (suppressed in Maha-month), **Masik Karthigai** (any day Krittika nakshatra prevails — sampled at sunrise / midday / sunset / nishita), Pushya days, Shravan Somvar and other month+weekday patterns.
169
201
  - Adhika (leap) months auto-skipped for tithi-based rules; Purnimanta naming respected.
@@ -332,7 +364,7 @@ Both functions share the same core astronomy, but `getDailyPanchang` operates on
332
364
  | `computeEndTimes` | `boolean` | `true` | Set `false` for ~5x faster, names-only output |
333
365
  | `precision` | `'standard' \| 'high'` | `'standard'` | Binary-search iterations (15 vs 25). High precision is rarely needed. |
334
366
  | `masaSystem` | `'purnimanta' \| 'amanta'` | `'purnimanta'` | Lunar month naming system. Purnimanta (North Indian) or Amanta (South Indian). |
335
- | `region` | `FestivalRegion` | `'all'` | Scopes regional festival variants (Pongal, Vishu, Baisakhi, Bihu, Ayyappa, etc.). See [`FestivalRegion`](#types) for supported values. The canonical pan-Indian `sankranti` event is always emitted regardless. |
367
+ | `region` | `FestivalRegion` | `'all'` | Scopes regional festival variants (Pongal, Vishu, Gudi Padwa, Lohri, Govardhan Puja, Bonalu, …) to a specific Indian state. See [`FestivalRegion`](#types) for the full list. Pre-v2.1 values (`'tamil'`, `'bengal'`, `'north-india'`) are still accepted but emit a deprecation warning; removal in v3. Pan-Indian festivals and the canonical `sankranti` event emit regardless of this setting. |
336
368
  | `janmaRashi` | `number` | _(omitted)_ | Native's birth Moon rashi index (0 = Mesha … 11 = Meena). When provided, the result includes `chandraBalam`. |
337
369
 
338
370
  **`InstantPanchangOptions`** (optional for `getInstantPanchang`): same as above but without `timezone` (instant mode works in UTC).
@@ -582,17 +614,56 @@ interface FestivalInfo {
582
614
  deferralDate?: Date;
583
615
  }
584
616
 
617
+ // State-slug scheme. A caller sets `region` to limit regional variants to
618
+ // their state; pan-Indian festivals (Holi, Diwali, Sankranti itself, …)
619
+ // emit regardless.
585
620
  type FestivalRegion =
586
- | 'all' // default — emits every regional variant
587
- | 'north-india'
588
- | 'tamil'
589
- | 'kerala'
590
- | 'bengal'
591
- | 'punjab'
592
- | 'gujarat'
593
- | 'assam'
594
- | 'maharashtra';
621
+ | 'all' // default — emits every regional variant
622
+ // South
623
+ | 'tamil-nadu' | 'kerala' | 'karnataka' | 'andhra-pradesh' | 'telangana'
624
+ // East
625
+ | 'west-bengal' | 'odisha' | 'assam' | 'bihar' | 'jharkhand'
626
+ // West
627
+ | 'gujarat' | 'maharashtra' | 'goa' | 'rajasthan'
628
+ // North / Central
629
+ | 'punjab' | 'haryana' | 'himachal-pradesh' | 'uttarakhand'
630
+ | 'uttar-pradesh' | 'madhya-pradesh'
631
+ // Neighbour
632
+ | 'nepal';
633
+
634
+ // Pre-v2.1 identifiers. Accepted as input and mapped at call time; a
635
+ // one-shot console warning fires per distinct legacy value. Removal in v3.
636
+ // 'tamil' → 'tamil-nadu'
637
+ // 'bengal' → 'west-bengal'
638
+ // 'north-india' → 'all' (Makar Sankranti is pan-Indian; use state
639
+ // slugs for Lohri / Govardhan / Bhai Dooj)
640
+ type LegacyFestivalRegion = 'tamil' | 'bengal' | 'north-india';
595
641
  ```
642
+
643
+ **Region-scoped festivals** (non-exhaustive — see `src/core/festivals.ts`):
644
+
645
+ | Region | Festival names (keys) |
646
+ |---|---|
647
+ | `tamil-nadu` | pongal, puthandu, varamahalakshmi |
648
+ | `kerala` | vishu, ayyappa_makara_jyothi, onam *(solar-nakshatra)* |
649
+ | `karnataka` | karaga, varamahalakshmi |
650
+ | `andhra-pradesh` | varamahalakshmi |
651
+ | `telangana` | bonalu, varamahalakshmi, bathukamma_start, bathukamma_saddula |
652
+ | `west-bengal` | pohela_boishakh, bhai_dooj |
653
+ | `odisha` | singh_sankranti, raja_pahili, raja_sankranti, raja_basi |
654
+ | `assam` | bohag_bihu, magh_bihu, kati_bihu |
655
+ | `bihar` | singh_sankranti, hariyali_teej, govardhan_puja, bhai_dooj |
656
+ | `gujarat` | uttarayan, govardhan_puja, bhai_dooj |
657
+ | `maharashtra` | gudi_padwa, hartalika_teej, bhai_dooj |
658
+ | `goa` | gudi_padwa |
659
+ | `rajasthan` | gangaur, hariyali_teej, kajari_teej, hartalika_teej, govardhan_puja, bhai_dooj |
660
+ | `punjab` | baisakhi, lohri, govardhan_puja |
661
+ | `haryana` | baisakhi, lohri, govardhan_puja, bhai_dooj |
662
+ | `himachal-pradesh` | sair, phagli, lohri |
663
+ | `uttarakhand` | harela |
664
+ | `uttar-pradesh` | hariyali_teej, kajari_teej, hartalika_teej, govardhan_puja, bhai_dooj |
665
+ | `madhya-pradesh` | hariyali_teej, kajari_teej, hartalika_teej |
666
+ | `nepal` | singh_sankranti, bhai_dooj |
596
667
  </details>
597
668
 
598
669
  <details>
package/dist/index.cjs CHANGED
@@ -3756,28 +3756,47 @@ function computeDurMuhurta(sunrise, sunset, varaIndex) {
3756
3756
  var SANKRANTI_REGIONAL = {
3757
3757
  // Mesha (0) — solar new year across regions
3758
3758
  0: [
3759
- { key: "baisakhi", region: "punjab", type: "major" },
3760
- { key: "vishu", region: "kerala", type: "major" },
3761
- { key: "pohela_boishakh", region: "bengal", type: "major" },
3762
- { key: "puthandu", region: "tamil", type: "major" }
3759
+ { key: "baisakhi", regions: ["punjab", "haryana"], type: "major" },
3760
+ { key: "vishu", regions: ["kerala"], type: "major" },
3761
+ { key: "pohela_boishakh", regions: ["west-bengal"], type: "major" },
3762
+ { key: "puthandu", regions: ["tamil-nadu"], type: "major" },
3763
+ { key: "bohag_bihu", regions: ["assam"], type: "major" }
3763
3764
  ],
3764
3765
  // Karka (3) — Dakshinayana (Sun's southward course begins)
3765
3766
  3: [
3766
- { key: "dakshinayana", region: "all", type: "minor" }
3767
+ { key: "dakshinayana", regions: ["all"], type: "minor" },
3768
+ // Raja Parba (Odisha) — 4-day monsoon festival; we emit a single-day
3769
+ // marker on Karka Sankranti, the most widely cited anchor day.
3770
+ { key: "raja_sankranti", regions: ["odisha"], type: "major" },
3771
+ // Harela (Kumaon / Uttarakhand) — observed on Shravana solar-month start.
3772
+ { key: "harela", regions: ["uttarakhand"], type: "major" }
3767
3773
  ],
3768
- // Simha (4)
3774
+ // Simha (4) — Singh Sankranti is primarily observed in Odisha, Bihar,
3775
+ // and Nepal (as Singhasankranti); not a pan-Indian observance despite
3776
+ // the pre-v2.1 tagging.
3769
3777
  4: [
3770
- { key: "singh_sankranti", region: "all", type: "minor" }
3778
+ { key: "singh_sankranti", regions: ["odisha", "bihar", "jharkhand", "nepal"], type: "minor" }
3779
+ ],
3780
+ // Kanya (5) — Sair (Himachal): first day of the Ashwin solar month.
3781
+ 5: [
3782
+ { key: "sair", regions: ["himachal-pradesh"], type: "minor" }
3783
+ ],
3784
+ // Tula (6) — Kati Bihu (Assam): Kartika solar-month start.
3785
+ 6: [
3786
+ { key: "kati_bihu", regions: ["assam"], type: "minor" }
3771
3787
  ],
3772
3788
  // Makara (9) — Uttarayana / harvest festivals
3773
3789
  9: [
3774
- { key: "makar_sankranti", region: "north-india", type: "major" },
3775
- { key: "pongal", region: "tamil", type: "major" },
3776
- { key: "uttarayan", region: "gujarat", type: "major" },
3777
- { key: "bihu", region: "assam", type: "major" },
3778
- { key: "ayyappa_makara_jyothi", region: "kerala", type: "major" }
3790
+ // Makar Sankranti is pan-Indian (re-scoped from the pre-v2.1 'north-india').
3791
+ { key: "makar_sankranti", regions: ["all"], type: "major" },
3792
+ { key: "pongal", regions: ["tamil-nadu"], type: "major" },
3793
+ { key: "uttarayan", regions: ["gujarat"], type: "major" },
3794
+ { key: "magh_bihu", regions: ["assam"], type: "major" },
3795
+ { key: "ayyappa_makara_jyothi", regions: ["kerala"], type: "major" }
3779
3796
  ]
3780
3797
  };
3798
+ var LOHRI_REGIONS = ["punjab", "haryana", "himachal-pradesh"];
3799
+ var RAJA_REGIONS = ["odisha"];
3781
3800
  var FESTIVAL_REGISTRY = [
3782
3801
  // Chaitra (0)
3783
3802
  { key: "ugadi", masa: 0, tithi: 0, type: "major" },
@@ -3851,7 +3870,144 @@ var FESTIVAL_REGISTRY = [
3851
3870
  // Rig Upakarma — Shravana nakshatra (21) in Shravana chandra masa (4).
3852
3871
  { key: "rig_upakarma", masa: 4, nakshatra: 21, type: "major" },
3853
3872
  // Sama Upakarma — Hasta nakshatra (12) in Bhadrapada chandra masa (5).
3854
- { key: "sama_upakarma", masa: 5, nakshatra: 12, type: "major" }
3873
+ { key: "sama_upakarma", masa: 5, nakshatra: 12, type: "major" },
3874
+ // ── Regional festivals (v2.1 expansion) ─────────────────────
3875
+ // Chaitra (0) — Marathi/Konkani New Year; same tithi as Ugadi but
3876
+ // emitted as a Maharashtra-specific variant name alongside Ugadi.
3877
+ {
3878
+ key: "gudi_padwa",
3879
+ masa: 0,
3880
+ tithi: 0,
3881
+ type: "major",
3882
+ regions: ["maharashtra", "goa"]
3883
+ },
3884
+ // Chaitra (0) Shukla Tritiya — Gangaur (18-day festival concludes here).
3885
+ {
3886
+ key: "gangaur",
3887
+ masa: 0,
3888
+ tithi: 2,
3889
+ type: "major",
3890
+ regions: ["rajasthan"]
3891
+ },
3892
+ // Chaitra (0) Purnima — Karaga festival of Bengaluru.
3893
+ {
3894
+ key: "karaga",
3895
+ masa: 0,
3896
+ tithi: 14,
3897
+ type: "major",
3898
+ regions: ["karnataka"]
3899
+ },
3900
+ // Ashadha (3) — Bonalu, Sundays at Mahakali temples across Telangana.
3901
+ {
3902
+ key: "bonalu",
3903
+ masa: 3,
3904
+ vara: 0,
3905
+ type: "minor",
3906
+ adhikaBehaviour: "observe-in-both",
3907
+ regions: ["telangana"]
3908
+ },
3909
+ // Shravana (4) Shukla Tritiya — Hariyali Teej.
3910
+ {
3911
+ key: "hariyali_teej",
3912
+ masa: 4,
3913
+ tithi: 2,
3914
+ type: "major",
3915
+ regions: ["rajasthan", "uttar-pradesh", "bihar", "haryana", "madhya-pradesh"]
3916
+ },
3917
+ // Shravana (4) Krishna Tritiya — Kajari Teej (tithi 17 = Krishna Tritiya).
3918
+ {
3919
+ key: "kajari_teej",
3920
+ masa: 4,
3921
+ tithi: 17,
3922
+ type: "major",
3923
+ regions: ["rajasthan", "uttar-pradesh", "madhya-pradesh"]
3924
+ },
3925
+ // Bhadrapada (5) Shukla Tritiya — Hartalika Teej.
3926
+ {
3927
+ key: "hartalika_teej",
3928
+ masa: 5,
3929
+ tithi: 2,
3930
+ type: "major",
3931
+ regions: ["rajasthan", "uttar-pradesh", "bihar", "maharashtra", "madhya-pradesh"]
3932
+ },
3933
+ // Amanta Kartika (7) Shukla Pratipada — day after Diwali.
3934
+ // In Purnimanta convention this is also "Kartika Shukla Pratipada" (naming
3935
+ // system aligns), so a namingSystem tag isn't required here.
3936
+ {
3937
+ key: "govardhan_puja",
3938
+ masa: 7,
3939
+ tithi: 0,
3940
+ type: "major",
3941
+ regions: [
3942
+ "uttar-pradesh",
3943
+ "bihar",
3944
+ "haryana",
3945
+ "rajasthan",
3946
+ "gujarat",
3947
+ "madhya-pradesh",
3948
+ "punjab",
3949
+ "jharkhand"
3950
+ ]
3951
+ },
3952
+ // Amanta Kartika (7) Shukla Dwitiya — Bhai Dooj.
3953
+ {
3954
+ key: "bhai_dooj",
3955
+ masa: 7,
3956
+ tithi: 1,
3957
+ type: "major",
3958
+ regions: [
3959
+ "uttar-pradesh",
3960
+ "bihar",
3961
+ "haryana",
3962
+ "maharashtra",
3963
+ "gujarat",
3964
+ "rajasthan",
3965
+ "madhya-pradesh",
3966
+ "west-bengal",
3967
+ "jharkhand",
3968
+ "nepal"
3969
+ ]
3970
+ },
3971
+ // Phalguna (11) Purnima — Phagli (varies by valley; Purnima anchor).
3972
+ {
3973
+ key: "phagli",
3974
+ masa: 11,
3975
+ tithi: 14,
3976
+ type: "minor",
3977
+ regions: ["himachal-pradesh"]
3978
+ },
3979
+ // Ashadha (3) Shukla Dwitiya — Jagannath Rath Yatra (pan-Indian; cultural
3980
+ // epicenter is Puri, Odisha but observed nationwide).
3981
+ { key: "jagannath_rath_yatra", masa: 3, tithi: 1, type: "major" },
3982
+ // Shravana (4) Shukla — Varamahalakshmi: last Friday in Shukla paksha
3983
+ // before Purnima. The (masa+vara) match is gated by tithi ∈ [7,13] so
3984
+ // only the second Friday of the paksha (the one closest to Purnima) fires.
3985
+ {
3986
+ key: "varamahalakshmi",
3987
+ masa: 4,
3988
+ vara: 5,
3989
+ type: "major",
3990
+ tithiRange: [7, 13],
3991
+ regions: ["karnataka", "andhra-pradesh", "telangana", "tamil-nadu"]
3992
+ },
3993
+ // Bathukamma (Telangana) — 9-day floral festival from Bhadrapada
3994
+ // Amavasya through Ashwin Shukla Navami. We emit start (Engili Pula
3995
+ // Bathukamma, masa=5/tithi=29) and climax (Saddula Bathukamma, masa=6/
3996
+ // tithi=8) markers; intermediate days carry no library-level emission.
3997
+ {
3998
+ key: "bathukamma_start",
3999
+ masa: 5,
4000
+ tithi: 29,
4001
+ type: "major",
4002
+ regions: ["telangana"]
4003
+ },
4004
+ {
4005
+ key: "bathukamma_saddula",
4006
+ masa: 6,
4007
+ tithi: 8,
4008
+ type: "major",
4009
+ regions: ["telangana"]
4010
+ }
3855
4011
  ];
3856
4012
  var EKADASHI_NAMES = [
3857
4013
  ["kamada", "papamochani"],
@@ -3928,7 +4084,14 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
3928
4084
  match = masaMatches && rule.nakshatra === ctx.nakshatraIndex;
3929
4085
  } else if (rule.vara !== void 0 && rule.masa !== void 0) {
3930
4086
  const masaMatches = rule.masa === ctx.chandraMasaIndex && (adhikaBehaviour !== "shift-to-nija" || !ctx.isAdhika);
3931
- match = masaMatches && rule.vara === ctx.varaIndex;
4087
+ let inTithiRange = true;
4088
+ if (rule.tithiRange !== void 0) {
4089
+ const dateRule = rule.dateRule ?? "sunrise";
4090
+ const tithi = tithiForRule(dateRule);
4091
+ const [lo, hi2] = rule.tithiRange;
4092
+ inTithiRange = tithi >= lo && tithi <= hi2;
4093
+ }
4094
+ match = masaMatches && rule.vara === ctx.varaIndex && inTithiRange;
3932
4095
  } else if (rule.masa !== void 0 && rule.tithi !== void 0) {
3933
4096
  const masaMatches = rule.masa === ctx.chandraMasaIndex && // `shift-to-nija`: only observe in Nija following an Adhika (but still OK if no prior Adhika,
3934
4097
  // since the normal year has no Adhika and the festival observes as usual).
@@ -3948,6 +4111,12 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
3948
4111
  }
3949
4112
  }
3950
4113
  if (!match) continue;
4114
+ if (rule.regions !== void 0) {
4115
+ const region2 = ctx.region ?? "all";
4116
+ if (region2 !== "all" && !rule.regions.includes("all") && !rule.regions.includes(region2)) {
4117
+ continue;
4118
+ }
4119
+ }
3951
4120
  const festival = { name: nameResolver(rule.key), type: rule.type };
3952
4121
  if (rule.namingSystem === "purnimanta" && ctx.purnimantaMasaName && ctx.amantaMasaName) {
3953
4122
  festival.description = `Purnimanta: ${ctx.purnimantaMasaName} Krishna Paksha`;
@@ -4052,6 +4221,7 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
4052
4221
  description: nameResolver(variantKey)
4053
4222
  });
4054
4223
  }
4224
+ const region = ctx.region ?? "all";
4055
4225
  if (ctx.sankrantiRashi !== void 0 && ctx.sankrantiRashi !== null) {
4056
4226
  const rashiName = rashiNameResolver ? rashiNameResolver(ctx.sankrantiRashi) : `Rashi ${ctx.sankrantiRashi}`;
4057
4227
  results.push({
@@ -4059,11 +4229,10 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
4059
4229
  type: "sankranti",
4060
4230
  description: rashiName
4061
4231
  });
4062
- const region = ctx.region ?? "all";
4063
4232
  const regionalRules = SANKRANTI_REGIONAL[ctx.sankrantiRashi];
4064
4233
  if (regionalRules) {
4065
4234
  for (const r of regionalRules) {
4066
- if (region !== "all" && r.region !== "all" && r.region !== region) continue;
4235
+ if (region !== "all" && !r.regions.includes("all") && !r.regions.includes(region)) continue;
4067
4236
  results.push({
4068
4237
  name: nameResolver(r.key),
4069
4238
  type: "sankranti",
@@ -4072,9 +4241,47 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
4072
4241
  }
4073
4242
  }
4074
4243
  }
4244
+ if (ctx.nextDaySankrantiRashi === 9) {
4245
+ if (region === "all" || LOHRI_REGIONS.includes(region)) {
4246
+ results.push({ name: nameResolver("lohri"), type: "major" });
4247
+ }
4248
+ }
4249
+ if (ctx.nextDaySankrantiRashi === 3) {
4250
+ if (region === "all" || RAJA_REGIONS.includes(region)) {
4251
+ results.push({ name: nameResolver("raja_pahili"), type: "major" });
4252
+ }
4253
+ }
4254
+ if (ctx.prevDaySankrantiRashi === 3) {
4255
+ if (region === "all" || RAJA_REGIONS.includes(region)) {
4256
+ results.push({ name: nameResolver("raja_basi"), type: "major" });
4257
+ }
4258
+ }
4075
4259
  return results;
4076
4260
  }
4077
4261
 
4262
+ // src/core/regionAlias.ts
4263
+ var LEGACY_REGION_ALIASES = {
4264
+ "tamil": "tamil-nadu",
4265
+ "bengal": "west-bengal",
4266
+ "north-india": "all"
4267
+ };
4268
+ var warned = /* @__PURE__ */ new Set();
4269
+ function resolveRegionAlias(region) {
4270
+ if (region === void 0) return "all";
4271
+ if (region in LEGACY_REGION_ALIASES) {
4272
+ const legacy = region;
4273
+ const canonical = LEGACY_REGION_ALIASES[legacy];
4274
+ if (!warned.has(legacy)) {
4275
+ warned.add(legacy);
4276
+ console.warn(
4277
+ `[panchang-ts] FestivalRegion '${legacy}' is deprecated; use '${canonical}'. Legacy value will be removed in v3.`
4278
+ );
4279
+ }
4280
+ return canonical;
4281
+ }
4282
+ return region;
4283
+ }
4284
+
4078
4285
  // src/core/bhadra.ts
4079
4286
  function isVishtiKarana(karanaIndex) {
4080
4287
  if (karanaIndex <= 0 || karanaIndex >= 57) return false;
@@ -4350,13 +4557,36 @@ var en = {
4350
4557
  vishu: "Vishu",
4351
4558
  pohela_boishakh: "Pohela Boishakh",
4352
4559
  puthandu: "Puthandu",
4560
+ bohag_bihu: "Bohag Bihu",
4353
4561
  makar_sankranti: "Makar Sankranti",
4354
4562
  pongal: "Pongal",
4355
4563
  uttarayan: "Uttarayan",
4356
- bihu: "Magh Bihu",
4564
+ magh_bihu: "Magh Bihu",
4357
4565
  ayyappa_makara_jyothi: "Ayyappa Makara Jyothi",
4358
4566
  dakshinayana: "Dakshinayana",
4567
+ raja_sankranti: "Raja Sankranti",
4568
+ raja_pahili: "Pahili Raja",
4569
+ raja_basi: "Basi Raja",
4570
+ harela: "Harela",
4359
4571
  singh_sankranti: "Singh Sankranti",
4572
+ sair: "Sair",
4573
+ kati_bihu: "Kati Bihu",
4574
+ lohri: "Lohri",
4575
+ // Regional festivals (v2.1 expansion)
4576
+ gudi_padwa: "Gudi Padwa",
4577
+ gangaur: "Gangaur",
4578
+ karaga: "Karaga",
4579
+ bonalu: "Bonalu",
4580
+ hariyali_teej: "Hariyali Teej",
4581
+ kajari_teej: "Kajari Teej",
4582
+ hartalika_teej: "Hartalika Teej",
4583
+ govardhan_puja: "Govardhan Puja",
4584
+ bhai_dooj: "Bhai Dooj",
4585
+ phagli: "Phagli",
4586
+ jagannath_rath_yatra: "Jagannath Rath Yatra",
4587
+ varamahalakshmi: "Varamahalakshmi Vratam",
4588
+ bathukamma_start: "Bathukamma \u2014 Engili Pula",
4589
+ bathukamma_saddula: "Bathukamma \u2014 Saddula",
4360
4590
  // Chhath Puja (4-day, Kartika Shukla Chaturthi→Saptami)
4361
4591
  chhath_nahay_khay: "Chhath \u2014 Nahay Khay",
4362
4592
  chhath_kharna: "Chhath \u2014 Kharna",
@@ -4592,13 +4822,36 @@ var hi = {
4592
4822
  vishu: "\u0935\u093F\u0937\u0941",
4593
4823
  pohela_boishakh: "\u092A\u094B\u0939\u0947\u0932\u093E \u092C\u094B\u0907\u0936\u093E\u0916",
4594
4824
  puthandu: "\u092A\u0941\u0925\u093E\u0902\u0921\u0941",
4825
+ bohag_bihu: "\u092C\u094B\u0939\u093E\u0917 \u092C\u093F\u0939\u0942",
4595
4826
  makar_sankranti: "\u092E\u0915\u0930 \u0938\u0902\u0915\u094D\u0930\u093E\u0902\u0924\u093F",
4596
4827
  pongal: "\u092A\u094B\u0902\u0917\u0932",
4597
4828
  uttarayan: "\u0909\u0924\u094D\u0924\u0930\u093E\u092F\u0923",
4598
- bihu: "\u092E\u093E\u0918 \u092C\u093F\u0939\u0942",
4829
+ magh_bihu: "\u092E\u093E\u0918 \u092C\u093F\u0939\u0942",
4599
4830
  ayyappa_makara_jyothi: "\u0905\u092F\u094D\u092F\u092A\u094D\u092A\u093E \u092E\u0915\u0930 \u091C\u094D\u092F\u094B\u0924\u093F",
4600
4831
  dakshinayana: "\u0926\u0915\u094D\u0937\u093F\u0923\u093E\u092F\u0928",
4832
+ raja_sankranti: "\u0930\u093E\u091C\u093E \u0938\u0902\u0915\u094D\u0930\u093E\u0902\u0924\u093F",
4833
+ raja_pahili: "\u092A\u0939\u093F\u0932\u0940 \u0930\u093E\u091C\u093E",
4834
+ raja_basi: "\u092C\u093E\u0938\u0940 \u0930\u093E\u091C\u093E",
4835
+ harela: "\u0939\u0930\u0947\u0932\u093E",
4601
4836
  singh_sankranti: "\u0938\u093F\u0902\u0939 \u0938\u0902\u0915\u094D\u0930\u093E\u0902\u0924\u093F",
4837
+ sair: "\u0938\u0948\u0930",
4838
+ kati_bihu: "\u0915\u093E\u0924\u0940 \u092C\u093F\u0939\u0942",
4839
+ lohri: "\u0932\u094B\u0939\u0921\u093C\u0940",
4840
+ // Regional festivals (v2.1 expansion)
4841
+ gudi_padwa: "\u0917\u0941\u0921\u093C\u0940 \u092A\u0921\u093C\u0935\u093E",
4842
+ gangaur: "\u0917\u0923\u0917\u094C\u0930",
4843
+ karaga: "\u0915\u0930\u0917\u093E",
4844
+ bonalu: "\u092C\u094B\u0928\u093E\u0932\u0941",
4845
+ hariyali_teej: "\u0939\u0930\u093F\u092F\u093E\u0932\u0940 \u0924\u0940\u091C",
4846
+ kajari_teej: "\u0915\u091C\u0930\u0940 \u0924\u0940\u091C",
4847
+ hartalika_teej: "\u0939\u0930\u0924\u093E\u0932\u093F\u0915\u093E \u0924\u0940\u091C",
4848
+ govardhan_puja: "\u0917\u094B\u0935\u0930\u094D\u0927\u0928 \u092A\u0942\u091C\u093E",
4849
+ bhai_dooj: "\u092D\u093E\u0908 \u0926\u0942\u091C",
4850
+ phagli: "\u092B\u093E\u0917\u094D\u0932\u0940",
4851
+ jagannath_rath_yatra: "\u091C\u0917\u0928\u094D\u0928\u093E\u0925 \u0930\u0925 \u092F\u093E\u0924\u094D\u0930\u093E",
4852
+ varamahalakshmi: "\u0935\u0930\u092E\u0939\u093E\u0932\u0915\u094D\u0937\u094D\u092E\u0940 \u0935\u094D\u0930\u0924",
4853
+ bathukamma_start: "\u092C\u0924\u0941\u0915\u092E\u094D\u092E\u093E \u2014 \u090F\u0902\u0917\u093F\u0932\u0940 \u092A\u0941\u0932\u093E",
4854
+ bathukamma_saddula: "\u092C\u0924\u0941\u0915\u092E\u094D\u092E\u093E \u2014 \u0938\u0926\u094D\u0926\u0941\u0932\u093E",
4602
4855
  // Chhath Puja
4603
4856
  chhath_nahay_khay: "\u091B\u0920 \u2014 \u0928\u0939\u093E\u092F \u0916\u093E\u092F",
4604
4857
  chhath_kharna: "\u091B\u0920 \u2014 \u0916\u0930\u0928\u093E",
@@ -4828,7 +5081,7 @@ function getInstantPanchang(date, location, options) {
4828
5081
  isAdhika: chandramasa.isAdhika,
4829
5082
  varaIndex: vara.index,
4830
5083
  solarMasaIndex: Math.floor(siderealSun / 30) % 12,
4831
- region: options?.region ?? "all"
5084
+ region: resolveRegionAlias(options?.region)
4832
5085
  },
4833
5086
  (key) => t.festivalNames[key] ?? t.misc[key] ?? key,
4834
5087
  (idx) => resolveMasaName(idx, lang)
@@ -5013,6 +5266,21 @@ function getDailyPanchang(date, location, options) {
5013
5266
  const rashiAtSunrise = Math.floor(siderealSunAtSunrise / 30) % 12;
5014
5267
  const rashiAtNextSunrise = Math.floor(getSun(nextSunriseUtc) / 30) % 12;
5015
5268
  const sankrantiRashi = rashiAtSunrise !== rashiAtNextSunrise ? rashiAtNextSunrise : null;
5269
+ let nextDaySankrantiRashi = null;
5270
+ try {
5271
+ const tomorrowSunsetUtc = computeSunset(nextSunriseUtc, location);
5272
+ const dayAfterSunriseUtc = computeSunrise(tomorrowSunsetUtc, location);
5273
+ const rashiAtDayAfterSunrise = Math.floor(getSun(dayAfterSunriseUtc) / 30) % 12;
5274
+ if (rashiAtNextSunrise !== rashiAtDayAfterSunrise) {
5275
+ nextDaySankrantiRashi = rashiAtDayAfterSunrise;
5276
+ }
5277
+ } catch (e) {
5278
+ if (!(e instanceof PanchangError && (e.code === "NO_SUNRISE" || e.code === "NO_SUNSET"))) {
5279
+ throw e;
5280
+ }
5281
+ }
5282
+ const rashiAtYesterdaySunrise = Math.floor(getSun(yesterdaySunriseUtc) / 30) % 12;
5283
+ const prevDaySankrantiRashi = rashiAtYesterdaySunrise !== rashiAtSunrise ? rashiAtSunrise : null;
5016
5284
  let ekadashiDashamiViddha = false;
5017
5285
  if (tithiAtSunrise.index === 10 || tithiAtSunrise.index === 25) {
5018
5286
  const tithiAtArunodaya = tithiAt(arunodayaUtc);
@@ -5062,6 +5330,8 @@ function getDailyPanchang(date, location, options) {
5062
5330
  priorDayTithiByRule,
5063
5331
  nakshatraIndicesInDay,
5064
5332
  sankrantiRashi,
5333
+ nextDaySankrantiRashi,
5334
+ prevDaySankrantiRashi,
5065
5335
  ekadashiDashamiViddha,
5066
5336
  smartaDwadashiToday,
5067
5337
  moonriseInDay: moonriseInDayUtc,
@@ -5070,7 +5340,7 @@ function getDailyPanchang(date, location, options) {
5070
5340
  end: utcToLocalDisplay(bhadraUtc.end, offsetMinutes)
5071
5341
  } : null,
5072
5342
  formatClock,
5073
- region: options.region ?? "all"
5343
+ region: resolveRegionAlias(options.region)
5074
5344
  },
5075
5345
  (key) => t.festivalNames[key] ?? t.misc[key] ?? key,
5076
5346
  (idx) => resolveMasaName(idx, lang)
package/dist/index.d.cts CHANGED
@@ -12,13 +12,31 @@ type Language = 'en' | 'hi';
12
12
  type Precision = 'standard' | 'high';
13
13
  type MasaSystem = 'purnimanta' | 'amanta';
14
14
  /**
15
- * Regional scope for region-specific festival variants (primarily regional
16
- * Sankranti names Pongal, Vishu, Baisakhi, Bihu, Ayyappa Makara Jyothi,
17
- * etc.). Default `'all'` emits every regional variant; narrower values
18
- * filter the regional variants to that region. The canonical pan-Indian
15
+ * Regional scope for region-specific festival variants. Default `'all'` emits
16
+ * every regional variant; narrower values filter to festivals scoped to that
17
+ * region (or pan-Indian festivals, which always emit). The canonical
19
18
  * `sankranti` event is always emitted regardless of this setting.
19
+ *
20
+ * State-slug naming: each value corresponds to an Indian state (or `nepal`
21
+ * for Nepali panchang usage). The single pre-v2.1 direction-based value
22
+ * `'north-india'` and the ethno-linguistic slugs `'tamil'` and `'bengal'`
23
+ * are still accepted as inputs ({@link LegacyFestivalRegion}) and mapped
24
+ * to their canonical equivalents at entry-point resolution time.
25
+ */
26
+ type FestivalRegion = 'all' | 'tamil-nadu' | 'kerala' | 'karnataka' | 'andhra-pradesh' | 'telangana' | 'west-bengal' | 'odisha' | 'assam' | 'bihar' | 'jharkhand' | 'gujarat' | 'maharashtra' | 'goa' | 'rajasthan' | 'punjab' | 'haryana' | 'himachal-pradesh' | 'uttarakhand' | 'uttar-pradesh' | 'madhya-pradesh' | 'nepal';
27
+ /**
28
+ * Pre-v2.1 region identifiers accepted for back-compat. These are mapped
29
+ * to canonical {@link FestivalRegion} values by `resolveRegionAlias` before
30
+ * festival filtering. Slated for removal in v3.
31
+ *
32
+ * - `'tamil'` → `'tamil-nadu'`
33
+ * - `'bengal'` → `'west-bengal'`
34
+ * - `'north-india'` → `'all'` (Makar Sankranti is pan-Indian; use explicit
35
+ * state slugs for Lohri / Govardhan / Bhai Dooj)
36
+ *
37
+ * @deprecated Use the equivalent {@link FestivalRegion} value. Removal in v3.
20
38
  */
21
- type FestivalRegion = 'all' | 'north-india' | 'tamil' | 'kerala' | 'bengal' | 'punjab' | 'gujarat' | 'assam' | 'maharashtra';
39
+ type LegacyFestivalRegion = 'tamil' | 'bengal' | 'north-india';
22
40
  interface PanchangOptions {
23
41
  timezone: number | string;
24
42
  ayanamsa?: AyanamsaType;
@@ -35,9 +53,10 @@ interface PanchangOptions {
35
53
  janmaRashi?: number;
36
54
  /**
37
55
  * Regional scope for region-specific festival variants. Default `'all'`.
38
- * See {@link FestivalRegion} for supported regions.
56
+ * See {@link FestivalRegion} for supported regions; pre-v2.1 values
57
+ * ({@link LegacyFestivalRegion}) are accepted and mapped internally.
39
58
  */
40
- region?: FestivalRegion;
59
+ region?: FestivalRegion | LegacyFestivalRegion;
41
60
  }
42
61
  interface InstantPanchangOptions {
43
62
  ayanamsa?: AyanamsaType;
@@ -54,9 +73,10 @@ interface InstantPanchangOptions {
54
73
  janmaRashi?: number;
55
74
  /**
56
75
  * Regional scope for region-specific festival variants. Default `'all'`.
57
- * See {@link FestivalRegion} for supported regions.
76
+ * See {@link FestivalRegion} for supported regions; pre-v2.1 values
77
+ * ({@link LegacyFestivalRegion}) are accepted and mapped internally.
58
78
  */
59
- region?: FestivalRegion;
79
+ region?: FestivalRegion | LegacyFestivalRegion;
60
80
  }
61
81
 
62
82
  interface TimePeriod {
@@ -964,4 +984,4 @@ declare class PanchangError extends Error {
964
984
  constructor(message: string, code: PanchangErrorCode);
965
985
  }
966
986
 
967
- export { type AntarDasha, type AyanamsaType, type BhadraInfo, type ChandraBalamInfo, type ChandraMasaInfo, type ChoghadiyaInfo, type ChoghadiyaQuality, type ChoghadiyaSlot, type DailyKaranaInfo, type DailyNakshatraInfo, type DailyPanchangResult, type DailyTithiInfo, type DailyYogaInfo, type DashaLord, type FestivalInfo, type FestivalRegion, GRAHA_ABBR, type GeoLocation, type GowriInfo, type GowriSlot, type GrahaName, type GrahaPosition, type HoraInfo, type HoraSlot, type InstantPanchangOptions, type InstantPanchangResult, type KaranaInfo, type Language, type MahaDasha, type MasaInfo, type MasaSystem, type NakshatraInfo, PanchangError, type PanchangErrorCode, type PanchangOptions, type PlanetaryPositions, type Precision, type RashiInfo, type SamvatInfo, type SpecialYogaInfo, type TimePeriod, type TithiInfo, type VaraInfo, type VimshottariDashaResult, type YogaInfo, computeAbhijitMuhurta, computeAmritKala, computeBrahmaMuhurta, computeChandraBalam, computeGodhuliMuhurta, computeGowriPanchangam, computeGulikaKalam, computeNishitaMuhurta, computePlanetaryPositions, computeRahuKalam, computeVijayaMuhurta, computeVimshottariDasha, computeVimshottariDashaFromBirth, computeYamaganda, computeAyanamsa as getAyanamsa, getDailyPanchang, getEclipseDuringDay, getInstantPanchang, getMoonrise, getMoonset, getSiderealMoonLongitude, getSiderealSunLongitude, computeSunrise as getSunrise, computeSunset as getSunset, getUpcomingLunarEclipse, getUpcomingSolarEclipse };
987
+ export { type AntarDasha, type AyanamsaType, type BhadraInfo, type ChandraBalamInfo, type ChandraMasaInfo, type ChoghadiyaInfo, type ChoghadiyaQuality, type ChoghadiyaSlot, type DailyKaranaInfo, type DailyNakshatraInfo, type DailyPanchangResult, type DailyTithiInfo, type DailyYogaInfo, type DashaLord, type FestivalInfo, type FestivalRegion, GRAHA_ABBR, type GeoLocation, type GowriInfo, type GowriSlot, type GrahaName, type GrahaPosition, type HoraInfo, type HoraSlot, type InstantPanchangOptions, type InstantPanchangResult, type KaranaInfo, type Language, type LegacyFestivalRegion, type MahaDasha, type MasaInfo, type MasaSystem, type NakshatraInfo, PanchangError, type PanchangErrorCode, type PanchangOptions, type PlanetaryPositions, type Precision, type RashiInfo, type SamvatInfo, type SpecialYogaInfo, type TimePeriod, type TithiInfo, type VaraInfo, type VimshottariDashaResult, type YogaInfo, computeAbhijitMuhurta, computeAmritKala, computeBrahmaMuhurta, computeChandraBalam, computeGodhuliMuhurta, computeGowriPanchangam, computeGulikaKalam, computeNishitaMuhurta, computePlanetaryPositions, computeRahuKalam, computeVijayaMuhurta, computeVimshottariDasha, computeVimshottariDashaFromBirth, computeYamaganda, computeAyanamsa as getAyanamsa, getDailyPanchang, getEclipseDuringDay, getInstantPanchang, getMoonrise, getMoonset, getSiderealMoonLongitude, getSiderealSunLongitude, computeSunrise as getSunrise, computeSunset as getSunset, getUpcomingLunarEclipse, getUpcomingSolarEclipse };
package/dist/index.d.ts CHANGED
@@ -12,13 +12,31 @@ type Language = 'en' | 'hi';
12
12
  type Precision = 'standard' | 'high';
13
13
  type MasaSystem = 'purnimanta' | 'amanta';
14
14
  /**
15
- * Regional scope for region-specific festival variants (primarily regional
16
- * Sankranti names Pongal, Vishu, Baisakhi, Bihu, Ayyappa Makara Jyothi,
17
- * etc.). Default `'all'` emits every regional variant; narrower values
18
- * filter the regional variants to that region. The canonical pan-Indian
15
+ * Regional scope for region-specific festival variants. Default `'all'` emits
16
+ * every regional variant; narrower values filter to festivals scoped to that
17
+ * region (or pan-Indian festivals, which always emit). The canonical
19
18
  * `sankranti` event is always emitted regardless of this setting.
19
+ *
20
+ * State-slug naming: each value corresponds to an Indian state (or `nepal`
21
+ * for Nepali panchang usage). The single pre-v2.1 direction-based value
22
+ * `'north-india'` and the ethno-linguistic slugs `'tamil'` and `'bengal'`
23
+ * are still accepted as inputs ({@link LegacyFestivalRegion}) and mapped
24
+ * to their canonical equivalents at entry-point resolution time.
25
+ */
26
+ type FestivalRegion = 'all' | 'tamil-nadu' | 'kerala' | 'karnataka' | 'andhra-pradesh' | 'telangana' | 'west-bengal' | 'odisha' | 'assam' | 'bihar' | 'jharkhand' | 'gujarat' | 'maharashtra' | 'goa' | 'rajasthan' | 'punjab' | 'haryana' | 'himachal-pradesh' | 'uttarakhand' | 'uttar-pradesh' | 'madhya-pradesh' | 'nepal';
27
+ /**
28
+ * Pre-v2.1 region identifiers accepted for back-compat. These are mapped
29
+ * to canonical {@link FestivalRegion} values by `resolveRegionAlias` before
30
+ * festival filtering. Slated for removal in v3.
31
+ *
32
+ * - `'tamil'` → `'tamil-nadu'`
33
+ * - `'bengal'` → `'west-bengal'`
34
+ * - `'north-india'` → `'all'` (Makar Sankranti is pan-Indian; use explicit
35
+ * state slugs for Lohri / Govardhan / Bhai Dooj)
36
+ *
37
+ * @deprecated Use the equivalent {@link FestivalRegion} value. Removal in v3.
20
38
  */
21
- type FestivalRegion = 'all' | 'north-india' | 'tamil' | 'kerala' | 'bengal' | 'punjab' | 'gujarat' | 'assam' | 'maharashtra';
39
+ type LegacyFestivalRegion = 'tamil' | 'bengal' | 'north-india';
22
40
  interface PanchangOptions {
23
41
  timezone: number | string;
24
42
  ayanamsa?: AyanamsaType;
@@ -35,9 +53,10 @@ interface PanchangOptions {
35
53
  janmaRashi?: number;
36
54
  /**
37
55
  * Regional scope for region-specific festival variants. Default `'all'`.
38
- * See {@link FestivalRegion} for supported regions.
56
+ * See {@link FestivalRegion} for supported regions; pre-v2.1 values
57
+ * ({@link LegacyFestivalRegion}) are accepted and mapped internally.
39
58
  */
40
- region?: FestivalRegion;
59
+ region?: FestivalRegion | LegacyFestivalRegion;
41
60
  }
42
61
  interface InstantPanchangOptions {
43
62
  ayanamsa?: AyanamsaType;
@@ -54,9 +73,10 @@ interface InstantPanchangOptions {
54
73
  janmaRashi?: number;
55
74
  /**
56
75
  * Regional scope for region-specific festival variants. Default `'all'`.
57
- * See {@link FestivalRegion} for supported regions.
76
+ * See {@link FestivalRegion} for supported regions; pre-v2.1 values
77
+ * ({@link LegacyFestivalRegion}) are accepted and mapped internally.
58
78
  */
59
- region?: FestivalRegion;
79
+ region?: FestivalRegion | LegacyFestivalRegion;
60
80
  }
61
81
 
62
82
  interface TimePeriod {
@@ -964,4 +984,4 @@ declare class PanchangError extends Error {
964
984
  constructor(message: string, code: PanchangErrorCode);
965
985
  }
966
986
 
967
- export { type AntarDasha, type AyanamsaType, type BhadraInfo, type ChandraBalamInfo, type ChandraMasaInfo, type ChoghadiyaInfo, type ChoghadiyaQuality, type ChoghadiyaSlot, type DailyKaranaInfo, type DailyNakshatraInfo, type DailyPanchangResult, type DailyTithiInfo, type DailyYogaInfo, type DashaLord, type FestivalInfo, type FestivalRegion, GRAHA_ABBR, type GeoLocation, type GowriInfo, type GowriSlot, type GrahaName, type GrahaPosition, type HoraInfo, type HoraSlot, type InstantPanchangOptions, type InstantPanchangResult, type KaranaInfo, type Language, type MahaDasha, type MasaInfo, type MasaSystem, type NakshatraInfo, PanchangError, type PanchangErrorCode, type PanchangOptions, type PlanetaryPositions, type Precision, type RashiInfo, type SamvatInfo, type SpecialYogaInfo, type TimePeriod, type TithiInfo, type VaraInfo, type VimshottariDashaResult, type YogaInfo, computeAbhijitMuhurta, computeAmritKala, computeBrahmaMuhurta, computeChandraBalam, computeGodhuliMuhurta, computeGowriPanchangam, computeGulikaKalam, computeNishitaMuhurta, computePlanetaryPositions, computeRahuKalam, computeVijayaMuhurta, computeVimshottariDasha, computeVimshottariDashaFromBirth, computeYamaganda, computeAyanamsa as getAyanamsa, getDailyPanchang, getEclipseDuringDay, getInstantPanchang, getMoonrise, getMoonset, getSiderealMoonLongitude, getSiderealSunLongitude, computeSunrise as getSunrise, computeSunset as getSunset, getUpcomingLunarEclipse, getUpcomingSolarEclipse };
987
+ export { type AntarDasha, type AyanamsaType, type BhadraInfo, type ChandraBalamInfo, type ChandraMasaInfo, type ChoghadiyaInfo, type ChoghadiyaQuality, type ChoghadiyaSlot, type DailyKaranaInfo, type DailyNakshatraInfo, type DailyPanchangResult, type DailyTithiInfo, type DailyYogaInfo, type DashaLord, type FestivalInfo, type FestivalRegion, GRAHA_ABBR, type GeoLocation, type GowriInfo, type GowriSlot, type GrahaName, type GrahaPosition, type HoraInfo, type HoraSlot, type InstantPanchangOptions, type InstantPanchangResult, type KaranaInfo, type Language, type LegacyFestivalRegion, type MahaDasha, type MasaInfo, type MasaSystem, type NakshatraInfo, PanchangError, type PanchangErrorCode, type PanchangOptions, type PlanetaryPositions, type Precision, type RashiInfo, type SamvatInfo, type SpecialYogaInfo, type TimePeriod, type TithiInfo, type VaraInfo, type VimshottariDashaResult, type YogaInfo, computeAbhijitMuhurta, computeAmritKala, computeBrahmaMuhurta, computeChandraBalam, computeGodhuliMuhurta, computeGowriPanchangam, computeGulikaKalam, computeNishitaMuhurta, computePlanetaryPositions, computeRahuKalam, computeVijayaMuhurta, computeVimshottariDasha, computeVimshottariDashaFromBirth, computeYamaganda, computeAyanamsa as getAyanamsa, getDailyPanchang, getEclipseDuringDay, getInstantPanchang, getMoonrise, getMoonset, getSiderealMoonLongitude, getSiderealSunLongitude, computeSunrise as getSunrise, computeSunset as getSunset, getUpcomingLunarEclipse, getUpcomingSolarEclipse };
package/dist/index.js CHANGED
@@ -3754,28 +3754,47 @@ function computeDurMuhurta(sunrise, sunset, varaIndex) {
3754
3754
  var SANKRANTI_REGIONAL = {
3755
3755
  // Mesha (0) — solar new year across regions
3756
3756
  0: [
3757
- { key: "baisakhi", region: "punjab", type: "major" },
3758
- { key: "vishu", region: "kerala", type: "major" },
3759
- { key: "pohela_boishakh", region: "bengal", type: "major" },
3760
- { key: "puthandu", region: "tamil", type: "major" }
3757
+ { key: "baisakhi", regions: ["punjab", "haryana"], type: "major" },
3758
+ { key: "vishu", regions: ["kerala"], type: "major" },
3759
+ { key: "pohela_boishakh", regions: ["west-bengal"], type: "major" },
3760
+ { key: "puthandu", regions: ["tamil-nadu"], type: "major" },
3761
+ { key: "bohag_bihu", regions: ["assam"], type: "major" }
3761
3762
  ],
3762
3763
  // Karka (3) — Dakshinayana (Sun's southward course begins)
3763
3764
  3: [
3764
- { key: "dakshinayana", region: "all", type: "minor" }
3765
+ { key: "dakshinayana", regions: ["all"], type: "minor" },
3766
+ // Raja Parba (Odisha) — 4-day monsoon festival; we emit a single-day
3767
+ // marker on Karka Sankranti, the most widely cited anchor day.
3768
+ { key: "raja_sankranti", regions: ["odisha"], type: "major" },
3769
+ // Harela (Kumaon / Uttarakhand) — observed on Shravana solar-month start.
3770
+ { key: "harela", regions: ["uttarakhand"], type: "major" }
3765
3771
  ],
3766
- // Simha (4)
3772
+ // Simha (4) — Singh Sankranti is primarily observed in Odisha, Bihar,
3773
+ // and Nepal (as Singhasankranti); not a pan-Indian observance despite
3774
+ // the pre-v2.1 tagging.
3767
3775
  4: [
3768
- { key: "singh_sankranti", region: "all", type: "minor" }
3776
+ { key: "singh_sankranti", regions: ["odisha", "bihar", "jharkhand", "nepal"], type: "minor" }
3777
+ ],
3778
+ // Kanya (5) — Sair (Himachal): first day of the Ashwin solar month.
3779
+ 5: [
3780
+ { key: "sair", regions: ["himachal-pradesh"], type: "minor" }
3781
+ ],
3782
+ // Tula (6) — Kati Bihu (Assam): Kartika solar-month start.
3783
+ 6: [
3784
+ { key: "kati_bihu", regions: ["assam"], type: "minor" }
3769
3785
  ],
3770
3786
  // Makara (9) — Uttarayana / harvest festivals
3771
3787
  9: [
3772
- { key: "makar_sankranti", region: "north-india", type: "major" },
3773
- { key: "pongal", region: "tamil", type: "major" },
3774
- { key: "uttarayan", region: "gujarat", type: "major" },
3775
- { key: "bihu", region: "assam", type: "major" },
3776
- { key: "ayyappa_makara_jyothi", region: "kerala", type: "major" }
3788
+ // Makar Sankranti is pan-Indian (re-scoped from the pre-v2.1 'north-india').
3789
+ { key: "makar_sankranti", regions: ["all"], type: "major" },
3790
+ { key: "pongal", regions: ["tamil-nadu"], type: "major" },
3791
+ { key: "uttarayan", regions: ["gujarat"], type: "major" },
3792
+ { key: "magh_bihu", regions: ["assam"], type: "major" },
3793
+ { key: "ayyappa_makara_jyothi", regions: ["kerala"], type: "major" }
3777
3794
  ]
3778
3795
  };
3796
+ var LOHRI_REGIONS = ["punjab", "haryana", "himachal-pradesh"];
3797
+ var RAJA_REGIONS = ["odisha"];
3779
3798
  var FESTIVAL_REGISTRY = [
3780
3799
  // Chaitra (0)
3781
3800
  { key: "ugadi", masa: 0, tithi: 0, type: "major" },
@@ -3849,7 +3868,144 @@ var FESTIVAL_REGISTRY = [
3849
3868
  // Rig Upakarma — Shravana nakshatra (21) in Shravana chandra masa (4).
3850
3869
  { key: "rig_upakarma", masa: 4, nakshatra: 21, type: "major" },
3851
3870
  // Sama Upakarma — Hasta nakshatra (12) in Bhadrapada chandra masa (5).
3852
- { key: "sama_upakarma", masa: 5, nakshatra: 12, type: "major" }
3871
+ { key: "sama_upakarma", masa: 5, nakshatra: 12, type: "major" },
3872
+ // ── Regional festivals (v2.1 expansion) ─────────────────────
3873
+ // Chaitra (0) — Marathi/Konkani New Year; same tithi as Ugadi but
3874
+ // emitted as a Maharashtra-specific variant name alongside Ugadi.
3875
+ {
3876
+ key: "gudi_padwa",
3877
+ masa: 0,
3878
+ tithi: 0,
3879
+ type: "major",
3880
+ regions: ["maharashtra", "goa"]
3881
+ },
3882
+ // Chaitra (0) Shukla Tritiya — Gangaur (18-day festival concludes here).
3883
+ {
3884
+ key: "gangaur",
3885
+ masa: 0,
3886
+ tithi: 2,
3887
+ type: "major",
3888
+ regions: ["rajasthan"]
3889
+ },
3890
+ // Chaitra (0) Purnima — Karaga festival of Bengaluru.
3891
+ {
3892
+ key: "karaga",
3893
+ masa: 0,
3894
+ tithi: 14,
3895
+ type: "major",
3896
+ regions: ["karnataka"]
3897
+ },
3898
+ // Ashadha (3) — Bonalu, Sundays at Mahakali temples across Telangana.
3899
+ {
3900
+ key: "bonalu",
3901
+ masa: 3,
3902
+ vara: 0,
3903
+ type: "minor",
3904
+ adhikaBehaviour: "observe-in-both",
3905
+ regions: ["telangana"]
3906
+ },
3907
+ // Shravana (4) Shukla Tritiya — Hariyali Teej.
3908
+ {
3909
+ key: "hariyali_teej",
3910
+ masa: 4,
3911
+ tithi: 2,
3912
+ type: "major",
3913
+ regions: ["rajasthan", "uttar-pradesh", "bihar", "haryana", "madhya-pradesh"]
3914
+ },
3915
+ // Shravana (4) Krishna Tritiya — Kajari Teej (tithi 17 = Krishna Tritiya).
3916
+ {
3917
+ key: "kajari_teej",
3918
+ masa: 4,
3919
+ tithi: 17,
3920
+ type: "major",
3921
+ regions: ["rajasthan", "uttar-pradesh", "madhya-pradesh"]
3922
+ },
3923
+ // Bhadrapada (5) Shukla Tritiya — Hartalika Teej.
3924
+ {
3925
+ key: "hartalika_teej",
3926
+ masa: 5,
3927
+ tithi: 2,
3928
+ type: "major",
3929
+ regions: ["rajasthan", "uttar-pradesh", "bihar", "maharashtra", "madhya-pradesh"]
3930
+ },
3931
+ // Amanta Kartika (7) Shukla Pratipada — day after Diwali.
3932
+ // In Purnimanta convention this is also "Kartika Shukla Pratipada" (naming
3933
+ // system aligns), so a namingSystem tag isn't required here.
3934
+ {
3935
+ key: "govardhan_puja",
3936
+ masa: 7,
3937
+ tithi: 0,
3938
+ type: "major",
3939
+ regions: [
3940
+ "uttar-pradesh",
3941
+ "bihar",
3942
+ "haryana",
3943
+ "rajasthan",
3944
+ "gujarat",
3945
+ "madhya-pradesh",
3946
+ "punjab",
3947
+ "jharkhand"
3948
+ ]
3949
+ },
3950
+ // Amanta Kartika (7) Shukla Dwitiya — Bhai Dooj.
3951
+ {
3952
+ key: "bhai_dooj",
3953
+ masa: 7,
3954
+ tithi: 1,
3955
+ type: "major",
3956
+ regions: [
3957
+ "uttar-pradesh",
3958
+ "bihar",
3959
+ "haryana",
3960
+ "maharashtra",
3961
+ "gujarat",
3962
+ "rajasthan",
3963
+ "madhya-pradesh",
3964
+ "west-bengal",
3965
+ "jharkhand",
3966
+ "nepal"
3967
+ ]
3968
+ },
3969
+ // Phalguna (11) Purnima — Phagli (varies by valley; Purnima anchor).
3970
+ {
3971
+ key: "phagli",
3972
+ masa: 11,
3973
+ tithi: 14,
3974
+ type: "minor",
3975
+ regions: ["himachal-pradesh"]
3976
+ },
3977
+ // Ashadha (3) Shukla Dwitiya — Jagannath Rath Yatra (pan-Indian; cultural
3978
+ // epicenter is Puri, Odisha but observed nationwide).
3979
+ { key: "jagannath_rath_yatra", masa: 3, tithi: 1, type: "major" },
3980
+ // Shravana (4) Shukla — Varamahalakshmi: last Friday in Shukla paksha
3981
+ // before Purnima. The (masa+vara) match is gated by tithi ∈ [7,13] so
3982
+ // only the second Friday of the paksha (the one closest to Purnima) fires.
3983
+ {
3984
+ key: "varamahalakshmi",
3985
+ masa: 4,
3986
+ vara: 5,
3987
+ type: "major",
3988
+ tithiRange: [7, 13],
3989
+ regions: ["karnataka", "andhra-pradesh", "telangana", "tamil-nadu"]
3990
+ },
3991
+ // Bathukamma (Telangana) — 9-day floral festival from Bhadrapada
3992
+ // Amavasya through Ashwin Shukla Navami. We emit start (Engili Pula
3993
+ // Bathukamma, masa=5/tithi=29) and climax (Saddula Bathukamma, masa=6/
3994
+ // tithi=8) markers; intermediate days carry no library-level emission.
3995
+ {
3996
+ key: "bathukamma_start",
3997
+ masa: 5,
3998
+ tithi: 29,
3999
+ type: "major",
4000
+ regions: ["telangana"]
4001
+ },
4002
+ {
4003
+ key: "bathukamma_saddula",
4004
+ masa: 6,
4005
+ tithi: 8,
4006
+ type: "major",
4007
+ regions: ["telangana"]
4008
+ }
3853
4009
  ];
3854
4010
  var EKADASHI_NAMES = [
3855
4011
  ["kamada", "papamochani"],
@@ -3926,7 +4082,14 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
3926
4082
  match = masaMatches && rule.nakshatra === ctx.nakshatraIndex;
3927
4083
  } else if (rule.vara !== void 0 && rule.masa !== void 0) {
3928
4084
  const masaMatches = rule.masa === ctx.chandraMasaIndex && (adhikaBehaviour !== "shift-to-nija" || !ctx.isAdhika);
3929
- match = masaMatches && rule.vara === ctx.varaIndex;
4085
+ let inTithiRange = true;
4086
+ if (rule.tithiRange !== void 0) {
4087
+ const dateRule = rule.dateRule ?? "sunrise";
4088
+ const tithi = tithiForRule(dateRule);
4089
+ const [lo, hi2] = rule.tithiRange;
4090
+ inTithiRange = tithi >= lo && tithi <= hi2;
4091
+ }
4092
+ match = masaMatches && rule.vara === ctx.varaIndex && inTithiRange;
3930
4093
  } else if (rule.masa !== void 0 && rule.tithi !== void 0) {
3931
4094
  const masaMatches = rule.masa === ctx.chandraMasaIndex && // `shift-to-nija`: only observe in Nija following an Adhika (but still OK if no prior Adhika,
3932
4095
  // since the normal year has no Adhika and the festival observes as usual).
@@ -3946,6 +4109,12 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
3946
4109
  }
3947
4110
  }
3948
4111
  if (!match) continue;
4112
+ if (rule.regions !== void 0) {
4113
+ const region2 = ctx.region ?? "all";
4114
+ if (region2 !== "all" && !rule.regions.includes("all") && !rule.regions.includes(region2)) {
4115
+ continue;
4116
+ }
4117
+ }
3949
4118
  const festival = { name: nameResolver(rule.key), type: rule.type };
3950
4119
  if (rule.namingSystem === "purnimanta" && ctx.purnimantaMasaName && ctx.amantaMasaName) {
3951
4120
  festival.description = `Purnimanta: ${ctx.purnimantaMasaName} Krishna Paksha`;
@@ -4050,6 +4219,7 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
4050
4219
  description: nameResolver(variantKey)
4051
4220
  });
4052
4221
  }
4222
+ const region = ctx.region ?? "all";
4053
4223
  if (ctx.sankrantiRashi !== void 0 && ctx.sankrantiRashi !== null) {
4054
4224
  const rashiName = rashiNameResolver ? rashiNameResolver(ctx.sankrantiRashi) : `Rashi ${ctx.sankrantiRashi}`;
4055
4225
  results.push({
@@ -4057,11 +4227,10 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
4057
4227
  type: "sankranti",
4058
4228
  description: rashiName
4059
4229
  });
4060
- const region = ctx.region ?? "all";
4061
4230
  const regionalRules = SANKRANTI_REGIONAL[ctx.sankrantiRashi];
4062
4231
  if (regionalRules) {
4063
4232
  for (const r of regionalRules) {
4064
- if (region !== "all" && r.region !== "all" && r.region !== region) continue;
4233
+ if (region !== "all" && !r.regions.includes("all") && !r.regions.includes(region)) continue;
4065
4234
  results.push({
4066
4235
  name: nameResolver(r.key),
4067
4236
  type: "sankranti",
@@ -4070,9 +4239,47 @@ function computeFestivals(ctx, nameResolver, rashiNameResolver) {
4070
4239
  }
4071
4240
  }
4072
4241
  }
4242
+ if (ctx.nextDaySankrantiRashi === 9) {
4243
+ if (region === "all" || LOHRI_REGIONS.includes(region)) {
4244
+ results.push({ name: nameResolver("lohri"), type: "major" });
4245
+ }
4246
+ }
4247
+ if (ctx.nextDaySankrantiRashi === 3) {
4248
+ if (region === "all" || RAJA_REGIONS.includes(region)) {
4249
+ results.push({ name: nameResolver("raja_pahili"), type: "major" });
4250
+ }
4251
+ }
4252
+ if (ctx.prevDaySankrantiRashi === 3) {
4253
+ if (region === "all" || RAJA_REGIONS.includes(region)) {
4254
+ results.push({ name: nameResolver("raja_basi"), type: "major" });
4255
+ }
4256
+ }
4073
4257
  return results;
4074
4258
  }
4075
4259
 
4260
+ // src/core/regionAlias.ts
4261
+ var LEGACY_REGION_ALIASES = {
4262
+ "tamil": "tamil-nadu",
4263
+ "bengal": "west-bengal",
4264
+ "north-india": "all"
4265
+ };
4266
+ var warned = /* @__PURE__ */ new Set();
4267
+ function resolveRegionAlias(region) {
4268
+ if (region === void 0) return "all";
4269
+ if (region in LEGACY_REGION_ALIASES) {
4270
+ const legacy = region;
4271
+ const canonical = LEGACY_REGION_ALIASES[legacy];
4272
+ if (!warned.has(legacy)) {
4273
+ warned.add(legacy);
4274
+ console.warn(
4275
+ `[panchang-ts] FestivalRegion '${legacy}' is deprecated; use '${canonical}'. Legacy value will be removed in v3.`
4276
+ );
4277
+ }
4278
+ return canonical;
4279
+ }
4280
+ return region;
4281
+ }
4282
+
4076
4283
  // src/core/bhadra.ts
4077
4284
  function isVishtiKarana(karanaIndex) {
4078
4285
  if (karanaIndex <= 0 || karanaIndex >= 57) return false;
@@ -4348,13 +4555,36 @@ var en = {
4348
4555
  vishu: "Vishu",
4349
4556
  pohela_boishakh: "Pohela Boishakh",
4350
4557
  puthandu: "Puthandu",
4558
+ bohag_bihu: "Bohag Bihu",
4351
4559
  makar_sankranti: "Makar Sankranti",
4352
4560
  pongal: "Pongal",
4353
4561
  uttarayan: "Uttarayan",
4354
- bihu: "Magh Bihu",
4562
+ magh_bihu: "Magh Bihu",
4355
4563
  ayyappa_makara_jyothi: "Ayyappa Makara Jyothi",
4356
4564
  dakshinayana: "Dakshinayana",
4565
+ raja_sankranti: "Raja Sankranti",
4566
+ raja_pahili: "Pahili Raja",
4567
+ raja_basi: "Basi Raja",
4568
+ harela: "Harela",
4357
4569
  singh_sankranti: "Singh Sankranti",
4570
+ sair: "Sair",
4571
+ kati_bihu: "Kati Bihu",
4572
+ lohri: "Lohri",
4573
+ // Regional festivals (v2.1 expansion)
4574
+ gudi_padwa: "Gudi Padwa",
4575
+ gangaur: "Gangaur",
4576
+ karaga: "Karaga",
4577
+ bonalu: "Bonalu",
4578
+ hariyali_teej: "Hariyali Teej",
4579
+ kajari_teej: "Kajari Teej",
4580
+ hartalika_teej: "Hartalika Teej",
4581
+ govardhan_puja: "Govardhan Puja",
4582
+ bhai_dooj: "Bhai Dooj",
4583
+ phagli: "Phagli",
4584
+ jagannath_rath_yatra: "Jagannath Rath Yatra",
4585
+ varamahalakshmi: "Varamahalakshmi Vratam",
4586
+ bathukamma_start: "Bathukamma \u2014 Engili Pula",
4587
+ bathukamma_saddula: "Bathukamma \u2014 Saddula",
4358
4588
  // Chhath Puja (4-day, Kartika Shukla Chaturthi→Saptami)
4359
4589
  chhath_nahay_khay: "Chhath \u2014 Nahay Khay",
4360
4590
  chhath_kharna: "Chhath \u2014 Kharna",
@@ -4590,13 +4820,36 @@ var hi = {
4590
4820
  vishu: "\u0935\u093F\u0937\u0941",
4591
4821
  pohela_boishakh: "\u092A\u094B\u0939\u0947\u0932\u093E \u092C\u094B\u0907\u0936\u093E\u0916",
4592
4822
  puthandu: "\u092A\u0941\u0925\u093E\u0902\u0921\u0941",
4823
+ bohag_bihu: "\u092C\u094B\u0939\u093E\u0917 \u092C\u093F\u0939\u0942",
4593
4824
  makar_sankranti: "\u092E\u0915\u0930 \u0938\u0902\u0915\u094D\u0930\u093E\u0902\u0924\u093F",
4594
4825
  pongal: "\u092A\u094B\u0902\u0917\u0932",
4595
4826
  uttarayan: "\u0909\u0924\u094D\u0924\u0930\u093E\u092F\u0923",
4596
- bihu: "\u092E\u093E\u0918 \u092C\u093F\u0939\u0942",
4827
+ magh_bihu: "\u092E\u093E\u0918 \u092C\u093F\u0939\u0942",
4597
4828
  ayyappa_makara_jyothi: "\u0905\u092F\u094D\u092F\u092A\u094D\u092A\u093E \u092E\u0915\u0930 \u091C\u094D\u092F\u094B\u0924\u093F",
4598
4829
  dakshinayana: "\u0926\u0915\u094D\u0937\u093F\u0923\u093E\u092F\u0928",
4830
+ raja_sankranti: "\u0930\u093E\u091C\u093E \u0938\u0902\u0915\u094D\u0930\u093E\u0902\u0924\u093F",
4831
+ raja_pahili: "\u092A\u0939\u093F\u0932\u0940 \u0930\u093E\u091C\u093E",
4832
+ raja_basi: "\u092C\u093E\u0938\u0940 \u0930\u093E\u091C\u093E",
4833
+ harela: "\u0939\u0930\u0947\u0932\u093E",
4599
4834
  singh_sankranti: "\u0938\u093F\u0902\u0939 \u0938\u0902\u0915\u094D\u0930\u093E\u0902\u0924\u093F",
4835
+ sair: "\u0938\u0948\u0930",
4836
+ kati_bihu: "\u0915\u093E\u0924\u0940 \u092C\u093F\u0939\u0942",
4837
+ lohri: "\u0932\u094B\u0939\u0921\u093C\u0940",
4838
+ // Regional festivals (v2.1 expansion)
4839
+ gudi_padwa: "\u0917\u0941\u0921\u093C\u0940 \u092A\u0921\u093C\u0935\u093E",
4840
+ gangaur: "\u0917\u0923\u0917\u094C\u0930",
4841
+ karaga: "\u0915\u0930\u0917\u093E",
4842
+ bonalu: "\u092C\u094B\u0928\u093E\u0932\u0941",
4843
+ hariyali_teej: "\u0939\u0930\u093F\u092F\u093E\u0932\u0940 \u0924\u0940\u091C",
4844
+ kajari_teej: "\u0915\u091C\u0930\u0940 \u0924\u0940\u091C",
4845
+ hartalika_teej: "\u0939\u0930\u0924\u093E\u0932\u093F\u0915\u093E \u0924\u0940\u091C",
4846
+ govardhan_puja: "\u0917\u094B\u0935\u0930\u094D\u0927\u0928 \u092A\u0942\u091C\u093E",
4847
+ bhai_dooj: "\u092D\u093E\u0908 \u0926\u0942\u091C",
4848
+ phagli: "\u092B\u093E\u0917\u094D\u0932\u0940",
4849
+ jagannath_rath_yatra: "\u091C\u0917\u0928\u094D\u0928\u093E\u0925 \u0930\u0925 \u092F\u093E\u0924\u094D\u0930\u093E",
4850
+ varamahalakshmi: "\u0935\u0930\u092E\u0939\u093E\u0932\u0915\u094D\u0937\u094D\u092E\u0940 \u0935\u094D\u0930\u0924",
4851
+ bathukamma_start: "\u092C\u0924\u0941\u0915\u092E\u094D\u092E\u093E \u2014 \u090F\u0902\u0917\u093F\u0932\u0940 \u092A\u0941\u0932\u093E",
4852
+ bathukamma_saddula: "\u092C\u0924\u0941\u0915\u092E\u094D\u092E\u093E \u2014 \u0938\u0926\u094D\u0926\u0941\u0932\u093E",
4600
4853
  // Chhath Puja
4601
4854
  chhath_nahay_khay: "\u091B\u0920 \u2014 \u0928\u0939\u093E\u092F \u0916\u093E\u092F",
4602
4855
  chhath_kharna: "\u091B\u0920 \u2014 \u0916\u0930\u0928\u093E",
@@ -4826,7 +5079,7 @@ function getInstantPanchang(date, location, options) {
4826
5079
  isAdhika: chandramasa.isAdhika,
4827
5080
  varaIndex: vara.index,
4828
5081
  solarMasaIndex: Math.floor(siderealSun / 30) % 12,
4829
- region: options?.region ?? "all"
5082
+ region: resolveRegionAlias(options?.region)
4830
5083
  },
4831
5084
  (key) => t.festivalNames[key] ?? t.misc[key] ?? key,
4832
5085
  (idx) => resolveMasaName(idx, lang)
@@ -5011,6 +5264,21 @@ function getDailyPanchang(date, location, options) {
5011
5264
  const rashiAtSunrise = Math.floor(siderealSunAtSunrise / 30) % 12;
5012
5265
  const rashiAtNextSunrise = Math.floor(getSun(nextSunriseUtc) / 30) % 12;
5013
5266
  const sankrantiRashi = rashiAtSunrise !== rashiAtNextSunrise ? rashiAtNextSunrise : null;
5267
+ let nextDaySankrantiRashi = null;
5268
+ try {
5269
+ const tomorrowSunsetUtc = computeSunset(nextSunriseUtc, location);
5270
+ const dayAfterSunriseUtc = computeSunrise(tomorrowSunsetUtc, location);
5271
+ const rashiAtDayAfterSunrise = Math.floor(getSun(dayAfterSunriseUtc) / 30) % 12;
5272
+ if (rashiAtNextSunrise !== rashiAtDayAfterSunrise) {
5273
+ nextDaySankrantiRashi = rashiAtDayAfterSunrise;
5274
+ }
5275
+ } catch (e) {
5276
+ if (!(e instanceof PanchangError && (e.code === "NO_SUNRISE" || e.code === "NO_SUNSET"))) {
5277
+ throw e;
5278
+ }
5279
+ }
5280
+ const rashiAtYesterdaySunrise = Math.floor(getSun(yesterdaySunriseUtc) / 30) % 12;
5281
+ const prevDaySankrantiRashi = rashiAtYesterdaySunrise !== rashiAtSunrise ? rashiAtSunrise : null;
5014
5282
  let ekadashiDashamiViddha = false;
5015
5283
  if (tithiAtSunrise.index === 10 || tithiAtSunrise.index === 25) {
5016
5284
  const tithiAtArunodaya = tithiAt(arunodayaUtc);
@@ -5060,6 +5328,8 @@ function getDailyPanchang(date, location, options) {
5060
5328
  priorDayTithiByRule,
5061
5329
  nakshatraIndicesInDay,
5062
5330
  sankrantiRashi,
5331
+ nextDaySankrantiRashi,
5332
+ prevDaySankrantiRashi,
5063
5333
  ekadashiDashamiViddha,
5064
5334
  smartaDwadashiToday,
5065
5335
  moonriseInDay: moonriseInDayUtc,
@@ -5068,7 +5338,7 @@ function getDailyPanchang(date, location, options) {
5068
5338
  end: utcToLocalDisplay(bhadraUtc.end, offsetMinutes)
5069
5339
  } : null,
5070
5340
  formatClock,
5071
- region: options.region ?? "all"
5341
+ region: resolveRegionAlias(options.region)
5072
5342
  },
5073
5343
  (key) => t.festivalNames[key] ?? t.misc[key] ?? key,
5074
5344
  (idx) => resolveMasaName(idx, lang)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "panchang-ts",
3
- "version": "2.0.1",
3
+ "version": "2.1.0",
4
4
  "description": "Pure TypeScript Hindu Panchang calculations. Tithi, Nakshatra, Yoga, Karana, Vara, and more. Offline-first, React Native compatible.",
5
5
  "author": "Ishank",
6
6
  "license": "MIT",