Skip to content

Commit 9ddc9c4

Browse files
authored
feat: migrate @carbon/type to TypeScript (#22164)
* feat: migrate @carbon/type to TypeScript * build: update typescript-config-carbon
1 parent 7363e14 commit 9ddc9c4

16 files changed

Lines changed: 199 additions & 145 deletions

packages/type/package.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"version": "11.60.0",
55
"license": "Apache-2.0",
66
"main": "lib/index.js",
7+
"types": "lib/index.d.ts",
78
"module": "es/index.js",
89
"sass": "index.scss",
910
"repository": {
@@ -16,7 +17,6 @@
1617
"es",
1718
"lib",
1819
"scss",
19-
"src",
2020
"umd",
2121
"index.scss",
2222
"telemetry.yml"
@@ -36,7 +36,8 @@
3636
"provenance": true
3737
},
3838
"scripts": {
39-
"build": "yarn clean && carbon-cli bundle src/index.js --name CarbonType && carbon-cli check \"scss/*.scss\"",
39+
"build:types": "tsc -p tsconfig.types.json",
40+
"build": "yarn clean && carbon-cli bundle src/index.ts --name CarbonType && yarn build:types && carbon-cli check \"scss/*.scss\"",
4041
"clean": "rimraf css es lib umd",
4142
"postinstall": "ibmtelemetry --config=telemetry.yml"
4243
},
@@ -50,7 +51,9 @@
5051
"@carbon/test-utils": "^10.41.0",
5152
"change-case-all": "^2.1.0",
5253
"css": "^3.0.0",
53-
"rimraf": "^6.0.1"
54+
"rimraf": "^6.0.1",
55+
"typescript": "^5.7.3",
56+
"typescript-config-carbon": "workspace:^0.10.0"
5457
},
5558
"eyeglass": {
5659
"exports": false,

packages/type/src/fluid.js

Lines changed: 0 additions & 86 deletions
This file was deleted.

packages/type/src/fluid.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/**
2+
* Copyright IBM Corp. 2018, 2026
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import { breakpoint as bp, breakpoints } from '@carbon/layout';
9+
import type { BreakpointName } from '@carbon/layout';
10+
import type { TypeStyle } from './types';
11+
12+
type TypeBreakpointStyles = Partial<TypeStyle>;
13+
14+
type TypeToken = TypeStyle & {
15+
breakpoints?: Partial<Record<BreakpointName, TypeBreakpointStyles>>;
16+
};
17+
18+
type FluidResult = TypeStyle &
19+
Record<string, TypeBreakpointStyles | number | string | undefined>;
20+
21+
const breakpointNames = Object.keys(breakpoints) as BreakpointName[];
22+
23+
const next = (name: BreakpointName) => {
24+
return breakpointNames[breakpointNames.indexOf(name) + 1];
25+
};
26+
27+
export const fluid = (selector: TypeToken): FluidResult => {
28+
const { breakpoints: fluidBreakpoints, ...baseStyles } = selector;
29+
const styles: FluidResult = { ...baseStyles };
30+
31+
if (typeof fluidBreakpoints !== 'object' || fluidBreakpoints === null) {
32+
return styles;
33+
}
34+
35+
const fluidBreakpointNames = Object.keys(
36+
fluidBreakpoints
37+
) as BreakpointName[];
38+
if (fluidBreakpointNames.length === 0) {
39+
return styles;
40+
}
41+
42+
styles.fontSize = fluidTypeSize(styles, 'sm', fluidBreakpoints);
43+
44+
fluidBreakpointNames.forEach((name) => {
45+
styles[bp(name)] = {
46+
...fluidBreakpoints[name],
47+
fontSize: fluidTypeSize(styles, name, fluidBreakpoints),
48+
};
49+
});
50+
51+
return styles;
52+
};
53+
54+
const fluidTypeSize = (
55+
defaultStyles: TypeStyle,
56+
fluidBreakpointName: BreakpointName,
57+
fluidBreakpoints: Partial<Record<BreakpointName, TypeBreakpointStyles>>
58+
) => {
59+
const breakpoint = breakpoints[fluidBreakpointName];
60+
const fluidBreakpoint =
61+
fluidBreakpointName === 'sm'
62+
? defaultStyles
63+
: fluidBreakpoints[fluidBreakpointName];
64+
65+
const defaultFontSize = defaultStyles.fontSize ?? '';
66+
const breakpointFontSize = fluidBreakpoint?.fontSize;
67+
68+
let maxFontSize = defaultFontSize;
69+
let minFontSize = defaultFontSize;
70+
if (breakpointFontSize) {
71+
minFontSize = breakpointFontSize;
72+
}
73+
74+
let maxViewportWidth = breakpoint.width;
75+
const minViewportWidth = breakpoint.width;
76+
77+
let nextBreakpointAvailable = next(fluidBreakpointName);
78+
let nextFluidBreakpointName: BreakpointName | null = null;
79+
80+
while (nextBreakpointAvailable) {
81+
if (fluidBreakpoints[nextBreakpointAvailable]) {
82+
nextFluidBreakpointName = nextBreakpointAvailable;
83+
break;
84+
}
85+
nextBreakpointAvailable = next(nextBreakpointAvailable);
86+
}
87+
88+
if (nextFluidBreakpointName) {
89+
const nextFluidBreakpoint = breakpoints[nextFluidBreakpointName];
90+
const nextFontSize = fluidBreakpoints[nextFluidBreakpointName]?.fontSize;
91+
92+
if (!nextFontSize) {
93+
return minFontSize;
94+
}
95+
96+
maxFontSize = nextFontSize;
97+
maxViewportWidth = nextFluidBreakpoint.width;
98+
99+
return `calc(${minFontSize} + ${subtract(
100+
maxFontSize,
101+
minFontSize
102+
)} * ((100vw - ${minViewportWidth}) / ${subtract(
103+
maxViewportWidth,
104+
minViewportWidth
105+
)}))`;
106+
}
107+
108+
return minFontSize;
109+
};
110+
111+
const subtract = (a: string | number, b: string | number) => {
112+
return parseFloat(String(a)) - parseFloat(String(b));
113+
};
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright IBM Corp. 2018, 2023
2+
* Copyright IBM Corp. 2018, 2026
33
*
44
* This source code is licensed under the Apache-2.0 license found in the
55
* LICENSE file in the root directory of this source tree.
@@ -17,8 +17,8 @@ export const fontFamilies = {
1717
serif: "'IBM Plex Serif', 'Georgia', Times, serif",
1818
};
1919

20-
export function fontFamily(name) {
21-
if (!fontFamilies[name]) {
20+
export const fontFamily = (name: keyof typeof fontFamilies) => {
21+
if (!(name in fontFamilies)) {
2222
throw new Error(
2323
`Unable to find font family: \`${name}\`. Expected one of: ` +
2424
`[${Object.keys(fontFamilies).join(', ')}]`
@@ -27,4 +27,4 @@ export function fontFamily(name) {
2727
return {
2828
fontFamily: fontFamilies[name],
2929
};
30-
}
30+
};
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright IBM Corp. 2018, 2023
2+
* Copyright IBM Corp. 2018, 2026
33
*
44
* This source code is licensed under the Apache-2.0 license found in the
55
* LICENSE file in the root directory of this source tree.
@@ -11,8 +11,8 @@ export const fontWeights = {
1111
semibold: 600,
1212
};
1313

14-
export function fontWeight(weight) {
15-
if (!fontWeights[weight]) {
14+
export const fontWeight = (weight: keyof typeof fontWeights) => {
15+
if (!(weight in fontWeights)) {
1616
throw new Error(
1717
`Unable to find font weight: \`${weight}\`. Expected one of: ` +
1818
`[${Object.keys(fontWeights).join(', ')}]`
@@ -21,4 +21,4 @@ export function fontWeight(weight) {
2121
return {
2222
fontWeight: fontWeights[weight],
2323
};
24-
}
24+
};

packages/type/src/index.js

Lines changed: 0 additions & 28 deletions
This file was deleted.

packages/type/src/index.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Copyright IBM Corp. 2018, 2026
3+
*
4+
* This source code is licensed under the Apache-2.0 license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
export { fluid } from './fluid';
9+
export { fontFamilies, fontFamily } from './fontFamily';
10+
export { fontWeight, fontWeights } from './fontWeight';
11+
export { print } from './print';
12+
export { reset } from './reset';
13+
export { getTypeSize, scale } from './scale';
14+
export * from './styles';
15+
export * as styles from './styles';
16+
export { unstable_tokens } from './tokens';
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
/**
2-
* Copyright IBM Corp. 2018, 2023
2+
* Copyright IBM Corp. 2018, 2026
33
*
44
* This source code is licensed under the Apache-2.0 license found in the
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8-
export function print(block) {
8+
type PrintableBlock = Record<string, number | string>;
9+
10+
export const print = (block: PrintableBlock) => {
911
return Object.keys(block).reduce((acc, key, index) => {
1012
// Short-circuit on the foreign key 'breakpoints'. This is used in our
1113
// tokens for fluid type and should not be printed. In the future, we should
@@ -20,9 +22,9 @@ export function print(block) {
2022
}
2123
return acc + '\n' + property;
2224
}, '');
23-
}
25+
};
2426

25-
function paramCase(string) {
27+
const paramCase = (string: string) => {
2628
let result = '';
2729
for (let i = 0; i < string.length; i++) {
2830
const character = string[i];
@@ -33,4 +35,4 @@ function paramCase(string) {
3335
result += character;
3436
}
3537
return result;
36-
}
38+
};
Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright IBM Corp. 2018, 2023
2+
* Copyright IBM Corp. 2018, 2026
33
*
44
* This source code is licensed under the Apache-2.0 license found in the
55
* LICENSE file in the root directory of this source tree.
@@ -8,8 +8,9 @@
88
import { baseFontSize, px } from '@carbon/layout';
99
import { fontFamilies } from './fontFamily';
1010
import { fontWeights } from './fontWeight';
11+
import type { TypeStyle } from './types';
1112

12-
export const reset = {
13+
export const reset: Record<'body' | 'code' | 'html' | 'strong', TypeStyle> = {
1314
html: {
1415
fontSize: px(baseFontSize),
1516
},

0 commit comments

Comments
 (0)