diff --git a/src/App.css b/src/App.css index 3878ff8..48b54ff 100644 --- a/src/App.css +++ b/src/App.css @@ -1,3 +1,14 @@ +:root { + --LRS-dark-mode-background: #212121; + --LRS-dark-mode-button: #8891a3; + --LRS-dark-mode-input-background: #272c35; + --LRS-dark-mode-text: rgb(167, 167, 167); +} + +* { + box-sizing: border-box; +} + .block-reference-container { position: absolute; top: 15%; @@ -10,6 +21,10 @@ padding: 24px; box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4); } +.block-ref-style-wrapper.title { + color: #212121; +} + .block-ref-style-wrapper { display: flex; flex-direction: row; @@ -27,23 +42,27 @@ visibility: visible; } .block-ref-input { - font-size: 20px; + /* font-size: 20px; margin: 4px; border-radius: 4px; - background-color: #ddd; + background-color: #ddd; */ + text-align: center; } -.fix { +/* .fix { width: 5em; } .char { width: 2em; } .color { - width: 10em; + width: 7em; +} +.color-dark { + width: 7em; } .btn-add { margin-top: 4px; -} +} */ .closeButton { position: absolute; top: 4px; @@ -53,3 +72,86 @@ color: rgba(0, 0, 0, 0.3); cursor: pointer; } + + +/* style more */ +.block-reference-container { + left: 50%; + min-width: 50%; + max-height: 70%; + overflow: auto; +} +.block-ref-style-wrapper { + margin-bottom: 10px; + min-height: 33px; +} +.block-ref-style { + justify-content: space-around; + gap: 15px; + width: 90%; +} +/* each line */ +.block-ref-style :nth-child(1) { + flex-grow: 3; + flex-basis: 35%; +} +.block-ref-style :nth-child(2) { + flex-grow: 1; + flex-basis: 10%; +} +.block-ref-style :nth-child(3) { + flex-grow: 2; + flex-basis: 25%; +} +.block-ref-style :nth-child(4) { + flex-grow: 2; + flex-basis: 25%; +} + +/* color input */ +.block-ref-input.color, +.block-ref-input.color-dark{ + border: none; + height: 100%; + background-color: #eee; +} +/* delete , add button and close button*/ +.btn.btn-block-remove { + margin-left: 15px; + width: 34px; + height: 34px; + padding: 0px; +} + +.btn-add::before, +.btn-add::after { + transition: width 0.2s ease-in-out, border-radius 0.2s ease-in-out; + content: ""; + position: absolute; + height: 4px; + width: 10px; + top: calc(50% - 2px); + background: seagreen; +} + + +.btn-add::before { + left: 14px; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; +} +.btn-add:hover{ + box-shadow: 3px 3px 3px #212121; +} + +/* dark mode */ +.block-reference-container.dark { + background-color: var(--LRS-dark-mode-background); +} +.block-ref-style-wrapper.title.dark{ + color: var(--LRS-dark-mode-text); +} +.block-ref-input.color.dark, +.block-ref-input.color-dark.dark{ + background-color: var(--LRS-dark-mode-background); +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index eb008a3..c9fe472 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,33 +2,51 @@ import '@logseq/libs'; import React, {useState} from 'react'; import './App.css'; import {v4 as uuid} from 'uuid'; -import {makePrefixCSS} from './makePrefixCSS'; - +import {makePrefixCSS,makePrefixCSSDarkMode} from './makePrefixCSS'; +import ThemeConfig, {ThemeMode} from "./UserTheme" +import CustomInput from './customInput'; +import DeleteButton from './cutomButton/deleteButton'; +import AddButton from './cutomButton/AddButton' export type BlockStyle = { prefix: string; character?: string; color?: string; + colorDarkMode?: string; }; export type BlockStyles = {[key: string]: BlockStyle}; -const makeCSS = (customizations: BlockStyles) => { - return Object.entries(customizations) - .map((customization) => makePrefixCSS(...customization)) - .join('\n\n'); +const makeCSS = (customizations: BlockStyles,themeMode:ThemeMode) => { + if(!themeMode || (themeMode === "light")) + return Object.entries(customizations) + .map((customization) => makePrefixCSS(...customization)) + .join('\n\n'); + else + return Object.entries(customizations) + .map((customization) => makePrefixCSSDarkMode(...customization)) + .join('\n\n'); }; const App = () => { const [blockStyles, setBlockStylesInStateOnly] = useState( - JSON.parse(logseq.settings.blockStyles) as BlockStyles, + JSON.parse(logseq.settings?.blockStyles) as BlockStyles, ); + const [userTheme,setUserTheme] = useState(undefined) + + React.useEffect(() => { + ThemeConfig.getTheme() + .then((theme) => { + setUserTheme(theme) + }) + ThemeConfig.onThemeChange(setUserTheme) + },[]) React.useEffect(() => { logseq.provideStyle({ key: 'logseq-reference-styles-style', - style: makeCSS(blockStyles), + style: makeCSS(blockStyles,userTheme), }); - }, [blockStyles]); + }, [blockStyles,userTheme]); const setBlockStyles = (blockStyles: BlockStyles) => { setBlockStylesInStateOnly(blockStyles); @@ -59,6 +77,10 @@ const App = () => { setBlockStyles(newStyles); }; + function isDark() : "" | "dark"{ + return userTheme === "dark" ? "dark" : "" + } + return (
{ }} >
{ e.stopPropagation(); }} @@ -77,17 +99,25 @@ const App = () => { X
+
+
+ {["Label","Emoji","Light","Dark"].map((title) => { + return (

{title}

) + })} +
+
+ {Object.entries({ ...blockStyles, }).map(([name, blockStyle]) => { - const {prefix, character, color} = blockStyle; + const {prefix, character, color,colorDarkMode} = blockStyle; return (
- handleChange(name, { ...blockStyle, @@ -95,9 +125,9 @@ const App = () => { }) } /> - handleChange(name, { @@ -108,25 +138,28 @@ const App = () => { /> handleChange(name, {...blockStyle, color: e.target.value}) } /> + + handleChange(name, {...blockStyle, colorDarkMode: e.target.value}) + } + />
- handleDelete(name)} - /> + handleDelete(name)} />
); })} - handleAdd()} diff --git a/src/UserTheme.tsx b/src/UserTheme.tsx new file mode 100644 index 0000000..699c409 --- /dev/null +++ b/src/UserTheme.tsx @@ -0,0 +1,25 @@ +import "@logseq/libs"; +export type ThemeMode = "light" | "dark" | undefined; + +let Theme:ThemeMode = undefined +function setTheme(t) { + Theme = t +} +export function getTheme() { + return Theme +} + +export default { + async getTheme() { + const config = await logseq.App.getUserConfigs() + const theme = config.preferredThemeMode + setTheme(theme) + return theme + }, + onThemeChange(cb: (ThemeMode: ThemeMode) => void) { + logseq.App.onThemeModeChanged((ev) => { + setTheme(ev.mode) + cb(ev.mode); + }); + }, +}; diff --git a/src/customInput/index.tsx b/src/customInput/index.tsx new file mode 100644 index 0000000..8b47374 --- /dev/null +++ b/src/customInput/index.tsx @@ -0,0 +1,12 @@ +import React,{FunctionComponent} from 'react' +import "./inputbox.css" + + + +export default function CustomInput(props){ + return ( +
+ +
+ ) +} diff --git a/src/customInput/inputbox.css b/src/customInput/inputbox.css new file mode 100644 index 0000000..95957ff --- /dev/null +++ b/src/customInput/inputbox.css @@ -0,0 +1,96 @@ +.textInputWrapper { + position: relative; + /* margin: 12px 5px; */ + --accent-color: #a3e583; + display: inline-block; +} + +.textInputWrapper:before { + transition: border-bottom-color 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; + border-bottom: 1px solid rgba(0, 0, 0, 0.42); +} + +.textInputWrapper:before, +.textInputWrapper:after { + content: ""; + left: 0; + right: 0; + position: absolute; + pointer-events: none; + bottom: -1px; + z-index: 4; + width: 100%; +} + +.textInputWrapper:focus-within:before { + border-bottom: 1px solid var(--accent-color); +} + +.textInputWrapper:before { + transition: border-bottom-color 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; + border-bottom: 1px solid rgba(0, 0, 0, 0.42); +} + +.textInputWrapper:focus-within:before { + border-bottom: 1px solid var(--accent-color); + transform: scaleX(1); +} + +.textInputWrapper:focus-within:after { + border-bottom: 2px solid var(--accent-color); + transform: scaleX(1); +} + +.textInputWrapper:after { + content: ""; + transform: scaleX(0); + transition: transform 250ms cubic-bezier(0, 0, 0.2, 1) 0ms; + will-change: transform; + border-bottom: 2px solid var(--accent-color); + border-bottom-color: var(--accent-color); +} + +.textInput::placeholder { + transition: opacity 250ms cubic-bezier(0, 0, 0.2, 1) 0ms; + opacity: 1; + user-select: none; + color: rgba(255, 255, 255, 0.582); +} + +.textInputWrapper .textInput { + border-radius: 5px 5px 0px 0px; + box-shadow: 0px 2px 5px rgb(35 35 35 / 30%); + max-height: 36px; + background-color: whitesmoke; + transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1); + transition-duration: 200ms; + transition-property: background-color; + color: #252525; + width: 100%; + height: 100%; + border-left: none; + border-bottom: none; + border-right: none; + border-top: none; +} + +.textInputWrapper .textInput.dark { + background-color: #252525; + color: #e8e8e8; +} + +.textInputWrapper .textInput:focus, +.textInputWrapper .textInput:active { + outline: none; +} + +.textInputWrapper:focus-within .textInput, +.textInputWrapper .textInput:focus, +.textInputWrapper .textInput:active { + /* background-color: #353535; */ +} + +.textInputWrapper:focus-within .textInput::placeholder { + opacity: 0; +} + diff --git a/src/cutomButton/AddButton.css b/src/cutomButton/AddButton.css new file mode 100644 index 0000000..b4d29f8 --- /dev/null +++ b/src/cutomButton/AddButton.css @@ -0,0 +1,43 @@ +/* From uiverse.io by @mrhyddenn */ + +.icon-btn { + width: 50px; + height: 25px; + border: 1px solid #cdcdcd; + background: white; + border-radius: 25px; + overflow: hidden; + position: relative; + transition: width 0.2s ease-in-out; + font-weight: 500; + font-family: inherit; +} + + +.add-icon::after, +.add-icon::before { + transition: all 0.2s ease-in-out; + content: ""; + position: absolute; + height: 20px; + width: 2px; + top: calc(50% - 10px); + background: seagreen; + overflow: hidden; +} + +.add-icon::before { + left: 22px; + border-top-left-radius: 2px; + border-bottom-left-radius: 2px; +} + +.add-icon::after { + right: 22px; + border-top-right-radius: 2px; + border-bottom-right-radius: 2px; +} + +.icon-btn.dark { + background-color: var(--LRS-dark-mode-background); +} \ No newline at end of file diff --git a/src/cutomButton/AddButton.tsx b/src/cutomButton/AddButton.tsx new file mode 100644 index 0000000..5ea95cf --- /dev/null +++ b/src/cutomButton/AddButton.tsx @@ -0,0 +1,10 @@ +import React from "react"; +import "./addButton.css"; + +export default function DeleteButton(props) { + return ( + + ); +} diff --git a/src/cutomButton/deleteButton.css b/src/cutomButton/deleteButton.css new file mode 100644 index 0000000..7afbbce --- /dev/null +++ b/src/cutomButton/deleteButton.css @@ -0,0 +1,24 @@ +/* From uiverse.io by @hannahyockel */ +.btn-block-remove { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + border: 0px solid transparent; + background-color: rgba(100,77,237,0.08); + border-radius: 1.25em; + transition: all 0.2s linear; +} + +.btn-block-remove:hover { + box-shadow: 3.4px 2.5px 4.9px rgba(0, 0, 0, 0.025), + 8.6px 6.3px 12.4px rgba(0, 0, 0, 0.035), + 17.5px 12.8px 25.3px rgba(0, 0, 0, 0.045), + 36.1px 26.3px 52.2px rgba(0, 0, 0, 0.055), + 99px 72px 143px rgba(0, 0, 0, 0.08); +} + +.tooltip { + position: relative; + display: inline-block; +} diff --git a/src/cutomButton/deleteButton.tsx b/src/cutomButton/deleteButton.tsx new file mode 100644 index 0000000..142e057 --- /dev/null +++ b/src/cutomButton/deleteButton.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import "./deleteButton.css" + +export default function DeleteButton(props) { + + return ( + + ); +} diff --git a/src/makePrefixCSS.ts b/src/makePrefixCSS.ts index f290c77..98ff301 100644 --- a/src/makePrefixCSS.ts +++ b/src/makePrefixCSS.ts @@ -48,3 +48,42 @@ export const makePrefixCSS = ( top: 3px; }`; }; + +export const makePrefixCSSDarkMode = ( + title: string, + {prefix, character, color, colorDarkMode}: BlockStyle, +) => { + // brittle, imitating `page-name-sanity` in the logseq source code + const prefixEscaped = prefix + .replace(/[\[\:\\\*\?\"\<\>\|\]\+\%\#]/g, '_') + .toLowerCase(); + return ` +/* ${title} */ +.page-reference[data-ref^='${prefix}'] .page-ref, +.page-ref[data-ref^='${prefixEscaped}'], +.recent-item[data-ref^='${prefixEscaped}'] a, +.title[data-ref^='${prefixEscaped}'] { + ${color ? `color: ${colorDarkMode}!important;` : 'color: inherit!important;'} + font-weight: 500; +} +.recent-item[data-ref^='${prefixEscaped}'] { + position: relative; +} +.recent-item[data-ref^='${prefixEscaped}'] .page-icon { + visibility: hidden; +} +.page-reference[data-ref^='${prefix}'] .page-ref:before, +.page-ref[data-ref^='${prefixEscaped}']:before, +.recent-item[data-ref^='${prefixEscaped}']:before, +.title[data-ref^='${prefixEscaped}']:before { + display: ${character ? 'inline' : 'none'}; + content: '${character || ''}'; + margin-right: 2px; +} + +.recent-item[data-ref^='${prefixEscaped}']:before { + position: absolute; + left: 20px; + top: 3px; +}`; +};