Skip to content

Commit

Permalink
TypeScript: convert fontProvider (#12761)
Browse files Browse the repository at this point in the history
* WIP

* First iteration

* Trying to fix types in `cleanForSlug`

* Addressing feedback

* Fixed references to renamed functions

Doh!

* Fixed default value for custom fonts (before they are loaded)
  • Loading branch information
Morten Barklund authored Dec 9, 2022
1 parent 7739692 commit 976a8c5
Show file tree
Hide file tree
Showing 26 changed files with 237 additions and 126 deletions.
6 changes: 1 addition & 5 deletions packages/element-library/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,5 @@
{ "path": "../transform" },
{ "path": "../units" }
],
"include": [
"src/constants.ts",
"src/types.ts",
"src/types"
]
"include": ["src/constants.ts", "src/types.ts", "src/types"]
}
18 changes: 16 additions & 2 deletions packages/elements/src/types/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,30 @@ export interface FontMetrics {
lGap: number;
}

export interface FontData {
export interface BaseFontData {
family: string;
service?: string;
weights?: FontWeight[];
styles?: FontStyle[];
variants?: FontVariant[];
fallbacks?: string[];
metrics?: FontMetrics;
}

export interface GoogleFontData extends BaseFontData {
service: 'fonts.google.com';
}

export interface SystemFontData extends BaseFontData {
service: 'system';
}

export interface CustomFontData extends BaseFontData {
service: 'custom';
url: string;
}

export type FontData = GoogleFontData | SystemFontData | CustomFontData;

export interface ProductImage {
alt: string;
url: string;
Expand Down
30 changes: 25 additions & 5 deletions packages/elements/src/types/element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,31 @@ export interface ProductElement extends Element {
product: ProductData;
}

interface BaseTextElementFont {
service: string;
family: string;
fallbacks: string[];
}

export interface GoogleTextElementFont extends BaseTextElementFont {
service: 'fonts.google.com';
}

export interface SystemTextElementFont extends BaseTextElementFont {
service: 'system';
}

export interface CustomTextElementFont extends BaseTextElementFont {
service: 'custom';
url: string;
}

export type TextElementFont =
| GoogleTextElementFont
| SystemTextElementFont
| CustomTextElementFont;

export interface TextElement extends Element {
content: string;
font: {
service: string;
family: string;
fallbacks: string[];
};
font: TextElementFont;
}
2 changes: 1 addition & 1 deletion packages/fonts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
},
"main": "dist/index.js",
"module": "dist-module/index.js",
"tyoes": "dist-types/index.d.ts",
"types": "dist-types/index.d.ts",
"source": "src/index.ts",
"publishConfig": {
"access": "public"
Expand Down
2 changes: 1 addition & 1 deletion packages/fonts/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@

export interface Font {
family: string;
variants: Array<[number, number]>;
variants?: Array<[number, number]>;
}
5 changes: 1 addition & 4 deletions packages/output/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,5 @@
{ "path": "../units" },
{ "path": "../url" }
],
"include": [
"src/types.ts",
"src/utils/*.ts"
]
"include": ["src/types.ts", "src/utils/*.ts"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,17 @@ import {
ensureFontLoaded,
loadInlineStylesheet,
} from '@googleforcreators/dom';
import type { FontData } from '@googleforcreators/elements';

/**
* Internal dependencies
*/
import cleanForSlug from '../../../utils/cleanForSlug';
import type { FontConfig } from '../types';

function useLoadFontFiles() {
const maybeLoadFont = useCallback(async (font) => {
const { family, service, variants, url } = font;
const maybeLoadFont = useCallback(async (font: FontData) => {
const { family, service, variants } = font;

const handle = cleanForSlug(family);
const elementId = `web-stories-${handle}-font-css`;
Expand All @@ -50,9 +52,14 @@ function useLoadFontFiles() {
elementId
);
break;
case 'custom':
await loadInlineStylesheet(elementId, getFontCSS(family, url));
case 'custom': {
const fontCSS = getFontCSS(family, font.url);
if (!fontCSS) {
return;
}
loadInlineStylesheet(elementId, fontCSS);
break;
}
default:
return;
}
Expand All @@ -67,7 +74,7 @@ function useLoadFontFiles() {
* @return {Promise<boolean>} Returns fonts loaded promise
*/
const maybeEnqueueFontStyle = useCallback(
(fonts) => {
(fonts: FontConfig[]) => {
return Promise.allSettled(
fonts.map(async ({ font, fontWeight, fontStyle, content }) => {
const { family, service } = font;
Expand Down
22 changes: 0 additions & 22 deletions packages/story-editor/src/app/font/context.js

This file was deleted.

46 changes: 46 additions & 0 deletions packages/story-editor/src/app/font/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/**
* External dependencies
*/
import { createContext } from '@googleforcreators/react';

/**
* Internal dependencies
*/
import type { FontProviderState } from './types';

export default createContext<FontProviderState>({
state: {
fonts: [],
curatedFonts: [],
customFonts: [],
recentFonts: [],
},
actions: {
getFontsBySearch: () => Promise.resolve([]),
getFontByName: () => null,
maybeEnqueueFontStyle: () => Promise.resolve(),
getFontWeight: (name: string) => [{ name, value: 400 }],
getFontFallback: () => [''],
ensureMenuFontsLoaded: () => undefined,
ensureCustomFontsLoaded: () => undefined,
addRecentFont: () => undefined,
loadCustomFonts: () => Promise.resolve(),
loadCuratedFonts: () => Promise.resolve(),
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
/**
* External dependencies
*/
import PropTypes from 'prop-types';
import type { PropsWithChildren } from 'react';
import { useCallback, useRef, useState } from '@googleforcreators/react';
import { CURATED_FONT_NAMES } from '@googleforcreators/fonts';
import { loadStylesheet } from '@googleforcreators/dom';
import type { FontData } from '@googleforcreators/elements';

/**
* Internal dependencies
Expand All @@ -30,19 +31,20 @@ import { useAPI } from '../api';
import Context from './context';
import useLoadFontFiles from './actions/useLoadFontFiles';
import { GOOGLE_MENU_FONT_URL } from './constants';
import type { FontWeightOption } from './types';

function FontProvider({ children }) {
const [queriedFonts, setQueriedFonts] = useState([]);
const [curatedFonts, setCuratedFonts] = useState([]);
const [recentFonts, setRecentFonts] = useState([]);
const [customFonts, setCustomFonts] = useState(null);
function FontProvider({ children }: PropsWithChildren<unknown>) {
const [queriedFonts, setQueriedFonts] = useState<FontData[]>([]);
const [curatedFonts, setCuratedFonts] = useState<FontData[]>([]);
const [recentFonts, setRecentFonts] = useState<FontData[]>([]);
const [customFonts, setCustomFonts] = useState<FontData[] | null>(null);
const {
actions: { getFonts },
} = useAPI();

const fonts = queriedFonts.length > 0 ? queriedFonts : curatedFonts;

const getCustomFonts = useCallback(async () => {
const loadCustomFonts = useCallback(async () => {
if (customFonts || !getFonts) {
return;
}
Expand All @@ -66,7 +68,7 @@ function FontProvider({ children }) {
setCustomFonts(formattedFonts);
}, [getFonts, customFonts]);

const getCuratedFonts = useCallback(async () => {
const loadCuratedFonts = useCallback(async () => {
if (curatedFonts.length || !getFonts) {
return;
}
Expand All @@ -92,21 +94,21 @@ function FontProvider({ children }) {
const { maybeEnqueueFontStyle, maybeLoadFont } = useLoadFontFiles();

const getFontByName = useCallback(
(name) => {
(name: string) => {
const foundFont = fonts.find((font) => font.family === name);
return foundFont ? foundFont : {};
return foundFont ? foundFont : null;
},
[fonts]
);

const getFontsBySearch = useCallback(
async (search) => {
async (search: string) => {
if (search.length < 2) {
setQueriedFonts([]);
return [];
}

const newFonts = await getFonts({ search });
const newFonts = (await getFonts?.({ search })) || [];

const formattedFonts = newFonts.map((font) => ({
...font,
Expand All @@ -122,8 +124,10 @@ function FontProvider({ children }) {
);

const getFontWeight = useCallback(
(name) => {
const defaultFontWeights = [{ name: FONT_WEIGHT_NAMES[400], value: 400 }];
(name: string) => {
const defaultFontWeights: FontWeightOption[] = [
{ name: FONT_WEIGHT_NAMES[400], value: 400 },
];

const currentFont = getFontByName(name);
let fontWeights = defaultFontWeights;
Expand All @@ -142,15 +146,15 @@ function FontProvider({ children }) {
);

const getFontFallback = useCallback(
(name) => {
(name: string) => {
const currentFont = getFontByName(name);
return currentFont?.fallbacks ? currentFont.fallbacks : [];
},
[getFontByName]
);

const addRecentFont = useCallback(
(recentFont) => {
(recentFont: FontData) => {
const newRecentFonts = [recentFont];
recentFonts.forEach((font) => {
if (recentFont.family === font.family) {
Expand All @@ -163,8 +167,8 @@ function FontProvider({ children }) {
[recentFonts]
);

const menuFonts = useRef([]);
const ensureMenuFontsLoaded = useCallback((fontsToLoad) => {
const menuFonts = useRef<string[]>([]);
const ensureMenuFontsLoaded = useCallback((fontsToLoad: string[]) => {
const newMenuFonts = fontsToLoad.filter(
(fontName) => !menuFonts.current.includes(fontName)
);
Expand All @@ -187,13 +191,13 @@ function FontProvider({ children }) {
const ensureCustomFontsLoaded = useCallback(
(fontsToLoad) => {
for (const font of fontsToLoad) {
const fontObj = customFonts.find(({ family }) => family === font);
const fontObj = customFonts?.find(({ family }) => family === font);

if (!fontObj) {
continue;
}

maybeLoadFont(fontObj);
void maybeLoadFont(fontObj);
}
},
[customFonts, maybeLoadFont]
Expand All @@ -215,16 +219,12 @@ function FontProvider({ children }) {
ensureMenuFontsLoaded,
ensureCustomFontsLoaded,
addRecentFont,
getCustomFonts,
getCuratedFonts,
loadCustomFonts,
loadCuratedFonts,
},
};

return <Context.Provider value={state}>{children}</Context.Provider>;
}

FontProvider.propTypes = {
children: PropTypes.node,
};

export default FontProvider;
File renamed without changes.
Loading

0 comments on commit 976a8c5

Please sign in to comment.