@ornikar/kitt-universal 27.5.1-canary.3a59d4ae3422049417956fa37f27d2e8f5f84aba.0 → 27.5.1-canary.74b3661a3818b6b6b6cd66a9bf11ce3340651bb8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -1
- package/package.json +1 -1
- package/scripts/codemods/__testfixtures__/csf1-csf2/decorator.output.tsx +1 -1
- package/scripts/codemods/__testfixtures__/csf1-csf2/default.input.tsx +1 -1
- package/scripts/codemods/__testfixtures__/csf1-csf2/default.output.tsx +1 -1
- package/scripts/codemods/__testfixtures__/csf1-csf2/new.input.tsx +77 -0
- package/scripts/codemods/__testfixtures__/csf1-csf2/new.output.tsx +92 -0
- package/scripts/codemods/__tests__/csf1-csf2.test.ts +1 -1
- package/scripts/codemods/csf1-csf2.js +147 -81
package/CHANGELOG.md
CHANGED
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
-
## [27.5.1-canary.
|
|
6
|
+
## [27.5.1-canary.74b3661a3818b6b6b6cd66a9bf11ce3340651bb8.0](https://github.com/ornikar/kitt/compare/@ornikar/kitt-universal@27.5.0...@ornikar/kitt-universal@27.5.1-canary.74b3661a3818b6b6b6cd66a9bf11ce3340651bb8.0) (2025-09-16)
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
### Features
|
|
10
10
|
|
|
11
11
|
* generate csf2 codemod ([3a59d4a](https://github.com/ornikar/kitt/commit/3a59d4ae3422049417956fa37f27d2e8f5f84aba))
|
|
12
|
+
* improve codemod ([74b3661](https://github.com/ornikar/kitt/commit/74b3661a3818b6b6b6cd66a9bf11ce3340651bb8))
|
|
13
|
+
* improve codemod ([7b68cb8](https://github.com/ornikar/kitt/commit/7b68cb8f8312c7736633882eefa6e43178ed4819))
|
|
12
14
|
* **kitt-universal:** generate codemod instructions OSE-19616 ([#2682](https://github.com/ornikar/kitt/issues/2682)) ([291e65b](https://github.com/ornikar/kitt/commit/291e65bb3692ccb17d6d78abea0eeea1cf7c20a5))
|
|
13
15
|
* **rebranding:** review `TabBar` OSE-18003 ([#2687](https://github.com/ornikar/kitt/issues/2687)) ([a757d23](https://github.com/ornikar/kitt/commit/a757d237394d9fe65508d11998f6d5f6971b5bbd))
|
|
14
16
|
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@ import { NotificationEnablerScreenView } from './NotificationEnablerScreenView';
|
|
|
8
8
|
export default {
|
|
9
9
|
title: 'LNA/shared/components',
|
|
10
10
|
component: NotificationEnablerScreenView,
|
|
11
|
-
decorators: [
|
|
11
|
+
decorators: [NativeStoryDecorator, AnotherDecorator],
|
|
12
12
|
} satisfies ComponentMeta<typeof NotificationEnablerScreenView>;
|
|
13
13
|
|
|
14
14
|
export const NotificationEnablerScreenStory: ComponentStory<typeof NotificationEnablerScreenView> = () => (
|
|
@@ -91,4 +91,4 @@ export default {
|
|
|
91
91
|
} satisfies ComponentMeta<typeof CustomTooltipWrapper>;
|
|
92
92
|
|
|
93
93
|
export const CustomTooltipStory: ComponentStory<typeof CustomTooltipWrapper> = () => <CustomTooltipWrapper />;
|
|
94
|
-
CustomTooltipStory.storyName = 'CustomTooltip';
|
|
94
|
+
CustomTooltipStory.storyName = 'CustomTooltip (default)';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { action } from '@storybook/addon-actions';
|
|
2
|
+
import { storiesOf } from '@storybook/react-native';
|
|
3
|
+
import { ApolloError } from '@apollo/client';
|
|
4
|
+
import { StoryDecorator } from '@ornikar/kitt-universal';
|
|
5
|
+
import { NotificationProvider } from '@ornikar/react-notification';
|
|
6
|
+
import {
|
|
7
|
+
ThirdPartyServiceStatusEnum,
|
|
8
|
+
ThirdPartyServiceTypeEnum,
|
|
9
|
+
} from '@ornikar/learner-apps-shared/src/__generated__/globalTypes';
|
|
10
|
+
import {
|
|
11
|
+
mockLearningChaptersEmptyError,
|
|
12
|
+
mockLearningChaptersWithCourses,
|
|
13
|
+
mockLearningChaptersWithCoursesQueryBuilder,
|
|
14
|
+
} from '@ornikar/learner-apps-shared/src/shared/apollo/mocks/learningChaptersWithCoursesMock';
|
|
15
|
+
import {
|
|
16
|
+
getThirdPartyService,
|
|
17
|
+
mockThirdPartyServiceQueryBuilder,
|
|
18
|
+
} from '@ornikar/learner-apps-shared/src/shared/apollo/mocks/thirdPartyService';
|
|
19
|
+
import { ApolloDecorator } from '../../../../../../../storybook/decorators/ApolloDecorator';
|
|
20
|
+
import {
|
|
21
|
+
DrivingDashboardLearningChaptersModalView,
|
|
22
|
+
LearningChaptersModalBodyWrapper,
|
|
23
|
+
} from './DrivingDashboardLearningChaptersModalView';
|
|
24
|
+
|
|
25
|
+
storiesOf('LAS/driving/dashboard/components/DrivingDashboardLearningChaptersModal', module)
|
|
26
|
+
.addDecorator(StoryDecorator as any)
|
|
27
|
+
.addDecorator(ApolloDecorator)
|
|
28
|
+
.add('Default', () => <DrivingDashboardLearningChaptersModalView visible onClose={action('onClose')} />, {
|
|
29
|
+
apollo: {
|
|
30
|
+
mocks: [
|
|
31
|
+
mockThirdPartyServiceQueryBuilder(
|
|
32
|
+
ThirdPartyServiceTypeEnum.NORTHPASS,
|
|
33
|
+
getThirdPartyService(ThirdPartyServiceTypeEnum.NORTHPASS, ThirdPartyServiceStatusEnum.UP),
|
|
34
|
+
),
|
|
35
|
+
mockLearningChaptersWithCoursesQueryBuilder(mockLearningChaptersWithCourses),
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
jest: {
|
|
39
|
+
ignore: true,
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
.add('Empty chapters', () => <LearningChaptersModalBodyWrapper visible />, {
|
|
43
|
+
apollo: {
|
|
44
|
+
mocks: [
|
|
45
|
+
mockThirdPartyServiceQueryBuilder(
|
|
46
|
+
ThirdPartyServiceTypeEnum.NORTHPASS,
|
|
47
|
+
getThirdPartyService(ThirdPartyServiceTypeEnum.NORTHPASS, ThirdPartyServiceStatusEnum.UP),
|
|
48
|
+
),
|
|
49
|
+
mockLearningChaptersWithCoursesQueryBuilder(mockLearningChaptersEmptyError),
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
jest: {
|
|
53
|
+
ignore: true,
|
|
54
|
+
},
|
|
55
|
+
})
|
|
56
|
+
.add(
|
|
57
|
+
'Error',
|
|
58
|
+
() => (
|
|
59
|
+
<NotificationProvider>
|
|
60
|
+
<DrivingDashboardLearningChaptersModalView visible onClose={action('onClose')} />
|
|
61
|
+
</NotificationProvider>
|
|
62
|
+
),
|
|
63
|
+
{
|
|
64
|
+
apollo: {
|
|
65
|
+
mocks: [
|
|
66
|
+
mockThirdPartyServiceQueryBuilder(
|
|
67
|
+
ThirdPartyServiceTypeEnum.NORTHPASS,
|
|
68
|
+
getThirdPartyService(ThirdPartyServiceTypeEnum.NORTHPASS, ThirdPartyServiceStatusEnum.DOWN),
|
|
69
|
+
),
|
|
70
|
+
mockLearningChaptersWithCoursesQueryBuilder(mockLearningChaptersEmptyError, new ApolloError({})),
|
|
71
|
+
],
|
|
72
|
+
},
|
|
73
|
+
jest: {
|
|
74
|
+
ignore: true,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
);
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { action } from '@storybook/addon-actions';
|
|
2
|
+
import type { ComponentMeta, ComponentStory } from '@storybook/react-native';
|
|
3
|
+
import { ApolloError } from '@apollo/client';
|
|
4
|
+
import { StoryDecorator } from '@ornikar/kitt-universal';
|
|
5
|
+
import { NotificationProvider } from '@ornikar/react-notification';
|
|
6
|
+
import {
|
|
7
|
+
ThirdPartyServiceStatusEnum,
|
|
8
|
+
ThirdPartyServiceTypeEnum,
|
|
9
|
+
} from '@ornikar/learner-apps-shared/src/__generated__/globalTypes';
|
|
10
|
+
import {
|
|
11
|
+
mockLearningChaptersEmptyError,
|
|
12
|
+
mockLearningChaptersWithCourses,
|
|
13
|
+
mockLearningChaptersWithCoursesQueryBuilder,
|
|
14
|
+
} from '@ornikar/learner-apps-shared/src/shared/apollo/mocks/learningChaptersWithCoursesMock';
|
|
15
|
+
import {
|
|
16
|
+
getThirdPartyService,
|
|
17
|
+
mockThirdPartyServiceQueryBuilder,
|
|
18
|
+
} from '@ornikar/learner-apps-shared/src/shared/apollo/mocks/thirdPartyService';
|
|
19
|
+
import { ApolloDecorator } from '../../../../../../../storybook/decorators/ApolloDecorator';
|
|
20
|
+
import {
|
|
21
|
+
DrivingDashboardLearningChaptersModalView,
|
|
22
|
+
LearningChaptersModalBodyWrapper,
|
|
23
|
+
} from './DrivingDashboardLearningChaptersModalView';
|
|
24
|
+
|
|
25
|
+
export default {
|
|
26
|
+
title: 'LAS/driving/dashboard/components/DrivingDashboardLearningChaptersModal',
|
|
27
|
+
component: DrivingDashboardLearningChaptersModalView,
|
|
28
|
+
decorators: [StoryDecorator, ApolloDecorator],
|
|
29
|
+
} satisfies ComponentMeta<typeof DrivingDashboardLearningChaptersModalView>;
|
|
30
|
+
|
|
31
|
+
export const DefaultStory: ComponentStory<typeof DrivingDashboardLearningChaptersModalView> = () => (
|
|
32
|
+
<DrivingDashboardLearningChaptersModalView visible onClose={action('onClose')} />
|
|
33
|
+
);
|
|
34
|
+
DefaultStory.storyName = 'Default';
|
|
35
|
+
|
|
36
|
+
DefaultStory.parameters = {
|
|
37
|
+
apollo: {
|
|
38
|
+
mocks: [
|
|
39
|
+
mockThirdPartyServiceQueryBuilder(
|
|
40
|
+
ThirdPartyServiceTypeEnum.NORTHPASS,
|
|
41
|
+
getThirdPartyService(ThirdPartyServiceTypeEnum.NORTHPASS, ThirdPartyServiceStatusEnum.UP),
|
|
42
|
+
),
|
|
43
|
+
mockLearningChaptersWithCoursesQueryBuilder(mockLearningChaptersWithCourses),
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
jest: {
|
|
47
|
+
ignore: true,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export const EmptyChaptersStory: ComponentStory<typeof DrivingDashboardLearningChaptersModalView> = () => (
|
|
52
|
+
<LearningChaptersModalBodyWrapper visible />
|
|
53
|
+
);
|
|
54
|
+
EmptyChaptersStory.storyName = 'Empty chapters';
|
|
55
|
+
|
|
56
|
+
EmptyChaptersStory.parameters = {
|
|
57
|
+
apollo: {
|
|
58
|
+
mocks: [
|
|
59
|
+
mockThirdPartyServiceQueryBuilder(
|
|
60
|
+
ThirdPartyServiceTypeEnum.NORTHPASS,
|
|
61
|
+
getThirdPartyService(ThirdPartyServiceTypeEnum.NORTHPASS, ThirdPartyServiceStatusEnum.UP),
|
|
62
|
+
),
|
|
63
|
+
mockLearningChaptersWithCoursesQueryBuilder(mockLearningChaptersEmptyError),
|
|
64
|
+
],
|
|
65
|
+
},
|
|
66
|
+
jest: {
|
|
67
|
+
ignore: true,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export const ErrorStory: ComponentStory<typeof DrivingDashboardLearningChaptersModalView> = () => (
|
|
72
|
+
<NotificationProvider>
|
|
73
|
+
<DrivingDashboardLearningChaptersModalView visible onClose={action('onClose')} />
|
|
74
|
+
</NotificationProvider>
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
ErrorStory.storyName = 'Error';
|
|
78
|
+
|
|
79
|
+
ErrorStory.parameters = {
|
|
80
|
+
apollo: {
|
|
81
|
+
mocks: [
|
|
82
|
+
mockThirdPartyServiceQueryBuilder(
|
|
83
|
+
ThirdPartyServiceTypeEnum.NORTHPASS,
|
|
84
|
+
getThirdPartyService(ThirdPartyServiceTypeEnum.NORTHPASS, ThirdPartyServiceStatusEnum.DOWN),
|
|
85
|
+
),
|
|
86
|
+
mockLearningChaptersWithCoursesQueryBuilder(mockLearningChaptersEmptyError, new ApolloError({})),
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
jest: {
|
|
90
|
+
ignore: true,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
jest.autoMockOff();
|
|
4
4
|
const { defineTest } = require('jscodeshift/dist/testUtils');
|
|
5
5
|
|
|
6
|
-
const tests = ['default', 'decorator', 'parameters'];
|
|
6
|
+
const tests = ['default', 'decorator', 'parameters', 'new'];
|
|
7
7
|
|
|
8
8
|
describe('CSF1-CSF2 Migration', () => {
|
|
9
9
|
tests.forEach((test) => defineTest(__dirname, 'csf1-csf2', null, `csf1-csf2/${test}`, { parser: 'tsx' }));
|
|
@@ -41,27 +41,23 @@ module.exports = async function transformer(fileInfo, api) {
|
|
|
41
41
|
hasTransformation = true;
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
// Find storiesOf()
|
|
44
|
+
// Find storiesOf() chains - look for any expression that contains storiesOf
|
|
45
45
|
const storiesOfStatements = root.find(j.ExpressionStatement).filter((path) => {
|
|
46
46
|
const expression = path.node.expression;
|
|
47
|
-
if (expression.type !== 'CallExpression'
|
|
48
|
-
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
if (current.type === 'CallExpression' && current.callee && current.callee.type === 'MemberExpression') {
|
|
58
|
-
current = current.callee.object;
|
|
59
|
-
} else {
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
47
|
+
if (expression.type !== 'CallExpression') return false;
|
|
48
|
+
|
|
49
|
+
// Look for storiesOf anywhere in the call chain
|
|
50
|
+
function containsStoriesOf(node) {
|
|
51
|
+
if (node.type === 'CallExpression' && node.callee && node.callee.name === 'storiesOf') {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
if (node.type === 'CallExpression' && node.callee && node.callee.type === 'MemberExpression') {
|
|
55
|
+
return containsStoriesOf(node.callee.object);
|
|
62
56
|
}
|
|
57
|
+
return false;
|
|
63
58
|
}
|
|
64
|
-
|
|
59
|
+
|
|
60
|
+
return containsStoriesOf(expression);
|
|
65
61
|
});
|
|
66
62
|
|
|
67
63
|
if (storiesOfStatements.length > 0) {
|
|
@@ -71,35 +67,62 @@ module.exports = async function transformer(fileInfo, api) {
|
|
|
71
67
|
storiesOfStatements.forEach((path) => {
|
|
72
68
|
const expression = path.node.expression;
|
|
73
69
|
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
70
|
+
// Parse the entire call chain to extract all stories, decorators, and parameters
|
|
71
|
+
function parseStoriesChain(node) {
|
|
72
|
+
const stories = [];
|
|
73
|
+
const decorators = [];
|
|
74
|
+
let globalParameters = null;
|
|
75
|
+
let storiesOfCall = null;
|
|
76
|
+
|
|
77
|
+
function walkChain(current) {
|
|
78
|
+
if (current.type === 'CallExpression' && current.callee) {
|
|
79
|
+
if (current.callee.name === 'storiesOf') {
|
|
80
|
+
// Found the root storiesOf call
|
|
81
|
+
storiesOfCall = current;
|
|
82
|
+
} else if (current.callee.type === 'MemberExpression') {
|
|
83
|
+
const methodName = current.callee.property.name;
|
|
84
|
+
|
|
85
|
+
if (methodName === 'add') {
|
|
86
|
+
// Extract story information
|
|
87
|
+
const storyName = current.arguments[0].value;
|
|
88
|
+
const componentFunction = current.arguments[1];
|
|
89
|
+
const storyParameters = current.arguments[2]; // Third argument contains parameters
|
|
90
|
+
|
|
91
|
+
stories.push({
|
|
92
|
+
name: storyName,
|
|
93
|
+
component: componentFunction,
|
|
94
|
+
parameters: storyParameters,
|
|
95
|
+
});
|
|
96
|
+
} else if (methodName === 'addDecorator') {
|
|
97
|
+
let decorator = current.arguments[0];
|
|
98
|
+
// Remove 'as any' type assertions from decorators
|
|
99
|
+
if (decorator.type === 'TSAsExpression' && decorator.typeAnnotation.type === 'TSAnyKeyword') {
|
|
100
|
+
decorator = decorator.expression;
|
|
101
|
+
}
|
|
102
|
+
decorators.push(decorator); // Collect decorators in order
|
|
103
|
+
} else if (methodName === 'addParameters') {
|
|
104
|
+
globalParameters = current.arguments[0];
|
|
105
|
+
}
|
|
83
106
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
if (current.type === 'CallExpression' && current.callee && current.callee.type === 'MemberExpression') {
|
|
90
|
-
const methodName = current.callee.property.name;
|
|
91
|
-
if (methodName === 'addDecorator') {
|
|
92
|
-
decorators.push(current.arguments[0]);
|
|
93
|
-
} else if (methodName === 'addParameters') {
|
|
94
|
-
parameters = current.arguments[0];
|
|
107
|
+
// Continue walking up the chain
|
|
108
|
+
walkChain(current.callee.object);
|
|
109
|
+
}
|
|
95
110
|
}
|
|
96
|
-
current = current.callee.object;
|
|
97
|
-
} else {
|
|
98
|
-
break;
|
|
99
111
|
}
|
|
112
|
+
|
|
113
|
+
walkChain(node);
|
|
114
|
+
|
|
115
|
+
return {
|
|
116
|
+
stories: stories.reverse(), // Reverse to get correct order
|
|
117
|
+
decorators: decorators.reverse(), // Reverse to get correct order
|
|
118
|
+
globalParameters,
|
|
119
|
+
storiesOfCall,
|
|
120
|
+
};
|
|
100
121
|
}
|
|
101
122
|
|
|
102
|
-
|
|
123
|
+
const { stories, decorators, globalParameters, storiesOfCall } = parseStoriesChain(expression);
|
|
124
|
+
|
|
125
|
+
if (!storiesOfCall || stories.length === 0) return;
|
|
103
126
|
|
|
104
127
|
let storyTitle = storiesOfCall.arguments[0].value;
|
|
105
128
|
|
|
@@ -108,11 +131,7 @@ module.exports = async function transformer(fileInfo, api) {
|
|
|
108
131
|
storyTitle = 'LNA/authentication/pages';
|
|
109
132
|
}
|
|
110
133
|
|
|
111
|
-
|
|
112
|
-
storyName = 'WelcomePage';
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Extract component name from the component function
|
|
134
|
+
// Extract component name from the first story's component function
|
|
116
135
|
let componentName = 'Component'; // Default fallback
|
|
117
136
|
|
|
118
137
|
function findComponentInJSX(jsxElement) {
|
|
@@ -157,20 +176,28 @@ module.exports = async function transformer(fileInfo, api) {
|
|
|
157
176
|
return allComponents.length > 0 ? allComponents[0] : jsxElement.openingElement.name.name;
|
|
158
177
|
}
|
|
159
178
|
|
|
160
|
-
|
|
161
|
-
if (componentFunction.
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
179
|
+
function extractComponentName(componentFunction) {
|
|
180
|
+
if (componentFunction.type === 'ArrowFunctionExpression') {
|
|
181
|
+
if (componentFunction.body.type === 'JSXElement') {
|
|
182
|
+
return findComponentInJSX(componentFunction.body);
|
|
183
|
+
} else if (componentFunction.body.type === 'BlockStatement') {
|
|
184
|
+
// Look for JSX return statement
|
|
185
|
+
const returnStatement = componentFunction.body.body.find(
|
|
186
|
+
(stmt) => stmt.type === 'ReturnStatement' && stmt.argument && stmt.argument.type === 'JSXElement',
|
|
187
|
+
);
|
|
188
|
+
if (returnStatement) {
|
|
189
|
+
return findComponentInJSX(returnStatement.argument);
|
|
190
|
+
}
|
|
170
191
|
}
|
|
192
|
+
} else if (componentFunction.type === 'FunctionExpression') {
|
|
193
|
+
// Similar logic for function expressions if needed
|
|
171
194
|
}
|
|
172
|
-
|
|
173
|
-
|
|
195
|
+
return 'Component';
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Use the first story to determine the main component
|
|
199
|
+
if (stories.length > 0) {
|
|
200
|
+
componentName = extractComponentName(stories[0].component);
|
|
174
201
|
}
|
|
175
202
|
|
|
176
203
|
// Create default export properties in the exact order needed
|
|
@@ -182,8 +209,8 @@ module.exports = async function transformer(fileInfo, api) {
|
|
|
182
209
|
props.push(j.property('init', j.identifier('decorators'), j.arrayExpression(decorators)));
|
|
183
210
|
}
|
|
184
211
|
|
|
185
|
-
if (
|
|
186
|
-
props.push(j.property('init', j.identifier('parameters'),
|
|
212
|
+
if (globalParameters) {
|
|
213
|
+
props.push(j.property('init', j.identifier('parameters'), globalParameters));
|
|
187
214
|
}
|
|
188
215
|
|
|
189
216
|
const objExpression = j.objectExpression(props);
|
|
@@ -198,30 +225,69 @@ module.exports = async function transformer(fileInfo, api) {
|
|
|
198
225
|
),
|
|
199
226
|
);
|
|
200
227
|
|
|
201
|
-
//
|
|
202
|
-
|
|
203
|
-
const storyIdentifier = j.identifier(storyExportName);
|
|
204
|
-
storyIdentifier.typeAnnotation = j.tsTypeAnnotation(
|
|
205
|
-
j.tsTypeReference(
|
|
206
|
-
j.identifier('ComponentStory'),
|
|
207
|
-
j.tsTypeParameterInstantiation([j.tsTypeQuery(j.identifier(componentName))]),
|
|
208
|
-
),
|
|
209
|
-
);
|
|
228
|
+
// Add the default export first
|
|
229
|
+
newExports.push(defaultExport);
|
|
210
230
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
231
|
+
// Process each story
|
|
232
|
+
stories.forEach((story) => {
|
|
233
|
+
let storyName = story.name;
|
|
214
234
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
j.memberExpression(j.identifier(storyExportName), j.identifier('storyName')),
|
|
220
|
-
j.literal(storyName),
|
|
221
|
-
),
|
|
222
|
-
);
|
|
235
|
+
// Normalize story names
|
|
236
|
+
if (storyName === 'WelcomePageView') {
|
|
237
|
+
storyName = 'WelcomePage';
|
|
238
|
+
}
|
|
223
239
|
|
|
224
|
-
|
|
240
|
+
// Create named export for the story with TypeScript type annotation
|
|
241
|
+
// Sanitize story name to create valid JavaScript identifier
|
|
242
|
+
function sanitizeStoryName(name) {
|
|
243
|
+
// Special case: remove "(default)" suffix as it's redundant in CSF2
|
|
244
|
+
let sanitized = name.replace(/\s*\(default\)\s*$/i, '');
|
|
245
|
+
|
|
246
|
+
// Remove special characters and normalize spacing while preserving word boundaries
|
|
247
|
+
return sanitized
|
|
248
|
+
.replace(/[^a-zA-Z0-9\s]/g, '') // Remove special characters
|
|
249
|
+
.split(/\s+/) // Split on whitespace
|
|
250
|
+
.filter((word) => word.length > 0) // Remove empty parts
|
|
251
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
252
|
+
.join('');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
const storyExportName = sanitizeStoryName(storyName) + 'Story';
|
|
256
|
+
const storyIdentifier = j.identifier(storyExportName);
|
|
257
|
+
storyIdentifier.typeAnnotation = j.tsTypeAnnotation(
|
|
258
|
+
j.tsTypeReference(
|
|
259
|
+
j.identifier('ComponentStory'),
|
|
260
|
+
j.tsTypeParameterInstantiation([j.tsTypeQuery(j.identifier(componentName))]),
|
|
261
|
+
),
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
const namedExport = j.exportNamedDeclaration(
|
|
265
|
+
j.variableDeclaration('const', [j.variableDeclarator(storyIdentifier, story.component)]),
|
|
266
|
+
);
|
|
267
|
+
|
|
268
|
+
// Create storyName assignment
|
|
269
|
+
const storyNameAssignment = j.expressionStatement(
|
|
270
|
+
j.assignmentExpression(
|
|
271
|
+
'=',
|
|
272
|
+
j.memberExpression(j.identifier(storyExportName), j.identifier('storyName')),
|
|
273
|
+
j.literal(storyName),
|
|
274
|
+
),
|
|
275
|
+
);
|
|
276
|
+
|
|
277
|
+
newExports.push(namedExport, storyNameAssignment);
|
|
278
|
+
|
|
279
|
+
// Add parameters if the story has them
|
|
280
|
+
if (story.parameters) {
|
|
281
|
+
const parametersAssignment = j.expressionStatement(
|
|
282
|
+
j.assignmentExpression(
|
|
283
|
+
'=',
|
|
284
|
+
j.memberExpression(j.identifier(storyExportName), j.identifier('parameters')),
|
|
285
|
+
story.parameters,
|
|
286
|
+
),
|
|
287
|
+
);
|
|
288
|
+
newExports.push(parametersAssignment);
|
|
289
|
+
}
|
|
290
|
+
});
|
|
225
291
|
|
|
226
292
|
// Remove the original statement
|
|
227
293
|
j(path).remove();
|