Skip to content

Commit 65a2edf

Browse files
xrendanclaude
andcommitted
Fix MobX decorator incompatibility: switch from legacy to TC39 stage 3 decorators
The esbuild config in build.ts was emitting legacy TypeScript decorators (__decorateClass), but MobX 6.15 expects TC39 stage 3 decorators, causing "context.addInitializer is not a function" at runtime. - Set experimentalDecorators: false in build.ts esbuild config - Fix 11 source files that mixed @decorator syntax with makeObservable annotation args (not allowed with TC39 decorators) - Use @observable accessor for non-serializable classes - Use all-annotations approach for AxisConfig/ChartDimension to preserve Object.keys() serialization compatibility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent c8546a9 commit 65a2edf

File tree

12 files changed

+45
-62
lines changed

12 files changed

+45
-62
lines changed

packages/charts/build.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,10 @@ const transpileFile = async (srcPath: string, destPath: string) => {
4141
target: "esnext",
4242
sourcemap: "external",
4343
sourcefile: srcPath,
44-
// Use legacy decorators mode for compatibility with mobx-react
4544
tsconfigRaw: {
4645
compilerOptions: {
47-
experimentalDecorators: true,
48-
emitDecoratorMetadata: false,
49-
useDefineForClassFields: false,
46+
experimentalDecorators: false,
47+
useDefineForClassFields: true,
5048
},
5149
},
5250
})

