diff --git a/src/codeblocks/dateHeader/components/dateNavigator/DateNavigator.ts b/src/codeblocks/dateHeader/DateNavigator.ts
similarity index 100%
rename from src/codeblocks/dateHeader/components/dateNavigator/DateNavigator.ts
rename to src/codeblocks/dateHeader/DateNavigator.ts
diff --git a/src/codeblocks/dateHeader/components/dateNavigator/dateNavigator.types.ts b/src/codeblocks/dateHeader/dateNavigator.types.ts
similarity index 100%
rename from src/codeblocks/dateHeader/components/dateNavigator/dateNavigator.types.ts
rename to src/codeblocks/dateHeader/dateNavigator.types.ts
diff --git a/src/codeblocks/dateHeader/components/dateNavigator/dom/buildDateNavigatorDOM.ts b/src/codeblocks/dateHeader/dom/buildDateNavigatorDOM.ts
similarity index 91%
rename from src/codeblocks/dateHeader/components/dateNavigator/dom/buildDateNavigatorDOM.ts
rename to src/codeblocks/dateHeader/dom/buildDateNavigatorDOM.ts
index bec0f51..cd25d04 100644
--- a/src/codeblocks/dateHeader/components/dateNavigator/dom/buildDateNavigatorDOM.ts
+++ b/src/codeblocks/dateHeader/dom/buildDateNavigatorDOM.ts
@@ -1,6 +1,5 @@
-// src/components/dateNavigator/dom/buildDateNavigatorDOM.ts
-import { formatDateForDisplay, parseDateISO } from "../../datePicker/datePickerUtils";
-import type { DateNavigatorDOMElements } from "../dateNavigator.types"; // Type only
+import { formatDateForDisplay, parseDateISO } from "src/helpers/dateUtils";
+import type { DateNavigatorDOMElements } from "../dateNavigator.types";
//? Structure for the handlers needed by the builder
export interface DateNavigatorHandlers {
@@ -15,7 +14,7 @@ export function buildDateNavigatorDOM(
initialIsoDate: string,
handlers: DateNavigatorHandlers
): DateNavigatorDOMElements {
- containerEl.empty(); // Clear container first
+ containerEl.empty();
const wrapper = containerEl.createDiv({ cls: "date-navigator-wrapper" });
const navRow = wrapper.createDiv({ cls: "date-nav-row" });
diff --git a/src/codeblocks/dateHeader/components/dateNavigator/eventHandlers/dateNavigationHandlers.ts b/src/codeblocks/dateHeader/eventHandlers/dateNavigationHandlers.ts
similarity index 75%
rename from src/codeblocks/dateHeader/components/dateNavigator/eventHandlers/dateNavigationHandlers.ts
rename to src/codeblocks/dateHeader/eventHandlers/dateNavigationHandlers.ts
index c959969..e93b401 100644
--- a/src/codeblocks/dateHeader/components/dateNavigator/eventHandlers/dateNavigationHandlers.ts
+++ b/src/codeblocks/dateHeader/eventHandlers/dateNavigationHandlers.ts
@@ -1,8 +1,7 @@
-// src/components/dateNavigator/eventHandlers/dateNavigationHandlers.ts
import { App } from "obsidian";
-import { DatePickerModal } from "../../datePicker/DatePickerModal";
+import { DatePickerModal } from "src/components/DatePickerModal/DatePickerModal";
import { PluginState } from "src/pluginState";
-import { parseDateISO, formatDateISO } from "../../datePicker/datePickerUtils";
+import { parseDateISO, formatDateISO } from "src/helpers/dateUtils";
import { NavigationPeriod } from "../dateNavigator.types";
/** Updates the global plugin state with the new date and triggers necessary updates */
@@ -10,13 +9,10 @@ function updateGlobalDate(newDate: Date, pluginState: PluginState, app: App): vo
const newIsoDate = formatDateISO(newDate);
if (pluginState.selectedDate !== newIsoDate) {
pluginState.selectedDate = newIsoDate;
- // Optional: Force re-render if needed, maybe make this configurable
- // app.workspace.getActiveViewOfType(MarkdownView)?.previewMode?.rerender(true);
}
- //todo: Could add dispatchEvent here for more reactive updates elsewhere
}
-/** //? Creates the handler for the "previous" button click */
+/** Creates the handler for the "previous" button click */
export function createPrevHandler(
pluginState: PluginState,
period: NavigationPeriod,
@@ -49,7 +45,6 @@ export function createNextHandler(
): () => void {
return () => {
const currentDate = parseDateISO(pluginState.selectedDate) ?? new Date();
- //& console.log(`[DateNavHandlers] Next clicked. Current: ${formatDateISO(currentDate)}, Period: ${period}`);
switch (period) {
case 'day':
currentDate.setUTCDate(currentDate.getUTCDate() + 1);
@@ -72,8 +67,6 @@ export function createOpenModalHandler(
): () => void {
return () => {
new DatePickerModal(app, pluginState.selectedDate, (newIsoDate) => {
- //? This is the callback executed when the modal confirms a selection
- //? No need to call updateGlobalDate here, modal already did via pluginState setter
updateDisplayCallback(newIsoDate);
}).open();
};
diff --git a/src/codeblocks/dateHeader/index.ts b/src/codeblocks/dateHeader/index.ts
index f09e2be..1c82ea8 100644
--- a/src/codeblocks/dateHeader/index.ts
+++ b/src/codeblocks/dateHeader/index.ts
@@ -1,6 +1,6 @@
import { MarkdownRenderChild, App } from 'obsidian';
-import { DateNavigator } from './components/dateNavigator/DateNavigator';
+import { DateNavigator } from './DateNavigator';
import { pluginState } from '../../pluginState';
/**
diff --git a/src/codeblocks/dateHeader/components/datePicker/DatePickerModal.ts b/src/components/DatePickerModal/DatePickerModal.ts
similarity index 98%
rename from src/codeblocks/dateHeader/components/datePicker/DatePickerModal.ts
rename to src/components/DatePickerModal/DatePickerModal.ts
index 26f3a26..f8ab4ea 100644
--- a/src/codeblocks/dateHeader/components/datePicker/DatePickerModal.ts
+++ b/src/components/DatePickerModal/DatePickerModal.ts
@@ -3,7 +3,7 @@ import { buildDatePickerHeader } from "./dom/buildDatePickerHeader";
import { buildWeekdayHeaders } from "./dom/buildWeekdayHeaders";
import { buildCalendarGrid } from "./dom/buildCalendarGrid";
import { buildDatePickerFooter } from "./dom/buildDatePickerFooter";
-import { formatDateISO, parseDateISO } from "./datePickerUtils";
+import { formatDateISO, parseDateISO } from "src/helpers/dateUtils";
export class DatePickerModal extends Modal {
private selectedDateObj: Date; //? Internal state as Date object
diff --git a/src/components/DatePickerModal/datePickerUtils.ts b/src/components/DatePickerModal/datePickerUtils.ts
new file mode 100644
index 0000000..e69de29
diff --git a/src/codeblocks/dateHeader/components/datePicker/dom/buildCalendarGrid.ts b/src/components/DatePickerModal/dom/buildCalendarGrid.ts
similarity index 98%
rename from src/codeblocks/dateHeader/components/datePicker/dom/buildCalendarGrid.ts
rename to src/components/DatePickerModal/dom/buildCalendarGrid.ts
index 442e22b..ea21214 100644
--- a/src/codeblocks/dateHeader/components/datePicker/dom/buildCalendarGrid.ts
+++ b/src/components/DatePickerModal/dom/buildCalendarGrid.ts
@@ -1,4 +1,4 @@
-import { getISOWeekNumber } from "../datePickerUtils";
+import { getISOWeekNumber } from "src/helpers/dateUtils";
/**
* Builds the main grid of days for the calendar month.
diff --git a/src/codeblocks/dateHeader/components/datePicker/dom/buildDatePickerFooter.ts b/src/components/DatePickerModal/dom/buildDatePickerFooter.ts
similarity index 86%
rename from src/codeblocks/dateHeader/components/datePicker/dom/buildDatePickerFooter.ts
rename to src/components/DatePickerModal/dom/buildDatePickerFooter.ts
index 24640e1..a258ac8 100644
--- a/src/codeblocks/dateHeader/components/datePicker/dom/buildDatePickerFooter.ts
+++ b/src/components/DatePickerModal/dom/buildDatePickerFooter.ts
@@ -1,5 +1,4 @@
-// src/components/datePicker/dom/buildDatePickerFooter.ts
-import { formatDateForDisplay } from "../datePickerUtils"; // Use consistent display formatting
+import { formatDateForDisplay } from "src/helpers/dateUtils";
/**
* Builds the footer section of the date picker modal (Selected Date Display, Confirm Button).
diff --git a/src/codeblocks/dateHeader/components/datePicker/dom/buildDatePickerHeader.ts b/src/components/DatePickerModal/dom/buildDatePickerHeader.ts
similarity index 100%
rename from src/codeblocks/dateHeader/components/datePicker/dom/buildDatePickerHeader.ts
rename to src/components/DatePickerModal/dom/buildDatePickerHeader.ts
diff --git a/src/codeblocks/dateHeader/components/datePicker/dom/buildWeekdayHeaders.ts b/src/components/DatePickerModal/dom/buildWeekdayHeaders.ts
similarity index 100%
rename from src/codeblocks/dateHeader/components/datePicker/dom/buildWeekdayHeaders.ts
rename to src/components/DatePickerModal/dom/buildWeekdayHeaders.ts
diff --git a/src/components/TimePickerModal.ts b/src/components/TimePickerModal.ts
deleted file mode 100644
index 8413c33..0000000
--- a/src/components/TimePickerModal.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-import { App, Modal, Notice, Setting } from "obsidian";
-
-//? A very basic example modal for selecting a time.
-export class TimePickerModal extends Modal {
- private currentTime: string; // e.g., "HH:MM"
- private onSelectCallback: (selectedTime: string) => void;
-
- constructor(app: App, initialTime: string | undefined, onSelect: (selectedTime: string) => void) {
- super(app);
- //? Basic validation or default
- this.currentTime = initialTime && /^\d{2}:\d{2}$/.test(initialTime) ? initialTime : "12:00";
- this.onSelectCallback = onSelect;
- }
-
- onOpen() {
- const { contentEl } = this;
- contentEl.empty();
- contentEl.addClass("time-picker-modal-content"); // For styling
-
- contentEl.createEl("h2", { text: "Select Time" });
-
- // --- Basic Time Input (replace with better UI later) ---
- let tempTime = this.currentTime;
- new Setting(contentEl)
- .setName("Time (HH:MM)")
- .addText(text => text
- .setValue(tempTime)
- .setPlaceholder("HH:MM")
- .onChange(value => {
- // Basic format check
- if (/^\d{1,2}:\d{1,2}$/.test(value)) {
- // Format to HH:MM
- const parts = value.split(':');
- const hh = parts[0].padStart(2,'0');
- const mm = parts[1].padStart(2,'0');
- // Basic hour/minute range check (can be improved)
- if (parseInt(hh) >= 0 && parseInt(hh) <= 23 && parseInt(mm) >= 0 && parseInt(mm) <= 59) {
- tempTime = `${hh}:${mm}`;
- } else {
- // Handle invalid range slightly? Or let confirm check.
- }
- }
- }));
-
- // --- Action Buttons ---
- new Setting(contentEl)
- .addButton(button => button
- .setButtonText("Cancel")
- .onClick(() => this.close()))
- .addButton(button => button
- .setButtonText("Confirm")
- .setCta() // Make it the primary action
- .onClick(() => {
- //? Final validation before confirming
- if (/^\d{2}:\d{2}$/.test(tempTime)) {
- this.onSelectCallback(tempTime);
- this.close();
- } else {
- new Notice("Invalid time format. Use HH:MM.");
- }
- }));
- }
-
- onClose() {
- this.contentEl.empty();
- }
-}
\ No newline at end of file
diff --git a/src/components/TimePickerModal/TimePickerModal.ts b/src/components/TimePickerModal/TimePickerModal.ts
new file mode 100644
index 0000000..ebf509c
--- /dev/null
+++ b/src/components/TimePickerModal/TimePickerModal.ts
@@ -0,0 +1,64 @@
+import { App, Modal } from "obsidian";
+import { buildTimePickerDOM, buildTimePickerActions, TimePickerDOMElements } from "./dom/buildTimePickerDOM";
+import { parseTimeString, formatTimeString } from "./timePickerUtils";
+
+export class TimePickerModal extends Modal {
+ private initialHour: number;
+ private initialMinute: number;
+ private onSelectCallback: (selectedTime: string) => void;
+
+ //? References to the dropdown elements
+ private uiElements: TimePickerDOMElements | null = null;
+
+ constructor(app: App, initialTime: string | undefined, onSelect: (selectedTime: string) => void) {
+ super(app);
+ this.onSelectCallback = onSelect;
+
+ //? Parse initial time into numbers
+ const { hour, minute } = parseTimeString(initialTime ?? ""); // Provide default if undefined
+ this.initialHour = hour;
+ this.initialMinute = minute;
+
+ }
+
+ onOpen() {
+ const { contentEl } = this;
+ contentEl.empty();
+ contentEl.addClass("time-picker-modal-content"); // For styling
+
+ contentEl.createEl("h2", { text: "Select Time" });
+
+ // --- Build Dropdowns ---
+ this.uiElements = buildTimePickerDOM(contentEl, this.initialHour, this.initialMinute);
+
+ // --- Build Actions ---
+ buildTimePickerActions(contentEl, this._handleCancel, this._handleConfirm);
+ }
+
+ // --- Handlers ---
+
+ private _handleCancel = (): void => {
+ this.close();
+ };
+
+ private _handleConfirm = (): void => {
+ if (!this.uiElements) {
+ console.error("[TimePickerModal] Cannot confirm: UI elements not found.");
+ return;
+ }
+ //? Get current values from dropdowns
+ const selectedHour = this.uiElements.hourSelect.value;
+ const selectedMinute = this.uiElements.minuteSelect.value;
+
+ //? Format the selected time
+ const selectedTime = formatTimeString(selectedHour, selectedMinute);
+
+ this.onSelectCallback(selectedTime); // Pass HH:MM string back
+ this.close();
+ };
+
+ onClose() {
+ this.contentEl.empty();
+ this.uiElements = null; // Clear references
+ }
+}
\ No newline at end of file
diff --git a/src/components/TimePickerModal/dom/buildTimePickerDOM.ts b/src/components/TimePickerModal/dom/buildTimePickerDOM.ts
new file mode 100644
index 0000000..1535bdf
--- /dev/null
+++ b/src/components/TimePickerModal/dom/buildTimePickerDOM.ts
@@ -0,0 +1,66 @@
+import { Setting } from "obsidian";
+import { createHourOptions, createMinuteOptions } from "../timePickerUtils";
+
+//? Interface for the references to the created select elements
+export interface TimePickerDOMElements {
+ hourSelect: HTMLSelectElement;
+ minuteSelect: HTMLSelectElement;
+}
+
+/**
+ * Builds the core UI elements (dropdowns) for the Time Picker Modal.
+ * @param contentEl - The HTMLElement to append the controls to.
+ * @param initialHour - The initially selected hour (0-23).
+ * @param initialMinute - The initially selected minute (0-59).
+ * @returns Object containing references to the select elements.
+ */
+export function buildTimePickerDOM(
+ contentEl: HTMLElement,
+ initialHour: number,
+ initialMinute: number
+): TimePickerDOMElements {
+
+ // Use Obsidian's Setting components for structure and alignment
+ const setting = new Setting(contentEl)
+ .setName("Select Time")
+ .setClass("time-picker-controls"); // Add class for specific styling
+
+ // --- Hour Dropdown ---
+ const hourSelect = document.createElement("select");
+ hourSelect.classList.add("dropdown", "time-picker-select", "time-picker-hour");
+ hourSelect.setAttribute("aria-label", "Hour");
+ hourSelect.appendChild(createHourOptions(initialHour)); // Populate options
+ setting.controlEl.appendChild(hourSelect); // Add to setting's control area
+
+ // --- Separator ---
+ const separator = document.createElement("span");
+ separator.textContent = ":";
+ separator.addClass("time-picker-separator");
+ setting.controlEl.appendChild(separator);
+
+ // --- Minute Dropdown ---
+ const minuteSelect = document.createElement("select");
+ minuteSelect.classList.add("dropdown", "time-picker-select", "time-picker-minute");
+ minuteSelect.setAttribute("aria-label", "Minute");
+ minuteSelect.appendChild(createMinuteOptions(initialMinute)); // Populate options
+ setting.controlEl.appendChild(minuteSelect);
+
+ return { hourSelect, minuteSelect };
+}
+
+/** Builds the action buttons (Cancel, Confirm) for the modal. */
+export function buildTimePickerActions(
+ contentEl: HTMLElement,
+ onCancel: () => void,
+ onConfirm: () => void
+): void {
+ new Setting(contentEl)
+ .setClass("time-picker-actions") // Add class for styling
+ .addButton(button => button
+ .setButtonText("Cancel")
+ .onClick(onCancel))
+ .addButton(button => button
+ .setButtonText("Confirm")
+ .setCta() // Make it the primary action
+ .onClick(onConfirm));
+}
\ No newline at end of file
diff --git a/src/components/TimePickerModal/timePickerUtils.ts b/src/components/TimePickerModal/timePickerUtils.ts
new file mode 100644
index 0000000..98b36bb
--- /dev/null
+++ b/src/components/TimePickerModal/timePickerUtils.ts
@@ -0,0 +1,60 @@
+
+/** Generates