Tooltips overhaul

This commit is contained in:
thepaperpilot 2022-04-23 15:23:38 -05:00
parent 89861dfbd5
commit f76d5deb6e
12 changed files with 212 additions and 146 deletions

View file

@ -3,7 +3,7 @@
<img v-if="banner" :src="banner" class="banner" :alt="title" /> <img v-if="banner" :src="banner" class="banner" :alt="title" />
<div v-else class="title">{{ title }}</div> <div v-else class="title">{{ title }}</div>
<div @click="changelog?.open()" class="version-container"> <div @click="changelog?.open()" class="version-container">
<Tooltip display="Changelog" bottom class="version" <Tooltip display="Changelog" :direction="TooltipDirection.DOWN" class="version"
><span>v{{ versionNumber }}</span></Tooltip ><span>v{{ versionNumber }}</span></Tooltip
> >
</div> </div>
@ -26,51 +26,56 @@
</div> </div>
<div> <div>
<a href="https://forums.moddingtree.com/" target="_blank"> <a href="https://forums.moddingtree.com/" target="_blank">
<Tooltip display="Forums" bottom yoffset="5px"> <Tooltip display="Forums" :direction="TooltipDirection.DOWN" yoffset="5px">
<span class="material-icons">forum</span> <span class="material-icons">forum</span>
</Tooltip> </Tooltip>
</a> </a>
</div> </div>
<div @click="info?.open()"> <div @click="info?.open()">
<Tooltip display="Info" bottom class="info"> <Tooltip display="Info" :direction="TooltipDirection.DOWN" class="info">
<span class="material-icons">info</span> <span class="material-icons">info</span>
</Tooltip> </Tooltip>
</div> </div>
<div @click="savesManager?.open()"> <div @click="savesManager?.open()">
<Tooltip display="Saves" bottom xoffset="-20px"> <Tooltip display="Saves" :direction="TooltipDirection.DOWN" xoffset="-20px">
<span class="material-icons">library_books</span> <span class="material-icons">library_books</span>
</Tooltip> </Tooltip>
</div> </div>
<div @click="options?.open()"> <div @click="options?.open()">
<Tooltip display="Options" bottom xoffset="-66px"> <Tooltip display="Options" :direction="TooltipDirection.DOWN" xoffset="-66px">
<span class="material-icons">settings</span> <span class="material-icons">settings</span>
</Tooltip> </Tooltip>
</div> </div>
</div> </div>
<div v-else class="overlay-nav" v-bind="$attrs"> <div v-else class="overlay-nav" v-bind="$attrs">
<div @click="changelog?.open()" class="version-container"> <div @click="changelog?.open()" class="version-container">
<Tooltip display="Changelog" right xoffset="25%" class="version"> <Tooltip
display="Changelog"
:direction="TooltipDirection.RIGHT"
xoffset="25%"
class="version"
>
<span>v{{ versionNumber }}</span> <span>v{{ versionNumber }}</span>
</Tooltip> </Tooltip>
</div> </div>
<div @click="savesManager?.open()"> <div @click="savesManager?.open()">
<Tooltip display="Saves" right> <Tooltip display="Saves" :direction="TooltipDirection.RIGHT">
<span class="material-icons">library_books</span> <span class="material-icons">library_books</span>
</Tooltip> </Tooltip>
</div> </div>
<div @click="options?.open()"> <div @click="options?.open()">
<Tooltip display="Options" right> <Tooltip display="Options" :direction="TooltipDirection.RIGHT">
<span class="material-icons">settings</span> <span class="material-icons">settings</span>
</Tooltip> </Tooltip>
</div> </div>
<div @click="info?.open()"> <div @click="info?.open()">
<Tooltip display="Info" right> <Tooltip display="Info" :direction="TooltipDirection.RIGHT">
<span class="material-icons">info</span> <span class="material-icons">info</span>
</Tooltip> </Tooltip>
</div> </div>
<div> <div>
<a href="https://forums.moddingtree.com/" target="_blank"> <a href="https://forums.moddingtree.com/" target="_blank">
<Tooltip display="Forums" right xoffset="7px"> <Tooltip display="Forums" :direction="TooltipDirection.RIGHT" xoffset="7px">
<span class="material-icons">forum</span> <span class="material-icons">forum</span>
</Tooltip> </Tooltip>
</a> </a>
@ -105,7 +110,8 @@ import { ComponentPublicInstance, ref } from "vue";
import Info from "./Info.vue"; import Info from "./Info.vue";
import Options from "./Options.vue"; import Options from "./Options.vue";
import SavesManager from "./SavesManager.vue"; import SavesManager from "./SavesManager.vue";
import Tooltip from "./Tooltip.vue"; import Tooltip from "features/tooltips/Tooltip.vue";
import { TooltipDirection } from "features/tooltips/tooltip";
const info = ref<ComponentPublicInstance<typeof Info> | null>(null); const info = ref<ComponentPublicInstance<typeof Info> | null>(null);
const savesManager = ref<ComponentPublicInstance<typeof SavesManager> | null>(null); const savesManager = ref<ComponentPublicInstance<typeof SavesManager> | null>(null);

