mirror of
https://github.com/kazi-aidah/sidecards.git
synced 2026-07-22 06:42:13 +00:00
Fixed Card Border Radius & Homepage Top Spacing bug
This commit is contained in:
parent
f6276b019f
commit
217a4fd4da
7 changed files with 208 additions and 341 deletions
241
main.js
241
main.js
|
|
@ -76,7 +76,7 @@ function resolveColorVarToHex(colorVar, settings) {
|
|||
return null;
|
||||
}
|
||||
function applyCardColorToElement(cardEl, colorVar, settings) {
|
||||
var _a, _b, _c, _d, _e;
|
||||
var _a, _b, _c, _d;
|
||||
const style = Number((_a = settings.cardStyle) != null ? _a : 2);
|
||||
const opacity = Number((_b = settings.cardBgOpacity) != null ? _b : 0.08);
|
||||
const borderThickness = Number((_c = settings.borderThickness) != null ? _c : 2);
|
||||
|
|
@ -90,7 +90,6 @@ function applyCardColorToElement(cardEl, colorVar, settings) {
|
|||
const hex = resolveColorVarToHex(colorVar, settings) || colorVar;
|
||||
const rgba = hexToRgba(hex, opacity);
|
||||
const borderColor = borderShadowOpacity >= 1 ? colorVar : hexToRgba(hex, borderShadowOpacity);
|
||||
const borderRadius = (_e = settings.borderRadius) != null ? _e : 6;
|
||||
if (style === 1) {
|
||||
cardEl.setCssProps({
|
||||
"border": `${borderThickness}px solid ${borderColor}`,
|
||||
|
|
@ -111,7 +110,6 @@ function applyCardColorToElement(cardEl, colorVar, settings) {
|
|||
"box-shadow": `2px 2px 0 0 ${borderColor}`
|
||||
});
|
||||
}
|
||||
cardEl.setCssProps({ "border-radius": `${borderRadius}px` });
|
||||
}
|
||||
function resolveAutoColor(content, tags, settings) {
|
||||
const rules = settings.autoColorRules;
|
||||
|
|
@ -265,7 +263,7 @@ var DateTimeModal = class extends import_obsidian.Modal {
|
|||
});
|
||||
});
|
||||
const exactPanel = contentEl.createDiv("sc-dt-panel sc-dt-panel-exact");
|
||||
exactPanel.setCssProps({ "display": "none" });
|
||||
exactPanel.addClass("sc-hidden");
|
||||
const exactInput = exactPanel.createEl("input", { type: "datetime-local", cls: "sc-dt-exact-input" });
|
||||
if (this.card.expiresAt) {
|
||||
const d = new Date(this.card.expiresAt);
|
||||
|
|
@ -281,15 +279,15 @@ var DateTimeModal = class extends import_obsidian.Modal {
|
|||
relRadio.addEventListener("change", () => {
|
||||
if (relRadio.checked) {
|
||||
this.mode = "relative";
|
||||
relPanel.setCssProps({ "display": "" });
|
||||
exactPanel.setCssProps({ "display": "none" });
|
||||
relPanel.removeClass("sc-hidden");
|
||||
exactPanel.addClass("sc-hidden");
|
||||
}
|
||||
});
|
||||
exactRadio.addEventListener("change", () => {
|
||||
if (exactRadio.checked) {
|
||||
this.mode = "exact";
|
||||
relPanel.setCssProps({ "display": "none" });
|
||||
exactPanel.setCssProps({ "display": "" });
|
||||
relPanel.addClass("sc-hidden");
|
||||
exactPanel.removeClass("sc-hidden");
|
||||
}
|
||||
});
|
||||
const actionsRow = contentEl.createDiv("sc-dt-actions-row");
|
||||
|
|
@ -352,7 +350,7 @@ var DateTimeModal = class extends import_obsidian.Modal {
|
|||
};
|
||||
|
||||
// src/utils/editor-utils.ts
|
||||
function handleKeyWrap(event, editorEl, editor, enabled = true) {
|
||||
function handleKeyWrap(event, editorEl, _editor, enabled = true) {
|
||||
if (!enabled)
|
||||
return false;
|
||||
if (event.ctrlKey || event.metaKey || event.altKey)
|
||||
|
|
@ -1090,22 +1088,18 @@ var _CardComponent = class extends import_obsidian3.Component {
|
|||
const pill = container.createDiv("sc-expiry-pill");
|
||||
pill.textContent = this.formatExpiryTimeLeft(this.card.expiresAt);
|
||||
if (this.card.status)
|
||||
pill.setCssProps({ "margin-bottom": "4px" });
|
||||
pill.addClass("sc-status-pill--with-margin");
|
||||
}
|
||||
if (this.card.status) {
|
||||
const pill = container.createDiv("sc-status-pill");
|
||||
pill.textContent = this.card.status.name;
|
||||
const statusDef = (this.store.settings.cardStatuses || []).find((s) => s.name === this.card.status.name);
|
||||
if (statusDef == null ? void 0 : statusDef.colorIndex) {
|
||||
pill.setCssProps({
|
||||
"background-color": `var(--card-color-${statusDef.colorIndex})`,
|
||||
"color": statusDef.textColor || "#000"
|
||||
});
|
||||
pill.style.backgroundColor = `var(--card-color-${statusDef.colorIndex})`;
|
||||
pill.style.color = statusDef.textColor || "#000";
|
||||
} else {
|
||||
pill.setCssProps({
|
||||
"background-color": this.card.status.color || "transparent",
|
||||
"color": this.card.status.textColor || "#000"
|
||||
});
|
||||
pill.style.backgroundColor = this.card.status.color || "transparent";
|
||||
pill.style.color = this.card.status.textColor || "#000";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1428,7 +1422,7 @@ var _CardComponent = class extends import_obsidian3.Component {
|
|||
if (todayVisible) {
|
||||
menu.addItem((item) => {
|
||||
var _a, _b;
|
||||
item.setTitle("Add to today").setIcon((_b = (_a = s.builtinCategoryIcons) == null ? void 0 : _a["today"]) != null ? _b : "calendar-check").onClick(async () => {
|
||||
item.setTitle("Add to Today").setIcon((_b = (_a = s.builtinCategoryIcons) == null ? void 0 : _a["today"]) != null ? _b : "calendar-check").onClick(async () => {
|
||||
await this.store.setCategory(this.card.id, "today");
|
||||
});
|
||||
});
|
||||
|
|
@ -1436,7 +1430,7 @@ var _CardComponent = class extends import_obsidian3.Component {
|
|||
if (tomorrowVisible) {
|
||||
menu.addItem((item) => {
|
||||
var _a, _b;
|
||||
item.setTitle("Add to tomorrow").setIcon((_b = (_a = s.builtinCategoryIcons) == null ? void 0 : _a["tomorrow"]) != null ? _b : "calendar-plus").onClick(async () => {
|
||||
item.setTitle("Add to Tomorrow").setIcon((_b = (_a = s.builtinCategoryIcons) == null ? void 0 : _a["tomorrow"]) != null ? _b : "calendar-plus").onClick(async () => {
|
||||
await this.store.setCategory(this.card.id, "tomorrow");
|
||||
});
|
||||
});
|
||||
|
|
@ -1458,13 +1452,13 @@ var _CardComponent = class extends import_obsidian3.Component {
|
|||
}
|
||||
menu.addSeparator();
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(this.card.pinned ? "Unpin" : "Pin card").setIcon("pin").onClick(async () => {
|
||||
item.setTitle(this.card.pinned ? "Unpin" : "Pin Card").setIcon("pin").onClick(async () => {
|
||||
await this.store.togglePin(this.card.id, !this.card.pinned);
|
||||
});
|
||||
});
|
||||
if (s.enableCardStatus && Array.isArray(s.cardStatuses) && s.cardStatuses.length > 0) {
|
||||
menu.addItem((item) => {
|
||||
item.setTitle("Set status").setIcon("flag").onClick(() => {
|
||||
item.setTitle("Set Status").setIcon("flag").onClick(() => {
|
||||
var _a;
|
||||
const menu2 = new import_obsidian3.Menu();
|
||||
(_a = s.cardStatuses) == null ? void 0 : _a.forEach((st) => {
|
||||
|
|
@ -1480,7 +1474,7 @@ var _CardComponent = class extends import_obsidian3.Component {
|
|||
});
|
||||
});
|
||||
menu2.addItem((i) => {
|
||||
i.setTitle("Clear status").onClick(async () => {
|
||||
i.setTitle("Clear Status").onClick(async () => {
|
||||
await this.store.setStatus(this.card.id, null);
|
||||
});
|
||||
});
|
||||
|
|
@ -1489,7 +1483,7 @@ var _CardComponent = class extends import_obsidian3.Component {
|
|||
});
|
||||
}
|
||||
menu.addItem((item) => {
|
||||
item.setTitle("Set expiry").setIcon("alarm-clock").onClick(() => {
|
||||
item.setTitle("Set Expiry").setIcon("alarm-clock").onClick(() => {
|
||||
new DateTimeModal(this.app, this.card, this.store).open();
|
||||
});
|
||||
});
|
||||
|
|
@ -1500,7 +1494,7 @@ var _CardComponent = class extends import_obsidian3.Component {
|
|||
});
|
||||
});
|
||||
menu.addItem((item) => {
|
||||
item.setTitle(this.card.notePath ? "View note" : "Create note").setIcon(this.card.notePath ? "link" : "file-plus").onClick(async () => {
|
||||
item.setTitle(this.card.notePath ? "View Note" : "Create Note").setIcon(this.card.notePath ? "link" : "file-plus").onClick(async () => {
|
||||
if (this.card.notePath) {
|
||||
const file = this.app.vault.getAbstractFileByPath(this.card.notePath);
|
||||
if (file instanceof import_obsidian3.TFile) {
|
||||
|
|
@ -2319,7 +2313,7 @@ var CardSidebarView = class extends import_obsidian4.ItemView {
|
|||
if (!baseRange.collapsed)
|
||||
return baseRange;
|
||||
const node = baseRange.startContainer;
|
||||
if (!(node instanceof Text))
|
||||
if (!(node == null ? void 0 : node.data))
|
||||
return null;
|
||||
const text = node.data;
|
||||
if (!text)
|
||||
|
|
@ -2552,7 +2546,7 @@ var CardSidebarView = class extends import_obsidian4.ItemView {
|
|||
box.createDiv({ text: "Loading cards...", cls: "sc-sidebar-loading-text" });
|
||||
this._loadingTimeout = window.setTimeout(() => this.hideLoadingOverlay(), maxMs);
|
||||
}
|
||||
hideLoadingOverlay(fadeMs = 0) {
|
||||
hideLoadingOverlay(_fadeMs = 0) {
|
||||
if (this._loadingTimeout) {
|
||||
window.clearTimeout(this._loadingTimeout);
|
||||
this._loadingTimeout = null;
|
||||
|
|
@ -2907,7 +2901,7 @@ var CardSidebarView = class extends import_obsidian4.ItemView {
|
|||
const menu = new import_obsidian4.Menu();
|
||||
menu.addItem((item) => {
|
||||
var _a;
|
||||
item.setTitle("Show tags").setChecked((_a = this.plugin.settings.sidebarShowTags) != null ? _a : true).onClick(async () => {
|
||||
item.setTitle("Show Tags").setChecked((_a = this.plugin.settings.sidebarShowTags) != null ? _a : true).onClick(async () => {
|
||||
var _a2;
|
||||
const current = (_a2 = this.plugin.settings.sidebarShowTags) != null ? _a2 : true;
|
||||
this.plugin.settings.sidebarShowTags = !current;
|
||||
|
|
@ -2917,7 +2911,7 @@ var CardSidebarView = class extends import_obsidian4.ItemView {
|
|||
});
|
||||
menu.addItem((item) => {
|
||||
var _a;
|
||||
item.setTitle("Show timestamps").setChecked((_a = this.plugin.settings.sidebarShowTimestamps) != null ? _a : this.plugin.settings.showTimestamps).onClick(async () => {
|
||||
item.setTitle("Show Timestamps").setChecked((_a = this.plugin.settings.sidebarShowTimestamps) != null ? _a : this.plugin.settings.showTimestamps).onClick(async () => {
|
||||
var _a2;
|
||||
const current = (_a2 = this.plugin.settings.sidebarShowTimestamps) != null ? _a2 : this.plugin.settings.showTimestamps;
|
||||
this.plugin.settings.sidebarShowTimestamps = !current;
|
||||
|
|
@ -3000,7 +2994,7 @@ var CardSidebarView = class extends import_obsidian4.ItemView {
|
|||
void this.renderCards();
|
||||
}, 300);
|
||||
}
|
||||
async renderCards(isManualReload = false) {
|
||||
async renderCards(_isManualReload = false) {
|
||||
var _a, _b;
|
||||
const settings = { ...this.store.settings };
|
||||
const scrollTop = ((_a = this.cardsContainer) == null ? void 0 : _a.scrollTop) || 0;
|
||||
|
|
@ -4157,8 +4151,8 @@ var QuickCardWithFilterModal = class extends import_obsidian7.Modal {
|
|||
const { contentEl } = this;
|
||||
contentEl.empty();
|
||||
contentEl.addClass("sc-quick-card-modal");
|
||||
contentEl.createEl("h2", { text: "Quick card add", cls: "sc-modal-title" });
|
||||
contentEl.createEl("h3", { text: "Card content", cls: "sc-modal-section-title" });
|
||||
contentEl.createDiv({ text: "Quick card add", cls: "sc-modal-title" });
|
||||
contentEl.createDiv({ text: "Card content", cls: "sc-modal-section-title" });
|
||||
const editorEl = contentEl.createDiv({
|
||||
cls: "sc-modal-textarea"
|
||||
});
|
||||
|
|
@ -4182,7 +4176,7 @@ var QuickCardWithFilterModal = class extends import_obsidian7.Modal {
|
|||
this.app.workspace.activeEditor = null;
|
||||
}
|
||||
});
|
||||
contentEl.createEl("h3", { text: "Color", cls: "sc-modal-section-title" });
|
||||
contentEl.createDiv({ text: "Color", cls: "sc-modal-section-title" });
|
||||
const colorContainer = contentEl.createDiv("sc-modal-color-container");
|
||||
let selectedColor = "var(--card-color-1)";
|
||||
const colors = [
|
||||
|
|
@ -4199,8 +4193,7 @@ var QuickCardWithFilterModal = class extends import_obsidian7.Modal {
|
|||
];
|
||||
colors.forEach((color, idx) => {
|
||||
const swatch = colorContainer.createDiv("sc-modal-color-swatch");
|
||||
const hex = this.resolveColor(color.var);
|
||||
swatch.setCssProps({ "background-color": hex });
|
||||
swatch.style.backgroundColor = this.resolveColor(color.var);
|
||||
swatch.title = this.store.settings.colorNames[idx] || color.name;
|
||||
if (selectedColor === color.var)
|
||||
swatch.addClass("is-selected");
|
||||
|
|
@ -4210,7 +4203,7 @@ var QuickCardWithFilterModal = class extends import_obsidian7.Modal {
|
|||
selectedColor = color.var;
|
||||
});
|
||||
});
|
||||
contentEl.createEl("h3", { text: "Tags", cls: "sc-modal-section-title" });
|
||||
contentEl.createDiv({ text: "Tags", cls: "sc-modal-section-title" });
|
||||
const tagsWrapper = contentEl.createDiv("sc-modal-tags-wrapper");
|
||||
const tagsInput = tagsWrapper.createEl("input", {
|
||||
placeholder: "Tags (comma separated)...",
|
||||
|
|
@ -4265,7 +4258,7 @@ var QuickCardWithFilterModal = class extends import_obsidian7.Modal {
|
|||
items[selectedTagIdx].click();
|
||||
}
|
||||
});
|
||||
contentEl.createEl("h3", { text: "Apply category", cls: "sc-modal-section-title" });
|
||||
contentEl.createDiv({ text: "Apply category", cls: "sc-modal-section-title" });
|
||||
const select = contentEl.createEl("select", { cls: "sc-modal-select" });
|
||||
this.getAvailableFilters().forEach((f) => {
|
||||
const opt = select.createEl("option", { value: f.value, text: f.label });
|
||||
|
|
@ -4365,10 +4358,6 @@ var SearchModal = class extends import_obsidian8.Modal {
|
|||
cls: "sc-search-input"
|
||||
});
|
||||
this.resultsContainer = contentEl.createDiv("sc-search-results");
|
||||
this.resultsContainer.setCssProps({
|
||||
"max-height": "400px",
|
||||
"overflow": "auto"
|
||||
});
|
||||
this.searchInput.focus();
|
||||
this.searchInput.addEventListener("input", () => this.renderResults());
|
||||
this.searchInput.addEventListener("keydown", (e) => this.handleKeydown(e));
|
||||
|
|
@ -4383,11 +4372,7 @@ var SearchModal = class extends import_obsidian8.Modal {
|
|||
this.searchResults.forEach((card, idx) => {
|
||||
const result = this.resultsContainer.createDiv("sc-search-result");
|
||||
result.textContent = card.content.substring(0, 100) + (card.content.length > 100 ? "..." : "");
|
||||
result.setCssProps({
|
||||
"padding": "8px",
|
||||
"cursor": "pointer",
|
||||
"border-left": `4px solid ${card.color}`
|
||||
});
|
||||
result.style.borderLeft = `4px solid ${card.color}`;
|
||||
result.dataset.index = String(idx);
|
||||
result.addEventListener("click", () => this.selectResult(card));
|
||||
result.addEventListener("mouseenter", () => {
|
||||
|
|
@ -4401,10 +4386,10 @@ var SearchModal = class extends import_obsidian8.Modal {
|
|||
els.forEach((el, idx) => {
|
||||
if (idx === this.selectedIndex) {
|
||||
el.addClass("selected");
|
||||
el.setCssProps({ "background-color": "var(--background-modifier-hover)" });
|
||||
el.addClass("sc-search-result--selected");
|
||||
} else {
|
||||
el.removeClass("selected");
|
||||
el.setCssProps({ "background-color": "" });
|
||||
el.removeClass("sc-search-result--selected");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -4504,7 +4489,7 @@ var SideCardsHomeView = class extends import_obsidian9.ItemView {
|
|||
if (!baseRange.collapsed)
|
||||
return baseRange;
|
||||
const node = baseRange.startContainer;
|
||||
if (!(node instanceof Text))
|
||||
if (!(node == null ? void 0 : node.data))
|
||||
return null;
|
||||
const text = node.data;
|
||||
if (!text)
|
||||
|
|
@ -4702,7 +4687,7 @@ var SideCardsHomeView = class extends import_obsidian9.ItemView {
|
|||
return "home";
|
||||
}
|
||||
async onOpen() {
|
||||
var _a, _b;
|
||||
var _a;
|
||||
const container = this.containerEl;
|
||||
container.empty();
|
||||
container.addClass("sc-home-container");
|
||||
|
|
@ -4711,10 +4696,8 @@ var SideCardsHomeView = class extends import_obsidian9.ItemView {
|
|||
const main = container.createDiv({ cls: "sc-home-main" });
|
||||
const maxW = (_a = this.plugin.settings.homepageMaxWidth) != null ? _a : 1e3;
|
||||
container.setCssProps({ "--sc-home-max-width": `${maxW}px` });
|
||||
const topMargin = (_b = this.plugin.settings.homepageTopMargin) != null ? _b : 70;
|
||||
container.setCssProps({ "--sc-home-top-margin": `${topMargin}px` });
|
||||
const topSection = main.createDiv({ cls: "sc-home-top" });
|
||||
topSection.createEl("h2", { text: this.plugin.settings.homepageName || "SideCards", cls: "sc-home-title" });
|
||||
topSection.createDiv({ text: this.plugin.settings.homepageName || "SideCards", cls: "sc-home-title" });
|
||||
const paletteRow = topSection.createDiv({ cls: "sc-home-palette-row" });
|
||||
if (this.plugin.settings.hideCategoryDropdown && this.plugin.settings.hideColorSwatches) {
|
||||
paletteRow.addClass("sc-hidden");
|
||||
|
|
@ -4884,7 +4867,7 @@ var SideCardsHomeView = class extends import_obsidian9.ItemView {
|
|||
item.addEventListener("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
const menu = new import_obsidian9.Menu();
|
||||
menu.addItem((i) => i.setTitle("Unpin from homepage").setIcon("pin-off").onClick(async () => {
|
||||
menu.addItem((i) => i.setTitle("Unpin from Homepage").setIcon("pin-off").onClick(async () => {
|
||||
this.plugin.settings.pinnedNotes = (this.plugin.settings.pinnedNotes || []).filter((p) => p !== file.path);
|
||||
await this.plugin.saveSettings();
|
||||
await this.renderFileList(container, "pinned");
|
||||
|
|
@ -5124,7 +5107,7 @@ var SideCardsHomeView = class extends import_obsidian9.ItemView {
|
|||
await this.renderFileList(recentList, "recent");
|
||||
this.renderCards(cardList);
|
||||
}
|
||||
renderToolbar(container, editorEl, cardList, pinnedList, recentList) {
|
||||
renderToolbar(container, _editorEl, cardList, pinnedList, recentList) {
|
||||
container.empty();
|
||||
const leftActions = container.createDiv({ cls: "sc-home-toolbar-left" });
|
||||
const searchWrap = container.createDiv({ cls: "sc-home-search-wrap" });
|
||||
|
|
@ -5190,7 +5173,7 @@ var SideCardsHomeView = class extends import_obsidian9.ItemView {
|
|||
const menu = new import_obsidian9.Menu();
|
||||
menu.addItem((item) => {
|
||||
var _a;
|
||||
item.setTitle("Show tags").setChecked((_a = this.plugin.settings.homeShowTags) != null ? _a : true).onClick(async () => {
|
||||
item.setTitle("Show Tags").setChecked((_a = this.plugin.settings.homeShowTags) != null ? _a : true).onClick(async () => {
|
||||
var _a2;
|
||||
const current = (_a2 = this.plugin.settings.homeShowTags) != null ? _a2 : true;
|
||||
this.plugin.settings.homeShowTags = !current;
|
||||
|
|
@ -5200,7 +5183,7 @@ var SideCardsHomeView = class extends import_obsidian9.ItemView {
|
|||
});
|
||||
menu.addItem((item) => {
|
||||
var _a;
|
||||
item.setTitle("Show timestamps").setChecked((_a = this.plugin.settings.homeShowTimestamps) != null ? _a : this.plugin.settings.showTimestamps).onClick(async () => {
|
||||
item.setTitle("Show Timestamps").setChecked((_a = this.plugin.settings.homeShowTimestamps) != null ? _a : this.plugin.settings.showTimestamps).onClick(async () => {
|
||||
var _a2;
|
||||
const current = (_a2 = this.plugin.settings.homeShowTimestamps) != null ? _a2 : this.plugin.settings.showTimestamps;
|
||||
this.plugin.settings.homeShowTimestamps = !current;
|
||||
|
|
@ -5377,7 +5360,7 @@ var SideCardsHomeView = class extends import_obsidian9.ItemView {
|
|||
return [];
|
||||
}
|
||||
}
|
||||
async createCardFromHomeInput(editorEl, cardList) {
|
||||
async createCardFromHomeInput(editorEl, _cardList) {
|
||||
var _a;
|
||||
const content = (_a = editorEl.textContent) == null ? void 0 : _a.trim();
|
||||
if (!content)
|
||||
|
|
@ -5563,9 +5546,9 @@ var SideCardsPlugin = class extends import_obsidian10.Plugin {
|
|||
return false;
|
||||
}
|
||||
});
|
||||
this.addRibbonIcon("home", "Open homepage", () => void this.activateHomeView());
|
||||
this.addRibbonIcon("rows-3", "Open sidebar", () => void this.activateView());
|
||||
this.addRibbonIcon("rectangle-horizontal", "Add card", () => new QuickCardWithFilterModal(this.app, this, this.store).open());
|
||||
this.addRibbonIcon("home", "Open Homepage", () => void this.activateHomeView());
|
||||
this.addRibbonIcon("rows-3", "Open Sidebar", () => void this.activateView());
|
||||
this.addRibbonIcon("rectangle-horizontal", "Add Card", () => new QuickCardWithFilterModal(this.app, this, this.store).open());
|
||||
this.addSettingTab(new SideCardsSettingTab(this.app, this));
|
||||
this.registerEvent(
|
||||
this.app.vault.on("rename", (file, oldPath) => {
|
||||
|
|
@ -5626,6 +5609,7 @@ var SideCardsPlugin = class extends import_obsidian10.Plugin {
|
|||
this.injectStatusColors();
|
||||
this.applyButtonPadding();
|
||||
this.applyMaxCardHeight();
|
||||
this.applyHomepageTopMargin();
|
||||
this.registerDomEvent(document, "dragover", (ev) => {
|
||||
if (!ev.dataTransfer)
|
||||
return;
|
||||
|
|
@ -5728,6 +5712,11 @@ var SideCardsPlugin = class extends import_obsidian10.Plugin {
|
|||
document.body.removeClass("sc-max-card-height-active");
|
||||
}
|
||||
}
|
||||
applyHomepageTopMargin() {
|
||||
var _a;
|
||||
const topMargin = (_a = this.settings.homepageTopMargin) != null ? _a : 70;
|
||||
document.documentElement.style.setProperty("--sc-home-top-margin", `${topMargin}px`);
|
||||
}
|
||||
injectStatusColors() {
|
||||
}
|
||||
async activateView() {
|
||||
|
|
@ -5783,7 +5772,7 @@ var SideCardsPlugin = class extends import_obsidian10.Plugin {
|
|||
if (!baseRange.collapsed)
|
||||
return baseRange;
|
||||
const node = baseRange.startContainer;
|
||||
if (!(node instanceof Text))
|
||||
if (!(node == null ? void 0 : node.data))
|
||||
return null;
|
||||
const text = node.data;
|
||||
if (!text)
|
||||
|
|
@ -6165,27 +6154,31 @@ var SideCardsSettingTab = class extends import_obsidian10.PluginSettingTab {
|
|||
}
|
||||
};
|
||||
new import_obsidian10.Setting(containerEl).setName("Latest release notes").setDesc("View the most recent plugin release notes.").addButton((b) => {
|
||||
b.setButtonText("Open changelog").onClick(() => {
|
||||
b.setButtonText("Open Changelog").onClick(() => {
|
||||
new ChangelogModal(this.app, this.plugin).open();
|
||||
});
|
||||
});
|
||||
new import_obsidian10.Setting(containerEl).setName("Storage folder").setDesc("Choose where to save notes created from cards.").addSearch((cb) => {
|
||||
cb.setPlaceholder("Choose a folder").setValue(this.plugin.settings.storageFolder || "").onChange(async (value) => {
|
||||
const newFolder = value.trim();
|
||||
const oldFolder = this.plugin.settings.storageFolder;
|
||||
this.plugin.settings.storageFolder = newFolder;
|
||||
this.plugin.settings.tutorialShown = true;
|
||||
await this.plugin.saveSettings();
|
||||
if (newFolder !== oldFolder) {
|
||||
await this.plugin.store.switchStorageFolder(newFolder);
|
||||
}
|
||||
new import_obsidian10.Setting(containerEl).setName("Storage folder").setDesc("Choose where to save notes created from cards.").addButton((b) => {
|
||||
var _a;
|
||||
b.setButtonText(((_a = this.plugin.settings.storageFolder) == null ? void 0 : _a.trim()) ? this.plugin.settings.storageFolder : "Unset").onClick(() => {
|
||||
const folders = this.app.vault.getAllLoadedFiles().filter((f) => f instanceof import_obsidian10.TFolder).map((f) => f.path).sort();
|
||||
const suggest = new FolderSuggestModal(this.app, folders, async (folder) => {
|
||||
var _a2;
|
||||
const newFolder = folder || "";
|
||||
const oldFolder = this.plugin.settings.storageFolder;
|
||||
this.plugin.settings.storageFolder = newFolder;
|
||||
this.plugin.settings.tutorialShown = true;
|
||||
await this.plugin.saveSettings();
|
||||
if (newFolder !== oldFolder) {
|
||||
await this.plugin.store.switchStorageFolder(newFolder);
|
||||
}
|
||||
b.setButtonText(((_a2 = this.plugin.settings.storageFolder) == null ? void 0 : _a2.trim()) ? this.plugin.settings.storageFolder : "Unset");
|
||||
refreshSidebarCards();
|
||||
refreshHomepage();
|
||||
});
|
||||
suggest.setPlaceholder("Select storage folder...");
|
||||
suggest.open();
|
||||
});
|
||||
const folders = /* @__PURE__ */ new Set(["/"]);
|
||||
this.app.vault.getAllLoadedFiles().forEach((file) => {
|
||||
if (file.parent)
|
||||
folders.add(file.parent.path);
|
||||
});
|
||||
new FolderSuggest(this.app, cb.inputEl, folders);
|
||||
});
|
||||
new import_obsidian10.Setting(containerEl).setName("Behaviour").setDesc("").setHeading();
|
||||
new import_obsidian10.Setting(containerEl).setName("Note title format").setDesc("Format used when creating a note from a card.").addDropdown((dd) => dd.addOption("words3_hhmm", "First 3 words + hhmm").addOption("words5_hhmm", "First 5 words + hhmm").addOption("datetime", "Date and time").setValue(this.plugin.settings.noteTitleFormat || "words3_hhmm").onChange(async (value) => {
|
||||
|
|
@ -6307,9 +6300,7 @@ var SideCardsSettingTab = class extends import_obsidian10.PluginSettingTab {
|
|||
this.plugin.settings.homepageTopMargin = value;
|
||||
label.textContent = `${value}px`;
|
||||
await this.plugin.saveSettings();
|
||||
document.querySelectorAll(".sc-home-container").forEach((el) => {
|
||||
el.setCssProps({ "--sc-home-top-margin": `${value}px` });
|
||||
});
|
||||
document.documentElement.style.setProperty("--sc-home-top-margin", `${value}px`);
|
||||
});
|
||||
slider.sliderEl.insertAdjacentElement("afterend", label);
|
||||
});
|
||||
|
|
@ -7282,13 +7273,13 @@ var SideCardsSettingTab = class extends import_obsidian10.PluginSettingTab {
|
|||
);
|
||||
};
|
||||
renderStatusConfig();
|
||||
new import_obsidian10.Setting(containerEl).setName("Data management").setHeading();
|
||||
new import_obsidian10.Setting(containerEl).setName("Export data").setDesc("Download all cards as a JSON file.").addButton((btn) => btn.setButtonText("Export data").onClick(() => {
|
||||
new import_obsidian10.Setting(containerEl).setName("Data Management").setHeading();
|
||||
new import_obsidian10.Setting(containerEl).setName("Export Data").setDesc("Download all cards as a JSON file.").addButton((btn) => btn.setButtonText("Export Data").onClick(() => {
|
||||
const cards = this.plugin.store.getAll().map((c) => c.toJSON());
|
||||
const payload = JSON.stringify({ version: 1, exportedAt: new Date().toISOString(), cards }, null, 2);
|
||||
const blob = new Blob([payload], { type: "application/json" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const a = document.createElement("a");
|
||||
const a = containerEl.createEl("a");
|
||||
a.href = url;
|
||||
a.download = `sidecards-export-${new Date().toISOString().slice(0, 10)}.json`;
|
||||
document.body.appendChild(a);
|
||||
|
|
@ -7297,8 +7288,8 @@ var SideCardsSettingTab = class extends import_obsidian10.PluginSettingTab {
|
|||
URL.revokeObjectURL(url);
|
||||
new import_obsidian10.Notice("Cards exported.");
|
||||
}));
|
||||
new import_obsidian10.Setting(containerEl).setName("Import data").setDesc("Import cards from a previously exported JSON file. Existing cards with the same ID will be skipped.").addButton((btn) => btn.setButtonText("Import data").onClick(() => {
|
||||
const input = document.createElement("input");
|
||||
new import_obsidian10.Setting(containerEl).setName("Import Data").setDesc("Import cards from a previously exported JSON file.").addButton((btn) => btn.setButtonText("Import Data").onClick(() => {
|
||||
const input = containerEl.createEl("input");
|
||||
input.type = "file";
|
||||
input.accept = ".json,application/json";
|
||||
input.addEventListener("change", () => {
|
||||
|
|
@ -7469,74 +7460,20 @@ var ChangelogModal = class extends import_obsidian10.Modal {
|
|||
this.contentEl.empty();
|
||||
}
|
||||
};
|
||||
var FolderSuggest = class {
|
||||
constructor(app, inputEl, folders) {
|
||||
this.app = app;
|
||||
this.inputEl = inputEl;
|
||||
var _a;
|
||||
this.folders = Array.from(folders).sort();
|
||||
this.suggestEl = document.createElement("div");
|
||||
this.suggestEl.className = "suggestion-container sc-folder-suggest";
|
||||
(_a = this.inputEl.parentElement) == null ? void 0 : _a.appendChild(this.suggestEl);
|
||||
this.inputEl.addEventListener("click", () => this.onFocus());
|
||||
this.inputEl.addEventListener("input", () => this.onInput());
|
||||
document.addEventListener("click", (event) => this.onClick(event));
|
||||
var FolderSuggestModal = class extends import_obsidian10.FuzzySuggestModal {
|
||||
constructor(app, folders, onChoose) {
|
||||
super(app);
|
||||
this.folders = folders;
|
||||
this.onChoose = onChoose;
|
||||
}
|
||||
onFocus() {
|
||||
var _a;
|
||||
const foldersSet = /* @__PURE__ */ new Set(["/"]);
|
||||
const vaultWithRoot = this.app.vault;
|
||||
const root = (_a = vaultWithRoot.getRoot) == null ? void 0 : _a.call(vaultWithRoot);
|
||||
const walk = (node) => {
|
||||
if (!node)
|
||||
return;
|
||||
const children = node.children || [];
|
||||
for (const c of children) {
|
||||
if (c && c.path && c.children) {
|
||||
foldersSet.add(c.path || "/");
|
||||
walk(c);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (root)
|
||||
walk(root);
|
||||
try {
|
||||
this.app.vault.getAllLoadedFiles().forEach((file) => {
|
||||
if (file && file.parent)
|
||||
foldersSet.add(file.parent.path);
|
||||
});
|
||||
} catch (e) {
|
||||
}
|
||||
this.folders = Array.from(foldersSet).sort();
|
||||
this.updateSuggestions();
|
||||
this.suggestEl.addClass("is-visible");
|
||||
getItems() {
|
||||
return this.folders;
|
||||
}
|
||||
onInput() {
|
||||
this.updateSuggestions();
|
||||
getItemText(item) {
|
||||
return item;
|
||||
}
|
||||
onClick(event) {
|
||||
const target = event.target;
|
||||
if (!target)
|
||||
return;
|
||||
if (!this.inputEl.contains(target) && !this.suggestEl.contains(target)) {
|
||||
this.suggestEl.removeClass("is-visible");
|
||||
}
|
||||
}
|
||||
updateSuggestions() {
|
||||
const inputValue = this.inputEl.value.toLowerCase();
|
||||
this.suggestEl.empty();
|
||||
const filtered = this.folders.filter((folder) => folder.toLowerCase().includes(inputValue)).slice(0, 100);
|
||||
filtered.forEach((folder) => {
|
||||
const item = document.createElement("div");
|
||||
item.className = "suggestion-item sc-folder-suggest-item";
|
||||
item.textContent = folder;
|
||||
item.addEventListener("click", () => {
|
||||
this.inputEl.value = folder;
|
||||
this.inputEl.dispatchEvent(new Event("input"));
|
||||
this.suggestEl.removeClass("is-visible");
|
||||
});
|
||||
this.suggestEl.appendChild(item);
|
||||
});
|
||||
onChooseItem(item, evt) {
|
||||
void Promise.resolve(this.onChoose(item));
|
||||
}
|
||||
};
|
||||
var SidecardsIconPickerModal = class extends import_obsidian10.Modal {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
import { Plugin, PluginSettingTab, App, Setting, WorkspaceLeaf, setIcon, Notice, TFile, Platform, requestUrl, Component, MarkdownRenderer, Modal, getIconIds, MarkdownView, activeDocument, activeWindow, Text } from "obsidian";
|
||||
import { Plugin, PluginSettingTab, App, Setting, WorkspaceLeaf, setIcon, Notice, TFile, Platform, requestUrl, Component, MarkdownRenderer, Modal, getIconIds, MarkdownView, FuzzySuggestModal, TFolder } from "obsidian";
|
||||
import { CardSidebarView } from "../views/CardSidebarView";
|
||||
import { CardStore } from "../services/CardStore";
|
||||
import { FilterService } from "../services/FilterService";
|
||||
|
|
@ -20,7 +20,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
|
||||
async onload() {
|
||||
await this.loadSettings();
|
||||
(activeDocument.documentElement).setCssProps({
|
||||
(document.documentElement).setCssProps({
|
||||
'--card-color-1': this.settings.color1 || '#8392a4',
|
||||
'--card-color-2': this.settings.color2 || '#eb3b5a',
|
||||
'--card-color-3': this.settings.color3 || '#fa8231',
|
||||
|
|
@ -117,7 +117,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
id: 'custom-wrap-comment',
|
||||
name: 'Wrap with comment %% (any focused editable)',
|
||||
checkCallback: (checking: boolean) => {
|
||||
const activeEl = activeDocument.activeElement;
|
||||
const activeEl = document.activeElement;
|
||||
if (activeEl instanceof HTMLElement && activeEl.isContentEditable) {
|
||||
if (!checking) {
|
||||
this.wrapWith('%%', '%%');
|
||||
|
|
@ -132,7 +132,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
id: 'custom-wrap-bold',
|
||||
name: 'Wrap with **bold**',
|
||||
checkCallback: (checking: boolean) => {
|
||||
const activeEl = activeDocument.activeElement;
|
||||
const activeEl = document.activeElement;
|
||||
if (activeEl instanceof HTMLElement && activeEl.isContentEditable) {
|
||||
if (!checking) {
|
||||
this.wrapWith('**', '**');
|
||||
|
|
@ -147,7 +147,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
id: 'custom-wrap-italic',
|
||||
name: 'Wrap with *italic*',
|
||||
checkCallback: (checking: boolean) => {
|
||||
const activeEl = activeDocument.activeElement;
|
||||
const activeEl = document.activeElement;
|
||||
if (activeEl instanceof HTMLElement && activeEl.isContentEditable) {
|
||||
if (!checking) {
|
||||
this.wrapWith('*', '*');
|
||||
|
|
@ -162,7 +162,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
id: 'custom-wrap-highlight',
|
||||
name: 'Wrap with ==highlight==',
|
||||
checkCallback: (checking: boolean) => {
|
||||
const activeEl = activeDocument.activeElement;
|
||||
const activeEl = document.activeElement;
|
||||
if (activeEl instanceof HTMLElement && activeEl.isContentEditable) {
|
||||
if (!checking) {
|
||||
this.wrapWith('==', '==');
|
||||
|
|
@ -240,9 +240,10 @@ export default class SideCardsPlugin extends Plugin {
|
|||
this.injectStatusColors();
|
||||
this.applyButtonPadding();
|
||||
this.applyMaxCardHeight();
|
||||
this.applyHomepageTopMargin();
|
||||
|
||||
// Allow drop on any element — needed so the browser accepts the drop
|
||||
this.registerDomEvent(activeDocument, 'dragover', (ev: DragEvent) => {
|
||||
this.registerDomEvent(document, 'dragover', (ev: DragEvent) => {
|
||||
if (!ev.dataTransfer) return;
|
||||
const types = Array.from(ev.dataTransfer.types || []);
|
||||
if (!types.includes('text/x-card-sidebar')) return;
|
||||
|
|
@ -301,8 +302,8 @@ export default class SideCardsPlugin extends Plugin {
|
|||
mdView.editor.replaceSelection(content);
|
||||
mdView.editor.focus();
|
||||
};
|
||||
activeDocument.addEventListener('drop', cardDropHandler, true /* capture */);
|
||||
(this as unknown as { _cardDropCleanup?: () => void })._cardDropCleanup = () => activeDocument.removeEventListener('drop', cardDropHandler, true);
|
||||
document.addEventListener('drop', cardDropHandler, true /* capture */);
|
||||
(this as unknown as { _cardDropCleanup?: () => void })._cardDropCleanup = () => document.removeEventListener('drop', cardDropHandler, true);
|
||||
|
||||
// Auto-open sidebar on startup; show setup modal if no storage folder set
|
||||
this.app.workspace.onLayoutReady(() => {
|
||||
|
|
@ -325,7 +326,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
|
||||
applyButtonPadding(): void {
|
||||
const paddingPx = this.settings.buttonPaddingBottom ?? 26;
|
||||
(activeDocument.documentElement).setCssProps({
|
||||
(document.documentElement).setCssProps({
|
||||
'--sc-button-padding-bottom': `${paddingPx}px`
|
||||
});
|
||||
}
|
||||
|
|
@ -333,14 +334,19 @@ export default class SideCardsPlugin extends Plugin {
|
|||
applyMaxCardHeight(): void {
|
||||
const h = this.settings.maxCardHeight;
|
||||
if (h && h > 0) {
|
||||
activeDocument.documentElement.setCssProps({ '--sc-max-card-height': `${h}px` });
|
||||
activeDocument.body.addClass('sc-max-card-height-active');
|
||||
document.documentElement.setCssProps({ '--sc-max-card-height': `${h}px` });
|
||||
document.body.addClass('sc-max-card-height-active');
|
||||
} else {
|
||||
activeDocument.documentElement.style.removeProperty('--sc-max-card-height');
|
||||
activeDocument.body.removeClass('sc-max-card-height-active');
|
||||
document.documentElement.style.removeProperty('--sc-max-card-height');
|
||||
document.body.removeClass('sc-max-card-height-active');
|
||||
}
|
||||
}
|
||||
|
||||
applyHomepageTopMargin(): void {
|
||||
const topMargin = this.settings.homepageTopMargin ?? 70;
|
||||
document.documentElement.style.setProperty('--sc-home-top-margin', `${topMargin}px`);
|
||||
}
|
||||
|
||||
injectStatusColors(): void {
|
||||
// We now apply status colors directly to elements in CardComponent
|
||||
}
|
||||
|
|
@ -366,7 +372,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
}
|
||||
|
||||
private wrapWith(start: string, end: string) {
|
||||
const activeEl = activeDocument.activeElement;
|
||||
const activeEl = document.activeElement;
|
||||
if (!(activeEl instanceof HTMLElement) || activeEl.isContentEditable !== true) {
|
||||
new Notice('No editable field focused');
|
||||
return;
|
||||
|
|
@ -390,10 +396,10 @@ export default class SideCardsPlugin extends Plugin {
|
|||
const wrapped = start + text + end;
|
||||
|
||||
range.deleteContents();
|
||||
range.insertNode(activeDocument.createTextNode(wrapped));
|
||||
range.insertNode(document.createTextNode(wrapped));
|
||||
|
||||
// Optional: place caret inside the wrapped text
|
||||
const newRange = activeDocument.createRange();
|
||||
const newRange = document.createRange();
|
||||
newRange.setStart(range.startContainer, range.startOffset + start.length);
|
||||
newRange.collapse(true);
|
||||
sel.removeAllRanges();
|
||||
|
|
@ -408,8 +414,8 @@ export default class SideCardsPlugin extends Plugin {
|
|||
if (!selection.rangeCount) return null;
|
||||
const baseRange = selection.getRangeAt(0);
|
||||
if (!baseRange.collapsed) return baseRange;
|
||||
const node = baseRange.startContainer;
|
||||
if (!node.instanceOf(Text)) return null;
|
||||
const node = baseRange.startContainer as Text;
|
||||
if (!node?.data) return null;
|
||||
const text = node.data;
|
||||
if (!text) return null;
|
||||
const offset = baseRange.startOffset;
|
||||
|
|
@ -420,7 +426,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
let end = offset;
|
||||
while (start > 0 && this.isWordChar(text[start - 1])) start--;
|
||||
while (end < text.length && this.isWordChar(text[end])) end++;
|
||||
const wordRange = activeDocument.createRange();
|
||||
const wordRange = document.createRange();
|
||||
wordRange.setStart(node, start);
|
||||
wordRange.setEnd(node, end);
|
||||
return wordRange;
|
||||
|
|
@ -511,7 +517,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
|
||||
folderInput.addEventListener('focus', () => renderSuggestions(folderInput.value));
|
||||
folderInput.addEventListener('input', () => renderSuggestions(folderInput.value));
|
||||
folderInput.addEventListener('blur', () => activeWindow.setTimeout(() => suggestEl.removeClass('is-visible'), 150));
|
||||
folderInput.addEventListener('blur', () => window.setTimeout(() => suggestEl.removeClass('is-visible'), 150));
|
||||
|
||||
const btnRow = content.createDiv({ cls: 'sc-setup-btn-row' });
|
||||
|
||||
|
|
@ -537,7 +543,7 @@ export default class SideCardsPlugin extends Plugin {
|
|||
});
|
||||
|
||||
modal.open();
|
||||
activeWindow.setTimeout(() => folderInput.focus(), 50);
|
||||
window.setTimeout(() => folderInput.focus(), 50);
|
||||
}
|
||||
|
||||
async fetchAllReleases(): Promise<Array<{ name?: string; tag_name?: string; published_at?: string; created_at?: string; body?: string }>> {
|
||||
|
|
@ -579,7 +585,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
}
|
||||
|
||||
private updateCSSVariables(): void {
|
||||
const root = activeDocument.documentElement;
|
||||
const root = document.documentElement;
|
||||
root.setCssProps({
|
||||
'--card-color-1': this.plugin.settings.color1 || '#8392a4',
|
||||
'--card-color-2': this.plugin.settings.color2 || '#eb3b5a',
|
||||
|
|
@ -613,7 +619,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
if (hex && hex.startsWith('var')) {
|
||||
const varName = hex.match(/--[a-zA-Z0-9-]+/)?.[0];
|
||||
if (varName) {
|
||||
hex = getComputedStyle(activeDocument.documentElement).getPropertyValue(varName).trim();
|
||||
hex = getComputedStyle(document.documentElement).getPropertyValue(varName).trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -691,8 +697,8 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
const rect = row.getBoundingClientRect();
|
||||
offsetY = e.clientY - rect.top;
|
||||
|
||||
activeDocument.addEventListener('pointermove', onPointerMove, { passive: false });
|
||||
activeDocument.addEventListener('pointerup', onPointerUp);
|
||||
document.addEventListener('pointermove', onPointerMove, { passive: false });
|
||||
document.addEventListener('pointerup', onPointerUp);
|
||||
// Don't preventDefault yet — let clicks through until threshold
|
||||
};
|
||||
|
||||
|
|
@ -725,7 +731,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
boxShadow: '0 4px 16px rgba(0,0,0,0.25)',
|
||||
opacity: '0.9',
|
||||
});
|
||||
activeDocument.body.appendChild(ghost);
|
||||
document.body.appendChild(ghost);
|
||||
draggedEl!.setCssProps({ 'opacity': '0.3' });
|
||||
}
|
||||
|
||||
|
|
@ -754,8 +760,8 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
};
|
||||
|
||||
const onPointerUp = (e: PointerEvent) => {
|
||||
activeDocument.removeEventListener('pointermove', onPointerMove);
|
||||
activeDocument.removeEventListener('pointerup', onPointerUp);
|
||||
document.removeEventListener('pointermove', onPointerMove);
|
||||
document.removeEventListener('pointerup', onPointerUp);
|
||||
|
||||
getRows().forEach(row => row.removeClass('sc-drag-over-top', 'sc-drag-over-bottom'));
|
||||
|
||||
|
|
@ -779,8 +785,8 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
container.addEventListener('pointerdown', onPointerDown);
|
||||
return () => {
|
||||
container.removeEventListener('pointerdown', onPointerDown);
|
||||
activeDocument.removeEventListener('pointermove', onPointerMove);
|
||||
activeDocument.removeEventListener('pointerup', onPointerUp);
|
||||
document.removeEventListener('pointermove', onPointerMove);
|
||||
document.removeEventListener('pointerup', onPointerUp);
|
||||
ghost?.remove();
|
||||
if (draggedEl) draggedEl.setCssProps({ 'opacity': '' });
|
||||
};
|
||||
|
|
@ -841,22 +847,29 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
new Setting(containerEl)
|
||||
.setName('Storage folder')
|
||||
.setDesc('Choose where to save notes created from cards.')
|
||||
.addSearch(cb => {
|
||||
cb.setPlaceholder('Choose a folder')
|
||||
.setValue(this.plugin.settings.storageFolder || '')
|
||||
.onChange(async (value) => {
|
||||
const newFolder = value.trim();
|
||||
const oldFolder = this.plugin.settings.storageFolder;
|
||||
this.plugin.settings.storageFolder = newFolder;
|
||||
this.plugin.settings.tutorialShown = true;
|
||||
await this.plugin.saveSettings();
|
||||
if (newFolder !== oldFolder) {
|
||||
await this.plugin.store.switchStorageFolder(newFolder);
|
||||
}
|
||||
.addButton(b => {
|
||||
b.setButtonText(this.plugin.settings.storageFolder?.trim() ? this.plugin.settings.storageFolder : 'Unset')
|
||||
.onClick(() => {
|
||||
const folders = this.app.vault.getAllLoadedFiles()
|
||||
.filter((f): f is TFolder => f instanceof TFolder)
|
||||
.map(f => f.path)
|
||||
.sort();
|
||||
const suggest = new FolderSuggestModal(this.app, folders, async (folder) => {
|
||||
const newFolder = folder || '';
|
||||
const oldFolder = this.plugin.settings.storageFolder;
|
||||
this.plugin.settings.storageFolder = newFolder;
|
||||
this.plugin.settings.tutorialShown = true;
|
||||
await this.plugin.saveSettings();
|
||||
if (newFolder !== oldFolder) {
|
||||
await this.plugin.store.switchStorageFolder(newFolder);
|
||||
}
|
||||
b.setButtonText(this.plugin.settings.storageFolder?.trim() ? this.plugin.settings.storageFolder : 'Unset');
|
||||
refreshSidebarCards();
|
||||
refreshHomepage();
|
||||
});
|
||||
suggest.setPlaceholder('Select storage folder...');
|
||||
suggest.open();
|
||||
});
|
||||
const folders = new Set<string>(['/']);
|
||||
this.app.vault.getAllLoadedFiles().forEach((file) => { if (file.parent) folders.add(file.parent.path); });
|
||||
new FolderSuggest(this.app, cb.inputEl, folders);
|
||||
});
|
||||
|
||||
// ── Behaviour ─────────────────────────────────────────────────────────────
|
||||
|
|
@ -1038,7 +1051,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
label.textContent = `${value}px`;
|
||||
await this.plugin.saveSettings();
|
||||
// Apply live to open homepage views
|
||||
activeDocument.querySelectorAll('.sc-home-container').forEach((el) => {
|
||||
document.querySelectorAll('.sc-home-container').forEach((el) => {
|
||||
(el as HTMLElement).setCssProps({ '--sc-home-max-width': `${value}px` });
|
||||
});
|
||||
});
|
||||
|
|
@ -1059,9 +1072,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
this.plugin.settings.homepageTopMargin = value;
|
||||
label.textContent = `${value}px`;
|
||||
await this.plugin.saveSettings();
|
||||
activeDocument.querySelectorAll('.sc-home-container').forEach((el) => {
|
||||
(el as HTMLElement).setCssProps({ '--sc-home-top-margin': `${value}px` });
|
||||
});
|
||||
document.documentElement.style.setProperty('--sc-home-top-margin', `${value}px`);
|
||||
});
|
||||
slider.sliderEl.insertAdjacentElement('afterend', label);
|
||||
});
|
||||
|
|
@ -1079,7 +1090,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
previewCard.className = 'sc-card';
|
||||
previewCard.addClass(`sc-style-${settings.cardStyle || 2}`);
|
||||
const color1 = settings.color1 || '#8392a4';
|
||||
const root = activeDocument.documentElement;
|
||||
const root = document.documentElement;
|
||||
root.setCssProps({ '--card-color-1': color1 });
|
||||
previewCard.setCssProps({
|
||||
'border-radius': `${settings.borderRadius || 0}px`,
|
||||
|
|
@ -1142,7 +1153,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
new Setting(containerEl).setName('Card border radius').setDesc('Set the corner rounding of the card').addSlider(slider => slider.setLimits(0, 30, 1).setValue(this.plugin.settings.borderRadius || 0).setDynamicTooltip().onChange(async (value) => {
|
||||
this.plugin.settings.borderRadius = value;
|
||||
await this.plugin.saveSettings();
|
||||
activeDocument.documentElement.setCssProps({ '--card-border-radius': `${value}px` });
|
||||
document.documentElement.setCssProps({ '--card-border-radius': `${value}px` });
|
||||
updatePreview();
|
||||
refreshSidebarCards();
|
||||
}));
|
||||
|
|
@ -1369,7 +1380,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
if (e.dataTransfer) {
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
}
|
||||
activeWindow.setTimeout(() => {
|
||||
window.setTimeout(() => {
|
||||
setting.settingEl.addClass('sc-dragging');
|
||||
}, 0);
|
||||
});
|
||||
|
|
@ -1824,7 +1835,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
ruleDragSrcId = `rule-${idx}`;
|
||||
e.dataTransfer?.setData('text/plain', ruleDragSrcId);
|
||||
if (e.dataTransfer) e.dataTransfer.effectAllowed = 'move';
|
||||
activeWindow.setTimeout(() => setting.settingEl.addClass('sc-dragging'), 0);
|
||||
window.setTimeout(() => setting.settingEl.addClass('sc-dragging'), 0);
|
||||
});
|
||||
setting.settingEl.addEventListener('dragend', () => {
|
||||
rulesContainer.querySelectorAll('.sc-dragging').forEach(el => el.removeClass('sc-dragging'));
|
||||
|
|
@ -2047,7 +2058,7 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
statusDragSrcId = `status-${idx}`;
|
||||
e.dataTransfer?.setData('text/plain', statusDragSrcId);
|
||||
if (e.dataTransfer) e.dataTransfer.effectAllowed = 'move';
|
||||
activeWindow.setTimeout(() => setting.settingEl.addClass('sc-dragging'), 0);
|
||||
window.setTimeout(() => setting.settingEl.addClass('sc-dragging'), 0);
|
||||
});
|
||||
setting.settingEl.addEventListener('dragend', () => {
|
||||
statusConfigContainer.querySelectorAll('.sc-dragging').forEach(el => el.removeClass('sc-dragging'));
|
||||
|
|
@ -2128,16 +2139,16 @@ class SideCardsSettingTab extends PluginSettingTab {
|
|||
const a = containerEl.createEl('a');
|
||||
a.href = url;
|
||||
a.download = `sidecards-export-${new Date().toISOString().slice(0, 10)}.json`;
|
||||
activeDocument.body.appendChild(a);
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
activeDocument.body.removeChild(a);
|
||||
document.body.removeChild(a);
|
||||
URL.revokeObjectURL(url);
|
||||
new Notice('Cards exported.');
|
||||
}));
|
||||
|
||||
new Setting(containerEl)
|
||||
.setName('Import Data')
|
||||
.setDesc('Import cards from a previously exported JSON file. Existing cards with the same ID will be skipped.')
|
||||
.setDesc('Import cards from a previously exported JSON file.')
|
||||
.addButton(btn => btn
|
||||
.setButtonText('Import Data')
|
||||
.onClick(() => {
|
||||
|
|
@ -2306,73 +2317,26 @@ class ChangelogModal extends Modal {
|
|||
}
|
||||
}
|
||||
|
||||
class FolderSuggest {
|
||||
private suggestEl: HTMLElement;
|
||||
private folders: string[];
|
||||
class FolderSuggestModal extends FuzzySuggestModal<string> {
|
||||
folders: string[];
|
||||
onChoose: (folder: string) => void | Promise<void>;
|
||||
|
||||
constructor(private app: App, private inputEl: HTMLInputElement, folders: Set<string>) {
|
||||
this.folders = Array.from(folders).sort();
|
||||
this.suggestEl = this.inputEl.parentElement?.createDiv() || activeDocument.createElement('div');
|
||||
this.suggestEl.className = 'suggestion-container sc-folder-suggest';
|
||||
this.inputEl.parentElement?.appendChild(this.suggestEl);
|
||||
this.inputEl.addEventListener('click', () => this.onFocus());
|
||||
this.inputEl.addEventListener('input', () => this.onInput());
|
||||
activeDocument.addEventListener('click', (event) => this.onClick(event));
|
||||
constructor(app: App, folders: string[], onChoose: (folder: string) => void | Promise<void>) {
|
||||
super(app);
|
||||
this.folders = folders;
|
||||
this.onChoose = onChoose;
|
||||
}
|
||||
|
||||
private onFocus(): void {
|
||||
const foldersSet = new Set<string>(['/']);
|
||||
type VaultNode = { path?: string; children?: VaultNode[] };
|
||||
const vaultWithRoot = this.app.vault as unknown as { getRoot?: () => VaultNode };
|
||||
const root: VaultNode | undefined = vaultWithRoot.getRoot?.();
|
||||
const walk = (node: VaultNode) => {
|
||||
if (!node) return;
|
||||
const children = node.children || [];
|
||||
for (const c of children) {
|
||||
if (c && c.path && c.children) {
|
||||
foldersSet.add(c.path || '/');
|
||||
walk(c);
|
||||
}
|
||||
}
|
||||
};
|
||||
if (root) walk(root);
|
||||
try {
|
||||
this.app.vault.getAllLoadedFiles().forEach((file) => {
|
||||
if (file && file.parent) foldersSet.add(file.parent.path);
|
||||
});
|
||||
} catch { /* ignore */ }
|
||||
this.folders = Array.from(foldersSet).sort();
|
||||
this.updateSuggestions();
|
||||
this.suggestEl.addClass('is-visible');
|
||||
getItems(): string[] {
|
||||
return this.folders;
|
||||
}
|
||||
|
||||
private onInput(): void {
|
||||
this.updateSuggestions();
|
||||
getItemText(item: string): string {
|
||||
return item;
|
||||
}
|
||||
|
||||
private onClick(event: MouseEvent): void {
|
||||
const target = event.target as Node | null;
|
||||
if (!target) return;
|
||||
if (!this.inputEl.contains(target) && !this.suggestEl.contains(target)) {
|
||||
this.suggestEl.removeClass('is-visible');
|
||||
}
|
||||
}
|
||||
|
||||
private updateSuggestions(): void {
|
||||
const inputValue = this.inputEl.value.toLowerCase();
|
||||
this.suggestEl.empty();
|
||||
const filtered = this.folders.filter(folder => folder.toLowerCase().includes(inputValue)).slice(0, 100);
|
||||
filtered.forEach(folder => {
|
||||
const item = this.suggestEl.createDiv();
|
||||
item.className = 'suggestion-item sc-folder-suggest-item';
|
||||
item.textContent = folder;
|
||||
item.addEventListener('click', () => {
|
||||
this.inputEl.value = folder;
|
||||
this.inputEl.dispatchEvent(new Event('input'));
|
||||
this.suggestEl.removeClass('is-visible');
|
||||
});
|
||||
this.suggestEl.appendChild(item);
|
||||
});
|
||||
onChooseItem(item: string, evt: MouseEvent | KeyboardEvent): void {
|
||||
void Promise.resolve(this.onChoose(item));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -67,8 +67,6 @@ export function applyCardColorToElement(cardEl: HTMLElement, colorVar: string, s
|
|||
const hex = resolveColorVarToHex(colorVar, settings) || colorVar;
|
||||
const rgba = hexToRgba(hex, opacity);
|
||||
const borderColor = borderShadowOpacity >= 1 ? colorVar : hexToRgba(hex, borderShadowOpacity);
|
||||
const borderRadius = settings.borderRadius ?? 6;
|
||||
|
||||
if (style === 1) {
|
||||
cardEl.setCssProps({
|
||||
'border': `${borderThickness}px solid ${borderColor}`,
|
||||
|
|
@ -90,8 +88,6 @@ export function applyCardColorToElement(cardEl: HTMLElement, colorVar: string, s
|
|||
'box-shadow': `2px 2px 0 0 ${borderColor}`
|
||||
});
|
||||
}
|
||||
|
||||
cardEl.setCssProps({ 'border-radius': `${borderRadius}px` });
|
||||
}
|
||||
|
||||
export function resolveAutoColor(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { activeDocument } from "obsidian";
|
||||
import SideCardsPlugin from "../core/Plugin";
|
||||
|
||||
/**
|
||||
|
|
@ -175,8 +174,8 @@ export function attachDragToReorder(
|
|||
offsetX = e.clientX - rect.left;
|
||||
offsetY = e.clientY - rect.top;
|
||||
|
||||
activeDocument.addEventListener('pointermove', onPointerMove);
|
||||
activeDocument.addEventListener('pointerup', onPointerUp);
|
||||
document.addEventListener('pointermove', onPointerMove);
|
||||
document.addEventListener('pointerup', onPointerUp);
|
||||
// Don't preventDefault here for mouse — let clicks through until threshold crossed
|
||||
// For touch, we need to prevent scroll once drag is active (done in onPointerMove)
|
||||
};
|
||||
|
|
@ -436,8 +435,8 @@ export function attachPinnedListDragToReorder(
|
|||
dropIndex = computeDropIndex(e.clientY);
|
||||
positionIndicator(dropIndex);
|
||||
|
||||
activeDocument.addEventListener('pointermove', onPointerMove);
|
||||
activeDocument.addEventListener('pointerup', onPointerUp);
|
||||
document.addEventListener('pointermove', onPointerMove);
|
||||
document.addEventListener('pointerup', onPointerUp);
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
import { ItemView, WorkspaceLeaf, Notice, Menu, TFile, setIcon, Scope, Editor, App, MarkdownFileInfo, Text } from "obsidian";
|
||||
import { ItemView, WorkspaceLeaf, Notice, Menu, TFile, setIcon, Scope, Editor, App, MarkdownFileInfo } from "obsidian";
|
||||
import { CardStore } from "../services/CardStore";
|
||||
import { FilterService, FilterOptions } from "../services/FilterService";
|
||||
import { SortService, SortMode } from "../services/SortService";
|
||||
|
|
@ -86,8 +86,8 @@ export class CardSidebarView extends ItemView {
|
|||
if (!selection.rangeCount) return null;
|
||||
const baseRange = selection.getRangeAt(0);
|
||||
if (!baseRange.collapsed) return baseRange;
|
||||
const node = baseRange.startContainer;
|
||||
if (!node.instanceOf(Text)) return null;
|
||||
const node = baseRange.startContainer as Text;
|
||||
if (!node?.data) return null;
|
||||
const text = node.data;
|
||||
if (!text) return null;
|
||||
const offset = baseRange.startOffset;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { ItemView, WorkspaceLeaf, Menu, Notice, setIcon, Scope, Editor, TFile, Platform, App, MarkdownFileInfo, Text } from "obsidian";
|
||||
import { ItemView, WorkspaceLeaf, Menu, Notice, setIcon, Scope, Editor, TFile, Platform, App, MarkdownFileInfo } from "obsidian";
|
||||
import type SideCardsPlugin from "../core/Plugin";
|
||||
import { CardStore } from "../services/CardStore";
|
||||
import { Card } from "../models/Card";
|
||||
|
|
@ -91,8 +91,8 @@ export class SideCardsHomeView extends ItemView {
|
|||
if (!selection.rangeCount) return null;
|
||||
const baseRange = selection.getRangeAt(0);
|
||||
if (!baseRange.collapsed) return baseRange;
|
||||
const node = baseRange.startContainer;
|
||||
if (!node.instanceOf(Text)) return null;
|
||||
const node = baseRange.startContainer as Text;
|
||||
if (!node?.data) return null;
|
||||
const text = node.data;
|
||||
if (!text) return null;
|
||||
const offset = baseRange.startOffset;
|
||||
|
|
@ -306,8 +306,6 @@ export class SideCardsHomeView extends ItemView {
|
|||
// Apply user-configured max width via CSS variable so it overrides correctly
|
||||
const maxW = this.plugin.settings.homepageMaxWidth ?? 1000;
|
||||
container.setCssProps({ '--sc-home-max-width': `${maxW}px` });
|
||||
const topMargin = this.plugin.settings.homepageTopMargin ?? 70;
|
||||
container.setCssProps({ '--sc-home-top-margin': `${topMargin}px` });
|
||||
|
||||
// Top Section
|
||||
const topSection = main.createDiv({ cls: 'sc-home-top' });
|
||||
|
|
@ -762,7 +760,7 @@ export class SideCardsHomeView extends ItemView {
|
|||
this.renderCards(cardList);
|
||||
}
|
||||
|
||||
private renderToolbar(container: HTMLElement, _editorEl: HTMLElement, _cardList: HTMLElement, pinnedList: HTMLElement, recentList: HTMLElement) {
|
||||
private renderToolbar(container: HTMLElement, _editorEl: HTMLElement, cardList: HTMLElement, pinnedList: HTMLElement, recentList: HTMLElement) {
|
||||
container.empty();
|
||||
|
||||
const leftActions = container.createDiv({ cls: 'sc-home-toolbar-left' });
|
||||
|
|
|
|||
79
styles.css
79
styles.css
|
|
@ -8,16 +8,32 @@
|
|||
.sc-home-category-bar {
|
||||
margin: 0;
|
||||
gap: 10px;
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 0;
|
||||
margin-bottom: 16px;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.sc-color-dots.two-row {
|
||||
gap: 8px;
|
||||
margin-bottom: 6px;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 18px);
|
||||
grid-auto-rows: 18px;
|
||||
column-gap: 8px;
|
||||
row-gap: 8px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.sc-home-main {
|
||||
margin-top: var(--sc-home-top-margin, 70px);
|
||||
margin: var(--sc-home-top-margin, 70px) auto 0;
|
||||
transition: all 0.2s ease;
|
||||
width: 100%;
|
||||
max-width: var(--sc-home-max-width, 1000px);
|
||||
padding: 40px 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sc-home-right,
|
||||
|
|
@ -30,6 +46,10 @@
|
|||
|
||||
.sc-sidebar-button-container {
|
||||
padding-bottom: var(--sc-button-padding-bottom, 26px);
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.sc-content p {
|
||||
|
|
@ -162,14 +182,6 @@
|
|||
background-color: var(--background-primary);
|
||||
}
|
||||
|
||||
.sc-home-main {
|
||||
width: 100%;
|
||||
max-width: var(--sc-home-max-width, 1000px);
|
||||
margin: 0 auto;
|
||||
padding: 40px 20px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sc-home-top {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
|
@ -348,27 +360,14 @@
|
|||
padding: 6px 8px;
|
||||
font-size: 13px;
|
||||
width: 100%;
|
||||
font-family: var(--font-interface);
|
||||
}
|
||||
|
||||
.sc-home-search-input::placeholder {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.sc-home-category-bar {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
flex-wrap: nowrap;
|
||||
overflow-x: auto;
|
||||
padding-bottom: 16px;
|
||||
margin-bottom: 16px;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.sc-home-category-bar::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sc-home-card-list {
|
||||
.sc-home-card-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
|
|
@ -447,6 +446,7 @@
|
|||
padding: 8px;
|
||||
scrollbar-width: auto;
|
||||
-ms-overflow-style: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.sc-sidebar-cards-container.hide-scrollbar {
|
||||
|
|
@ -623,7 +623,7 @@
|
|||
flex-shrink: 0;
|
||||
transition: transform 0.1s ease;
|
||||
}
|
||||
de
|
||||
|
||||
.sc-home-color-dot {
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--background-primary);
|
||||
|
|
@ -807,11 +807,6 @@ de
|
|||
height: 100%;
|
||||
}
|
||||
|
||||
/* sc-sidebar-cards-container positional */
|
||||
.sc-sidebar-cards-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* sc-sidebar-input-container: sticky bottom input area */
|
||||
.sc-sidebar-input-container {
|
||||
padding: 8px;
|
||||
|
|
@ -821,14 +816,6 @@ de
|
|||
bottom: 0;
|
||||
}
|
||||
|
||||
/* sc-sidebar-button-container: action buttons row */
|
||||
.sc-sidebar-button-container {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: flex-end;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* sc-sidebar-loading: full-cover loading overlay */
|
||||
.sc-sidebar-loading {
|
||||
position: absolute;
|
||||
|
|
@ -863,6 +850,7 @@ de
|
|||
overflow-x: auto;
|
||||
flex-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
border-bottom: 1px solid var(--background-modifier-border);
|
||||
}
|
||||
|
||||
/* sc-search-wrap visibility helpers */
|
||||
|
|
@ -897,21 +885,6 @@ de
|
|||
order: 1;
|
||||
}
|
||||
|
||||
/* Home search input font */
|
||||
.sc-home-search-input {
|
||||
font-family: var(--font-interface);
|
||||
}
|
||||
|
||||
/* Color swatch grid (two-row context menu) */
|
||||
.sc-color-dots.two-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(5, 18px);
|
||||
grid-auto-rows: 18px;
|
||||
column-gap: 8px;
|
||||
row-gap: 8px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
/* Individual color swatch in context menu */
|
||||
.sc-color-dot-swatch {
|
||||
width: 18px;
|
||||
|
|
|
|||
Loading…
Reference in a new issue