@mrck-labs/vanaheim-shared 0.1.1 → 0.2.1

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