View file

@ -30,7 +30,7 @@ import { coerceComponent, render } from "util/vue";
import { computed, ref, toRefs } from "vue"; import { computed, ref, toRefs } from "vue";
import Select from "./fields/Select.vue"; import Select from "./fields/Select.vue";
import Toggle from "./fields/Toggle.vue"; import Toggle from "./fields/Toggle.vue";
import Tooltip from "./Tooltip.vue"; import Tooltip from "features/tooltips/Tooltip.vue";
const isOpen = ref(false); const isOpen = ref(false);

View file

@ -9,7 +9,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { computed, toRefs, unref } from "vue"; import { computed, toRefs, unref } from "vue";
import Tooltip from "../Tooltip.vue"; import Tooltip from "features/tooltips/Tooltip.vue";
import "components/common/fields.css"; import "components/common/fields.css";
const _props = defineProps<{ const _props = defineProps<{

View file

@ -26,7 +26,6 @@
import { CoercableComponent, Visibility } from "features/feature"; import { CoercableComponent, Visibility } from "features/feature";
import { computeOptionalComponent, processedPropType } from "util/vue"; import { computeOptionalComponent, processedPropType } from "util/vue";
import { defineComponent, StyleValue, toRefs, unref } from "vue"; import { defineComponent, StyleValue, toRefs, unref } from "vue";
import Tooltip from "components/Tooltip.vue";
import Node from "components/Node.vue"; import Node from "components/Node.vue";
import MarkNode from "components/MarkNode.vue"; import MarkNode from "components/MarkNode.vue";
import "components/common/features.css"; import "components/common/features.css";
@ -53,8 +52,7 @@ export default defineComponent({
}, },
components: { components: {
Node, Node,
MarkNode, MarkNode
Tooltip
}, },
setup(props) { setup(props) {
const { display } = toRefs(props); const { display } = toRefs(props);

View file

@ -1,25 +0,0 @@
import { CoercableComponent } from "features/feature";
import { ProcessedComputable } from "util/computed";
declare module "@vue/runtime-dom" {
interface CSSProperties {
"--xoffset"?: string;
"--yoffset"?: string;
}
}
export interface Tooltip {
display: ProcessedComputable<CoercableComponent>;
top?: ProcessedComputable<boolean>;
left?: ProcessedComputable<boolean>;
right?: ProcessedComputable<boolean>;
bottom?: ProcessedComputable<boolean>;
xoffset?: ProcessedComputable<string>;
yoffset?: ProcessedComputable<string>;
force?: ProcessedComputable<boolean>;
}
export function gatherTooltipProps(tooltip: Tooltip) {
const { display, top, left, right, bottom, xoffset, yoffset, force } = tooltip;
return { display, top, left, right, bottom, xoffset, yoffset, force };
}

View file

@ -1,20 +1,23 @@
<template> <template>
<div <div
class="tooltip-container" class="tooltip-container"
:class="{ shown: isShown }" :class="{ shown: isShown, ...unref(classes) }"
@mouseenter="isHovered = true" @mouseenter="isHovered = true"
@mouseleave="isHovered = false" @mouseleave="isHovered = false"
@click="togglePinned"
:style="unref(style)"
> >
<slot /> <slot />
<component v-if="elementComp" :is="elementComp" />
<transition name="fade"> <transition name="fade">
<div <div
v-if="isShown" v-if="isShown"
class="tooltip" class="tooltip"
:class="{ :class="{
top: unref(top), top: unref(direction) === TooltipDirection.UP,
left: unref(left), left: unref(direction) === TooltipDirection.LEFT,
right: unref(right), right: unref(direction) === TooltipDirection.RIGHT,
bottom: unref(bottom) bottom: unref(direction) === TooltipDirection.DOWN
}" }"
:style="{ :style="{
'--xoffset': unref(xoffset) || '0px', '--xoffset': unref(xoffset) || '0px',
@ -28,33 +31,76 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { CoercableComponent } from "features/feature"; import { CoercableComponent, jsx, StyleValue } from "features/feature";
import { computeOptionalComponent, processedPropType, unwrapRef } from "util/vue"; import { Persistent } from "game/persistence";
import { computed, defineComponent, ref, toRefs, unref } from "vue"; import {
coerceComponent,
computeOptionalComponent,
processedPropType,
render,
unwrapRef,
VueFeature
} from "util/vue";
import {
Component,
computed,
defineComponent,
PropType,
ref,
shallowRef,
toRefs,
unref,
watchEffect
} from "vue";
import { TooltipDirection } from "./tooltip";
export default defineComponent({ export default defineComponent({
props: { props: {
display: processedPropType<CoercableComponent>(Object, String, Function), element: processedPropType<VueFeature>(Object),
top: processedPropType<boolean>(Boolean), display: {
left: processedPropType<boolean>(Boolean), type: processedPropType<CoercableComponent>(Object, String, Function),
right: processedPropType<boolean>(Boolean), required: true
bottom: processedPropType<boolean>(Boolean), },
style: processedPropType<StyleValue>(Object, String, Array),
classes: processedPropType<Record<string, boolean>>(Object),
direction: processedPropType<TooltipDirection>(Number),
xoffset: processedPropType<string>(String), xoffset: processedPropType<string>(String),
yoffset: processedPropType<string>(String), yoffset: processedPropType<string>(String),
force: processedPropType<boolean>(Boolean) pinned: Object as PropType<Persistent<boolean>>
}, },
setup(props) { setup(props) {
const { display, force } = toRefs(props); const { element, display, pinned } = toRefs(props);
const isHovered = ref(false); const isHovered = ref(false);
const isShown = computed(() => (unwrapRef(force) || isHovered.value) && comp.value); const isShown = computed(() => (unwrapRef(pinned) || isHovered.value) && comp.value);
const comp = computeOptionalComponent(display); const comp = computeOptionalComponent(display);
const elementComp = shallowRef<Component | "" | null>(null);
watchEffect(() => {
const currComponent = unwrapRef(element);
elementComp.value =
currComponent == null
? null
: coerceComponent(jsx(() => render(currComponent) as JSX.Element));
});
function togglePinned(e: MouseEvent) {
const isPinned = pinned as unknown as Persistent<boolean> | undefined; // Vue typing :/
if (e.shiftKey && isPinned) {
isPinned.value = !isPinned.value;
e.stopPropagation();
e.preventDefault();
}
}
return { return {
TooltipDirection,
isHovered, isHovered,
isShown, isShown,
comp, comp,
unref elementComp,
unref,
togglePinned
}; };
} }
}); });

View file

@ -0,0 +1,115 @@
import TooltipComponent from "./Tooltip.vue";
import {
CoercableComponent,
Component,
GatherProps,
Replace,
setDefault,
StyleValue
} from "features/feature";
import {
Computable,
GetComputableType,
GetComputableTypeWithDefault,
processComputable,
ProcessedComputable
} from "util/computed";
import { VueFeature } from "util/vue";
import { readonly, ref, Ref } from "vue";
import { persistent } from "game/persistence";
declare module "@vue/runtime-dom" {
interface CSSProperties {
"--xoffset"?: string;
"--yoffset"?: string;
}
}
export enum TooltipDirection {
UP,
LEFT,
RIGHT,
DOWN
}
export interface TooltipOptions {
pinnable?: boolean;
display: Computable<CoercableComponent>;
classes?: Computable<Record<string, boolean>>;
style?: Computable<StyleValue>;
direction?: Computable<TooltipDirection>;
xoffset?: Computable<string>;
yoffset?: Computable<string>;
}
export interface BaseTooltip {
pinned?: Ref<boolean>;
}
export type Tooltip<T extends TooltipOptions> = Replace<
T & BaseTooltip,
{
pinnable: T["pinnable"] extends unknown ? true : T["pinnable"];
display: GetComputableType<T["display"]>;
classes: GetComputableType<T["classes"]>;
style: GetComputableType<T["style"]>;
direction: GetComputableTypeWithDefault<T["direction"], TooltipDirection.UP>;
xoffset: GetComputableType<T["xoffset"]>;
yoffset: GetComputableType<T["yoffset"]>;
}
>;
export type GenericTooltip = Replace<
Tooltip<TooltipOptions>,
{
pinnable: boolean;
direction: ProcessedComputable<TooltipDirection>;
}
>;
export function addTooltip<T extends TooltipOptions>(
element: VueFeature,
options: T & ThisType<Tooltip<T>> & Partial<BaseTooltip>
): Tooltip<T> {
if (options.pinnable) {
if ("pinned" in element) {
console.error(
"Cannot add pinnable tooltip to element that already has a property called 'pinned'"
);
options.pinnable = false;
} else {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(element as any).pinned = options.pinned = persistent<boolean>(false);
}
}
processComputable(options as T, "display");
processComputable(options as T, "classes");
processComputable(options as T, "style");
processComputable(options as T, "direction");
setDefault(options, "direction", TooltipDirection.UP);
processComputable(options as T, "xoffset");
processComputable(options as T, "yoffset");
const elementComponent = element[Component];
element[Component] = TooltipComponent;
const elementGratherProps = element[GatherProps].bind(element);
element[GatherProps] = function gatherTooltipProps(this: GenericTooltip) {
const { display, classes, style, direction, xoffset, yoffset, pinned } = this;
return {
element: {
[Component]: elementComponent,
[GatherProps]: elementGratherProps
},
display,
classes,
style,
direction,
xoffset,
yoffset,
pinned
};
}.bind(options as GenericTooltip);
return options as unknown as Tooltip<T>;
}

View file

@ -4,7 +4,6 @@
v-for="(node, nodeIndex) in row" v-for="(node, nodeIndex) in row"
:key="nodeIndex" :key="nodeIndex"
v-bind="gatherNodeProps(node)" v-bind="gatherNodeProps(node)"
:force-tooltip="node.forceTooltip"
/> />
</span> </span>
<span class="left-side-nodes" v-if="unref(leftSideNodes)"> <span class="left-side-nodes" v-if="unref(leftSideNodes)">
@ -12,7 +11,6 @@
v-for="(node, nodeIndex) in unref(leftSideNodes)" v-for="(node, nodeIndex) in unref(leftSideNodes)"
:key="nodeIndex" :key="nodeIndex"
v-bind="gatherNodeProps(node)" v-bind="gatherNodeProps(node)"
:force-tooltip="node.forceTooltip"
small small
/> />
</span> </span>
@ -21,7 +19,6 @@
v-for="(node, nodeIndex) in unref(rightSideNodes)" v-for="(node, nodeIndex) in unref(rightSideNodes)"
:key="nodeIndex" :key="nodeIndex"
v-bind="gatherNodeProps(node)" v-bind="gatherNodeProps(node)"
:force-tooltip="node.forceTooltip"
small small
/> />
</span> </span>
@ -54,12 +51,10 @@ export default defineComponent({
visibility, visibility,
style, style,
classes, classes,
tooltip,
onClick, onClick,
onHold, onHold,
color, color,
glowColor, glowColor,
forceTooltip,
canClick, canClick,
mark, mark,
id id
@ -69,12 +64,10 @@ export default defineComponent({
visibility, visibility,
style, style,
classes, classes,
tooltip,
onClick, onClick,
onHold, onHold,
color, color,
glowColor, glowColor,
forceTooltip,
canClick, canClick,
mark, mark,
id id

View file

@ -1,9 +1,6 @@
<template> <template>
<Tooltip <div
v-if="unref(visibility) !== Visibility.None" v-if="unref(visibility) !== Visibility.None"
v-bind="tooltipToBind && gatherTooltipProps(tooltipToBind)"
:display="tooltipDisplay"
:force="forceTooltip"
:style="{ visibility: unref(visibility) === Visibility.Hidden ? 'hidden' : undefined }" :style="{ visibility: unref(visibility) === Visibility.Hidden ? 'hidden' : undefined }"
:class="{ :class="{
treeNode: true, treeNode: true,
@ -13,7 +10,7 @@
}" }"
> >
<div <div
@click="click" @click="onClick"
@mousedown="start" @mousedown="start"
@mouseleave="stop" @mouseleave="stop"
@mouseup="stop" @mouseup="stop"
@ -34,33 +31,20 @@
</div> </div>
<MarkNode :mark="unref(mark)" /> <MarkNode :mark="unref(mark)" />
<Node :id="id" /> <Node :id="id" />
</Tooltip> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import Node from "components/Node.vue"; import Node from "components/Node.vue";
import MarkNode from "components/MarkNode.vue"; import MarkNode from "components/MarkNode.vue";
import TooltipVue from "components/Tooltip.vue";
import { CoercableComponent, StyleValue, Visibility } from "features/feature"; import { CoercableComponent, StyleValue, Visibility } from "features/feature";
import { gatherTooltipProps, Tooltip } from "features/tooltip";
import { ProcessedComputable } from "util/computed";
import { import {
computeOptionalComponent, computeOptionalComponent,
isCoercableComponent, isCoercableComponent,
processedPropType, processedPropType,
setupHoldToClick, setupHoldToClick
unwrapRef
} from "util/vue"; } from "util/vue";
import { import { defineComponent, PropType, toRefs, unref } from "vue";
computed,
defineComponent,
PropType,
Ref,
shallowRef,
toRefs,
unref,
watchEffect
} from "vue";
export default defineComponent({ export default defineComponent({
props: { props: {
@ -71,15 +55,10 @@ export default defineComponent({
}, },
style: processedPropType<StyleValue>(String, Object, Array), style: processedPropType<StyleValue>(String, Object, Array),
classes: processedPropType<Record<string, boolean>>(Object), classes: processedPropType<Record<string, boolean>>(Object),
tooltip: processedPropType<CoercableComponent | Tooltip>(Object, String, Function),
onClick: Function as PropType<(e?: MouseEvent | TouchEvent) => void>, onClick: Function as PropType<(e?: MouseEvent | TouchEvent) => void>,
onHold: Function as PropType<VoidFunction>, onHold: Function as PropType<VoidFunction>,
color: processedPropType<string>(String), color: processedPropType<string>(String),
glowColor: processedPropType<string>(String), glowColor: processedPropType<string>(String),
forceTooltip: {
type: Object as PropType<Ref<boolean>>,
required: true
},
canClick: { canClick: {
type: processedPropType<boolean>(Boolean), type: processedPropType<boolean>(Boolean),
required: true required: true
@ -92,55 +71,22 @@ export default defineComponent({
small: processedPropType<boolean>(Boolean) small: processedPropType<boolean>(Boolean)
}, },
components: { components: {
Tooltip: TooltipVue,
MarkNode, MarkNode,
Node Node
}, },
setup(props) { setup(props) {
const { tooltip, forceTooltip, onClick, onHold, display } = toRefs(props); const { onClick, onHold, display } = toRefs(props);
function click(e: MouseEvent) {
if (e.shiftKey && tooltip) {
forceTooltip.value = !forceTooltip.value;
} else {
unref(onClick)?.();
}
}
const comp = computeOptionalComponent(display); const comp = computeOptionalComponent(display);
const tooltipDisplay = shallowRef<ProcessedComputable<CoercableComponent> | undefined>(
undefined
);
watchEffect(() => {
const currTooltip = unwrapRef(tooltip);
if (typeof currTooltip === "object" && !isCoercableComponent(currTooltip)) {
tooltipDisplay.value = currTooltip.display;
return;
}
tooltipDisplay.value = currTooltip;
});
const tooltipToBind = computed(() => {
const currTooltip = unwrapRef(tooltip);
if (typeof currTooltip === "object" && !isCoercableComponent(currTooltip)) {
return currTooltip;
}
return null;
});
const { start, stop } = setupHoldToClick(onClick, onHold); const { start, stop } = setupHoldToClick(onClick, onHold);
return { return {
click,
start, start,
stop, stop,
comp, comp,
tooltipDisplay,
tooltipToBind,
unref, unref,
Visibility, Visibility,
gatherTooltipProps,
isCoercableComponent isCoercableComponent
}; };
} }

View file

@ -12,9 +12,7 @@ import {
import { Link } from "features/links/links"; import { Link } from "features/links/links";
import { GenericReset } from "features/reset"; import { GenericReset } from "features/reset";
import { displayResource, Resource } from "features/resources/resource"; import { displayResource, Resource } from "features/resources/resource";
import { Tooltip } from "features/tooltip";
import TreeComponent from "features/trees/Tree.vue"; import TreeComponent from "features/trees/Tree.vue";
import { deletePersistent, persistent } from "game/persistence";
import Decimal, { DecimalSource, format, formatWhole } from "util/bignum"; import Decimal, { DecimalSource, format, formatWhole } from "util/bignum";
import { import {
Computable, Computable,
@ -35,7 +33,6 @@ export interface TreeNodeOptions {
canClick?: Computable<boolean>; canClick?: Computable<boolean>;
color?: Computable<string>; color?: Computable<string>;
display?: Computable<CoercableComponent>; display?: Computable<CoercableComponent>;
tooltip?: Computable<string | Tooltip>;
glowColor?: Computable<string>; glowColor?: Computable<string>;
classes?: Computable<Record<string, boolean>>; classes?: Computable<Record<string, boolean>>;
style?: Computable<StyleValue>; style?: Computable<StyleValue>;
@ -47,7 +44,6 @@ export interface TreeNodeOptions {
export interface BaseTreeNode { export interface BaseTreeNode {
id: string; id: string;
forceTooltip: Ref<boolean>;
type: typeof TreeNodeType; type: typeof TreeNodeType;
} }
@ -62,7 +58,6 @@ export type TreeNode<T extends TreeNodeOptions> = Replace<
classes: GetComputableType<T["classes"]>; classes: GetComputableType<T["classes"]>;
style: GetComputableType<T["style"]>; style: GetComputableType<T["style"]>;
mark: GetComputableType<T["mark"]>; mark: GetComputableType<T["mark"]>;
tooltip: GetComputableType<T["tooltip"]>;
} }
>; >;
@ -77,27 +72,17 @@ export type GenericTreeNode = Replace<
export function createTreeNode<T extends TreeNodeOptions>( export function createTreeNode<T extends TreeNodeOptions>(
optionsFunc: OptionsFunc<T, TreeNode<T>, BaseTreeNode> optionsFunc: OptionsFunc<T, TreeNode<T>, BaseTreeNode>
): TreeNode<T> { ): TreeNode<T> {
const forceTooltip = persistent(false);
return createLazyProxy(() => { return createLazyProxy(() => {
const treeNode = optionsFunc(); const treeNode = optionsFunc();
treeNode.id = getUniqueID("treeNode-"); treeNode.id = getUniqueID("treeNode-");
treeNode.type = TreeNodeType; treeNode.type = TreeNodeType;
if (treeNode.tooltip) {
treeNode.forceTooltip = forceTooltip;
} else {
// If we don't have a tooltip, no point in making this persistent
treeNode.forceTooltip = ref(false);
deletePersistent(forceTooltip);
}
processComputable(treeNode as T, "visibility"); processComputable(treeNode as T, "visibility");
setDefault(treeNode, "visibility", Visibility.Visible); setDefault(treeNode, "visibility", Visibility.Visible);
processComputable(treeNode as T, "canClick"); processComputable(treeNode as T, "canClick");
setDefault(treeNode, "canClick", true); setDefault(treeNode, "canClick", true);
processComputable(treeNode as T, "color"); processComputable(treeNode as T, "color");
processComputable(treeNode as T, "display"); processComputable(treeNode as T, "display");
processComputable(treeNode as T, "tooltip");
processComputable(treeNode as T, "glowColor"); processComputable(treeNode as T, "glowColor");
processComputable(treeNode as T, "classes"); processComputable(treeNode as T, "classes");
processComputable(treeNode as T, "style"); processComputable(treeNode as T, "style");

View file

@ -40,8 +40,10 @@ export function createLazyProxy<T extends object, S>(
return (calculateObj() as any)[key]; return (calculateObj() as any)[key];
}, },
set(target, key, value) { set(target, key, value) {
console.error("Layers and features are shallow readonly", key, value); // TODO give warning about this? It should only be done with caution
return false; // eslint-disable-next-line @typescript-eslint/no-explicit-any
(calculateObj() as any)[key] = value;
return true;
}, },
has(target, key) { has(target, key) {
if (key === ProxyState) { if (key === ProxyState) {

View file

@ -164,8 +164,8 @@ export function getFirstFeature<T extends { visibility: ProcessedComputable<Visi
export function computeComponent( export function computeComponent(
component: Ref<ProcessedComputable<CoercableComponent>>, component: Ref<ProcessedComputable<CoercableComponent>>,
defaultWrapper = "div" defaultWrapper = "div"
): ShallowRef<Component | JSXFunction | ""> { ): ShallowRef<Component | ""> {
const comp = shallowRef<Component | JSXFunction | "">(); const comp = shallowRef<Component | "">();
watchEffect(() => { watchEffect(() => {
comp.value = coerceComponent(unwrapRef(component), defaultWrapper); comp.value = coerceComponent(unwrapRef(component), defaultWrapper);
}); });
@ -174,8 +174,8 @@ export function computeComponent(
export function computeOptionalComponent( export function computeOptionalComponent(
component: Ref<ProcessedComputable<CoercableComponent | undefined> | undefined>, component: Ref<ProcessedComputable<CoercableComponent | undefined> | undefined>,
defaultWrapper = "div" defaultWrapper = "div"
): ShallowRef<Component | JSXFunction | "" | null> { ): ShallowRef<Component | "" | null> {
const comp = shallowRef<Component | JSXFunction | "" | null>(null); const comp = shallowRef<Component | "" | null>(null);
watchEffect(() => { watchEffect(() => {
const currComponent = unwrapRef(component); const currComponent = unwrapRef(component);
comp.value = currComponent == null ? null : coerceComponent(currComponent, defaultWrapper); comp.value = currComponent == null ? null : coerceComponent(currComponent, defaultWrapper);