mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-03 21:08:18 +00:00
Add suffix widget non-rounding; add disabled state to many widgets
This commit is contained in:
parent
ff75e0eae9
commit
a1e061fa14
28 changed files with 218 additions and 63 deletions
|
@ -99,6 +99,11 @@ img {
|
|||
display: block;
|
||||
}
|
||||
|
||||
.sharp-right-corners.sharp-right-corners.sharp-right-corners.sharp-right-corners {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.layout-row,
|
||||
.layout-col {
|
||||
.scrollable-x,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<template>
|
||||
<div class="widget-layout">
|
||||
<component :is="LayoutGroupType(layoutRow)" :widgetData="layoutRow" :layoutTarget="layout.layoutTarget" v-for="(layoutRow, index) in layout.layout" :key="index" />
|
||||
<component :is="layoutGroupType(layoutRow)" :widgetData="layoutRow" :layoutTarget="layout.layoutTarget" v-for="(layoutRow, index) in layout.layout" :key="index" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -28,7 +28,7 @@ export default defineComponent({
|
|||
layout: { type: Object as PropType<WidgetLayout>, required: true },
|
||||
},
|
||||
methods: {
|
||||
LayoutGroupType(layoutRow: LayoutGroup): unknown {
|
||||
layoutGroupType(layoutRow: LayoutGroup): unknown {
|
||||
if (isWidgetColumn(layoutRow)) return WidgetRow;
|
||||
if (isWidgetRow(layoutRow)) return WidgetRow;
|
||||
if (isWidgetSection(layoutRow)) return WidgetSection;
|
||||
|
@ -36,10 +36,6 @@ export default defineComponent({
|
|||
throw new Error("Layout row type does not exist");
|
||||
},
|
||||
},
|
||||
data: () => ({
|
||||
isWidgetRow,
|
||||
isWidgetSection,
|
||||
}),
|
||||
components: {
|
||||
WidgetRow,
|
||||
WidgetSection,
|
||||
|
|
|
@ -3,17 +3,30 @@
|
|||
|
||||
<template>
|
||||
<div :class="`widget-${direction}`">
|
||||
<template v-for="(component, index) in widgets" :key="index">
|
||||
<template v-for="([component, nextIsSuffix], index) in widgetsAndNextSiblingIsSuffix" :key="index">
|
||||
<CheckboxInput v-if="component.props.kind === 'CheckboxInput'" v-bind="component.props" @update:checked="(value: boolean) => updateLayout(component.widgetId, value)" />
|
||||
<ColorInput v-if="component.props.kind === 'ColorInput'" v-bind="component.props" v-model:open="open" @update:value="(value: unknown) => updateLayout(component.widgetId, value)" />
|
||||
<ColorInput
|
||||
v-if="component.props.kind === 'ColorInput'"
|
||||
v-bind="component.props"
|
||||
v-model:open="open"
|
||||
@update:value="(value: unknown) => updateLayout(component.widgetId, value)"
|
||||
:sharpRightCorners="nextIsSuffix"
|
||||
/>
|
||||
<DropdownInput
|
||||
v-if="component.props.kind === 'DropdownInput'"
|
||||
v-bind="component.props"
|
||||
v-model:open="open"
|
||||
@update:selectedIndex="(value: number) => updateLayout(component.widgetId, value)"
|
||||
:sharpRightCorners="nextIsSuffix"
|
||||
/>
|
||||
<FontInput v-if="component.props.kind === 'FontInput'" v-bind="component.props" v-model:open="open" @changeFont="(value: unknown) => updateLayout(component.widgetId, value)" />
|
||||
<IconButton v-if="component.props.kind === 'IconButton'" v-bind="component.props" :action="() => updateLayout(component.widgetId, undefined)" />
|
||||
<FontInput
|
||||
v-if="component.props.kind === 'FontInput'"
|
||||
v-bind="component.props"
|
||||
v-model:open="open"
|
||||
@changeFont="(value: unknown) => updateLayout(component.widgetId, value)"
|
||||
:sharpRightCorners="nextIsSuffix"
|
||||
/>
|
||||
<IconButton v-if="component.props.kind === 'IconButton'" v-bind="component.props" :action="() => updateLayout(component.widgetId, undefined)" :sharpRightCorners="nextIsSuffix" />
|
||||
<IconLabel v-if="component.props.kind === 'IconLabel'" v-bind="component.props" />
|
||||
<NumberInput
|
||||
v-if="component.props.kind === 'NumberInput'"
|
||||
|
@ -21,6 +34,7 @@
|
|||
@update:value="(value: number) => updateLayout(component.widgetId, value)"
|
||||
:incrementCallbackIncrease="() => updateLayout(component.widgetId, 'Increment')"
|
||||
:incrementCallbackDecrease="() => updateLayout(component.widgetId, 'Decrement')"
|
||||
:sharpRightCorners="nextIsSuffix"
|
||||
/>
|
||||
<OptionalInput v-if="component.props.kind === 'OptionalInput'" v-bind="component.props" @update:checked="(value: boolean) => updateLayout(component.widgetId, value)" />
|
||||
<PivotAssist v-if="component.props.kind === 'PivotAssist'" v-bind="component.props" @update:position="(value: string) => updateLayout(component.widgetId, value)" />
|
||||
|
@ -28,12 +42,22 @@
|
|||
<h3>{{ (component.props as any).header }}</h3>
|
||||
<p>{{ (component.props as any).text }}</p>
|
||||
</PopoverButton>
|
||||
<RadioInput v-if="component.props.kind === 'RadioInput'" v-bind="component.props" @update:selectedIndex="(value: number) => updateLayout(component.widgetId, value)" />
|
||||
<RadioInput
|
||||
v-if="component.props.kind === 'RadioInput'"
|
||||
v-bind="component.props"
|
||||
@update:selectedIndex="(value: number) => updateLayout(component.widgetId, value)"
|
||||
:sharpRightCorners="nextIsSuffix"
|
||||
/>
|
||||
<Separator v-if="component.props.kind === 'Separator'" v-bind="component.props" />
|
||||
<SwatchPairInput v-if="component.props.kind === 'SwatchPairInput'" v-bind="component.props" />
|
||||
<TextAreaInput v-if="component.props.kind === 'TextAreaInput'" v-bind="component.props" @commitText="(value: string) => updateLayout(component.widgetId, value)" />
|
||||
<TextButton v-if="component.props.kind === 'TextButton'" v-bind="component.props" :action="() => updateLayout(component.widgetId, undefined)" />
|
||||
<TextInput v-if="component.props.kind === 'TextInput'" v-bind="component.props" @commitText="(value: string) => updateLayout(component.widgetId, value)" />
|
||||
<TextButton v-if="component.props.kind === 'TextButton'" v-bind="component.props" :action="() => updateLayout(component.widgetId, undefined)" :sharpRightCorners="nextIsSuffix" />
|
||||
<TextInput
|
||||
v-if="component.props.kind === 'TextInput'"
|
||||
v-bind="component.props"
|
||||
@commitText="(value: string) => updateLayout(component.widgetId, value)"
|
||||
:sharpRightCorners="nextIsSuffix"
|
||||
/>
|
||||
<TextLabel v-if="component.props.kind === 'TextLabel'" v-bind="withoutValue(component.props)">{{ (component.props as any).value }}</TextLabel>
|
||||
</template>
|
||||
</div>
|
||||
|
@ -74,6 +98,7 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent, type PropType } from "vue";
|
||||
|
||||
import type { Widget } from "@/wasm-communication/messages";
|
||||
import { isWidgetColumn, isWidgetRow, type WidgetColumn, type WidgetRow } from "@/wasm-communication/messages";
|
||||
|
||||
import PivotAssist from "@/components/widgets/assists/PivotAssist.vue";
|
||||
|
@ -94,6 +119,8 @@ import IconLabel from "@/components/widgets/labels/IconLabel.vue";
|
|||
import Separator from "@/components/widgets/labels/Separator.vue";
|
||||
import TextLabel from "@/components/widgets/labels/TextLabel.vue";
|
||||
|
||||
const SUFFIX_WIDGETS = ["PopoverButton"];
|
||||
|
||||
export default defineComponent({
|
||||
inject: ["editor"],
|
||||
props: {
|
||||
|
@ -106,15 +133,24 @@ export default defineComponent({
|
|||
};
|
||||
},
|
||||
computed: {
|
||||
direction() {
|
||||
direction(): "column" | "row" | "ERROR" {
|
||||
if (isWidgetColumn(this.widgetData)) return "column";
|
||||
if (isWidgetRow(this.widgetData)) return "row";
|
||||
return "ERROR";
|
||||
},
|
||||
widgets() {
|
||||
if (isWidgetColumn(this.widgetData)) return this.widgetData.columnWidgets;
|
||||
if (isWidgetRow(this.widgetData)) return this.widgetData.rowWidgets;
|
||||
return [];
|
||||
widgetsAndNextSiblingIsSuffix(): [Widget, boolean][] {
|
||||
let widgets: Widget[] = [];
|
||||
if (isWidgetColumn(this.widgetData)) widgets = this.widgetData.columnWidgets;
|
||||
if (isWidgetRow(this.widgetData)) widgets = this.widgetData.rowWidgets;
|
||||
|
||||
return widgets.map((widget, index): [Widget, boolean] => {
|
||||
// A suffix widget is one that joins up with this widget at the end with only a 1px gap.
|
||||
// It uses the CSS sibling selector to give its own left edge corners zero radius.
|
||||
// But this JS is needed to set its preceding sibling widget's right edge corners to zero radius.
|
||||
const nextSiblingIsSuffix = SUFFIX_WIDGETS.includes(widgets[index + 1]?.props.kind);
|
||||
|
||||
return [widget, nextSiblingIsSuffix];
|
||||
});
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div class="pivot-assist">
|
||||
<button @click="setPosition('TopLeft')" class="row-1 col-1" :class="{ active: position === 'TopLeft' }" tabindex="-1"><div></div></button>
|
||||
<button @click="setPosition('TopCenter')" class="row-1 col-2" :class="{ active: position === 'TopCenter' }" tabindex="-1"><div></div></button>
|
||||
<button @click="setPosition('TopRight')" class="row-1 col-3" :class="{ active: position === 'TopRight' }" tabindex="-1"><div></div></button>
|
||||
<button @click="setPosition('CenterLeft')" class="row-2 col-1" :class="{ active: position === 'CenterLeft' }" tabindex="-1"><div></div></button>
|
||||
<button @click="setPosition('Center')" class="row-2 col-2" :class="{ active: position === 'Center' }" tabindex="-1"><div></div></button>
|
||||
<button @click="setPosition('CenterRight')" class="row-2 col-3" :class="{ active: position === 'CenterRight' }" tabindex="-1"><div></div></button>
|
||||
<button @click="setPosition('BottomLeft')" class="row-3 col-1" :class="{ active: position === 'BottomLeft' }" tabindex="-1"><div></div></button>
|
||||
<button @click="setPosition('BottomCenter')" class="row-3 col-2" :class="{ active: position === 'BottomCenter' }" tabindex="-1"><div></div></button>
|
||||
<button @click="setPosition('BottomRight')" class="row-3 col-3" :class="{ active: position === 'BottomRight' }" tabindex="-1"><div></div></button>
|
||||
<div class="pivot-assist" :class="{ disabled }">
|
||||
<button @click="setPosition('TopLeft')" class="row-1 col-1" :class="{ active: position === 'TopLeft' }" tabindex="-1" :disabled="disabled"><div></div></button>
|
||||
<button @click="setPosition('TopCenter')" class="row-1 col-2" :class="{ active: position === 'TopCenter' }" tabindex="-1" :disabled="disabled"><div></div></button>
|
||||
<button @click="setPosition('TopRight')" class="row-1 col-3" :class="{ active: position === 'TopRight' }" tabindex="-1" :disabled="disabled"><div></div></button>
|
||||
<button @click="setPosition('CenterLeft')" class="row-2 col-1" :class="{ active: position === 'CenterLeft' }" tabindex="-1" :disabled="disabled"><div></div></button>
|
||||
<button @click="setPosition('Center')" class="row-2 col-2" :class="{ active: position === 'Center' }" tabindex="-1" :disabled="disabled"><div></div></button>
|
||||
<button @click="setPosition('CenterRight')" class="row-2 col-3" :class="{ active: position === 'CenterRight' }" tabindex="-1" :disabled="disabled"><div></div></button>
|
||||
<button @click="setPosition('BottomLeft')" class="row-3 col-1" :class="{ active: position === 'BottomLeft' }" tabindex="-1" :disabled="disabled"><div></div></button>
|
||||
<button @click="setPosition('BottomCenter')" class="row-3 col-2" :class="{ active: position === 'BottomCenter' }" tabindex="-1" :disabled="disabled"><div></div></button>
|
||||
<button @click="setPosition('BottomRight')" class="row-3 col-3" :class="{ active: position === 'BottomRight' }" tabindex="-1" :disabled="disabled"><div></div></button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
|||
flex: 0 0 auto;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
--pivot-border-color: var(--color-5-dullgray);
|
||||
--pivot-fill-active: var(--color-e-nearwhite);
|
||||
|
||||
button {
|
||||
position: absolute;
|
||||
|
@ -26,16 +28,11 @@
|
|||
margin: 0;
|
||||
padding: 0;
|
||||
background: var(--color-1-nearblack);
|
||||
border: 1px solid var(--color-5-dullgray);
|
||||
|
||||
&:hover {
|
||||
border-color: transparent;
|
||||
background: var(--color-6-lowergray);
|
||||
}
|
||||
border: 1px solid var(--pivot-border-color);
|
||||
|
||||
&.active {
|
||||
border-color: transparent;
|
||||
background: var(--color-e-nearwhite);
|
||||
background: var(--pivot-fill-active);
|
||||
}
|
||||
|
||||
&.col-1::before,
|
||||
|
@ -44,7 +41,7 @@
|
|||
pointer-events: none;
|
||||
width: 2px;
|
||||
height: 0;
|
||||
border-top: 1px solid var(--color-5-dullgray);
|
||||
border-top: 1px solid var(--pivot-border-color);
|
||||
position: absolute;
|
||||
top: 1px;
|
||||
right: -3px;
|
||||
|
@ -56,7 +53,7 @@
|
|||
pointer-events: none;
|
||||
width: 0;
|
||||
height: 2px;
|
||||
border-left: 1px solid var(--color-5-dullgray);
|
||||
border-left: 1px solid var(--pivot-border-color);
|
||||
position: absolute;
|
||||
bottom: -3px;
|
||||
right: 1px;
|
||||
|
@ -91,6 +88,16 @@
|
|||
margin: -2px;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.disabled) button:not(.active):hover {
|
||||
border-color: transparent;
|
||||
background: var(--color-6-lowergray);
|
||||
}
|
||||
|
||||
&.disabled button {
|
||||
--pivot-border-color: var(--color-4-dimgray);
|
||||
--pivot-fill-active: var(--color-8-uppergray);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
@ -103,6 +110,7 @@ export default defineComponent({
|
|||
emits: ["update:position"],
|
||||
props: {
|
||||
position: { type: String as PropType<string>, required: true },
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
},
|
||||
methods: {
|
||||
setPosition(newPosition: PivotPosition) {
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
<template>
|
||||
<button :class="['icon-button', `size-${size}`, active && 'active']" @click="(e: MouseEvent) => action(e)" :title="tooltip" :tabindex="active ? -1 : 0">
|
||||
<button
|
||||
:class="['icon-button', `size-${size}`, { disabled, active, 'sharp-right-corners': sharpRightCorners }]"
|
||||
@click="(e: MouseEvent) => action(e)"
|
||||
:disabled="disabled"
|
||||
:title="tooltip"
|
||||
:tabindex="active ? -1 : 0"
|
||||
>
|
||||
<IconLabel :icon="icon" />
|
||||
</button>
|
||||
</template>
|
||||
|
@ -24,15 +30,7 @@
|
|||
margin-left: 0;
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--color-e-nearwhite);
|
||||
|
||||
svg {
|
||||
fill: var(--color-2-mildblack);
|
||||
}
|
||||
}
|
||||
|
||||
&:hover:not(.active) {
|
||||
&:hover {
|
||||
background: var(--color-6-lowergray);
|
||||
color: var(--color-f-white);
|
||||
|
||||
|
@ -41,6 +39,22 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background: none;
|
||||
|
||||
svg {
|
||||
fill: var(--color-8-uppergray);
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--color-e-nearwhite);
|
||||
|
||||
svg {
|
||||
fill: var(--color-2-mildblack);
|
||||
}
|
||||
}
|
||||
|
||||
&.size-12 {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
|
@ -74,8 +88,10 @@ export default defineComponent({
|
|||
props: {
|
||||
icon: { type: String as PropType<IconName>, required: true },
|
||||
size: { type: Number as PropType<IconSize>, required: true },
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
active: { type: Boolean as PropType<boolean>, default: false },
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
sharpRightCorners: { type: Boolean as PropType<boolean>, default: false },
|
||||
|
||||
// Callbacks
|
||||
action: { type: Function as PropType<(e?: MouseEvent) => void>, required: true },
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<LayoutRow class="popover-button">
|
||||
<IconButton :class="{ open }" :action="() => onClick()" :icon="icon" :size="16" data-floating-menu-spawner :tooltip="tooltip" />
|
||||
<IconButton :class="{ open }" :disabled="disabled" :action="() => onClick()" :icon="icon" :size="16" data-floating-menu-spawner :tooltip="tooltip" />
|
||||
<FloatingMenu v-model:open="open" :type="'Popover'" :direction="'Bottom'">
|
||||
<slot></slot>
|
||||
</FloatingMenu>
|
||||
|
@ -33,6 +33,11 @@
|
|||
background: var(--color-6-lowergray);
|
||||
fill: var(--color-f-white);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background: var(--color-2-mildblack);
|
||||
fill: var(--color-8-uppergray);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Refactor this and other complicated cases dealing with joined widget margins and border-radius by adding a single standard set of classes: joined-first, joined-inner, and joined-last
|
||||
|
@ -59,6 +64,7 @@ export default defineComponent({
|
|||
props: {
|
||||
icon: { type: String as PropType<IconName>, default: "DropdownArrow" },
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
|
||||
// Callbacks
|
||||
action: { type: Function as PropType<() => void>, required: false },
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<button
|
||||
class="text-button"
|
||||
:class="{ emphasized, disabled }"
|
||||
:class="{ emphasized, disabled, 'sharp-right-corners': sharpRightCorners }"
|
||||
:data-emphasized="emphasized || undefined"
|
||||
:data-disabled="disabled || undefined"
|
||||
data-text-button
|
||||
|
@ -80,6 +80,7 @@ export default defineComponent({
|
|||
minWidth: { type: Number as PropType<number>, default: 0 },
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
sharpRightCorners: { type: Boolean as PropType<boolean>, default: false },
|
||||
|
||||
// Callbacks
|
||||
action: { type: Function as PropType<(e: MouseEvent) => void>, required: true },
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
<template>
|
||||
<LayoutRow class="color-input" :title="tooltip">
|
||||
<button :class="{ none: value.none }" :style="{ '--chosen-color': value.toHexOptionalAlpha() }" @click="() => $emit('update:open', true)" tabindex="0" data-floating-menu-spawner>
|
||||
<LayoutRow class="color-input" :class="{ 'sharp-right-corners': sharpRightCorners }" :title="tooltip">
|
||||
<button
|
||||
:class="{ none: value.none, 'sharp-right-corners': sharpRightCorners }"
|
||||
:style="{ '--chosen-color': value.toHexOptionalAlpha() }"
|
||||
@click="() => $emit('update:open', true)"
|
||||
tabindex="0"
|
||||
data-floating-menu-spawner
|
||||
>
|
||||
<TextLabel :bold="true" class="chip" v-if="chip">{{ chip }}</TextLabel>
|
||||
</button>
|
||||
<ColorPicker v-model:open="isOpen" :color="value" @update:color="(color: Color) => colorPickerUpdated(color)" :allowNone="true" />
|
||||
|
@ -86,8 +92,9 @@ export default defineComponent({
|
|||
props: {
|
||||
value: { type: Color as PropType<Color>, required: true },
|
||||
noTransparency: { type: Boolean as PropType<boolean>, default: false }, // TODO: Rename to allowTransparency, also implement allowNone
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false }, // TODO: Design and implement
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
sharpRightCorners: { type: Boolean as PropType<boolean>, default: false },
|
||||
|
||||
// Bound through `v-model`
|
||||
// TODO: See if this should be made to follow the pattern of DropdownInput.vue so this could be removed
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<LayoutRow class="dropdown-input" data-dropdown-input>
|
||||
<LayoutRow
|
||||
class="dropdown-box"
|
||||
:class="{ disabled, open }"
|
||||
:class="{ disabled, open, 'sharp-right-corners': sharpRightCorners }"
|
||||
:style="{ minWidth: `${minWidth}px` }"
|
||||
:title="tooltip"
|
||||
@click="() => !disabled && (open = true)"
|
||||
|
@ -116,6 +116,7 @@ export default defineComponent({
|
|||
interactive: { type: Boolean as PropType<boolean>, default: true },
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
sharpRightCorners: { type: Boolean as PropType<boolean>, default: false },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<!-- This is a base component, extended by others like NumberInput and TextInput. It should not be used directly. -->
|
||||
<template>
|
||||
<LayoutRow class="field-input" :class="{ disabled }" :title="tooltip">
|
||||
<LayoutRow class="field-input" :class="{ disabled, 'sharp-right-corners': sharpRightCorners }" :title="tooltip">
|
||||
<input
|
||||
v-if="!textarea"
|
||||
:class="{ 'has-label': label }"
|
||||
|
@ -136,6 +136,7 @@ export default defineComponent({
|
|||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
textarea: { type: Boolean as PropType<boolean>, default: false },
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
sharpRightCorners: { type: Boolean as PropType<boolean>, default: false },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<!-- TODO: Combine this widget into the DropdownInput widget -->
|
||||
|
||||
<template>
|
||||
<LayoutRow class="font-input">
|
||||
<LayoutRow
|
||||
class="dropdown-box"
|
||||
:class="{ disabled }"
|
||||
:class="{ disabled, 'sharp-right-corners': sharpRightCorners }"
|
||||
:style="{ minWidth: `${minWidth}px` }"
|
||||
:title="tooltip"
|
||||
:tabindex="disabled ? -1 : 0"
|
||||
|
@ -95,6 +97,7 @@ export default defineComponent({
|
|||
isStyle: { type: Boolean as PropType<boolean>, default: false },
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
sharpRightCorners: { type: Boolean as PropType<boolean>, default: false },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
:disabled="disabled"
|
||||
:style="minWidth > 0 ? `min-width: ${minWidth}px` : ''"
|
||||
:tooltip="tooltip"
|
||||
:sharpRightCorners="sharpRightCorners"
|
||||
@textFocused="() => onTextFocused()"
|
||||
@textChanged="() => onTextChanged()"
|
||||
@cancelTextChange="() => onCancelTextChange()"
|
||||
|
@ -110,6 +111,7 @@ export default defineComponent({
|
|||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
minWidth: { type: Number as PropType<number>, default: 0 },
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
sharpRightCorners: { type: Boolean as PropType<boolean>, default: false },
|
||||
|
||||
// Callbacks
|
||||
incrementCallbackIncrease: { type: Function as PropType<() => void>, required: false },
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
<template>
|
||||
<LayoutRow class="radio-input">
|
||||
<LayoutRow class="radio-input" :class="{ disabled }">
|
||||
<button
|
||||
:class="{ active: index === selectedIndex }"
|
||||
:class="{ active: index === selectedIndex, disabled, 'sharp-right-corners': index === entries.length - 1 && sharpRightCorners }"
|
||||
v-for="(entry, index) in entries"
|
||||
:key="index"
|
||||
@click="() => handleEntryClick(entry)"
|
||||
:title="entry.tooltip"
|
||||
:tabindex="index === selectedIndex ? -1 : 0"
|
||||
:disabled="disabled"
|
||||
>
|
||||
<IconLabel v-if="entry.icon" :icon="entry.icon" />
|
||||
<TextLabel v-if="entry.label">{{ entry.label }}</TextLabel>
|
||||
|
@ -43,6 +44,24 @@
|
|||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
background: var(--color-4-dimgray);
|
||||
color: var(--color-8-uppergray);
|
||||
|
||||
svg {
|
||||
fill: var(--color-8-uppergray);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: var(--color-8-uppergray);
|
||||
color: var(--color-2-mildblack);
|
||||
|
||||
svg {
|
||||
fill: var(--color-2-mildblack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& + button {
|
||||
margin-left: 1px;
|
||||
}
|
||||
|
@ -80,7 +99,9 @@ export default defineComponent({
|
|||
emits: ["update:selectedIndex"],
|
||||
props: {
|
||||
entries: { type: Array as PropType<RadioEntries>, required: true },
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
selectedIndex: { type: Number as PropType<number>, required: true },
|
||||
sharpRightCorners: { type: Boolean as PropType<boolean>, default: false },
|
||||
},
|
||||
methods: {
|
||||
handleEntryClick(radioEntryData: RadioEntryData) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
:disabled="disabled"
|
||||
:tooltip="tooltip"
|
||||
:style="minWidth > 0 ? `min-width: ${minWidth}px` : ''"
|
||||
:sharpRightCorners="sharpRightCorners"
|
||||
@textFocused="() => onTextFocused()"
|
||||
@textChanged="() => onTextChanged()"
|
||||
@cancelTextChange="() => onCancelTextChange()"
|
||||
|
@ -43,6 +44,7 @@ export default defineComponent({
|
|||
centered: { type: Boolean as PropType<boolean>, default: false },
|
||||
minWidth: { type: Number as PropType<number>, default: 0 },
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
sharpRightCorners: { type: Boolean as PropType<boolean>, default: false },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<LayoutRow :class="['icon-label', iconSizeClass]" :title="tooltip">
|
||||
<LayoutRow :class="['icon-label', iconSizeClass, { disabled }]" :title="tooltip">
|
||||
<component :is="icon" />
|
||||
</LayoutRow>
|
||||
</template>
|
||||
|
@ -9,6 +9,10 @@
|
|||
flex: 0 0 auto;
|
||||
fill: var(--color-e-nearwhite);
|
||||
|
||||
&.disabled {
|
||||
fill: var(--color-8-uppergray);
|
||||
}
|
||||
|
||||
&.size-12 {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
|
@ -36,6 +40,7 @@ import LayoutRow from "@/components/layout/LayoutRow.vue";
|
|||
export default defineComponent({
|
||||
props: {
|
||||
icon: { type: String as PropType<IconName>, required: true },
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
tooltip: { type: String as PropType<string | undefined>, required: false },
|
||||
},
|
||||
computed: {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<span class="text-label" :class="{ bold, italic, multiline, 'table-align': tableAlign }" :style="minWidth > 0 ? `min-width: ${minWidth}px` : ''" :title="tooltip">
|
||||
<span class="text-label" :class="{ disabled, bold, italic, multiline, 'table-align': tableAlign }" :style="minWidth > 0 ? `min-width: ${minWidth}px` : ''" :title="tooltip">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</template>
|
||||
|
@ -9,6 +9,10 @@
|
|||
line-height: 18px;
|
||||
white-space: nowrap;
|
||||
|
||||
&.disabled {
|
||||
color: var(--color-8-uppergray);
|
||||
}
|
||||
|
||||
&.bold {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
@ -34,6 +38,7 @@ import { defineComponent, type PropType } from "vue";
|
|||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
disabled: { type: Boolean as PropType<boolean>, default: false },
|
||||
bold: { type: Boolean as PropType<boolean>, default: false },
|
||||
italic: { type: Boolean as PropType<boolean>, default: false },
|
||||
tableAlign: { type: Boolean as PropType<boolean>, default: false },
|
||||
|
|
|
@ -26,8 +26,8 @@ export function createPanicManager(editor: Editor, dialogState: DialogState): vo
|
|||
function preparePanicDialog(header: string, details: string, panicDetails: string): [IconName, WidgetLayout, TextButtonWidget[]] {
|
||||
const widgets: WidgetLayout = {
|
||||
layout: [
|
||||
{ rowWidgets: [new Widget({ kind: "TextLabel", value: header, bold: true, italic: false, tableAlign: false, minWidth: 0, multiline: false, tooltip: "" }, 0n)] },
|
||||
{ rowWidgets: [new Widget({ kind: "TextLabel", value: details, bold: false, italic: false, tableAlign: false, minWidth: 0, multiline: true, tooltip: "" }, 1n)] },
|
||||
{ rowWidgets: [new Widget({ kind: "TextLabel", value: header, disabled: false, bold: true, italic: false, tableAlign: false, minWidth: 0, multiline: false, tooltip: "" }, 0n)] },
|
||||
{ rowWidgets: [new Widget({ kind: "TextLabel", value: details, disabled: false, bold: false, italic: false, tableAlign: false, minWidth: 0, multiline: true, tooltip: "" }, 1n)] },
|
||||
],
|
||||
layoutTarget: undefined,
|
||||
};
|
||||
|
|
|
@ -788,6 +788,8 @@ export class IconButton extends WidgetProps {
|
|||
|
||||
size!: IconSize;
|
||||
|
||||
disabled!: boolean;
|
||||
|
||||
active!: boolean;
|
||||
|
||||
@Transform(({ value }: { value: string }) => (value.length > 0 ? value : undefined))
|
||||
|
@ -797,6 +799,8 @@ export class IconButton extends WidgetProps {
|
|||
export class IconLabel extends WidgetProps {
|
||||
icon!: IconName;
|
||||
|
||||
disabled!: boolean;
|
||||
|
||||
@Transform(({ value }: { value: string }) => (value.length > 0 ? value : undefined))
|
||||
tooltip!: string | undefined;
|
||||
}
|
||||
|
@ -846,6 +850,8 @@ export class OptionalInput extends WidgetProps {
|
|||
export class PopoverButton extends WidgetProps {
|
||||
icon!: string | undefined;
|
||||
|
||||
disabled!: boolean;
|
||||
|
||||
// Body
|
||||
header!: string;
|
||||
|
||||
|
@ -869,6 +875,8 @@ export type RadioEntries = RadioEntryData[];
|
|||
export class RadioInput extends WidgetProps {
|
||||
entries!: RadioEntries;
|
||||
|
||||
disabled!: boolean;
|
||||
|
||||
selectedIndex!: number;
|
||||
}
|
||||
|
||||
|
@ -951,6 +959,8 @@ export class TextLabel extends WidgetProps {
|
|||
value!: string;
|
||||
|
||||
// Props
|
||||
disabled!: boolean;
|
||||
|
||||
bold!: boolean;
|
||||
|
||||
italic!: boolean;
|
||||
|
@ -969,6 +979,8 @@ export type PivotPosition = "None" | "TopLeft" | "TopCenter" | "TopRight" | "Cen
|
|||
|
||||
export class PivotAssist extends WidgetProps {
|
||||
position!: PivotPosition;
|
||||
|
||||
disabled!: boolean;
|
||||
}
|
||||
|
||||
// WIDGET
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue