mirror of
https://github.com/ankitects/anki.git
synced 2025-09-21 23:42:23 -04:00
Fix field description (#1923)
* Remove most of the original description placeholder implementation * Move description showing logic to RichTextInput - there is no need to propagate it to ContentEditable * Remove the @html from field-description This actually worked - however I removed it in case we'd rather offer markdown support or something else in the future. * Do not remove placeholder already on focus - Other editors do not do it either * Hide via hidden attribute instead of unmounting * Do not pass content to ContentEditable * Sort imports * Change placeholder text color (dae) In day mode, slightly-grey is almost indistinguishable from black (at least on the monitor I'm using here)
This commit is contained in:
parent
cd3f9ff646
commit
c1e54e6842
3 changed files with 57 additions and 38 deletions
|
@ -7,11 +7,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext } from "svelte";
|
import type { Writable } from "svelte/store";
|
||||||
import type { Readable, Writable } from "svelte/store";
|
|
||||||
|
|
||||||
import { updateAllState } from "../components/WithState.svelte";
|
import { updateAllState } from "../components/WithState.svelte";
|
||||||
import { descriptionKey } from "../lib/context-keys";
|
|
||||||
import actionList from "../sveltelib/action-list";
|
import actionList from "../sveltelib/action-list";
|
||||||
import type { MirrorAction } from "../sveltelib/dom-mirror";
|
import type { MirrorAction } from "../sveltelib/dom-mirror";
|
||||||
import type { SetupInputHandlerAction } from "../sveltelib/input-handler";
|
import type { SetupInputHandlerAction } from "../sveltelib/input-handler";
|
||||||
|
@ -35,15 +33,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
const [focusHandler, setupFocusHandling] = useFocusHandler();
|
const [focusHandler, setupFocusHandling] = useFocusHandler();
|
||||||
|
|
||||||
Object.assign(api, { focusHandler });
|
Object.assign(api, { focusHandler });
|
||||||
|
|
||||||
const description = getContext<Readable<string>>(descriptionKey);
|
|
||||||
$: descriptionCSSValue = `"${$description}"`;
|
|
||||||
|
|
||||||
export let content: string;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<anki-editable
|
<anki-editable
|
||||||
class:empty={!content}
|
|
||||||
contenteditable="true"
|
contenteditable="true"
|
||||||
use:resolve
|
use:resolve
|
||||||
use:setupFocusHandling
|
use:setupFocusHandling
|
||||||
|
@ -54,14 +46,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
on:blur
|
on:blur
|
||||||
on:click={updateAllState}
|
on:click={updateAllState}
|
||||||
on:keyup={updateAllState}
|
on:keyup={updateAllState}
|
||||||
style="--description: {descriptionCSSValue}"
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
anki-editable {
|
anki-editable {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 6px;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
/* fallback for iOS */
|
/* fallback for iOS */
|
||||||
|
@ -70,17 +61,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
&.empty::before {
|
|
||||||
content: var(--description);
|
|
||||||
opacity: 0.4;
|
|
||||||
cursor: text;
|
|
||||||
/* stay on single line */
|
|
||||||
position: absolute;
|
|
||||||
max-width: 95%;
|
|
||||||
overflow-x: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* editable-base.scss contains styling targeting user HTML */
|
/* editable-base.scss contains styling targeting user HTML */
|
||||||
|
|
|
@ -47,10 +47,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getAllContexts, onMount } from "svelte";
|
import { getAllContexts, getContext, onMount } from "svelte";
|
||||||
|
import type { Readable } from "svelte/store";
|
||||||
|
|
||||||
import { placeCaretAfterContent } from "../../domlib/place-caret";
|
import { placeCaretAfterContent } from "../../domlib/place-caret";
|
||||||
import ContentEditable from "../../editable/ContentEditable.svelte";
|
import ContentEditable from "../../editable/ContentEditable.svelte";
|
||||||
|
import {
|
||||||
|
descriptionKey,
|
||||||
|
directionKey,
|
||||||
|
fontFamilyKey,
|
||||||
|
fontSizeKey,
|
||||||
|
} from "../../lib/context-keys";
|
||||||
import { promiseWithResolver } from "../../lib/promise";
|
import { promiseWithResolver } from "../../lib/promise";
|
||||||
import { singleCallback } from "../../lib/typing";
|
import { singleCallback } from "../../lib/typing";
|
||||||
import useDOMMirror from "../../sveltelib/dom-mirror";
|
import useDOMMirror from "../../sveltelib/dom-mirror";
|
||||||
|
@ -68,6 +75,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
const { focusedInput } = noteEditorContext.get();
|
const { focusedInput } = noteEditorContext.get();
|
||||||
const { content, editingInputs } = editingAreaContext.get();
|
const { content, editingInputs } = editingAreaContext.get();
|
||||||
|
|
||||||
|
const description = getContext<Readable<string>>(descriptionKey);
|
||||||
|
const fontFamily = getContext<Readable<string>>(fontFamilyKey);
|
||||||
|
const fontSize = getContext<Readable<number>>(fontSizeKey);
|
||||||
|
const direction = getContext<Readable<"ltr" | "rtl">>(directionKey);
|
||||||
|
|
||||||
const nodes = getNormalizingNodeStore();
|
const nodes = getNormalizingNodeStore();
|
||||||
const [richTextPromise, resolve] = useRichTextResolve();
|
const [richTextPromise, resolve] = useRichTextResolve();
|
||||||
const { mirror, preventResubscription } = useDOMMirror();
|
const { mirror, preventResubscription } = useDOMMirror();
|
||||||
|
@ -148,7 +160,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
mirrors: [mirror],
|
mirrors: [mirror],
|
||||||
inputHandlers: [setupInputHandler, setupGlobalInputHandler],
|
inputHandlers: [setupInputHandler, setupGlobalInputHandler],
|
||||||
api: api.editable,
|
api: api.editable,
|
||||||
content: $content,
|
|
||||||
},
|
},
|
||||||
context: allContexts,
|
context: allContexts,
|
||||||
});
|
});
|
||||||
|
@ -160,6 +171,15 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
$editingInputs = $editingInputs;
|
$editingInputs = $editingInputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setFocus(): void {
|
||||||
|
$focusedInput = api;
|
||||||
|
|
||||||
|
// We do not unset focusedInput here.
|
||||||
|
// If we did, UI components for the input would react the store
|
||||||
|
// being unset, even though most likely it will be set to some other
|
||||||
|
// field right away.
|
||||||
|
}
|
||||||
|
|
||||||
$: pushUpdate(!hidden);
|
$: pushUpdate(!hidden);
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
|
@ -180,9 +200,23 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
setupLifecycleHooks(api);
|
setupLifecycleHooks(api);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="rich-text-input" on:focusin={() => ($focusedInput = api)}>
|
<div class="rich-text-input" on:focusin={setFocus} {hidden}>
|
||||||
|
{#if $content.length === 0}
|
||||||
|
<div
|
||||||
|
class="rich-text-placeholder"
|
||||||
|
style:font-family={$fontFamily}
|
||||||
|
style:font-size={$fontSize + "px"}
|
||||||
|
style:direction={$direction}
|
||||||
|
>
|
||||||
|
{$description}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<RichTextStyles
|
<RichTextStyles
|
||||||
color={$pageTheme.isDark ? "white" : "black"}
|
color={$pageTheme.isDark ? "white" : "black"}
|
||||||
|
fontFamily={$fontFamily}
|
||||||
|
fontSize={$fontSize}
|
||||||
|
direction={$direction}
|
||||||
callback={stylesResolve}
|
callback={stylesResolve}
|
||||||
let:attachToShadow={attachStyles}
|
let:attachToShadow={attachStyles}
|
||||||
let:stylesDidLoad
|
let:stylesDidLoad
|
||||||
|
@ -190,7 +224,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
<div
|
<div
|
||||||
bind:this={richTextDiv}
|
bind:this={richTextDiv}
|
||||||
class={className}
|
class={className}
|
||||||
class:hidden
|
|
||||||
class:night-mode={$pageTheme.isDark}
|
class:night-mode={$pageTheme.isDark}
|
||||||
use:attachShadow
|
use:attachShadow
|
||||||
use:attachStyles
|
use:attachStyles
|
||||||
|
@ -208,7 +241,17 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.hidden {
|
.rich-text-input {
|
||||||
display: none;
|
position: relative;
|
||||||
|
margin: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rich-text-placeholder {
|
||||||
|
position: absolute;
|
||||||
|
color: var(--disabled);
|
||||||
|
|
||||||
|
/* Adopts same size as the content editable element */
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,10 +3,6 @@ Copyright: Ankitects Pty Ltd and contributors
|
||||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { getContext } from "svelte";
|
|
||||||
import type { Readable } from "svelte/store";
|
|
||||||
|
|
||||||
import { directionKey, fontFamilyKey, fontSizeKey } from "../../lib/context-keys";
|
|
||||||
import { promiseWithResolver } from "../../lib/promise";
|
import { promiseWithResolver } from "../../lib/promise";
|
||||||
import type { StyleLinkType, StyleObject } from "./CustomStyles.svelte";
|
import type { StyleLinkType, StyleObject } from "./CustomStyles.svelte";
|
||||||
import CustomStyles from "./CustomStyles.svelte";
|
import CustomStyles from "./CustomStyles.svelte";
|
||||||
|
@ -25,9 +21,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
});
|
});
|
||||||
|
|
||||||
export let color: string;
|
export let color: string;
|
||||||
const fontFamily = getContext<Readable<string>>(fontFamilyKey);
|
export let fontFamily: string;
|
||||||
const fontSize = getContext<Readable<number>>(fontSizeKey);
|
export let fontSize: number;
|
||||||
const direction = getContext<Readable<"ltr" | "rtl">>(directionKey);
|
export let direction: "ltr" | "rtl";
|
||||||
|
|
||||||
async function setStyling(property: string, value: unknown): Promise<void> {
|
async function setStyling(property: string, value: unknown): Promise<void> {
|
||||||
const rule = await userBaseRule;
|
const rule = await userBaseRule;
|
||||||
|
@ -35,9 +31,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
|
|
||||||
$: setStyling("color", color);
|
$: setStyling("color", color);
|
||||||
$: setStyling("fontFamily", $fontFamily);
|
$: setStyling("fontFamily", fontFamily);
|
||||||
$: setStyling("fontSize", $fontSize + "px");
|
$: setStyling("fontSize", fontSize + "px");
|
||||||
$: setStyling("direction", $direction);
|
$: setStyling("direction", direction);
|
||||||
|
|
||||||
const styles = [
|
const styles = [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue