forked from profectus/Profectus
Remove processedPropType and convert all components to composition API
This commit is contained in:
parent
ccd685cb9c
commit
1e5411d279
19 changed files with 1058 additions and 1046 deletions
|
@ -29,14 +29,23 @@ import player from "game/player";
|
|||
import { computed, toRef, unref } from "vue";
|
||||
import Layer from "./Layer.vue";
|
||||
import Nav from "./Nav.vue";
|
||||
import { deepUnref } from "util/vue";
|
||||
|
||||
const tabs = toRef(player, "tabs");
|
||||
const layerKeys = computed(() => Object.keys(layers));
|
||||
const useHeader = projInfo.useHeader;
|
||||
|
||||
function gatherLayerProps(layer: GenericLayer) {
|
||||
const { display, minimized, name, color, minimizable, nodes, minimizedDisplay } = layer;
|
||||
return { display, minimized, name, color, minimizable, nodes, minimizedDisplay };
|
||||
const { display, name, color, minimizable, minimizedDisplay } = deepUnref(layer);
|
||||
return {
|
||||
display,
|
||||
name,
|
||||
color,
|
||||
minimizable,
|
||||
minimizedDisplay,
|
||||
minimized: layer.minimized,
|
||||
nodes: layer.nodes
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -23,80 +23,48 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import projInfo from "data/projInfo.json";
|
||||
import type { CoercableComponent } from "features/feature";
|
||||
import type { FeatureNode } from "game/layers";
|
||||
import player from "game/player";
|
||||
import { computeComponent, computeOptionalComponent, processedPropType, unwrapRef } from "util/vue";
|
||||
import { PropType, Ref, computed, defineComponent, onErrorCaptured, ref, toRefs, unref } from "vue";
|
||||
import { computeComponent, computeOptionalComponent } from "util/vue";
|
||||
import { Ref, computed, onErrorCaptured, ref, toRef, unref } from "vue";
|
||||
import Context from "./Context.vue";
|
||||
import ErrorVue from "./Error.vue";
|
||||
|
||||
export default defineComponent({
|
||||
components: { Context, ErrorVue },
|
||||
props: {
|
||||
index: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
display: {
|
||||
type: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
required: true
|
||||
},
|
||||
minimizedDisplay: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
minimized: {
|
||||
type: Object as PropType<Ref<boolean>>,
|
||||
required: true
|
||||
},
|
||||
name: {
|
||||
type: processedPropType<string>(String),
|
||||
required: true
|
||||
},
|
||||
color: processedPropType<string>(String),
|
||||
minimizable: processedPropType<boolean>(Boolean),
|
||||
nodes: {
|
||||
type: Object as PropType<Ref<Record<string, FeatureNode | undefined>>>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
emits: ["setMinimized"],
|
||||
setup(props) {
|
||||
const { display, index, minimized, minimizedDisplay } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
index: number;
|
||||
display: CoercableComponent;
|
||||
minimizedDisplay?: CoercableComponent;
|
||||
minimized: Ref<boolean>;
|
||||
name: string;
|
||||
color?: string;
|
||||
minimizable?: boolean;
|
||||
nodes: Ref<Record<string, FeatureNode | undefined>>;
|
||||
}>();
|
||||
|
||||
const component = computeComponent(display);
|
||||
const minimizedComponent = computeOptionalComponent(minimizedDisplay);
|
||||
const showGoBack = computed(
|
||||
() => projInfo.allowGoBack && index.value > 0 && !unwrapRef(minimized)
|
||||
);
|
||||
const component = computeComponent(toRef(props, "display"));
|
||||
const minimizedComponent = computeOptionalComponent(toRef(props, "minimizedDisplay"));
|
||||
const showGoBack = computed(
|
||||
() => projInfo.allowGoBack && props.index > 0 && !unref(props.minimized)
|
||||
);
|
||||
|
||||
function goBack() {
|
||||
function goBack() {
|
||||
player.tabs.splice(unref(props.index), Infinity);
|
||||
}
|
||||
}
|
||||
|
||||
function updateNodes(nodes: Record<string, FeatureNode | undefined>) {
|
||||
function updateNodes(nodes: Record<string, FeatureNode | undefined>) {
|
||||
props.nodes.value = nodes;
|
||||
}
|
||||
}
|
||||
|
||||
const errors = ref<Error[]>([]);
|
||||
onErrorCaptured((err, instance, info) => {
|
||||
const errors = ref<Error[]>([]);
|
||||
onErrorCaptured((err, instance, info) => {
|
||||
console.warn(`Error caught in "${props.name}" layer`, err, instance, info);
|
||||
errors.value.push(
|
||||
err instanceof Error ? (err as Error) : new Error(JSON.stringify(err))
|
||||
);
|
||||
return false;
|
||||
});
|
||||
|
||||
return {
|
||||
component,
|
||||
minimizedComponent,
|
||||
showGoBack,
|
||||
updateNodes,
|
||||
unref,
|
||||
goBack,
|
||||
errors
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
<script setup lang="ts">
|
||||
import "components/common/fields.css";
|
||||
import type { CoercableComponent } from "features/feature";
|
||||
import { computeOptionalComponent, unwrapRef } from "util/vue";
|
||||
import { ref, toRef, watch } from "vue";
|
||||
import { computeOptionalComponent } from "util/vue";
|
||||
import { ref, toRef, unref, watch } from "vue";
|
||||
import VueNextSelect from "vue-next-select";
|
||||
import "vue-next-select/dist/index.css";
|
||||
|
||||
|
@ -40,7 +40,7 @@ const value = ref<SelectOption | null>(
|
|||
props.options.find(option => option.value === props.modelValue) ?? null
|
||||
);
|
||||
watch(toRef(props, "modelValue"), modelValue => {
|
||||
if (unwrapRef(value) !== modelValue) {
|
||||
if (unref(value) !== modelValue) {
|
||||
value.value = props.options.find(option => option.value === modelValue) ?? null;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -23,49 +23,31 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
<script setup lang="tsx">
|
||||
import "components/common/features.css";
|
||||
import MarkNode from "components/MarkNode.vue";
|
||||
import Node from "components/Node.vue";
|
||||
import { isHidden, isVisible, jsx, Visibility } from "features/feature";
|
||||
import { displayRequirements, Requirements } from "game/requirements";
|
||||
import { coerceComponent, isCoercableComponent, processedPropType, unwrapRef } from "util/vue";
|
||||
import { Component, defineComponent, shallowRef, StyleValue, toRefs, unref, UnwrapRef, watchEffect } from "vue";
|
||||
import { coerceComponent, isCoercableComponent } from "util/vue";
|
||||
import { Component, shallowRef, StyleValue, unref, UnwrapRef, watchEffect } from "vue";
|
||||
import { GenericAchievement } from "./achievement";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
display: processedPropType<UnwrapRef<GenericAchievement["display"]>>(Object, String, Function),
|
||||
earned: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
requirements: processedPropType<Requirements>(Object, Array),
|
||||
image: processedPropType<string>(String),
|
||||
style: processedPropType<StyleValue>(String, Object, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
mark: processedPropType<boolean | string>(Boolean, String),
|
||||
small: processedPropType<boolean>(Boolean),
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Node,
|
||||
MarkNode
|
||||
},
|
||||
setup(props) {
|
||||
const { display, requirements, earned } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
visibility: Visibility | boolean;
|
||||
display?: UnwrapRef<GenericAchievement["display"]>;
|
||||
earned: boolean;
|
||||
requirements?: Requirements;
|
||||
image?: string;
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
mark?: boolean | string;
|
||||
small?: boolean;
|
||||
id: string;
|
||||
}>();
|
||||
|
||||
const comp = shallowRef<Component | string>("");
|
||||
const comp = shallowRef<Component | string>("");
|
||||
|
||||
watchEffect(() => {
|
||||
const currDisplay = unwrapRef(display);
|
||||
watchEffect(() => {
|
||||
const currDisplay = props.display;
|
||||
if (currDisplay == null) {
|
||||
comp.value = "";
|
||||
return;
|
||||
|
@ -74,9 +56,10 @@ export default defineComponent({
|
|||
comp.value = coerceComponent(currDisplay);
|
||||
return;
|
||||
}
|
||||
const Requirement = coerceComponent(currDisplay.requirement ? currDisplay.requirement : jsx(() => displayRequirements(unwrapRef(requirements) ?? [])), "h3");
|
||||
const Requirement = coerceComponent(currDisplay.requirement ? currDisplay.requirement :
|
||||
jsx(() => displayRequirements(props.requirements ?? [])), "h3");
|
||||
const EffectDisplay = coerceComponent(currDisplay.effectDisplay || "", "b");
|
||||
const OptionsDisplay = unwrapRef(earned) ?
|
||||
const OptionsDisplay = props.earned ?
|
||||
coerceComponent(currDisplay.optionsDisplay || "", "span") :
|
||||
"";
|
||||
comp.value = coerceComponent(
|
||||
|
@ -96,16 +79,6 @@ export default defineComponent({
|
|||
</span>
|
||||
))
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
comp,
|
||||
unref,
|
||||
Visibility,
|
||||
isVisible,
|
||||
isHidden
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -41,80 +41,53 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import MarkNode from "components/MarkNode.vue";
|
||||
import Node from "components/Node.vue";
|
||||
<script setup lang="ts">
|
||||
import { CoercableComponent, isHidden, isVisible, Visibility } from "features/feature";
|
||||
import type { DecimalSource } from "util/bignum";
|
||||
import Decimal from "util/bignum";
|
||||
import { Direction } from "util/common";
|
||||
import { computeOptionalComponent, processedPropType, unwrapRef } from "util/vue";
|
||||
import { computeOptionalComponent } from "util/vue";
|
||||
import type { CSSProperties, StyleValue } from "vue";
|
||||
import { computed, defineComponent, toRefs, unref } from "vue";
|
||||
import { computed, toRef, unref } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
progress: {
|
||||
type: processedPropType<DecimalSource>(String, Object, Number),
|
||||
required: true
|
||||
},
|
||||
width: {
|
||||
type: processedPropType<number>(Number),
|
||||
required: true
|
||||
},
|
||||
height: {
|
||||
type: processedPropType<number>(Number),
|
||||
required: true
|
||||
},
|
||||
direction: {
|
||||
type: processedPropType<Direction>(String),
|
||||
required: true
|
||||
},
|
||||
display: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
style: processedPropType<StyleValue>(Object, String, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
borderStyle: processedPropType<StyleValue>(Object, String, Array),
|
||||
textStyle: processedPropType<StyleValue>(Object, String, Array),
|
||||
baseStyle: processedPropType<StyleValue>(Object, String, Array),
|
||||
fillStyle: processedPropType<StyleValue>(Object, String, Array),
|
||||
mark: processedPropType<boolean | string>(Boolean, String),
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MarkNode,
|
||||
Node
|
||||
},
|
||||
setup(props) {
|
||||
const { progress, width, height, direction, display } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
progress: DecimalSource;
|
||||
width: number;
|
||||
height: number;
|
||||
direction: Direction;
|
||||
display?: CoercableComponent;
|
||||
visibility: Visibility | boolean;
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
borderStyle?: StyleValue;
|
||||
textStyle?: StyleValue;
|
||||
baseStyle?: StyleValue;
|
||||
fillStyle?: StyleValue;
|
||||
mark?: boolean | string;
|
||||
id: string;
|
||||
}>();
|
||||
|
||||
const normalizedProgress = computed(() => {
|
||||
const normalizedProgress = computed(() => {
|
||||
let progressNumber =
|
||||
progress.value instanceof Decimal
|
||||
? progress.value.toNumber()
|
||||
: Number(progress.value);
|
||||
props.progress instanceof Decimal
|
||||
? props.progress.toNumber()
|
||||
: Number(props.progress);
|
||||
return (1 - Math.min(Math.max(progressNumber, 0), 1)) * 100;
|
||||
});
|
||||
});
|
||||
|
||||
const barStyle = computed(() => {
|
||||
const barStyle = computed(() => {
|
||||
const barStyle: Partial<CSSProperties> = {
|
||||
width: unwrapRef(width) + 0.5 + "px",
|
||||
height: unwrapRef(height) + 0.5 + "px"
|
||||
width: props.width + 0.5 + "px",
|
||||
height: props.height + 0.5 + "px"
|
||||
};
|
||||
switch (unref(direction)) {
|
||||
switch (props.direction) {
|
||||
case Direction.Up:
|
||||
barStyle.clipPath = `inset(${normalizedProgress.value}% 0% 0% 0%)`;
|
||||
barStyle.width = unwrapRef(width) + 1 + "px";
|
||||
barStyle.width = props.width + 1 + "px";
|
||||
break;
|
||||
case Direction.Down:
|
||||
barStyle.clipPath = `inset(0% 0% ${normalizedProgress.value}% 0%)`;
|
||||
barStyle.width = unwrapRef(width) + 1 + "px";
|
||||
barStyle.width = props.width + 1 + "px";
|
||||
break;
|
||||
case Direction.Right:
|
||||
barStyle.clipPath = `inset(0% ${normalizedProgress.value}% 0% 0%)`;
|
||||
|
@ -127,21 +100,9 @@ export default defineComponent({
|
|||
break;
|
||||
}
|
||||
return barStyle;
|
||||
});
|
||||
|
||||
const component = computeOptionalComponent(display);
|
||||
|
||||
return {
|
||||
normalizedProgress,
|
||||
barStyle,
|
||||
component,
|
||||
unref,
|
||||
Visibility,
|
||||
isVisible,
|
||||
isHidden
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const component = computeOptionalComponent(toRef(props, "display"));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
<script setup lang="tsx">
|
||||
import "components/common/features.css";
|
||||
import MarkNode from "components/MarkNode.vue";
|
||||
import Node from "components/Node.vue";
|
||||
|
@ -39,76 +39,41 @@ import type { StyleValue } from "features/feature";
|
|||
import { isHidden, isVisible, jsx, Visibility } from "features/feature";
|
||||
import { getHighNotifyStyle, getNotifyStyle } from "game/notifications";
|
||||
import { displayRequirements, Requirements } from "game/requirements";
|
||||
import { coerceComponent, isCoercableComponent, processedPropType, unwrapRef } from "util/vue";
|
||||
import type { Component, PropType, UnwrapRef } from "vue";
|
||||
import { computed, defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue";
|
||||
import { coerceComponent, isCoercableComponent } from "util/vue";
|
||||
import type { Component, UnwrapRef } from "vue";
|
||||
import { computed, shallowRef, unref, watchEffect } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
active: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
maxed: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
canComplete: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
display: processedPropType<UnwrapRef<GenericChallenge["display"]>>(
|
||||
String,
|
||||
Object,
|
||||
Function
|
||||
),
|
||||
requirements: processedPropType<Requirements>(Object, Array),
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
style: processedPropType<StyleValue>(String, Object, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
completed: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
canStart: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
mark: processedPropType<boolean | string>(Boolean, String),
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
toggle: {
|
||||
type: Function as PropType<VoidFunction>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MarkNode,
|
||||
Node
|
||||
},
|
||||
setup(props) {
|
||||
const { active, maxed, canComplete, display, requirements } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
active: boolean;
|
||||
maxed: boolean;
|
||||
canComplete: boolean;
|
||||
display?: UnwrapRef<GenericChallenge["display"]>;
|
||||
requirements?: Requirements;
|
||||
visibility: Visibility | boolean;
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
completed: boolean;
|
||||
canStart: boolean;
|
||||
mark?: boolean | string;
|
||||
id: string;
|
||||
toggle: VoidFunction;
|
||||
}>();
|
||||
|
||||
const buttonText = computed(() => {
|
||||
if (active.value) {
|
||||
return canComplete.value ? "Finish" : "Exit Early";
|
||||
const buttonText = computed(() => {
|
||||
if (props.active) {
|
||||
return props.canComplete ? "Finish" : "Exit Early";
|
||||
}
|
||||
if (maxed.value) {
|
||||
if (props.maxed) {
|
||||
return "Completed";
|
||||
}
|
||||
return "Start";
|
||||
});
|
||||
});
|
||||
|
||||
const comp = shallowRef<Component | string>("");
|
||||
const comp = shallowRef<Component | string>("");
|
||||
|
||||
const notifyStyle = computed(() => {
|
||||
const currActive = unwrapRef(active);
|
||||
const currCanComplete = unwrapRef(canComplete);
|
||||
const notifyStyle = computed(() => {
|
||||
const currActive = props.active;
|
||||
const currCanComplete = props.canComplete;
|
||||
if (currActive) {
|
||||
if (currCanComplete) {
|
||||
return getHighNotifyStyle();
|
||||
|
@ -116,10 +81,10 @@ export default defineComponent({
|
|||
return getNotifyStyle();
|
||||
}
|
||||
return {};
|
||||
});
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
const currDisplay = unwrapRef(display);
|
||||
watchEffect(() => {
|
||||
const currDisplay = props.display;
|
||||
if (currDisplay == null) {
|
||||
comp.value = "";
|
||||
return;
|
||||
|
@ -130,7 +95,7 @@ export default defineComponent({
|
|||
}
|
||||
const Title = coerceComponent(currDisplay.title || "", "h3");
|
||||
const Description = coerceComponent(currDisplay.description, "div");
|
||||
const Goal = coerceComponent(currDisplay.goal != null ? currDisplay.goal : jsx(() => displayRequirements(unwrapRef(requirements) ?? [])), "h3");
|
||||
const Goal = coerceComponent(currDisplay.goal != null ? currDisplay.goal : jsx(() => displayRequirements(props.requirements ?? [])), "h3");
|
||||
const Reward = coerceComponent(currDisplay.reward || "");
|
||||
const EffectDisplay = coerceComponent(currDisplay.effectDisplay || "");
|
||||
comp.value = coerceComponent(
|
||||
|
@ -160,18 +125,6 @@ export default defineComponent({
|
|||
</span>
|
||||
))
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
buttonText,
|
||||
notifyStyle,
|
||||
comp,
|
||||
Visibility,
|
||||
isVisible,
|
||||
isHidden,
|
||||
unref
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</button>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
<script setup lang="tsx">
|
||||
import "components/common/features.css";
|
||||
import MarkNode from "components/MarkNode.vue";
|
||||
import Node from "components/Node.vue";
|
||||
|
@ -37,53 +37,28 @@ import { isHidden, isVisible, jsx, Visibility } from "features/feature";
|
|||
import {
|
||||
coerceComponent,
|
||||
isCoercableComponent,
|
||||
processedPropType,
|
||||
setupHoldToClick,
|
||||
unwrapRef
|
||||
setupHoldToClick
|
||||
} from "util/vue";
|
||||
import type { Component, PropType, UnwrapRef } from "vue";
|
||||
import { defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue";
|
||||
import type { Component, UnwrapRef } from "vue";
|
||||
import { shallowRef, toRef, unref, watchEffect } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
display: {
|
||||
type: processedPropType<UnwrapRef<GenericClickable["display"]>>(
|
||||
Object,
|
||||
String,
|
||||
Function
|
||||
),
|
||||
required: true
|
||||
},
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
style: processedPropType<StyleValue>(Object, String, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
onClick: Function as PropType<(e?: MouseEvent | TouchEvent) => void>,
|
||||
onHold: Function as PropType<VoidFunction>,
|
||||
canClick: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
small: Boolean,
|
||||
mark: processedPropType<boolean | string>(Boolean, String),
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Node,
|
||||
MarkNode
|
||||
},
|
||||
setup(props) {
|
||||
const { display, onClick, onHold } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
display: UnwrapRef<GenericClickable["display"]>;
|
||||
visibility: Visibility | boolean;
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
onClick?: (e?: MouseEvent | TouchEvent) => void;
|
||||
onHold?: VoidFunction;
|
||||
canClick: boolean;
|
||||
small?: boolean;
|
||||
mark?: boolean | string;
|
||||
id: string;
|
||||
}>();
|
||||
|
||||
const comp = shallowRef<Component | string>("");
|
||||
const comp = shallowRef<Component | string>("");
|
||||
|
||||
watchEffect(() => {
|
||||
const currDisplay = unwrapRef(display);
|
||||
watchEffect(() => {
|
||||
const currDisplay = props.display;
|
||||
if (currDisplay == null) {
|
||||
comp.value = "";
|
||||
return;
|
||||
|
@ -106,21 +81,9 @@ export default defineComponent({
|
|||
</span>
|
||||
))
|
||||
);
|
||||
});
|
||||
|
||||
const { start, stop } = setupHoldToClick(onClick, onHold);
|
||||
|
||||
return {
|
||||
start,
|
||||
stop,
|
||||
comp,
|
||||
Visibility,
|
||||
isVisible,
|
||||
isHidden,
|
||||
unref
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const { start, stop } = setupHoldToClick(toRef(props, "onClick"), toRef(props, "onHold"));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
class="table-grid"
|
||||
>
|
||||
<div v-for="row in unref(rows)" class="row-grid" :class="{ mergeAdjacent }" :key="row">
|
||||
<GridCell
|
||||
<GridCellVue
|
||||
v-for="col in unref(cols)"
|
||||
:key="col"
|
||||
v-bind="gatherCellProps(unref(cells)[row * 100 + col])"
|
||||
|
@ -16,45 +16,26 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import "components/common/table.css";
|
||||
import themes from "data/themes";
|
||||
import { isHidden, isVisible, Visibility } from "features/feature";
|
||||
import type { GridCell } from "features/grids/grid";
|
||||
import settings from "game/settings";
|
||||
import { processedPropType } from "util/vue";
|
||||
import { computed, defineComponent, unref } from "vue";
|
||||
import { computed, unref } from "vue";
|
||||
import GridCellVue from "./GridCell.vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
rows: {
|
||||
type: processedPropType<number>(Number),
|
||||
required: true
|
||||
},
|
||||
cols: {
|
||||
type: processedPropType<number>(Number),
|
||||
required: true
|
||||
},
|
||||
cells: {
|
||||
type: processedPropType<Record<string, GridCell>>(Object),
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: { GridCell: GridCellVue },
|
||||
setup() {
|
||||
const mergeAdjacent = computed(() => themes[settings.theme].mergeAdjacent);
|
||||
defineProps<{
|
||||
visibility: Visibility | boolean;
|
||||
rows: number;
|
||||
cols: number;
|
||||
cells: Record<string, GridCell>;
|
||||
}>();
|
||||
|
||||
function gatherCellProps(cell: GridCell) {
|
||||
const mergeAdjacent = computed(() => themes[settings.theme].mergeAdjacent);
|
||||
|
||||
function gatherCellProps(cell: GridCell) {
|
||||
const { visibility, onClick, onHold, display, title, style, canClick, id } = cell;
|
||||
return { visibility, onClick, onHold, display, title, style, canClick, id };
|
||||
}
|
||||
|
||||
return { unref, gatherCellProps, Visibility, mergeAdjacent, isVisible, isHidden };
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
</button>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import "components/common/features.css";
|
||||
import Node from "components/Node.vue";
|
||||
import type { CoercableComponent, StyleValue } from "features/feature";
|
||||
|
@ -30,58 +30,26 @@ import { isHidden, isVisible, Visibility } from "features/feature";
|
|||
import {
|
||||
computeComponent,
|
||||
computeOptionalComponent,
|
||||
processedPropType,
|
||||
setupHoldToClick
|
||||
} from "util/vue";
|
||||
import type { PropType } from "vue";
|
||||
import { defineComponent, toRefs, unref } from "vue";
|
||||
import { toRef, unref } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
onClick: Function as PropType<(e?: MouseEvent | TouchEvent) => void>,
|
||||
onHold: Function as PropType<VoidFunction>,
|
||||
display: {
|
||||
type: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
required: true
|
||||
},
|
||||
title: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
style: processedPropType<StyleValue>(String, Object, Array),
|
||||
canClick: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Node
|
||||
},
|
||||
setup(props) {
|
||||
const { onClick, onHold, title, display } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
visibility: Visibility | boolean;
|
||||
onClick?: (e?: MouseEvent | TouchEvent) => void;
|
||||
onHold?: VoidFunction;
|
||||
display: CoercableComponent;
|
||||
title?: CoercableComponent;
|
||||
style?: StyleValue;
|
||||
canClick: boolean;
|
||||
id: string;
|
||||
}>();
|
||||
|
||||
const { start, stop } = setupHoldToClick(onClick, onHold);
|
||||
|
||||
const titleComponent = computeOptionalComponent(title);
|
||||
const component = computeComponent(display);
|
||||
const { start, stop } = setupHoldToClick(toRef(props, "onClick"), toRef(props, "onHold"));
|
||||
|
||||
return {
|
||||
start,
|
||||
stop,
|
||||
titleComponent,
|
||||
component,
|
||||
Visibility,
|
||||
unref,
|
||||
isVisible,
|
||||
isHidden
|
||||
};
|
||||
}
|
||||
});
|
||||
const titleComponent = computeOptionalComponent(toRef(props, "title"));
|
||||
const component = computeComponent(toRef(props, "display"));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -28,67 +28,33 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import CollapseTransition from "@ivanv/vue-collapse-transition/src/CollapseTransition.vue";
|
||||
import Node from "components/Node.vue";
|
||||
import themes from "data/themes";
|
||||
import type { CoercableComponent } from "features/feature";
|
||||
import { isHidden, isVisible, Visibility } from "features/feature";
|
||||
import settings from "game/settings";
|
||||
import { computeComponent, processedPropType } from "util/vue";
|
||||
import type { PropType, Ref, StyleValue } from "vue";
|
||||
import { computed, defineComponent, toRefs, unref } from "vue";
|
||||
import { computeComponent } from "util/vue";
|
||||
import type { Ref, StyleValue } from "vue";
|
||||
import { computed, toRef, unref } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
display: {
|
||||
type: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
required: true
|
||||
},
|
||||
title: {
|
||||
type: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
required: true
|
||||
},
|
||||
color: processedPropType<string>(String),
|
||||
collapsed: {
|
||||
type: Object as PropType<Ref<boolean>>,
|
||||
required: true
|
||||
},
|
||||
style: processedPropType<StyleValue>(Object, String, Array),
|
||||
titleStyle: processedPropType<StyleValue>(Object, String, Array),
|
||||
bodyStyle: processedPropType<StyleValue>(Object, String, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Node,
|
||||
CollapseTransition
|
||||
},
|
||||
setup(props) {
|
||||
const { title, display } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
visibility: Visibility | boolean;
|
||||
display: CoercableComponent;
|
||||
title: CoercableComponent;
|
||||
color?: string;
|
||||
collapsed: Ref<boolean>;
|
||||
style?: StyleValue;
|
||||
titleStyle?: StyleValue;
|
||||
bodyStyle?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
id: string;
|
||||
}>();
|
||||
|
||||
const titleComponent = computeComponent(title);
|
||||
const bodyComponent = computeComponent(display);
|
||||
const stacked = computed(() => themes[settings.theme].mergeAdjacent);
|
||||
|
||||
return {
|
||||
titleComponent,
|
||||
bodyComponent,
|
||||
stacked,
|
||||
unref,
|
||||
Visibility,
|
||||
isVisible,
|
||||
isHidden
|
||||
};
|
||||
}
|
||||
});
|
||||
const titleComponent = computeComponent(toRef(props, "title"));
|
||||
const bodyComponent = computeComponent(toRef(props, "display"));
|
||||
const stacked = computed(() => themes[settings.theme].mergeAdjacent);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -7,38 +7,28 @@
|
|||
/>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
<script setup lang="tsx">
|
||||
import { Application } from "@pixi/app";
|
||||
import type { StyleValue } from "features/feature";
|
||||
import { globalBus } from "game/events";
|
||||
import "lib/pixi";
|
||||
import { processedPropType } from "util/vue";
|
||||
import type { PropType } from "vue";
|
||||
import { defineComponent, nextTick, onBeforeUnmount, onMounted, shallowRef, unref } from "vue";
|
||||
import { nextTick, onBeforeUnmount, onMounted, shallowRef, unref } from "vue";
|
||||
|
||||
// TODO get typing support on the Particles component
|
||||
export default defineComponent({
|
||||
props: {
|
||||
style: processedPropType<StyleValue>(String, Object, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
onInit: {
|
||||
type: Function as PropType<(app: Application) => void>,
|
||||
required: true
|
||||
},
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
onContainerResized: Function as PropType<(rect: DOMRect) => void>,
|
||||
onHotReload: Function as PropType<VoidFunction>
|
||||
},
|
||||
setup(props) {
|
||||
const app = shallowRef<null | Application>(null);
|
||||
const props = defineProps<{
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
onInit: (app: Application) => void;
|
||||
id: string;
|
||||
onContainerResized?: (rect: DOMRect) => void;
|
||||
onHotReload?: VoidFunction;
|
||||
}>();
|
||||
|
||||
const resizeObserver = new ResizeObserver(updateBounds);
|
||||
const resizeListener = shallowRef<HTMLElement | null>(null);
|
||||
const app = shallowRef<null | Application>(null);
|
||||
|
||||
onMounted(() => {
|
||||
const resizeObserver = new ResizeObserver(updateBounds);
|
||||
const resizeListener = shallowRef<HTMLElement | null>(null);
|
||||
|
||||
onMounted(() => {
|
||||
// ResizeListener exists because ResizeObserver's don't work when told to observe an SVG element
|
||||
const resListener = resizeListener.value;
|
||||
if (resListener != null) {
|
||||
|
@ -54,13 +44,13 @@ export default defineComponent({
|
|||
if (props.onHotReload) {
|
||||
nextTick(props.onHotReload);
|
||||
}
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
app.value?.destroy();
|
||||
});
|
||||
});
|
||||
|
||||
let isDirty = true;
|
||||
function updateBounds() {
|
||||
let isDirty = true;
|
||||
function updateBounds() {
|
||||
if (isDirty) {
|
||||
isDirty = false;
|
||||
nextTick(() => {
|
||||
|
@ -70,15 +60,8 @@ export default defineComponent({
|
|||
isDirty = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
globalBus.on("fontsLoaded", updateBounds);
|
||||
|
||||
return {
|
||||
unref,
|
||||
resizeListener
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
globalBus.on("fontsLoaded", updateBounds);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -19,61 +19,43 @@
|
|||
</button>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import type { CoercableComponent, StyleValue } from "features/feature";
|
||||
import { isHidden, isVisible, Visibility } from "features/feature";
|
||||
import { getNotifyStyle } from "game/notifications";
|
||||
import { computeComponent, processedPropType, unwrapRef } from "util/vue";
|
||||
import { computed, defineComponent, toRefs, unref } from "vue";
|
||||
import { computeComponent } from "util/vue";
|
||||
import { computed, toRef, unref } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
display: {
|
||||
type: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
required: true
|
||||
},
|
||||
style: processedPropType<StyleValue>(String, Object, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
glowColor: processedPropType<string>(String),
|
||||
active: Boolean,
|
||||
floating: Boolean
|
||||
},
|
||||
emits: ["selectTab"],
|
||||
setup(props, { emit }) {
|
||||
const { display, glowColor, floating } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
visibility: Visibility | boolean;
|
||||
display: CoercableComponent;
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
glowColor?: string;
|
||||
active?: boolean;
|
||||
floating?: boolean;
|
||||
}>();
|
||||
|
||||
const component = computeComponent(display);
|
||||
const emit = defineEmits<{
|
||||
selectTab: [];
|
||||
}>();
|
||||
|
||||
const glowColorStyle = computed(() => {
|
||||
const color = unwrapRef(glowColor);
|
||||
const component = computeComponent(toRef(props, "display"));
|
||||
|
||||
const glowColorStyle = computed(() => {
|
||||
const color = props.glowColor;
|
||||
if (color == null || color === "") {
|
||||
return {};
|
||||
}
|
||||
if (unref(floating)) {
|
||||
if (props.floating) {
|
||||
return getNotifyStyle(color);
|
||||
}
|
||||
return { boxShadow: `0px 9px 5px -6px ${color}` };
|
||||
});
|
||||
|
||||
function selectTab() {
|
||||
emit("selectTab");
|
||||
}
|
||||
|
||||
return {
|
||||
selectTab,
|
||||
component,
|
||||
glowColorStyle,
|
||||
unref,
|
||||
Visibility,
|
||||
isVisible,
|
||||
isHidden
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
function selectTab() {
|
||||
emit("selectTab");
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
<script setup lang="ts">
|
||||
import Sticky from "components/layout/Sticky.vue";
|
||||
import themes from "data/themes";
|
||||
import type { CoercableComponent, StyleValue } from "features/feature";
|
||||
|
@ -42,48 +42,29 @@ import type { GenericTab } from "features/tabs/tab";
|
|||
import TabButton from "features/tabs/TabButton.vue";
|
||||
import type { GenericTabButton } from "features/tabs/tabFamily";
|
||||
import settings from "game/settings";
|
||||
import { coerceComponent, isCoercableComponent, processedPropType, unwrapRef } from "util/vue";
|
||||
import type { Component, PropType, Ref } from "vue";
|
||||
import { computed, defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue";
|
||||
import { coerceComponent, deepUnref, isCoercableComponent } from "util/vue";
|
||||
import type { Component, Ref } from "vue";
|
||||
import { computed, shallowRef, unref, watchEffect } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
activeTab: {
|
||||
type: processedPropType<GenericTab | CoercableComponent | null>(Object),
|
||||
required: true
|
||||
},
|
||||
selected: {
|
||||
type: Object as PropType<Ref<string>>,
|
||||
required: true
|
||||
},
|
||||
tabs: {
|
||||
type: processedPropType<Record<string, GenericTabButton>>(Object),
|
||||
required: true
|
||||
},
|
||||
style: processedPropType<StyleValue>(String, Object, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
buttonContainerStyle: processedPropType<StyleValue>(String, Object, Array),
|
||||
buttonContainerClasses: processedPropType<Record<string, boolean>>(Object)
|
||||
},
|
||||
components: {
|
||||
Sticky,
|
||||
TabButton
|
||||
},
|
||||
setup(props) {
|
||||
const { activeTab } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
visibility: Visibility | boolean;
|
||||
activeTab: GenericTab | CoercableComponent | null;
|
||||
selected: Ref<string>;
|
||||
tabs: Record<string, GenericTabButton>;
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
buttonContainerStyle?: StyleValue;
|
||||
buttonContainerClasses?: Record<string, boolean>;
|
||||
}>();
|
||||
|
||||
const floating = computed(() => {
|
||||
const floating = computed(() => {
|
||||
return themes[settings.theme].floatingTabs;
|
||||
});
|
||||
});
|
||||
|
||||
const component = shallowRef<Component | string>("");
|
||||
const component = shallowRef<Component | string>("");
|
||||
|
||||
watchEffect(() => {
|
||||
const currActiveTab = unwrapRef(activeTab);
|
||||
watchEffect(() => {
|
||||
const currActiveTab = props.activeTab;
|
||||
if (currActiveTab == null) {
|
||||
component.value = "";
|
||||
return;
|
||||
|
@ -93,42 +74,28 @@ export default defineComponent({
|
|||
return;
|
||||
}
|
||||
component.value = coerceComponent(unref(currActiveTab.display));
|
||||
});
|
||||
});
|
||||
|
||||
const tabClasses = computed(() => {
|
||||
const currActiveTab = unwrapRef(activeTab);
|
||||
const tabClasses = computed(() => {
|
||||
const currActiveTab = props.activeTab;
|
||||
const tabClasses =
|
||||
isCoercableComponent(currActiveTab) || !currActiveTab
|
||||
? undefined
|
||||
: unref(currActiveTab.classes);
|
||||
return tabClasses;
|
||||
});
|
||||
});
|
||||
|
||||
const tabStyle = computed(() => {
|
||||
const currActiveTab = unwrapRef(activeTab);
|
||||
const tabStyle = computed(() => {
|
||||
const currActiveTab = props.activeTab;
|
||||
return isCoercableComponent(currActiveTab) || !currActiveTab
|
||||
? undefined
|
||||
: unref(currActiveTab.style);
|
||||
});
|
||||
|
||||
function gatherButtonProps(button: GenericTabButton) {
|
||||
const { display, style, classes, glowColor, visibility } = button;
|
||||
return { display, style: unref(style), classes, glowColor, visibility };
|
||||
}
|
||||
|
||||
return {
|
||||
floating,
|
||||
tabClasses,
|
||||
tabStyle,
|
||||
Visibility,
|
||||
component,
|
||||
gatherButtonProps,
|
||||
unref,
|
||||
isVisible,
|
||||
isHidden
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
function gatherButtonProps(button: GenericTabButton) {
|
||||
const { display, style, classes, glowColor, visibility } = deepUnref(button);
|
||||
return { display, style, classes, glowColor, visibility };
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
<script setup lang="tsx">
|
||||
import themes from "data/themes";
|
||||
import type { CoercableComponent } from "features/feature";
|
||||
import { jsx, StyleValue } from "features/feature";
|
||||
|
@ -45,66 +45,45 @@ import type { VueFeature } from "util/vue";
|
|||
import {
|
||||
coerceComponent,
|
||||
computeOptionalComponent,
|
||||
processedPropType,
|
||||
renderJSX,
|
||||
unwrapRef
|
||||
renderJSX
|
||||
} from "util/vue";
|
||||
import type { Component, PropType } from "vue";
|
||||
import { computed, defineComponent, ref, shallowRef, toRefs, unref } from "vue";
|
||||
import type { Component } from "vue";
|
||||
import { computed, ref, shallowRef, toRef, unref } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
element: Object as PropType<VueFeature>,
|
||||
display: {
|
||||
type: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
required: true
|
||||
},
|
||||
style: processedPropType<StyleValue>(Object, String, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
direction: processedPropType<Direction>(String),
|
||||
xoffset: processedPropType<string>(String),
|
||||
yoffset: processedPropType<string>(String),
|
||||
pinned: Object as PropType<Persistent<boolean>>
|
||||
},
|
||||
setup(props) {
|
||||
const { element, display, pinned } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
element?: VueFeature;
|
||||
display: CoercableComponent;
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
direction?: Direction;
|
||||
xoffset?: string;
|
||||
yoffset?: string;
|
||||
pinned?: Persistent<boolean>;
|
||||
}>();
|
||||
|
||||
const isHovered = ref(false);
|
||||
const isShown = computed(() => (unwrapRef(pinned) || isHovered.value) && comp.value);
|
||||
const comp = computeOptionalComponent(display);
|
||||
const isHovered = ref(false);
|
||||
const isShown = computed(() => (props.pinned?.value === true || isHovered.value) && comp.value);
|
||||
const comp = computeOptionalComponent(toRef(props, "display"));
|
||||
|
||||
const elementComp = shallowRef<Component | "" | null>(
|
||||
const elementComp = shallowRef<Component | "" | null>(
|
||||
coerceComponent(
|
||||
jsx(() => {
|
||||
const currComponent = unwrapRef(element);
|
||||
const currComponent = props.element;
|
||||
return currComponent == null ? "" : renderJSX(currComponent);
|
||||
})
|
||||
)
|
||||
);
|
||||
);
|
||||
|
||||
function togglePinned(e: MouseEvent) {
|
||||
const isPinned = pinned as unknown as Persistent<boolean> | undefined; // Vue typing :/
|
||||
if (e.shiftKey && isPinned) {
|
||||
function togglePinned(e: MouseEvent) {
|
||||
const isPinned = props.pinned;
|
||||
if (e.shiftKey && isPinned != null) {
|
||||
isPinned.value = !isPinned.value;
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const showPin = computed(() => unwrapRef(pinned) && themes[settings.theme].showPin);
|
||||
|
||||
return {
|
||||
Direction,
|
||||
isHovered,
|
||||
isShown,
|
||||
comp,
|
||||
elementComp,
|
||||
unref,
|
||||
togglePinned,
|
||||
showPin
|
||||
};
|
||||
}
|
||||
});
|
||||
const showPin = computed(() => props.pinned?.value === true && themes[settings.theme].showPin);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -5,32 +5,25 @@
|
|||
<Links v-if="branches" :links="unref(branches)" />
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
<script setup lang="tsx">
|
||||
import "components/common/table.css";
|
||||
import { jsx } from "features/feature";
|
||||
import Links from "features/links/Links.vue";
|
||||
import type { GenericTreeNode, TreeBranch } from "features/trees/tree";
|
||||
import { coerceComponent, processedPropType, renderJSX, unwrapRef } from "util/vue";
|
||||
import { coerceComponent, renderJSX } from "util/vue";
|
||||
import type { Component } from "vue";
|
||||
import { defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue";
|
||||
import { shallowRef, unref, watchEffect } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
nodes: {
|
||||
type: processedPropType<GenericTreeNode[][]>(Array),
|
||||
required: true
|
||||
},
|
||||
leftSideNodes: processedPropType<GenericTreeNode[]>(Array),
|
||||
rightSideNodes: processedPropType<GenericTreeNode[]>(Array),
|
||||
branches: processedPropType<TreeBranch[]>(Array)
|
||||
},
|
||||
components: { Links },
|
||||
setup(props) {
|
||||
const { nodes, leftSideNodes, rightSideNodes } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
nodes: GenericTreeNode[][];
|
||||
leftSideNodes?: GenericTreeNode[];
|
||||
rightSideNodes?: GenericTreeNode[];
|
||||
branches?: TreeBranch[];
|
||||
}>();
|
||||
|
||||
const nodesComp = shallowRef<Component | "">();
|
||||
watchEffect(() => {
|
||||
const currNodes = unwrapRef(nodes);
|
||||
const nodesComp = shallowRef<Component | "">();
|
||||
watchEffect(() => {
|
||||
const currNodes = props.nodes;
|
||||
nodesComp.value = coerceComponent(
|
||||
jsx(() => (
|
||||
<>
|
||||
|
@ -42,11 +35,11 @@ export default defineComponent({
|
|||
</>
|
||||
))
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
const leftNodesComp = shallowRef<Component | "">();
|
||||
watchEffect(() => {
|
||||
const currNodes = unwrapRef(leftSideNodes);
|
||||
const leftNodesComp = shallowRef<Component | "">();
|
||||
watchEffect(() => {
|
||||
const currNodes = props.leftSideNodes;
|
||||
leftNodesComp.value = currNodes
|
||||
? coerceComponent(
|
||||
jsx(() => (
|
||||
|
@ -54,25 +47,16 @@ export default defineComponent({
|
|||
))
|
||||
)
|
||||
: "";
|
||||
});
|
||||
});
|
||||
|
||||
const rightNodesComp = shallowRef<Component | "">();
|
||||
watchEffect(() => {
|
||||
const currNodes = unwrapRef(rightSideNodes);
|
||||
const rightNodesComp = shallowRef<Component | "">();
|
||||
watchEffect(() => {
|
||||
const currNodes = props.rightSideNodes;
|
||||
rightNodesComp.value = currNodes
|
||||
? coerceComponent(
|
||||
jsx(() => <span class="side-nodes small">{currNodes.map(renderJSX)}</span>)
|
||||
)
|
||||
: "";
|
||||
});
|
||||
|
||||
return {
|
||||
unref,
|
||||
nodesComp,
|
||||
leftNodesComp,
|
||||
rightNodesComp
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -33,66 +33,32 @@
|
|||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import MarkNode from "components/MarkNode.vue";
|
||||
import Node from "components/Node.vue";
|
||||
import type { CoercableComponent, StyleValue } from "features/feature";
|
||||
import { isHidden, isVisible, Visibility } from "features/feature";
|
||||
<script setup lang="ts">
|
||||
import type { CoercableComponent, StyleValue, Visibility } from "features/feature";
|
||||
import { isHidden, isVisible } from "features/feature";
|
||||
import {
|
||||
computeOptionalComponent,
|
||||
isCoercableComponent,
|
||||
processedPropType,
|
||||
setupHoldToClick
|
||||
} from "util/vue";
|
||||
import type { PropType } from "vue";
|
||||
import { defineComponent, toRefs, unref } from "vue";
|
||||
import { toRef, unref } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
display: processedPropType<CoercableComponent>(Object, String, Function),
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
style: processedPropType<StyleValue>(String, Object, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
onClick: Function as PropType<(e?: MouseEvent | TouchEvent) => void>,
|
||||
onHold: Function as PropType<VoidFunction>,
|
||||
color: processedPropType<string>(String),
|
||||
glowColor: processedPropType<string>(String),
|
||||
canClick: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
mark: processedPropType<boolean | string>(Boolean, String),
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
MarkNode,
|
||||
Node
|
||||
},
|
||||
setup(props) {
|
||||
const { onClick, onHold, display } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
visibility: Visibility | boolean;
|
||||
canClick: boolean;
|
||||
id: string;
|
||||
display?: CoercableComponent;
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
onClick?: (e?: MouseEvent | TouchEvent) => void;
|
||||
onHold?: VoidFunction;
|
||||
color?: string;
|
||||
glowColor?: string;
|
||||
mark?: boolean | string;
|
||||
}>();
|
||||
|
||||
const comp = computeOptionalComponent(display);
|
||||
const comp = computeOptionalComponent(toRef(props, "display"));
|
||||
|
||||
const { start, stop } = setupHoldToClick(onClick, onHold);
|
||||
|
||||
return {
|
||||
start,
|
||||
stop,
|
||||
comp,
|
||||
unref,
|
||||
Visibility,
|
||||
isCoercableComponent,
|
||||
isVisible,
|
||||
isHidden
|
||||
};
|
||||
}
|
||||
});
|
||||
const { start, stop } = setupHoldToClick(toRef(props, "onClick"), toRef(props, "onHold"));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
</button>
|
||||
</template>
|
||||
|
||||
<script lang="tsx">
|
||||
<script setup lang="tsx">
|
||||
import "components/common/features.css";
|
||||
import MarkNode from "components/MarkNode.vue";
|
||||
import Node from "components/Node.vue";
|
||||
|
@ -32,55 +32,27 @@ import type { StyleValue } from "features/feature";
|
|||
import { isHidden, isVisible, jsx, Visibility } from "features/feature";
|
||||
import type { GenericUpgrade } from "features/upgrades/upgrade";
|
||||
import { displayRequirements, Requirements } from "game/requirements";
|
||||
import { coerceComponent, isCoercableComponent, processedPropType, unwrapRef } from "util/vue";
|
||||
import type { Component, PropType, UnwrapRef } from "vue";
|
||||
import { defineComponent, shallowRef, toRefs, unref, watchEffect } from "vue";
|
||||
import { coerceComponent, isCoercableComponent } from "util/vue";
|
||||
import type { Component, UnwrapRef } from "vue";
|
||||
import { shallowRef, unref, watchEffect } from "vue";
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
display: {
|
||||
type: processedPropType<UnwrapRef<GenericUpgrade["display"]>>(String, Object, Function),
|
||||
required: true
|
||||
},
|
||||
visibility: {
|
||||
type: processedPropType<Visibility | boolean>(Number, Boolean),
|
||||
required: true
|
||||
},
|
||||
style: processedPropType<StyleValue>(String, Object, Array),
|
||||
classes: processedPropType<Record<string, boolean>>(Object),
|
||||
requirements: {
|
||||
type: Object as PropType<Requirements>,
|
||||
required: true
|
||||
},
|
||||
canPurchase: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
bought: {
|
||||
type: processedPropType<boolean>(Boolean),
|
||||
required: true
|
||||
},
|
||||
mark: processedPropType<boolean | string>(Boolean, String),
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
purchase: {
|
||||
type: Function as PropType<VoidFunction>,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Node,
|
||||
MarkNode
|
||||
},
|
||||
setup(props) {
|
||||
const { display, requirements, bought } = toRefs(props);
|
||||
const props = defineProps<{
|
||||
display: UnwrapRef<GenericUpgrade["display"]>;
|
||||
visibility: Visibility | boolean;
|
||||
style?: StyleValue;
|
||||
classes?: Record<string, boolean>;
|
||||
requirements: Requirements;
|
||||
canPurchase: boolean;
|
||||
bought: boolean;
|
||||
mark?: boolean | string;
|
||||
id: string;
|
||||
purchase?: VoidFunction;
|
||||
}>();
|
||||
|
||||
const component = shallowRef<Component | string>("");
|
||||
const component = shallowRef<Component | string>("");
|
||||
|
||||
watchEffect(() => {
|
||||
const currDisplay = unwrapRef(display);
|
||||
watchEffect(() => {
|
||||
const currDisplay = props.display;
|
||||
if (currDisplay == null) {
|
||||
component.value = "";
|
||||
return;
|
||||
|
@ -106,20 +78,10 @@ export default defineComponent({
|
|||
Currently: <EffectDisplay />
|
||||
</div>
|
||||
) : null}
|
||||
{bought.value ? null : <><br />{displayRequirements(requirements.value)}</>}
|
||||
{props.bought ? null : <><br />{displayRequirements(props.requirements)}</>}
|
||||
</span>
|
||||
))
|
||||
);
|
||||
});
|
||||
|
||||
return {
|
||||
component,
|
||||
unref,
|
||||
Visibility,
|
||||
isVisible,
|
||||
isHidden
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
} from "features/feature";
|
||||
import type { ProcessedComputable } from "util/computed";
|
||||
import { DoNotCache } from "util/computed";
|
||||
import type { Component, ComputedRef, DefineComponent, PropType, Ref, ShallowRef } from "vue";
|
||||
import type { Component, DefineComponent, Ref, ShallowRef, UnwrapRef } from "vue";
|
||||
import {
|
||||
computed,
|
||||
defineComponent,
|
||||
|
@ -175,22 +175,22 @@ export function getFirstFeature<
|
|||
}
|
||||
|
||||
export function computeComponent(
|
||||
component: Ref<ProcessedComputable<CoercableComponent>>,
|
||||
component: Ref<CoercableComponent>,
|
||||
defaultWrapper = "div"
|
||||
): ShallowRef<Component | ""> {
|
||||
const comp = shallowRef<Component | "">();
|
||||
watchEffect(() => {
|
||||
comp.value = coerceComponent(unwrapRef(component), defaultWrapper);
|
||||
comp.value = coerceComponent(unref(component), defaultWrapper);
|
||||
});
|
||||
return comp as ShallowRef<Component | "">;
|
||||
}
|
||||
export function computeOptionalComponent(
|
||||
component: Ref<ProcessedComputable<CoercableComponent | undefined> | undefined>,
|
||||
component: Ref<CoercableComponent | undefined>,
|
||||
defaultWrapper = "div"
|
||||
): ShallowRef<Component | "" | null> {
|
||||
const comp = shallowRef<Component | "" | null>(null);
|
||||
watchEffect(() => {
|
||||
const currComponent = unwrapRef(component);
|
||||
const currComponent = unref(component);
|
||||
comp.value =
|
||||
currComponent === "" || currComponent == null
|
||||
? null
|
||||
|
@ -199,12 +199,14 @@ export function computeOptionalComponent(
|
|||
return comp;
|
||||
}
|
||||
|
||||
export function wrapRef<T>(ref: Ref<ProcessedComputable<T>>): ComputedRef<T> {
|
||||
return computed(() => unwrapRef(ref));
|
||||
}
|
||||
|
||||
export function unwrapRef<T>(ref: Ref<ProcessedComputable<T>>): T {
|
||||
return unref<T>(unref(ref));
|
||||
export function deepUnref<T extends object>(refObject: T): { [K in keyof T]: UnwrapRef<T[K]> } {
|
||||
return (Object.keys(refObject) as (keyof T)[]).reduce(
|
||||
(acc, curr) => {
|
||||
acc[curr] = unref(refObject[curr]) as UnwrapRef<T[keyof T]>;
|
||||
return acc;
|
||||
},
|
||||
{} as { [K in keyof T]: UnwrapRef<T[K]> }
|
||||
);
|
||||
}
|
||||
|
||||
export function setRefValue<T>(ref: Ref<T | Ref<T>>, value: T) {
|
||||
|
@ -222,14 +224,6 @@ export type PropTypes =
|
|||
| typeof Function
|
||||
| typeof Object
|
||||
| typeof Array;
|
||||
// TODO Unfortunately, the typescript engine gives up on typing completely when you use this method,
|
||||
// Even though it has the same typing as when doing it manually
|
||||
export function processedPropType<T>(...types: PropTypes[]): PropType<ProcessedComputable<T>> {
|
||||
if (!types.includes(Object)) {
|
||||
types.push(Object);
|
||||
}
|
||||
return types as PropType<ProcessedComputable<T>>;
|
||||
}
|
||||
|
||||
export function trackHover(element: VueFeature): Ref<boolean> {
|
||||
const isHovered = ref(false);
|
||||
|
@ -245,8 +239,11 @@ export function trackHover(element: VueFeature): Ref<boolean> {
|
|||
}
|
||||
|
||||
export function kebabifyObject(object: Record<string, unknown>) {
|
||||
return Object.keys(object).reduce((acc, curr) => {
|
||||
return Object.keys(object).reduce(
|
||||
(acc, curr) => {
|
||||
acc[camelToKebab(curr)] = object[curr];
|
||||
return acc;
|
||||
}, {} as Record<string, unknown>);
|
||||
},
|
||||
{} as Record<string, unknown>
|
||||
);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue