Merge branch 'main' into disenchant and run prettier

This commit is contained in:
vorotamoroz
2025-10-04 17:59:42 +09:00
8 changed files with 511 additions and 349 deletions

4
.gitignore vendored
View File

@@ -9,6 +9,7 @@ package-lock.json
# build
main.js
main_org.js
main_org_*.js
*.js.map
meta.json
meta-*.json
@@ -17,3 +18,6 @@ meta-*.json
# obsidian
data.json
.vscode
# environment variables
.env

View File

@@ -19,6 +19,18 @@ const manifestJson = JSON.parse(fs.readFileSync("./manifest.json") + "");
const packageJson = JSON.parse(fs.readFileSync("./package.json") + "");
const updateInfo = JSON.stringify(fs.readFileSync("./updates.md") + "");
const PATHS_TEST_INSTALL = process.env?.PATHS_TEST_INSTALL || "";
const PATH_TEST_INSTALL = PATHS_TEST_INSTALL.split(path.delimiter).map(p => p.trim()).filter(p => p.length);
if (!prod) {
if (PATH_TEST_INSTALL) {
console.log(`Built files will be copied to ${PATH_TEST_INSTALL}`);
} else {
console.log("Development build: You can install the plug-in to Obsidian for testing by exporting the PATHS_TEST_INSTALL environment variable with the paths to your vault plugins directories separated by your system path delimiter (':' on Unix, ';' on Windows).");
}
} else {
console.log("Production build");
}
const moduleAliasPlugin = {
name: "module-alias",
setup(build) {
@@ -95,6 +107,21 @@ const plugins = [
} else {
fs.copyFileSync("./main_org.js", "./main.js");
}
if (PATH_TEST_INSTALL) {
for (const installPath of PATH_TEST_INSTALL) {
const realPath = path.resolve(installPath);
console.log(`Copying built files to ${realPath}`);
if (!fs.existsSync(realPath)) {
console.warn(`Test install path ${installPath} does not exist`);
continue;
}
const manifestX = JSON.parse(fs.readFileSync("./manifest.json") + "");
manifestX.version = manifestJson.version + "." + Date.now();
fs.writeFileSync(path.join(installPath, "manifest.json"), JSON.stringify(manifestX, null, 2));
fs.copyFileSync("./main.js", path.join(installPath, "main.js"));
fs.copyFileSync("./styles.css", path.join(installPath, "styles.css"));
}
}
});
},
},

1
example.env Normal file
View File

@@ -0,0 +1 @@
PATHS_TEST_INSTALL=your-vault-plugin-path:and-another-path

284
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -13,7 +13,7 @@
"postbakei18n": "prettier --config ./.prettierrc ./src/lib/src/common/messages/*.ts --write --log-level error",
"posti18n:yaml2json": "npm run prettyjson",
"predev": "npm run bakei18n",
"dev": "node esbuild.config.mjs",
"dev": "node --env-file=.env esbuild.config.mjs",
"prebuild": "npm run bakei18n",
"build": "node esbuild.config.mjs production",
"buildDev": "node esbuild.config.mjs dev",
@@ -49,6 +49,7 @@
"@typescript-eslint/parser": "8.25.0",
"builtin-modules": "5.0.0",
"esbuild": "0.25.0",
"esbuild-plugin-inline-worker": "^0.1.1",
"esbuild-svelte": "^0.9.0",
"eslint": "^9.21.0",
"eslint-plugin-import": "^2.31.0",
@@ -71,6 +72,7 @@
"pouchdb-utils": "^9.0.0",
"prettier": "3.5.2",
"svelte": "5.28.6",
"svelte-check": "^4.1.7",
"svelte-preprocess": "^6.0.3",
"terser": "^5.39.0",
"transform-pouch": "^2.0.0",
@@ -88,13 +90,11 @@
"@smithy/protocol-http": "^5.1.0",
"@smithy/querystring-builder": "^4.0.2",
"diff-match-patch": "^1.0.5",
"esbuild-plugin-inline-worker": "^0.1.1",
"fflate": "^0.8.2",
"idb": "^8.0.3",
"minimatch": "^10.0.1",
"minimatch": "^10.0.2",
"octagonal-wheels": "^0.1.40",
"qrcode-generator": "^1.4.4",
"svelte-check": "^4.1.7",
"trystero": "github:vrtmrz/trystero#9e892a93ec14eeb57ce806d272fbb7c3935256d8",
"xxhash-wasm-102": "npm:xxhash-wasm@^1.0.2"
}

