@mrck-labs/vanaheim-shared 0.1.1 → 0.2.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/dist/index.mjs CHANGED
@@ -112,7 +112,7 @@ function formatTotalTime(seconds) {
112
112
  }
113
113
  return `${mins}m`;
114
114
  }
115
- function formatCurrency(amount, currency, locale = "en-CH") {
115
+ function formatCurrency(amount, currency, locale = "de-CH") {
116
116
  return new Intl.NumberFormat(locale, {
117
117
  style: "currency",
118
118
  currency,
@@ -149,12 +149,12 @@ function formatDueDate(dueDate) {
149
149
  tomorrow.setDate(tomorrow.getDate() + 1);
150
150
  const dueDay = new Date(due);
151
151
  dueDay.setHours(0, 0, 0, 0);
152
- const isOverdue = dueDay < today;
152
+ const isOverdue2 = dueDay < today;
153
153
  if (dueDay.getTime() === today.getTime()) {
154
154
  return { text: "Today", isOverdue: false };
155
155
  } else if (dueDay.getTime() === tomorrow.getTime()) {
156
156
  return { text: "Tomorrow", isOverdue: false };
157
- } else if (isOverdue) {
157
+ } else if (isOverdue2) {
158
158
  const daysAgo = Math.ceil(
159
159
  (today.getTime() - dueDay.getTime()) / (1e3 * 60 * 60 * 24)
160
160
  );
@@ -296,6 +296,517 @@ function calculateFocusStats(sessions) {
296
296
  completionRate
297
297
  };
298
298
  }
299
+
300
+ // src/query/index.ts
301
+ var queryKeys = {
302
+ // -------------------------------------------------------------------------
303
+ // Expenses
304
+ // -------------------------------------------------------------------------
305
+ expenses: {
306
+ all: ["expenses"],
307
+ lists: () => [...queryKeys.expenses.all, "list"],
308
+ list: (filters) => [...queryKeys.expenses.lists(), filters],
309
+ detail: (id) => [...queryKeys.expenses.all, "detail", id]
310
+ },
311
+ // Expense Categories
312
+ expenseCategories: {
313
+ all: ["expenseCategories"],
314
+ list: () => [...queryKeys.expenseCategories.all, "list"]
315
+ },
316
+ // Expense Payments
317
+ expensePayments: {
318
+ all: ["expensePayments"],
319
+ lists: () => [...queryKeys.expensePayments.all, "list"],
320
+ list: (filters) => [...queryKeys.expensePayments.lists(), filters],
321
+ detail: (id) => [...queryKeys.expensePayments.all, "detail", id]
322
+ },
323
+ // -------------------------------------------------------------------------
324
+ // Income
325
+ // -------------------------------------------------------------------------
326
+ incomes: {
327
+ all: ["incomes"],
328
+ lists: () => [...queryKeys.incomes.all, "list"],
329
+ list: (filters) => [...queryKeys.incomes.lists(), filters],
330
+ detail: (id) => [...queryKeys.incomes.all, "detail", id]
331
+ },
332
+ // Income Categories
333
+ incomeCategories: {
334
+ all: ["incomeCategories"],
335
+ list: () => [...queryKeys.incomeCategories.all, "list"]
336
+ },
337
+ // Income Payments
338
+ incomePayments: {
339
+ all: ["incomePayments"],
340
+ lists: () => [...queryKeys.incomePayments.all, "list"],
341
+ list: (filters) => [...queryKeys.incomePayments.lists(), filters],
342
+ detail: (id) => [...queryKeys.incomePayments.all, "detail", id]
343
+ },
344
+ // Exchange Rates
345
+ exchangeRates: {
346
+ all: ["exchangeRates"],
347
+ list: () => [...queryKeys.exchangeRates.all, "list"]
348
+ },
349
+ // -------------------------------------------------------------------------
350
+ // Focus
351
+ // -------------------------------------------------------------------------
352
+ focusSessions: {
353
+ all: ["focusSessions"],
354
+ lists: () => [...queryKeys.focusSessions.all, "list"],
355
+ list: (filters) => [...queryKeys.focusSessions.lists(), filters],
356
+ today: () => [...queryKeys.focusSessions.all, "today"],
357
+ active: () => [...queryKeys.focusSessions.all, "active"],
358
+ detail: (id) => [...queryKeys.focusSessions.all, "detail", id]
359
+ },
360
+ // Focus Categories
361
+ focusCategories: {
362
+ all: ["focusCategories"],
363
+ list: () => [...queryKeys.focusCategories.all, "list"]
364
+ },
365
+ // -------------------------------------------------------------------------
366
+ // Settings
367
+ // -------------------------------------------------------------------------
368
+ settings: {
369
+ all: ["settings"],
370
+ detail: (key) => [...queryKeys.settings.all, key]
371
+ },
372
+ // -------------------------------------------------------------------------
373
+ // EF Work (Lieu Days & Links)
374
+ // -------------------------------------------------------------------------
375
+ lieuDays: {
376
+ all: ["lieuDays"],
377
+ list: () => [...queryKeys.lieuDays.all, "list"],
378
+ balance: () => [...queryKeys.lieuDays.all, "balance"],
379
+ detail: (id) => [...queryKeys.lieuDays.all, "detail", id]
380
+ },
381
+ efLinks: {
382
+ all: ["efLinks"],
383
+ list: () => [...queryKeys.efLinks.all, "list"],
384
+ detail: (id) => [...queryKeys.efLinks.all, "detail", id]
385
+ },
386
+ // -------------------------------------------------------------------------
387
+ // Banking
388
+ // -------------------------------------------------------------------------
389
+ bankConnections: {
390
+ all: ["bankConnections"],
391
+ list: () => [...queryKeys.bankConnections.all, "list"],
392
+ detail: (id) => [...queryKeys.bankConnections.all, "detail", id]
393
+ },
394
+ bankTransactions: {
395
+ all: ["bankTransactions"],
396
+ lists: () => [...queryKeys.bankTransactions.all, "list"],
397
+ list: (filters) => [...queryKeys.bankTransactions.lists(), filters],
398
+ stats: (connectionId) => [...queryKeys.bankTransactions.all, "stats", connectionId]
399
+ },
400
+ // -------------------------------------------------------------------------
401
+ // Health
402
+ // -------------------------------------------------------------------------
403
+ healthCategories: {
404
+ all: ["healthCategories"],
405
+ list: () => [...queryKeys.healthCategories.all, "list"],
406
+ detail: (id) => [...queryKeys.healthCategories.all, "detail", id]
407
+ },
408
+ healthHabits: {
409
+ all: ["healthHabits"],
410
+ lists: () => [...queryKeys.healthHabits.all, "list"],
411
+ list: (filters) => [...queryKeys.healthHabits.lists(), filters],
412
+ detail: (id) => [...queryKeys.healthHabits.all, "detail", id]
413
+ },
414
+ healthCompletions: {
415
+ all: ["healthCompletions"],
416
+ lists: () => [...queryKeys.healthCompletions.all, "list"],
417
+ list: (filters) => [...queryKeys.healthCompletions.lists(), filters],
418
+ forHabit: (habitId) => [...queryKeys.healthCompletions.all, "habit", habitId],
419
+ forDate: (date) => [...queryKeys.healthCompletions.all, "date", date]
420
+ },
421
+ healthStats: {
422
+ all: ["healthStats"],
423
+ forDate: (date) => [...queryKeys.healthStats.all, date ?? "today"]
424
+ },
425
+ // -------------------------------------------------------------------------
426
+ // Prompts
427
+ // -------------------------------------------------------------------------
428
+ promptCategories: {
429
+ all: ["promptCategories"],
430
+ list: () => [...queryKeys.promptCategories.all, "list"],
431
+ detail: (id) => [...queryKeys.promptCategories.all, "detail", id]
432
+ },
433
+ promptLabels: {
434
+ all: ["promptLabels"],
435
+ list: () => [...queryKeys.promptLabels.all, "list"],
436
+ detail: (id) => [...queryKeys.promptLabels.all, "detail", id]
437
+ },
438
+ prompts: {
439
+ all: ["prompts"],
440
+ lists: () => [...queryKeys.prompts.all, "list"],
441
+ list: (filters) => [...queryKeys.prompts.lists(), filters],
442
+ detail: (id) => [...queryKeys.prompts.all, "detail", id]
443
+ },
444
+ // -------------------------------------------------------------------------
445
+ // Training
446
+ // -------------------------------------------------------------------------
447
+ trainingActivities: {
448
+ all: ["trainingActivities"],
449
+ list: () => [...queryKeys.trainingActivities.all, "list"],
450
+ detail: (id) => [...queryKeys.trainingActivities.all, "detail", id],
451
+ byStravaType: (stravaType) => [...queryKeys.trainingActivities.all, "strava", stravaType]
452
+ },
453
+ trainingSessions: {
454
+ all: ["trainingSessions"],
455
+ lists: () => [...queryKeys.trainingSessions.all, "list"],
456
+ list: (filters) => [...queryKeys.trainingSessions.lists(), filters],
457
+ detail: (id) => [...queryKeys.trainingSessions.all, "detail", id],
458
+ byStravaId: (stravaActivityId) => [...queryKeys.trainingSessions.all, "strava", stravaActivityId]
459
+ },
460
+ plannedSessions: {
461
+ all: ["plannedSessions"],
462
+ lists: () => [...queryKeys.plannedSessions.all, "list"],
463
+ list: (filters) => [...queryKeys.plannedSessions.lists(), filters],
464
+ detail: (id) => [...queryKeys.plannedSessions.all, "detail", id],
465
+ upcoming: () => [...queryKeys.plannedSessions.all, "upcoming"]
466
+ },
467
+ races: {
468
+ all: ["races"],
469
+ lists: () => [...queryKeys.races.all, "list"],
470
+ list: (filters) => [...queryKeys.races.lists(), filters],
471
+ detail: (id) => [...queryKeys.races.all, "detail", id],
472
+ next: () => [...queryKeys.races.all, "next"]
473
+ },
474
+ trainingStats: {
475
+ all: ["trainingStats"],
476
+ forRange: (dateFrom, dateTo) => [...queryKeys.trainingStats.all, dateFrom, dateTo]
477
+ },
478
+ // Strava
479
+ strava: {
480
+ all: ["strava"],
481
+ athlete: () => [...queryKeys.strava.all, "athlete"],
482
+ connected: () => [...queryKeys.strava.all, "connected"],
483
+ activities: (options) => [...queryKeys.strava.all, "activities", options]
484
+ },
485
+ // -------------------------------------------------------------------------
486
+ // Journal
487
+ // -------------------------------------------------------------------------
488
+ journalEntries: {
489
+ all: ["journalEntries"],
490
+ lists: () => [...queryKeys.journalEntries.all, "list"],
491
+ list: (filters) => [...queryKeys.journalEntries.lists(), filters],
492
+ forDate: (date) => [...queryKeys.journalEntries.all, "date", date]
493
+ },
494
+ // Journal data (aggregated)
495
+ journalData: {
496
+ all: ["journalData"],
497
+ forDate: (date) => [...queryKeys.journalData.all, date]
498
+ },
499
+ // -------------------------------------------------------------------------
500
+ // Chat
501
+ // -------------------------------------------------------------------------
502
+ chatConversations: {
503
+ all: ["chatConversations"],
504
+ list: () => [...queryKeys.chatConversations.all, "list"],
505
+ detail: (id) => [...queryKeys.chatConversations.all, "detail", id]
506
+ },
507
+ chatMessages: {
508
+ all: ["chatMessages"],
509
+ forConversation: (conversationId) => [...queryKeys.chatMessages.all, "conversation", conversationId]
510
+ },
511
+ // -------------------------------------------------------------------------
512
+ // Google Calendar
513
+ // -------------------------------------------------------------------------
514
+ googleCalendar: {
515
+ all: ["googleCalendar"],
516
+ calendars: () => [...queryKeys.googleCalendar.all, "calendars"],
517
+ events: (calendarId, timeMin, timeMax) => [...queryKeys.googleCalendar.all, "events", calendarId, timeMin, timeMax]
518
+ },
519
+ // -------------------------------------------------------------------------
520
+ // Linear
521
+ // -------------------------------------------------------------------------
522
+ linear: {
523
+ all: ["linear"],
524
+ issues: (filters) => [...queryKeys.linear.all, "issues", filters],
525
+ projects: () => [...queryKeys.linear.all, "projects"]
526
+ }
527
+ };
528
+
529
+ // src/atoms/focus.ts
530
+ import { atom } from "jotai";
531
+ var timerStatusAtom = atom("idle");
532
+ var targetSecondsAtom = atom(25 * 60);
533
+ var elapsedSecondsAtom = atom(0);
534
+ var activeSessionAtom = atom(null);
535
+ var remainingSecondsAtom = atom((get) => {
536
+ const target = get(targetSecondsAtom);
537
+ const elapsed = get(elapsedSecondsAtom);
538
+ return Math.max(0, target - elapsed);
539
+ });
540
+ var progressAtom = atom((get) => {
541
+ const target = get(targetSecondsAtom);
542
+ const elapsed = get(elapsedSecondsAtom);
543
+ if (target === 0) return 0;
544
+ return Math.min(1, elapsed / target);
545
+ });
546
+ var formattedRemainingAtom = atom((get) => {
547
+ return formatTime(get(remainingSecondsAtom));
548
+ });
549
+ var formattedElapsedAtom = atom((get) => {
550
+ return formatTime(get(elapsedSecondsAtom));
551
+ });
552
+ var progressPercentAtom = atom((get) => {
553
+ return get(progressAtom) * 100;
554
+ });
555
+
556
+ // src/date/index.ts
557
+ function normalizeToMidnight(date) {
558
+ const d = new Date(date);
559
+ d.setHours(0, 0, 0, 0);
560
+ return d;
561
+ }
562
+ function getTodayMidnight() {
563
+ return normalizeToMidnight(/* @__PURE__ */ new Date());
564
+ }
565
+ function formatDateString(date) {
566
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
567
+ }
568
+ function getTodayString() {
569
+ return formatDateString(/* @__PURE__ */ new Date());
570
+ }
571
+ function parseLocalDate(dateStr) {
572
+ return /* @__PURE__ */ new Date(dateStr + "T00:00:00");
573
+ }
574
+ function isToday(dateStr) {
575
+ if (!dateStr) return false;
576
+ return dateStr === getTodayString();
577
+ }
578
+ function isOverdue(dateStr) {
579
+ if (!dateStr) return false;
580
+ return dateStr < getTodayString();
581
+ }
582
+ function isDueSoon(dateStr, daysThreshold = 7) {
583
+ if (!dateStr) return false;
584
+ if (isOverdue(dateStr)) return false;
585
+ const today = getTodayMidnight();
586
+ const targetDate = parseLocalDate(dateStr);
587
+ const diffMs = targetDate.getTime() - today.getTime();
588
+ const diffDays = Math.ceil(diffMs / (1e3 * 60 * 60 * 24));
589
+ return diffDays >= 0 && diffDays <= daysThreshold;
590
+ }
591
+ function addDays(dateStr, days) {
592
+ const date = parseLocalDate(dateStr);
593
+ date.setDate(date.getDate() + days);
594
+ return formatDateString(date);
595
+ }
596
+ function subtractDays(dateStr, days) {
597
+ return addDays(dateStr, -days);
598
+ }
599
+ function getYesterdayString() {
600
+ return subtractDays(getTodayString(), 1);
601
+ }
602
+ function getTomorrowString() {
603
+ return addDays(getTodayString(), 1);
604
+ }
605
+ function getStartOfDayISO(dateStr) {
606
+ const date = parseLocalDate(dateStr);
607
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate()).toISOString();
608
+ }
609
+ function getEndOfDayISO(dateStr) {
610
+ const date = parseLocalDate(dateStr);
611
+ return new Date(
612
+ date.getFullYear(),
613
+ date.getMonth(),
614
+ date.getDate(),
615
+ 23,
616
+ 59,
617
+ 59,
618
+ 999
619
+ ).toISOString();
620
+ }
621
+ function getWeekStart(date) {
622
+ const d = new Date(date);
623
+ const day = d.getDay();
624
+ const diff = d.getDate() - day + (day === 0 ? -6 : 1);
625
+ d.setDate(diff);
626
+ d.setHours(0, 0, 0, 0);
627
+ return d;
628
+ }
629
+ function getWeekEnd(weekStart) {
630
+ const d = new Date(weekStart);
631
+ d.setDate(d.getDate() + 6);
632
+ return d;
633
+ }
634
+ function getPreviousWeek(weekStart) {
635
+ const d = new Date(weekStart);
636
+ d.setDate(d.getDate() - 7);
637
+ return d;
638
+ }
639
+ function getNextWeek(weekStart) {
640
+ const d = new Date(weekStart);
641
+ d.setDate(d.getDate() + 7);
642
+ return d;
643
+ }
644
+ function getWeekStartString(baseDate = /* @__PURE__ */ new Date()) {
645
+ return formatDateString(getWeekStart(baseDate));
646
+ }
647
+ function getWeekEndString(baseDate = /* @__PURE__ */ new Date()) {
648
+ return formatDateString(getWeekEnd(getWeekStart(baseDate)));
649
+ }
650
+ function formatWeekRange(weekStart) {
651
+ const weekEnd = getWeekEnd(weekStart);
652
+ const startMonth = weekStart.toLocaleDateString("en-US", { month: "short" });
653
+ const endMonth = weekEnd.toLocaleDateString("en-US", { month: "short" });
654
+ if (startMonth === endMonth) {
655
+ return `${startMonth} ${weekStart.getDate()} - ${weekEnd.getDate()}, ${weekStart.getFullYear()}`;
656
+ }
657
+ return `${startMonth} ${weekStart.getDate()} - ${endMonth} ${weekEnd.getDate()}, ${weekStart.getFullYear()}`;
658
+ }
659
+ function formatFullDate(dateStr) {
660
+ const date = parseLocalDate(dateStr);
661
+ return date.toLocaleDateString("en-US", {
662
+ weekday: "long",
663
+ year: "numeric",
664
+ month: "long",
665
+ day: "numeric"
666
+ });
667
+ }
668
+ function formatDateLong(dateStr) {
669
+ const date = parseLocalDate(dateStr);
670
+ return date.toLocaleDateString("en-GB", {
671
+ weekday: "long",
672
+ day: "numeric",
673
+ month: "long"
674
+ });
675
+ }
676
+ function formatMonthYear(date) {
677
+ return date.toLocaleDateString("en-US", {
678
+ month: "long",
679
+ year: "numeric"
680
+ });
681
+ }
682
+ function formatTimeHHMM(date) {
683
+ const d = typeof date === "string" ? new Date(date) : date;
684
+ return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
685
+ }
686
+ function formatTimeWithSeconds(date) {
687
+ const d = typeof date === "string" ? new Date(date) : date;
688
+ return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit" });
689
+ }
690
+ function formatDateHeader(dateStr) {
691
+ const today = getTodayString();
692
+ if (dateStr < today) {
693
+ return "Overdue";
694
+ }
695
+ if (dateStr === today) {
696
+ return "Today";
697
+ }
698
+ const tomorrowStr = getTomorrowString();
699
+ if (dateStr === tomorrowStr) {
700
+ return "Tomorrow";
701
+ }
702
+ const date = parseLocalDate(dateStr);
703
+ return date.toLocaleDateString("en-US", {
704
+ weekday: "long",
705
+ month: "short",
706
+ day: "numeric"
707
+ });
708
+ }
709
+ function formatDueDateString(dateStr) {
710
+ if (!dateStr) return "No due date";
711
+ const today = getTodayString();
712
+ const tomorrowStr = getTomorrowString();
713
+ if (dateStr < today) {
714
+ const date2 = parseLocalDate(dateStr);
715
+ return `Overdue \u2022 ${date2.toLocaleDateString("en-US", { month: "short", day: "numeric" })}`;
716
+ }
717
+ if (dateStr === today) {
718
+ return "Today";
719
+ }
720
+ if (dateStr === tomorrowStr) {
721
+ return "Tomorrow";
722
+ }
723
+ const date = parseLocalDate(dateStr);
724
+ const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
725
+ const dateYear = date.getFullYear();
726
+ return date.toLocaleDateString("en-US", {
727
+ month: "short",
728
+ day: "numeric",
729
+ year: dateYear !== currentYear ? "numeric" : void 0
730
+ });
731
+ }
732
+ function formatRelativeTimeExtended(dateStr) {
733
+ const date = typeof dateStr === "string" ? new Date(dateStr) : dateStr;
734
+ const now = /* @__PURE__ */ new Date();
735
+ const diffMs = now.getTime() - date.getTime();
736
+ const diffMins = Math.floor(diffMs / 6e4);
737
+ const diffHours = Math.floor(diffMins / 60);
738
+ const diffDays = Math.floor(diffHours / 24);
739
+ if (diffMins < 1) return "Just now";
740
+ if (diffMins < 60) return `${diffMins}m ago`;
741
+ if (diffHours < 24) return `${diffHours}h ago`;
742
+ if (diffDays < 7) return `${diffDays}d ago`;
743
+ return date.toLocaleDateString();
744
+ }
745
+ function formatRelativeDueDate(dateStr, options) {
746
+ const { duePrefix = "Due", overduePrefix = "" } = options || {};
747
+ const date = parseLocalDate(dateStr);
748
+ const now = normalizeToMidnight(/* @__PURE__ */ new Date());
749
+ const diffMs = date.getTime() - now.getTime();
750
+ const diffDays = Math.round(diffMs / (1e3 * 60 * 60 * 24));
751
+ if (diffDays < 0) {
752
+ const absDays = Math.abs(diffDays);
753
+ return overduePrefix ? `${overduePrefix} ${absDays} day${absDays !== 1 ? "s" : ""} overdue` : `${absDays} day${absDays !== 1 ? "s" : ""} overdue`;
754
+ }
755
+ if (diffDays === 0) return `${duePrefix} today`;
756
+ if (diffDays === 1) return `${duePrefix} tomorrow`;
757
+ if (diffDays <= 7) return `${duePrefix} in ${diffDays} days`;
758
+ return date.toLocaleDateString("en-GB", { day: "numeric", month: "short" });
759
+ }
760
+ function formatRelativePayDate(dateStr) {
761
+ const date = parseLocalDate(dateStr);
762
+ const now = normalizeToMidnight(/* @__PURE__ */ new Date());
763
+ const diffMs = date.getTime() - now.getTime();
764
+ const diffDays = Math.round(diffMs / (1e3 * 60 * 60 * 24));
765
+ if (diffDays < 0) {
766
+ const absDays = Math.abs(diffDays);
767
+ return `${absDays} day${absDays !== 1 ? "s" : ""} ago`;
768
+ }
769
+ if (diffDays === 0) return "Today";
770
+ if (diffDays === 1) return "Tomorrow";
771
+ if (diffDays <= 7) return `In ${diffDays} days`;
772
+ return date.toLocaleDateString("en-GB", { day: "numeric", month: "short" });
773
+ }
774
+ function formatDateLocalized(date, format = "medium") {
775
+ const d = typeof date === "string" ? new Date(date) : date;
776
+ switch (format) {
777
+ case "short":
778
+ return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
779
+ case "medium":
780
+ return d.toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
781
+ case "long":
782
+ return d.toLocaleDateString("en-US", {
783
+ weekday: "long",
784
+ month: "long",
785
+ day: "numeric",
786
+ year: "numeric"
787
+ });
788
+ case "weekday":
789
+ return d.toLocaleDateString("en-US", { weekday: "short" });
790
+ default:
791
+ return d.toLocaleDateString();
792
+ }
793
+ }
794
+ function formatTimeLocalized(date, format = "short") {
795
+ const d = typeof date === "string" ? new Date(date) : date;
796
+ switch (format) {
797
+ case "short":
798
+ return d.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: true });
799
+ case "withSeconds":
800
+ return d.toLocaleTimeString("en-US", {
801
+ hour: "2-digit",
802
+ minute: "2-digit",
803
+ second: "2-digit",
804
+ hour12: true
805
+ });
806
+ default:
807
+ return d.toLocaleTimeString();
808
+ }
809
+ }
299
810
  export {
300
811
  API_URLS,
301
812
  CLOUD_AGENT_STATUSES,
@@ -313,29 +824,72 @@ export {
313
824
  LINEAR_PRIORITY_COLORS,
314
825
  LINEAR_PRIORITY_LABELS,
315
826
  SETTING_KEYS,
827
+ activeSessionAtom,
828
+ addDays,
316
829
  calculateFocusStats,
317
830
  calculateLieuBalance,
318
831
  calculateMonthlyExpenses,
319
832
  calculateMonthlyIncome,
320
833
  calculateMonthlySavings,
321
834
  calculateSavingsRate,
835
+ elapsedSecondsAtom,
322
836
  formatCurrency,
323
837
  formatDate,
838
+ formatDateHeader,
839
+ formatDateLocalized,
840
+ formatDateLong,
841
+ formatDateString,
324
842
  formatDueDate,
843
+ formatDueDateString,
844
+ formatFullDate,
845
+ formatMonthYear,
846
+ formatRelativeDueDate,
847
+ formatRelativePayDate,
325
848
  formatRelativeTime,
849
+ formatRelativeTimeExtended,
326
850
  formatTime,
851
+ formatTimeHHMM,
852
+ formatTimeLocalized,
853
+ formatTimeWithSeconds,
327
854
  formatTotalTime,
855
+ formatWeekRange,
856
+ formattedElapsedAtom,
857
+ formattedRemainingAtom,
328
858
  generateId,
329
859
  generateRandomColor,
330
860
  generateShortId,
861
+ getEndOfDayISO,
862
+ getNextWeek,
863
+ getPreviousWeek,
331
864
  getRepoName,
865
+ getStartOfDayISO,
866
+ getTodayMidnight,
867
+ getTodayString,
868
+ getTomorrowString,
869
+ getWeekEnd,
870
+ getWeekEndString,
871
+ getWeekStart,
872
+ getWeekStartString,
873
+ getYesterdayString,
874
+ isDueSoon,
332
875
  isNonEmptyString,
876
+ isOverdue,
333
877
  isPositiveNumber,
878
+ isToday,
334
879
  isValidCurrency,
335
880
  isValidEmail,
336
881
  isValidFrequency,
337
882
  isValidISODate,
338
883
  isValidUrl,
884
+ normalizeToMidnight,
885
+ parseLocalDate,
886
+ progressAtom,
887
+ progressPercentAtom,
888
+ queryKeys,
889
+ remainingSecondsAtom,
890
+ subtractDays,
891
+ targetSecondsAtom,
892
+ timerStatusAtom,
339
893
  toMonthlyAmount,
340
894
  toYearlyAmount,
341
895
  truncate