@juspay/svelte-ui-components 3.5.0 → 4.0.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/README.md +25 -16
- package/dist/Accordion/Accordion.svelte +1 -5
- package/dist/Accordion/properties.d.ts +0 -1
- package/dist/AreaChart/AreaChart.svelte +2 -8
- package/dist/AreaChart/properties.d.ts +0 -10
- package/dist/AttachmentChipRow/AttachmentChipRow.svelte +30 -30
- package/dist/AttachmentChipRow/properties.d.ts +6 -6
- package/dist/Banner/Banner.svelte +1 -5
- package/dist/Banner/properties.d.ts +0 -1
- package/dist/BarChart/BarChart.svelte +7 -13
- package/dist/BarChart/properties.d.ts +1 -9
- package/dist/Book/Book.svelte +1 -5
- package/dist/Book/properties.d.ts +0 -1
- package/dist/Calendar/Calendar.svelte +3 -11
- package/dist/Calendar/properties.d.ts +0 -11
- package/dist/Chat/Chat.svelte +9 -29
- package/dist/Chat/properties.d.ts +0 -9
- package/dist/Chat/types.d.ts +7 -0
- package/dist/ChatBubble/ChatBubble.svelte +3 -11
- package/dist/ChatBubble/properties.d.ts +0 -3
- package/dist/ChatComposer/ChatComposer.svelte +18 -44
- package/dist/ChatComposer/properties.d.ts +0 -12
- package/dist/ChatHeader/ChatHeader.svelte +1 -5
- package/dist/ChatHeader/properties.d.ts +0 -1
- package/dist/ChatMessage/ChatMessage.svelte +87 -11
- package/dist/ChatMessage/properties.d.ts +18 -3
- package/dist/ChatMessageList/ChatMessageList.svelte +5 -11
- package/dist/ChatMessageList/properties.d.ts +0 -6
- package/dist/ChatSuggestions/ChatSuggestions.svelte +1 -5
- package/dist/ChatSuggestions/properties.d.ts +0 -1
- package/dist/CheckListItem/CheckListItem.svelte +1 -5
- package/dist/CheckListItem/properties.d.ts +0 -1
- package/dist/Checkbox/Checkbox.svelte +1 -5
- package/dist/Checkbox/properties.d.ts +0 -1
- package/dist/ChipInput/ChipInput.svelte +10 -20
- package/dist/ChipInput/properties.d.ts +0 -4
- package/dist/Choicebox/Choicebox.svelte +1 -5
- package/dist/Choicebox/properties.d.ts +0 -1
- package/dist/ColorPicker/ColorPicker.svelte +4 -10
- package/dist/ColorPicker/properties.d.ts +0 -2
- package/dist/Combobox/Combobox.svelte +15 -33
- package/dist/Combobox/properties.d.ts +0 -8
- package/dist/CommandMenu/CommandMenu.svelte +2 -8
- package/dist/CommandMenu/properties.d.ts +0 -2
- package/dist/ContextMenu/ContextMenu.svelte +3 -11
- package/dist/ContextMenu/properties.d.ts +0 -3
- package/dist/DateRangePicker/DateRangePicker.svelte +6 -20
- package/dist/DateRangePicker/properties.d.ts +0 -19
- package/dist/Draggable/Draggable.svelte +7 -7
- package/dist/Draggable/properties.d.ts +3 -3
- package/dist/DualAxisBarChart/DualAxisBarChart.svelte +1 -5
- package/dist/DualAxisBarChart/properties.d.ts +0 -4
- package/dist/FileDropzoneTrigger/FileDropzoneTrigger.svelte +1 -5
- package/dist/FileDropzoneTrigger/properties.d.ts +0 -1
- package/dist/FileInput/FileInput.svelte +2 -8
- package/dist/FileInput/properties.d.ts +0 -2
- package/dist/FunnelChart/FunnelChart.svelte +2 -8
- package/dist/FunnelChart/properties.d.ts +0 -8
- package/dist/Gallery/Gallery.svelte +15 -15
- package/dist/Gallery/properties.d.ts +6 -6
- package/dist/HITL/HITL.svelte +10 -8
- package/dist/HITL/properties.d.ts +2 -2
- package/dist/IframeViewer/IframeViewer.svelte +3 -2
- package/dist/IframeViewer/properties.d.ts +1 -1
- package/dist/Img/Img.svelte +119 -39
- package/dist/Img/properties.d.ts +0 -1
- package/dist/Input/Input.svelte +22 -37
- package/dist/Input/properties.d.ts +3 -10
- package/dist/InputButton/InputButton.svelte +2 -2
- package/dist/LineChart/LineChart.svelte +4 -10
- package/dist/LineChart/properties.d.ts +1 -11
- package/dist/ListItem/ListItem.svelte +10 -22
- package/dist/ListItem/properties.d.ts +5 -10
- package/dist/LottiePlayer/LottiePlayer.svelte +2 -8
- package/dist/LottiePlayer/properties.d.ts +0 -2
- package/dist/MediaPlayer/MediaPlayer.svelte +1 -5
- package/dist/MediaPlayer/properties.d.ts +0 -1
- package/dist/MediaUpload/MediaUpload.svelte +6 -6
- package/dist/MediaUpload/properties.d.ts +3 -3
- package/dist/Menu/Menu.svelte +3 -11
- package/dist/Menu/properties.d.ts +0 -3
- package/dist/Modal/Modal.svelte +15 -31
- package/dist/Modal/properties.d.ts +5 -11
- package/dist/Pagination/Pagination.svelte +3 -7
- package/dist/Pagination/properties.d.ts +1 -2
- package/dist/PieChart/PieChart.svelte +4 -10
- package/dist/PieChart/properties.d.ts +1 -9
- package/dist/Pill/Pill.svelte +1 -5
- package/dist/Pill/properties.d.ts +0 -1
- package/dist/Radio/Radio.svelte +1 -5
- package/dist/Radio/properties.d.ts +0 -1
- package/dist/Resizable/Resizable.svelte +3 -11
- package/dist/Resizable/properties.d.ts +0 -3
- package/dist/SankeyChart/SankeyChart.svelte +4 -14
- package/dist/SankeyChart/properties.d.ts +0 -12
- package/dist/Scroller/Scroller.svelte +1 -5
- package/dist/Scroller/properties.d.ts +0 -1
- package/dist/Select/Select.svelte +3 -11
- package/dist/Select/properties.d.ts +0 -3
- package/dist/Sheet/Sheet.svelte +3 -11
- package/dist/Sheet/properties.d.ts +0 -3
- package/dist/Slider/Slider.svelte +2 -8
- package/dist/Slider/properties.d.ts +0 -2
- package/dist/Snippet/Snippet.svelte +1 -5
- package/dist/Snippet/properties.d.ts +0 -1
- package/dist/SplitButton/SplitButton.svelte +1 -5
- package/dist/SplitButton/properties.d.ts +0 -1
- package/dist/SplitInput/SplitInput.svelte +6 -14
- package/dist/SplitInput/properties.d.ts +0 -3
- package/dist/StatCard/StatCard.svelte +2 -2
- package/dist/StatCard/properties.d.ts +1 -1
- package/dist/Status/Status.svelte +2 -6
- package/dist/Status/properties.d.ts +1 -2
- package/dist/Stepper/Stepper.svelte +2 -12
- package/dist/Stepper/properties.d.ts +1 -14
- package/dist/Table/BuiltinCell.svelte +1 -1
- package/dist/Table/Table.svelte +16 -17
- package/dist/Table/properties.d.ts +3 -35
- package/dist/Tabs/Tabs.svelte +2 -8
- package/dist/Tabs/properties.d.ts +0 -2
- package/dist/TaskList/TaskList.svelte +1 -4
- package/dist/TaskList/properties.d.ts +0 -1
- package/dist/ThemeSwitcher/ThemeSwitcher.svelte +1 -5
- package/dist/ThemeSwitcher/properties.d.ts +0 -1
- package/dist/ThinkingIndicator/ThinkingIndicator.svelte +4 -10
- package/dist/ThinkingIndicator/properties.d.ts +1 -3
- package/dist/Toast/Toast.svelte +2 -2
- package/dist/Toast/properties.d.ts +1 -1
- package/dist/Toggle/Toggle.svelte +1 -5
- package/dist/Toggle/properties.d.ts +0 -1
- package/dist/ToolCallLog/ToolCallLog.svelte +1 -10
- package/dist/ToolCallLog/properties.d.ts +0 -1
- package/dist/Toolbar/Toolbar.svelte +2 -6
- package/dist/Toolbar/properties.d.ts +1 -2
- package/dist/TypewriterText/TypewriterText.svelte +3 -3
- package/dist/TypewriterText/properties.d.ts +1 -1
- package/dist-codemod/bin.js +32 -0
- package/dist-codemod/cli.js +175 -0
- package/dist-codemod/legacy-pairs.js +228 -0
- package/dist-codemod/transform.js +278 -0
- package/dist-codemod/wc-children.js +66 -0
- package/dist-wc/index.js +4458 -5127
- package/package.json +9 -7
- package/scripts/postinstall.mjs +14 -12
- package/dist/deprecation.d.ts +0 -42
- package/dist/deprecation.js +0 -57
- package/scripts/codemod/README.md +0 -76
- package/scripts/codemod/cli.ts +0 -206
- package/scripts/codemod/map.ts +0 -118
- package/scripts/codemod/transform.ts +0 -549
- package/scripts/codemod/tsconfig.json +0 -15
- package/scripts/codemod/wc-children.ts +0 -75
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/svelte-ui-components",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "A themeable Svelte 5 UI component library with CSS custom property driven styling",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"svelte",
|
|
@@ -21,13 +21,14 @@
|
|
|
21
21
|
"homepage": "https://github.com/juspay/svelte-ui-components",
|
|
22
22
|
"scripts": {
|
|
23
23
|
"dev": "vite dev --host",
|
|
24
|
-
"build": "vite build && npm run build:wc && npm run package",
|
|
24
|
+
"build": "vite build && npm run build:wc && npm run build:codemod && npm run package",
|
|
25
25
|
"build:wc": "vite build --config vite.config.wc.ts && echo 'export {};' > dist-wc/index.d.ts",
|
|
26
|
+
"build:codemod": "rm -rf dist-codemod && tsc -p scripts/codemod/tsconfig.build.json",
|
|
26
27
|
"preview": "vite preview",
|
|
27
28
|
"package": "svelte-kit sync && svelte-package && publint",
|
|
28
|
-
"prepublishOnly": "npm run build:wc && npm run package",
|
|
29
|
+
"prepublishOnly": "npm run build:wc && npm run build:codemod && npm run package",
|
|
29
30
|
"test": "npm run test:integration && npm run test:unit",
|
|
30
|
-
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && npm run check:codemod && npm run check:migrate && npm run check:wc-parity",
|
|
31
|
+
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && npm run check:wc && npm run check:codemod && npm run check:migrate && npm run check:wc-parity",
|
|
31
32
|
"check:codemod": "tsc -p scripts/codemod/tsconfig.json",
|
|
32
33
|
"codemod": "node scripts/codemod/cli.ts",
|
|
33
34
|
"check:wc": "svelte-check --tsconfig ./tsconfig.wc.json --compiler-warnings \"options_missing_custom_element:ignore\"",
|
|
@@ -59,8 +60,7 @@
|
|
|
59
60
|
"!dist/**/*.test.*",
|
|
60
61
|
"!dist/**/*.spec.*",
|
|
61
62
|
"dist-wc",
|
|
62
|
-
"
|
|
63
|
-
"!scripts/codemod/*.test.ts",
|
|
63
|
+
"dist-codemod",
|
|
64
64
|
"scripts/postinstall.mjs"
|
|
65
65
|
],
|
|
66
66
|
"peerDependencies": {
|
|
@@ -92,6 +92,7 @@
|
|
|
92
92
|
"@sveltejs/kit": "^2.63.1",
|
|
93
93
|
"@sveltejs/package": "^2.5.8",
|
|
94
94
|
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
95
|
+
"@testing-library/svelte": "^5.4.2",
|
|
95
96
|
"@types/node": "^22.20.1",
|
|
96
97
|
"@types/semver": "^7.8.0",
|
|
97
98
|
"@typescript-eslint/eslint-plugin": "^8.60.1",
|
|
@@ -102,6 +103,7 @@
|
|
|
102
103
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
103
104
|
"globals": "^17.6.0",
|
|
104
105
|
"husky": "^9.1.7",
|
|
106
|
+
"jsdom": "^29.1.1",
|
|
105
107
|
"lottie-web": "^5.13.0",
|
|
106
108
|
"marked": "^18.0.5",
|
|
107
109
|
"prettier": "^3.8.3",
|
|
@@ -194,7 +196,7 @@
|
|
|
194
196
|
}
|
|
195
197
|
},
|
|
196
198
|
"bin": {
|
|
197
|
-
"sui-codemod": "./
|
|
199
|
+
"sui-codemod": "./dist-codemod/bin.js"
|
|
198
200
|
},
|
|
199
201
|
"engines": {
|
|
200
202
|
"node": ">=22.18"
|
package/scripts/postinstall.mjs
CHANGED
|
@@ -27,23 +27,25 @@ const isNonInteractive = () =>
|
|
|
27
27
|
const notice = () =>
|
|
28
28
|
[
|
|
29
29
|
'',
|
|
30
|
-
`${BOLD}@juspay/svelte-ui-components —
|
|
30
|
+
`${BOLD}@juspay/svelte-ui-components — two breaking changes are coming in 4.0.0${RESET}`,
|
|
31
31
|
'',
|
|
32
|
-
' Nothing has changed yet.
|
|
33
|
-
' property on sui-chat-bubble, sui-draggable and sui-resizable, and',
|
|
34
|
-
' assigning it will silently lose the content.',
|
|
32
|
+
' Nothing has changed yet. Both work today; both go away in 4.0.0:',
|
|
35
33
|
'',
|
|
36
|
-
'
|
|
37
|
-
`
|
|
38
|
-
|
|
34
|
+
' 1. Every event prop is now lowercase (`onRowClick` -> `onrowclick`,',
|
|
35
|
+
' `onClick` -> `onclick`), matching one rule for native and invented',
|
|
36
|
+
' events alike. The 191 earlier spellings still work and warn once per',
|
|
37
|
+
' prop in dev builds; 4.0.0 removes them.',
|
|
38
|
+
' Plan: docs/EVENT_CASING_MIGRATION.md in the repository.',
|
|
39
39
|
'',
|
|
40
|
-
'
|
|
41
|
-
'
|
|
40
|
+
' 2. `children` stops being a settable property on sui-chat-bubble,',
|
|
41
|
+
' sui-draggable and sui-resizable; assigning it will silently lose',
|
|
42
|
+
' the content. Move to light-DOM children ahead of time:',
|
|
43
|
+
` ${DIM}el.children = snippet;${RESET} // before`,
|
|
44
|
+
` ${DIM}<sui-draggable><div>…</div></sui-draggable>${RESET} // after`,
|
|
42
45
|
'',
|
|
43
|
-
|
|
46
|
+
' One command reports every affected call site (writes nothing), and',
|
|
47
|
+
' rewrites the event props for you without --dry-run:',
|
|
44
48
|
` ${BOLD}npx sui-codemod --dry-run ./src${RESET}`,
|
|
45
|
-
'',
|
|
46
|
-
` ${DIM}Nothing else in the custom-element surface breaks.${RESET}`,
|
|
47
49
|
''
|
|
48
50
|
].join('\n');
|
|
49
51
|
|
package/dist/deprecation.d.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 2 of `docs/EVENT_CASING_MIGRATION.md`: tell a consumer, once, that a
|
|
3
|
-
* prop spelling is going away and what replaces it.
|
|
4
|
-
*
|
|
5
|
-
* Two constraints shape this.
|
|
6
|
-
*
|
|
7
|
-
* It is dev-only. A production warning is noise a consumer cannot act on
|
|
8
|
-
* mid-incident, and 142 props warning in a production console would bury real
|
|
9
|
-
* output. `import.meta.env.DEV` is the guard because it is what the bundler
|
|
10
|
-
* this library is built with statically replaces, so the whole call is removed
|
|
11
|
-
* from a production build rather than merely skipped at runtime.
|
|
12
|
-
*
|
|
13
|
-
* It warns once per component-and-prop, not once per render. A deprecated prop
|
|
14
|
-
* on a list row would otherwise warn on every one of a thousand rows, and a
|
|
15
|
-
* consumer would learn less from a thousand identical lines than from one.
|
|
16
|
-
*
|
|
17
|
-
* Internal. Nothing here is re-exported from `src/lib/index.ts`, because a
|
|
18
|
-
* consumer has no call for it: the components invoke it themselves when they
|
|
19
|
-
* are handed a deprecated spelling. That is this library's normal way of
|
|
20
|
-
* marking a module internal rather than an omission -- `src/lib/utils.ts`
|
|
21
|
-
* exports ten functions and the barrel re-exports three, leaving
|
|
22
|
-
* `getStorageItem`, `hexToRgb` and five others reachable only from inside.
|
|
23
|
-
* Exporting these two would add public API that 4.0.0 then has to keep.
|
|
24
|
-
*/
|
|
25
|
-
/**
|
|
26
|
-
* The release that removes the old spellings, named in one place so the message
|
|
27
|
-
* and the migration plan cannot drift apart.
|
|
28
|
-
*
|
|
29
|
-
* 4.0.0 is a commitment, not a placeholder. An earlier draft of this string was
|
|
30
|
-
* written while #506 was expected to cut the major; it shipped inside 3.2.0 as
|
|
31
|
-
* a minor instead, which briefly left this warning promising a version nothing
|
|
32
|
-
* was committed to. `docs/EVENT_CASING_MIGRATION.md` holds the plan; a test
|
|
33
|
-
* pins this value so moving it is a deliberate edit and not a silent one.
|
|
34
|
-
*/
|
|
35
|
-
export declare const DEPRECATION_REMOVAL_VERSION = "4.0.0";
|
|
36
|
-
/**
|
|
37
|
-
* Exposed for tests. A module-level Set survives between test cases, so a
|
|
38
|
-
* second case asserting "warns once" would pass vacuously by inheriting the
|
|
39
|
-
* first case's suppression rather than by exercising it.
|
|
40
|
-
*/
|
|
41
|
-
export declare const resetDeprecationWarnings: () => void;
|
|
42
|
-
export declare const warnDeprecatedProp: (component: string, oldName: string, newName: string) => void;
|
package/dist/deprecation.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Phase 2 of `docs/EVENT_CASING_MIGRATION.md`: tell a consumer, once, that a
|
|
3
|
-
* prop spelling is going away and what replaces it.
|
|
4
|
-
*
|
|
5
|
-
* Two constraints shape this.
|
|
6
|
-
*
|
|
7
|
-
* It is dev-only. A production warning is noise a consumer cannot act on
|
|
8
|
-
* mid-incident, and 142 props warning in a production console would bury real
|
|
9
|
-
* output. `import.meta.env.DEV` is the guard because it is what the bundler
|
|
10
|
-
* this library is built with statically replaces, so the whole call is removed
|
|
11
|
-
* from a production build rather than merely skipped at runtime.
|
|
12
|
-
*
|
|
13
|
-
* It warns once per component-and-prop, not once per render. A deprecated prop
|
|
14
|
-
* on a list row would otherwise warn on every one of a thousand rows, and a
|
|
15
|
-
* consumer would learn less from a thousand identical lines than from one.
|
|
16
|
-
*
|
|
17
|
-
* Internal. Nothing here is re-exported from `src/lib/index.ts`, because a
|
|
18
|
-
* consumer has no call for it: the components invoke it themselves when they
|
|
19
|
-
* are handed a deprecated spelling. That is this library's normal way of
|
|
20
|
-
* marking a module internal rather than an omission -- `src/lib/utils.ts`
|
|
21
|
-
* exports ten functions and the barrel re-exports three, leaving
|
|
22
|
-
* `getStorageItem`, `hexToRgb` and five others reachable only from inside.
|
|
23
|
-
* Exporting these two would add public API that 4.0.0 then has to keep.
|
|
24
|
-
*/
|
|
25
|
-
/**
|
|
26
|
-
* The release that removes the old spellings, named in one place so the message
|
|
27
|
-
* and the migration plan cannot drift apart.
|
|
28
|
-
*
|
|
29
|
-
* 4.0.0 is a commitment, not a placeholder. An earlier draft of this string was
|
|
30
|
-
* written while #506 was expected to cut the major; it shipped inside 3.2.0 as
|
|
31
|
-
* a minor instead, which briefly left this warning promising a version nothing
|
|
32
|
-
* was committed to. `docs/EVENT_CASING_MIGRATION.md` holds the plan; a test
|
|
33
|
-
* pins this value so moving it is a deliberate edit and not a silent one.
|
|
34
|
-
*/
|
|
35
|
-
export const DEPRECATION_REMOVAL_VERSION = '4.0.0';
|
|
36
|
-
const seen = new Set();
|
|
37
|
-
/**
|
|
38
|
-
* Exposed for tests. A module-level Set survives between test cases, so a
|
|
39
|
-
* second case asserting "warns once" would pass vacuously by inheriting the
|
|
40
|
-
* first case's suppression rather than by exercising it.
|
|
41
|
-
*/
|
|
42
|
-
export const resetDeprecationWarnings = () => {
|
|
43
|
-
seen.clear();
|
|
44
|
-
};
|
|
45
|
-
export const warnDeprecatedProp = (component, oldName, newName) => {
|
|
46
|
-
if (import.meta.env.DEV !== true) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
const key = `${component}.${oldName}`;
|
|
50
|
-
if (seen.has(key)) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
seen.add(key);
|
|
54
|
-
console.warn(`[svelte-ui-components] \`${oldName}\` on <${component}> is deprecated and will be ` +
|
|
55
|
-
`removed in ${DEPRECATION_REMOVAL_VERSION}. Use \`${newName}\` instead — both work today. ` +
|
|
56
|
-
`Run \`npx sui-codemod --dry-run ./src\` to see every affected call site.`);
|
|
57
|
-
};
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# polymorph → SUI consumer migration codemod
|
|
2
|
-
|
|
3
|
-
Also reports the one breaking change in the 4.0.0 custom-element surface:
|
|
4
|
-
`children` is no longer a declared property on `sui-chat-bubble`,
|
|
5
|
-
`sui-draggable` or `sui-resizable`, so assigning it silently loses the content.
|
|
6
|
-
That check runs on every forward migration and in dry runs, reports rather than
|
|
7
|
-
rewrites (moving content into markup is a decision, not a rename), and only
|
|
8
|
-
fires in files that also mention one of the three elements. See
|
|
9
|
-
`wc-children.ts`.
|
|
10
|
-
|
|
11
|
-
This package is published, so consumers can run it without a checkout:
|
|
12
|
-
|
|
13
|
-
```sh
|
|
14
|
-
npx sui-codemod --dry-run ./src
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Mechanically migrates a consumer codebase from `polymorph-ui-components` to
|
|
18
|
-
`@juspay/svelte-ui-components`:
|
|
19
|
-
|
|
20
|
-
- rewrites import/export/dynamic-import specifiers (subpaths like `/wc` are
|
|
21
|
-
preserved), in `.svelte`, `.ts` and `.js` files;
|
|
22
|
-
- renames the 28 synthetic event props (see `map.ts`) on library components in
|
|
23
|
-
`.svelte` markup. All but one differ from the fork only in case; Stepper's
|
|
24
|
-
`onhandlestepclick` becomes `onstepclick`, stepping over the deprecated
|
|
25
|
-
`onhandleStepClick` alias that the casing match would otherwise have picked.
|
|
26
|
-
Renaming is component-aware: `onsort` is renamed on a
|
|
27
|
-
`<Table>` imported from the library (through aliases,
|
|
28
|
-
`import { Table as DataTable }`, namespace imports and
|
|
29
|
-
`<svelte:component this={Table}>`), and left alone on your own components
|
|
30
|
-
and on native elements.
|
|
31
|
-
|
|
32
|
-
## Usage
|
|
33
|
-
|
|
34
|
-
Run from a checkout of this repo (dependencies resolve here), pointing at the
|
|
35
|
-
consumer project. Requires Node >= 22.18 (runs TypeScript directly).
|
|
36
|
-
|
|
37
|
-
```sh
|
|
38
|
-
# preview
|
|
39
|
-
npm run codemod -- --dry-run ../consumer-app/src
|
|
40
|
-
|
|
41
|
-
# apply
|
|
42
|
-
npm run codemod -- ../consumer-app/src
|
|
43
|
-
|
|
44
|
-
# migrate in the other direction (SUI -> polymorph)
|
|
45
|
-
npm run codemod -- --reverse ../consumer-app/src
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
Directories are walked recursively; `node_modules`, `.git`, `.svelte-kit`,
|
|
49
|
-
`dist`, `dist-wc`, `build`, `coverage`, `playwright-report` and `test-results`
|
|
50
|
-
are skipped.
|
|
51
|
-
|
|
52
|
-
## What it will not do (by design)
|
|
53
|
-
|
|
54
|
-
Anything it cannot prove safe is reported as a `WARN` with `file:line:column`
|
|
55
|
-
instead of being rewritten — silent wrong rewrites are worse than reported
|
|
56
|
-
skips:
|
|
57
|
-
|
|
58
|
-
- **Spread attributes.** `<Table {...props} />` may carry a renamed prop
|
|
59
|
-
inside `props`; the object is defined elsewhere, so it is warned about, not
|
|
60
|
-
rewritten.
|
|
61
|
-
- **Unresolvable components.** `const Picked = Table;` then
|
|
62
|
-
`<Picked onsort={...} />` — the tag does not resolve to an import, so a
|
|
63
|
-
warning is emitted when it carries a renameable prop name.
|
|
64
|
-
- **Default imports** from the library cannot be resolved to a component.
|
|
65
|
-
- **Semantic renames** — same event, different word — are not casing pairs
|
|
66
|
-
and need a human: Gallery `onclose`→`onDismiss`, `onchange`→`onIndexChange`;
|
|
67
|
-
MediaUpload `onchange`→`onFilesChange`, `onerror`→`onRejected`.
|
|
68
|
-
- Props typed against library types in `<script>` (e.g. an object literal fed
|
|
69
|
-
to a spread) are not rewritten — the spread warning covers the usage site.
|
|
70
|
-
|
|
71
|
-
Shorthand attributes are expanded when renamed (`{onsort}` →
|
|
72
|
-
`onSort={onsort}`), so a `--reverse` round trip restores the original names
|
|
73
|
-
but not the shorthand form.
|
|
74
|
-
|
|
75
|
-
`map.ts` documents how the pair list was derived and verified against both
|
|
76
|
-
libraries' sources.
|
package/scripts/codemod/cli.ts
DELETED
|
@@ -1,206 +0,0 @@
|
|
|
1
|
-
import { existsSync, readdirSync, readFileSync, statSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { join, resolve } from 'node:path';
|
|
3
|
-
import { pathToFileURL } from 'node:url';
|
|
4
|
-
import { parseArgs } from 'node:util';
|
|
5
|
-
import type { Direction } from './map.ts';
|
|
6
|
-
import { transformModuleSpecifiers, transformSvelte } from './transform.ts';
|
|
7
|
-
import type { TransformResult } from './transform.ts';
|
|
8
|
-
import { findChildrenAssignments } from './wc-children.ts';
|
|
9
|
-
|
|
10
|
-
export type CliSummary = {
|
|
11
|
-
readonly exitCode: number;
|
|
12
|
-
readonly filesScanned: number;
|
|
13
|
-
readonly filesChanged: number;
|
|
14
|
-
readonly propsRenamed: number;
|
|
15
|
-
readonly importsRewritten: number;
|
|
16
|
-
readonly warnings: number;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const USAGE = [
|
|
20
|
-
'Usage: node scripts/codemod/cli.ts [--reverse] [--dry-run] <path...>',
|
|
21
|
-
'',
|
|
22
|
-
'Migrates consumer sources from polymorph-ui-components to',
|
|
23
|
-
'@juspay/svelte-ui-components: rewrites import specifiers and renames the',
|
|
24
|
-
'casing-only synthetic event props on library components (see map.ts).',
|
|
25
|
-
'',
|
|
26
|
-
' --reverse migrate @juspay/svelte-ui-components -> polymorph-ui-components',
|
|
27
|
-
' --dry-run print every change as a diff without writing any file',
|
|
28
|
-
' --help show this help',
|
|
29
|
-
'',
|
|
30
|
-
'Paths may be files or directories; directories are walked recursively,',
|
|
31
|
-
'skipping node_modules, .git, .svelte-kit, dist, dist-wc, build, coverage,',
|
|
32
|
-
'playwright-report and test-results.'
|
|
33
|
-
].join('\n');
|
|
34
|
-
|
|
35
|
-
const SKIPPED_DIRECTORIES = new Set([
|
|
36
|
-
'node_modules',
|
|
37
|
-
'.git',
|
|
38
|
-
'.svelte-kit',
|
|
39
|
-
'dist',
|
|
40
|
-
'dist-wc',
|
|
41
|
-
'build',
|
|
42
|
-
'coverage',
|
|
43
|
-
'playwright-report',
|
|
44
|
-
'test-results'
|
|
45
|
-
]);
|
|
46
|
-
|
|
47
|
-
const SCRIPT_FILE = /\.(ts|js|mts|mjs|cts|cjs)$/;
|
|
48
|
-
|
|
49
|
-
function collectFiles(path: string, out: Set<string>): void {
|
|
50
|
-
const stats = statSync(path);
|
|
51
|
-
if (stats.isFile()) {
|
|
52
|
-
if (path.endsWith('.svelte') || SCRIPT_FILE.test(path)) {
|
|
53
|
-
out.add(path);
|
|
54
|
-
}
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
if (!stats.isDirectory()) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
const entries = [...readdirSync(path, { withFileTypes: true })].sort((a, b) =>
|
|
61
|
-
a.name.localeCompare(b.name)
|
|
62
|
-
);
|
|
63
|
-
for (const entry of entries) {
|
|
64
|
-
if (entry.isDirectory()) {
|
|
65
|
-
if (!SKIPPED_DIRECTORIES.has(entry.name)) {
|
|
66
|
-
collectFiles(join(path, entry.name), out);
|
|
67
|
-
}
|
|
68
|
-
} else if (entry.isFile()) {
|
|
69
|
-
collectFiles(join(path, entry.name), out);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Every edit the transform makes stays on a single line, so old and new text
|
|
76
|
-
* always have the same line count and a pairwise comparison is an exact diff.
|
|
77
|
-
*/
|
|
78
|
-
function printLineDiff(
|
|
79
|
-
file: string,
|
|
80
|
-
before: string,
|
|
81
|
-
after: string,
|
|
82
|
-
log: (line: string) => void
|
|
83
|
-
): void {
|
|
84
|
-
const oldLines = before.split('\n');
|
|
85
|
-
const newLines = after.split('\n');
|
|
86
|
-
log(`--- ${file}`);
|
|
87
|
-
if (oldLines.length !== newLines.length) {
|
|
88
|
-
log(' (line counts differ; showing full replacement)');
|
|
89
|
-
for (const line of oldLines) {
|
|
90
|
-
log(`- ${line}`);
|
|
91
|
-
}
|
|
92
|
-
for (const line of newLines) {
|
|
93
|
-
log(`+ ${line}`);
|
|
94
|
-
}
|
|
95
|
-
return;
|
|
96
|
-
}
|
|
97
|
-
oldLines.forEach((oldLine, index) => {
|
|
98
|
-
const newLine = newLines.at(index) ?? '';
|
|
99
|
-
if (oldLine !== newLine) {
|
|
100
|
-
log(`@@ ${file}:${index + 1}`);
|
|
101
|
-
log(`- ${oldLine}`);
|
|
102
|
-
log(`+ ${newLine}`);
|
|
103
|
-
}
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
export function runCodemod(argv: ReadonlyArray<string>, log: (line: string) => void): CliSummary {
|
|
108
|
-
const failure = {
|
|
109
|
-
exitCode: 2,
|
|
110
|
-
filesScanned: 0,
|
|
111
|
-
filesChanged: 0,
|
|
112
|
-
propsRenamed: 0,
|
|
113
|
-
importsRewritten: 0,
|
|
114
|
-
warnings: 0
|
|
115
|
-
};
|
|
116
|
-
let parsed;
|
|
117
|
-
try {
|
|
118
|
-
parsed = parseArgs({
|
|
119
|
-
args: [...argv],
|
|
120
|
-
options: {
|
|
121
|
-
reverse: { type: 'boolean' },
|
|
122
|
-
'dry-run': { type: 'boolean' },
|
|
123
|
-
help: { type: 'boolean' }
|
|
124
|
-
},
|
|
125
|
-
allowPositionals: true,
|
|
126
|
-
strict: true
|
|
127
|
-
});
|
|
128
|
-
} catch (error) {
|
|
129
|
-
log(error instanceof Error ? error.message : String(error));
|
|
130
|
-
log(USAGE);
|
|
131
|
-
return failure;
|
|
132
|
-
}
|
|
133
|
-
if (parsed.values.help === true) {
|
|
134
|
-
log(USAGE);
|
|
135
|
-
return { ...failure, exitCode: 0 };
|
|
136
|
-
}
|
|
137
|
-
if (parsed.positionals.length === 0) {
|
|
138
|
-
log(USAGE);
|
|
139
|
-
return failure;
|
|
140
|
-
}
|
|
141
|
-
for (const path of parsed.positionals) {
|
|
142
|
-
if (!existsSync(path)) {
|
|
143
|
-
log(`path does not exist: ${path}`);
|
|
144
|
-
return failure;
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
const direction: Direction = parsed.values.reverse === true ? 'to-poly' : 'to-sui';
|
|
148
|
-
const dryRun = parsed.values['dry-run'] === true;
|
|
149
|
-
|
|
150
|
-
const files = new Set<string>();
|
|
151
|
-
for (const path of parsed.positionals) {
|
|
152
|
-
collectFiles(resolve(path), files);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
let filesChanged = 0;
|
|
156
|
-
let propsRenamed = 0;
|
|
157
|
-
let importsRewritten = 0;
|
|
158
|
-
let warnings = 0;
|
|
159
|
-
for (const file of files) {
|
|
160
|
-
const source = readFileSync(file, 'utf8');
|
|
161
|
-
const result: TransformResult = file.endsWith('.svelte')
|
|
162
|
-
? transformSvelte(source, file, direction)
|
|
163
|
-
: transformModuleSpecifiers(source, file, direction);
|
|
164
|
-
// Reported in both directions and in dry runs: it is a 4.0.0 breaking change
|
|
165
|
-
// to report, not a rename to apply, so it never contributes to filesChanged.
|
|
166
|
-
const childrenWarnings = direction === 'to-sui' ? findChildrenAssignments(source, file) : [];
|
|
167
|
-
for (const warning of [...result.warnings, ...childrenWarnings]) {
|
|
168
|
-
log(`${warning.file}:${warning.line}:${warning.column} WARN ${warning.message}`);
|
|
169
|
-
}
|
|
170
|
-
warnings += result.warnings.length + childrenWarnings.length;
|
|
171
|
-
if (!result.changed) {
|
|
172
|
-
continue;
|
|
173
|
-
}
|
|
174
|
-
filesChanged += 1;
|
|
175
|
-
propsRenamed += result.propsRenamed;
|
|
176
|
-
importsRewritten += result.importsRewritten;
|
|
177
|
-
if (dryRun) {
|
|
178
|
-
printLineDiff(file, source, result.code, log);
|
|
179
|
-
} else {
|
|
180
|
-
writeFileSync(file, result.code);
|
|
181
|
-
log(
|
|
182
|
-
`${file}: ${result.propsRenamed} prop(s) renamed, ${result.importsRewritten} import(s) rewritten`
|
|
183
|
-
);
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
log(
|
|
187
|
-
`${dryRun ? '[dry run] ' : ''}scanned ${files.size} file(s), changed ${filesChanged}, ` +
|
|
188
|
-
`renamed ${propsRenamed} prop(s), rewrote ${importsRewritten} import(s), ${warnings} warning(s)`
|
|
189
|
-
);
|
|
190
|
-
return {
|
|
191
|
-
exitCode: 0,
|
|
192
|
-
filesScanned: files.size,
|
|
193
|
-
filesChanged,
|
|
194
|
-
propsRenamed,
|
|
195
|
-
importsRewritten,
|
|
196
|
-
warnings
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
const entryPoint = process.argv.at(1) ?? '';
|
|
201
|
-
if (entryPoint !== '' && import.meta.url === pathToFileURL(entryPoint).href) {
|
|
202
|
-
const summary = runCodemod(process.argv.slice(2), (line) => {
|
|
203
|
-
console.log(line);
|
|
204
|
-
});
|
|
205
|
-
process.exitCode = summary.exitCode;
|
|
206
|
-
}
|
package/scripts/codemod/map.ts
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Casing-only prop pairs between this library (SUI) and its fork
|
|
3
|
-
* `polymorph-ui-components` (poly). Poly renamed synthesized event props to
|
|
4
|
-
* all-lowercase; these are the props whose names differ ONLY in case between
|
|
5
|
-
* the two libraries.
|
|
6
|
-
*
|
|
7
|
-
* Derived mechanically (not copied from docs): the `$props()` destructure of
|
|
8
|
-
* every component exported by both `src/lib/index.ts` (SUI @ release) and
|
|
9
|
-
* `dist/index.js` of polymorph-ui-components@0.7.0 was parsed with
|
|
10
|
-
* `svelte/compiler`, and a pair was accepted only when
|
|
11
|
-
* `lower(suiName) === lower(polyName)`, the names differ, and neither side
|
|
12
|
-
* also declares the other side's spelling (which would make a rewrite
|
|
13
|
-
* ambiguous or unnecessary). Cross-checked against each component's
|
|
14
|
-
* `properties.ts` / `properties.d.ts`.
|
|
15
|
-
*
|
|
16
|
-
* That derivation is deprecation-blind, and one pair had to be corrected by
|
|
17
|
-
* hand afterwards: where a component keeps a deprecated alias whose lowercase
|
|
18
|
-
* spelling matches the fork's, the alias wins the case-insensitive match and
|
|
19
|
-
* outranks the canonical prop. Stepper is the only such pair. `map.test.ts`
|
|
20
|
-
* now asserts no target is `@deprecated`, so a future alias cannot repeat it.
|
|
21
|
-
*
|
|
22
|
-
* Deliberately excluded (same event, different word — a semantic rename, not
|
|
23
|
-
* a casing pair; these need a human):
|
|
24
|
-
* Gallery: poly `onclose` vs SUI `onDismiss`, poly `onchange` vs SUI `onIndexChange`
|
|
25
|
-
* MediaUpload: poly `onchange` vs SUI `onFilesChange`, poly `onerror` vs SUI `onRejected`
|
|
26
|
-
* Props spelled identically on both sides (e.g. `onkeydown` on ListItem or
|
|
27
|
-
* Modal) are intentionally absent: they need no rewrite. `onkeydown` on Input
|
|
28
|
-
* IS listed because SUI's Input only accepts `onKeyDown`.
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
export type PropPair = {
|
|
32
|
-
readonly component: string;
|
|
33
|
-
readonly sui: string;
|
|
34
|
-
readonly poly: string;
|
|
35
|
-
/**
|
|
36
|
-
* Superseded SUI spellings that still work. Never a rewrite target, but
|
|
37
|
-
* recognized as a source when rewriting back to the fork.
|
|
38
|
-
*/
|
|
39
|
-
readonly suiDeprecatedAliases?: readonly string[];
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export const SUI_PACKAGE = '@juspay/svelte-ui-components';
|
|
43
|
-
export const POLY_PACKAGE = 'polymorph-ui-components';
|
|
44
|
-
|
|
45
|
-
export const PROP_PAIRS: ReadonlyArray<PropPair> = [
|
|
46
|
-
{ component: 'Gallery', sui: 'onDeleteClick', poly: 'ondeleteclick' },
|
|
47
|
-
{ component: 'Gallery', sui: 'onEditClick', poly: 'oneditclick' },
|
|
48
|
-
{ component: 'Gallery', sui: 'onImageClick', poly: 'onimageclick' },
|
|
49
|
-
{ component: 'Gallery', sui: 'onOpen', poly: 'onopen' },
|
|
50
|
-
{ component: 'Input', sui: 'onBlur', poly: 'onblur' },
|
|
51
|
-
{ component: 'Input', sui: 'onClick', poly: 'onclick' },
|
|
52
|
-
{ component: 'Input', sui: 'onFocus', poly: 'onfocus' },
|
|
53
|
-
{ component: 'Input', sui: 'onFocusout', poly: 'onfocusout' },
|
|
54
|
-
{ component: 'Input', sui: 'onInput', poly: 'oninput' },
|
|
55
|
-
{ component: 'Input', sui: 'onKeyDown', poly: 'onkeydown' },
|
|
56
|
-
{ component: 'Input', sui: 'onPaste', poly: 'onpaste' },
|
|
57
|
-
{ component: 'Input', sui: 'onStateChange', poly: 'onstatechange' },
|
|
58
|
-
{ component: 'ListItem', sui: 'oncenterTextClick', poly: 'oncentertextclick' },
|
|
59
|
-
{ component: 'ListItem', sui: 'onitemClick', poly: 'onitemclick' },
|
|
60
|
-
{ component: 'ListItem', sui: 'onleftImageClick', poly: 'onleftimageclick' },
|
|
61
|
-
{ component: 'ListItem', sui: 'onrightImageClick', poly: 'onrightimageclick' },
|
|
62
|
-
{ component: 'ListItem', sui: 'ontopSectionClick', poly: 'ontopsectionclick' },
|
|
63
|
-
{ component: 'MediaUpload', sui: 'onRemove', poly: 'onremove' },
|
|
64
|
-
{ component: 'Modal', sui: 'onheaderLeftImageClick', poly: 'onheaderleftimageclick' },
|
|
65
|
-
{ component: 'Modal', sui: 'onheaderRightImageClick', poly: 'onheaderrightimageclick' },
|
|
66
|
-
{ component: 'Modal', sui: 'onoverlayClick', poly: 'onoverlayclick' },
|
|
67
|
-
{ component: 'Modal', sui: 'onprimaryButtonClick', poly: 'onprimarybuttonclick' },
|
|
68
|
-
{ component: 'Modal', sui: 'onsecondaryButtonClick', poly: 'onsecondarybuttonclick' },
|
|
69
|
-
// The lowercase match here is `onhandleStepClick`, which SUI deprecates in
|
|
70
|
-
// favour of `onstepclick`. Rewriting to the alias would be case-correct and
|
|
71
|
-
// still wrong: it is the one spelling of this event scheduled for removal.
|
|
72
|
-
{
|
|
73
|
-
component: 'Stepper',
|
|
74
|
-
sui: 'onstepclick',
|
|
75
|
-
poly: 'onhandlestepclick',
|
|
76
|
-
suiDeprecatedAliases: ['onhandleStepClick']
|
|
77
|
-
},
|
|
78
|
-
{ component: 'Table', sui: 'onRowClick', poly: 'onrowclick' },
|
|
79
|
-
{ component: 'Table', sui: 'onSort', poly: 'onsort' },
|
|
80
|
-
{ component: 'Toast', sui: 'onToastHide', poly: 'ontoasthide' },
|
|
81
|
-
{ component: 'Toolbar', sui: 'onbackClick', poly: 'onbackclick' }
|
|
82
|
-
];
|
|
83
|
-
|
|
84
|
-
export type Direction = 'to-sui' | 'to-poly';
|
|
85
|
-
|
|
86
|
-
export type DirectionConfig = {
|
|
87
|
-
readonly fromPackage: string;
|
|
88
|
-
readonly toPackage: string;
|
|
89
|
-
/** component name -> (source prop name -> target prop name) */
|
|
90
|
-
readonly renames: ReadonlyMap<string, ReadonlyMap<string, string>>;
|
|
91
|
-
/** every source prop name across all components, for unresolved-tag warnings */
|
|
92
|
-
readonly allFromProps: ReadonlySet<string>;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
export function directionConfig(direction: Direction): DirectionConfig {
|
|
96
|
-
const renames = new Map<string, Map<string, string>>();
|
|
97
|
-
const allFromProps = new Set<string>();
|
|
98
|
-
for (const pair of PROP_PAIRS) {
|
|
99
|
-
const table = renames.get(pair.component) ?? new Map<string, string>();
|
|
100
|
-
// Deprecated aliases are sources, never targets: a consumer moving to SUI
|
|
101
|
-
// lands on the canonical prop, while one moving back to the fork is
|
|
102
|
-
// recognized whichever spelling they are currently on.
|
|
103
|
-
const sources =
|
|
104
|
-
direction === 'to-sui' ? [pair.poly] : [pair.sui, ...(pair.suiDeprecatedAliases ?? [])];
|
|
105
|
-
const to = direction === 'to-sui' ? pair.sui : pair.poly;
|
|
106
|
-
for (const from of sources) {
|
|
107
|
-
table.set(from, to);
|
|
108
|
-
allFromProps.add(from);
|
|
109
|
-
}
|
|
110
|
-
renames.set(pair.component, table);
|
|
111
|
-
}
|
|
112
|
-
return {
|
|
113
|
-
fromPackage: direction === 'to-sui' ? POLY_PACKAGE : SUI_PACKAGE,
|
|
114
|
-
toPackage: direction === 'to-sui' ? SUI_PACKAGE : POLY_PACKAGE,
|
|
115
|
-
renames,
|
|
116
|
-
allFromProps
|
|
117
|
-
};
|
|
118
|
-
}
|