Add feature decorator system #13

Merged
murapix merged 18 commits from main into main 2023-04-20 01:28:11 +00:00
12 changed files with 213 additions and 350 deletions
Showing only changes of commit 691a68ecf2 - Show all commits

View file

@ -1,4 +1,5 @@
import AchievementComponent from "features/achievements/Achievement.vue";
import { Decorator } from "features/decorators";
import {
CoercableComponent,
Component,
@ -72,20 +73,28 @@ export type GenericAchievement = Replace<
>;
export function createAchievement<T extends AchievementOptions>(
optionsFunc?: OptionsFunc<T, BaseAchievement, GenericAchievement>
optionsFunc?: OptionsFunc<T, BaseAchievement, GenericAchievement>,
...decorators: Decorator<T, BaseAchievement, GenericAchievement>[]
): Achievement<T> {
const earned = persistent<boolean>(false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => {
const achievement = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
achievement.id = getUniqueID("achievement-");
achievement.type = AchievementType;
achievement[Component] = AchievementComponent;
for (const decorator of decorators) {
decorator.preConstruct?.(achievement);
}
achievement.earned = earned;
achievement.complete = function () {
earned.value = true;
};
Object.assign(achievement, decoratedData);
processComputable(achievement as T, "visibility");
setDefault(achievement, "visibility", Visibility.Visible);
processComputable(achievement as T, "display");
@ -94,9 +103,14 @@ export function createAchievement<T extends AchievementOptions>(
processComputable(achievement as T, "style");
processComputable(achievement as T, "classes");
for (const decorator of decorators) {
decorator.postConstruct?.(achievement);
}
const decoratedProps = decorators.reduce((current, next) => Object.assign(current, next.getGatheredProps?.(achievement)), {});
achievement[GatherProps] = function (this: GenericAchievement) {
const { visibility, display, earned, image, style, classes, mark, id } = this;
return { visibility, display, earned, image, style: unref(style), classes, mark, id };
return { visibility, display, earned, image, style: unref(style), classes, mark, id, ...decoratedProps };
};
if (achievement.shouldEarn) {

View file

@ -31,6 +31,7 @@ import { coerceComponent, isCoercableComponent, render } from "util/vue";
import { computed, Ref, ref, unref } from "vue";
import { BarOptions, createBar, GenericBar } from "./bars/bar";
import { ClickableOptions } from "./clickables/clickable";
import { Decorator } from "./decorators";
export const ActionType = Symbol("Action");
@ -77,9 +78,11 @@ export type GenericAction = Replace<
>;
export function createAction<T extends ActionOptions>(
optionsFunc?: OptionsFunc<T, BaseAction, GenericAction>
optionsFunc?: OptionsFunc<T, BaseAction, GenericAction>,
...decorators: Decorator<T, BaseAction, GenericAction>[]
): Action<T> {
const progress = persistent<DecimalSource>(0);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => {
const action = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
action.id = getUniqueID("action-");
@ -89,8 +92,13 @@ export function createAction<T extends ActionOptions>(
// Required because of display changing types
const genericAction = action as unknown as GenericAction;
for (const decorator of decorators) {
decorator.preConstruct?.(action);
}
action.isHolding = ref(false);
action.progress = progress;
Object.assign(action, decoratedData);
processComputable(action as T, "visibility");
setDefault(action, "visibility", Visibility.Visible);
@ -202,6 +210,11 @@ export function createAction<T extends ActionOptions>(
}
};
for (const decorator of decorators) {
decorator.postConstruct?.(action);
}
const decoratedProps = decorators.reduce((current, next) => Object.assign(current, next.getGatheredProps?.(action)));
action[GatherProps] = function (this: GenericAction) {
const {
display,
@ -225,7 +238,8 @@ export function createAction<T extends ActionOptions>(
canClick,
small,
mark,
id
id,
...decoratedProps
};
};

View file

@ -1,4 +1,5 @@
import BarComponent from "features/bars/Bar.vue";
import { Decorator } from "features/decorators";
import type {
CoercableComponent,
GenericComponent,
@ -71,14 +72,22 @@ export type GenericBar = Replace<
>;
export function createBar<T extends BarOptions>(
optionsFunc: OptionsFunc<T, BaseBar, GenericBar>
optionsFunc: OptionsFunc<T, BaseBar, GenericBar>,
...decorators: Decorator<T, BaseBar, GenericBar>[]
): Bar<T> {
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => {
const bar = optionsFunc();
bar.id = getUniqueID("bar-");
bar.type = BarType;
bar[Component] = BarComponent;
for (const decorator of decorators) {
decorator.preConstruct?.(bar);
}
Object.assign(bar, decoratedData);
processComputable(bar as T, "visibility");
setDefault(bar, "visibility", Visibility.Visible);
processComputable(bar as T, "width");
@ -94,6 +103,11 @@ export function createBar<T extends BarOptions>(
processComputable(bar as T, "display");
processComputable(bar as T, "mark");
for (const decorator of decorators) {
decorator.postConstruct?.(bar);
}
const decoratedProps = decorators.reduce((current, next) => Object.assign(current, next.getGatheredProps?.(bar)), {});
bar[GatherProps] = function (this: GenericBar) {
const {
progress,
@ -125,7 +139,8 @@ export function createBar<T extends BarOptions>(
baseStyle,
fillStyle,
mark,
id
id,
...decoratedProps
};
};

View file

@ -1,269 +0,0 @@
import ClickableComponent from "features/clickables/Clickable.vue";
import type {
CoercableComponent,
GenericComponent,
OptionsFunc,
Replace,
StyleValue
} from "features/feature";
import { Component, GatherProps, getUniqueID, jsx, setDefault, Visibility } from "features/feature";
import type { Resource } from "features/resources/resource";
import { DefaultValue, Persistent } from "game/persistence";
import { persistent } from "game/persistence";
import type { DecimalSource } from "util/bignum";
import Decimal, { format, formatWhole } from "util/bignum";
import type {
Computable,
GetComputableType,
GetComputableTypeWithDefault,
ProcessedComputable
} from "util/computed";
import { processComputable } from "util/computed";
import { createLazyProxy } from "util/proxies";
import { coerceComponent, isCoercableComponent } from "util/vue";
import type { Ref } from "vue";
import { computed, unref } from "vue";
import { Decorator } from "./decorators";
export const BuyableType = Symbol("Buyable");
export type BuyableDisplay =
| CoercableComponent
| {
title?: CoercableComponent;
description?: CoercableComponent;
effectDisplay?: CoercableComponent;
showAmount?: boolean;
};
export interface BuyableOptions {
visibility?: Computable<Visibility>;
cost?: Computable<DecimalSource>;
resource?: Resource;
canPurchase?: Computable<boolean>;
purchaseLimit?: Computable<DecimalSource>;
initialValue?: DecimalSource;
classes?: Computable<Record<string, boolean>>;
style?: Computable<StyleValue>;
mark?: Computable<boolean | string>;
small?: Computable<boolean>;
display?: Computable<BuyableDisplay>;
onPurchase?: (cost: DecimalSource | undefined) => void;
}
export interface BaseBuyable {
id: string;
amount: Persistent<DecimalSource>;
maxed: Ref<boolean>;
canAfford: Ref<boolean>;
canClick: ProcessedComputable<boolean>;
onClick: VoidFunction;
purchase: VoidFunction;
type: typeof BuyableType;
[Component]: typeof ClickableComponent;
[GatherProps]: () => Record<string, unknown>;
}
export type Buyable<T extends BuyableOptions> = Replace<
T & BaseBuyable,
{
visibility: GetComputableTypeWithDefault<T["visibility"], Visibility.Visible>;
cost: GetComputableType<T["cost"]>;
resource: GetComputableType<T["resource"]>;
canPurchase: GetComputableTypeWithDefault<T["canPurchase"], Ref<boolean>>;
purchaseLimit: GetComputableTypeWithDefault<T["purchaseLimit"], Decimal>;
classes: GetComputableType<T["classes"]>;
style: GetComputableType<T["style"]>;
mark: GetComputableType<T["mark"]>;
small: GetComputableType<T["small"]>;
display: Ref<CoercableComponent>;
}
>;
export type GenericBuyable = Replace<
Buyable<BuyableOptions>,
{
visibility: ProcessedComputable<Visibility>;
canPurchase: ProcessedComputable<boolean>;
purchaseLimit: ProcessedComputable<DecimalSource>;
}
>;
export function createBuyable<T extends BuyableOptions>(
optionsFunc: OptionsFunc<T, BaseBuyable, GenericBuyable>,
...decorators: Decorator<T, BaseBuyable, GenericBuyable>[]
): Buyable<T> {
const amount = persistent<DecimalSource>(0);
const persistents = decorators.reduce((current, next) => Object.assign(current, next.getPersistents?.()), {});
return createLazyProxy(() => {
const buyable = optionsFunc();
if (buyable.canPurchase == null && (buyable.resource == null || buyable.cost == null)) {
console.warn(
"Cannot create buyable without a canPurchase property or a resource and cost property",
buyable
);
throw "Cannot create buyable without a canPurchase property or a resource and cost property";
}
buyable.id = getUniqueID("buyable-");
buyable.type = BuyableType;
buyable[Component] = ClickableComponent;
for (const decorator of decorators) {
decorator.preConstruct?.(buyable);
}
buyable.amount = amount;
buyable.amount[DefaultValue] = buyable.initialValue ?? 0;
Object.assign(buyable, persistents);
buyable.canAfford = computed(() => {
const genericBuyable = buyable as GenericBuyable;
const cost = unref(genericBuyable.cost);
return (
genericBuyable.resource != null &&
cost != null &&
Decimal.gte(genericBuyable.resource.value, cost)
);
});
if (buyable.canPurchase == null) {
buyable.canPurchase = computed(
() =>
unref((buyable as GenericBuyable).visibility) === Visibility.Visible &&
unref((buyable as GenericBuyable).canAfford) &&
Decimal.lt(
(buyable as GenericBuyable).amount.value,
unref((buyable as GenericBuyable).purchaseLimit)
)
);
}
buyable.maxed = computed(() =>
Decimal.gte(
(buyable as GenericBuyable).amount.value,
unref((buyable as GenericBuyable).purchaseLimit)
)
);
processComputable(buyable as T, "classes");
const classes = buyable.classes as ProcessedComputable<Record<string, boolean>> | undefined;
buyable.classes = computed(() => {
const currClasses = unref(classes) || {};
if ((buyable as GenericBuyable).maxed.value) {
currClasses.bought = true;
}
return currClasses;
});
processComputable(buyable as T, "canPurchase");
buyable.canClick = buyable.canPurchase as ProcessedComputable<boolean>;
buyable.onClick = buyable.purchase =
buyable.onClick ??
buyable.purchase ??
function (this: GenericBuyable) {
const genericBuyable = buyable as GenericBuyable;
if (!unref(genericBuyable.canPurchase)) {
return;
}
const cost = unref(genericBuyable.cost);
if (genericBuyable.cost != null && genericBuyable.resource != null) {
genericBuyable.resource.value = Decimal.sub(
genericBuyable.resource.value,
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
cost!
);
genericBuyable.amount.value = Decimal.add(genericBuyable.amount.value, 1);
}
genericBuyable.onPurchase?.(cost);
};
processComputable(buyable as T, "display");
const display = buyable.display;
buyable.display = jsx(() => {
// TODO once processComputable types correctly, remove this "as X"
const currDisplay = unref(display) as BuyableDisplay;
if (isCoercableComponent(currDisplay)) {
const CurrDisplay = coerceComponent(currDisplay);
return <CurrDisplay />;
}
if (currDisplay != null && buyable.cost != null && buyable.resource != null) {
const genericBuyable = buyable as GenericBuyable;
const Title = coerceComponent(currDisplay.title ?? "", "h3");
const Description = coerceComponent(currDisplay.description ?? "");
const EffectDisplay = coerceComponent(currDisplay.effectDisplay ?? "");
return (
<span>
{currDisplay.title == null ? null : (
<div>
<Title />
</div>
)}
{currDisplay.description == null ? null : <Description />}
{currDisplay.showAmount === false ? null : (
<div>
<br />
{unref(genericBuyable.purchaseLimit) === Decimal.dInf ? (
<>Amount: {formatWhole(genericBuyable.amount.value)}</>
) : (
<>
Amount: {formatWhole(genericBuyable.amount.value)} /{" "}
{formatWhole(unref(genericBuyable.purchaseLimit))}
</>
)}
</div>
)}
{currDisplay.effectDisplay == null ? null : (
<div>
<br />
Currently: <EffectDisplay />
</div>
)}
{genericBuyable.cost != null && !genericBuyable.maxed.value ? (
<div>
<br />
Cost: {format(unref(genericBuyable.cost))}{" "}
{buyable.resource.displayName}
</div>
) : null}
</span>
);
}
return "";
});
processComputable(buyable as T, "visibility");
setDefault(buyable, "visibility", Visibility.Visible);
processComputable(buyable as T, "cost");
processComputable(buyable as T, "resource");
processComputable(buyable as T, "purchaseLimit");
setDefault(buyable, "purchaseLimit", Decimal.dInf);
processComputable(buyable as T, "style");
processComputable(buyable as T, "mark");
processComputable(buyable as T, "small");
const gatheredProps = decorators.reduce((current, next) => Object.assign(current, next.getGatheredProps?.(buyable)), {});
buyable[GatherProps] = function (this: GenericBuyable) {
const { display, visibility, style, classes, onClick, canClick, small, mark, id } =
this;
return {
display,
visibility,
style: unref(style),
classes,
onClick,
canClick,
small,
mark,
id,
...gatheredProps
};
};
for (const decorator of decorators) {
decorator.postConstruct?.(buyable);
}
return buyable as unknown as Buyable<T>;
});
}

View file

@ -1,6 +1,7 @@
import { isArray } from "@vue/shared";
import Toggle from "components/fields/Toggle.vue";
import ChallengeComponent from "features/challenges/Challenge.vue";
import { Decorator } from "features/decorators";
import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature";
import {
Component,
@ -98,10 +99,12 @@ export type GenericChallenge = Replace<
>;
export function createChallenge<T extends ChallengeOptions>(
optionsFunc: OptionsFunc<T, BaseChallenge, GenericChallenge>
optionsFunc: OptionsFunc<T, BaseChallenge, GenericChallenge>,
...decorators: Decorator<T, BaseChallenge, GenericChallenge>[]
): Challenge<T> {
const completions = persistent(0);
const active = persistent(false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => {
const challenge = optionsFunc();
@ -120,8 +123,14 @@ export function createChallenge<T extends ChallengeOptions>(
challenge.type = ChallengeType;
challenge[Component] = ChallengeComponent;
for (const decorator of decorators) {
decorator.preConstruct?.(challenge);
}
challenge.completions = completions;
challenge.active = active;
Object.assign(challenge, decoratedData);
challenge.completed = computed(() =>
Decimal.gt((challenge as GenericChallenge).completions.value, 0)
);
@ -234,6 +243,11 @@ export function createChallenge<T extends ChallengeOptions>(
});
}
for (const decorator of decorators) {
decorator.postConstruct?.(challenge);
}
const decoratedProps = decorators.reduce((current, next) => Object.assign(current, next.getGatheredProps?.(challenge)), {});
challenge[GatherProps] = function (this: GenericChallenge) {
const {
active,
@ -261,7 +275,8 @@ export function createChallenge<T extends ChallengeOptions>(
canStart,
mark,
id,
toggle
toggle,
...decoratedProps
};
};

View file

@ -1,4 +1,5 @@
import ClickableComponent from "features/clickables/Clickable.vue";
import { Decorator } from "features/decorators";
import type {
CoercableComponent,
GenericComponent,
@ -67,14 +68,22 @@ export type GenericClickable = Replace<
>;
export function createClickable<T extends ClickableOptions>(
optionsFunc?: OptionsFunc<T, BaseClickable, GenericClickable>
optionsFunc?: OptionsFunc<T, BaseClickable, GenericClickable>,
...decorators: Decorator<T, BaseClickable, GenericClickable>[]
): Clickable<T> {
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => {
const clickable = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
clickable.id = getUniqueID("clickable-");
clickable.type = ClickableType;
clickable[Component] = ClickableComponent;
for (const decorator of decorators) {
decorator.preConstruct?.(clickable);
}
Object.assign(clickable, decoratedData);
processComputable(clickable as T, "visibility");
setDefault(clickable, "visibility", Visibility.Visible);
processComputable(clickable as T, "canClick");
@ -101,6 +110,11 @@ export function createClickable<T extends ClickableOptions>(
};
}
for (const decorator of decorators) {
decorator.postConstruct?.(clickable);
}
const decoratedProps = decorators.reduce((current, next) => Object.assign(current, next.getGatheredProps?.(clickable)), {});
clickable[GatherProps] = function (this: GenericClickable) {
const {
display,
@ -124,7 +138,8 @@ export function createClickable<T extends ClickableOptions>(
canClick,
small,
mark,
id
id,
...decoratedProps
};
};

View file

@ -11,6 +11,7 @@ import { convertComputable, processComputable } from "util/computed";
import { createLazyProxy } from "util/proxies";
import type { Ref } from "vue";
import { computed, unref } from "vue";
import { Decorator } from "./decorators";
/** An object that configures a {@link Conversion}. */
export interface ConversionOptions {
@ -135,11 +136,16 @@ export type GenericConversion = Replace<
* @see {@link createIndependentConversion}.
*/
export function createConversion<T extends ConversionOptions>(
optionsFunc: OptionsFunc<T, BaseConversion, GenericConversion>
optionsFunc: OptionsFunc<T, BaseConversion, GenericConversion>,
...decorators: Decorator<T, BaseConversion, GenericConversion>[]
): Conversion<T> {
return createLazyProxy(() => {
const conversion = optionsFunc();
for (const decorator of decorators) {
decorator.preConstruct?.(conversion);
}
if (conversion.currentGain == null) {
conversion.currentGain = computed(() => {
let gain = conversion.gainModifier
@ -201,6 +207,10 @@ export function createConversion<T extends ConversionOptions>(
processComputable(conversion as T, "roundUpCost");
setDefault(conversion, "roundUpCost", true);
for (const decorator of decorators) {
decorator.postConstruct?.(conversion);
}
return conversion as unknown as Conversion<T>;
});
}

View file

@ -1,49 +1,35 @@
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
import { Replace, OptionsObject } from "./feature";
import Decimal, { DecimalSource } from "util/bignum";
import { Computable, GetComputableType, processComputable, ProcessedComputable } from "util/computed";
import { AchievementOptions, BaseAchievement, GenericAchievement } from "./achievements/achievement";
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
import { BarOptions, BaseBar, GenericBar } from "./bars/bar";
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
import { BaseBuyable, BuyableOptions, GenericBuyable } from "./buyable";
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
import { BaseChallenge, ChallengeOptions, GenericChallenge } from "./challenges/challenge";
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
import { BaseClickable, ClickableOptions, GenericClickable } from "./clickables/clickable";
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
import { BaseMilestone, GenericMilestone, MilestoneOptions } from "./milestones/milestone";
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
import { BaseUpgrade, GenericUpgrade, UpgradeOptions } from "./upgrades/upgrade";
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
import { Persistent, State } from "game/persistence";
import { computed, Ref, unref } from "vue";
type FeatureOptions = AchievementOptions | BarOptions | BuyableOptions | ChallengeOptions | ClickableOptions | MilestoneOptions | UpgradeOptions;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
type BaseFeature = BaseAchievement | BaseBar | BaseBuyable | BaseChallenge | BaseClickable | BaseMilestone | BaseUpgrade;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
type GenericFeature = GenericAchievement | GenericBar | GenericBuyable | GenericChallenge | GenericClickable | GenericMilestone | GenericUpgrade;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
/*----====----*/
export type Decorator<Options extends FeatureOptions, Base extends BaseFeature, Generic extends GenericFeature, S extends State = State> = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
getPersistents?(): Record<string, Persistent<S>>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
preConstruct?(feature: OptionsObject<Options,Base,Generic>): void;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
postConstruct?(feature: OptionsObject<Options,Base,Generic>): void;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
getGatheredProps?(feature: OptionsObject<Options,Base,Generic>): Partial<OptionsObject<Options,Base,Generic>>
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export type Decorator<FeatureOptions, BaseFeature = {}, GenericFeature = {}, S extends State = State> = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
getPersistentData?(): Record<string, Persistent<S>>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
preConstruct?(feature: OptionsObject<FeatureOptions,BaseFeature,GenericFeature>): void;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
postConstruct?(feature: OptionsObject<FeatureOptions,BaseFeature,GenericFeature>): void;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
getGatheredProps?(feature: OptionsObject<FeatureOptions,BaseFeature,GenericFeature>): Partial<OptionsObject<FeatureOptions,BaseFeature,GenericFeature>>
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
/*----====----*/
// #region Effect Decorator
export type EffectFeatureOptions = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export interface EffectFeatureOptions {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
effect: Computable<any>;
}
export type EffectFeature<T extends EffectFeatureOptions, U extends BaseFeature> = Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
T & U,
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
{ effect: GetComputableType<T["effect"]>; }
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export type EffectFeature<T extends EffectFeatureOptions> = Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
T, { effect: GetComputableType<T["effect"]>; }
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
>;
export type GenericEffectFeature<T extends GenericFeature> = T & Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
EffectFeature<EffectFeatureOptions, BaseFeature>,
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export type GenericEffectFeature = Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
EffectFeature<EffectFeatureOptions>,
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
{ effect: ProcessedComputable<any>; }
>;
export const effectDecorator: Decorator<FeatureOptions & EffectFeatureOptions, BaseFeature, GenericFeature & BaseFeature> = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export const effectDecorator: Decorator<EffectFeatureOptions, {}, GenericEffectFeature> = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
postConstruct(feature) {
processComputable(feature, "effect");
}
@ -52,31 +38,46 @@ export const effectDecorator: Decorator<FeatureOptions & EffectFeatureOptions, B
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
/*----====----*/
// #region Bonus Amount Decorator
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export interface BonusFeatureOptions {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
// #region Bonus Amount/Completions Decorator
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export interface BonusAmountFeatureOptions {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
bonusAmount: Computable<DecimalSource>;
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export type BaseBonusFeature = BaseFeature & {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
totalAmount: Ref<DecimalSource>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export interface BonusCompletionsFeatureOptions {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
bonusCompletions: Computable<DecimalSource>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
export type BonusAmountFeature<T extends BonusFeatureOptions, U extends BaseBonusFeature> = Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
T & U,
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
{
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
bonusAmount: GetComputableType<T["bonusAmount"]>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export interface BaseBonusAmountFeature {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
amount: Ref<DecimalSource>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
totalAmount: Ref<DecimalSource>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export interface BaseBonusCompletionsFeature {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
completions: Ref<DecimalSource>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
totalCompletions: Ref<DecimalSource>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export type BonusAmountFeature<T extends BonusAmountFeatureOptions> = Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
T, { bonusAmount: GetComputableType<T["bonusAmount"]>; }
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export type BonusCompletionsFeature<T extends BonusCompletionsFeatureOptions> = Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
T, { bonusAmount: GetComputableType<T["bonusCompletions"]>; }
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
>;
export type GenericBonusFeature<T extends GenericFeature> = Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
T & BonusAmountFeature<BonusFeatureOptions, BaseBonusFeature>,
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export type GenericBonusAmountFeature = Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
BonusAmountFeature<BonusAmountFeatureOptions>,
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
{
bonusAmount: ProcessedComputable<DecimalSource>;
totalAmount: ProcessedComputable<DecimalSource>;
}
>;
export type GenericBonusCompletionsFeature = Replace<
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
BonusCompletionsFeature<BonusCompletionsFeatureOptions>,
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
{
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
bonusCompletions: ProcessedComputable<DecimalSource>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
totalCompletions: ProcessedComputable<DecimalSource>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
>;
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export const bonusAmountDecorator: Decorator<FeatureOptions & BonusFeatureOptions, BaseBonusFeature & {amount: ProcessedComputable<DecimalSource>}, GenericFeature & BaseBonusFeature & {amount: ProcessedComputable<DecimalSource>}> = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export const bonusAmountDecorator: Decorator<BonusAmountFeatureOptions, BaseBonusAmountFeature, GenericBonusAmountFeature> = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
postConstruct(feature) {
processComputable(feature, "bonusAmount");
if (feature.totalAmount === undefined) {
@ -87,30 +88,17 @@ export const bonusAmountDecorator: Decorator<FeatureOptions & BonusFeatureOption
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
}
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export const bonusCompletionsDecorator: Decorator<FeatureOptions & BonusFeatureOptions, BaseBonusFeature & {completions: ProcessedComputable<DecimalSource>}, GenericFeature & BaseBonusFeature & {completions: ProcessedComputable<DecimalSource>}> = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export const bonusCompletionsDecorator: Decorator<BonusAmountFeatureOptions, BaseBonusCompletionsFeature, GenericBonusCompletionsFeature> = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
postConstruct(feature) {
processComputable(feature, "bonusAmount");
if (feature.totalAmount === undefined) {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
feature.totalAmount = computed(() => Decimal.add(
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
if (feature.totalCompletions === undefined) {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
feature.totalCompletions = computed(() => Decimal.add(
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
unref(feature.completions ?? 0),
unref(feature.bonusAmount as ProcessedComputable<DecimalSource>)
));
}
}
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
export const bonusEarnedDecorator: Decorator<FeatureOptions & BonusFeatureOptions, BaseBonusFeature & {earned: ProcessedComputable<boolean>}, GenericFeature & BaseBonusFeature & {earned: ProcessedComputable<boolean>}> = {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
postConstruct(feature) {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
processComputable(feature, "bonusAmount");
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
if (feature.totalAmount === undefined) {
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
feature.totalAmount = computed(() => unref(feature.earned ?? false)
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
? Decimal.add(unref(feature.bonusAmount as ProcessedComputable<DecimalSource>), 1)
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
: unref(feature.bonusAmount as ProcessedComputable<DecimalSource>)
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
);
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
}
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
// #endregion
/*----====----*/

thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).
thepaperpilot commented 2023-02-26 16:40:13 +00:00 (Migrated from github.com)
Review

I think the specific decorators probably belong in their own files, or in common.tsx if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

I think the specific decorators probably belong in their own files, or in `common.tsx` if they're particularly small and useful enough to be included as part of the "base" project (as effects would be, but maybe not the bonusAmounts/completions).

View file

@ -1,4 +1,5 @@
import Select from "components/fields/Select.vue";
import { Decorator } from "features/decorators";
import type {
CoercableComponent,
GenericComponent,
@ -92,16 +93,23 @@ export type GenericMilestone = Replace<
>;
export function createMilestone<T extends MilestoneOptions>(
optionsFunc?: OptionsFunc<T, BaseMilestone, GenericMilestone>
optionsFunc?: OptionsFunc<T, BaseMilestone, GenericMilestone>,
...decorators: Decorator<T, BaseMilestone, GenericMilestone>[]
): Milestone<T> {
const earned = persistent<boolean>(false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => {
const milestone = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
milestone.id = getUniqueID("milestone-");
milestone.type = MilestoneType;
milestone[Component] = MilestoneComponent;
for (const decorator of decorators) {
decorator.preConstruct?.(milestone);
}
milestone.earned = earned;
Object.assign(milestone, decoratedData);
milestone.complete = function () {
const genericMilestone = milestone as GenericMilestone;
earned.value = true;
@ -160,9 +168,14 @@ export function createMilestone<T extends MilestoneOptions>(
processComputable(milestone as T, "display");
processComputable(milestone as T, "showPopups");
for (const decorator of decorators) {
decorator.postConstruct?.(milestone);
}
const decoratedProps = decorators.reduce((current, next) => Object.assign(current, next?.getGatheredProps?.(milestone)), {});
milestone[GatherProps] = function (this: GenericMilestone) {
const { visibility, display, style, classes, earned, id } = this;
return { visibility, display, style: unref(style), classes, earned, id };
return { visibility, display, style: unref(style), classes, earned, id, ...decoratedProps };
};
if (milestone.shouldEarn) {

View file

@ -24,6 +24,7 @@ import { createLazyProxy } from "util/proxies";
import { coerceComponent, isCoercableComponent } from "util/vue";
import type { Ref } from "vue";
import { computed, unref } from "vue";
import { Decorator, GenericBonusAmountFeature } from "./decorators";
/** A symbol used to identify {@link Repeatable} features. */
export const RepeatableType = Symbol("Repeatable");
@ -118,9 +119,11 @@ export type GenericRepeatable = Replace<
* @param optionsFunc Repeatable options.
*/
export function createRepeatable<T extends RepeatableOptions>(
optionsFunc: OptionsFunc<T, BaseRepeatable, GenericRepeatable>
optionsFunc: OptionsFunc<T, BaseRepeatable, GenericRepeatable>,
...decorators: Decorator<T, BaseRepeatable, GenericRepeatable>[]
): Repeatable<T> {
const amount = persistent<DecimalSource>(0);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => {
const repeatable = optionsFunc();
@ -128,9 +131,15 @@ export function createRepeatable<T extends RepeatableOptions>(
repeatable.type = RepeatableType;
repeatable[Component] = ClickableComponent;
for (const decorator of decorators) {
decorator.preConstruct?.(repeatable);
}
repeatable.amount = amount;
repeatable.amount[DefaultValue] = repeatable.initialAmount ?? 0;
Object.assign(repeatable, decoratedData);
const limitRequirement = {
requirementMet: computed(() =>
Decimal.sub(
@ -212,14 +221,17 @@ export function createRepeatable<T extends RepeatableOptions>(
{currDisplay.showAmount === false ? null : (
<div>
<br />
{unref(genericRepeatable.limit) === Decimal.dInf ? (
<>Amount: {formatWhole(genericRepeatable.amount.value)}</>
) : (
<>
Amount: {formatWhole(genericRepeatable.amount.value)} /{" "}
{formatWhole(unref(genericRepeatable.limit))}
</>
)}
joinJSX(
<>Amount: {formatWhole(genericRepeatable.amount.value)}</>,
{unref(genericRepeatable.limit) !== Decimal.dInf ? (
<> / {formatWhole(unref(genericRepeatable.limit))}</>
) : undefined},
{(genericRepeatable as GenericRepeatable & GenericBonusAmountFeature).bonusAmount == null ? null : (
Decimal.gt(unref((genericRepeatable as GenericRepeatable & GenericBonusAmountFeature).bonusAmount), 0) ? (
<> + {formatWhole(unref((genericRepeatable as GenericRepeatable & GenericBonusAmountFeature).bonusAmount))}</>
) : undefined)
}
)
</div>
)}
{currDisplay.effectDisplay == null ? null : (
@ -254,6 +266,11 @@ export function createRepeatable<T extends RepeatableOptions>(
processComputable(repeatable as T, "small");
processComputable(repeatable as T, "maximize");
for (const decorator of decorators) {
decorator.postConstruct?.(repeatable);
}
const decoratedProps = decorators.reduce((current, next) => Object.assign(current, next.getGatheredProps?.(repeatable)), {});
repeatable[GatherProps] = function (this: GenericRepeatable) {
const { display, visibility, style, classes, onClick, canClick, small, mark, id } =
this;
@ -266,7 +283,8 @@ export function createRepeatable<T extends RepeatableOptions>(
canClick,
small,
mark,
id
id,
...decoratedProps
};
};

View file

@ -1,3 +1,4 @@
import { Decorator } from "features/decorators";
import type { CoercableComponent, OptionsFunc, Replace, StyleValue } from "features/feature";
import { Component, GatherProps, getUniqueID, setDefault, Visibility } from "features/feature";
import type { Link } from "features/links/links";
@ -66,14 +67,22 @@ export type GenericTreeNode = Replace<
>;
export function createTreeNode<T extends TreeNodeOptions>(
optionsFunc?: OptionsFunc<T, BaseTreeNode, GenericTreeNode>
optionsFunc?: OptionsFunc<T, BaseTreeNode, GenericTreeNode>,
...decorators: Decorator<T, BaseTreeNode, GenericTreeNode>[]
): TreeNode<T> {
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => {
const treeNode = optionsFunc?.() ?? ({} as ReturnType<NonNullable<typeof optionsFunc>>);
treeNode.id = getUniqueID("treeNode-");
treeNode.type = TreeNodeType;
treeNode[Component] = TreeNodeComponent;
for (const decorator of decorators) {
decorator.preConstruct?.(treeNode);
}
Object.assign(decoratedData);
processComputable(treeNode as T, "visibility");
setDefault(treeNode, "visibility", Visibility.Visible);
processComputable(treeNode as T, "canClick");
@ -85,6 +94,10 @@ export function createTreeNode<T extends TreeNodeOptions>(
processComputable(treeNode as T, "style");
processComputable(treeNode as T, "mark");
for (const decorator of decorators) {
decorator.postConstruct?.(treeNode);
}
if (treeNode.onClick) {
const onClick = treeNode.onClick.bind(treeNode);
treeNode.onClick = function (e) {
@ -102,6 +115,7 @@ export function createTreeNode<T extends TreeNodeOptions>(
};
}
const decoratedProps = decorators.reduce((current, next) => Object.assign(current, next.getGatheredProps?.(treeNode)), {});
treeNode[GatherProps] = function (this: GenericTreeNode) {
const {
display,
@ -127,7 +141,8 @@ export function createTreeNode<T extends TreeNodeOptions>(
glowColor,
canClick,
mark,
id
id,
...decoratedProps
};
};

View file

@ -1,4 +1,5 @@
import { isArray } from "@vue/shared";
import { Decorator } from "features/decorators";
import type {
CoercableComponent,
GenericComponent,
@ -85,16 +86,24 @@ export type GenericUpgrade = Replace<
>;
export function createUpgrade<T extends UpgradeOptions>(
optionsFunc: OptionsFunc<T, BaseUpgrade, GenericUpgrade>
optionsFunc: OptionsFunc<T, BaseUpgrade, GenericUpgrade>,
...decorators: Decorator<T, BaseUpgrade, GenericUpgrade>[]
): Upgrade<T> {
const bought = persistent<boolean>(false);
const decoratedData = decorators.reduce((current, next) => Object.assign(current, next.getPersistentData?.()), {});
return createLazyProxy(() => {
const upgrade = optionsFunc();
upgrade.id = getUniqueID("upgrade-");
upgrade.type = UpgradeType;
upgrade[Component] = UpgradeComponent;
for (const decorator of decorators) {
decorator.preConstruct?.(upgrade);
}
upgrade.bought = bought;
Object.assign(upgrade, decoratedData);
upgrade.canPurchase = computed(() => requirementsMet(upgrade.requirements));
upgrade.purchase = function () {
const genericUpgrade = upgrade as GenericUpgrade;
@ -120,6 +129,11 @@ export function createUpgrade<T extends UpgradeOptions>(
processComputable(upgrade as T, "display");
processComputable(upgrade as T, "mark");
for (const decorator of decorators) {
decorator.preConstruct?.(upgrade);
}
const decoratedProps = decorators.reduce((current, next) => Object.assign(current, next.getGatheredProps?.(upgrade)), {});
upgrade[GatherProps] = function (this: GenericUpgrade) {
const {
display,
@ -143,7 +157,8 @@ export function createUpgrade<T extends UpgradeOptions>(
bought,
mark,
id,
purchase
purchase,
...decoratedProps
};
};