Submodule src/lib updated: 868590e814...6f58b4f076

View File

@@ -321,281 +321,281 @@ export function paneRemoteConfig(
},
onUpdate: this.enableOnlySyncDisabled,
});
void addPanel(paneEl, "Peer-to-Peer", undefined, this.onlyOnOnlyP2P).then((paneEl) => {
const syncWarnP2P = this.createEl(paneEl, "div", {
text: "",
});
const p2pMessage = `This feature is a Work In Progress, and configurable on \`P2P Replicator\` Pane.
});
void addPanel(paneEl, "Peer-to-Peer", undefined, this.onlyOnOnlyP2P).then((paneEl) => {
const syncWarnP2P = this.createEl(paneEl, "div", {
text: "",
});
const p2pMessage = `This feature is a Work In Progress, and configurable on \`P2P Replicator\` Pane.
The pane also can be launched by \`P2P Replicator\` command from the Command Palette.
`;
void MarkdownRenderer.render(this.plugin.app, p2pMessage, syncWarnP2P, "/", this.plugin);
syncWarnP2P.addClass("op-warn-info");
new Setting(paneEl).setName("Apply Settings").setClass("wizardHidden").addApplyButton(["remoteType"]);
// .addOnUpdate(onlyOnMinIO);
// new Setting(paneEl).addButton((button) =>
// button
// .setButtonText("Open P2P Replicator")
// .onClick(() => {
// const addOn = this.plugin.getAddOn<P2PReplicator>(P2PReplicator.name);
// void addOn?.openPane();
// this.closeSetting();
// })
// );
});
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleMinioS3R2"), undefined, this.onlyOnMinIO).then(
(paneEl) => {
const syncWarnMinio = this.createEl(paneEl, "div", {
text: "",
});
const ObjectStorageMessage = $msg("obsidianLiveSyncSettingTab.msgObjectStorageWarning");
void MarkdownRenderer.render(this.plugin.app, p2pMessage, syncWarnP2P, "/", this.plugin);
syncWarnP2P.addClass("op-warn-info");
new Setting(paneEl).setName("Apply Settings").setClass("wizardHidden").addApplyButton(["remoteType"]);
// .addOnUpdate(onlyOnMinIO);
// new Setting(paneEl).addButton((button) =>
// button
// .setButtonText("Open P2P Replicator")
// .onClick(() => {
// const addOn = this.plugin.getAddOn<P2PReplicator>(P2PReplicator.name);
// void addOn?.openPane();
// this.closeSetting();
// })
// );
});
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleMinioS3R2"), undefined, this.onlyOnMinIO).then(
(paneEl) => {
const syncWarnMinio = this.createEl(paneEl, "div", {
text: "",
});
const ObjectStorageMessage = $msg("obsidianLiveSyncSettingTab.msgObjectStorageWarning");
void MarkdownRenderer.render(this.plugin.app, ObjectStorageMessage, syncWarnMinio, "/", this.plugin);
syncWarnMinio.addClass("op-warn-info");
void MarkdownRenderer.render(this.plugin.app, ObjectStorageMessage, syncWarnMinio, "/", this.plugin);
syncWarnMinio.addClass("op-warn-info");
new Setting(paneEl).autoWireText("endpoint", { holdValue: true });
new Setting(paneEl).autoWireToggle("forcePathStyle", { holdValue: true });
new Setting(paneEl).autoWireText("accessKey", { holdValue: true });
new Setting(paneEl).autoWireText("endpoint", { holdValue: true });
new Setting(paneEl).autoWireToggle("forcePathStyle", { holdValue: true });
new Setting(paneEl).autoWireText("accessKey", { holdValue: true });
new Setting(paneEl).autoWireText("secretKey", {
holdValue: true,
isPassword: true,
});
new Setting(paneEl).autoWireText("secretKey", {
holdValue: true,
isPassword: true,
});
new Setting(paneEl).autoWireText("region", { holdValue: true });
new Setting(paneEl).autoWireText("region", { holdValue: true });
new Setting(paneEl).autoWireText("bucket", { holdValue: true });
new Setting(paneEl).autoWireText("bucketPrefix", {
holdValue: true,
placeHolder: "vaultname/",
});
new Setting(paneEl).autoWireText("bucket", { holdValue: true });
new Setting(paneEl).autoWireText("bucketPrefix", {
holdValue: true,
placeHolder: "vaultname/",
});
new Setting(paneEl).autoWireToggle("useCustomRequestHandler", { holdValue: true });
new Setting(paneEl).autoWireTextArea("bucketCustomHeaders", {
holdValue: true,
placeHolder: "x-custom-header: value\n x-custom-header2: value2",
});
new Setting(paneEl).setName($msg("obsidianLiveSyncSettingTab.nameTestConnection")).addButton((button) =>
new Setting(paneEl).autoWireToggle("useCustomRequestHandler", { holdValue: true });
new Setting(paneEl).autoWireTextArea("bucketCustomHeaders", {
holdValue: true,
placeHolder: "x-custom-header: value\n x-custom-header2: value2",
});
new Setting(paneEl).setName($msg("obsidianLiveSyncSettingTab.nameTestConnection")).addButton((button) =>
button
.setButtonText($msg("obsidianLiveSyncSettingTab.btnTest"))
.setDisabled(false)
.onClick(async () => {
await this.testConnection(this.editingSettings);
})
);
new Setting(paneEl)
.setName($msg("obsidianLiveSyncSettingTab.nameApplySettings"))
.setClass("wizardHidden")
.addApplyButton([
"remoteType",
"endpoint",
"region",
"accessKey",
"secretKey",
"bucket",
"useCustomRequestHandler",
"bucketCustomHeaders",
"bucketPrefix",
])
.addOnUpdate(this.onlyOnMinIO);
}
);
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleCouchDB"), undefined, this.onlyOnCouchDB).then(
(paneEl) => {
if (this.services.API.isMobile()) {
this.createEl(
paneEl,
"div",
{
text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSWarning"),
},
undefined,
visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://"))
).addClass("op-warn");
} else {
this.createEl(
paneEl,
"div",
{
text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSInfo"),
},
undefined,
visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://"))
).addClass("op-warn-info");
}
new Setting(paneEl).autoWireText("couchDB_URI", {
holdValue: true,
onUpdate: this.enableOnlySyncDisabled,
});
new Setting(paneEl).autoWireToggle("useJWT", {
holdValue: true,
onUpdate: this.enableOnlySyncDisabled,
});
new Setting(paneEl).autoWireText("couchDB_USER", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => !this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireText("couchDB_PASSWORD", {
holdValue: true,
isPassword: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => !this.editingSettings.useJWT)
),
});
const algorithms = {
["HS256"]: "HS256",
["HS512"]: "HS512",
["ES256"]: "ES256",
["ES512"]: "ES512",
} as const;
new Setting(paneEl).autoWireDropDown("jwtAlgorithm", {
options: algorithms,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireTextArea("jwtKey", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
// eslint-disable-next-line prefer-const
let generatedKeyDivEl: HTMLDivElement;
new Setting(paneEl)
.setDesc("Generate ES256 Keypair for testing")
.addButton((button) =>
button.setButtonText("Generate").onClick(async () => {
const crypto = await getWebCrypto();
const keyPair = await crypto.subtle.generateKey({ name: "ECDSA", namedCurve: "P-256" }, true, [
"sign",
"verify",
]);
const pubKey = await crypto.subtle.exportKey("spki", keyPair.publicKey);
const privateKey = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
const encodedPublicKey = await arrayBufferToBase64Single(pubKey);
const encodedPrivateKey = await arrayBufferToBase64Single(privateKey);
const privateKeyPem = `> -----BEGIN PRIVATE KEY-----\n> ${encodedPrivateKey}\n> -----END PRIVATE KEY-----`;
const publicKeyPem = `> -----BEGIN PUBLIC KEY-----\\n${encodedPublicKey}\\n-----END PUBLIC KEY-----`;
const title = $msg("Setting.GenerateKeyPair.Title");
const msg = $msg("Setting.GenerateKeyPair.Desc", {
public_key: publicKeyPem,
private_key: privateKeyPem,
});
await MarkdownRenderer.render(
this.plugin.app,
"## " + title + "\n\n" + msg,
generatedKeyDivEl,
"/",
this.plugin
);
})
)
.addOnUpdate(
combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
)
);
generatedKeyDivEl = this.createEl(
paneEl,
"div",
{ text: "" },
(el) => {},
visibleOnly(() => this.editingSettings.useJWT)
);
new Setting(paneEl).autoWireText("jwtKid", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireText("jwtSub", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireNumeric("jwtExpDuration", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireText("couchDB_DBNAME", {
holdValue: true,
onUpdate: this.enableOnlySyncDisabled,
});
new Setting(paneEl).autoWireTextArea("couchDB_CustomHeaders", { holdValue: true });
new Setting(paneEl).autoWireToggle("useRequestAPI", {
holdValue: true,
onUpdate: this.enableOnlySyncDisabled,
});
new Setting(paneEl)
.setName($msg("obsidianLiveSyncSettingTab.nameTestDatabaseConnection"))
.setClass("wizardHidden")
.setDesc($msg("obsidianLiveSyncSettingTab.descTestDatabaseConnection"))
.addButton((button) =>
button
.setButtonText($msg("obsidianLiveSyncSettingTab.btnTest"))
.setDisabled(false)
.onClick(async () => {
await this.testConnection(this.editingSettings);
await this.testConnection();
})
);
new Setting(paneEl)
.setName($msg("obsidianLiveSyncSettingTab.nameApplySettings"))
.setClass("wizardHidden")
.addApplyButton([
"remoteType",
"endpoint",
"region",
"accessKey",
"secretKey",
"bucket",
"useCustomRequestHandler",
"bucketCustomHeaders",
"bucketPrefix",
])
.addOnUpdate(this.onlyOnMinIO);
}
);
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleCouchDB"), undefined, this.onlyOnCouchDB).then(
(paneEl) => {
if (this.services.API.isMobile()) {
this.createEl(
paneEl,
"div",
{
text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSWarning"),
},
undefined,
visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://"))
).addClass("op-warn");
} else {
this.createEl(
paneEl,
"div",
{
text: $msg("obsidianLiveSyncSettingTab.msgNonHTTPSInfo"),
},
undefined,
visibleOnly(() => !this.editingSettings.couchDB_URI.startsWith("https://"))
).addClass("op-warn-info");
}
new Setting(paneEl).autoWireText("couchDB_URI", {
holdValue: true,
onUpdate: this.enableOnlySyncDisabled,
});
new Setting(paneEl).autoWireToggle("useJWT", {
holdValue: true,
onUpdate: this.enableOnlySyncDisabled,
});
new Setting(paneEl).autoWireText("couchDB_USER", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => !this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireText("couchDB_PASSWORD", {
holdValue: true,
isPassword: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => !this.editingSettings.useJWT)
),
});
const algorithms = {
["HS256"]: "HS256",
["HS512"]: "HS512",
["ES256"]: "ES256",
["ES512"]: "ES512",
} as const;
new Setting(paneEl).autoWireDropDown("jwtAlgorithm", {
options: algorithms,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireTextArea("jwtKey", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
// eslint-disable-next-line prefer-const
let generatedKeyDivEl: HTMLDivElement;
new Setting(paneEl)
.setDesc("Generate ES256 Keypair for testing")
.addButton((button) =>
button.setButtonText("Generate").onClick(async () => {
const crypto = await getWebCrypto();
const keyPair = await crypto.subtle.generateKey(
{ name: "ECDSA", namedCurve: "P-256" },
true,
["sign", "verify"]
);
const pubKey = await crypto.subtle.exportKey("spki", keyPair.publicKey);
const privateKey = await crypto.subtle.exportKey("pkcs8", keyPair.privateKey);
const encodedPublicKey = await arrayBufferToBase64Single(pubKey);
const encodedPrivateKey = await arrayBufferToBase64Single(privateKey);
const privateKeyPem = `> -----BEGIN PRIVATE KEY-----\n> ${encodedPrivateKey}\n> -----END PRIVATE KEY-----`;
const publicKeyPem = `> -----BEGIN PUBLIC KEY-----\\n${encodedPublicKey}\\n-----END PUBLIC KEY-----`;
const title = $msg("Setting.GenerateKeyPair.Title");
const msg = $msg("Setting.GenerateKeyPair.Desc", {
public_key: publicKeyPem,
private_key: privateKeyPem,
});
await MarkdownRenderer.render(
this.plugin.app,
"## " + title + "\n\n" + msg,
generatedKeyDivEl,
"/",
this.plugin
);
new Setting(paneEl)
.setName($msg("obsidianLiveSyncSettingTab.nameValidateDatabaseConfig"))
.setDesc($msg("obsidianLiveSyncSettingTab.descValidateDatabaseConfig"))
.addButton((button) =>
button
.setButtonText($msg("obsidianLiveSyncSettingTab.btnCheck"))
.setDisabled(false)
.onClick(async () => {
await checkConfig(checkResultDiv);
})
)
.addOnUpdate(
combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
)
);
generatedKeyDivEl = this.createEl(
paneEl,
"div",
{ text: "" },
(el) => {},
visibleOnly(() => this.editingSettings.useJWT)
);
checkResultDiv = this.createEl(paneEl, "div", {
text: "",
});
new Setting(paneEl).autoWireText("jwtKid", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireText("jwtSub", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireNumeric("jwtExpDuration", {
holdValue: true,
onUpdate: combineOnUpdate(
this.enableOnlySyncDisabled,
visibleOnly(() => this.editingSettings.useJWT)
),
});
new Setting(paneEl).autoWireText("couchDB_DBNAME", {
holdValue: true,
onUpdate: this.enableOnlySyncDisabled,
});
new Setting(paneEl).autoWireTextArea("couchDB_CustomHeaders", { holdValue: true });
new Setting(paneEl).autoWireToggle("useRequestAPI", {
holdValue: true,
onUpdate: this.enableOnlySyncDisabled,
});
new Setting(paneEl)
.setName($msg("obsidianLiveSyncSettingTab.nameTestDatabaseConnection"))
.setClass("wizardHidden")
.setDesc($msg("obsidianLiveSyncSettingTab.descTestDatabaseConnection"))
.addButton((button) =>
button
.setButtonText($msg("obsidianLiveSyncSettingTab.btnTest"))
.setDisabled(false)
.onClick(async () => {
await this.testConnection();
})
);
new Setting(paneEl)
.setName($msg("obsidianLiveSyncSettingTab.nameValidateDatabaseConfig"))
.setDesc($msg("obsidianLiveSyncSettingTab.descValidateDatabaseConfig"))
.addButton((button) =>
button
.setButtonText($msg("obsidianLiveSyncSettingTab.btnCheck"))
.setDisabled(false)
.onClick(async () => {
await checkConfig(checkResultDiv);
})
);
checkResultDiv = this.createEl(paneEl, "div", {
text: "",
});
new Setting(paneEl)
.setName($msg("obsidianLiveSyncSettingTab.nameApplySettings"))
.setClass("wizardHidden")
.addApplyButton([
"remoteType",
"couchDB_URI",
"couchDB_USER",
"couchDB_PASSWORD",
"couchDB_DBNAME",
"jwtAlgorithm",
"jwtExpDuration",
"jwtKey",
"jwtSub",
"jwtKid",
"useJWT",
"couchDB_CustomHeaders",
"useRequestAPI",
])
.addOnUpdate(this.onlyOnCouchDB);
}
);
});
new Setting(paneEl)
.setName($msg("obsidianLiveSyncSettingTab.nameApplySettings"))
.setClass("wizardHidden")
.addApplyButton([
"remoteType",
"couchDB_URI",
"couchDB_USER",
"couchDB_PASSWORD",
"couchDB_DBNAME",
"jwtAlgorithm",
"jwtExpDuration",
"jwtKey",
"jwtSub",
"jwtKid",
"useJWT",
"couchDB_CustomHeaders",
"useRequestAPI",
])
.addOnUpdate(this.onlyOnCouchDB);
}
);
void addPanel(paneEl, $msg("obsidianLiveSyncSettingTab.titleNotification"), () => {}, this.onlyOnCouchDB).then(
(paneEl) => {
paneEl.addClass("wizardHidden");

View File

@@ -110,10 +110,10 @@
div.sls-setting-menu-btn {
color: var(--text-normal);
background-color: var(--background-secondary-alt);
border-radius: 4px 4px 0 0;
border-radius: 8px;
padding: 6px 10px;
cursor: pointer;
margin-right: 12px;
margin-right: 2px;
font-family: "Inter", sans-serif;
outline: none;
user-select: none;
@@ -140,9 +140,9 @@ div.sls-setting-menu-btn {
flex-grow: 1;
position: sticky;
top: 0;
background-color: rgba(var(--background-primary), 0.3);
backdrop-filter: blur(4px);
border-radius: 4px;
backdrop-filter: blur(15px);
padding: 4px;
border-radius: 10px;
z-index: 10;
}
@@ -437,13 +437,11 @@ div.workspace-leaf-content[data-type=bases] .livesync-status {
.sls-setting-panel-title {
position: sticky;
}
.sls-setting-panel-title {
top: 2em;
background-color: rgba(var(--background-primary), 0.3);
backdrop-filter: blur(4px);
border-radius: 30%;
font-size: medium;
top: 2.5em;
background-color: var(--background-secondary-alt);
border-radius: 10px;
padding: 0.5em 1.0em;
}
.sls-dialogue-note-wrapper {