@epilot/zenith-react 0.2.0-next.3 → 0.2.0-next.4
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/README.md +25 -0
- package/codemods/README.md +168 -0
- package/codemods/migrate/base-elements/accordion.ts +132 -0
- package/codemods/migrate/base-elements/alert.ts +81 -0
- package/codemods/migrate/base-elements/avatar.ts +116 -0
- package/codemods/migrate/base-elements/button.ts +188 -0
- package/codemods/migrate/base-elements/checkbox.ts +17 -0
- package/codemods/migrate/base-elements/chip.ts +87 -0
- package/codemods/migrate/base-elements/chip360.ts +162 -0
- package/codemods/migrate/base-elements/circular-progress.ts +73 -0
- package/codemods/migrate/base-elements/dialog.ts +323 -0
- package/codemods/migrate/base-elements/divider.ts +61 -0
- package/codemods/migrate/base-elements/feedback-message.ts +95 -0
- package/codemods/migrate/base-elements/icon-button.ts +203 -0
- package/codemods/migrate/base-elements/index.ts +55 -0
- package/codemods/migrate/base-elements/mui-props.ts +29 -0
- package/codemods/migrate/base-elements/notification.ts +98 -0
- package/codemods/migrate/base-elements/paper.ts +78 -0
- package/codemods/migrate/base-elements/select.ts +328 -0
- package/codemods/migrate/base-elements/shared.ts +910 -0
- package/codemods/migrate/base-elements/skeleton.ts +83 -0
- package/codemods/migrate/base-elements/switch.ts +19 -0
- package/codemods/migrate/base-elements/tabs.ts +222 -0
- package/codemods/migrate/base-elements/text-field.ts +425 -0
- package/codemods/migrate/base-elements/toggle-button.ts +185 -0
- package/codemods/migrate/base-elements/tooltip.ts +231 -0
- package/codemods/migrate/base-elements/typography.ts +247 -0
- package/codemods/migrate/base-elements/unsupported.ts +277 -0
- package/codemods/migrate/from-base-elements.ts +20 -0
- package/codemods/migrate/from-volt.ts +20 -0
- package/codemods/migrate/lib/imports.ts +399 -0
- package/codemods/migrate/lib/jsx.ts +313 -0
- package/codemods/migrate/lib/run-migration.ts +528 -0
- package/codemods/migrate/lib/source.ts +6 -0
- package/codemods/migrate/lib/todo.ts +107 -0
- package/codemods/migrate/lib/types.ts +114 -0
- package/codemods/migrate/volt/class-helpers.ts +37 -0
- package/codemods/migrate/volt/index.ts +18 -0
- package/codemods/migrate/volt/pagination.ts +26 -0
- package/codemods/migrate/volt/same-name.ts +293 -0
- package/codemods/migrate/volt/stylesheets.ts +18 -0
- package/codemods/migrate/volt/tanstack-types.ts +20 -0
- package/codemods/radix-to-base-ui.ts +389 -0
- package/dist/_virtual/_zenith-runtime-family_accordion.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_accordion.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_alert-dialog.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_alert-dialog.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_avatar.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_avatar.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_button.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_button.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_checkbox.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_checkbox.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_csp-provider.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_csp-provider.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_dialog.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_dialog.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_direction-provider.js +8 -0
- package/dist/_virtual/_zenith-runtime-family_direction-provider.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_menu.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_menu.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_merge-props.js +11 -0
- package/dist/_virtual/_zenith-runtime-family_merge-props.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_popover.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_popover.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_radio-group.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_radio-group.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_radio.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_radio.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_scroll-area.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_scroll-area.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_select.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_select.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_separator.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_separator.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_switch.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_switch.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_tabs.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_tabs.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_toast.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_toast.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_toggle-group.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_toggle-group.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_toggle.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_toggle.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_tooltip.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_tooltip.js.map +1 -0
- package/dist/_virtual/_zenith-runtime-family_use-render.js +7 -0
- package/dist/_virtual/_zenith-runtime-family_use-render.js.map +1 -0
- package/dist/components/accordion/accordion.js +179 -96
- package/dist/components/accordion/accordion.js.map +1 -1
- package/dist/components/alert-dialog/alert-dialog.js +243 -206
- package/dist/components/alert-dialog/alert-dialog.js.map +1 -1
- package/dist/components/avatar/avatar.js +94 -82
- package/dist/components/avatar/avatar.js.map +1 -1
- package/dist/components/badge/badge.js +11 -11
- package/dist/components/breadcrumb/breadcrumb.js +69 -70
- package/dist/components/breadcrumb/breadcrumb.js.map +1 -1
- package/dist/components/button/button.js +119 -102
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/checkbox/checkbox.js +68 -51
- package/dist/components/checkbox/checkbox.js.map +1 -1
- package/dist/components/date-range-picker/date-range-picker.js +100 -90
- package/dist/components/date-range-picker/date-range-picker.js.map +1 -1
- package/dist/components/date-time-picker/date-time-picker-input.js +118 -108
- package/dist/components/date-time-picker/date-time-picker-input.js.map +1 -1
- package/dist/components/date-time-picker/date-time-picker-panel.js +91 -94
- package/dist/components/date-time-picker/date-time-picker-panel.js.map +1 -1
- package/dist/components/dialog/dialog.js +238 -228
- package/dist/components/dialog/dialog.js.map +1 -1
- package/dist/components/drawer/drawer.js +259 -321
- package/dist/components/drawer/drawer.js.map +1 -1
- package/dist/components/dropdown-menu/dropdown-menu.js +533 -279
- package/dist/components/dropdown-menu/dropdown-menu.js.map +1 -1
- package/dist/components/field/field-combobox.js +87 -77
- package/dist/components/field/field-combobox.js.map +1 -1
- package/dist/components/list/list-sortable.js +104 -0
- package/dist/components/list/list-sortable.js.map +1 -0
- package/dist/components/list/list.js +246 -324
- package/dist/components/list/list.js.map +1 -1
- package/dist/components/option-card/option-card.js +121 -117
- package/dist/components/option-card/option-card.js.map +1 -1
- package/dist/components/pill/pill.js +7 -7
- package/dist/components/popover/popover.js +223 -127
- package/dist/components/popover/popover.js.map +1 -1
- package/dist/components/radio/radio-group-base.js +54 -0
- package/dist/components/radio/radio-group-base.js.map +1 -0
- package/dist/components/radio/radio.js +71 -60
- package/dist/components/radio/radio.js.map +1 -1
- package/dist/components/scroll-area/scroll-area.js +142 -108
- package/dist/components/scroll-area/scroll-area.js.map +1 -1
- package/dist/components/scroll-overflow/scroll-overflow.js +156 -127
- package/dist/components/scroll-overflow/scroll-overflow.js.map +1 -1
- package/dist/components/segmented-control/segmented-control.js +93 -81
- package/dist/components/segmented-control/segmented-control.js.map +1 -1
- package/dist/components/select/select.js +485 -310
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/separator/separator.js.map +1 -1
- package/dist/components/slot/compose-as-child.js +15 -12
- package/dist/components/slot/compose-as-child.js.map +1 -1
- package/dist/components/switch/switch.js +75 -68
- package/dist/components/switch/switch.js.map +1 -1
- package/dist/components/table/table-pagination.js +212 -175
- package/dist/components/table/table-pagination.js.map +1 -1
- package/dist/components/tabs/tabs.js +193 -190
- package/dist/components/tabs/tabs.js.map +1 -1
- package/dist/components/toast/toast.js +610 -148
- package/dist/components/toast/toast.js.map +1 -1
- package/dist/components/toggle/toggle-group.js +143 -32
- package/dist/components/toggle/toggle-group.js.map +1 -1
- package/dist/components/toggle/toggle.js +83 -53
- package/dist/components/toggle/toggle.js.map +1 -1
- package/dist/components/tooltip/tooltip.js +298 -138
- package/dist/components/tooltip/tooltip.js.map +1 -1
- package/dist/index.d.ts +2335 -2129
- package/dist/index.js +24 -23
- package/dist/list/sortable/index.d.ts +29 -0
- package/dist/list/sortable/index.js +5 -0
- package/dist/{_virtual → list/sortable}/index.js.map +1 -1
- package/dist/packages/tokens/dist/delivery/index.js +10 -10
- package/dist/packages/tokens/dist/delivery/index.js.map +1 -1
- package/dist/packages/tokens/dist/generated/core.generated.js +6 -15
- package/dist/packages/tokens/dist/generated/core.generated.js.map +1 -1
- package/dist/packages/tokens/dist/generated/palette.generated.js +4 -5
- package/dist/packages/tokens/dist/generated/palette.generated.js.map +1 -1
- package/dist/packages/tokens/dist/generated/palette.meta.generated.js +5 -0
- package/dist/packages/tokens/dist/generated/palette.meta.generated.js.map +1 -0
- package/dist/packages/tokens/dist/install.js +40 -17
- package/dist/packages/tokens/dist/install.js.map +1 -1
- package/dist/renderer/runtime-contract.generated.js +8 -0
- package/dist/renderer/runtime-contract.generated.js.map +1 -0
- package/dist/renderer/served.js +34 -0
- package/dist/renderer/served.js.map +1 -0
- package/dist/tokens/core.meta.generated.js +2 -2
- package/dist/tokens/core.meta.generated.js.map +1 -1
- package/dist/tokens/index.d.ts +1028 -1028
- package/dist/tokens/index.js +863 -863
- package/dist/tokens/index.js.map +1 -1
- package/dist/tokens/palette.meta.generated.js +5 -0
- package/dist/tokens/palette.meta.generated.js.map +1 -0
- package/dist/tokens.json +1 -1
- package/dist/vendor/.bun/@radix-ui_react-dialog@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-dialog/dist/index.js +57 -62
- package/dist/vendor/.bun/@radix-ui_react-dialog@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-dialog/dist/index.js.map +1 -1
- package/dist/vendor/.bun/@radix-ui_react-slot@1.2.3_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js +32 -38
- package/dist/vendor/.bun/@radix-ui_react-slot@1.2.3_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js.map +1 -1
- package/package.json +28 -21
- package/scripts/migration-diagnostics-core.mjs +18 -10
- package/scripts/migration-diagnostics.mjs +31 -8
- package/dist/_virtual/index.js +0 -6
- package/dist/_virtual/index2.js +0 -5
- package/dist/_virtual/index2.js.map +0 -1
- package/dist/_virtual/use-sync-external-store-shim.development.js +0 -5
- package/dist/_virtual/use-sync-external-store-shim.development.js.map +0 -1
- package/dist/_virtual/use-sync-external-store-shim.production.js +0 -5
- package/dist/_virtual/use-sync-external-store-shim.production.js.map +0 -1
- package/dist/tokens/palette.generated.js +0 -5
- package/dist/tokens/palette.generated.js.map +0 -1
- package/dist/vendor/.bun/@floating-ui_core@1.8.0/vendor/@floating-ui/core/dist/floating-ui.core.js +0 -512
- package/dist/vendor/.bun/@floating-ui_core@1.8.0/vendor/@floating-ui/core/dist/floating-ui.core.js.map +0 -1
- package/dist/vendor/.bun/@floating-ui_dom@1.8.0/vendor/@floating-ui/dom/dist/floating-ui.dom.js +0 -396
- package/dist/vendor/.bun/@floating-ui_dom@1.8.0/vendor/@floating-ui/dom/dist/floating-ui.dom.js.map +0 -1
- package/dist/vendor/.bun/@floating-ui_react-dom@2.1.9_6f4b9a1cfb20c0ae/vendor/@floating-ui/react-dom/dist/floating-ui.react-dom.js +0 -233
- package/dist/vendor/.bun/@floating-ui_react-dom@2.1.9_6f4b9a1cfb20c0ae/vendor/@floating-ui/react-dom/dist/floating-ui.react-dom.js.map +0 -1
- package/dist/vendor/.bun/@floating-ui_utils@0.2.12/vendor/@floating-ui/utils/dist/floating-ui.utils.dom.js +0 -137
- package/dist/vendor/.bun/@floating-ui_utils@0.2.12/vendor/@floating-ui/utils/dist/floating-ui.utils.dom.js.map +0 -1
- package/dist/vendor/.bun/@floating-ui_utils@0.2.12/vendor/@floating-ui/utils/dist/floating-ui.utils.js +0 -129
- package/dist/vendor/.bun/@floating-ui_utils@0.2.12/vendor/@floating-ui/utils/dist/floating-ui.utils.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_number@1.1.1/vendor/@radix-ui/number/dist/index.js +0 -7
- package/dist/vendor/.bun/@radix-ui_number@1.1.1/vendor/@radix-ui/number/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-accordion@1.2.12_2b23df507bdda662/vendor/@radix-ui/react-accordion/dist/index.js +0 -240
- package/dist/vendor/.bun/@radix-ui_react-accordion@1.2.12_2b23df507bdda662/vendor/@radix-ui/react-accordion/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-alert-dialog@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-alert-dialog/dist/index.js +0 -128
- package/dist/vendor/.bun/@radix-ui_react-alert-dialog@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-alert-dialog/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-arrow@1.1.7_2b23df507bdda662/vendor/@radix-ui/react-arrow/dist/index.js +0 -25
- package/dist/vendor/.bun/@radix-ui_react-arrow@1.1.7_2b23df507bdda662/vendor/@radix-ui/react-arrow/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-avatar@1.1.10_2b23df507bdda662/vendor/@radix-ui/react-avatar/dist/index.js +0 -76
- package/dist/vendor/.bun/@radix-ui_react-avatar@1.1.10_2b23df507bdda662/vendor/@radix-ui/react-avatar/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-checkbox@1.3.3_2b23df507bdda662/vendor/@radix-ui/react-checkbox/dist/index.js +0 -252
- package/dist/vendor/.bun/@radix-ui_react-checkbox@1.3.3_2b23df507bdda662/vendor/@radix-ui/react-checkbox/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-collapsible@1.1.12_2b23df507bdda662/vendor/@radix-ui/react-collapsible/dist/index.js +0 -121
- package/dist/vendor/.bun/@radix-ui_react-collapsible@1.1.12_2b23df507bdda662/vendor/@radix-ui/react-collapsible/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-collection@1.1.7_2b23df507bdda662/vendor/@radix-ui/react-collection/dist/index.js +0 -49
- package/dist/vendor/.bun/@radix-ui_react-collection@1.1.7_2b23df507bdda662/vendor/@radix-ui/react-collection/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-direction@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-direction/dist/index.js +0 -11
- package/dist/vendor/.bun/@radix-ui_react-direction@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-direction/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-dropdown-menu@2.1.16_2b23df507bdda662/vendor/@radix-ui/react-dropdown-menu/dist/index.js +0 -228
- package/dist/vendor/.bun/@radix-ui_react-dropdown-menu@2.1.16_2b23df507bdda662/vendor/@radix-ui/react-dropdown-menu/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-menu@2.1.16_2b23df507bdda662/vendor/@radix-ui/react-menu/dist/index.js +0 -653
- package/dist/vendor/.bun/@radix-ui_react-menu@2.1.16_2b23df507bdda662/vendor/@radix-ui/react-menu/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-popover@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-popover/dist/index.js +0 -244
- package/dist/vendor/.bun/@radix-ui_react-popover@1.1.15_2b23df507bdda662/vendor/@radix-ui/react-popover/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-popper@1.2.8_2b23df507bdda662/vendor/@radix-ui/react-popper/dist/index.js +0 -222
- package/dist/vendor/.bun/@radix-ui_react-popper@1.2.8_2b23df507bdda662/vendor/@radix-ui/react-popper/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-radio-group@1.3.8_2b23df507bdda662/vendor/@radix-ui/react-radio-group/dist/index.js +0 -239
- package/dist/vendor/.bun/@radix-ui_react-radio-group@1.3.8_2b23df507bdda662/vendor/@radix-ui/react-radio-group/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-roving-focus@1.1.11_2b23df507bdda662/vendor/@radix-ui/react-roving-focus/dist/index.js +0 -184
- package/dist/vendor/.bun/@radix-ui_react-roving-focus@1.1.11_2b23df507bdda662/vendor/@radix-ui/react-roving-focus/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-scroll-area@1.2.10_2b23df507bdda662/vendor/@radix-ui/react-scroll-area/dist/index.js +0 -535
- package/dist/vendor/.bun/@radix-ui_react-scroll-area@1.2.10_2b23df507bdda662/vendor/@radix-ui/react-scroll-area/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-select@2.2.6_2b23df507bdda662/vendor/@radix-ui/react-select/dist/index.js +0 -863
- package/dist/vendor/.bun/@radix-ui_react-select@2.2.6_2b23df507bdda662/vendor/@radix-ui/react-select/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-slot@1.2.4_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js +0 -63
- package/dist/vendor/.bun/@radix-ui_react-slot@1.2.4_0ac650c021fb1b59/vendor/@radix-ui/react-slot/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-switch@1.2.6_2b23df507bdda662/vendor/@radix-ui/react-switch/dist/index.js +0 -133
- package/dist/vendor/.bun/@radix-ui_react-switch@1.2.6_2b23df507bdda662/vendor/@radix-ui/react-switch/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-tabs@1.1.13_2b23df507bdda662/vendor/@radix-ui/react-tabs/dist/index.js +0 -164
- package/dist/vendor/.bun/@radix-ui_react-tabs@1.1.13_2b23df507bdda662/vendor/@radix-ui/react-tabs/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-toggle-group@1.1.11_2b23df507bdda662/vendor/@radix-ui/react-toggle-group/dist/index.js +0 -138
- package/dist/vendor/.bun/@radix-ui_react-toggle-group@1.1.11_2b23df507bdda662/vendor/@radix-ui/react-toggle-group/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-toggle@1.1.10_2b23df507bdda662/vendor/@radix-ui/react-toggle/dist/index.js +0 -34
- package/dist/vendor/.bun/@radix-ui_react-toggle@1.1.10_2b23df507bdda662/vendor/@radix-ui/react-toggle/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-tooltip@1.2.8_2b23df507bdda662/vendor/@radix-ui/react-tooltip/dist/index.js +0 -340
- package/dist/vendor/.bun/@radix-ui_react-tooltip@1.2.8_2b23df507bdda662/vendor/@radix-ui/react-tooltip/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-use-is-hydrated@0.1.0_0ac650c021fb1b59/vendor/@radix-ui/react-use-is-hydrated/dist/index.js +0 -16
- package/dist/vendor/.bun/@radix-ui_react-use-is-hydrated@0.1.0_0ac650c021fb1b59/vendor/@radix-ui/react-use-is-hydrated/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-use-previous@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-use-previous/dist/index.js +0 -9
- package/dist/vendor/.bun/@radix-ui_react-use-previous@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-use-previous/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-use-size@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-use-size/dist/index.js +0 -28
- package/dist/vendor/.bun/@radix-ui_react-use-size@1.1.1_0ac650c021fb1b59/vendor/@radix-ui/react-use-size/dist/index.js.map +0 -1
- package/dist/vendor/.bun/@radix-ui_react-visually-hidden@1.2.3_2b23df507bdda662/vendor/@radix-ui/react-visually-hidden/dist/index.js +0 -33
- package/dist/vendor/.bun/@radix-ui_react-visually-hidden@1.2.3_2b23df507bdda662/vendor/@radix-ui/react-visually-hidden/dist/index.js.map +0 -1
- package/dist/vendor/.bun/sonner@2.0.7_6f4b9a1cfb20c0ae/vendor/sonner/dist/index.js +0 -747
- package/dist/vendor/.bun/sonner@2.0.7_6f4b9a1cfb20c0ae/vendor/sonner/dist/index.js.map +0 -1
- package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/cjs/use-sync-external-store-shim.development.js +0 -68
- package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +0 -1
- package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/cjs/use-sync-external-store-shim.production.js +0 -56
- package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +0 -1
- package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/shim/index.js +0 -11
- package/dist/vendor/.bun/use-sync-external-store@1.7.0_62547eec5a2188e3/vendor/use-sync-external-store/shim/index.js.map +0 -1
|
@@ -0,0 +1,910 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers shared by the structural base-elements rules: build parts, move props between
|
|
3
|
+
* elements, and rewrite MUI's `(event, value)` handlers into the value-only callbacks Zenith's
|
|
4
|
+
* primitives take. Not a rule: the registry does not list it.
|
|
5
|
+
*/
|
|
6
|
+
import type {
|
|
7
|
+
ASTNode,
|
|
8
|
+
ASTPath,
|
|
9
|
+
JSCodeshift,
|
|
10
|
+
JSXAttribute,
|
|
11
|
+
JSXElement,
|
|
12
|
+
JSXSpreadAttribute,
|
|
13
|
+
} from "jscodeshift"
|
|
14
|
+
import { detectQuote } from "../lib/source"
|
|
15
|
+
import type { MigrateContext } from "../lib/types"
|
|
16
|
+
|
|
17
|
+
export type Child = NonNullable<JSXElement["children"]>[number]
|
|
18
|
+
type Expression = Parameters<JSCodeshift["expressionStatement"]>[0]
|
|
19
|
+
type Fn = {
|
|
20
|
+
type: string
|
|
21
|
+
params: { type: string; name?: string; typeAnnotation?: unknown }[]
|
|
22
|
+
body: ASTNode
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Source text of a node as it prints now (its original text when unchanged). */
|
|
26
|
+
export function source(j: JSCodeshift, node: ASTNode): string {
|
|
27
|
+
return j(node as never).toSource()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Parses `code` into an expression that prints as written: recast reuses the text of parsed
|
|
32
|
+
* nodes, where it would lay out a built `{ width: "100%" }` over three lines.
|
|
33
|
+
*/
|
|
34
|
+
export function parseExpression(j: JSCodeshift, code: string): Expression {
|
|
35
|
+
const declarator = j(`const value = ${code}`)
|
|
36
|
+
.find(j.VariableDeclarator)
|
|
37
|
+
.paths()[0]
|
|
38
|
+
return declarator.node.init as Expression
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** A string literal in the file's own quote style, for expressions (JSX attributes use `"`). */
|
|
42
|
+
export function stringIn(ctx: MigrateContext, value: string) {
|
|
43
|
+
return ctx.jsx.str(
|
|
44
|
+
value,
|
|
45
|
+
detectQuote(ctx.file.source) === "single" ? "'" : '"'
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* A JSX element that was an expression root (`return (<X />)`) keeps recast's `parenthesized`
|
|
51
|
+
* mark; among JSX children those parentheses would print as text.
|
|
52
|
+
*/
|
|
53
|
+
function unparenthesize(children: Child[]): Child[] {
|
|
54
|
+
for (const child of children) {
|
|
55
|
+
const extra = (child as { extra?: { parenthesized?: boolean } }).extra
|
|
56
|
+
if (extra?.parenthesized) extra.parenthesized = false
|
|
57
|
+
}
|
|
58
|
+
return children
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** `<tag {...attrs}>{children}</tag>`, self-closing when there are no children. */
|
|
62
|
+
export function element(
|
|
63
|
+
j: JSCodeshift,
|
|
64
|
+
tag: string,
|
|
65
|
+
attrs: (JSXAttribute | JSXSpreadAttribute)[] = [],
|
|
66
|
+
children: Child[] = []
|
|
67
|
+
): JSXElement {
|
|
68
|
+
const name = j.jsxIdentifier(tag)
|
|
69
|
+
if (children.length === 0)
|
|
70
|
+
return j.jsxElement(j.jsxOpeningElement(name, attrs, true), null, [])
|
|
71
|
+
return j.jsxElement(
|
|
72
|
+
j.jsxOpeningElement(name, attrs),
|
|
73
|
+
j.jsxClosingElement(j.jsxIdentifier(tag)),
|
|
74
|
+
unparenthesize(normalizeChildren(j, children))
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Re-splits text children so recast keeps them when it reprints the element: it trims every
|
|
80
|
+
* text child, which would drop the space in `<b>x</b> world`. A line break becomes its own
|
|
81
|
+
* `"\n"` text (recast indents it) and a significant edge space becomes `{" "}`.
|
|
82
|
+
*/
|
|
83
|
+
export function normalizeChildren(j: JSCodeshift, children: Child[]): Child[] {
|
|
84
|
+
const out: Child[] = []
|
|
85
|
+
const lineBreak = () => {
|
|
86
|
+
const prev = out[out.length - 1]
|
|
87
|
+
if (!(prev?.type === "JSXText" && prev.value === "\n"))
|
|
88
|
+
out.push(j.jsxText("\n"))
|
|
89
|
+
}
|
|
90
|
+
const space = () => out.push(j.jsxExpressionContainer(j.stringLiteral(" ")))
|
|
91
|
+
for (const child of children) {
|
|
92
|
+
if (child.type !== "JSXText") {
|
|
93
|
+
out.push(child)
|
|
94
|
+
continue
|
|
95
|
+
}
|
|
96
|
+
if (!/\S/.test(child.value)) {
|
|
97
|
+
if (child.value.includes("\n")) lineBreak()
|
|
98
|
+
else out.push(child)
|
|
99
|
+
continue
|
|
100
|
+
}
|
|
101
|
+
const [, lead, body, trail] = child.value.match(/^(\s*)([\s\S]*?)(\s*)$/)!
|
|
102
|
+
if (lead.includes("\n")) lineBreak()
|
|
103
|
+
else if (lead) space()
|
|
104
|
+
out.push(j.jsxText(body))
|
|
105
|
+
if (trail.includes("\n")) lineBreak()
|
|
106
|
+
else if (trail) space()
|
|
107
|
+
}
|
|
108
|
+
return out
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/** Whether the children span lines (any text child holds a line break). */
|
|
112
|
+
export function isMultiline(children: Child[] | undefined): boolean {
|
|
113
|
+
return (children ?? []).some(
|
|
114
|
+
(c) => c.type === "JSXText" && c.value.includes("\n")
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Sets the element's children, opening it up when it was self-closing. When the new array is
|
|
120
|
+
* as long as the parsed one, recast patches it slot by slot and loses the indentation of the
|
|
121
|
+
* new line breaks; an empty text child (it prints as nothing) makes it reprint the element.
|
|
122
|
+
*/
|
|
123
|
+
export function setChildren(
|
|
124
|
+
j: JSCodeshift,
|
|
125
|
+
el: JSXElement,
|
|
126
|
+
children: Child[]
|
|
127
|
+
): void {
|
|
128
|
+
const parsed = (el as { original?: JSXElement | null }).original
|
|
129
|
+
if (children.length && parsed?.children?.length === children.length)
|
|
130
|
+
children = [...children, j.jsxText("")]
|
|
131
|
+
el.children = children
|
|
132
|
+
if (children.length === 0) {
|
|
133
|
+
el.openingElement.selfClosing = true
|
|
134
|
+
el.closingElement = null
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
el.openingElement.selfClosing = false
|
|
138
|
+
if (!el.closingElement)
|
|
139
|
+
el.closingElement = j.jsxClosingElement(el.openingElement.name)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/** `[child]`, or `["\n", child, "\n"]` when the surrounding children spanned lines. */
|
|
143
|
+
export function onlyChild(
|
|
144
|
+
j: JSCodeshift,
|
|
145
|
+
child: Child,
|
|
146
|
+
multiline: boolean
|
|
147
|
+
): Child[] {
|
|
148
|
+
return multiline ? [j.jsxText("\n"), child, j.jsxText("\n")] : [child]
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** Moves `el`'s children into a new `<tag {...attrs}>`, which becomes `el`'s only child. */
|
|
152
|
+
export function nestChildren(
|
|
153
|
+
j: JSCodeshift,
|
|
154
|
+
el: JSXElement,
|
|
155
|
+
tag: string,
|
|
156
|
+
attrs: (JSXAttribute | JSXSpreadAttribute)[] = []
|
|
157
|
+
): JSXElement {
|
|
158
|
+
const multiline = isMultiline(el.children)
|
|
159
|
+
const inner = element(j, tag, attrs, el.children ?? [])
|
|
160
|
+
setChildren(j, el, onlyChild(j, inner, multiline))
|
|
161
|
+
return inner
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Adds `child` first or last, on its own line when the element's children span lines. */
|
|
165
|
+
export function insertChild(
|
|
166
|
+
j: JSCodeshift,
|
|
167
|
+
el: JSXElement,
|
|
168
|
+
child: Child,
|
|
169
|
+
at: "start" | "end"
|
|
170
|
+
): void {
|
|
171
|
+
const multiline = isMultiline(el.children)
|
|
172
|
+
const children = normalizeChildren(j, el.children ?? [])
|
|
173
|
+
const nl = () => j.jsxText("\n")
|
|
174
|
+
if (children.length === 0) setChildren(j, el, [child])
|
|
175
|
+
else if (!multiline)
|
|
176
|
+
setChildren(
|
|
177
|
+
j,
|
|
178
|
+
el,
|
|
179
|
+
at === "start" ? [child, ...children] : [...children, child]
|
|
180
|
+
)
|
|
181
|
+
else if (at === "start") setChildren(j, el, [nl(), child, ...children])
|
|
182
|
+
else setChildren(j, el, [...children, child, nl()])
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/** Maps a string literal, or a conditional whose branches are string literals, through `map`. */
|
|
186
|
+
export function mapStringExpression(
|
|
187
|
+
j: JSCodeshift,
|
|
188
|
+
expression: Expression | undefined,
|
|
189
|
+
map: (value: string) => string | undefined,
|
|
190
|
+
literal: (value: string) => Expression = (value) => j.stringLiteral(value)
|
|
191
|
+
): Expression | undefined {
|
|
192
|
+
if (!expression) return undefined
|
|
193
|
+
if (
|
|
194
|
+
expression.type === "StringLiteral" ||
|
|
195
|
+
(expression.type === "Literal" &&
|
|
196
|
+
typeof (expression as { value: unknown }).value === "string")
|
|
197
|
+
) {
|
|
198
|
+
const next = map(String((expression as { value: unknown }).value))
|
|
199
|
+
return next === undefined ? undefined : literal(next)
|
|
200
|
+
}
|
|
201
|
+
if (expression.type === "ConditionalExpression") {
|
|
202
|
+
const consequent = mapStringExpression(
|
|
203
|
+
j,
|
|
204
|
+
expression.consequent,
|
|
205
|
+
map,
|
|
206
|
+
literal
|
|
207
|
+
)
|
|
208
|
+
const alternate = mapStringExpression(j, expression.alternate, map, literal)
|
|
209
|
+
if (!consequent || !alternate) return undefined
|
|
210
|
+
return j.conditionalExpression(
|
|
211
|
+
expression.test,
|
|
212
|
+
consequent as never,
|
|
213
|
+
alternate as never
|
|
214
|
+
)
|
|
215
|
+
}
|
|
216
|
+
return undefined
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* `jsx.mapAttrValue` (literals and ternaries of literals) with a Zenith default and a rename: a
|
|
221
|
+
* value mapping to `fallback` drops the attribute (`undefined` in a ternary), and a mapped
|
|
222
|
+
* attribute takes the name `rename`, replacing one of that name. Returns `false`, leaving the
|
|
223
|
+
* attribute as it was, when the value is dynamic or unmapped (the caller reports it); `true`
|
|
224
|
+
* when mapped or absent.
|
|
225
|
+
*/
|
|
226
|
+
export function mapAttr(
|
|
227
|
+
ctx: MigrateContext,
|
|
228
|
+
el: JSXElement,
|
|
229
|
+
name: string,
|
|
230
|
+
map: Readonly<Record<string, string>>,
|
|
231
|
+
{ rename = name, fallback }: { rename?: string; fallback?: string } = {}
|
|
232
|
+
): boolean {
|
|
233
|
+
const table: Record<string, string | null> = {}
|
|
234
|
+
for (const [key, value] of Object.entries(map))
|
|
235
|
+
table[key] = value === fallback ? null : value
|
|
236
|
+
const result = ctx.jsx.mapAttrValue(el, name, table)
|
|
237
|
+
if (result === "dynamic" || result === "unknown") return false
|
|
238
|
+
if (result === "mapped" && rename !== name && ctx.jsx.attr(el, name)) {
|
|
239
|
+
ctx.jsx.removeAttr(el, rename)
|
|
240
|
+
ctx.jsx.renameAttr(el, name, rename)
|
|
241
|
+
}
|
|
242
|
+
return true
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* MUI's ButtonBase renders `type="button"` unless told otherwise; a Zenith Button renders a
|
|
247
|
+
* bare `<button>`, which submits its form. Adds `type="button"` to an element that renders a
|
|
248
|
+
* native button and has no `type`, ahead of any spread so a spread `type` still wins.
|
|
249
|
+
*/
|
|
250
|
+
export function defaultButtonType(ctx: MigrateContext, el: JSXElement): void {
|
|
251
|
+
if (ctx.jsx.attr(el, "type") || ctx.jsx.attr(el, "asChild")) return
|
|
252
|
+
el.openingElement.attributes = [
|
|
253
|
+
ctx.j.jsxAttribute(ctx.j.jsxIdentifier("type"), ctx.jsx.str("button")),
|
|
254
|
+
...(el.openingElement.attributes ?? []),
|
|
255
|
+
]
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/** Children that are not whitespace-only text. */
|
|
259
|
+
export function contentChildren(el: JSXElement): Child[] {
|
|
260
|
+
return (el.children ?? []).filter(
|
|
261
|
+
(c) => !(c.type === "JSXText" && !c.value.trim())
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** Removes the named attributes and returns those present, in source order. */
|
|
266
|
+
export function takeAttrs(
|
|
267
|
+
ctx: MigrateContext,
|
|
268
|
+
el: JSXElement,
|
|
269
|
+
names: readonly string[]
|
|
270
|
+
): JSXAttribute[] {
|
|
271
|
+
const taken = ctx.jsx
|
|
272
|
+
.attrs(el)
|
|
273
|
+
.filter((a) => names.includes(ctx.jsx.attrName(a)))
|
|
274
|
+
for (const a of taken) ctx.jsx.removeAttr(el, ctx.jsx.attrName(a))
|
|
275
|
+
return taken
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/** Removes every attribute not in `keep` (spreads stay) and returns the removed ones. */
|
|
279
|
+
export function takeAttrsExcept(
|
|
280
|
+
ctx: MigrateContext,
|
|
281
|
+
el: JSXElement,
|
|
282
|
+
keep: (name: string) => boolean
|
|
283
|
+
): JSXAttribute[] {
|
|
284
|
+
const names = ctx.jsx
|
|
285
|
+
.attrs(el)
|
|
286
|
+
.map((a) => ctx.jsx.attrName(a))
|
|
287
|
+
.filter((n) => !keep(n))
|
|
288
|
+
return takeAttrs(ctx, el, names)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* One attribute as printed source, for a TODO message, which is one report line: a multi-line
|
|
293
|
+
* value is collapsed onto one line, a very long one prints as `name={…}`.
|
|
294
|
+
*/
|
|
295
|
+
export function printAttr(ctx: MigrateContext, a: JSXAttribute): string {
|
|
296
|
+
// One line, so the report stays one line per TODO; long values abbreviate (the diff has them).
|
|
297
|
+
const printed = ctx.jsx.print(a).replace(/\s*\n\s*/g, " ")
|
|
298
|
+
if (printed.length <= 160) return printed
|
|
299
|
+
return `${ctx.jsx.attrName(a)}={…}`
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/** `a={b} c="d"`: attributes as printed source, for a TODO message. */
|
|
303
|
+
export function printAttrs(
|
|
304
|
+
ctx: MigrateContext,
|
|
305
|
+
attrs: readonly JSXAttribute[]
|
|
306
|
+
): string {
|
|
307
|
+
return attrs.map((a) => printAttr(ctx, a)).join(" ")
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** The expression inside `name={…}`, or `undefined` for a string or bare attribute. */
|
|
311
|
+
export function attrExpression(
|
|
312
|
+
a: JSXAttribute | undefined
|
|
313
|
+
): Expression | undefined {
|
|
314
|
+
const v = a?.value
|
|
315
|
+
if (v?.type !== "JSXExpressionContainer") return undefined
|
|
316
|
+
if (v.expression.type === "JSXEmptyExpression") return undefined
|
|
317
|
+
return v.expression as Expression
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/** The value of an attribute as an expression: `"x"` → `"x"`, `{e}` → `e`, bare → `true`. */
|
|
321
|
+
export function attrValue(j: JSCodeshift, a: JSXAttribute): Expression {
|
|
322
|
+
const v = a.value
|
|
323
|
+
if (v == null) return j.booleanLiteral(true)
|
|
324
|
+
if (v.type === "JSXExpressionContainer")
|
|
325
|
+
return v.expression as unknown as Expression
|
|
326
|
+
if (v.type === "StringLiteral" || v.type === "Literal")
|
|
327
|
+
return j.stringLiteral(String(v.value))
|
|
328
|
+
return v as unknown as Expression
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/** A copy of `a` under a new name (the value node is shared, the attribute is not). */
|
|
332
|
+
export function renamedAttr(
|
|
333
|
+
j: JSCodeshift,
|
|
334
|
+
a: JSXAttribute,
|
|
335
|
+
name: string
|
|
336
|
+
): JSXAttribute {
|
|
337
|
+
return j.jsxAttribute(j.jsxIdentifier(name), a.value)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
/** Whether an attribute is `name`, `name={true}` (a literal `true`). */
|
|
341
|
+
export function isTrue(ctx: MigrateContext, a: JSXAttribute | undefined) {
|
|
342
|
+
return ctx.jsx.literal(a) === true
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** The nearest JSX element ancestor whose tag is `tag`. */
|
|
346
|
+
export function closestElement(
|
|
347
|
+
path: ASTPath,
|
|
348
|
+
tag: string
|
|
349
|
+
): ASTPath<JSXElement> | undefined {
|
|
350
|
+
let current = path.parent as ASTPath | null
|
|
351
|
+
while (current) {
|
|
352
|
+
const node = current.node as JSXElement
|
|
353
|
+
if (
|
|
354
|
+
node.type === "JSXElement" &&
|
|
355
|
+
node.openingElement.name.type === "JSXIdentifier" &&
|
|
356
|
+
node.openingElement.name.name === tag
|
|
357
|
+
)
|
|
358
|
+
return current as ASTPath<JSXElement>
|
|
359
|
+
current = current.parent
|
|
360
|
+
}
|
|
361
|
+
return undefined
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** Whether `path` sits among JSX children, where an element may be replaced by `{expr}`. */
|
|
365
|
+
export function inJsxChildren(path: ASTPath): boolean {
|
|
366
|
+
const parent = path.parent?.node as { type?: string } | undefined
|
|
367
|
+
return parent?.type === "JSXElement" || parent?.type === "JSXFragment"
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/** `cond && <el />`, as a JSX child `{…}` or as a plain expression elsewhere. */
|
|
371
|
+
export function renderWhen(
|
|
372
|
+
j: JSCodeshift,
|
|
373
|
+
path: ASTPath<JSXElement>,
|
|
374
|
+
condition: Expression,
|
|
375
|
+
el: JSXElement
|
|
376
|
+
): void {
|
|
377
|
+
const expression = j.logicalExpression("&&", condition as never, el)
|
|
378
|
+
path.replace(
|
|
379
|
+
inJsxChildren(path) ? j.jsxExpressionContainer(expression) : expression
|
|
380
|
+
)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/** The names an expression references or declares, to pick a fresh parameter name. */
|
|
384
|
+
function namesIn(j: JSCodeshift, node: ASTNode): Set<string> {
|
|
385
|
+
const names = new Set<string>()
|
|
386
|
+
j(node as never)
|
|
387
|
+
.find(j.Identifier)
|
|
388
|
+
.forEach((p) => {
|
|
389
|
+
const parent = p.parent?.node
|
|
390
|
+
const property =
|
|
391
|
+
(parent?.type === "MemberExpression" ||
|
|
392
|
+
parent?.type === "OptionalMemberExpression") &&
|
|
393
|
+
parent.property === p.node &&
|
|
394
|
+
!parent.computed
|
|
395
|
+
if (!property) names.add(p.node.name)
|
|
396
|
+
})
|
|
397
|
+
return names
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export function freshName(
|
|
401
|
+
j: JSCodeshift,
|
|
402
|
+
node: ASTNode,
|
|
403
|
+
preferred: string
|
|
404
|
+
): string {
|
|
405
|
+
const taken = namesIn(j, node)
|
|
406
|
+
if (!taken.has(preferred)) return preferred
|
|
407
|
+
const next = `next${preferred[0].toUpperCase()}${preferred.slice(1)}`
|
|
408
|
+
if (!taken.has(next)) return next
|
|
409
|
+
let i = 2
|
|
410
|
+
while (taken.has(`${preferred}${i}`)) i += 1
|
|
411
|
+
return `${preferred}${i}`
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
function isFunction(node: ASTNode | undefined): node is ASTNode & Fn {
|
|
415
|
+
return (
|
|
416
|
+
!!node &&
|
|
417
|
+
(node.type === "ArrowFunctionExpression" ||
|
|
418
|
+
node.type === "FunctionExpression")
|
|
419
|
+
)
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/** Identifier paths in `fn`'s body that reference the binding `name` (keys excluded). */
|
|
423
|
+
function references(
|
|
424
|
+
j: JSCodeshift,
|
|
425
|
+
fn: Fn,
|
|
426
|
+
name: string
|
|
427
|
+
): ASTPath<ASTNode & { name: string }>[] {
|
|
428
|
+
return j(fn.body as never)
|
|
429
|
+
.find(j.Identifier, { name })
|
|
430
|
+
.filter((p) => {
|
|
431
|
+
const parent = p.parent.node
|
|
432
|
+
if (
|
|
433
|
+
(parent.type === "MemberExpression" ||
|
|
434
|
+
parent.type === "OptionalMemberExpression") &&
|
|
435
|
+
parent.property === p.node &&
|
|
436
|
+
!parent.computed
|
|
437
|
+
)
|
|
438
|
+
return false
|
|
439
|
+
if (
|
|
440
|
+
(parent.type === "ObjectProperty" || parent.type === "Property") &&
|
|
441
|
+
parent.key === p.node &&
|
|
442
|
+
!parent.computed &&
|
|
443
|
+
!parent.shorthand
|
|
444
|
+
)
|
|
445
|
+
return false
|
|
446
|
+
return true
|
|
447
|
+
})
|
|
448
|
+
.paths() as never
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/** `event.target.<prop>` / `event.currentTarget.<prop>` around a reference path, if it is one. */
|
|
452
|
+
function targetRead(path: ASTPath, prop: string): ASTPath | undefined {
|
|
453
|
+
const inner = path.parent
|
|
454
|
+
const n = inner?.node
|
|
455
|
+
if (
|
|
456
|
+
!n ||
|
|
457
|
+
n.type !== "MemberExpression" ||
|
|
458
|
+
n.object !== path.node ||
|
|
459
|
+
n.computed ||
|
|
460
|
+
n.property.type !== "Identifier" ||
|
|
461
|
+
(n.property.name !== "target" && n.property.name !== "currentTarget")
|
|
462
|
+
)
|
|
463
|
+
return undefined
|
|
464
|
+
const outer = inner.parent
|
|
465
|
+
const m = outer?.node
|
|
466
|
+
if (
|
|
467
|
+
!m ||
|
|
468
|
+
m.type !== "MemberExpression" ||
|
|
469
|
+
m.object !== n ||
|
|
470
|
+
m.computed ||
|
|
471
|
+
m.property.type !== "Identifier" ||
|
|
472
|
+
m.property.name !== prop
|
|
473
|
+
)
|
|
474
|
+
return undefined
|
|
475
|
+
return outer
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
export type ValueHandlerOptions = {
|
|
479
|
+
/** What MUI's handler read from the event: `event.target.<prop>` becomes the value. */
|
|
480
|
+
targetProp?: string
|
|
481
|
+
/** Preferred name for the value parameter when the handler had none. */
|
|
482
|
+
valueName: string
|
|
483
|
+
/** Wraps every read of the value (`checked` → `checked === true` for a tri-state checkbox). */
|
|
484
|
+
mapValue?: (value: Expression) => Expression
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Rewrites MUI's `(event, value) => …` into `(value) => …`, for an inline arrow or function
|
|
489
|
+
* whose event parameter is unused or read only as `event.target.<targetProp>`. Returns the
|
|
490
|
+
* rewritten function, or `undefined` for any other shape (a handler reference, a used event):
|
|
491
|
+
* the caller reports a TODO.
|
|
492
|
+
*/
|
|
493
|
+
export function valueHandler(
|
|
494
|
+
j: JSCodeshift,
|
|
495
|
+
expression: Expression | undefined,
|
|
496
|
+
options: ValueHandlerOptions
|
|
497
|
+
): Expression | undefined {
|
|
498
|
+
// `((_, v: T) => …) as never` only quietened MUI's handler type: unwrap the cast.
|
|
499
|
+
while (
|
|
500
|
+
expression &&
|
|
501
|
+
(expression.type === "TSAsExpression" ||
|
|
502
|
+
expression.type === "TSSatisfiesExpression" ||
|
|
503
|
+
expression.type === "TSNonNullExpression")
|
|
504
|
+
)
|
|
505
|
+
expression = expression.expression as Expression
|
|
506
|
+
if (!isFunction(expression as ASTNode)) return undefined
|
|
507
|
+
const fn = expression as unknown as Fn
|
|
508
|
+
const [event, value, ...rest] = fn.params
|
|
509
|
+
if (rest.length) return undefined
|
|
510
|
+
if (event && event.type !== "Identifier") return undefined
|
|
511
|
+
if (value && value.type !== "Identifier") return undefined
|
|
512
|
+
|
|
513
|
+
const eventReads: ASTPath[] = []
|
|
514
|
+
if (event) {
|
|
515
|
+
for (const ref of references(j, fn, event.name!)) {
|
|
516
|
+
const read = options.targetProp
|
|
517
|
+
? targetRead(ref, options.targetProp)
|
|
518
|
+
: undefined
|
|
519
|
+
if (!read) return undefined
|
|
520
|
+
eventReads.push(read)
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
const valueName = value
|
|
525
|
+
? value.name!
|
|
526
|
+
: freshName(j, fn.body, options.valueName)
|
|
527
|
+
// A narrower annotation than the primitive passes (`v: "a" | "b"`) becomes a cast at each
|
|
528
|
+
// read, since the parameter itself must accept what Zenith passes.
|
|
529
|
+
const annotation = (
|
|
530
|
+
value?.typeAnnotation as { typeAnnotation?: ASTNode } | undefined
|
|
531
|
+
)?.typeAnnotation
|
|
532
|
+
const cast =
|
|
533
|
+
annotation &&
|
|
534
|
+
!["TSStringKeyword", "TSBooleanKeyword", "TSAnyKeyword"].includes(
|
|
535
|
+
annotation.type
|
|
536
|
+
)
|
|
537
|
+
? source(j, annotation)
|
|
538
|
+
: undefined
|
|
539
|
+
const valueRef = (): Expression =>
|
|
540
|
+
cast
|
|
541
|
+
? parseExpression(j, `${valueName} as ${cast}`)
|
|
542
|
+
: j.identifier(valueName)
|
|
543
|
+
const mapped = () =>
|
|
544
|
+
options.mapValue ? options.mapValue(valueRef()) : valueRef()
|
|
545
|
+
|
|
546
|
+
if (value && (options.mapValue || cast))
|
|
547
|
+
for (const ref of references(j, fn, valueName)) ref.replace(mapped())
|
|
548
|
+
for (const read of eventReads) read.replace(mapped())
|
|
549
|
+
|
|
550
|
+
// Rebuilt from source text so the parameter keeps its parentheses and the body its layout.
|
|
551
|
+
const params = event || value ? valueName : ""
|
|
552
|
+
const body = source(j, fn.body)
|
|
553
|
+
return parseExpression(
|
|
554
|
+
j,
|
|
555
|
+
fn.type === "ArrowFunctionExpression"
|
|
556
|
+
? `(${params}) => ${body}`
|
|
557
|
+
: `function (${params}) ${body}`
|
|
558
|
+
)
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
/**
|
|
562
|
+
* `onClose={fn}` → `(open) => { if (!open) fn() }`: MUI's close callback as a Radix
|
|
563
|
+
* `onOpenChange`. Inline functions must take no parameters (their body moves under the
|
|
564
|
+
* `if`); a reference is called with no arguments, so a handler that needs MUI's
|
|
565
|
+
* `(event, reason)` fails the typecheck instead of silently changing. `undefined` for other
|
|
566
|
+
* shapes.
|
|
567
|
+
*/
|
|
568
|
+
export function closeAsOpenChange(
|
|
569
|
+
j: JSCodeshift,
|
|
570
|
+
expression: Expression | undefined
|
|
571
|
+
): Expression | undefined {
|
|
572
|
+
if (!expression) return undefined
|
|
573
|
+
const open = freshName(j, expression as ASTNode, "open")
|
|
574
|
+
if (isFunction(expression as ASTNode)) {
|
|
575
|
+
const fn = expression as unknown as Fn
|
|
576
|
+
if (fn.params.length) return undefined
|
|
577
|
+
const body = source(j, fn.body)
|
|
578
|
+
return parseExpression(
|
|
579
|
+
j,
|
|
580
|
+
fn.body.type === "BlockStatement"
|
|
581
|
+
? `(${open}) => {\n if (!${open}) ${body.replace(/\n/g, "\n ")}\n}`
|
|
582
|
+
: `(${open}) => { if (!${open}) ${body} }`
|
|
583
|
+
)
|
|
584
|
+
}
|
|
585
|
+
if (
|
|
586
|
+
expression.type === "Identifier" ||
|
|
587
|
+
expression.type === "MemberExpression"
|
|
588
|
+
)
|
|
589
|
+
return parseExpression(
|
|
590
|
+
j,
|
|
591
|
+
`(${open}) => { if (!${open}) ${source(j, expression)}() }`
|
|
592
|
+
)
|
|
593
|
+
return undefined
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Replaces `path`'s element with `<tag {...attrs}>…before, element, …after</tag>` and returns the
|
|
598
|
+
* path of the (original) element inside it, whose source line a TODO can still report.
|
|
599
|
+
*/
|
|
600
|
+
export function wrapElement(
|
|
601
|
+
j: JSCodeshift,
|
|
602
|
+
path: ASTPath<JSXElement>,
|
|
603
|
+
tag: string,
|
|
604
|
+
attrs: JSXAttribute[],
|
|
605
|
+
before: Child[],
|
|
606
|
+
after: Child[]
|
|
607
|
+
): ASTPath<JSXElement> {
|
|
608
|
+
const node = path.node
|
|
609
|
+
const wrapper = element(j, tag, attrs, [...before, node, ...after])
|
|
610
|
+
const [wrapperPath] = path.replace(wrapper) as ASTPath<JSXElement>[]
|
|
611
|
+
return wrapperPath.get("children", wrapper.children!.indexOf(node))
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
export type CheckedControlOptions = {
|
|
615
|
+
/** Radix Checkbox passes `boolean | "indeterminate"`: reads of the value become `=== true`. */
|
|
616
|
+
tristate: boolean
|
|
617
|
+
/** MUI `size` → Zenith `size`; `undefined` drops the prop silently. */
|
|
618
|
+
sizes?: Record<string, string>
|
|
619
|
+
fallbackSize?: string
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
/**
|
|
623
|
+
* Switch / Checkbox: `onChange(event, checked)` → `onCheckedChange(checked)` for inline handlers
|
|
624
|
+
* that read only the second parameter or `event.target.checked`; base-elements' `label` and
|
|
625
|
+
* `labelPlacement` → a wrapping Zenith `<Label>`. Everything else is reported.
|
|
626
|
+
*/
|
|
627
|
+
export function migrateCheckedControl(
|
|
628
|
+
ctx: MigrateContext,
|
|
629
|
+
path: ASTPath<JSXElement>,
|
|
630
|
+
component: string,
|
|
631
|
+
options: CheckedControlOptions
|
|
632
|
+
): void {
|
|
633
|
+
const { j, jsx } = ctx
|
|
634
|
+
const el = path.node
|
|
635
|
+
const reported: string[] = []
|
|
636
|
+
|
|
637
|
+
const onChange = jsx.attr(el, "onChange")
|
|
638
|
+
if (onChange) {
|
|
639
|
+
const handler = valueHandler(j, attrExpression(onChange), {
|
|
640
|
+
targetProp: "checked",
|
|
641
|
+
valueName: "checked",
|
|
642
|
+
mapValue: options.tristate
|
|
643
|
+
? (value) =>
|
|
644
|
+
j.binaryExpression("===", value as never, j.booleanLiteral(true))
|
|
645
|
+
: undefined,
|
|
646
|
+
})
|
|
647
|
+
if (handler) {
|
|
648
|
+
onChange.name = j.jsxIdentifier("onCheckedChange")
|
|
649
|
+
onChange.value = j.jsxExpressionContainer(handler as never)
|
|
650
|
+
} else {
|
|
651
|
+
jsx.removeAttr(el, "onChange")
|
|
652
|
+
reported.push(
|
|
653
|
+
`dropped ${printAttr(ctx, onChange)} (onCheckedChange(checked) passes only the new state${options.tristate ? ', true | false | "indeterminate"' : ""}; call your handler with it)`
|
|
654
|
+
)
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
if (options.tristate) {
|
|
659
|
+
const indeterminate = jsx.removeAttr(el, "indeterminate")
|
|
660
|
+
const checked = jsx.attr(el, "checked")
|
|
661
|
+
if (indeterminate && jsx.literal(indeterminate) !== false) {
|
|
662
|
+
const value = stringIn(ctx, "indeterminate")
|
|
663
|
+
if (isTrue(ctx, indeterminate))
|
|
664
|
+
jsx.setAttr(el, "checked", "indeterminate")
|
|
665
|
+
else
|
|
666
|
+
jsx.setAttr(
|
|
667
|
+
el,
|
|
668
|
+
"checked",
|
|
669
|
+
j.conditionalExpression(
|
|
670
|
+
attrValue(j, indeterminate) as never,
|
|
671
|
+
value as never,
|
|
672
|
+
(checked ? attrValue(j, checked) : j.booleanLiteral(false)) as never
|
|
673
|
+
)
|
|
674
|
+
)
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
if (options.sizes) {
|
|
679
|
+
if (
|
|
680
|
+
!mapAttr(ctx, el, "size", options.sizes, {
|
|
681
|
+
fallback: options.fallbackSize,
|
|
682
|
+
})
|
|
683
|
+
)
|
|
684
|
+
reported.push(
|
|
685
|
+
`dropped ${printAttrs(ctx, takeAttrs(ctx, el, ["size"]))} (size: ${Object.values(options.sizes).join(" | ")})`
|
|
686
|
+
)
|
|
687
|
+
} else takeAttrs(ctx, el, ["size"])
|
|
688
|
+
takeAttrs(ctx, el, ["color", "disableRipple", "disableFocusRipple"])
|
|
689
|
+
|
|
690
|
+
const unsupported = takeAttrs(ctx, el, [
|
|
691
|
+
"inputProps",
|
|
692
|
+
"inputRef",
|
|
693
|
+
"edge",
|
|
694
|
+
"icon",
|
|
695
|
+
"checkedIcon",
|
|
696
|
+
"indeterminateIcon",
|
|
697
|
+
"classes",
|
|
698
|
+
"checkboxPlacement",
|
|
699
|
+
])
|
|
700
|
+
if (unsupported.length)
|
|
701
|
+
reported.push(
|
|
702
|
+
`dropped ${printAttrs(ctx, unsupported)} (no Zenith equivalent)`
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
// Spread props ({...field}, {...register("x")}) carry an onChange that Radix's button root
|
|
706
|
+
// never fires; the checked state has to be wired by hand.
|
|
707
|
+
for (const spread of el.openingElement.attributes ?? [])
|
|
708
|
+
if (spread.type === "JSXSpreadAttribute")
|
|
709
|
+
reported.push(
|
|
710
|
+
`${source(j, spread)} reaches Radix's button root, which never fires onChange: pass checked and onCheckedChange explicitly (react-hook-form: a Controller)`
|
|
711
|
+
)
|
|
712
|
+
|
|
713
|
+
const label = jsx.removeAttr(el, "label")
|
|
714
|
+
const placement = jsx.removeAttr(el, "labelPlacement")
|
|
715
|
+
let todoPath = path
|
|
716
|
+
if (label) {
|
|
717
|
+
const where = placement ? jsx.literal(placement) : "end"
|
|
718
|
+
if (where !== "end" && where !== "start")
|
|
719
|
+
reported.push(
|
|
720
|
+
`dropped ${printAttr(ctx, placement!)} (the Label lays control and text out in a row; stack them yourself)`
|
|
721
|
+
)
|
|
722
|
+
const text = jsx.childFromValue(label)
|
|
723
|
+
const nl = () => j.jsxText("\n")
|
|
724
|
+
todoPath =
|
|
725
|
+
where === "start"
|
|
726
|
+
? wrapElement(
|
|
727
|
+
j,
|
|
728
|
+
path,
|
|
729
|
+
ctx.ensureZenith("Label"),
|
|
730
|
+
[],
|
|
731
|
+
[nl(), text, nl()],
|
|
732
|
+
[nl()]
|
|
733
|
+
)
|
|
734
|
+
: wrapElement(
|
|
735
|
+
j,
|
|
736
|
+
path,
|
|
737
|
+
ctx.ensureZenith("Label"),
|
|
738
|
+
[],
|
|
739
|
+
[nl()],
|
|
740
|
+
[nl(), text, nl()]
|
|
741
|
+
)
|
|
742
|
+
}
|
|
743
|
+
if (reported.length) ctx.todo(todoPath, component, reported.join("; "))
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
/**
|
|
747
|
+
* A close callback as a no-argument one (Callout `onDismiss`, Accordion `onValueChange` reads):
|
|
748
|
+
* a reference as is (the typecheck catches a handler that needs the event), an inline function
|
|
749
|
+
* whose parameters are unused without them. `undefined` when a parameter is read.
|
|
750
|
+
*/
|
|
751
|
+
export function withoutParams(
|
|
752
|
+
j: JSCodeshift,
|
|
753
|
+
expression: Expression | undefined
|
|
754
|
+
): Expression | undefined {
|
|
755
|
+
if (!expression) return undefined
|
|
756
|
+
if (
|
|
757
|
+
expression.type === "Identifier" ||
|
|
758
|
+
expression.type === "MemberExpression"
|
|
759
|
+
)
|
|
760
|
+
return expression
|
|
761
|
+
if (!isFunction(expression as ASTNode)) return undefined
|
|
762
|
+
const fn = expression as unknown as Fn
|
|
763
|
+
if (!fn.params.length) return expression
|
|
764
|
+
for (const param of fn.params) {
|
|
765
|
+
if (param.type !== "Identifier") return undefined
|
|
766
|
+
if (references(j, fn, param.name!).length) return undefined
|
|
767
|
+
}
|
|
768
|
+
const body = source(j, fn.body)
|
|
769
|
+
return parseExpression(
|
|
770
|
+
j,
|
|
771
|
+
fn.type === "ArrowFunctionExpression"
|
|
772
|
+
? `() => ${body}`
|
|
773
|
+
: `function () ${body}`
|
|
774
|
+
)
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/** MUI Alert severity → Callout variant. */
|
|
778
|
+
export const SEVERITY: Record<string, string> = {
|
|
779
|
+
success: "success",
|
|
780
|
+
info: "info",
|
|
781
|
+
warning: "warning",
|
|
782
|
+
error: "destructive",
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
export type CalloutParts = {
|
|
786
|
+
title?: JSXAttribute
|
|
787
|
+
/** Children of CalloutDescription. */
|
|
788
|
+
description: Child[]
|
|
789
|
+
/** `onClose` → `dismissible onDismiss`. */
|
|
790
|
+
onClose?: JSXAttribute
|
|
791
|
+
/** `action` → a trailing CalloutAction. */
|
|
792
|
+
action?: JSXAttribute
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Fills a Callout element in place: title and description parts, a dismiss handler and an
|
|
797
|
+
* action. Returns what it could not carry over, for the caller's TODO.
|
|
798
|
+
*/
|
|
799
|
+
export function fillCallout(
|
|
800
|
+
ctx: MigrateContext,
|
|
801
|
+
el: JSXElement,
|
|
802
|
+
parts: CalloutParts
|
|
803
|
+
): string[] {
|
|
804
|
+
const { j, jsx } = ctx
|
|
805
|
+
const reported: string[] = []
|
|
806
|
+
const children: Child[] = []
|
|
807
|
+
const nl = () => j.jsxText("\n")
|
|
808
|
+
if (parts.title)
|
|
809
|
+
children.push(
|
|
810
|
+
nl(),
|
|
811
|
+
element(
|
|
812
|
+
j,
|
|
813
|
+
ctx.ensureZenith("CalloutTitle"),
|
|
814
|
+
[],
|
|
815
|
+
[jsx.childFromValue(parts.title)]
|
|
816
|
+
)
|
|
817
|
+
)
|
|
818
|
+
const description = parts.description.filter(
|
|
819
|
+
(c) => !(c.type === "JSXText" && !c.value.trim())
|
|
820
|
+
)
|
|
821
|
+
if (description.length)
|
|
822
|
+
children.push(
|
|
823
|
+
nl(),
|
|
824
|
+
element(j, ctx.ensureZenith("CalloutDescription"), [], parts.description)
|
|
825
|
+
)
|
|
826
|
+
if (parts.action)
|
|
827
|
+
children.push(
|
|
828
|
+
nl(),
|
|
829
|
+
element(
|
|
830
|
+
j,
|
|
831
|
+
ctx.ensureZenith("CalloutAction"),
|
|
832
|
+
[],
|
|
833
|
+
[jsx.childFromValue(parts.action)]
|
|
834
|
+
)
|
|
835
|
+
)
|
|
836
|
+
if (children.length) children.push(nl())
|
|
837
|
+
setChildren(j, el, children)
|
|
838
|
+
|
|
839
|
+
if (parts.onClose) {
|
|
840
|
+
const handler = withoutParams(j, attrExpression(parts.onClose))
|
|
841
|
+
if (handler) {
|
|
842
|
+
jsx.setAttr(el, "dismissible", null)
|
|
843
|
+
jsx.setAttr(el, "onDismiss", handler)
|
|
844
|
+
} else
|
|
845
|
+
reported.push(
|
|
846
|
+
`dropped ${printAttr(ctx, parts.onClose)} (Callout dismissible + onDismiss() takes no event)`
|
|
847
|
+
)
|
|
848
|
+
}
|
|
849
|
+
return reported
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
/**
|
|
853
|
+
* Reports each use of legacy `name` as a value (`styled(X)`, `component={X}`) on its statement,
|
|
854
|
+
* in the wording of the runner's `moveElements` plus `fix`, for a rule that keeps the name
|
|
855
|
+
* itself (a family that stays, a body that stays MUI's). Returns the number of uses.
|
|
856
|
+
*/
|
|
857
|
+
export function reportValueUses(
|
|
858
|
+
ctx: MigrateContext,
|
|
859
|
+
name: string,
|
|
860
|
+
fix: string
|
|
861
|
+
): number {
|
|
862
|
+
if (!ctx.names[name]) return 0
|
|
863
|
+
const { j } = ctx
|
|
864
|
+
const uses = ctx.valueUses(name)
|
|
865
|
+
uses.forEach((path) => {
|
|
866
|
+
let statement = (j(path).closest(j.Statement).paths()[0] ?? path) as ASTPath
|
|
867
|
+
if (
|
|
868
|
+
/^Export(Named|Default)Declaration$/.test(
|
|
869
|
+
String(statement.parent?.node.type ?? "")
|
|
870
|
+
)
|
|
871
|
+
)
|
|
872
|
+
statement = statement.parent
|
|
873
|
+
ctx.todo(
|
|
874
|
+
statement,
|
|
875
|
+
name,
|
|
876
|
+
`${source(j, path.parent.node)}: ${name} is used as a value here, so it stays on ${ctx.source}; ${fix}`
|
|
877
|
+
)
|
|
878
|
+
})
|
|
879
|
+
return uses.size()
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/** The runner's `moveElements`, then `each` on every element it moved. */
|
|
883
|
+
export function moveElements(
|
|
884
|
+
ctx: MigrateContext,
|
|
885
|
+
name: string,
|
|
886
|
+
target: string,
|
|
887
|
+
each: (path: ASTPath<JSXElement>) => void
|
|
888
|
+
): void {
|
|
889
|
+
const paths = ctx.elements(name).paths()
|
|
890
|
+
ctx.moveElements(name, target)
|
|
891
|
+
paths.forEach(each)
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/**
|
|
895
|
+
* For a family whose Zenith parts need the Zenith root's context (Dialog, Tabs, Accordion,
|
|
896
|
+
* ToggleButtonGroup): when any member is used as a value (`styled(TabContext)`), nothing in the
|
|
897
|
+
* family is migrated, since a Zenith part inside a base-elements root breaks at runtime. The
|
|
898
|
+
* uses are reported with `fix` and every name stays silently; `true` when the family stays.
|
|
899
|
+
*/
|
|
900
|
+
export function familyStays(
|
|
901
|
+
ctx: MigrateContext,
|
|
902
|
+
names: readonly string[],
|
|
903
|
+
fix: string
|
|
904
|
+
): boolean {
|
|
905
|
+
const used = names.filter((n) => ctx.names[n] && ctx.valueUses(n).size() > 0)
|
|
906
|
+
if (!used.length) return false
|
|
907
|
+
for (const n of used) reportValueUses(ctx, n, fix)
|
|
908
|
+
for (const n of names) ctx.keep(n)
|
|
909
|
+
return true
|
|
910
|
+
}
|