@kaizen/components 0.0.0-canary-04-titleblock-logic-20251211225600 → 0.0.0-canary-guidance-block-codemod-20251212045145

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.
Files changed (44) hide show
  1. package/codemods/migrateGuidanceBlockActionsToActionsSlot/migrateGuidanceBlockActionsToActionsSlot.spec.ts +209 -26
  2. package/codemods/migrateGuidanceBlockActionsToActionsSlot/migrateGuidanceBlockActionsToActionsSlot.ts +24 -1
  3. package/codemods/migrateGuidanceBlockActionsToActionsSlot/transformActionsToActionsSlot.spec.ts +2 -1
  4. package/codemods/migrateGuidanceBlockActionsToActionsSlot/transformActionsToActionsSlot.ts +20 -0
  5. package/codemods/runV1Codemods/__snapshots__/runV1Codemods.spec.ts.snap +2 -3
  6. package/codemods/runV1Codemods/runV1Codemods.spec.ts +2 -3
  7. package/codemods/utils/transformV1ButtonPropsToButtonOrLinkButton.ts +40 -0
  8. package/dist/cjs/src/MenuV1/index.cjs +3 -4
  9. package/dist/cjs/src/MenuV1/subcomponents/MenuHeading/MenuHeading.cjs +27 -0
  10. package/dist/cjs/src/MenuV1/subcomponents/MenuHeading/MenuHeading.module.scss.cjs +6 -0
  11. package/dist/cjs/src/TitleBlock/TitleBlock.cjs +36 -32
  12. package/dist/cjs/src/TitleBlock/TitleBlock.module.scss.cjs +1 -5
  13. package/dist/cjs/src/TitleBlock/subcomponents/MainActions.cjs +45 -90
  14. package/dist/cjs/src/TitleBlock/subcomponents/MainActions.module.scss.cjs +1 -3
  15. package/dist/cjs/src/TitleBlock/subcomponents/MobileActions.cjs +306 -0
  16. package/dist/cjs/src/TitleBlock/subcomponents/MobileActions.module.scss.cjs +16 -0
  17. package/dist/cjs/src/TitleBlock/subcomponents/SecondaryActions.cjs +14 -60
  18. package/dist/esm/src/MenuV1/index.mjs +3 -5
  19. package/dist/esm/src/MenuV1/subcomponents/MenuHeading/MenuHeading.mjs +21 -0
  20. package/dist/esm/src/MenuV1/subcomponents/MenuHeading/MenuHeading.module.scss.mjs +4 -0
  21. package/dist/esm/src/TitleBlock/TitleBlock.mjs +37 -33
  22. package/dist/esm/src/TitleBlock/TitleBlock.module.scss.mjs +1 -5
  23. package/dist/esm/src/TitleBlock/subcomponents/MainActions.mjs +47 -92
  24. package/dist/esm/src/TitleBlock/subcomponents/MainActions.module.scss.mjs +1 -3
  25. package/dist/esm/src/TitleBlock/subcomponents/MobileActions.mjs +300 -0
  26. package/dist/esm/src/TitleBlock/subcomponents/MobileActions.module.scss.mjs +14 -0
  27. package/dist/esm/src/TitleBlock/subcomponents/SecondaryActions.mjs +14 -60
  28. package/dist/styles.css +206 -82
  29. package/dist/types/TitleBlock/TitleBlock.d.ts +1 -1
  30. package/dist/types/TitleBlock/subcomponents/MainActions.d.ts +3 -4
  31. package/dist/types/TitleBlock/subcomponents/MobileActions.d.ts +14 -0
  32. package/package.json +1 -1
  33. package/src/TitleBlock/TitleBlock.module.scss +14 -55
  34. package/src/TitleBlock/TitleBlock.spec.tsx +461 -33
  35. package/src/TitleBlock/TitleBlock.tsx +24 -7
  36. package/src/TitleBlock/_docs/TitleBlock.stories.tsx +5 -25
  37. package/src/TitleBlock/_mixins.scss +0 -6
  38. package/src/TitleBlock/subcomponents/MainActions.module.scss +2 -28
  39. package/src/TitleBlock/subcomponents/MainActions.tsx +70 -127
  40. package/src/TitleBlock/subcomponents/MobileActions.module.scss +208 -0
  41. package/src/TitleBlock/subcomponents/MobileActions.spec.tsx +210 -0
  42. package/src/TitleBlock/subcomponents/MobileActions.tsx +472 -0
  43. package/src/TitleBlock/subcomponents/SecondaryActions.tsx +45 -114
  44. package/src/TitleBlock/subcomponents/Toolbar.tsx +0 -1
