mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Join RichTextAPI and RichTextContextAPI + Expose anki/RichTextInput
(#1918)
* Format scss correctly so it passes ts:format * Use on and singleCallback in ImageHandle and MathjaxHandle * Add a few comments * Fix relict of partial commit * Fix 'element not found' in ImageHandle * Remove setting css on image handle twice * Remove use of container in ImageHandle * Remove use of container in MathjaxHandle * Use unprefixed properties of RichTextInputAPI * Inline api to get to RichTextInputAPI * Join customStyles into RichTextInputAPI * Export RichTextInput; Remove SetContext * Address eslint and svelte_check
This commit is contained in:
parent
336ad05693
commit
3969487e77
7 changed files with 142 additions and 136 deletions
|
@ -23,7 +23,8 @@ html {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
html,
|
||||||
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,13 @@ 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 { onDestroy, tick } from "svelte";
|
import { onMount, tick } from "svelte";
|
||||||
|
|
||||||
import ButtonDropdown from "../../components/ButtonDropdown.svelte";
|
import ButtonDropdown from "../../components/ButtonDropdown.svelte";
|
||||||
import WithDropdown from "../../components/WithDropdown.svelte";
|
import WithDropdown from "../../components/WithDropdown.svelte";
|
||||||
|
import { on } from "../../lib/events";
|
||||||
import * as tr from "../../lib/ftl";
|
import * as tr from "../../lib/ftl";
|
||||||
|
import { singleCallback } from "../../lib/typing";
|
||||||
import HandleBackground from "../HandleBackground.svelte";
|
import HandleBackground from "../HandleBackground.svelte";
|
||||||
import HandleControl from "../HandleControl.svelte";
|
import HandleControl from "../HandleControl.svelte";
|
||||||
import HandleLabel from "../HandleLabel.svelte";
|
import HandleLabel from "../HandleLabel.svelte";
|
||||||
|
@ -19,12 +21,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
export let maxWidth: number;
|
export let maxWidth: number;
|
||||||
export let maxHeight: number;
|
export let maxHeight: number;
|
||||||
|
|
||||||
const { container } = context.get();
|
const { element } = context.get();
|
||||||
|
|
||||||
$: {
|
|
||||||
container.style.setProperty("--editor-shrink-max-width", `${maxWidth}px`);
|
|
||||||
container.style.setProperty("--editor-shrink-max-height", `${maxHeight}px`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let activeImage: HTMLImageElement | null = null;
|
let activeImage: HTMLImageElement | null = null;
|
||||||
|
|
||||||
|
@ -59,11 +56,6 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
container.addEventListener("click", maybeShowHandle);
|
|
||||||
container.addEventListener("blur", resetHandle);
|
|
||||||
container.addEventListener("key", resetHandle);
|
|
||||||
container.addEventListener("paste", resetHandle);
|
|
||||||
|
|
||||||
$: naturalWidth = activeImage?.naturalWidth;
|
$: naturalWidth = activeImage?.naturalWidth;
|
||||||
$: naturalHeight = activeImage?.naturalHeight;
|
$: naturalHeight = activeImage?.naturalHeight;
|
||||||
$: aspectRatio = naturalWidth && naturalHeight ? naturalWidth / naturalHeight : NaN;
|
$: aspectRatio = naturalWidth && naturalHeight ? naturalWidth / naturalHeight : NaN;
|
||||||
|
@ -108,12 +100,19 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
});
|
});
|
||||||
|
|
||||||
$: observes = Boolean(activeImage);
|
$: observes = Boolean(activeImage);
|
||||||
$: if (observes) {
|
|
||||||
resizeObserver.observe(container);
|
async function toggleResizeObserver(observes: boolean) {
|
||||||
} else {
|
const container = await element;
|
||||||
resizeObserver.unobserve(container);
|
|
||||||
|
if (observes) {
|
||||||
|
resizeObserver.observe(container);
|
||||||
|
} else {
|
||||||
|
resizeObserver.unobserve(container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: toggleResizeObserver(observes);
|
||||||
|
|
||||||
/* memoized position of image on resize start
|
/* memoized position of image on resize start
|
||||||
* prevents frantic behavior when image shift into the next/previous line */
|
* prevents frantic behavior when image shift into the next/previous line */
|
||||||
let getDragWidth: (event: PointerEvent) => number;
|
let getDragWidth: (event: PointerEvent) => number;
|
||||||
|
@ -144,6 +143,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
target.setPointerCapture(pointerId);
|
target.setPointerCapture(pointerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let minResizeWidth: number;
|
||||||
|
let minResizeHeight: number;
|
||||||
$: [minResizeWidth, minResizeHeight] =
|
$: [minResizeWidth, minResizeHeight] =
|
||||||
aspectRatio > 1 ? [5 * aspectRatio, 5] : [5, 5 / aspectRatio];
|
aspectRatio > 1 ? [5 * aspectRatio, 5] : [5, 5 / aspectRatio];
|
||||||
|
|
||||||
|
@ -198,12 +199,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
activeImage!.removeAttribute("width");
|
activeImage!.removeAttribute("width");
|
||||||
}
|
}
|
||||||
|
|
||||||
onDestroy(() => {
|
onMount(async () => {
|
||||||
resizeObserver.disconnect();
|
const container = await element;
|
||||||
container.removeEventListener("click", maybeShowHandle);
|
|
||||||
container.removeEventListener("blur", resetHandle);
|
container.style.setProperty("--editor-shrink-max-width", `${maxWidth}px`);
|
||||||
container.removeEventListener("key", resetHandle);
|
container.style.setProperty("--editor-shrink-max-height", `${maxHeight}px`);
|
||||||
container.removeEventListener("paste", resetHandle);
|
|
||||||
|
return singleCallback(
|
||||||
|
on(container, "click", maybeShowHandle),
|
||||||
|
on(container, "blur", resetHandle),
|
||||||
|
on(container, "key" as any, resetHandle),
|
||||||
|
on(container, "paste", resetHandle),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let shrinkingDisabled: boolean;
|
let shrinkingDisabled: boolean;
|
||||||
|
@ -234,51 +241,55 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
let:dropdownObject
|
let:dropdownObject
|
||||||
>
|
>
|
||||||
{#if activeImage}
|
{#if activeImage}
|
||||||
<HandleSelection
|
{#await element then container}
|
||||||
bind:updateSelection
|
<HandleSelection
|
||||||
{container}
|
bind:updateSelection
|
||||||
image={activeImage}
|
{container}
|
||||||
on:mount={(event) => createDropdown(event.detail.selection)}
|
image={activeImage}
|
||||||
>
|
on:mount={(event) => createDropdown(event.detail.selection)}
|
||||||
<HandleBackground
|
>
|
||||||
on:dblclick={() => {
|
<HandleBackground
|
||||||
if (shrinkingDisabled) {
|
on:dblclick={() => {
|
||||||
return;
|
if (shrinkingDisabled) {
|
||||||
}
|
return;
|
||||||
toggleActualSize();
|
}
|
||||||
updateSizesWithDimensions();
|
toggleActualSize();
|
||||||
dropdownObject.update();
|
updateSizesWithDimensions();
|
||||||
}}
|
dropdownObject.update();
|
||||||
/>
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
<HandleLabel on:mount={updateDimensions}>
|
<HandleLabel on:mount={updateDimensions}>
|
||||||
{#if isSizeConstrained}
|
{#if isSizeConstrained}
|
||||||
<span>{tr.editingDoubleClickToExpand()}</span>
|
<span>{tr.editingDoubleClickToExpand()}</span>
|
||||||
{:else}
|
{:else}
|
||||||
<span>{actualWidth}×{actualHeight}</span>
|
<span>{actualWidth}×{actualHeight}</span>
|
||||||
{#if customDimensions}
|
{#if customDimensions}
|
||||||
<span>(Original: {naturalWidth}×{naturalHeight})</span>
|
<span>(Original: {naturalWidth}×{naturalHeight})</span
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
</HandleLabel>
|
||||||
</HandleLabel>
|
|
||||||
|
<HandleControl
|
||||||
|
active={!isSizeConstrained}
|
||||||
|
activeSize={8}
|
||||||
|
offsetX={5}
|
||||||
|
offsetY={5}
|
||||||
|
on:pointerclick={(event) => {
|
||||||
|
if (!isSizeConstrained) {
|
||||||
|
setPointerCapture(event);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
on:pointermove={(event) => {
|
||||||
|
resize(event);
|
||||||
|
updateSizesWithDimensions();
|
||||||
|
dropdownObject.update();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</HandleSelection>
|
||||||
|
{/await}
|
||||||
|
|
||||||
<HandleControl
|
|
||||||
active={!isSizeConstrained}
|
|
||||||
activeSize={8}
|
|
||||||
offsetX={5}
|
|
||||||
offsetY={5}
|
|
||||||
on:pointerclick={(event) => {
|
|
||||||
if (!isSizeConstrained) {
|
|
||||||
setPointerCapture(event);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
on:pointermove={(event) => {
|
|
||||||
resize(event);
|
|
||||||
updateSizesWithDimensions();
|
|
||||||
dropdownObject.update();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</HandleSelection>
|
|
||||||
<ButtonDropdown on:click={updateSizesWithDimensions}>
|
<ButtonDropdown on:click={updateSizesWithDimensions}>
|
||||||
<FloatButtons image={activeImage} on:update={dropdownObject.update} />
|
<FloatButtons image={activeImage} on:update={dropdownObject.update} />
|
||||||
<SizeSelect
|
<SizeSelect
|
||||||
|
|
|
@ -12,14 +12,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import { Mathjax } from "../../editable/mathjax-element";
|
import { Mathjax } from "../../editable/mathjax-element";
|
||||||
import { on } from "../../lib/events";
|
import { on } from "../../lib/events";
|
||||||
import { noop } from "../../lib/functional";
|
import { noop } from "../../lib/functional";
|
||||||
|
import { singleCallback } from "../../lib/typing";
|
||||||
import HandleBackground from "../HandleBackground.svelte";
|
import HandleBackground from "../HandleBackground.svelte";
|
||||||
import HandleControl from "../HandleControl.svelte";
|
import HandleControl from "../HandleControl.svelte";
|
||||||
import HandleSelection from "../HandleSelection.svelte";
|
import HandleSelection from "../HandleSelection.svelte";
|
||||||
import { context } from "../rich-text-input";
|
import { context } from "../rich-text-input";
|
||||||
import MathjaxMenu from "./MathjaxMenu.svelte";
|
import MathjaxMenu from "./MathjaxMenu.svelte";
|
||||||
|
|
||||||
const { container, api } = context.get();
|
const { editable, element, preventResubscription } = context.get();
|
||||||
const { editable, preventResubscription } = api;
|
|
||||||
|
|
||||||
let activeImage: HTMLImageElement | null = null;
|
let activeImage: HTMLImageElement | null = null;
|
||||||
let mathjaxElement: HTMLElement | null = null;
|
let mathjaxElement: HTMLElement | null = null;
|
||||||
|
@ -76,6 +76,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
async function maybeShowHandle({ target }: Event): Promise<void> {
|
async function maybeShowHandle({ target }: Event): Promise<void> {
|
||||||
await resetHandle();
|
await resetHandle();
|
||||||
|
|
||||||
if (target instanceof HTMLImageElement && target.dataset.anki === "mathjax") {
|
if (target instanceof HTMLImageElement && target.dataset.anki === "mathjax") {
|
||||||
showHandle(target);
|
showHandle(target);
|
||||||
}
|
}
|
||||||
|
@ -107,20 +108,14 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
showHandle(detail);
|
showHandle(detail);
|
||||||
}
|
}
|
||||||
|
|
||||||
onMount(() => {
|
onMount(async () => {
|
||||||
const removeClick = on(container, "click", maybeShowHandle);
|
const container = await element;
|
||||||
const removeCaretAfter = on(
|
|
||||||
container,
|
|
||||||
"movecaretafter" as any,
|
|
||||||
showAutofocusHandle,
|
|
||||||
);
|
|
||||||
const removeSelectAll = on(container, "selectall" as any, showSelectAll);
|
|
||||||
|
|
||||||
return () => {
|
return singleCallback(
|
||||||
removeClick();
|
on(container, "click", maybeShowHandle),
|
||||||
removeCaretAfter();
|
on(container, "movecaretafter" as any, showAutofocusHandle),
|
||||||
removeSelectAll();
|
on(container, "selectall" as any, showSelectAll),
|
||||||
};
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let updateSelection: () => Promise<void>;
|
let updateSelection: () => Promise<void>;
|
||||||
|
@ -136,7 +131,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
const resizeObserver = new ResizeObserver(onImageResize);
|
const resizeObserver = new ResizeObserver(onImageResize);
|
||||||
|
|
||||||
let clearResize = noop;
|
let clearResize = noop;
|
||||||
function handleImageResizing(activeImage: HTMLImageElement | null) {
|
async function handleImageResizing(activeImage: HTMLImageElement | null) {
|
||||||
|
const container = await element;
|
||||||
|
|
||||||
if (activeImage) {
|
if (activeImage) {
|
||||||
resizeObserver.observe(container);
|
resizeObserver.observe(container);
|
||||||
clearResize = on(activeImage, "resize", onImageResize);
|
clearResize = on(activeImage, "resize", onImageResize);
|
||||||
|
@ -172,16 +169,18 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
resetHandle();
|
resetHandle();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<HandleSelection
|
{#await element then container}
|
||||||
image={activeImage}
|
<HandleSelection
|
||||||
{container}
|
image={activeImage}
|
||||||
bind:updateSelection
|
{container}
|
||||||
on:mount={(event) =>
|
bind:updateSelection
|
||||||
(dropdownApi = createDropdown(event.detail.selection))}
|
on:mount={(event) =>
|
||||||
>
|
(dropdownApi = createDropdown(event.detail.selection))}
|
||||||
<HandleBackground tooltip={errorMessage} />
|
>
|
||||||
<HandleControl offsetX={1} offsetY={1} />
|
<HandleBackground tooltip={errorMessage} />
|
||||||
</HandleSelection>
|
<HandleControl offsetX={1} offsetY={1} />
|
||||||
|
</HandleSelection>
|
||||||
|
{/await}
|
||||||
</MathjaxMenu>
|
</MathjaxMenu>
|
||||||
{/if}
|
{/if}
|
||||||
</WithDropdown>
|
</WithDropdown>
|
||||||
|
|
|
@ -4,23 +4,21 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
-->
|
-->
|
||||||
<script context="module" lang="ts">
|
<script context="module" lang="ts">
|
||||||
import type { ContentEditableAPI } from "../../editable/ContentEditable.svelte";
|
import type { ContentEditableAPI } from "../../editable/ContentEditable.svelte";
|
||||||
import { singleCallback } from "../../lib/typing";
|
|
||||||
import useContextProperty from "../../sveltelib/context-property";
|
|
||||||
import useDOMMirror from "../../sveltelib/dom-mirror";
|
|
||||||
import type { InputHandlerAPI } from "../../sveltelib/input-handler";
|
import type { InputHandlerAPI } from "../../sveltelib/input-handler";
|
||||||
import useInputHandler from "../../sveltelib/input-handler";
|
|
||||||
import { pageTheme } from "../../sveltelib/theme";
|
|
||||||
import type { EditingInputAPI, FocusableInputAPI } from "../EditingArea.svelte";
|
import type { EditingInputAPI, FocusableInputAPI } from "../EditingArea.svelte";
|
||||||
import type CustomStyles from "./CustomStyles.svelte";
|
import type CustomStyles from "./CustomStyles.svelte";
|
||||||
|
|
||||||
export interface RichTextInputAPI extends EditingInputAPI {
|
export interface RichTextInputAPI extends EditingInputAPI {
|
||||||
name: "rich-text";
|
name: "rich-text";
|
||||||
|
/** This is the contentEditable anki-editable element */
|
||||||
element: Promise<HTMLElement>;
|
element: Promise<HTMLElement>;
|
||||||
moveCaretToEnd(): void;
|
moveCaretToEnd(): void;
|
||||||
toggle(): boolean;
|
toggle(): boolean;
|
||||||
preventResubscription(): () => void;
|
preventResubscription(): () => void;
|
||||||
inputHandler: InputHandlerAPI;
|
inputHandler: InputHandlerAPI;
|
||||||
|
/** The API exposed by the editable component */
|
||||||
editable: ContentEditableAPI;
|
editable: ContentEditableAPI;
|
||||||
|
customStyles: Promise<CustomStyles>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function editingInputIsRichText(
|
export function editingInputIsRichText(
|
||||||
|
@ -29,16 +27,21 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
return editingInput?.name === "rich-text";
|
return editingInput?.name === "rich-text";
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RichTextInputContextAPI {
|
import { registerPackage } from "../../lib/runtime-require";
|
||||||
styles: CustomStyles;
|
import contextProperty from "../../sveltelib/context-property";
|
||||||
container: HTMLElement;
|
import lifecycleHooks from "../../sveltelib/lifecycle-hooks";
|
||||||
api: RichTextInputAPI;
|
|
||||||
}
|
|
||||||
|
|
||||||
const key = Symbol("richText");
|
const key = Symbol("richText");
|
||||||
const [context, setContextProperty] =
|
const [context, setContextProperty] = contextProperty<RichTextInputAPI>(key);
|
||||||
useContextProperty<RichTextInputContextAPI>(key);
|
|
||||||
const [globalInputHandler, setupGlobalInputHandler] = useInputHandler();
|
const [globalInputHandler, setupGlobalInputHandler] = useInputHandler();
|
||||||
|
const [lifecycle, instances, setupLifecycleHooks] =
|
||||||
|
lifecycleHooks<RichTextInputAPI>();
|
||||||
|
|
||||||
|
registerPackage("anki/RichTextInput", {
|
||||||
|
context,
|
||||||
|
lifecycle,
|
||||||
|
instances,
|
||||||
|
});
|
||||||
|
|
||||||
export { context, globalInputHandler as inputHandler };
|
export { context, globalInputHandler as inputHandler };
|
||||||
</script>
|
</script>
|
||||||
|
@ -48,12 +51,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
|
|
||||||
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 { promiseWithResolver } from "../../lib/promise";
|
||||||
|
import { singleCallback } from "../../lib/typing";
|
||||||
|
import useDOMMirror from "../../sveltelib/dom-mirror";
|
||||||
|
import useInputHandler from "../../sveltelib/input-handler";
|
||||||
|
import { pageTheme } from "../../sveltelib/theme";
|
||||||
import { context as editingAreaContext } from "../EditingArea.svelte";
|
import { context as editingAreaContext } from "../EditingArea.svelte";
|
||||||
import { context as noteEditorContext } from "../NoteEditor.svelte";
|
import { context as noteEditorContext } from "../NoteEditor.svelte";
|
||||||
import getNormalizingNodeStore from "./normalizing-node-store";
|
import getNormalizingNodeStore from "./normalizing-node-store";
|
||||||
import useRichTextResolve from "./rich-text-resolve";
|
import useRichTextResolve from "./rich-text-resolve";
|
||||||
import RichTextStyles from "./RichTextStyles.svelte";
|
import RichTextStyles from "./RichTextStyles.svelte";
|
||||||
import SetContext from "./SetContext.svelte";
|
|
||||||
import { fragmentToStored, storedToFragment } from "./transform";
|
import { fragmentToStored, storedToFragment } from "./transform";
|
||||||
|
|
||||||
export let hidden: boolean;
|
export let hidden: boolean;
|
||||||
|
@ -65,6 +72,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
const [richTextPromise, resolve] = useRichTextResolve();
|
const [richTextPromise, resolve] = useRichTextResolve();
|
||||||
const { mirror, preventResubscription } = useDOMMirror();
|
const { mirror, preventResubscription } = useDOMMirror();
|
||||||
const [inputHandler, setupInputHandler] = useInputHandler();
|
const [inputHandler, setupInputHandler] = useInputHandler();
|
||||||
|
const [customStyles, stylesResolve] = promiseWithResolver<CustomStyles>();
|
||||||
|
|
||||||
export function attachShadow(element: Element): void {
|
export function attachShadow(element: Element): void {
|
||||||
element.attachShadow({ mode: "open" });
|
element.attachShadow({ mode: "open" });
|
||||||
|
@ -123,6 +131,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
preventResubscription,
|
preventResubscription,
|
||||||
inputHandler,
|
inputHandler,
|
||||||
editable: {} as ContentEditableAPI,
|
editable: {} as ContentEditableAPI,
|
||||||
|
customStyles,
|
||||||
};
|
};
|
||||||
|
|
||||||
const allContexts = getAllContexts();
|
const allContexts = getAllContexts();
|
||||||
|
@ -165,13 +174,16 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setContextProperty(api);
|
||||||
|
setupLifecycleHooks(api);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="rich-text-input" on:focusin={() => ($focusedInput = api)}>
|
<div class="rich-text-input" on:focusin={() => ($focusedInput = api)}>
|
||||||
<RichTextStyles
|
<RichTextStyles
|
||||||
color={$pageTheme.isDark ? "white" : "black"}
|
color={$pageTheme.isDark ? "white" : "black"}
|
||||||
|
callback={stylesResolve}
|
||||||
let:attachToShadow={attachStyles}
|
let:attachToShadow={attachStyles}
|
||||||
let:promise={stylesPromise}
|
|
||||||
let:stylesDidLoad
|
let:stylesDidLoad
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
@ -186,16 +198,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
on:focusout
|
on:focusout
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="rich-text-widgets">
|
{#await Promise.all([richTextPromise, stylesDidLoad]) then _}
|
||||||
{#await Promise.all( [richTextPromise, stylesPromise], ) then [container, styles]}
|
<div class="rich-text-widgets">
|
||||||
<SetContext
|
<slot />
|
||||||
setter={setContextProperty}
|
</div>
|
||||||
value={{ container, styles, api }}
|
{/await}
|
||||||
>
|
|
||||||
<slot />
|
|
||||||
</SetContext>
|
|
||||||
{/await}
|
|
||||||
</div>
|
|
||||||
</RichTextStyles>
|
</RichTextStyles>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -11,15 +11,12 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
import type { StyleLinkType, StyleObject } from "./CustomStyles.svelte";
|
import type { StyleLinkType, StyleObject } from "./CustomStyles.svelte";
|
||||||
import CustomStyles from "./CustomStyles.svelte";
|
import CustomStyles from "./CustomStyles.svelte";
|
||||||
|
|
||||||
const [promise, customStylesResolve] = promiseWithResolver<CustomStyles>();
|
export let callback: (styles: CustomStyles) => void;
|
||||||
|
|
||||||
const [userBaseStyle, userBaseResolve] = promiseWithResolver<StyleObject>();
|
const [userBaseStyle, userBaseResolve] = promiseWithResolver<StyleObject>();
|
||||||
const [userBaseRule, userBaseRuleResolve] = promiseWithResolver<CSSStyleRule>();
|
const [userBaseRule, userBaseRuleResolve] = promiseWithResolver<CSSStyleRule>();
|
||||||
|
|
||||||
const stylesDidLoad: Promise<unknown> = Promise.all([
|
const stylesDidLoad: Promise<unknown> = Promise.all([userBaseStyle, userBaseRule]);
|
||||||
promise,
|
|
||||||
userBaseStyle,
|
|
||||||
userBaseRule,
|
|
||||||
]);
|
|
||||||
|
|
||||||
userBaseStyle.then((baseStyle: StyleObject) => {
|
userBaseStyle.then((baseStyle: StyleObject) => {
|
||||||
const sheet = baseStyle.element.sheet as CSSStyleSheet;
|
const sheet = baseStyle.element.sheet as CSSStyleSheet;
|
||||||
|
@ -56,9 +53,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
||||||
props: { styles },
|
props: { styles },
|
||||||
});
|
});
|
||||||
|
|
||||||
customStyles.addStyleTag("userBase").then(userBaseResolve);
|
customStyles.addStyleTag("userBase").then((styleTag) => {
|
||||||
customStylesResolve(customStyles);
|
userBaseResolve(styleTag);
|
||||||
|
callback(customStyles);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<slot {attachToShadow} {promise} {stylesDidLoad} />
|
<slot {attachToShadow} {stylesDidLoad} />
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
<!--
|
|
||||||
Copyright: Ankitects Pty Ltd and contributors
|
|
||||||
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
||||||
-->
|
|
||||||
<script lang="ts">
|
|
||||||
export let setter: (value: any) => void;
|
|
||||||
export let value: any;
|
|
||||||
|
|
||||||
setter(value);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<slot />
|
|
|
@ -18,6 +18,7 @@ type AnkiPackages =
|
||||||
| "anki/NoteEditor"
|
| "anki/NoteEditor"
|
||||||
| "anki/EditorField"
|
| "anki/EditorField"
|
||||||
| "anki/PlainTextInput"
|
| "anki/PlainTextInput"
|
||||||
|
| "anki/RichTextInput"
|
||||||
| "anki/TemplateButtons"
|
| "anki/TemplateButtons"
|
||||||
| "anki/packages"
|
| "anki/packages"
|
||||||
| "anki/bridgecommand"
|
| "anki/bridgecommand"
|
||||||
|
|
Loading…
Reference in a new issue