@atlaskit/forge-react-types 0.42.8 → 0.42.10

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 (49) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/types/components/__generated__/BadgeProps.codegen.d.ts +2 -7
  3. package/dist/types/components/__generated__/BoxProps.codegen.d.ts +2 -2
  4. package/dist/types/components/__generated__/CalendarProps.codegen.d.ts +128 -4
  5. package/dist/types/components/__generated__/CheckboxProps.codegen.d.ts +62 -4
  6. package/dist/types/components/__generated__/CodeProps.codegen.d.ts +2 -2
  7. package/dist/types/components/__generated__/EmptyStateProps.codegen.d.ts +45 -4
  8. package/dist/types/components/__generated__/ErrorMessageProps.codegen.d.ts +14 -4
  9. package/dist/types/components/__generated__/HeadingProps.codegen.d.ts +29 -3
  10. package/dist/types/components/__generated__/LozengeProps.codegen.d.ts +26 -4
  11. package/dist/types/components/__generated__/PressableProps.codegen.d.ts +2 -2
  12. package/dist/types/components/__generated__/RangeProps.codegen.d.ts +50 -5
  13. package/dist/types/components/__generated__/index.d.ts +0 -1
  14. package/dist/types/index.d.ts +1 -1
  15. package/dist/types-ts4.5/components/__generated__/BadgeProps.codegen.d.ts +2 -7
  16. package/dist/types-ts4.5/components/__generated__/BoxProps.codegen.d.ts +2 -2
  17. package/dist/types-ts4.5/components/__generated__/CalendarProps.codegen.d.ts +128 -4
  18. package/dist/types-ts4.5/components/__generated__/CheckboxProps.codegen.d.ts +62 -4
  19. package/dist/types-ts4.5/components/__generated__/CodeProps.codegen.d.ts +2 -2
  20. package/dist/types-ts4.5/components/__generated__/EmptyStateProps.codegen.d.ts +45 -4
  21. package/dist/types-ts4.5/components/__generated__/ErrorMessageProps.codegen.d.ts +14 -4
  22. package/dist/types-ts4.5/components/__generated__/HeadingProps.codegen.d.ts +29 -3
  23. package/dist/types-ts4.5/components/__generated__/LozengeProps.codegen.d.ts +26 -4
  24. package/dist/types-ts4.5/components/__generated__/PressableProps.codegen.d.ts +2 -2
  25. package/dist/types-ts4.5/components/__generated__/RangeProps.codegen.d.ts +50 -5
  26. package/dist/types-ts4.5/components/__generated__/index.d.ts +0 -1
  27. package/dist/types-ts4.5/index.d.ts +1 -1
  28. package/package.json +5 -11
  29. package/scripts/codegen/codeGenerator.ts +118 -24
  30. package/scripts/codegen/typeSerializer.ts +122 -70
  31. package/scripts/codegen/utils.ts +71 -0
  32. package/scripts/typechecker.ts +37 -2
  33. package/src/components/__generated__/BadgeProps.codegen.tsx +3 -7
  34. package/src/components/__generated__/CalendarProps.codegen.tsx +119 -4
  35. package/src/components/__generated__/CheckboxProps.codegen.tsx +64 -4
  36. package/src/components/__generated__/CodeProps.codegen.tsx +2 -2
  37. package/src/components/__generated__/EmptyStateProps.codegen.tsx +47 -4
  38. package/src/components/__generated__/ErrorMessageProps.codegen.tsx +16 -4
  39. package/src/components/__generated__/HeadingProps.codegen.tsx +31 -3
  40. package/src/components/__generated__/LozengeProps.codegen.tsx +28 -4
  41. package/src/components/__generated__/RangeProps.codegen.tsx +54 -5
  42. package/src/components/__generated__/index.ts +1 -2
  43. package/src/index.ts +0 -2
  44. package/dist/cjs/components/__generated__/BleedProps.codegen.js +0 -5
  45. package/dist/es2019/components/__generated__/BleedProps.codegen.js +0 -1
  46. package/dist/esm/components/__generated__/BleedProps.codegen.js +0 -1
  47. package/dist/types/components/__generated__/BleedProps.codegen.d.ts +0 -15
  48. package/dist/types-ts4.5/components/__generated__/BleedProps.codegen.d.ts +0 -15
  49. package/src/components/__generated__/BleedProps.codegen.tsx +0 -22
