diff --git a/patches/x-data-spreadsheet+1.1.9.patch b/patches/x-data-spreadsheet+1.1.9.patch index cc0261c..c3411a6 100644 --- a/patches/x-data-spreadsheet+1.1.9.patch +++ b/patches/x-data-spreadsheet+1.1.9.patch @@ -11,7 +11,7 @@ index cdbc0fa..cb2a9db 100644 bind(target, 'touchend', (evt) => { if (!end) return; diff --git a/node_modules/x-data-spreadsheet/src/component/sheet.js b/node_modules/x-data-spreadsheet/src/component/sheet.js -index 086b8c4..cd01f6e 100644 +index 086b8c4..264823c 100644 --- a/node_modules/x-data-spreadsheet/src/component/sheet.js +++ b/node_modules/x-data-spreadsheet/src/component/sheet.js @@ -77,11 +77,11 @@ function selectorSet(multiple, ri, ci, indexesUpdated = true, moving = false) { @@ -28,11 +28,179 @@ index 086b8c4..cd01f6e 100644 } toolbar.reset(); table.render(); +@@ -854,7 +854,7 @@ function sheetInitEvents() { + } + + export default class Sheet { +- constructor(targetEl, data) { ++ constructor(targetEl, data, isDark) { + this.eventMap = createEventEmitter(); + const { view, showToolbar, showContextmenu } = data.settings; + this.el = h('div', `${cssPrefix}-sheet`); +@@ -904,7 +904,7 @@ export default class Sheet { + this.sortFilter.el, + ); + // table +- this.table = new Table(this.tableEl.el, data); ++ this.table = new Table(this.tableEl.el, data, isDark); + sheetInitEvents.call(this); + sheetReset.call(this); + // init selector [0, 0] +diff --git a/node_modules/x-data-spreadsheet/src/component/table.js b/node_modules/x-data-spreadsheet/src/component/table.js +index 41e1e14..09ac678 100644 +--- a/node_modules/x-data-spreadsheet/src/component/table.js ++++ b/node_modules/x-data-spreadsheet/src/component/table.js +@@ -7,22 +7,23 @@ import { formatm } from '../core/format'; + import { + Draw, DrawBox, thinLineWidth, npx, + } from '../canvas/draw'; ++import { idText } from 'typescript'; + // gobal var + const cellPaddingWidth = 5; + const tableFixedHeaderCleanStyle = { fillStyle: '#f4f5f8' }; +-const tableGridStyle = { ++var tableGridStyle = { + fillStyle: '#fff', + lineWidth: thinLineWidth, + strokeStyle: '#e6e6e6', + }; +-function tableFixedHeaderStyle() { ++function tableFixedHeaderStyle(isDark) { + return { + textAlign: 'center', + textBaseline: 'middle', + font: `500 ${npx(12)}px Source Sans Pro`, +- fillStyle: '#585757', ++ fillStyle: isDark ? '#dcdcdc' : '#585757', + lineWidth: thinLineWidth(), +- strokeStyle: '#e6e6e6', ++ strokeStyle: isDark ? '#c0c0c0': '#e6e6e6', + }; + } + +@@ -184,13 +185,18 @@ function renderSelectedHeaderCell(x, y, w, h) { + // h: the fixed height of header + // tx: moving distance on x-axis + // ty: moving distance on y-axis +-function renderFixedHeaders(type, viewRange, w, h, tx, ty) { ++function renderFixedHeaders(type, viewRange, w, h, tx, ty, isDark) { + const { draw, data } = this; + const sumHeight = viewRange.h; // rows.sumHeight(viewRange.sri, viewRange.eri + 1); + const sumWidth = viewRange.w; // cols.sumWidth(viewRange.sci, viewRange.eci + 1); + const nty = ty + h; + const ntx = tx + w; + ++ if (isDark) { ++ tableFixedHeaderCleanStyle.fillStyle = '#595d88' ++ tableFixedHeaderCleanStyle.strokeStyle = '#5d5d5d' ++ } ++ + draw.save(); + // draw rect background + draw.attr(tableFixedHeaderCleanStyle); +@@ -203,7 +209,7 @@ function renderFixedHeaders(type, viewRange, w, h, tx, ty) { + // console.log(data.selectIndexes); + // draw text + // text font, align... +- draw.attr(tableFixedHeaderStyle()); ++ draw.attr(tableFixedHeaderStyle(isDark)); + // y-header-text + if (type === 'all' || type === 'left') { + data.rowEach(viewRange.sri, viewRange.eri, (i, y1, rowHeight) => { +@@ -247,21 +253,25 @@ function renderFixedHeaders(type, viewRange, w, h, tx, ty) { + draw.restore(); + } + +-function renderFixedLeftTopCell(fw, fh) { ++function renderFixedLeftTopCell(fw, fh, isDark) { + const { draw } = this; + draw.save(); + // left-top-cell +- draw.attr({ fillStyle: '#f4f5f8' }) ++ draw.attr({ fillStyle: isDark ? '#595d88' : '#f4f5f8', strokeStyle: isDark ? '#5d5d5d' : '#e6e6e6' }) + .fillRect(0, 0, fw, fh); + draw.restore(); + } + + function renderContentGrid({ + sri, sci, eri, eci, w, h, +-}, fw, fh, tx, ty) { ++}, fw, fh, tx, ty, isDark) { + const { draw, data } = this; + const { settings } = data; + ++ if (isDark) { ++ tableGridStyle.strokeStyle = '#5d5d5d' ++ } ++ + draw.save(); + draw.attr(tableGridStyle) + .translate(fw + tx, fh + ty); +@@ -300,10 +310,11 @@ function renderFreezeHighlightLine(fw, fh, ftw, fth) { + + /** end */ + class Table { +- constructor(el, data) { ++ constructor(el, data, isDark) { + this.el = el; + this.draw = new Draw(el, data.viewWidth(), data.viewHeight()); + this.data = data; ++ this.isDark = isDark + } + + resetData(data) { +@@ -329,10 +340,10 @@ class Table { + const ty = data.freezeTotalHeight(); + const { x, y } = data.scroll; + // 1 +- renderContentGrid.call(this, viewRange, fw, fh, tx, ty); ++ renderContentGrid.call(this, viewRange, fw, fh, tx, ty, this.isDark); + renderContent.call(this, viewRange, fw, fh, -x, -y); +- renderFixedHeaders.call(this, 'all', viewRange, fw, fh, tx, ty); +- renderFixedLeftTopCell.call(this, fw, fh); ++ renderFixedHeaders.call(this, 'all', viewRange, fw, fh, tx, ty, this.isDark); ++ renderFixedLeftTopCell.call(this, fw, fh, this.isDark); + const [fri, fci] = data.freeze; + if (fri > 0 || fci > 0) { + // 2 +@@ -343,7 +354,7 @@ class Table { + vr.h = ty; + renderContentGrid.call(this, vr, fw, fh, tx, 0); + renderContent.call(this, vr, fw, fh, -x, 0); +- renderFixedHeaders.call(this, 'top', vr, fw, fh, tx, 0); ++ renderFixedHeaders.call(this, 'top', vr, fw, fh, tx, 0, this.isDark); + } + // 3 + if (fci > 0) { +@@ -352,13 +363,13 @@ class Table { + vr.eci = fci - 1; + vr.w = tx; + renderContentGrid.call(this, vr, fw, fh, 0, ty); +- renderFixedHeaders.call(this, 'left', vr, fw, fh, 0, ty); ++ renderFixedHeaders.call(this, 'left', vr, fw, fh, 0, ty, this.isDark); + renderContent.call(this, vr, fw, fh, 0, -y); + } + // 4 + const freezeViewRange = data.freezeViewRange(); + renderContentGrid.call(this, freezeViewRange, fw, fh, 0, 0); +- renderFixedHeaders.call(this, 'all', freezeViewRange, fw, fh, 0, 0); ++ renderFixedHeaders.call(this, 'all', freezeViewRange, fw, fh, 0, 0, this.isDark); + renderContent.call(this, freezeViewRange, fw, fh, 0, 0); + // 5 + renderFreezeHighlightLine.call(this, fw, fh, tx, ty); diff --git a/node_modules/x-data-spreadsheet/src/index.d.ts b/node_modules/x-data-spreadsheet/src/index.d.ts -index 948a8e9..7fe36b3 100644 +index 948a8e9..72fb91e 100644 --- a/node_modules/x-data-spreadsheet/src/index.d.ts +++ b/node_modules/x-data-spreadsheet/src/index.d.ts -@@ -45,18 +45,18 @@ declare module 'x-data-spreadsheet' { +@@ -34,6 +34,7 @@ declare module 'x-data-spreadsheet' { + italic: false; + }; + }; ++ isDark: boolean; + } + + export type CELL_SELECTED = 'cell-selected'; +@@ -45,18 +46,18 @@ declare module 'x-data-spreadsheet' { export interface SpreadsheetEventHandler { ( envt: CELL_SELECTED, @@ -54,7 +222,7 @@ index 948a8e9..7fe36b3 100644 ): void; } -@@ -182,6 +182,19 @@ declare module 'x-data-spreadsheet' { +@@ -182,6 +183,19 @@ declare module 'x-data-spreadsheet' { * @param callback */ change(callback: (json: Record) => void): this; @@ -75,9 +243,18 @@ index 948a8e9..7fe36b3 100644 * set locale * @param lang diff --git a/node_modules/x-data-spreadsheet/src/index.js b/node_modules/x-data-spreadsheet/src/index.js -index 479a0b7..96d0f3a 100644 +index 479a0b7..ae82d34 100644 --- a/node_modules/x-data-spreadsheet/src/index.js +++ b/node_modules/x-data-spreadsheet/src/index.js +@@ -11,7 +11,7 @@ import './index.less'; + class Spreadsheet { + constructor(selectors, options = {}) { + let targetEl = selectors; +- this.options = { showBottomBar: true, ...options }; ++ this.options = { isDark: false, showBottomBar: true, ...options }; + this.sheetIndex = 1; + this.datas = []; + if (typeof selectors === 'string') { @@ -20,6 +20,7 @@ class Spreadsheet { this.bottombar = this.options.showBottomBar ? new Bottombar(() => { const d = this.addSheet(); @@ -86,7 +263,7 @@ index 479a0b7..96d0f3a 100644 }, (index) => { const d = this.datas[index]; this.sheet.resetData(d); -@@ -27,6 +28,7 @@ class Spreadsheet { +@@ -27,13 +28,14 @@ class Spreadsheet { this.deleteSheet(); }, (index, value) => { this.datas[index].name = value; @@ -94,6 +271,14 @@ index 479a0b7..96d0f3a 100644 }) : null; this.data = this.addSheet(); const rootEl = h('div', `${cssPrefix}`) + .on('contextmenu', evt => evt.preventDefault()); + // create canvas element + targetEl.appendChild(rootEl.el); +- this.sheet = new Sheet(rootEl, this.data); ++ this.sheet = new Sheet(rootEl, this.data, options.isDark); + if (this.bottombar !== null) { + rootEl.child(this.bottombar.el); + } @@ -120,6 +122,16 @@ class Spreadsheet { return this; } diff --git a/src/ExcelSettingTab.ts b/src/ExcelSettingTab.ts index 92f7191..1550241 100644 --- a/src/ExcelSettingTab.ts +++ b/src/ExcelSettingTab.ts @@ -15,6 +15,21 @@ export class ExcelSettingTab extends PluginSettingTab { containerEl.empty() + containerEl.createEl("h1", { text: t("BASE_COLOR") }); + + new Setting(containerEl) + .setName(t("BASE_COLOR")) + .setDesc(t("BASE_COLOR_DESC")) + .addDropdown((dropdown) => + dropdown + .addOption("light","Light") + .addOption("dark","Dark") + .setValue(this.plugin.settings.theme) + .onChange(async (value) => { + this.plugin.settings.theme = value + }), + ); + containerEl.createEl("h1", { text: t("FILE_SETTING") }); new Setting(containerEl) diff --git a/src/ExcelView.ts b/src/ExcelView.ts index 66aace9..d3bbb12 100644 --- a/src/ExcelView.ts +++ b/src/ExcelView.ts @@ -8,6 +8,7 @@ import { getExcelData } from "./utils/DataUtils"; import zhCn from "./lang/locale/sheet-zh-cn" import en from "./lang/locale/sheet-en" import { t } from "./lang/helpers" +import { updateSheetTheme } from "./utils/ThemeUtils"; export class ExcelView extends TextFileView { public plugin: ExcelPlugin; @@ -186,6 +187,41 @@ export class ExcelView extends TextFileView { } else { Spreadsheet.locale('en', en) } + + // 设置 sheet 样式 + var style = { + bgcolor: '#ffffff', + align: 'left', + valign: 'middle', + textwrap: false, + strike: false, + underline: false, + color: '#0a0a0a', + font: { + name: 'Helvetica', + size: 10, + bold: false, + italic: false, + }, + } + + if (this.plugin.settings.theme === "dark") { + style = { + bgcolor: '#363636', + align: 'left', + valign: 'middle', + textwrap: false, + strike: false, + underline: false, + color: '#fff', + font: { + name: 'Helvetica', + size: 10, + bold: false, + italic: false, + }, + } + } //@ts-ignore this.sheet = new Spreadsheet(this.sheetEle, { @@ -204,6 +240,9 @@ export class ExcelView extends TextFileView { indexWidth: 60, minWidth: 60, }, + //@ts-ignore + style: style, + isDark: this.plugin.settings.theme === "dark" }) .loadData(jsonData) // load data .change(() => { @@ -241,6 +280,8 @@ export class ExcelView extends TextFileView { this.cellsSelected.eci = ci; }); + updateSheetTheme(this.plugin.settings.theme === "dark") + // @ts-ignore this.sheet.validate(); } diff --git a/src/MarkdownPostProcessor.ts b/src/MarkdownPostProcessor.ts index 116b397..915cf72 100644 --- a/src/MarkdownPostProcessor.ts +++ b/src/MarkdownPostProcessor.ts @@ -7,6 +7,7 @@ import { import ExcelPlugin from "./main"; import Spreadsheet from "x-data-spreadsheet"; import { getExcelData, getExcelAreaData } from "./utils/DataUtils"; +import { updateSheetTheme } from "./utils/ThemeUtils"; let plugin: ExcelPlugin; let vault: Vault; @@ -179,6 +180,42 @@ const createSheetEl = (data: string, file: TFile, width: number, height: number const jsonData = JSON.parse(data || "{}") || {}; // console.log("createSheetEl", jsonData, data) + + // 设置 sheet 样式 + var style = { + bgcolor: '#ffffff', + align: 'left', + valign: 'middle', + textwrap: false, + strike: false, + underline: false, + color: '#0a0a0a', + font: { + name: 'Helvetica', + size: 10, + bold: false, + italic: false, + }, + } + + if (plugin.settings.theme === "dark") { + style = { + bgcolor: '#363636', + align: 'left', + valign: 'middle', + textwrap: false, + strike: false, + underline: false, + color: '#fff', + font: { + name: 'Helvetica', + size: 10, + bold: false, + italic: false, + }, + } + } + //@ts-ignore const sheet = new Spreadsheet(sheetEl, { mode: "read", @@ -186,7 +223,7 @@ const createSheetEl = (data: string, file: TFile, width: number, height: number showBottomBar: true, view: { height: () => height, - width: () => width, + width: () => width - 10, }, row: { len: 100, @@ -198,8 +235,13 @@ const createSheetEl = (data: string, file: TFile, width: number, height: number indexWidth: 60, minWidth: 60, }, + // @ts-ignore + style: style, + isDark: plugin.settings.theme === "dark", }).loadData(jsonData); // load data + updateSheetTheme(plugin.settings.theme === "dark") + // @ts-ignore sheet.validate(); sheetDiv.appendChild(sheetEl) diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index 8d80db4..53af2ca 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -25,6 +25,8 @@ export default { // ExcelSettingTab.ts + BASE_COLOR: "Base color scheme", + BASE_COLOR_DESC: "Choose default color scheme", FILE_SETTING: "File Setting", FOLDER: "FOLDER", FOLDER_DESC: "Create files in this folder by default", diff --git a/src/lang/locale/zh-cn.ts b/src/lang/locale/zh-cn.ts index 2187a3f..1cd4036 100644 --- a/src/lang/locale/zh-cn.ts +++ b/src/lang/locale/zh-cn.ts @@ -24,6 +24,8 @@ export default { EXPORT_XLSX_FILE: "到处 xlsx 文件", // ExcelSettingTab.ts + BASE_COLOR: "基础颜色", + BASE_COLOR_DESC: "选择默认基础色", FILE_SETTING: "文件设置", FOLDER: "文件夹", FOLDER_DESC: "新建文件将放在此文件夹下", diff --git a/src/utils/Settings.ts b/src/utils/Settings.ts index afdccc3..0fa6cb9 100644 --- a/src/utils/Settings.ts +++ b/src/utils/Settings.ts @@ -4,7 +4,8 @@ export interface ExcelSettings { excelFilenameDateTime: string, sheetHeight: string, rowHeight: string, - colWidth: string + colWidth: string, + theme: string } export const DEFAULT_SETTINGS: ExcelSettings = { @@ -13,5 +14,6 @@ export const DEFAULT_SETTINGS: ExcelSettings = { excelFilenameDateTime: "YYYY-MM-DD HH.mm.ss", sheetHeight: "300", rowHeight: "25", - colWidth: "100" + colWidth: "100", + theme: "light" }; diff --git a/src/utils/ThemeUtils.ts b/src/utils/ThemeUtils.ts new file mode 100644 index 0000000..3af7f85 --- /dev/null +++ b/src/utils/ThemeUtils.ts @@ -0,0 +1,28 @@ +export function updateSheetTheme(isDark: Boolean) { + const root = document.documentElement; + if (isDark) { + root.style.setProperty('--sheet-iframe-background-color', "#363636") + root.style.setProperty('--sheet-iframe-border-color', "#a5a0f8") + root.style.setProperty('--sheet-toolbar-background-color', "#a5a0f8") + root.style.setProperty('--sheet-toolbar-divider-color', "#a5a0f8") + root.style.setProperty('--sheet-dropdown-content-background-color', "#857fe6") + root.style.setProperty('--sheet-dropdown-content-color', "#dcdcdc") + root.style.setProperty('--sheet-dropdown-title-color', "rgba(0,0,0,0.9)") + root.style.setProperty('--sheet-menu-color', "#000") + root.style.setProperty('--sheet-menu-active-background-color', "#bdb9f9") + root.style.setProperty('--sheet-header-background-color', "#bdb9f9") + root.style.setProperty('--sheet-checked-before', "#025492") + } else { + root.style.setProperty('--sheet-iframe-border-color', "#f5f6f7") + root.style.setProperty('--sheet-iframe-background-color', "#fff") + root.style.setProperty('--sheet-toolbar-background-color', "#f5f6f7") + root.style.setProperty('--sheet-toolbar-divider-color', "#e0e2e4") + root.style.setProperty('--sheet-dropdown-content-background-color', "#fff") + root.style.setProperty('--sheet-dropdown-content-color', "rgba(0,0,0,0.9)") + root.style.setProperty('--sheet-dropdown-title-color', "rgba(0,0,0,0.9)") + root.style.setProperty('--sheet-menu-color', "#80868b") + root.style.setProperty('--sheet-menu-active-background-color', "#fff") + root.style.setProperty('--sheet-header-background-color', "#f8f8f9") + root.style.setProperty('--sheet-checked-before', "#4b89ff") + } +} \ No newline at end of file diff --git a/styles.css b/styles.css index ac04264..224c7bf 100644 --- a/styles.css +++ b/styles.css @@ -1,3 +1,17 @@ +:root { + --sheet-iframe-border-color: #f5f6f7; + --sheet-iframe-background-color: #fff; + --sheet-toolbar-background-color: #f5f6f7; + --sheet-toolbar-divider-color: #e0e2e4; + --sheet-dropdown-content-background-color: #fff; + --sheet-dropdown-content-color: rgba(0,0,0,0.9); + --sheet-dropdown-title-color: rgba(0,0,0,0.9); + --sheet-menu-color: #80868b; + --sheet-menu-active-background-color: #fff; + --sheet-header-background-color: #f8f8f9; + --sheet-checked-before: #4b89ff; +} + .sheet-box { width: 100%; height: 100%; @@ -16,8 +30,8 @@ /* Markdown 文档引入样式设置*/ .sheet-iframe { width: 100%; - background-color: var(--background-primary-alt); - border: 5px solid #f5f6f7; + background-color: var(--sheet-iframe-background-color); + border: 5px solid var(--sheet-iframe-border-color); } ul.x-spreadsheet-menu { @@ -39,7 +53,7 @@ body { -moz-user-select: none; font-family: "Lato", "Source Sans Pro", Roboto, Helvetica, Arial, sans-serif; box-sizing: content-box; - background: #fff; + background: var(--sheet-iframe-background-color); -webkit-font-smoothing: antialiased; } .x-spreadsheet textarea { @@ -158,7 +172,7 @@ body { .x-spreadsheet-dropdown .x-spreadsheet-dropdown-content { position: absolute; z-index: 200; - background: #fff; + background: var(--sheet-dropdown-content-background-color); box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15); } .x-spreadsheet-dropdown.bottom-left .x-spreadsheet-dropdown-content { @@ -181,6 +195,11 @@ body { padding: 0 5px; display: inline-block; } + +.x-spreadsheet-dropdown-title { + color: var(--sheet-dropdown-title-color); +} + .x-spreadsheet-dropdown .x-spreadsheet-dropdown-header .x-spreadsheet-icon.arrow-left { @@ -353,7 +372,7 @@ body { border: 1px solid transparent; outline: none; height: 26px; - color: rgba(0, 0, 0, 0.9); + color: var(--sheet-dropdown-content-color); line-height: 26px; list-style: none; padding: 2px 10px; @@ -399,7 +418,7 @@ body { } .x-spreadsheet-item.state.checked:before, .x-spreadsheet-header.state.checked:before { - background: #4b89ff; + background: var(--sheet-checked-before); } .x-spreadsheet-checkbox { position: relative; @@ -424,7 +443,7 @@ body { .x-spreadsheet-sort-filter { position: absolute; box-shadow: 1px 2px 5px 2px rgba(51, 51, 51, 0.15); - background: #fff; + background: var(--sheet-dropdown-content-background-color); z-index: 100; width: 260px; pointer-events: auto; @@ -440,7 +459,7 @@ body { } .x-spreadsheet-filter .x-spreadsheet-header { padding: 0.5em 0.75em; - background: #f8f8f9; + background: var(--sheet-header-background-color); border-bottom: 1px solid #e9e9e9; border-left: 1px solid transparent; } @@ -460,9 +479,14 @@ body { height: 40px; padding: 0 30px; text-align: left; - background: #f5f6f7; + background: var(--sheet-toolbar-background-color); display: flex; } + +.x-spreadsheet-toolbar { + width: 100% !important +} + .x-spreadsheet-bottombar { position: relative; border-top: 1px solid #e0e2e4; @@ -473,7 +497,7 @@ body { padding-top: 0; padding-bottom: 0; vertical-align: middle; - border-right: 1px solid #e8eaed; + border-right: 1px solid var(--sheet-toolbar-divider-color); } .x-spreadsheet-menu { list-style: none; @@ -489,14 +513,14 @@ body { vertical-align: middle; text-align: left; font-weight: 400; - color: #80868b; + color: var(--sheet-menu-color); white-space: nowrap; cursor: pointer; transition: all 0.3s; font-weight: bold; } .x-spreadsheet-menu > li.active { - background-color: #fff; + background-color: var(--sheet-menu-active-background-color); color: rgba(0, 0, 0, 0.65); } .x-spreadsheet-menu > li .x-spreadsheet-icon { @@ -545,7 +569,7 @@ body { } .x-spreadsheet-toolbar-divider { display: inline-block; - border-right: 1px solid #e0e2e4; + border-right: 1px solid var(--sheet-toolbar-divider-color); width: 0; vertical-align: middle; height: 18px;