@@ -15,9 +15,10 @@ const transformGuidanceBlock = (sourceFile: TransformSourceArgs['sourceFile']):
15
15
  })
16
16
  }
17
17
 
18
- describe('transformActionsToButtonNext()', () => {
19
- it('imports Button from the /next path and transforms all button-like actions prop into a Button component', () => {
20
- const inputAst = parseJsx(`
18
+ describe('migrateGuidanceBlockActionsToActionsSlot()', () => {
19
+ describe('basic transformation', () => {
20
+ it('imports Button and transforms all button-like actions prop into a Button component', () => {
21
+ const inputAst = parseJsx(`
21
22
  import { GuidanceBlock } from "@kaizen/components"
22
23
  <GuidanceBlock
23
24
  layout="default"
@@ -34,21 +35,21 @@ describe('transformActionsToButtonNext()', () => {
34
35
  },
35
36
  }}
36
37
  />`)
37
- const outputAst = parseJsx(`
38
- import { GuidanceBlock } from "@kaizen/components"
39
- import { Button } from "@kaizen/components/next"
38
+ const outputAst = parseJsx(`
39
+ import { GuidanceBlock, Button, Icon } from "@kaizen/components"
40
40
  <GuidanceBlock
41
41
  layout="default"
42
42
  illustration={<Informative alt="" />}
43
43
  content={<div>Test</div>}
44
- actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large">Primary action</Button><Button onPress={() => alert('click 2')} variant="tertiary" size="large">Secondary action</Button></>}
44
+ actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large" icon={<Icon name="arrow_forward" shouldMirrorInRTL isPresentational />} iconPosition="end">Primary action</Button><Button onPress={() => alert('click 2')} variant="tertiary" size="large">Secondary action</Button></>}
45
45
  />
46
46
  `)
47
47
 
48
- expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
49
- })
50
- it('imports and transforms all button-like and link-like actions prop into a Button and LinkButton', () => {
51
- const inputAst = parseJsx(`
48
+ expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
49
+ })
50
+
51
+ it('imports and transforms all button-like and link-like actions prop into a Button and LinkButton', () => {
52
+ const inputAst = parseJsx(`
52
53
  import { GuidanceBlock } from "@kaizen/components"
53
54
  <GuidanceBlock
54
55
  layout="default"
@@ -65,23 +66,22 @@ describe('transformActionsToButtonNext()', () => {
65
66
  },
66
67
  }}
67
68
  />`)
68
- const outputAst = parseJsx(`
69
- import { GuidanceBlock, LinkButton } from "@kaizen/components"
70
- import { Button } from "@kaizen/components/next"
69
+ const outputAst = parseJsx(`
70
+ import {GuidanceBlock, Button, LinkButton, Icon } from "@kaizen/components"
71
71
  <GuidanceBlock
72
72
  layout="default"
73
73
  illustration={<Informative alt="" />}
74
74
  content={<div>Test</div>}
75
- actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large">Primary action</Button><LinkButton href="#secondary" variant="tertiary" size="large">Secondary action</LinkButton></>}
75
+ actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large" icon={<Icon name="arrow_forward" shouldMirrorInRTL isPresentational />} iconPosition="end">Primary action</Button><LinkButton href="#secondary" variant="tertiary" size="large">Secondary action</LinkButton></>}
76
76
  />
77
77
  `)
78
78
 
79
- expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
80
- })
81
- it('does not redeclare imports if found', () => {
82
- const inputAst = parseJsx(`
83
- import { GuidanceBlock } from "@kaizen/components"
84
- import { Button } from "@kaizen/components/next"
79
+ expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
80
+ })
81
+
82
+ it('does not redeclare imports if found', () => {
83
+ const inputAst = parseJsx(`
84
+ import { Button, GuidanceBlock } from "@kaizen/components"
85
85
  const MockLayout = () => (
86
86
  <>
87
87
  <GuidanceBlock
@@ -102,21 +102,204 @@ describe('transformActionsToButtonNext()', () => {
102
102
  <Button onPress={() => alert('page click 1')} variant="primary" size="large">Page button</Button>
103
103
  </>
104
104
  )`)
105
- const outputAst = parseJsx(`
106
- import { GuidanceBlock, LinkButton } from "@kaizen/components"
107
- import { Button } from "@kaizen/components/next"
105
+ const outputAst = parseJsx(`
106
+ import { Button, GuidanceBlock, LinkButton, Icon } from "@kaizen/components"
108
107
  const MockLayout = () => (
109
108
  <>
110
109
  <GuidanceBlock
111
110
  layout="default"
112
111
  illustration={<Informative alt="" />}
113
112
  content={<div>Test</div>}
114
- actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large">Primary action</Button><LinkButton href="#secondary" variant="tertiary" size="large">Secondary action</LinkButton></>}
113
+ actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large" icon={<Icon name="arrow_forward" shouldMirrorInRTL isPresentational />} iconPosition="end">Primary action</Button><LinkButton href="#secondary" variant="tertiary" size="large">Secondary action</LinkButton></>}
115
114
  />
116
115
  <Button onPress={() => alert('page click 1')} variant="primary" size="large">Page button</Button>
117
116
  </>
118
117
  )`)
119
118
 
120
- expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
119
+ expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
120
+ })
121
+
122
+ it('preserves custom icon components without adding Icon import', () => {
123
+ const inputAst = parseJsx(`
124
+ import { GuidanceBlock } from "@kaizen/components"
125
+ <GuidanceBlock
126
+ actions={{
127
+ primary: {
128
+ label: 'Action',
129
+ onClick: () => {},
130
+ icon: <MyCustomIcon />,
131
+ iconPosition: 'end',
132
+ },
133
+ }}
134
+ />`)
135
+ const outputAst = parseJsx(`
136
+ import { GuidanceBlock, Button } from "@kaizen/components"
137
+ <GuidanceBlock
138
+ actionsSlot={<><Button onPress={() => {}} icon={<MyCustomIcon />} iconPosition='end' variant="secondary" size="large">Action</Button></>}
139
+ />
140
+ `)
141
+
142
+ expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
143
+ })
144
+
145
+ describe('arrow icon handling', () => {
146
+ // When withActionButtonArrow not specified, add arrow icon actionsSlot secondary Button
147
+ it('adds arrow icon to actionsSlot secondary Button when withActionButtonArrow is not explicitly set', () => {
148
+ const inputAst = parseJsx(`
149
+ import { GuidanceBlock, LinkButton } from "@kaizen/components"
150
+ <GuidanceBlock
151
+ layout="default"
152
+ illustration={<Informative alt="" />}
153
+ content={<div>Test</div>}
154
+ actions={{
155
+ primary: {
156
+ label: 'Primary action',
157
+ onClick: () => alert('click 1'),
158
+ },
159
+ secondary: {
160
+ label: 'Secondary action',
161
+ href: "#secondary"
162
+ },
163
+ }}
164
+ />`)
165
+ const outputAst = parseJsx(`
166
+ import { GuidanceBlock, LinkButton, Button, Icon } from "@kaizen/components"
167
+ <GuidanceBlock
168
+ layout="default"
169
+ illustration={<Informative alt="" />}
170
+ content={<div>Test</div>}
171
+ actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large" icon={<Icon name="arrow_forward" shouldMirrorInRTL isPresentational />} iconPosition="end">Primary action</Button><LinkButton href="#secondary" variant="tertiary" size="large">Secondary action</LinkButton></>}
172
+ />
173
+ `)
174
+
175
+ expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
176
+ })
177
+
178
+ // When withActionButtonArrow is set to true, add arrow icon to actionsSlot secondary Button
179
+ it('adds arrow icon to actionsSlot secondary Button when withActionButtonArrow is true', () => {
180
+ const inputAst = parseJsx(`
181
+ import { GuidanceBlock } from "@kaizen/components"
182
+ <GuidanceBlock
183
+ layout="default"
184
+ illustration={<Informative alt="" />}
185
+ content={<div>Test</div>}
186
+ withActionButtonArrow={true}
187
+ actions={{
188
+ primary: {
189
+ label: 'Primary action',
190
+ onClick: () => alert('click 1'),
191
+ },
192
+ secondary: {
193
+ label: 'Secondary action',
194
+ href: "#secondary"
195
+ },
196
+ }}
197
+ />`)
198
+ const outputAst = parseJsx(`
199
+ import { GuidanceBlock, Button, LinkButton, Icon } from "@kaizen/components"
200
+ <GuidanceBlock
201
+ layout="default"
202
+ illustration={<Informative alt="" />}
203
+ content={<div>Test</div>}
204
+ actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large" icon={<Icon name="arrow_forward" shouldMirrorInRTL isPresentational />} iconPosition="end">Primary action</Button><LinkButton href="#secondary" variant="tertiary" size="large">Secondary action</LinkButton></>}
205
+ />
206
+ `)
207
+
208
+ expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
209
+ })
210
+
211
+ // When withActionButtonArrow is explicitly false, do not add arrow icon to actionsSlot secondary Button
212
+ it('does not add arrow icon to actionsSlot secondary Button when withActionButtonArrow is false', () => {
213
+ const inputAst = parseJsx(`
214
+ import { GuidanceBlock } from "@kaizen/components"
215
+ <GuidanceBlock
216
+ layout="default"
217
+ illustration={<Informative alt="" />}
218
+ content={<div>Test</div>}
219
+ withActionButtonArrow={false}
220
+ actions={{
221
+ primary: {
222
+ label: 'Primary action',
223
+ onClick: () => alert('click 1'),
224
+ },
225
+ secondary: {
226
+ label: 'Secondary action',
227
+ href: "#secondary"
228
+ },
229
+ }}
230
+ />`)
231
+ const outputAst = parseJsx(`
232
+ import { GuidanceBlock, Button, LinkButton } from "@kaizen/components"
233
+ <GuidanceBlock
234
+ layout="default"
235
+ illustration={<Informative alt="" />}
236
+ content={<div>Test</div>}
237
+ actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large">Primary action</Button><LinkButton href="#secondary" variant="tertiary" size="large">Secondary action</LinkButton></>}
238
+ />
239
+ `)
240
+
241
+ expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
242
+ })
243
+ })
244
+
245
+ describe('removes deprecated props', () => {
246
+ it('removes withActionButtonArrow prop', () => {
247
+ const inputAst = parseJsx(`
248
+ import { GuidanceBlock } from "@kaizen/components"
249
+ <GuidanceBlock
250
+ layout="default"
251
+ illustration={<Informative alt="" />}
252
+ content={<div>Test</div>}
253
+ withActionButtonArrow={true}
254
+ actions={{
255
+ primary: {
256
+ label: 'Primary action',
257
+ onClick: () => alert('click 1'),
258
+ },
259
+ }}
260
+ />
261
+ `)
262
+ const outputAst = parseJsx(`
263
+ import { GuidanceBlock, Button, Icon } from "@kaizen/components"
264
+ <GuidanceBlock
265
+ layout="default"
266
+ illustration={<Informative alt="" />}
267
+ content={<div>Test</div>}
268
+ actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large" icon={<Icon name="arrow_forward" shouldMirrorInRTL isPresentational />} iconPosition="end">Primary action</Button></>}
269
+ />
270
+ `)
271
+
272
+ expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
273
+ })
274
+
275
+ it('removes secondaryDismiss prop', () => {
276
+ const inputAst = parseJsx(`
277
+ import { GuidanceBlock } from "@kaizen/components"
278
+ <GuidanceBlock
279
+ layout="default"
280
+ illustration={<Informative alt="" />}
281
+ content={<div>Test</div>}
282
+ secondaryDismiss={true}
283
+ actions={{
284
+ primary: {
285
+ label: 'Primary action',
286
+ onClick: () => alert('click 1'),
287
+ },
288
+ }}
289
+ />
290
+ `)
291
+ const outputAst = parseJsx(`
292
+ import {GuidanceBlock, Button, Icon } from "@kaizen/components"
293
+ <GuidanceBlock
294
+ layout="default"
295
+ illustration={<Informative alt="" />}
296
+ content={<div>Test</div>}
297
+ actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large" icon={<Icon name="arrow_forward" shouldMirrorInRTL isPresentational />} iconPosition="end">Primary action</Button></>}
298
+ />
299
+ `)
300
+
301
+ expect(transformGuidanceBlock(inputAst)).toBe(printAst(outputAst))
302
+ })
303
+ })
121
304
  })
122
305
  })
@@ -8,8 +8,9 @@ import {
8
8
  } from '../utils'
9
9
  import { transformActionsToActionsSlot } from './transformActionsToActionsSlot'
10
10
 
11
- const BUTTON_IMPORT_DESTINATION = '@kaizen/components/next'
11
+ const BUTTON_IMPORT_DESTINATION = '@kaizen/components'
12
12
  const LINKBUTTON_IMPORT_DESTINATION = '@kaizen/components'
13
+ const ICON_IMPORT_DESTINATION = '@kaizen/components'
13
14
 
14
15
  export const migrateGuidanceBlockActionsToActionsSlot =
15
16
  (tagsMap: TagImportAttributesMap): ts.TransformerFactory<ts.SourceFile> =>
@@ -40,6 +41,9 @@ export const migrateGuidanceBlockActionsToActionsSlot =
40
41
  tagName === 'GuidanceBlock' ||
41
42
  tagImportAttributes.importModuleName === 'GuidanceBlock'
42
43
  ) {
44
+ // Added flag to add arrow-forward icon to the secondary-variant Button created from the primary action, to minimise visual changes
45
+ let hasActionButtonArrow: boolean = true
46
+
43
47
  const componentProps: ts.JsxAttributeLike[] = node.attributes.properties.reduce<
44
48
  ts.JsxAttributeLike[]
45
49
  >((guidanceBlockProps, prop) => {
@@ -47,9 +51,23 @@ export const migrateGuidanceBlockActionsToActionsSlot =
47
51
  const propName = prop.name.getText()
48
52
  const propValue = prop.initializer as ts.JsxExpression
49
53
 
54
+ if (propName === 'withActionButtonArrow') {
55
+ if (propValue?.expression?.kind === ts.SyntaxKind.FalseKeyword) {
56
+ hasActionButtonArrow = false
57
+ } else {
58
+ hasActionButtonArrow = true
59
+ }
60
+ return guidanceBlockProps
61
+ }
62
+
63
+ if (propName === 'secondaryDismiss') {
64
+ return guidanceBlockProps
65
+ }
66
+
50
67
  if (propName === 'actions') {
51
68
  const transformedActions = transformActionsToActionsSlot(
52
69
  propValue.getChildren()[1] as ts.ObjectLiteralExpression,
70
+ hasActionButtonArrow,
53
71
  )
54
72
 
55
73
  if (transformedActions?.importsToAdd) {
@@ -72,6 +90,11 @@ export const migrateGuidanceBlockActionsToActionsSlot =
72
90
  : undefined,
73
91
  })
74
92
  }
93
+ if (importToAdd === 'Icon') {
94
+ setImportToAdd(importsToAdd, ICON_IMPORT_DESTINATION, {
95
+ componentName: 'Icon',
96
+ })
97
+ }
75
98
  })