@@ -5,10 +5,21 @@ import {
5
5
  type SourceFile,
6
6
  type TypeAliasDeclaration,
7
7
  type ImportDeclaration,
8
+ type TypeReferenceNode,
9
+ SyntaxKind,
8
10
  } from 'ts-morph';
9
11
  // eslint-disable-next-line import/no-extraneous-dependencies
10
12
  import kebabCase from 'lodash/kebabCase';
11
- import { serializeSymbolType } from './typeSerializer';
13
+ import {
14
+ serializeTypeReferenceWithPickType,
15
+ extractPickKeys,
16
+ extractOmitKeys,
17
+ } from './typeSerializer';
18
+ import {
19
+ findTypeReferenceFromUnionOrIntersect,
20
+ getTypeNodeFromSymbol,
21
+ makePickOrOmitPredicate,
22
+ } from './utils';
12
23
 
13
24
  const getNames = (symbol: Symbol) => {
14
25
  const name = symbol.getName();
@@ -224,7 +235,7 @@ class SimpleImportDeclaration implements IImportDeclaration {
224
235
  .map((name) => `type ${name}`);
225
236
  const importedNames =
226
237
  importedNamesList.length > 0 ? `{ ${importedNamesList.join(', ')} }` : null;
227
- const defaultImport = this.defaultImport ? `${this.defaultImport}` : null;
238
+ const defaultImport = this.defaultImport ? `type ${this.defaultImport}` : null;
228
239
  return `import ${[defaultImport, importedNames].filter(Boolean).join(', ')} from '${this.packageName}';`;
229
240
  }
230
241
  }
@@ -567,12 +578,21 @@ const registeredExternalTypes: Record<
567
578
  defaultImport: string;
568
579
  }
