Better RTL support

This commit is contained in:
Henrik Giesel 2021-07-21 16:48:02 +02:00 committed by Damien Elmes
parent eb71c97872
commit c6e56e0465
8 changed files with 111 additions and 60 deletions

View file

@ -21,6 +21,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export let size: number | undefined = undefined; export let size: number | undefined = undefined;
export let wrap: boolean | undefined = undefined; export let wrap: boolean | undefined = undefined;
export let reverse = false;
$: buttonSize = size ? `--buttons-size: ${size}rem; ` : ""; $: buttonSize = size ? `--buttons-size: ${size}rem; ` : "";
let buttonWrap: string; let buttonWrap: string;
$: if (wrap === undefined) { $: if (wrap === undefined) {
@ -95,7 +97,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<div <div
bind:this={buttonGroupRef} bind:this={buttonGroupRef}
{id} {id}
class={`btn-group ${className}`} class="btn-group {className}"
class:reverse
{style} {style}
dir="ltr" dir="ltr"
role="group" role="group"
@ -110,8 +113,13 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<style lang="scss"> <style lang="scss">
div { div {
flex-direction: row;
flex-wrap: var(--buttons-wrap); flex-wrap: var(--buttons-wrap);
padding: calc(var(--buttons-size) / 10); padding: calc(var(--buttons-size) / 10);
margin: 0; margin: 0;
} }
.reverse {
flex-direction: row-reverse;
}
</style> </style>

View file

@ -18,6 +18,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export let iconSize: number = 75; export let iconSize: number = 75;
export let widthMultiplier: number = 1; export let widthMultiplier: number = 1;
export let flipX: boolean = false;
let buttonRef: HTMLButtonElement; let buttonRef: HTMLButtonElement;
@ -44,7 +45,9 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
on:click on:click
on:mousedown|preventDefault on:mousedown|preventDefault
> >
<span style={`--width-multiplier: ${widthMultiplier};`}> <slot /> </span> <span class:flip-x={flipX} style={`--width-multiplier: ${widthMultiplier};`}>
<slot />
</span>
</button> </button>
<style lang="scss"> <style lang="scss">
@ -80,6 +83,11 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
fill: currentColor; fill: currentColor;
vertical-align: unset; vertical-align: unset;
} }
&.flip-x > :global(svg),
&.flip-x > :global(img) {
transform: scaleX(-1);
}
} }
.dropdown-toggle::after { .dropdown-toggle::after {

View file

@ -3,7 +3,7 @@ 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="typescript"> <script lang="typescript">
import ImageHandleButtons from "./ImageHandleButtons.svelte"; import ImageHandleFloat from "./ImageHandleFloat.svelte";
import ImageHandleSizeSelect from "./ImageHandleSizeSelect.svelte"; import ImageHandleSizeSelect from "./ImageHandleSizeSelect.svelte";
import { getContext } from "svelte"; import { getContext } from "svelte";
@ -11,6 +11,8 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export let image: HTMLImageElement | null = null; export let image: HTMLImageElement | null = null;
export let imageRule: CSSStyleRule | null = null; export let imageRule: CSSStyleRule | null = null;
export let isRtl: boolean = false;
export let container: HTMLElement; export let container: HTMLElement;
$: showDimensions = image $: showDimensions = image
@ -37,9 +39,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
function updateSizes() { function updateSizes() {
const imageRect = image!.getBoundingClientRect(); const imageRect = image!.getBoundingClientRect();
const containerRect = ( const containerRect = container.getBoundingClientRect();
container ?? document.documentElement
).getBoundingClientRect();
naturalWidth = image!.naturalWidth; naturalWidth = image!.naturalWidth;
naturalHeight = image!.naturalHeight; naturalHeight = image!.naturalHeight;
@ -100,21 +100,22 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
class="image-handle-selection" class="image-handle-selection"
> >
<div class="image-handle-bg" on:dblclick={onDblclick} /> <div class="image-handle-bg" on:dblclick={onDblclick} />
<div class="image-handle-buttons"> <div class="image-handle-buttons" class:is-rtl={isRtl}>
<ImageHandleButtons bind:float={image.style.float} /> <ImageHandleFloat {isRtl} bind:float={image.style.float} />
</div> </div>
<div class="image-handle-size-select"> <div class="image-handle-size-select" class:is-rtl={isRtl}>
<ImageHandleSizeSelect <ImageHandleSizeSelect
bind:this={sizeSelect} bind:this={sizeSelect}
bind:active bind:active
{selector}
{image} {image}
{imageRule} {imageRule}
{selector}
{isRtl}
on:update={updateSizes} on:update={updateSizes}
/> />
</div> </div>
{#if showDimensions} {#if showDimensions}
<div class="image-handle-dimensions"> <div class="image-handle-dimensions" class:is-rtl={isRtl}>
{width}&times;{height} (Original: {naturalWidth}&times;{naturalHeight}) {width}&times;{height} (Original: {naturalWidth}&times;{naturalHeight})
</div> </div>
{/if} {/if}
@ -159,24 +160,40 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
.image-handle-buttons { .image-handle-buttons {
top: 3px; top: 3px;
left: 3px; left: 3px;
&.is-rtl {
left: auto;
right: 3px;
}
} }
.image-handle-size-select { .image-handle-size-select {
bottom: 3px; bottom: 3px;
left: 3px; left: 3px;
&.is-rtl {
left: auto;
right: 3px;
}
} }
.image-handle-dimensions { .image-handle-dimensions {
pointer-events: none; pointer-events: none;
user-select: none; user-select: none;
bottom: 3px;
right: 3px;
font-size: 13px; font-size: 13px;
background-color: rgba(0 0 0 / 0.3); background-color: rgba(0 0 0 / 0.3);
border-color: black; border-color: black;
border-radius: 0.25rem; border-radius: 0.25rem;
padding: 0 5px; padding: 0 5px;
bottom: 3px;
right: 3px;
&.is-rtl {
right: auto;
left: 3px;
}
} }
.image-handle-control { .image-handle-control {

View file

@ -1,44 +0,0 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="typescript">
import * as tr from "lib/i18n";
import ButtonToolbar from "components/ButtonToolbar.svelte";
import ButtonGroup from "components/ButtonGroup.svelte";
import ButtonGroupItem from "components/ButtonGroupItem.svelte";
import IconButton from "components/IconButton.svelte";
import { floatNoneIcon, floatLeftIcon, floatRightIcon } from "./icons";
export let float: string;
</script>
<ButtonToolbar size={1.6} wrap={false}>
<ButtonGroup>
<ButtonGroupItem>
<IconButton
tooltip={tr.editingFloatNone()}
active={float === "" || float === "none"}
on:click={() => (float = "")}>{@html floatNoneIcon}</IconButton
>
</ButtonGroupItem>
<ButtonGroupItem>
<IconButton
tooltip={tr.editingFloatLeft()}
active={float === "left"}
on:click={() => (float = "left")}>{@html floatLeftIcon}</IconButton
>
</ButtonGroupItem>
<ButtonGroupItem>
<IconButton
tooltip={tr.editingFloatRight()}
active={float === "right"}
on:click={() => (float = "right")}>{@html floatRightIcon}</IconButton
>
</ButtonGroupItem>
</ButtonGroup>
</ButtonToolbar>

View file

@ -0,0 +1,61 @@
<!--
Copyright: Ankitects Pty Ltd and contributors
License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
-->
<script lang="typescript">
import * as tr from "lib/i18n";
import ButtonGroup from "components/ButtonGroup.svelte";
import ButtonGroupItem from "components/ButtonGroupItem.svelte";
import IconButton from "components/IconButton.svelte";
import { floatNoneIcon, floatLeftIcon, floatRightIcon } from "./icons";
export let float: string;
export let isRtl: boolean;
const leftValues = {
position: "left",
label: tr.editingFloatLeft(),
icon: floatLeftIcon,
};
const rightValues = {
position: "right",
label: tr.editingFloatRight(),
};
$: inlineStart = isRtl ? rightValues : leftValues;
$: inlineEnd = isRtl ? leftValues : rightValues;
</script>
<ButtonGroup size={1.6} wrap={false} reverse={isRtl}>
<ButtonGroupItem>
<IconButton
tooltip={tr.editingFloatNone()}
active={float === "" || float === "none"}
flipX={isRtl}
on:click={() => (float = "")}>{@html floatNoneIcon}</IconButton
>
</ButtonGroupItem>
<ButtonGroupItem>
<IconButton
tooltip={inlineStart.label}
active={float === inlineStart.position}
flipX={isRtl}
on:click={() => (float = inlineStart.position)}
>{@html floatLeftIcon}</IconButton
>
</ButtonGroupItem>
<ButtonGroupItem>
<IconButton
tooltip={inlineEnd.label}
active={float === inlineEnd.position}
flipX={isRtl}
on:click={() => (float = inlineEnd.position)}
>{@html floatRightIcon}</IconButton
>
</ButtonGroupItem>
</ButtonGroup>

View file

@ -16,6 +16,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
export let imageRule: CSSStyleRule; export let imageRule: CSSStyleRule;
export let selector: string; export let selector: string;
export let active: boolean; export let active: boolean;
export let isRtl: boolean;
$: icon = active ? sizeActual : sizeMinimized; $: icon = active ? sizeActual : sizeMinimized;
@ -42,6 +43,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
<ButtonGroupItem> <ButtonGroupItem>
<IconButton <IconButton
{active} {active}
flipX={isRtl}
tooltip={tr.editingActualSize()} tooltip={tr.editingActualSize()}
on:click={toggleActualSize}>{@html icon}</IconButton on:click={toggleActualSize}>{@html icon}</IconButton
> >

View file

@ -58,8 +58,6 @@ export class EditableContainer extends HTMLDivElement {
} }
isRightToLeft(): boolean { isRightToLeft(): boolean {
const styleSheet = this.baseStyle.sheet as CSSStyleSheet; return this.baseRule!.style.direction === "rtl";
const firstRule = styleSheet.cssRules[0] as CSSStyleRule;
return firstRule.style.direction === "rtl";
} }
} }

View file

@ -171,6 +171,7 @@ export class EditingArea extends HTMLDivElement {
(this.imageHandle as any).$set({ (this.imageHandle as any).$set({
image: event.target, image: event.target,
imageRule: this.editableContainer.imageRule, imageRule: this.editableContainer.imageRule,
isRtl: this.isRightToLeft(),
}); });
} else { } else {
(this.imageHandle as any).$set({ (this.imageHandle as any).$set({