@mui/x-codemod 9.0.0-alpha.4 → 9.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +262 -2
- package/README.md +177 -1
- package/package.json +3 -3
- package/util/renameClasses.js +7 -0
- package/v9.0.0/pickers/preset-safe/index.js +17 -2
- package/v9.0.0/pickers/remove-disable-margin/index.js +134 -0
- package/v9.0.0/pickers/remove-enable-accessible-field-dom-structure/index.js +72 -0
- package/v9.0.0/pickers/remove-picker-day-2/index.js +155 -0
- package/v9.0.0/pickers/rename-picker-classes/index.js +126 -0
- package/v9.0.0/pickers/rename-picker-day-2/index.js +105 -0
- package/v9.0.0/pickers/rename-pickers-day/index.js +90 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,265 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 9.0.0-rc.0
|
|
4
|
+
|
|
5
|
+
<!-- generated comparing v9.0.0-beta.0..master -->
|
|
6
|
+
|
|
7
|
+
_Apr 7, 2026_
|
|
8
|
+
|
|
9
|
+
We'd like to extend a big thank you to the 18 contributors who made this release possible.
|
|
10
|
+
|
|
11
|
+
Special thanks go out to these community members for their valuable contributions:
|
|
12
|
+
@mixelburg, @sibananda485, @youjin-hong
|
|
13
|
+
|
|
14
|
+
The following team members contributed to this release:
|
|
15
|
+
@aemartos, @alexfauquette, @arminmeh, @brijeshb42, @flaviendelangle, @JCQuintas, @LukasTy, @mapache-salvaje, @MBilalShafi, @michelengelen, @noraleonte, @rita-codes, @romgrk, @siriwatknp, @ZeeshanTamboli
|
|
16
|
+
|
|
17
|
+
### Data Grid
|
|
18
|
+
|
|
19
|
+
#### `@mui/x-data-grid@9.0.0-rc.0`
|
|
20
|
+
|
|
21
|
+
- [DataGrid] Rename filter panel `Columns` label to singular `Column` (#21935) @youjin-hong
|
|
22
|
+
- [DataGrid] Export `GridColumnUnsortedIconProps` for custom column icon slots (#21658) @mixelburg
|
|
23
|
+
- [DataGrid] Remove `x-virtualizer`'s `virtualScroller` from public API (#21936) @romgrk
|
|
24
|
+
- [DataGrid][virtualizer] Scrolling without render gaps (#21616) @romgrk
|
|
25
|
+
|
|
26
|
+
#### `@mui/x-data-grid-pro@9.0.0-rc.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
27
|
+
|
|
28
|
+
Same changes as in `@mui/x-data-grid@9.0.0-rc.0`, plus:
|
|
29
|
+
|
|
30
|
+
- [DataGridPro] Improve trigger for nested row reordering (#21642) @MBilalShafi
|
|
31
|
+
- [DataGridPro] Undeprecate `onRowsScrollEnd` prop (#21912) @MBilalShafi
|
|
32
|
+
|
|
33
|
+
#### `@mui/x-data-grid-premium@9.0.0-rc.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
34
|
+
|
|
35
|
+
Same changes as in `@mui/x-data-grid-pro@9.0.0-rc.0`, plus:
|
|
36
|
+
|
|
37
|
+
- [DataGridPremium] Fix clipboard paste issue in portal (#21931) @sibananda485
|
|
38
|
+
|
|
39
|
+
### Date and Time Pickers
|
|
40
|
+
|
|
41
|
+
#### Breaking changes
|
|
42
|
+
|
|
43
|
+
- Accessible DOM structure is now the only default. [Read more](https://next.mui.com/x/migration/migration-pickers-v8/#accessible-dom-structure-is-now-the-default)
|
|
44
|
+
- The `PickerDay2` and `DateRangePickerDay2` components were propagated to stable while removing the previous defaults. [Read more](https://next.mui.com/x/migration/migration-pickers-v8/#day-slot)
|
|
45
|
+
|
|
46
|
+
#### `@mui/x-date-pickers@9.0.0-rc.0`
|
|
47
|
+
|
|
48
|
+
- [pickers] Remove `PickersDay` and `DateRangePickerDay` and promote their `2` versions as replacements (#21739) @michelengelen
|
|
49
|
+
|
|
50
|
+
#### `@mui/x-date-pickers-pro@9.0.0-rc.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
51
|
+
|
|
52
|
+
Same changes as in `@mui/x-date-pickers@9.0.0-rc.0`.
|
|
53
|
+
|
|
54
|
+
### Charts
|
|
55
|
+
|
|
56
|
+
#### `@mui/x-charts@9.0.0-rc.0.0`
|
|
57
|
+
|
|
58
|
+
- [charts] Make line visibility toggle start from the baseline (#21893) @alexfauquette
|
|
59
|
+
- [charts] Remove the container overflow (#21955) @alexfauquette
|
|
60
|
+
- [charts] Revert `theme.alpha` for non-channel token (#21965) @siriwatknp
|
|
61
|
+
|
|
62
|
+
#### `@mui/x-charts-pro@9.0.0-rc.0.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
63
|
+
|
|
64
|
+
Same changes as in `@mui/x-charts@9.0.0-rc.0.0`, plus:
|
|
65
|
+
|
|
66
|
+
- [charts-pro] Zoom slider touch improvements (#21832) @JCQuintas
|
|
67
|
+
- [charts-pro] Add `seriesIds` filter to zoom slider preview (#21933) @JCQuintas
|
|
68
|
+
- [charts-pro] Fix zoom slider preview with discard filter mode (#21883) @JCQuintas
|
|
69
|
+
|
|
70
|
+
#### `@mui/x-charts-premium@9.0.0-rc.0.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
71
|
+
|
|
72
|
+
Same changes as in `@mui/x-charts-pro@9.0.0-rc.0.0`, plus:
|
|
73
|
+
|
|
74
|
+
- [charts-premium] Add series `valueFormatter` to candlestick chart (#21905) @JCQuintas
|
|
75
|
+
- [charts-premium] Add zoom slider preview support for candlestick charts (#21914) @JCQuintas
|
|
76
|
+
- [charts-premium] Allow color customization in `Candlestick` chart (#21838) @JCQuintas
|
|
77
|
+
- [charts-premium] Support hide/show for OHLC (candlestick) series (#21807) @Copilot
|
|
78
|
+
- [charts-premium] Add `dataset` support to `Candlestick` chart (#21872) @JCQuintas
|
|
79
|
+
- [charts-premium] Add candlestick page to sidebar navigation (#21834) @JCQuintas
|
|
80
|
+
|
|
81
|
+
### Tree View
|
|
82
|
+
|
|
83
|
+
#### `@mui/x-tree-view@9.0.0-rc.0`
|
|
84
|
+
|
|
85
|
+
Internal changes.
|
|
86
|
+
|
|
87
|
+
#### `@mui/x-tree-view-pro@9.0.0-rc.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
88
|
+
|
|
89
|
+
Same changes as in `@mui/x-tree-view@9.0.0-rc.0`, plus:
|
|
90
|
+
|
|
91
|
+
- [RichTreeViewPro] Allow to auto-expand lazy loaded items (#21759) @flaviendelangle
|
|
92
|
+
|
|
93
|
+
### Scheduler
|
|
94
|
+
|
|
95
|
+
#### `@mui/x-scheduler@9.0.0-alpha.0`
|
|
96
|
+
|
|
97
|
+
- [scheduler] Add locale files, adapt l10n scripts, and add localization table to docs (#21870) @rita-codes
|
|
98
|
+
- [scheduler] Add planned features to the docs (#21705) @rita-codes
|
|
99
|
+
- [scheduler] Add scheduler to docs introduction (#21845) @rita-codes
|
|
100
|
+
- [scheduler] Add wide docs to scheduler (#21860) @noraleonte
|
|
101
|
+
- [scheduler] All day event bugfixes (#21884) @noraleonte
|
|
102
|
+
- [scheduler] Autofocus title field (#21947) @noraleonte
|
|
103
|
+
- [scheduler] Change default event creation trigger to single click (#21979) @rita-codes
|
|
104
|
+
- [scheduler] Change order of the views on the view selector (#21904) @rita-codes
|
|
105
|
+
- [scheduler] Disabled border color for the repeat day picker in dark mode (#21987) @rita-codes
|
|
106
|
+
- [scheduler] Drop unused dependency (#21956) @flaviendelangle
|
|
107
|
+
- [scheduler] Fix all-day event shifting to previous day in negative UTC offsets (#21994) @rita-codes
|
|
108
|
+
- [scheduler] Fix dark theme localization demos (#21992) @noraleonte
|
|
109
|
+
- [scheduler] Fix licensing confusion in docs (#21939) @rita-codes
|
|
110
|
+
- [scheduler] Fix preferences menu width shift when toggling options + Improve preferences menu accessibility (#21902) @rita-codes
|
|
111
|
+
- [scheduler] Prepare for the alpha launch (#21859) @rita-codes
|
|
112
|
+
- [scheduler] Sync Base UI internals and apply good practices (#21946) @flaviendelangle
|
|
113
|
+
- [scheduler] Update close modal aria label translation (#21940) @rita-codes
|
|
114
|
+
- [scheduler] Add Spanish (es-ES) locale (#21900) @rita-codes
|
|
115
|
+
- [scheduler] Improve French (fr-FR) locale (#21941) @rita-codes
|
|
116
|
+
- [scheduler] Improve Romanian (ro-RO) locale (#21942) @rita-codes
|
|
117
|
+
|
|
118
|
+
#### `@mui/x-scheduler-premium@9.0.0-alpha.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
119
|
+
|
|
120
|
+
Same changes as in `@mui/x-scheduler@9.0.0-alpha.0`.
|
|
121
|
+
|
|
122
|
+
### Codemod
|
|
123
|
+
|
|
124
|
+
#### `@mui/x-codemod@9.0.0-rc.0`
|
|
125
|
+
|
|
126
|
+
Internal changes.
|
|
127
|
+
|
|
128
|
+
### Docs
|
|
129
|
+
|
|
130
|
+
- [docs] Fix JSDOM → jsdom casing (#21907) @JCQuintas
|
|
131
|
+
- [docs] Remove Joy UI references and dependency (#21937) @siriwatknp
|
|
132
|
+
- [docs] Remove none generated files (#21886) @alexfauquette
|
|
133
|
+
- [docs] Remove unused interactive demo code (#21945) @LukasTy
|
|
134
|
+
- [docs] Revise the Funnel doc (#21677) @mapache-salvaje
|
|
135
|
+
- [docs] Revise the Line chart docs (#21554) @mapache-salvaje
|
|
136
|
+
- [docs] Revise the Radar doc (#21674) @mapache-salvaje
|
|
137
|
+
- [docs] Revise the Sankey doc (#21678) @mapache-salvaje
|
|
138
|
+
- [docs] Revise the Scatter chart docs (#21564) @mapache-salvaje
|
|
139
|
+
|
|
140
|
+
### Core
|
|
141
|
+
|
|
142
|
+
- [docs-infra] Update to the latest monorepo (#21971) @brijeshb42
|
|
143
|
+
- [internal] Remove checks for `materialVersion >= 6` (#21975) @LukasTy
|
|
144
|
+
|
|
145
|
+
### Miscellaneous
|
|
146
|
+
|
|
147
|
+
- [core] Bump @mui/material to v9.0.0-beta.1 (#21858) @siriwatknp
|
|
148
|
+
- [core] Update browserslistrc (#21974) @siriwatknp
|
|
149
|
+
- [deps] Bump minimum core packages to 7.3.0 to adopt theme color manipulator (#21892) @siriwatknp
|
|
150
|
+
- [telemetry] Prefer upstream remote over origin for `projectId` (#21882) @aemartos
|
|
151
|
+
- [telemetry] Send `repoHash`, `[x]packageNameHash`, and `rootPathHash` alongside `projectId` (#21896) @aemartos
|
|
152
|
+
- [test] Exclude flaky `DataGrid` argos test (#21977) @MBilalShafi
|
|
153
|
+
- [test] Fix flaky `DataGrid` test (#22000) @arminmeh
|
|
154
|
+
- [test] Remove `componentsProp` test from `describeConformance` (#21897) @ZeeshanTamboli
|
|
155
|
+
- [x-license] Change `orderId` type from `number` to `string` (#21885) @aemartos
|
|
156
|
+
|
|
157
|
+
## 9.0.0-beta.0
|
|
158
|
+
|
|
159
|
+
<!-- generated comparing v9.0.0-alpha.4..master -->
|
|
160
|
+
|
|
161
|
+
_Mar 27, 2026_
|
|
162
|
+
|
|
163
|
+
We'd like to extend a big thank you to the 10 contributors who made this release possible. Here are some highlights ✨:
|
|
164
|
+
|
|
165
|
+
- 🔊 New Charts voiceover component for improved screen reader support
|
|
166
|
+
- ⌨️ Charts keyboard navigation improvements: axis tooltip now shows when navigating with the keyboard
|
|
167
|
+
- 📊 Charts axes now can be set to automatically resize to fit their content
|
|
168
|
+
- 📝 New `rowCheckbox` slot in Data Grid for easier checkbox column customization
|
|
169
|
+
- ⚡️ `fetchRows()` API in Data Grid Pro now defaults `start` and `end` based on scroll position with lazy loading
|
|
170
|
+
- 🐞 Bugfixes and internal improvements
|
|
171
|
+
|
|
172
|
+
The following team members contributed to this release:
|
|
173
|
+
@aemartos, @alexfauquette, @arminmeh, @cherniavskii, @Janpot, @JCQuintas, @mapache-salvaje, @michelengelen, @noraleonte, @rita-codes
|
|
174
|
+
|
|
175
|
+
### Data Grid
|
|
176
|
+
|
|
177
|
+
#### `@mui/x-data-grid@9.0.0-beta.0`
|
|
178
|
+
|
|
179
|
+
- [DataGrid] Add `rowCheckbox` slot for easier customization (#21797) @michelengelen
|
|
180
|
+
- [DataGrid] Prevent repeated `hasScrollbar` state updates (#21820) @arminmeh
|
|
181
|
+
|
|
182
|
+
#### `@mui/x-data-grid-pro@9.0.0-beta.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
183
|
+
|
|
184
|
+
Same changes as in `@mui/x-data-grid@9.0.0-beta.0`, plus:
|
|
185
|
+
|
|
186
|
+
- [DataGridPro] `fetchRows()` API's default `start` and `end` params based on scroll position with lazy loading (#21742) @arminmeh
|
|
187
|
+
|
|
188
|
+
#### `@mui/x-data-grid-premium@9.0.0-beta.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
189
|
+
|
|
190
|
+
Same changes as in `@mui/x-data-grid-pro@9.0.0-beta.0`.
|
|
191
|
+
|
|
192
|
+
### Date and Time Pickers
|
|
193
|
+
|
|
194
|
+
#### `@mui/x-date-pickers@9.0.0-beta.0`
|
|
195
|
+
|
|
196
|
+
Internal changes.
|
|
197
|
+
|
|
198
|
+
#### `@mui/x-date-pickers-pro@9.0.0-beta.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
199
|
+
|
|
200
|
+
Same changes as in `@mui/x-date-pickers@9.0.0-beta.0`.
|
|
201
|
+
|
|
202
|
+
### Charts
|
|
203
|
+
|
|
204
|
+
#### `@mui/x-charts@9.0.0-beta.0`
|
|
205
|
+
|
|
206
|
+
- [charts] Add `className` prop to Pro chart plot components (#21793) @JCQuintas
|
|
207
|
+
- [charts] Add experimental position-based pointer interaction for line series (#21809) @JCQuintas
|
|
208
|
+
- [charts] Add l10n to the bar accessibility (#21815) @alexfauquette
|
|
209
|
+
- [charts] Add localization for the basic charts (#21822) @alexfauquette
|
|
210
|
+
- [charts] Add voiceover component (#21344) @alexfauquette
|
|
211
|
+
- [charts] Allow axes to automatically resize to content (#21087) @JCQuintas
|
|
212
|
+
- [charts] Document multiple use-cases for references (#21768) @alexfauquette
|
|
213
|
+
- [charts] Remove compatibility layer for React vs native events (#21780) @JCQuintas
|
|
214
|
+
- [charts] Remove deprecated `barLabel` props (#21783) @alexfauquette
|
|
215
|
+
- [charts] Show axis tooltip when navigating with keyboard (#21689) @Copilot
|
|
216
|
+
|
|
217
|
+
#### `@mui/x-charts-pro@9.0.0-beta.0` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
218
|
+
|
|
219
|
+
Same changes as in `@mui/x-charts@9.0.0-beta.0`.
|
|
220
|
+
|
|
221
|
+
#### `@mui/x-charts-premium@9.0.0-beta.0` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
222
|
+
|
|
223
|
+
Same changes as in `@mui/x-charts-pro@9.0.0-beta.0`.
|
|
224
|
+
|
|
225
|
+
### Tree View
|
|
226
|
+
|
|
227
|
+
#### `@mui/x-tree-view@9.0.0-alpha.4`
|
|
228
|
+
|
|
229
|
+
Internal changes.
|
|
230
|
+
|
|
231
|
+
#### `@mui/x-tree-view-pro@9.0.0-alpha.4` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
232
|
+
|
|
233
|
+
Same changes as in `@mui/x-tree-view@9.0.0-alpha.4`.
|
|
234
|
+
|
|
235
|
+
### Codemod
|
|
236
|
+
|
|
237
|
+
#### `@mui/x-codemod@9.0.0-alpha.4`
|
|
238
|
+
|
|
239
|
+
Internal changes.
|
|
240
|
+
|
|
241
|
+
### Docs
|
|
242
|
+
|
|
243
|
+
- [docs] Document how to customize voiceover announcement (#21833) @alexfauquette
|
|
244
|
+
- [docs] Remove Discord mention from docs (#21855) @mapache-salvaje
|
|
245
|
+
- [docs] Remove stabilized experimental feature from demo (#21869) @JCQuintas
|
|
246
|
+
- [docs] Update telemetry guide to reflect pseudonymous data collection and license compliance (#21812) @aemartos
|
|
247
|
+
- [docs] Revise the Sparkline doc (#21614) @mapache-salvaje
|
|
248
|
+
- [docs] Revise the Gauge doc (#21673) @mapache-salvaje
|
|
249
|
+
- [docs] Revise the Heatmap doc (#21676) @mapache-salvaje
|
|
250
|
+
|
|
251
|
+
### Core
|
|
252
|
+
|
|
253
|
+
- [code-infra] Remove unused deps and unify es-toolkit via catalog (#21840) @Janpot
|
|
254
|
+
- [code-infra] Update @mui/internal-bundle-size-checker to canary.68 (#21836) @Janpot
|
|
255
|
+
- [code-infra] Update next (#21837) @Janpot
|
|
256
|
+
- [internal] Remove headless data grid packages (#21843) @cherniavskii
|
|
257
|
+
|
|
258
|
+
### Miscellaneous
|
|
259
|
+
|
|
260
|
+
- Add @romgrk to CODEOWNERS for `x-virtualizer` and `x-internals` (#21819) @Copilot
|
|
261
|
+
- [x-license] add 2022 plan version (#21814) @aemartos
|
|
262
|
+
|
|
3
263
|
## 9.0.0-alpha.4
|
|
4
264
|
|
|
5
265
|
_Mar 19, 2026_
|
|
@@ -59,7 +319,7 @@ Same changes as in `@mui/x-date-pickers@9.0.0-alpha.4`.
|
|
|
59
319
|
- [charts] Remove deprecated `useMouseTracker()` (#21787) @alexfauquette
|
|
60
320
|
- [charts] Remove deprecated classes (#21775) @alexfauquette
|
|
61
321
|
- [charts] Remove deprecated props from PieArcLabel animation (#21789) @alexfauquette
|
|
62
|
-
- [charts] Remove get
|
|
322
|
+
- [charts] Remove get\*UtilityClass from public exports (#21769) @JCQuintas
|
|
63
323
|
- [charts] Remove the deprecated `disableHover` property (#21785) @alexfauquette
|
|
64
324
|
- [charts] Remove the deprecated `message` prop (#21784) @alexfauquette
|
|
65
325
|
- [charts] Remove deprecated props about voronoi (#21796) @alexfauquette
|
|
@@ -207,7 +467,7 @@ Same changes as in `@mui/x-charts-pro@9.0.0-alpha.3`, plus:
|
|
|
207
467
|
- Remove deprecated CSS state classes from `treeItemClasses`: `expanded`, `selected`, `focused`, `disabled`, `editable`, `editing` (use `[data-expanded]`, `[data-selected]`, etc.)
|
|
208
468
|
- The `<RichTreeViewPro />` component has now virtualization enabled by default.
|
|
209
469
|
- The items used inside the `<RichTreeViewPro />` now have a default height of `32px`.
|
|
210
|
-
- The
|
|
470
|
+
- The items of the `<RichTreeViewPro />` are now rendered as a flat list instead of a nested tree.
|
|
211
471
|
|
|
212
472
|
#### `@mui/x-tree-view@9.0.0-alpha.3`
|
|
213
473
|
|
package/README.md
CHANGED
|
@@ -76,9 +76,9 @@ The corresponding sub-sections are listed below
|
|
|
76
76
|
|
|
77
77
|
<!-- - [`preset-safe-for-tree-view`](#preset-safe-for-tree-view-v900) -->
|
|
78
78
|
<!-- - [`preset-safe-for-data-grid`](#preset-safe-for-data-grid-v900) -->
|
|
79
|
-
<!-- - [`preset-safe-for-pickers`](#preset-safe-for-pickers-v900) -->
|
|
80
79
|
|
|
81
80
|
- [`preset-safe-for-charts`](#preset-safe-for-charts-v900)
|
|
81
|
+
- [`preset-safe-for-pickers`](#preset-safe-for-pickers-v900)
|
|
82
82
|
|
|
83
83
|
### Data Grid codemods
|
|
84
84
|
|
|
@@ -311,6 +311,182 @@ Replaces the deprecated `isBarSeries()` and `isDefaultizedBarSeries()` helper fu
|
|
|
311
311
|
}
|
|
312
312
|
```
|
|
313
313
|
|
|
314
|
+
### Pickers codemods
|
|
315
|
+
|
|
316
|
+
#### 🚀 `preset-safe` for Pickers v9.0.0 <a id="preset-safe-for-pickers-v900"></a>
|
|
317
|
+
|
|
318
|
+
The `preset-safe` codemods for Pickers.
|
|
319
|
+
|
|
320
|
+
<!-- #npm-tag-reference -->
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
npx @mui/x-codemod@next v9.0.0/pickers/preset-safe <path|folder>
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
The list includes these transformers
|
|
327
|
+
|
|
328
|
+
- [`rename-field-ref`](#rename-field-ref)
|
|
329
|
+
- [`remove-enable-accessible-field-dom-structure`](#remove-enable-accessible-field-dom-structure)
|
|
330
|
+
- [`remove-picker-day-2`](#remove-picker-day-2)
|
|
331
|
+
- [`rename-picker-day-2`](#rename-picker-day-2)
|
|
332
|
+
- [`rename-pickers-day`](#rename-pickers-day)
|
|
333
|
+
- [`rename-picker-classes`](#rename-picker-classes)
|
|
334
|
+
- [`remove-disable-margin`](#remove-disable-margin)
|
|
335
|
+
|
|
336
|
+
#### `rename-field-ref`
|
|
337
|
+
|
|
338
|
+
Renames the `unstableFieldRef` prop to `fieldRef` on all Picker and Field components.
|
|
339
|
+
|
|
340
|
+
```diff
|
|
341
|
+
-<DateField unstableFieldRef={fieldRef} />
|
|
342
|
+
+<DateField fieldRef={fieldRef} />
|
|
343
|
+
|
|
344
|
+
-<DateRangePicker unstableStartFieldRef={startRef} unstableEndFieldRef={endRef} />
|
|
345
|
+
+<DateRangePicker startFieldRef={startRef} endFieldRef={endRef} />
|
|
346
|
+
|
|
347
|
+
-<DatePicker slotProps={{ field: { unstableFieldRef: fieldRef } }} />
|
|
348
|
+
+<DatePicker slotProps={{ field: { fieldRef: fieldRef } }} />
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
<!-- #npm-tag-reference -->
|
|
352
|
+
|
|
353
|
+
```bash
|
|
354
|
+
npx @mui/x-codemod@next v9.0.0/pickers/rename-field-ref <path|folder>
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
#### `remove-enable-accessible-field-dom-structure`
|
|
358
|
+
|
|
359
|
+
Removes the `enableAccessibleFieldDOMStructure` prop from all Picker and Field components.
|
|
360
|
+
The accessible DOM structure is now the only supported option and this prop has no effect.
|
|
361
|
+
|
|
362
|
+
```diff
|
|
363
|
+
-<DateField enableAccessibleFieldDOMStructure={false} />
|
|
364
|
+
+<DateField />
|
|
365
|
+
|
|
366
|
+
-<DatePicker enableAccessibleFieldDOMStructure={false} slots={{ textField: MyCustomTextField }} />
|
|
367
|
+
+<DatePicker slots={{ textField: MyCustomTextField }} />
|
|
368
|
+
|
|
369
|
+
-<DatePicker slotProps={{ field: { enableAccessibleFieldDOMStructure: false } }} />
|
|
370
|
+
+<DatePicker />
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
<!-- #npm-tag-reference -->
|
|
374
|
+
|
|
375
|
+
```bash
|
|
376
|
+
npx @mui/x-codemod@next v9.0.0/pickers/remove-enable-accessible-field-dom-structure <path|folder>
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
#### `remove-picker-day-2`
|
|
380
|
+
|
|
381
|
+
Removes the unnecessary `slots={{ day: PickerDay2 }}` and `slots={{ day: DateRangePickerDay2 }}` usages, since `PickerDay2` and `DateRangePickerDay2` are the new defaults.
|
|
382
|
+
Also handles objects passed through variables (for example `const slots = { day: PickerDay2 }`).
|
|
383
|
+
|
|
384
|
+
```diff
|
|
385
|
+
-<DatePicker slots={{ day: PickerDay2 }} />
|
|
386
|
+
+<DatePicker />
|
|
387
|
+
|
|
388
|
+
-<DateRangePicker slots={{ day: DateRangePickerDay2 }} />
|
|
389
|
+
+<DateRangePicker />
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
<!-- #npm-tag-reference -->
|
|
393
|
+
|
|
394
|
+
```bash
|
|
395
|
+
npx @mui/x-codemod@next v9.0.0/pickers/remove-picker-day-2 <path>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### `rename-picker-day-2`
|
|
399
|
+
|
|
400
|
+
Renames `PickerDay2` and `DateRangePickerDay2` components and their related types, classes, and theme component names to `PickerDay` and `DateRangePickerDay`.
|
|
401
|
+
|
|
402
|
+
```diff
|
|
403
|
+
-import { PickerDay2, PickerDay2Props, pickerDay2Classes } from '@mui/x-date-pickers/PickerDay2';
|
|
404
|
+
+import { PickerDay, PickerDayProps, pickerDayClasses } from '@mui/x-date-pickers/PickerDay';
|
|
405
|
+
|
|
406
|
+
-import { DateRangePickerDay2 } from '@mui/x-date-pickers-pro/DateRangePickerDay2';
|
|
407
|
+
+import { DateRangePickerDay } from '@mui/x-date-pickers-pro/DateRangePickerDay';
|
|
408
|
+
|
|
409
|
+
const theme = createTheme({
|
|
410
|
+
components: {
|
|
411
|
+
- MuiPickerDay2: {
|
|
412
|
+
+ MuiPickerDay: {
|
|
413
|
+
styleOverrides: { root: { color: 'red' } },
|
|
414
|
+
},
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
<!-- #npm-tag-reference -->
|
|
420
|
+
|
|
421
|
+
```bash
|
|
422
|
+
npx @mui/x-codemod@next v9.0.0/pickers/rename-picker-day-2 <path>
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
#### `rename-pickers-day`
|
|
426
|
+
|
|
427
|
+
Renames `PickersDay` to `PickerDay` and all related types, classes, and theme component names.
|
|
428
|
+
|
|
429
|
+
```diff
|
|
430
|
+
-import { PickersDay, PickersDayProps, pickersDayClasses } from '@mui/x-date-pickers/PickersDay';
|
|
431
|
+
+import { PickerDay, PickerDayProps, pickerDayClasses } from '@mui/x-date-pickers/PickerDay';
|
|
432
|
+
|
|
433
|
+
const theme = createTheme({
|
|
434
|
+
components: {
|
|
435
|
+
- MuiPickersDay: {
|
|
436
|
+
+ MuiPickerDay: {
|
|
437
|
+
styleOverrides: { root: { color: 'red' } },
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
});
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
<!-- #npm-tag-reference -->
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
npx @mui/x-codemod@next v9.0.0/pickers/rename-pickers-day <path>
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
#### `rename-picker-classes`
|
|
450
|
+
|
|
451
|
+
Renames `PickerDay` and `DateRangePickerDay` CSS class keys to their new equivalents.
|
|
452
|
+
|
|
453
|
+
```diff
|
|
454
|
+
-'& .MuiPickerDay-outsideCurrentMonth'
|
|
455
|
+
+'& .MuiPickerDay-dayOutsideMonth'
|
|
456
|
+
|
|
457
|
+
-'& .MuiDateRangePickerDay-rangeIntervalDayHighlightStart'
|
|
458
|
+
+'& .MuiDateRangePickerDay-selectionStart'
|
|
459
|
+
|
|
460
|
+
-'& .MuiDateRangePickerDay-dayInsideRangeInterval'
|
|
461
|
+
+'& .MuiDateRangePickerDay-insideSelection'
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
<!-- #npm-tag-reference -->
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
npx @mui/x-codemod@next v9.0.0/pickers/rename-picker-classes <path>
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
#### `remove-disable-margin`
|
|
471
|
+
|
|
472
|
+
Removes the `disableMargin` prop from `PickerDay` and `DateRangePickerDay` components and replaces it with the `--PickerDay-horizontalMargin` CSS variable via the `sx` prop.
|
|
473
|
+
|
|
474
|
+
```diff
|
|
475
|
+
-<PickerDay disableMargin day={day} />
|
|
476
|
+
+<PickerDay day={day} sx={{ '--PickerDay-horizontalMargin': 0 }} />
|
|
477
|
+
|
|
478
|
+
-<DatePicker slotProps={{ day: { disableMargin: true } }} />
|
|
479
|
+
+<DatePicker slotProps={{ day: { sx: { '--PickerDay-horizontalMargin': 0 } } }} />
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
When `disableMargin={false}`, the prop is simply removed without adding the CSS variable.
|
|
483
|
+
|
|
484
|
+
<!-- #npm-tag-reference -->
|
|
485
|
+
|
|
486
|
+
```bash
|
|
487
|
+
npx @mui/x-codemod@next v9.0.0/pickers/remove-disable-margin <path>
|
|
488
|
+
```
|
|
489
|
+
|
|
314
490
|
## v8.0.0
|
|
315
491
|
|
|
316
492
|
### 🚀 `preset-safe` for v8.0.0
|
package/package.json
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/x-codemod",
|
|
3
|
-
"version": "9.0.0-
|
|
3
|
+
"version": "9.0.0-rc.0",
|
|
4
4
|
"author": "MUI Team",
|
|
5
5
|
"description": "Codemod scripts for MUI X.",
|
|
6
|
+
"license": "MIT",
|
|
6
7
|
"keywords": [
|
|
7
8
|
"react",
|
|
8
9
|
"react-component",
|
|
@@ -16,7 +17,6 @@
|
|
|
16
17
|
"url": "git+https://github.com/mui/mui-x.git",
|
|
17
18
|
"directory": "packages/x-codemod"
|
|
18
19
|
},
|
|
19
|
-
"license": "MIT",
|
|
20
20
|
"homepage": "https://github.com/mui/mui-x/tree/master/packages/x-codemod",
|
|
21
21
|
"funding": {
|
|
22
22
|
"type": "opencollective",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"@babel/traverse": "^7.29.0",
|
|
29
29
|
"jscodeshift": "17.3.0",
|
|
30
30
|
"yargs": "^18.0.0",
|
|
31
|
-
"@mui/x-internals": "9.0.0-
|
|
31
|
+
"@mui/x-internals": "9.0.0-rc.0"
|
|
32
32
|
},
|
|
33
33
|
"sideEffects": false,
|
|
34
34
|
"publishConfig": {
|
package/util/renameClasses.js
CHANGED
|
@@ -44,7 +44,14 @@ function renameClasses(parameters) {
|
|
|
44
44
|
localNameToOldClassName[hasAlias ? localName : oldName] = oldName;
|
|
45
45
|
renamedIdentifiersMap[oldName] = config.newClassName;
|
|
46
46
|
if (!hasAlias && alreadyAvailableIdentifiersMap.has(config.newClassName)) {
|
|
47
|
+
const importDeclarationCollection = j(path).closest(j.ImportDeclaration);
|
|
47
48
|
path.prune();
|
|
49
|
+
if (importDeclarationCollection.length > 0) {
|
|
50
|
+
const importDeclaration = importDeclarationCollection.nodes()[0];
|
|
51
|
+
if (importDeclaration.specifiers?.length === 0) {
|
|
52
|
+
importDeclarationCollection.remove();
|
|
53
|
+
}
|
|
54
|
+
}
|
|
48
55
|
return;
|
|
49
56
|
}
|
|
50
57
|
alreadyAvailableIdentifiersMap.add(config.newClassName);
|
|
@@ -5,10 +5,25 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
7
|
exports.default = transformer;
|
|
8
|
+
exports.testConfig = void 0;
|
|
8
9
|
var _renameFieldRef = _interopRequireDefault(require("../rename-field-ref"));
|
|
10
|
+
var _removePickerDay = _interopRequireDefault(require("../remove-picker-day-2"));
|
|
11
|
+
var _renamePickerDay = _interopRequireDefault(require("../rename-picker-day-2"));
|
|
12
|
+
var _renamePickersDay = _interopRequireDefault(require("../rename-pickers-day"));
|
|
13
|
+
var _renamePickerClasses = _interopRequireDefault(require("../rename-picker-classes"));
|
|
14
|
+
var _removeDisableMargin = _interopRequireDefault(require("../remove-disable-margin"));
|
|
15
|
+
var _removeEnableAccessibleFieldDomStructure = _interopRequireDefault(require("../remove-enable-accessible-field-dom-structure"));
|
|
16
|
+
// Order matters: removePickerDay2 must run before renamePickerDay2
|
|
17
|
+
// because it looks for `PickerDay2` identifiers in slot objects.
|
|
18
|
+
// If renamePickerDay2 ran first, those identifiers would already be
|
|
19
|
+
// renamed to `PickerDay` and removePickerDay2 would not find them.
|
|
20
|
+
const allModules = [_renameFieldRef.default, _removePickerDay.default, _renamePickerDay.default, _renamePickersDay.default, _renamePickerClasses.default, _removeDisableMargin.default, _removeEnableAccessibleFieldDomStructure.default];
|
|
9
21
|
function transformer(file, api, options) {
|
|
10
|
-
|
|
22
|
+
allModules.forEach(transform => {
|
|
11
23
|
file.source = transform(file, api, options);
|
|
12
24
|
});
|
|
13
25
|
return file.source;
|
|
14
|
-
}
|
|
26
|
+
}
|
|
27
|
+
const testConfig = exports.testConfig = {
|
|
28
|
+
allModules
|
|
29
|
+
};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = transformer;
|
|
8
|
+
exports.testConfig = void 0;
|
|
9
|
+
var _path = _interopRequireDefault(require("path"));
|
|
10
|
+
var _readFile = _interopRequireDefault(require("../../../util/readFile"));
|
|
11
|
+
// Components on which disableMargin was a direct prop
|
|
12
|
+
const dayComponentNames = ['PickerDay', 'PickersDay', 'DateRangePickerDay'];
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Returns true if a disableMargin JSX attribute is considered enabled (i.e. `disableMargin` or
|
|
16
|
+
* `disableMargin={true}`). Returns false for `disableMargin={false}`.
|
|
17
|
+
*/
|
|
18
|
+
function isDisableMarginEnabled(attr) {
|
|
19
|
+
if (!attr.value) {
|
|
20
|
+
// bare `disableMargin` with no value — equivalent to true
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
if (attr.value.type === 'JSXExpressionContainer' && attr.value.expression.type === 'BooleanLiteral') {
|
|
24
|
+
return attr.value.expression.value;
|
|
25
|
+
}
|
|
26
|
+
// Any other expression (variable, etc.) — conservatively treat as enabled
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
const cssVarKey = '--PickerDay-horizontalMargin';
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Merges `'--PickerDay-horizontalMargin': 0` into an existing ObjectExpression used as an `sx` value.
|
|
33
|
+
* Only merges when the expression is a plain object literal.
|
|
34
|
+
* Returns true if the merge succeeded.
|
|
35
|
+
*/
|
|
36
|
+
function mergeCssVarIntoSxObject(j, sxExpr) {
|
|
37
|
+
if (sxExpr.type !== 'ObjectExpression') {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
// Avoid adding the CSS variable if it's already there
|
|
41
|
+
const alreadyHasVar = sxExpr.properties.some(p => p.type === 'ObjectProperty' && p.key?.value === cssVarKey);
|
|
42
|
+
if (!alreadyHasVar) {
|
|
43
|
+
sxExpr.properties.push(j.objectProperty(j.stringLiteral(cssVarKey), j.numericLiteral(0)));
|
|
44
|
+
}
|
|
45
|
+
return true;
|
|
46
|
+
}
|
|
47
|
+
function transformer(file, api, options) {
|
|
48
|
+
const j = api.jscodeshift;
|
|
49
|
+
const root = j(file.source);
|
|
50
|
+
const printOptions = options.printOptions || {
|
|
51
|
+
quote: 'single',
|
|
52
|
+
trailingComma: true
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// ─── Case 1: disableMargin directly on a day component JSX element ───────────
|
|
56
|
+
root.find(j.JSXOpeningElement).filter(p => {
|
|
57
|
+
const name = p.node.name;
|
|
58
|
+
return name.type === 'JSXIdentifier' && dayComponentNames.includes(name.name);
|
|
59
|
+
}).forEach(openingElPath => {
|
|
60
|
+
const attrs = openingElPath.node.attributes;
|
|
61
|
+
const dmIndex = attrs.findIndex(a => a.type === 'JSXAttribute' && a.name?.name === 'disableMargin');
|
|
62
|
+
if (dmIndex === -1) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const dmAttr = attrs[dmIndex];
|
|
66
|
+
const enabled = isDisableMarginEnabled(dmAttr);
|
|
67
|
+
attrs.splice(dmIndex, 1);
|
|
68
|
+
if (enabled) {
|
|
69
|
+
const sxIndex = attrs.findIndex(a => a.type === 'JSXAttribute' && a.name?.name === 'sx');
|
|
70
|
+
if (sxIndex === -1) {
|
|
71
|
+
attrs.push(j.jsxAttribute(j.jsxIdentifier('sx'), j.jsxExpressionContainer(j.objectExpression([j.objectProperty(j.stringLiteral(cssVarKey), j.numericLiteral(0))]))));
|
|
72
|
+
} else {
|
|
73
|
+
const sxAttr = attrs[sxIndex];
|
|
74
|
+
if (sxAttr.value?.type === 'JSXExpressionContainer') {
|
|
75
|
+
mergeCssVarIntoSxObject(j, sxAttr.value.expression);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// ─── Case 2: disableMargin inside a slotProps.day object ─────────────────────
|
|
82
|
+
root.find(j.JSXAttribute, {
|
|
83
|
+
name: {
|
|
84
|
+
name: 'slotProps'
|
|
85
|
+
}
|
|
86
|
+
}).forEach(slotPropsAttrPath => {
|
|
87
|
+
const container = slotPropsAttrPath.node.value;
|
|
88
|
+
if (container?.type !== 'JSXExpressionContainer') {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const slotPropsObj = container.expression;
|
|
92
|
+
if (slotPropsObj.type !== 'ObjectExpression') {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
slotPropsObj.properties.forEach(prop => {
|
|
96
|
+
if (prop.type !== 'ObjectProperty') {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const keyName = prop.key?.name ?? prop.key?.value;
|
|
100
|
+
if (keyName !== 'day') {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
const dayObj = prop.value;
|
|
104
|
+
if (dayObj.type !== 'ObjectExpression') {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const dmIndex = dayObj.properties.findIndex(p => p.type === 'ObjectProperty' && (p.key?.name === 'disableMargin' || p.key?.value === 'disableMargin'));
|
|
108
|
+
if (dmIndex === -1) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const dmProp = dayObj.properties[dmIndex];
|
|
112
|
+
const enabled = dmProp.value.type === 'BooleanLiteral' ? dmProp.value.value : true;
|
|
113
|
+
dayObj.properties.splice(dmIndex, 1);
|
|
114
|
+
if (enabled) {
|
|
115
|
+
const sxIndex = dayObj.properties.findIndex(p => p.type === 'ObjectProperty' && (p.key?.name === 'sx' || p.key?.value === 'sx'));
|
|
116
|
+
if (sxIndex === -1) {
|
|
117
|
+
dayObj.properties.push(j.objectProperty(j.identifier('sx'), j.objectExpression([j.objectProperty(j.stringLiteral(cssVarKey), j.numericLiteral(0))])));
|
|
118
|
+
} else {
|
|
119
|
+
mergeCssVarIntoSxObject(j, dayObj.properties[sxIndex].value);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
return root.toSource(printOptions);
|
|
125
|
+
}
|
|
126
|
+
const testConfig = () => ({
|
|
127
|
+
name: 'remove-disable-margin',
|
|
128
|
+
specFiles: [{
|
|
129
|
+
name: "remove disableMargin prop and replace with sx={{ '--PickerDay-horizontalMargin': 0 }}",
|
|
130
|
+
actual: (0, _readFile.default)(_path.default.join(__dirname, 'actual.spec.tsx')),
|
|
131
|
+
expected: (0, _readFile.default)(_path.default.join(__dirname, 'expected.spec.tsx'))
|
|
132
|
+
}]
|
|
133
|
+
});
|
|
134
|
+
exports.testConfig = testConfig;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = transformer;
|
|
8
|
+
exports.testConfig = void 0;
|
|
9
|
+
var _path = _interopRequireDefault(require("path"));
|
|
10
|
+
var _removeProps = _interopRequireDefault(require("../../../util/removeProps"));
|
|
11
|
+
var _readFile = _interopRequireDefault(require("../../../util/readFile"));
|
|
12
|
+
const componentNames = ['DateField', 'DateTimeField', 'TimeField', 'DateRangeField', 'DateTimeRangeField', 'TimeRangeField', 'MultiInputDateRangeField', 'MultiInputDateTimeRangeField', 'MultiInputTimeRangeField', 'SingleInputDateRangeField', 'SingleInputDateTimeRangeField', 'SingleInputTimeRangeField', 'DatePicker', 'DesktopDatePicker', 'MobileDatePicker', 'StaticDatePicker', 'DateTimePicker', 'DesktopDateTimePicker', 'MobileDateTimePicker', 'StaticDateTimePicker', 'TimePicker', 'DesktopTimePicker', 'MobileTimePicker', 'StaticTimePicker', 'DateRangePicker', 'DesktopDateRangePicker', 'MobileDateRangePicker', 'StaticDateRangePicker', 'DateTimeRangePicker', 'DesktopDateTimeRangePicker', 'MobileDateTimeRangePicker', 'TimeRangePicker', 'DesktopTimeRangePicker', 'MobileTimeRangePicker'];
|
|
13
|
+
function transformer(file, api, options) {
|
|
14
|
+
const j = api.jscodeshift;
|
|
15
|
+
const root = j(file.source);
|
|
16
|
+
const printOptions = options.printOptions || {
|
|
17
|
+
quote: 'single',
|
|
18
|
+
trailingComma: true
|
|
19
|
+
};
|
|
20
|
+
(0, _removeProps.default)({
|
|
21
|
+
root,
|
|
22
|
+
j,
|
|
23
|
+
componentNames,
|
|
24
|
+
props: ['enableAccessibleFieldDOMStructure']
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Also remove enableAccessibleFieldDOMStructure from slotProps.field
|
|
28
|
+
componentNames.forEach(componentName => {
|
|
29
|
+
root.find(j.JSXElement, {
|
|
30
|
+
openingElement: {
|
|
31
|
+
name: {
|
|
32
|
+
name: componentName
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}).forEach(elementPath => {
|
|
36
|
+
j(elementPath).find(j.JSXAttribute, {
|
|
37
|
+
name: {
|
|
38
|
+
name: 'slotProps'
|
|
39
|
+
}
|
|
40
|
+
}).forEach(slotPropsAttr => {
|
|
41
|
+
const value = slotPropsAttr.node.value;
|
|
42
|
+
if (value?.type !== 'JSXExpressionContainer' || value.expression.type !== 'ObjectExpression') {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const fieldProp = value.expression.properties.find(p => p.key?.name === 'field' || p.key?.value === 'field');
|
|
46
|
+
if (!fieldProp || fieldProp.value.type !== 'ObjectExpression') {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
fieldProp.value.properties = fieldProp.value.properties.filter(p => p.key?.name !== 'enableAccessibleFieldDOMStructure' && p.key?.value !== 'enableAccessibleFieldDOMStructure');
|
|
50
|
+
|
|
51
|
+
// If field object is now empty, remove it from slotProps
|
|
52
|
+
if (fieldProp.value.properties.length === 0) {
|
|
53
|
+
value.expression.properties = value.expression.properties.filter(p => p !== fieldProp);
|
|
54
|
+
// If slotProps object is now empty, remove the whole attribute
|
|
55
|
+
if (value.expression.properties.length === 0) {
|
|
56
|
+
j(slotPropsAttr).remove();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
return root.toSource(printOptions);
|
|
63
|
+
}
|
|
64
|
+
const testConfig = () => ({
|
|
65
|
+
name: 'remove-enable-accessible-field-dom-structure',
|
|
66
|
+
specFiles: [{
|
|
67
|
+
name: 'remove enableAccessibleFieldDOMStructure prop',
|
|
68
|
+
actual: (0, _readFile.default)(_path.default.join(__dirname, 'actual.spec.tsx')),
|
|
69
|
+
expected: (0, _readFile.default)(_path.default.join(__dirname, 'expected.spec.tsx'))
|
|
70
|
+
}]
|
|
71
|
+
});
|
|
72
|
+
exports.testConfig = testConfig;
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = transformer;
|
|
8
|
+
exports.testConfig = void 0;
|
|
9
|
+
var _path = _interopRequireDefault(require("path"));
|
|
10
|
+
var _readFile = _interopRequireDefault(require("../../../util/readFile"));
|
|
11
|
+
const pickerNames = ['DatePicker', 'DesktopDatePicker', 'MobileDatePicker', 'StaticDatePicker', 'DateTimePicker', 'DesktopDateTimePicker', 'MobileDateTimePicker', 'StaticDateTimePicker', 'TimePicker', 'DesktopTimePicker', 'MobileTimePicker', 'StaticTimePicker', 'DateRangePicker', 'DesktopDateRangePicker', 'MobileDateRangePicker', 'StaticDateRangePicker', 'DateTimeRangePicker', 'DesktopDateTimeRangePicker', 'MobileDateTimeRangePicker', 'TimeRangePicker', 'DesktopTimeRangePicker', 'MobileTimeRangePicker', 'DateCalendar', 'DayCalendar'];
|
|
12
|
+
function transformer(file, api, options) {
|
|
13
|
+
const j = api.jscodeshift;
|
|
14
|
+
const root = j(file.source);
|
|
15
|
+
const printOptions = options.printOptions || {
|
|
16
|
+
quote: 'single',
|
|
17
|
+
trailingComma: true
|
|
18
|
+
};
|
|
19
|
+
const dayComponents = ['PickerDay2', 'DateRangePickerDay2'];
|
|
20
|
+
root.find(j.ObjectExpression).forEach(objectExpressionPath => {
|
|
21
|
+
const properties = objectExpressionPath.node.properties;
|
|
22
|
+
const dayPropIndex = properties.findIndex(prop => {
|
|
23
|
+
const keyName = prop.key?.name || prop.key?.value;
|
|
24
|
+
if (keyName !== 'day') {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
const val = prop.value;
|
|
28
|
+
return val.type === 'Identifier' && dayComponents.includes(val.name);
|
|
29
|
+
});
|
|
30
|
+
if (dayPropIndex !== -1) {
|
|
31
|
+
properties.splice(dayPropIndex, 1);
|
|
32
|
+
if (properties.length === 0) {
|
|
33
|
+
// Case 1: inline slots attribute — remove the entire slots prop
|
|
34
|
+
const attrCollection = j(objectExpressionPath).closest(j.JSXAttribute, {
|
|
35
|
+
name: {
|
|
36
|
+
name: 'slots'
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
if (attrCollection.length > 0) {
|
|
40
|
+
const openingElement = j(objectExpressionPath).closest(j.JSXOpeningElement);
|
|
41
|
+
if (openingElement.length > 0) {
|
|
42
|
+
const nameNode = openingElement.get().value.name;
|
|
43
|
+
const componentName = nameNode.type === 'JSXIdentifier' ? nameNode.name : null;
|
|
44
|
+
if (componentName && pickerNames.includes(componentName)) {
|
|
45
|
+
attrCollection.remove();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Case 2: object is in a variable — remove slots={varName} on picker components,
|
|
51
|
+
// then remove the variable declaration if it becomes unreferenced
|
|
52
|
+
const varDeclarator = j(objectExpressionPath).closest(j.VariableDeclarator);
|
|
53
|
+
if (varDeclarator.length > 0) {
|
|
54
|
+
const varId = varDeclarator.get().value.id;
|
|
55
|
+
const varName = varId?.type === 'Identifier' ? varId.name : null;
|
|
56
|
+
if (varName) {
|
|
57
|
+
const slotsOnPickers = root.find(j.JSXAttribute, {
|
|
58
|
+
name: {
|
|
59
|
+
name: 'slots'
|
|
60
|
+
}
|
|
61
|
+
}).filter(attrPath => {
|
|
62
|
+
const val = attrPath.node.value;
|
|
63
|
+
return val?.type === 'JSXExpressionContainer' && val.expression.type === 'Identifier' && val.expression.name === varName;
|
|
64
|
+
}).filter(attrPath => {
|
|
65
|
+
const openingElement = j(attrPath).closest(j.JSXOpeningElement);
|
|
66
|
+
if (openingElement.length === 0) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
const nameNode = openingElement.get().value.name;
|
|
70
|
+
const componentName = nameNode.type === 'JSXIdentifier' ? nameNode.name : null;
|
|
71
|
+
return componentName !== null && pickerNames.includes(componentName);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Check (before any mutation) whether varName has references outside
|
|
75
|
+
// of picker slots and the declaration binding itself.
|
|
76
|
+
const hasNonPickerRefs = root.find(j.Identifier, {
|
|
77
|
+
name: varName
|
|
78
|
+
}).filter(idPath => {
|
|
79
|
+
// find(j.Identifier) also matches JSXIdentifier (attribute names) — skip them
|
|
80
|
+
if (idPath.node.type !== 'Identifier') {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
// Exclude the declaration binding (the `id` in `const varName = ...`)
|
|
84
|
+
if (idPath.name === 'id' && idPath.parent.value.type === 'VariableDeclarator') {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
// Exclude references inside picker slots attributes (those are being removed)
|
|
88
|
+
const closestAttr = j(idPath).closest(j.JSXAttribute, {
|
|
89
|
+
name: {
|
|
90
|
+
name: 'slots'
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
if (closestAttr.length > 0) {
|
|
94
|
+
const openingElement = j(closestAttr.get()).closest(j.JSXOpeningElement);
|
|
95
|
+
if (openingElement.length > 0) {
|
|
96
|
+
const nameNode = openingElement.get().value.name;
|
|
97
|
+
const componentName = nameNode.type === 'JSXIdentifier' ? nameNode.name : null;
|
|
98
|
+
if (componentName && pickerNames.includes(componentName)) {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return true;
|
|
104
|
+
}).length > 0;
|
|
105
|
+
slotsOnPickers.remove();
|
|
106
|
+
if (!hasNonPickerRefs) {
|
|
107
|
+
varDeclarator.closest(j.VariableDeclaration).remove();
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Remove imports if no longer used
|
|
116
|
+
dayComponents.forEach(componentName => {
|
|
117
|
+
const usages = root.find(j.Identifier, {
|
|
118
|
+
name: componentName
|
|
119
|
+
}).filter(componentPath => {
|
|
120
|
+
const {
|
|
121
|
+
parent
|
|
122
|
+
} = componentPath;
|
|
123
|
+
if (parent.value.type === 'ImportSpecifier') {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
return true;
|
|
127
|
+
});
|
|
128
|
+
if (usages.length === 0) {
|
|
129
|
+
root.find(j.ImportSpecifier, {
|
|
130
|
+
imported: {
|
|
131
|
+
name: componentName
|
|
132
|
+
}
|
|
133
|
+
}).filter(componentPath => {
|
|
134
|
+
const importDeclaration = componentPath.parentPath.parentPath.value;
|
|
135
|
+
return importDeclaration.source.value.startsWith('@mui/x-date-pickers') || importDeclaration.source.value.startsWith('@mui/x-date-pickers-pro');
|
|
136
|
+
}).forEach(componentPath => {
|
|
137
|
+
const importDeclaration = componentPath.parentPath.parentPath;
|
|
138
|
+
j(componentPath).remove();
|
|
139
|
+
if (importDeclaration.value.specifiers.length === 0) {
|
|
140
|
+
j(importDeclaration).remove();
|
|
141
|
+
}
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
return root.toSource(printOptions);
|
|
146
|
+
}
|
|
147
|
+
const testConfig = () => ({
|
|
148
|
+
name: 'remove-picker-day-2',
|
|
149
|
+
specFiles: [{
|
|
150
|
+
name: 'remove PickerDay2 and DateRangePickerDay2 from slots',
|
|
151
|
+
actual: (0, _readFile.default)(_path.default.join(__dirname, 'actual.spec.tsx')),
|
|
152
|
+
expected: (0, _readFile.default)(_path.default.join(__dirname, 'expected.spec.tsx'))
|
|
153
|
+
}]
|
|
154
|
+
});
|
|
155
|
+
exports.testConfig = testConfig;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = transformer;
|
|
8
|
+
exports.testConfig = void 0;
|
|
9
|
+
var _path = _interopRequireDefault(require("path"));
|
|
10
|
+
var _readFile = _interopRequireDefault(require("../../../util/readFile"));
|
|
11
|
+
var _renameClasses = require("../../../util/renameClasses");
|
|
12
|
+
const classRenames = {
|
|
13
|
+
outsideCurrentMonth: 'dayOutsideMonth',
|
|
14
|
+
hiddenDayFiller: 'fillerCell',
|
|
15
|
+
hiddenDaySpacingFiller: 'fillerCell',
|
|
16
|
+
rangeIntervalDayHighlightStart: 'selectionStart',
|
|
17
|
+
rangeIntervalDayHighlightEnd: 'selectionEnd',
|
|
18
|
+
rangeIntervalDayPreviewStart: 'previewStart',
|
|
19
|
+
rangeIntervalDayPreviewEnd: 'previewEnd',
|
|
20
|
+
dayInsideRangeInterval: 'insideSelection',
|
|
21
|
+
rangeIntervalPreview: 'insidePreviewing',
|
|
22
|
+
rangeIntervalDayHighlight: 'selectionStart',
|
|
23
|
+
rangeIntervalDayPreview: 'previewStart'
|
|
24
|
+
};
|
|
25
|
+
function transformer(file, api, options) {
|
|
26
|
+
const j = api.jscodeshift;
|
|
27
|
+
const root = j(file.source);
|
|
28
|
+
const printOptions = options.printOptions || {
|
|
29
|
+
quote: 'single',
|
|
30
|
+
trailingComma: true
|
|
31
|
+
};
|
|
32
|
+
(0, _renameClasses.renameClasses)({
|
|
33
|
+
j,
|
|
34
|
+
root,
|
|
35
|
+
packageNames: ['@mui/x-date-pickers', '@mui/x-date-pickers-pro'],
|
|
36
|
+
classes: {
|
|
37
|
+
dateRangePickerDayClasses: {
|
|
38
|
+
newClassName: 'dateRangePickerDayClasses',
|
|
39
|
+
properties: classRenames
|
|
40
|
+
},
|
|
41
|
+
pickerDayClasses: {
|
|
42
|
+
newClassName: 'pickerDayClasses',
|
|
43
|
+
properties: classRenames
|
|
44
|
+
},
|
|
45
|
+
pickersDayClasses: {
|
|
46
|
+
newClassName: 'pickerDayClasses',
|
|
47
|
+
properties: classRenames
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Rename properties in styleOverrides
|
|
53
|
+
const componentsToHandle = ['MuiDateRangePickerDay', 'MuiPickerDay', 'MuiPickersDay'];
|
|
54
|
+
root.find(j.ObjectProperty).forEach(objPropPath => {
|
|
55
|
+
const keyName = objPropPath.node.key.type === 'Identifier' ? objPropPath.node.key.name : objPropPath.node.key.value;
|
|
56
|
+
if (componentsToHandle.includes(keyName) && objPropPath.node.value.type === 'ObjectExpression') {
|
|
57
|
+
j(objPropPath.node.value).find(j.ObjectProperty).filter(p => {
|
|
58
|
+
const k = p.node.key.type === 'Identifier' ? p.node.key.name : p.node.key.value;
|
|
59
|
+
return k === 'styleOverrides';
|
|
60
|
+
}).forEach(styleOverridesPath => {
|
|
61
|
+
if (styleOverridesPath.node.value.type === 'ObjectExpression') {
|
|
62
|
+
const seenProperties = new Map();
|
|
63
|
+
const indicesToRemove = new Set();
|
|
64
|
+
styleOverridesPath.node.value.properties.forEach((prop, index) => {
|
|
65
|
+
if (prop.type === 'ObjectProperty') {
|
|
66
|
+
const propKey = prop.key.type === 'Identifier' ? prop.key.name : prop.key.value;
|
|
67
|
+
const newKey = classRenames[propKey];
|
|
68
|
+
if (newKey) {
|
|
69
|
+
if (seenProperties.has(newKey)) {
|
|
70
|
+
const firstProp = seenProperties.get(newKey);
|
|
71
|
+
if (firstProp.value.type === 'ObjectExpression' && prop.value.type === 'ObjectExpression') {
|
|
72
|
+
firstProp.value.properties.push(...prop.value.properties);
|
|
73
|
+
}
|
|
74
|
+
indicesToRemove.add(index);
|
|
75
|
+
} else {
|
|
76
|
+
if (prop.key.type === 'Identifier') {
|
|
77
|
+
prop.key.name = newKey;
|
|
78
|
+
} else if (prop.key.type === 'StringLiteral') {
|
|
79
|
+
prop.key.value = newKey;
|
|
80
|
+
}
|
|
81
|
+
seenProperties.set(newKey, prop);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
styleOverridesPath.node.value.properties = styleOverridesPath.node.value.properties.filter((_, index) => !indicesToRemove.has(index));
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// Rename class names in strings and template literals.
|
|
93
|
+
// Only replace within known MUI component CSS class prefixes to avoid false positives.
|
|
94
|
+
const muiClassPrefixes = componentsToHandle.map(c => `${c}-`);
|
|
95
|
+
const replaceClasses = value => {
|
|
96
|
+
let newValue = value;
|
|
97
|
+
muiClassPrefixes.forEach(prefix => {
|
|
98
|
+
Object.keys(classRenames).forEach(oldClass => {
|
|
99
|
+
const newClass = classRenames[oldClass];
|
|
100
|
+
newValue = newValue.replace(new RegExp(`${prefix}${oldClass}\\b`, 'g'), `${prefix}${newClass}`);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
return newValue;
|
|
104
|
+
};
|
|
105
|
+
root.find(j.StringLiteral).forEach(strPath => {
|
|
106
|
+
strPath.node.value = replaceClasses(strPath.node.value);
|
|
107
|
+
});
|
|
108
|
+
root.find(j.TemplateLiteral).forEach(templatePath => {
|
|
109
|
+
templatePath.node.quasis.forEach(quasi => {
|
|
110
|
+
quasi.value.raw = replaceClasses(quasi.value.raw);
|
|
111
|
+
if (quasi.value.cooked) {
|
|
112
|
+
quasi.value.cooked = replaceClasses(quasi.value.cooked);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
return root.toSource(printOptions);
|
|
117
|
+
}
|
|
118
|
+
const testConfig = () => ({
|
|
119
|
+
name: 'rename-picker-classes',
|
|
120
|
+
specFiles: [{
|
|
121
|
+
name: 'rename PickerDay and DateRangePickerDay class keys',
|
|
122
|
+
actual: (0, _readFile.default)(_path.default.join(__dirname, 'actual.spec.tsx')),
|
|
123
|
+
expected: (0, _readFile.default)(_path.default.join(__dirname, 'expected.spec.tsx'))
|
|
124
|
+
}]
|
|
125
|
+
});
|
|
126
|
+
exports.testConfig = testConfig;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = transformer;
|
|
8
|
+
exports.testConfig = void 0;
|
|
9
|
+
var _path = _interopRequireDefault(require("path"));
|
|
10
|
+
var _readFile = _interopRequireDefault(require("../../../util/readFile"));
|
|
11
|
+
function transformer(file, api, options) {
|
|
12
|
+
const j = api.jscodeshift;
|
|
13
|
+
const root = j(file.source);
|
|
14
|
+
const printOptions = options.printOptions || {
|
|
15
|
+
quote: 'single',
|
|
16
|
+
trailingComma: true
|
|
17
|
+
};
|
|
18
|
+
const renames = {
|
|
19
|
+
PickerDay2: 'PickerDay',
|
|
20
|
+
PickerDay2Props: 'PickerDayProps',
|
|
21
|
+
pickerDay2Classes: 'pickerDayClasses',
|
|
22
|
+
PickerDay2ClassKey: 'PickerDayClassKey',
|
|
23
|
+
PickerDay2Slots: 'PickerDaySlots',
|
|
24
|
+
PickerDay2SlotProps: 'PickerDaySlotProps',
|
|
25
|
+
PickerDay2OwnerState: 'PickerDayOwnerState',
|
|
26
|
+
DateRangePickerDay2: 'DateRangePickerDay',
|
|
27
|
+
DateRangePickerDay2Props: 'DateRangePickerDayProps',
|
|
28
|
+
dateRangePickerDay2Classes: 'dateRangePickerDayClasses',
|
|
29
|
+
DateRangePickerDay2ClassKey: 'DateRangePickerDayClassKey',
|
|
30
|
+
DateRangePickerDay2Slots: 'DateRangePickerDaySlots',
|
|
31
|
+
DateRangePickerDay2SlotProps: 'DateRangePickerDaySlotProps',
|
|
32
|
+
DateRangePickerDay2OwnerState: 'DateRangePickerDayOwnerState'
|
|
33
|
+
};
|
|
34
|
+
const renameKeys = Object.keys(renames);
|
|
35
|
+
|
|
36
|
+
// Rename imports and usages
|
|
37
|
+
renameKeys.forEach(oldName => {
|
|
38
|
+
const newName = renames[oldName];
|
|
39
|
+
root.find(j.Identifier, {
|
|
40
|
+
name: oldName
|
|
41
|
+
}).forEach(keyPath => {
|
|
42
|
+
// Avoid renaming property keys in objects unless they are shorthand or identifiers in other contexts
|
|
43
|
+
if (keyPath.parent.value.type === 'Property' && keyPath.parent.value.key === keyPath.node && !keyPath.parent.value.shorthand) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Avoid renaming member expressions like something.PickerDay2
|
|
47
|
+
if (keyPath.parent.value.type === 'MemberExpression' && keyPath.parent.value.property === keyPath.node && !keyPath.parent.value.computed) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
j(keyPath).replaceWith(j.identifier(newName));
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Rename theme components in createTheme / theme augmentation
|
|
55
|
+
root.find(j.Identifier, {
|
|
56
|
+
name: 'MuiPickerDay2'
|
|
57
|
+
}).forEach(keyPath => {
|
|
58
|
+
j(keyPath).replaceWith(j.identifier('MuiPickerDay'));
|
|
59
|
+
});
|
|
60
|
+
root.find(j.Identifier, {
|
|
61
|
+
name: 'MuiDateRangePickerDay2'
|
|
62
|
+
}).forEach(keyPath => {
|
|
63
|
+
j(keyPath).replaceWith(j.identifier('MuiDateRangePickerDay'));
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Also handle string literals and template literals
|
|
67
|
+
const replaceClass = value => value.replace(/MuiPickerDay2\b/g, 'MuiPickerDay').replace(/MuiDateRangePickerDay2\b/g, 'MuiDateRangePickerDay');
|
|
68
|
+
root.find(j.StringLiteral).forEach(keyPath => {
|
|
69
|
+
if (keyPath.value.value.includes('MuiPickerDay2') || keyPath.value.value.includes('MuiDateRangePickerDay2')) {
|
|
70
|
+
j(keyPath).replaceWith(j.stringLiteral(replaceClass(keyPath.value.value)));
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
root.find(j.TemplateLiteral).forEach(keyPath => {
|
|
74
|
+
keyPath.value.quasis.forEach(quasi => {
|
|
75
|
+
if (quasi.value.raw.includes('MuiPickerDay2') || quasi.value.raw.includes('MuiDateRangePickerDay2')) {
|
|
76
|
+
quasi.value.raw = replaceClass(quasi.value.raw);
|
|
77
|
+
}
|
|
78
|
+
if (quasi.value.cooked && (quasi.value.cooked.includes('MuiPickerDay2') || quasi.value.cooked.includes('MuiDateRangePickerDay2'))) {
|
|
79
|
+
quasi.value.cooked = replaceClass(quasi.value.cooked);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Update import sources
|
|
85
|
+
root.find(j.ImportDeclaration).forEach(importPath => {
|
|
86
|
+
if (typeof importPath.value.source.value === 'string') {
|
|
87
|
+
if (importPath.value.source.value.includes('/PickerDay2')) {
|
|
88
|
+
importPath.value.source.value = importPath.value.source.value.replace('/PickerDay2', '/PickerDay');
|
|
89
|
+
}
|
|
90
|
+
if (importPath.value.source.value.includes('/DateRangePickerDay2')) {
|
|
91
|
+
importPath.value.source.value = importPath.value.source.value.replace('/DateRangePickerDay2', '/DateRangePickerDay');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
return root.toSource(printOptions);
|
|
96
|
+
}
|
|
97
|
+
const testConfig = () => ({
|
|
98
|
+
name: 'rename-picker-day-2',
|
|
99
|
+
specFiles: [{
|
|
100
|
+
name: 'rename PickerDay2 and DateRangePickerDay2 to PickerDay and DateRangePickerDay',
|
|
101
|
+
actual: (0, _readFile.default)(_path.default.join(__dirname, 'actual.spec.tsx')),
|
|
102
|
+
expected: (0, _readFile.default)(_path.default.join(__dirname, 'expected.spec.tsx'))
|
|
103
|
+
}]
|
|
104
|
+
});
|
|
105
|
+
exports.testConfig = testConfig;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
|
|
4
|
+
Object.defineProperty(exports, "__esModule", {
|
|
5
|
+
value: true
|
|
6
|
+
});
|
|
7
|
+
exports.default = transformer;
|
|
8
|
+
exports.testConfig = void 0;
|
|
9
|
+
var _path = _interopRequireDefault(require("path"));
|
|
10
|
+
var _readFile = _interopRequireDefault(require("../../../util/readFile"));
|
|
11
|
+
function transformer(file, api, options) {
|
|
12
|
+
const j = api.jscodeshift;
|
|
13
|
+
const root = j(file.source);
|
|
14
|
+
const printOptions = options.printOptions || {
|
|
15
|
+
quote: 'single',
|
|
16
|
+
trailingComma: true
|
|
17
|
+
};
|
|
18
|
+
const renames = {
|
|
19
|
+
PickersDay: 'PickerDay',
|
|
20
|
+
PickersDayProps: 'PickerDayProps',
|
|
21
|
+
pickersDayClasses: 'pickerDayClasses',
|
|
22
|
+
PickersDayClassKey: 'PickerDayClassKey',
|
|
23
|
+
PickersDaySlots: 'PickerDaySlots',
|
|
24
|
+
PickersDaySlotProps: 'PickerDaySlotProps',
|
|
25
|
+
PickersDayOwnerState: 'PickerDayOwnerState'
|
|
26
|
+
};
|
|
27
|
+
const renameKeys = Object.keys(renames);
|
|
28
|
+
|
|
29
|
+
// Rename imports and usages
|
|
30
|
+
renameKeys.forEach(oldName => {
|
|
31
|
+
const newName = renames[oldName];
|
|
32
|
+
root.find(j.Identifier, {
|
|
33
|
+
name: oldName
|
|
34
|
+
}).forEach(keyPath => {
|
|
35
|
+
// Avoid renaming property keys in objects unless they are shorthand or identifiers in other contexts
|
|
36
|
+
if (keyPath.parent.value.type === 'Property' && keyPath.parent.value.key === keyPath.node && !keyPath.parent.value.shorthand) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
// Avoid renaming member expressions like something.PickersDay
|
|
40
|
+
if (keyPath.parent.value.type === 'MemberExpression' && keyPath.parent.value.property === keyPath.node && !keyPath.parent.value.computed) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
j(keyPath).replaceWith(j.identifier(newName));
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Rename theme components in createTheme / theme augmentation
|
|
48
|
+
root.find(j.Identifier, {
|
|
49
|
+
name: 'MuiPickersDay'
|
|
50
|
+
}).forEach(keyPath => {
|
|
51
|
+
j(keyPath).replaceWith(j.identifier('MuiPickerDay'));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Also handle string literals and template literals for MuiPickersDay if any (e.g. in theme overrides or sx)
|
|
55
|
+
const replaceClass = value => value.replace(/MuiPickersDay\b/g, 'MuiPickerDay');
|
|
56
|
+
root.find(j.StringLiteral).forEach(keyPath => {
|
|
57
|
+
if (keyPath.value.value.includes('MuiPickersDay')) {
|
|
58
|
+
j(keyPath).replaceWith(j.stringLiteral(replaceClass(keyPath.value.value)));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
root.find(j.TemplateLiteral).forEach(keyPath => {
|
|
62
|
+
keyPath.value.quasis.forEach(quasi => {
|
|
63
|
+
if (quasi.value.raw.includes('MuiPickersDay')) {
|
|
64
|
+
quasi.value.raw = replaceClass(quasi.value.raw);
|
|
65
|
+
}
|
|
66
|
+
if (quasi.value.cooked && quasi.value.cooked.includes('MuiPickersDay')) {
|
|
67
|
+
quasi.value.cooked = replaceClass(quasi.value.cooked);
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Update import sources if they point to PickersDay (though usually they point to @mui/x-date-pickers)
|
|
73
|
+
root.find(j.ImportDeclaration).forEach(importPath => {
|
|
74
|
+
if (typeof importPath.value.source.value === 'string') {
|
|
75
|
+
if (importPath.value.source.value.includes('/PickersDay')) {
|
|
76
|
+
importPath.value.source.value = importPath.value.source.value.replace('/PickersDay', '/PickerDay');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
return root.toSource(printOptions);
|
|
81
|
+
}
|
|
82
|
+
const testConfig = () => ({
|
|
83
|
+
name: 'rename-pickers-day',
|
|
84
|
+
specFiles: [{
|
|
85
|
+
name: 'rename PickersDay to PickerDay and related types',
|
|
86
|
+
actual: (0, _readFile.default)(_path.default.join(__dirname, 'actual.spec.tsx')),
|
|
87
|
+
expected: (0, _readFile.default)(_path.default.join(__dirname, 'expected.spec.tsx'))
|
|
88
|
+
}]
|
|
89
|
+
});
|
|
90
|
+
exports.testConfig = testConfig;
|