569
580
  > = {
570
- 'React.ReactNode': {
581
+ '^React..+$': {
571
582
  package: 'react',
572
583
  defaultImport: 'React',
573
584
  },
574
585
  };
575
586
 
587
+ const findExternalTypeInfo = (typeName: string) => {
588
+ return (
589
+ Object.entries(registeredExternalTypes).find(
590
+ ([externalTypePattern]) =>
591
+ externalTypePattern === typeName || new RegExp(externalTypePattern).test(typeName),
592
+ )?.[1] ?? null
593
+ );
594
+ };
595
+
576
596
  // consolidate external types into import declarations
577
597
  const consolidateImportDeclarations = (
578
598
  importDeclarations: ImportDeclarationProxy[],
@@ -580,7 +600,7 @@ const consolidateImportDeclarations = (
580
600
  ): IImportDeclaration[] => {
581
601
  const declarations: IImportDeclaration[] = [...importDeclarations];
582
602
  externalTypes.forEach((typeName) => {
583
- const typePackage = registeredExternalTypes[typeName];
603
+ const typePackage = findExternalTypeInfo(typeName);
584
604
  if (typePackage) {
585
605
  const existingImport = importDeclarations.find(
586
606
  (declaration) => declaration.getBasePackage() === typePackage.package,
@@ -602,6 +622,62 @@ const consolidateImportDeclarations = (
602
622
  return declarations;
603
623
  };
604
624
 
625
+ const extractPlatformPropsTypeDeclarationAndTargetPropertyKeys = (
626
+ rawDependentTypeDeclarations: TypeAliasDeclaration[],
627
+ baseComponentPropsSymbol: Symbol,
628
+ ): {
629
+ typeDeclaration: TypeAliasDeclaration;
630
+ baseComponentPropTypeReference: TypeReferenceNode;
631
+ omitKeys: string[];
632
+ pickKeys: string[];
633
+ } => {
634
+ // this pattern is used when there is special JSDoc comments override required to customize component documentation.
635
+ // e.g. Badge component has:
636
+ // PlatformBadgeProps = Omit<_PlatformBadgeProps, 'children'> & {}
637
+ // BadgeProps = Pick<PlatformBadgeProps, 'appearance' | 'children' | 'max' | 'testId'>
638
+ const specialPlatformPropsTypeDeclaration = rawDependentTypeDeclarations.find((declaration) =>
639
+ declaration.getName().startsWith('_Platform'),
640
+ );
641
+ const mainPlatformPropsTypeDeclaration = rawDependentTypeDeclarations.find((declaration) =>
642
+ declaration.getName().startsWith('Platform'),
643
+ );
644
+ if (!mainPlatformPropsTypeDeclaration && !specialPlatformPropsTypeDeclaration) {
645
+ throw new Error(
646
+ 'Could not find Platform props type declaration from the component prop type source code',
647
+ );
648
+ }
649
+ const platformPropsTypeDeclaration =
650
+ specialPlatformPropsTypeDeclaration ?? mainPlatformPropsTypeDeclaration;
651
+
652
+ const typeWhichPicksPlatformProps = findTypeReferenceFromUnionOrIntersect(
653
+ getTypeNodeFromSymbol(baseComponentPropsSymbol!)!,
654
+ makePickOrOmitPredicate('Pick', 'Platform'),
655
+ );
656
+ if (!typeWhichPicksPlatformProps) {
657
+ throw new Error(
658
+ `Could not find type which picks platform props from the component prop type source code for ${baseComponentPropsSymbol.getName()}`,
659
+ );
660
+ }
661
+ const pickKeys = extractPickKeys(typeWhichPicksPlatformProps);
662
+ let omitKeys: string[] = [];
663
+ if (specialPlatformPropsTypeDeclaration && mainPlatformPropsTypeDeclaration) {
664
+ const omitNode = mainPlatformPropsTypeDeclaration
665
+ .getTypeNodeOrThrow()
666
+ .asKindOrThrow(SyntaxKind.IntersectionType)
667
+ .getTypeNodes()[0]
668
+ .asKindOrThrow(SyntaxKind.TypeReference);
669
+ // if there is a special platform props type declaration, we need
670
+ omitKeys = extractOmitKeys(omitNode);
671
+ }
672
+
673
+ return {
674
+ typeDeclaration: platformPropsTypeDeclaration!,
675
+ baseComponentPropTypeReference: typeWhichPicksPlatformProps,
676
+ pickKeys,
677
+ omitKeys,
678
+ };
679
+ };
680
+
605
681
  /**
606
682
  * This function implements the new code generation logic for the component prop types.
607
683
  * Instead of referencing to the ADS component prop types, it generates the prop types
@@ -619,24 +695,20 @@ const generateComponentPropTypeSourceCodeWithSerializedType = (
619
695
  // 2) from the prop type code further extract other relevant types in the source file,
620
696
  // and separate the platform props type declaration from the rest of the dependent types.
621
697
  // as this will be used to generate the type code.
622
- const [dependentTypeDeclarations, platformPropsTypeDeclaration] = getDependentTypeDeclarations(
698
+ const rawDependentTypeDeclarations = getDependentTypeDeclarations(
623
699
  baseComponentPropSymbol,
624
700
  sourceFile,
625
- ).reduce(
626
- (agg, declarations) => {
627
- if (declarations.getName().startsWith('_Platform')) {
628
- // this is the platform props type declaration, we will use it to generate the type code.
629
- // this pattern is used when we need to add custom overrides to the platform props type.
630
- agg[1] = declarations;
631
- } else if (declarations.getName().startsWith('Platform') && !agg[1]) {
632
- // we only use this pattern if _Platform is not used. (this is for cases like Code and CodeBlock)
633
- agg[1] = declarations;
634
- } else {
635
- agg[0].push(declarations);
636
- }
637
- return agg;
638
- },
639
- [[] as TypeAliasDeclaration[], null as TypeAliasDeclaration | null],
701
+ );
702
+ const {
703
+ omitKeys,
704
+ typeDeclaration: platformPropsTypeDeclaration,
705
+ baseComponentPropTypeReference,
706
+ } = extractPlatformPropsTypeDeclarationAndTargetPropertyKeys(
707
+ rawDependentTypeDeclarations,
708
+ baseComponentPropSymbol,
709
+ );
710
+ const dependentTypeDeclarations = rawDependentTypeDeclarations.filter(
711
+ (declaration) => declaration !== platformPropsTypeDeclaration,
640
712
  );
641
713
 
642
714
  // 3) extract the import statement
@@ -654,9 +726,20 @@ const generateComponentPropTypeSourceCodeWithSerializedType = (
654
726
  );
655
727
 
656
728
  // 5) serialize the prop type for the @atlaskit component (e.g. PlatformButtonProps)
657
- const [typeDefCode, usedExternalTypes] = serializeSymbolType(
658
- baseComponentPropSymbol,
659
- sourceFile.getProject().getTypeChecker(),
729
+ const [typeDefCode, usedExternalTypes] = serializeTypeReferenceWithPickType(
730
+ baseComponentPropTypeReference,
731
+ ({ jsDoc, typeCode, propertySignature }) => {
732
+ const propertyName = propertySignature.getName();
733
+ if (omitKeys.includes(propertyName)) {
734
+ return {
735
+ typeCode,
736
+ };
737
+ }
738
+ return {
739
+ jsDoc,
740
+ typeCode,
741
+ };
742
+ },
660
743
  );
661
744
 
662
745
  // 6) generate the source file
@@ -739,7 +822,18 @@ const codeConsolidators: Record<string, CodeConsolidator> = {
739
822
  PressableProps: handleXCSSProp,
740
823
  };
741
824
 
742
- const typeSerializableComponentPropSymbols = ['CodeProps', 'CodeBlockProps', 'BadgeProps'];
825
+ const typeSerializableComponentPropSymbols = [
826
+ 'CalendarProps',
827
+ 'CheckboxProps',
828
+ 'CodeProps',
829
+ 'CodeBlockProps',
830
+ 'BadgeProps',
831
+ 'EmptyStateProps',
832
+ 'ErrorMessageProps',
833
+ 'LozengeProps',
834
+ 'HeadingProps',
835
+ 'RangeProps',
836
+ ];
743
837
 
744
838
  const generateComponentPropTypeSourceCode = (
745
839
  componentPropSymbol: Symbol,
@@ -1,56 +1,32 @@
1
1
  import {
2
- type Symbol as TSSymbol,
3
2
  type Node,
4
- type TypeChecker,
5
3
  type PropertySignature,
6
4
  type Type as TSType,
5
+ type UnionTypeNode,
6
+ type TypeReferenceNode,
7
7
  SyntaxKind,
8
8
  } from 'ts-morph';
9
9
 
10
- export const serializeSymbolType = (
11
- symbol: TSSymbol,
12
- typeChecker: TypeChecker,
13
- ): [string, Set<string>] => {
14
- const declaration = symbol.getDeclarations()[0];
15
-
16
- if (!declaration) {
17
- throw new Error(`No declaration found for symbol: ${symbol.getName()}`);
18
- }
10
+ type PropertyCallback = ({
11
+ jsDoc,
12
+ typeCode,
13
+ propertySignature,
14
+ }: {
15
+ jsDoc?: string;
16
+ typeCode: string;
17
+ propertySignature: PropertySignature;
18
+ }) => {
19
+ jsDoc?: string;
20
+ typeCode: string;
21
+ } | null;
19
22
 
23
+ export const serializeTypeReferenceWithPickType = (
24
+ typeReference: TypeReferenceNode,
25
+ propertyCallback: PropertyCallback,
26
+ ): [string, Set<string>] => {
20
27
  const usedExternalTypes = new Set<string>();
21
- if (declaration.getKind() === SyntaxKind.TypeAliasDeclaration) {
22
- const typeAlias = declaration.asKindOrThrow(SyntaxKind.TypeAliasDeclaration);
23
- const typeNode = typeAlias.getTypeNode();
24
- if (typeNode && isCommonComponentPropType(typeNode)) {
25
- const serializedType = flattenPickType(
26
- typeNode.asKindOrThrow(SyntaxKind.TypeReference),
27
- typeChecker,
28
- usedExternalTypes,
29
- );
30
- return [serializedType, usedExternalTypes];
31
- }
32
- }
33
-
34
- throw new Error(
35
- `Unsupported declaration kind: ${declaration.getKindName()} for symbol: ${symbol.getName()}`,
36
- );
37
- };
38
-
39
- /**
40
- * Checks if a node is a common component prop type. e.g.
41
- *
42
- * export type BleedProps = Pick<
43
- * PlatformBleedProps,
44
- * 'children' | 'all' | 'inline' | 'block' | 'testId' | 'role'
45
- * >;
46
- */
47
- const isCommonComponentPropType = (node: Node) => {
48
- if (node.getKind() === SyntaxKind.TypeReference) {
49
- const typeRef = node.asKindOrThrow(SyntaxKind.TypeReference);
50
- const typeName = typeRef.getTypeName().getText();
51
- return typeName === 'Pick';
52
- }
53
- return false;
28
+ const serializedType = flattenPickType(typeReference, usedExternalTypes, propertyCallback);
29
+ return [serializedType, usedExternalTypes];
54
30
  };
55
31
 
56
32
  // resolve single level type references (e.g. SupportedLanguages))
@@ -63,6 +39,54 @@ const isSimpleTypeReferenceNode = (tsType: TSType): boolean => {
63
39
  return false;
64
40
  };
65
41
 
42
+ // event function type that is not a React event handler
43
+ const isCustomEventHandlerType = (tsType: TSType): boolean => {
44
+ const callSignatures = tsType.getCallSignatures();
45
+ // we already import React, hence we don't have to serialize it
46
+ if (
47
+ callSignatures.length > 0 &&
48
+ callSignatures[0].getParameters().length > 1 &&
49
+ !tsType.getText().startsWith('React.')
50
+ ) {
51
+ const analyticsEventSymbol = callSignatures[0].getParameters()[1];
52
+ if (analyticsEventSymbol) {
53
+ const eventTypeName = analyticsEventSymbol
54
+ .getDeclarations()[0]
55
+ .asKind(SyntaxKind.Parameter)
56
+ ?.getTypeNode()
57
+ ?.getText();
58
+ return eventTypeName === 'UIAnalyticsEvent';
59
+ }
60
+ return true;
61
+ }
62
+ return false;
63
+ };
64
+
65
+ const serializeSimpleEventType = (tsType: TSType): string => {
66
+ const propertyCode: string[] = tsType
67
+ .getProperties()
68
+ .map((prop) => {
69
+ const propertySignature = prop.getDeclarations()[0] as PropertySignature | undefined;
70
+ if (propertySignature) {
71
+ const typeCode = serializeSimpleTypeNode(resolveNonNullableType(propertySignature));
72
+ return `${prop.getName()}: ${typeCode}`;
73
+ }
74
+ return null;
75
+ })
76
+ .filter(Boolean) as string[];
77
+ return `{ ${propertyCode.join(', ')} }`;
78
+ };
79
+
80
+ const serializeCustomEventHandlerType = (tsType: TSType): string => {
81
+ const callSignature = tsType.getCallSignatures()[0];
82
+ const eventSymbol = callSignature.getParameters()[0];
83
+ const parameterDeclaration = eventSymbol.getDeclarations()[0].asKindOrThrow(SyntaxKind.Parameter);
84
+ const eventType = parameterDeclaration.getType();
85
+ const analyticsEventName = callSignature.getParameters()[1]?.getName() ?? 'analyticsEvent';
86
+ const returnType = callSignature.getReturnType().getText();
87
+ return `(${eventSymbol.getName()}: ${serializeSimpleEventType(eventType)}, ${analyticsEventName}: any) => ${returnType}`;
88
+ };
89
+
66
90
  const serializeSimpleTypeNode = (tsType: TSType): string => {
67
91
  if (tsType.isStringLiteral()) {
68
92
  return `'${tsType.getLiteralValue()}'`;
@@ -72,6 +96,8 @@ const serializeSimpleTypeNode = (tsType: TSType): string => {
72
96
  const unionTypes = tsType.getUnionTypes();
73
97
  const serializedTypes = unionTypes.map((t) => serializeSimpleTypeNode(t));
74
98
  return serializedTypes.join(' | ');
99
+ } else if (isCustomEventHandlerType(tsType)) {
100
+ return serializeCustomEventHandlerType(tsType);
75
101
  }
76
102
  return tsType.getText();
77
103
  };
@@ -98,25 +124,14 @@ const serializePropertySignatureCode = (propertySignature: PropertySignature) =>
98
124
 
99
125
  const flattenPickType = (
100
126
  typeRef: Node,
101
- typeChecker: TypeChecker,
102
127
  usedExternalTypesOutput: Set<string>,
128
+ propertyCallback: PropertyCallback,
103
129
  ): string => {
104
- const typeArgs = typeRef.asKindOrThrow(SyntaxKind.TypeReference).getTypeArguments();
105
-
106
- if (typeArgs.length < 2) {
107
- return typeRef.getText(); // Fallback if not a valid Pick
108
- }
109
-
110
- const keysNode = typeArgs[1];
111
-
112
- // Get the selected keys
113
- const selectedKeys = extractUnionKeys(keysNode);
114
-
115
- // Get the base type symbol
130
+ const pickKeys = extractPickKeys(typeRef.asKindOrThrow(SyntaxKind.TypeReference));
116
131
  const properties = typeRef
117
132
  .getType()
118
133
  .getProperties()
119
- .filter((prop) => selectedKeys.includes(prop.getName()));
134
+ .filter((prop) => pickKeys.includes(prop.getName()));
120
135
 
121
136
  if (properties.length === 0) {
122
137
  return '{}'; // If no properties match, return 'any'
@@ -128,19 +143,23 @@ const flattenPickType = (
128
143
  if (!propertySignature) {
129
144
  return null; // Skip if no declaration
130
145
  }
131
- const jsDoc = propertySignature.getJsDocs()?.[0]?.getText();
132
- const typeCode = `\t${serializePropertySignatureCode(propertySignature)}`;
146
+ const { jsDoc, typeCode } =
147
+ propertyCallback({
148
+ propertySignature,
149
+ jsDoc: propertySignature.getJsDocs()?.[0]?.getText(),
150
+ typeCode: serializePropertySignatureCode(propertySignature),
151
+ }) || {};
133
152
  getUnresolvableTypes(propertySignature.getType()).forEach((typeName) => {
134
153
  usedExternalTypesOutput.add(typeName);
135
154
  });
136
- return [jsDoc, typeCode].filter(Boolean).join('\n');
155
+ return `${jsDoc ?? ''}\n\t${typeCode}`;
137
156
  })
138
157
  .filter(Boolean);
139
158
 
140
159
  if (serializedProperties.length === 0) {
141
160
  return '{}'; // If no properties are serialized, return empty object
142
161
  }
143
- return `{\n ${serializedProperties.join('\n ')}\n}`;
162
+ return `{\n${serializedProperties.map((prop) => (!!prop?.trim() ? ` ${prop}` : '')).join('\n')}\n}`;
144
163
  };
145
164
 
146
165
  const getUnresolvableTypes = (tsType: TSType) => {
@@ -195,18 +214,51 @@ const isExternalType = (tsType: TSType): boolean => {
195
214
  return filePath.includes('node_modules');
196
215
  };
197
216
 
217
+ export const extractUnionKeysFromTypeReferenceNode = (
218
+ typeReferenceNode: TypeReferenceNode,
219
+ targetTypeName: 'Pick' | 'Omit',
220
+ ): string[] => {
221
+ const typeName = typeReferenceNode.getTypeName().getText();
222
+ if (typeName !== targetTypeName) {
223
+ throw new Error(`Expected '${targetTypeName}' type, but found '${typeName}'`);
224
+ }
225
+ const typeArgs = typeReferenceNode.getTypeArguments();
226
+ if (typeArgs.length !== 2) {
227
+ throw new Error(
228
+ `Expected 2 type arguments for ${targetTypeName}, but found ${typeArgs.length}`,
229
+ );
230
+ }
231
+ const unionType = typeArgs[1];
232
+ return extractUnionKeys(unionType);
233
+ };
234
+
235
+ export const extractOmitKeys = (typeReferenceNode: TypeReferenceNode): string[] => {
236
+ return extractUnionKeysFromTypeReferenceNode(typeReferenceNode, 'Omit');
237
+ };
238
+
239
+ export const extractPickKeys = (typeReferenceNode: TypeReferenceNode): string[] => {
240
+ return extractUnionKeysFromTypeReferenceNode(typeReferenceNode, 'Pick');
241
+ };
242
+
243
+ const unwrapStringQuotes = (str: string): string => {
244
+ return str.replace(/['"]/g, '');
245
+ };
246
+
247
+ const extractUnionKeysFromUnionType = (unionType: UnionTypeNode): string[] => {
248
+ return unionType.getTypeNodes().map((node) => {
249
+ if (node.getKind() === SyntaxKind.StringLiteral) {
250
+ return node.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
251
+ }
252
+ return unwrapStringQuotes(node.getText());
253
+ });
254
+ };
255
+
198
256
  const extractUnionKeys = (keysNode: Node): string[] => {
199
257
  if (keysNode.getKind() === SyntaxKind.UnionType) {
200
258
  const unionType = keysNode.asKindOrThrow(SyntaxKind.UnionType);
201
- return unionType.getTypeNodes().map((node) => {
202
- if (node.getKind() === SyntaxKind.StringLiteral) {
203
- return node.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
204
- }
205
- return node.getText().replace(/['"]/g, '');
206
- });
259
+ return extractUnionKeysFromUnionType(unionType);
207
260
  } else if (keysNode.getKind() === SyntaxKind.StringLiteral) {
208
261
  return [keysNode.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue()];
209
262
  }
210
-
211
- return [keysNode.getText().replace(/['"]/g, '')];
263
+ return [unwrapStringQuotes(keysNode.getText())];
212
264
  };
@@ -0,0 +1,71 @@
1
+ import {
2
+ type Symbol as TSSymbol,
3
+ type TypeReferenceNode,
4
+ type TypeNode,
5
+ SyntaxKind,
6
+ } from 'ts-morph';
7
+
8
+ export const getTypeNodeFromSymbol = (symbol: TSSymbol): TypeNode | null => {
9
+ const declaration = symbol.getDeclarations()[0];
10
+ if (!declaration) {
11
+ return null;
12
+ }
13
+
14
+ if (declaration.getKind() === SyntaxKind.TypeAliasDeclaration) {
15
+ return declaration.asKindOrThrow(SyntaxKind.TypeAliasDeclaration).getTypeNode() ?? null;
16
+ }
17
+
18
+ return null;
19
+ };
20
+
21
+ type TypeFinderPredicate = (node: TypeNode) => boolean;
22
+
23
+ export const makePickOrOmitPredicate = (
24
+ targetTypeName: 'Pick' | 'Omit',
25
+ baseClassNamePrefix: string,
26
+ ): TypeFinderPredicate => {
27
+ return (node: TypeNode) => {
28
+ const typeReferenceNode = node.asKind(SyntaxKind.TypeReference);
29
+ if (!typeReferenceNode) {
30
+ return false;
31
+ }
32
+ const typeName = typeReferenceNode.getTypeName().getText();
33
+ if (typeName !== targetTypeName) {
34
+ return false;
35
+ }
36
+ const baseNode = typeReferenceNode.getTypeArguments()[0]!;
37
+ return baseNode.getText().startsWith(baseClassNamePrefix);
38
+ };
39
+ };
40
+
41
+ export const findTypeReferenceFromUnionOrIntersect = (
42
+ node: TypeNode,
43
+ predicate: TypeFinderPredicate,
44
+ ): TypeReferenceNode | null => {
45
+ if (predicate(node)) {
46
+ return node.asKindOrThrow(SyntaxKind.TypeReference);
47
+ }
48
+ if (node.getKind() === SyntaxKind.UnionType) {
49
+ const unionNode = node.asKindOrThrow(SyntaxKind.UnionType);
50
+ return (
51
+ (unionNode.getTypeNodes().find((n) => {
52
+ if (n.isKind(SyntaxKind.TypeReference)) {
53
+ return predicate(n.asKindOrThrow(SyntaxKind.TypeReference));
54
+ }
55
+ return false;
56
+ }) as TypeReferenceNode) ?? null
57
+ );
58
+ } else if (node.getKind() === SyntaxKind.IntersectionType) {
59
+ const intersectionNode = node.asKindOrThrow(SyntaxKind.IntersectionType);
60
+ return (
61
+ (intersectionNode.getTypeNodes().find((n) => {
62
+ if (n.isKind(SyntaxKind.TypeReference)) {
63
+ return predicate(n.asKindOrThrow(SyntaxKind.TypeReference));
64
+ }
65
+ return false;
66
+ }) as TypeReferenceNode) ?? null
67
+ );
68
+ }
69
+
70
+ return null;
71
+ };
@@ -1,12 +1,26 @@
1
1
  /* eslint-disable */
2
2
  import {
3
3
  type BadgeProps,
4
- type CodeProps,
4
+ type CalendarProps,
5
+ type CheckboxProps,
5
6
  type CodeBlockProps,
7
+ type CodeProps,
8
+ type EmptyStateProps,
9
+ type ErrorMessageProps,
10
+ type HeadingProps,
11
+ type LozengeProps,
12
+ type RangeProps,
6
13
  } from '@atlassian/forge-ui/src/components/UIKit';
7
14
  import { type BadgeProps as GeneratedBadgeProps } from '../src/components/__generated__/BadgeProps.codegen';
8
- import { type CodeProps as GeneratedCodeProps } from '../src/components/__generated__/CodeProps.codegen';
15
+ import { type CalendarProps as GeneratedCalendarProps } from '../src/components/__generated__/CalendarProps.codegen';
16
+ import { type CheckboxProps as GeneratedCheckboxProps } from '../src/components/__generated__/CheckboxProps.codegen';
9
17
  import { type CodeBlockProps as GeneratedCodeBlockProps } from '../src/components/__generated__/CodeBlockProps.codegen';
18
+ import { type CodeProps as GeneratedCodeProps } from '../src/components/__generated__/CodeProps.codegen';
19
+ import { type EmptyStateProps as GeneratedEmptyStateProps } from '../src/components/__generated__/EmptyStateProps.codegen';
20
+ import { type ErrorMessageProps as GeneratedErrorMessageProps } from '../src/components/__generated__/ErrorMessageProps.codegen';
21
+ import { type HeadingProps as GeneratedHeadingProps } from '../src/components/__generated__/HeadingProps.codegen';
22
+ import { type LozengeProps as GeneratedLozengeProps } from '../src/components/__generated__/LozengeProps.codegen';
23
+ import { type RangeProps as GeneratedRangeProps } from '../src/components/__generated__/RangeProps.codegen';
10
24
 
11
25
  const assertAssignable = <A, B extends A>() => {};
12
26
 
@@ -18,3 +32,24 @@ assertAssignable<CodeProps, GeneratedCodeProps>();
18
32
 
19
33
  assertAssignable<GeneratedCodeBlockProps, CodeBlockProps>();
20
34
  assertAssignable<CodeBlockProps, GeneratedCodeBlockProps>();
35
+
36
+ assertAssignable<GeneratedHeadingProps, HeadingProps>();
37
+ assertAssignable<HeadingProps, GeneratedHeadingProps>();
38
+
39
+ assertAssignable<GeneratedRangeProps, RangeProps>();
40
+ assertAssignable<RangeProps, GeneratedRangeProps>();
41
+
42
+ assertAssignable<GeneratedCalendarProps, CalendarProps>();
43
+ assertAssignable<CalendarProps, GeneratedCalendarProps>();
44
+
45
+ assertAssignable<GeneratedCheckboxProps, CheckboxProps>();
46
+ assertAssignable<CheckboxProps, GeneratedCheckboxProps>();
47
+
48
+ assertAssignable<GeneratedEmptyStateProps, EmptyStateProps>();
49
+ assertAssignable<EmptyStateProps, GeneratedEmptyStateProps>();
50
+
51
+ assertAssignable<GeneratedErrorMessageProps, ErrorMessageProps>();
52
+ assertAssignable<ErrorMessageProps, GeneratedErrorMessageProps>();
53
+
54
+ assertAssignable<GeneratedLozengeProps, LozengeProps>();
55
+ assertAssignable<LozengeProps, GeneratedLozengeProps>();
@@ -3,13 +3,13 @@
3
3
  *
4
4
  * Extract component prop types from UIKit 2 components - BadgeProps
5
5
  *
6
- * @codegen <<SignedSource::70958e2a60c7a0e1b3443db2d24003cc>>
6
+ * @codegen <<SignedSource::e4726fc9fc56127107db590dd21ef3f6>>
7
7
  * @codegenCommand yarn workspace @atlaskit/forge-react-types codegen
8
8
  * @codegenDependency ../../../../forge-ui/src/components/UIKit/badge/__generated__/index.partial.tsx <<SignedSource::89ad3341c1b8ef4b6fc93df162ac91d3>>
9
9
  */
10
10
  /* eslint @repo/internal/codegen/signed-source-integrity: "warn" */
11
11
 
12
- import React from 'react';
12
+ import type React from 'react';
13
13
 
14
14
  export type PlatformBadgeProps = Omit<_PlatformBadgeProps, 'children'> & {
15
15
  /**
@@ -26,11 +26,7 @@ type _PlatformBadgeProps = {
26
26
  * Affects the visual style of the badge.
27
27
  */
28
28
  appearance?: 'added' | 'default' | 'important' | 'primary' | 'primaryInverted' | 'removed';
29
- /**
30
- * The value displayed within the badge. A badge should only be used in cases where you want to represent a number. Use a lozenge for non-numeric information.
31
- *
32
- * @type string | number
33
- */
29
+
34
30
  children?: React.ReactNode;
35
31
  /**
36
32
  * The maximum value to display. Defaults to `99`. If the value is 100, and max is 50, "50+" will be displayed.