76
99
  }
77
100
 
@@ -19,6 +19,7 @@ export const mockedTransformer =
19
19
  if (propName === 'actions') {
20
20
  const transformedActions = transformActionsToActionsSlot(
21
21
  propValue.getChildren()[1] as ts.ObjectLiteralExpression,
22
+ true,
22
23
  )
23
24
 
24
25
  return transformedActions?.actionsSlotAttr
@@ -74,7 +75,7 @@ describe('transformActionsToActionsSlot()', () => {
74
75
  layout="default"
75
76
  illustration={<Informative alt="" />}
76
77
  content={<div>Test</div>}
77
- actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large">Primary action</Button><LinkButton href="#secondary" variant="tertiary" size="large">Secondary action</LinkButton></>}
78
+ actionsSlot={<><Button onPress={() => alert('click 1')} variant="secondary" size="large" icon={<Icon name="arrow_forward" shouldMirrorInRTL isPresentational/>} iconPosition="end">Primary action</Button><LinkButton href="#secondary" variant="tertiary" size="large">Secondary action</LinkButton></>}
78
79
  />
79
80
  `)
80
81
 
@@ -13,9 +13,11 @@ type GuidanceBlockTransformedActions = {
13
13
  */
14
14
  export const transformActionsToActionsSlot = (
15
15
  node: ts.ObjectLiteralExpression,
16
+ hasActionButtonArrow: boolean,
16
17
  ): GuidanceBlockTransformedActions | undefined => {
17
18
  if (ts.isObjectLiteralExpression(node)) {
18
19
  const newImports: (string | undefined)[] = []
20
+ let arrowIconWasAdded = false
19
21
 
20
22
  const primaryAction = node.properties.find((prop) => prop?.name?.getText() === 'primary') as
21
23
  | ts.PropertyAssignment
@@ -30,10 +32,23 @@ export const transformActionsToActionsSlot = (
30
32
 
31
33
  if (primaryAction) {
32
34
  const actionValue = primaryAction.initializer as ts.ObjectLiteralExpression
35
+
36
+ // Check if icon prop already exists
37
+ const hasExistingIcon = actionValue.properties.some(
38
+ (prop) => prop?.name?.getText() === 'icon',
39
+ )
40
+
33
41
  const transformedComponent = transformV1ButtonPropsToButtonOrLinkButton(
34
42
  actionValue,
35
43
  'secondary',
44
+ hasActionButtonArrow,
36
45
  )
46
+
47
+ // Track if arrow icon was actually added (only if hasActionButtonArrow is true and no existing icon)
48
+ if (hasActionButtonArrow && !hasExistingIcon) {
49
+ arrowIconWasAdded = true
50
+ }
51
+
37
52
  primaryButton = transformedComponent.component
38
53
  newImports.push(transformedComponent.import)
39
54
  }
@@ -61,6 +76,11 @@ export const transformActionsToActionsSlot = (
61
76
  ),
62
77
  )
63
78
 
79
+ // Add Icon import if arrow icon was added
80
+ if (arrowIconWasAdded) {
81
+ newImports.push('Icon')
82
+ }
83
+
64
84
  return {
65
85
  actionsSlotAttr: newActionsSlotAttr,
66
86
  importsToAdd: newImports.filter(Boolean) as string[],
@@ -4,8 +4,7 @@ exports[`runV1Codemods > MockComponentDir Snapshot Tests > should transform Mock
4
4
  {
5
5
  "MockComponent.tsx": "// @ts-nocheck this is a mock file - we can ignore this
6
6
  import React from 'react';
7
- import { BrandMoment, Card, GlobalNotification, GuidanceBlock, Informative, ProgressBar, Well, LinkButton } from '@kaizen/components';
8
- import { Button } from "@kaizen/components/next";
7
+ import { BrandMoment, Card, GlobalNotification, GuidanceBlock, Informative, ProgressBar, Well, Button, LinkButton, Icon } from '@kaizen/components';
9
8
  import { MockSubcomponent } from './subcomponents/MockSubcomponent';
10
9
 
11
10
  export const MockComponent = (): JSX.Element => {
@@ -13,7 +12,7 @@ export const MockComponent = (): JSX.Element => {
13
12
  <GuidanceBlock illustration={<Informative alt=""/>} text={{
14
13
  title: 'This is the call to action title',
15
14
  description: 'Mussum Ipsum, cacilds vidis litro abertis. Suco de cevadiss, é um leite divinis.',
16
- }} actionsSlot={<><Button onPress={() => undefined} variant="secondary" size="large">Action!</Button><LinkButton href='/cancel' variant="tertiary" size="large">Cancel</LinkButton></>}/>
15
+ }} actionsSlot={<><Button onPress={() => undefined} variant="secondary" size="large" icon={<Icon name="arrow_forward" shouldMirrorInRTL isPresentational/>} iconPosition="end">Action!</Button><LinkButton href='/cancel' variant="tertiary" size="large">Cancel</LinkButton></>}/>
17
16
  <BrandMoment variant="success">
18
17
  <div>Success message</div>
19
18
  </BrandMoment>
@@ -71,9 +71,8 @@ describe('runV1Codemods', () => {
71
71
 
72
72
  expect(transformedFiles['MockComponent.tsx']).toContain('actionsSlot')
73
73
  expect(transformedFiles['MockComponent.tsx']).not.toContain('actions={{')
74
- expect(transformedFiles['MockComponent.tsx']).toContain(
75
- 'import { Button } from "@kaizen/components/next"',
76
- )
74
+ expect(transformedFiles['MockComponent.tsx']).toContain('Button')
75
+ expect(transformedFiles['MockComponent.tsx']).toContain(`from '@kaizen/components'`)
77
76
 
78
77
  expect(transformedFiles['subcomponents/MockSubcomponent.tsx']).toContain('onPress')
79
78
  expect(transformedFiles['subcomponents/MockSubcomponent.tsx']).toContain(
@@ -84,11 +84,14 @@ export const transformV1ButtonPropsToButtonOrLinkButton = (
84
84
  buttonProps: ts.ObjectLiteralExpression,
85
85
  /** optional override for the variant type if needed, ie: primary or secondary actions*/
86
86
  variantOverride?: string,
87
+ /** whether to add an arrow icon to the button */
88
+ addArrowIcon?: boolean,
87
89
  ): TransformButtonProp => {
88
90
  let childrenValue: ts.JsxAttributeValue | undefined
89
91
  let hasSizeProp = false
90
92
  let hasVariant = false
91
93
  let hasLinkAttr = false
94
+ let hasIconProp = false
92
95
 
93
96
  const newProps = buttonProps.properties.reduce<ts.JsxAttributeLike[]>((acc, currentProp) => {
94
97
  const propName = currentProp?.name?.getText()
@@ -127,6 +130,10 @@ export const transformV1ButtonPropsToButtonOrLinkButton = (
127
130
  hasSizeProp = true
128
131
  }
129
132
 
133
+ if (propName === 'icon') {
134
+ hasIconProp = true
135
+ }
136
+
130
137
  if (propName === 'href') {
131
138
  hasLinkAttr = true
132
139
  if (propValue && propValue?.kind !== ts.SyntaxKind.StringLiteral) {
@@ -184,6 +191,39 @@ export const transformV1ButtonPropsToButtonOrLinkButton = (
184
191
  newProps.push(createStringProp('size', 'large'))
185
192
  }
186
193
 
194
+ // Only add arrow icon if addArrowIcon is true AND there's no existing icon prop
195
+ if (addArrowIcon && !hasIconProp) {
196
+ const iconProp = ts.factory.createJsxAttribute(
197
+ ts.factory.createIdentifier('icon'),
198
+ ts.factory.createJsxExpression(
199
+ undefined,
200
+ ts.factory.createJsxSelfClosingElement(
201
+ ts.factory.createIdentifier('Icon'),
202
+ undefined,
203
+ ts.factory.createJsxAttributes([
204
+ ts.factory.createJsxAttribute(
205
+ ts.factory.createIdentifier('name'),
206
+ ts.factory.createStringLiteral('arrow_forward'),
207
+ ),
208
+ ts.factory.createJsxAttribute(
209
+ ts.factory.createIdentifier('shouldMirrorInRTL'),
210
+ undefined,
211
+ ),
212
+ ts.factory.createJsxAttribute(
213
+ ts.factory.createIdentifier('isPresentational'),
214
+ undefined,
215
+ ),
216
+ ]),
217
+ ),
218
+ ),
219
+ )
220
+ const iconPositionProp = ts.factory.createJsxAttribute(
221
+ ts.factory.createIdentifier('iconPosition'),
222
+ ts.factory.createStringLiteral('end'),
223
+ )
224
+ newProps.push(iconProp, iconPositionProp)
225
+ }
226
+
187
227
  return {
188
228
  import: hasLinkAttr ? 'LinkButton' : 'Button',
189
229
  component: createJsxElementWithChildren(
@@ -1,18 +1,17 @@
1
1
  'use strict';
2
2
 
3
3
  var Menu$1 = require('./Menu.cjs');
4
- require('tslib');
5
- require('react');
6
- require('classnames');
7
- require('../Heading/Heading.cjs');
4
+ var MenuHeading$1 = require('./subcomponents/MenuHeading/MenuHeading.cjs');
8
5
  var MenuItem$1 = require('./subcomponents/MenuItem/MenuItem.cjs');
9
6
  var MenuList$1 = require('./subcomponents/MenuList/MenuList.cjs');
10
7
  require('./subcomponents/StatelessMenu/StatelessMenu.cjs');
11
8
 
12
9
  // Since we can't add a deprecation flag on a * export
13
10
  var Menu = Menu$1.Menu;
11
+ var MenuHeading = MenuHeading$1.MenuHeading;
14
12
  var MenuItem = MenuItem$1.MenuItem;
15
13
  var MenuList = MenuList$1.MenuList;
16
14
  exports.Menu = Menu;
15
+ exports.MenuHeading = MenuHeading;
17
16
  exports.MenuItem = MenuItem;
18
17
  exports.MenuList = MenuList;
@@ -0,0 +1,27 @@
1
+ 'use strict';
2
+
3
+ var tslib = require('tslib');
4
+ var React = require('react');
5
+ var classnames = require('classnames');
6
+ var Heading = require('../../../Heading/Heading.cjs');
7
+ var MenuHeading_module = require('./MenuHeading.module.scss.cjs');
8
+ function _interopDefault(e) {
9
+ return e && e.__esModule ? e : {
10
+ default: e
11
+ };
12
+ }
13
+ var React__default = /*#__PURE__*/_interopDefault(React);
14
+ var classnames__default = /*#__PURE__*/_interopDefault(classnames);
15
+ var MenuHeading = function (_a) {
16
+ var id = _a.id,
17
+ classNameOverride = _a.classNameOverride,
18
+ restProps = tslib.__rest(_a, ["id", "classNameOverride"]);
19
+ return React__default.default.createElement(Heading.Heading, tslib.__assign({
20
+ id: id,
21
+ variant: "heading-6",
22
+ tag: "span",
23
+ classNameOverride: classnames__default.default(MenuHeading_module.heading, classNameOverride)
24
+ }, restProps));
25
+ };
26
+ MenuHeading.displayName = 'MenuHeading';
27
+ exports.MenuHeading = MenuHeading;
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ var styles = {
4
+ "heading": "MenuHeading-module_heading__hrHGy"
5
+ };
6
+ module.exports = styles;