packages/charts/src/explorer/ExplorerDecisionMatrix.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,9 @@ const makeCheckBoxOption = (
9191
// allow the user to navigate amongst charts.
9292
export class DecisionMatrix {
9393
table: CoreTable
94-
currentParams: ExplorerChoiceParams = {}
94+
@observable accessor currentParams: ExplorerChoiceParams = {}
9595
constructor(delimited: string, hash = "") {
96-
makeObservable(this, {
97-
currentParams: observable,
98-
selectedRow: observable,
99-
})
96+
makeObservable(this)
10097
this.choiceNameToControlTypeMap = makeChoicesMap(delimited)
10198
this.table = new CoreTable(parseDelimited(dropColumnTypes(delimited)), [
10299
// todo: remove col def?
@@ -413,7 +410,7 @@ export class DecisionMatrix {
413410
: this.table.indexOf(this.firstMatch)
414411
}
415412

416-
selectedRow: any = {}
413+
@observable accessor selectedRow: any = {}
417414

418415
private toControlOption(
419416
choiceName: ChoiceName,

packages/charts/src/grapher/axis/AxisConfig.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,12 @@ export class AxisConfig
9393
{
9494
constructor(props?: AxisConfigInterface, axisManager?: AxisManager) {
9595
super()
96-
makeObservable(this)
96+
makeObservable<AxisConfig, "constrainedMin" | "constrainedMax">(this, {
97+
fontSize: computed,
98+
constrainedMin: computed,
99+
constrainedMax: computed,
100+
domain: computed,
101+
})
97102
this.updateFromObject(props)
98103
this.axisManager = axisManager
99104
}
@@ -138,12 +143,12 @@ export class AxisConfig
138143
return obj
139144
}
140145

141-
@computed get fontSize(): number {
146+
get fontSize(): number {
142147
return this.axisManager?.fontSize || BASE_FONT_SIZE
143148
}
144149

145150
// A log scale domain cannot have values <= 0, so we double check here
146-
@computed private get constrainedMin(): number {
151+
private get constrainedMin(): number {
147152
if (this.scaleType === ScaleType.log && (this.min ?? 0) <= 0)
148153
return Infinity
149154
return this.min ?? Infinity
@@ -157,13 +162,13 @@ export class AxisConfig
157162
return false
158163
}
159164

160-
@computed private get constrainedMax(): number {
165+
private get constrainedMax(): number {
161166
if (this.scaleType === ScaleType.log && (this.max || 0) <= 0)
162167
return -Infinity
163168
return this.max ?? -Infinity
164169
}
165170

166-
@computed get domain(): [number, number] {
171+
get domain(): [number, number] {
167172
return [this.constrainedMin, this.constrainedMax]
168173
}
169174

packages/charts/src/grapher/chart/ChartDimension.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,18 @@ export class ChartDimension
6565
) {
6666
super()
6767

68-
makeObservable(this, {
68+
makeObservable<ChartDimension, "table">(this, {
6969
_slug: observable,
70+
table: computed,
71+
slug: computed,
72+
column: computed,
73+
columnSlug: computed,
7074
})
7175
this.manager = manager
7276
if (obj) this.updateFromObject(obj)
7377
}
7478

75-
@computed private get table(): ChartsTable {
79+
private get table(): ChartsTable {
7680
return this.manager.table
7781
}
7882

@@ -102,7 +106,7 @@ export class ChartDimension
102106
// Do not persist yet, until we migrate off VariableIds
103107
_slug: ColumnSlug | undefined = undefined
104108

105-
@computed get slug(): ColumnSlug {
109+
get slug(): ColumnSlug {
106110
if (this._slug) return this._slug
107111
return getDimensionColumnSlug(this.variableId, this.targetYear)
108112
}
@@ -111,11 +115,11 @@ export class ChartDimension
111115
this._slug = value
112116
}
113117

114-
@computed get column(): CoreColumn {
118+
get column(): CoreColumn {
115119
return this.table.get(this.columnSlug)
116120
}
117121

118-
@computed get columnSlug(): string {
122+
get columnSlug(): string {
119123
return this.slug ?? this.variableId.toString()
120124
}
121125
}

packages/charts/src/grapher/footer/Footer.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,7 @@ abstract class AbstractFooter<
8383
constructor(props: Props) {
8484
super(props)
8585

86-
makeObservable(this, {
87-
tooltipTarget: observable.ref,
88-
})
86+
makeObservable(this)
8987
}
9088

9189
@computed protected get manager(): FooterManager {
@@ -318,7 +316,7 @@ abstract class AbstractFooter<
318316
}
319317

320318
base = React.createRef<HTMLDivElement>()
321-
tooltipTarget: { x: number; y: number } | undefined = undefined
319+
@observable.ref accessor tooltipTarget: { x: number; y: number } | undefined = undefined
322320

323321
@action.bound private onMouseMove(e: MouseEvent): void {
324322
const cc = this.base.current?.querySelector(".cclogo")

packages/charts/src/grapher/mapCharts/MapChart.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,20 +90,17 @@ export class MapChart
9090
constructor(props: MapChartProps) {
9191
super(props)
9292

93-
makeObservable(this, {
94-
hoverBracket: observable,
95-
tooltipState: observable,
96-
})
93+
makeObservable(this)
9794
}
9895

9996
/**
10097
* The currently hovered map bracket.
10198
*
10299
* Hovering a map bracket highlights all countries within that bracket on the map.
103100
*/
104-
hoverBracket: MapBracket | undefined = undefined
101+
@observable accessor hoverBracket: MapBracket | undefined = undefined
105102

106-
tooltipState = new TooltipState<{
103+
@observable accessor tooltipState = new TooltipState<{
107104
featureId: string
108105
}>()
109106

packages/charts/src/grapher/selection/SelectionArray.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,11 @@ import { action, computed, observable, makeObservable } from "mobx"
33

44
export class SelectionArray {
55
constructor(selectedEntityNames: EntityName[] = []) {
6-
makeObservable(this, {
7-
selectedEntityNames: observable,
8-
})
6+
makeObservable(this)
97
this.selectedEntityNames = selectedEntityNames.slice()
108
}
119

12-
selectedEntityNames: EntityName[]
10+
@observable accessor selectedEntityNames: EntityName[] = []
1311

1412
@computed get hasSelection(): boolean {
1513
return this.selectedEntityNames.length > 0

packages/charts/src/grapher/slideInDrawer/SlideInDrawer.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,13 @@ interface SlideInDrawerProps {
1717

1818
@observer
1919
export class SlideInDrawer extends React.Component<SlideInDrawerProps> {
20-
visible: boolean = this.props.active // true while the drawer is active and during enter/exit transitions
20+
@observable.ref accessor visible: boolean = this.props.active // true while the drawer is active and during enter/exit transitions
2121
drawerRef = React.createRef<HTMLDivElement>()
2222

2323
constructor(props: SlideInDrawerProps) {
2424
super(props)
2525

26-
makeObservable(this, {
27-
visible: observable.ref,
28-
})
26+
makeObservable(this)
2927
}
3028

3129
override componentDidMount(): void {

packages/charts/src/grapher/stackedCharts/MarimekkoChart.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,19 +87,16 @@ export class MarimekkoChart
8787
constructor(props: MarimekkoChartProps) {
8888
super(props)
8989

90-
makeObservable(this, {
91-
focusColorBin: observable,
92-
tooltipState: observable,
93-
})
90+
makeObservable(this)
9491
}
9592

9693
labelAngleInDegrees = -45 // 0 is horizontal, -90 is vertical from bottom to top, ...
9794

9895
// currently hovered legend color
99-
focusColorBin: ColorScaleBin | undefined = undefined
96+
@observable accessor focusColorBin: ColorScaleBin | undefined = undefined
10097

10198
// current tooltip target & position
102-
tooltipState = new TooltipState<{
99+
@observable accessor tooltipState = new TooltipState<{
103100
entityName: string
104101
}>()
105102

packages/charts/src/grapher/stackedCharts/StackedBarChart.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -77,19 +77,15 @@ export class StackedBarChart
7777
constructor(props: StackedBarChartProps) {
7878
super(props)
7979

80-
makeObservable(this, {
81-
hoverColor: observable,
82-
hoveredTick: observable,
83-
tooltipState: observable,
84-
})
80+
makeObservable(this)
8581
}
8682

8783
// currently hovered legend color
88-
hoverColor: string | undefined = undefined
84+
@observable accessor hoverColor: string | undefined = undefined
8985
// currently hovered axis label
90-
hoveredTick: TickmarkPlacement | undefined = undefined
86+
@observable accessor hoveredTick: TickmarkPlacement | undefined = undefined
9187
// current hovered individual bar
92-
tooltipState = new TooltipState<{
88+
@observable accessor tooltipState = new TooltipState<{
9389
bar: StackedPoint<number>
9490
series: StackedSeries<number>
9591
}>()

0 commit comments

Comments
 (0)