PluginProbe
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News / 4.0.8
Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News v4.0.8
4.0.8 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 4.0.2 4.0.1 2.3.5 2.3.6 2.4.0 2.4.1 2.4.10 2.4.11 2.4.12 2.4.13 2.4.14 2.4.15 2.4.16 2.4.17 2.4.18 2.4.19 2.4.2 2.4.20 2.4.21 All 88 releases
post-carousel / src / components / typography2 / typography.js

typography.js in Smart Post – Post Grid, Post Carousel, Post Slider Gutenberg Blocks for Blog & News 4.0.8, at src/components/typography2/typography.js

520 lines 14.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import Select from "react-select";
2 import { __ } from "@wordpress/i18n";
3 import { Button, Popover } from "@wordpress/components";
4 import { useEffect, useState } from "@wordpress/element";
5 import SPRangeControl from "../rangeControl/rangeControl.js";
6 import ComponentsTopSection from "../componentsTopControl/ComponentsTopSection.js";
7 import { EditIcon } from "./svgIcon.js";
8 import "./editor.scss";
9 import SelectField from "../selectField/selectField.js";
10 import { fontWeightMap, getFontWeightList, textStylesOptions } from "./utility.js";
11 import InputControl from "../inputControl/inputControl.js";
12 import { useDeviceType } from "../../controls/controls.js";
13
14 const fetchFonts = async () => {
15 try {
16 const response = await fetch(
17 "https://www.googleapis.com/webfonts/v1/webfonts?key=AIzaSyCJIzfKoHlACqsmK1zDzl-OAsgtJPk8BtI"
18 );
19 if (response.status === 200) {
20 return response.json();
21 }
22 } catch (error) {
23 // eslint-disable-next-line no-console
24 console.error("Error fetching Google Fonts:", error);
25 }
26 };
27
28 const TypographyNew = ({
29 setAttributes,
30 attributes,
31 fontSizeDefault = { unit: "px", value: 16 },
32 spacingDefaultValue = { unit: "px", value: 0 },
33 lineDefaultValue = { unit: "px", value: 0 },
34 typographyLabel = "Typography",
35 }) => {
36 const [allFonts, setAllFonts] = useState([]);
37 const [fontLists, setFontLists] = useState([]);
38 const [lineHeightUpdateKey, setLineHeightUpdateKey] = useState(0);
39 const {
40 family,
41 familyKey,
42 fontSize,
43 fontSizeKey,
44 lineHeight,
45 lineHeightKey,
46 fontSpacing,
47 fontSpacingKey,
48 wordSpacing,
49 wordSpacingKey,
50 } = attributes;
51 const deviceType = useDeviceType();
52
53 const [isVisible, setIsVisible] = useState(false);
54 const toggleVisible = () => {
55 setIsVisible((state) => !state);
56 };
57
58 useEffect(() => {
59 if (allFonts.length === 0) {
60 fetchFonts().then((data) => {
61 const fonts = data.items.map((item) => {
62 return {
63 label: item.family,
64 value: item.family,
65 font: { family: item.family, variants: item.variants },
66 };
67 });
68 setAllFonts(fonts);
69 setFontLists(fonts.filter((font, i) => i < 50 && font));
70 });
71 }
72 }, []);
73
74 const fontSearch = (inputValue) => {
75 const googleFonts = allFonts
76 .filter((font) => {
77 return font.label.toLowerCase().includes(inputValue.toLowerCase());
78 })
79 .filter((font, i) => i < 30 && font);
80 setFontLists(googleFonts);
81 };
82
83 const fontWCheck = Array(
84 "100italic",
85 "300italic",
86 "italic",
87 "400italic",
88 "500italic",
89 "600italic",
90 "700italic",
91 "800italic",
92 "900italic"
93 );
94 const fontW = family.googleFont?.variants?.map((value) => {
95 if (fontWCheck.includes(value) || "100" === value) {
96 return "";
97 }
98
99 if ("regular" === value) {
100 value = "400";
101 }
102 return { label: value, value: value };
103 });
104
105 let fontWeightList = [];
106 if (fontW) {
107 fontWeightList = fontW.filter(function (item, pos) {
108 return "" !== item;
109 });
110 }
111
112 useEffect(() => {
113 const clickOutSite = (e) => {
114 const target = e.target.closest(".sp-smart-post-typography-fonts");
115 const buttonTarget = e.target.closest(".sp-smart-post-typography-btn button");
116 const familyTarget = e.target.closest(".css-1nmdiq5-menu");
117 if (!target && isVisible && !buttonTarget && !familyTarget) {
118 setIsVisible(false);
119 }
120 };
121 window.addEventListener("click", clickOutSite);
122
123 return () => window.removeEventListener("click", clickOutSite);
124 });
125
126 // default and active family options.
127 const defaultFamilyOption = {
128 label: "Default",
129 value: "Default",
130 font: {
131 family: "Default",
132 variants: ["300", "400", "500", "600", "700", "800"],
133 },
134 };
135 const activeFontFamily =
136 family.typography.family === ""
137 ? defaultFamilyOption
138 : {
139 label: family.googleFont?.family,
140 value: family.googleFont?.family,
141 font: family.googleFont,
142 };
143
144 const allFamilyList = [defaultFamilyOption, ...fontLists];
145
146 const isAvailableOnList = allFamilyList?.find((font) => font.value === activeFontFamily.value);
147
148 const fontFamilySelectOptions = isAvailableOnList
149 ? allFamilyList
150 : [defaultFamilyOption, activeFontFamily, ...fontLists];
151
152 // font family.
153 const { fontWeight, style } = family.typography;
154
155 const onChangeFontStyle = (fontStyle) => {
156 const arrayOfStyles = fontWeightMap[fontStyle]?.split(" ");
157 const style = fontWeightMap[fontStyle].includes("italic") ? "italic" : "";
158 const fontWeight = arrayOfStyles[arrayOfStyles?.length - 1];
159
160 setAttributes({
161 [familyKey]: {
162 ...family,
163 typography: {
164 ...family.typography,
165 fontWeight: fontWeight,
166 style: style,
167 },
168 },
169 });
170 };
171
172 const onChangeLineHeight = (value) => {
173 setAttributes({
174 [lineHeightKey]: {
175 ...lineHeight,
176 device: {
177 ...lineHeight?.device,
178 [deviceType]: value,
179 },
180 unit: {
181 ...lineHeight.unit,
182 [deviceType]: "px",
183 },
184 },
185 });
186 };
187 const onChangeFontSize = (newValue) => {
188 setAttributes({
189 [fontSizeKey]: {
190 ...fontSize,
191 device: {
192 ...fontSize?.device,
193 [deviceType]: newValue.value,
194 },
195 },
196 });
197 if (fontSize?.unit?.[deviceType] === "px") {
198 const dynamicLineHeight = parseInt(newValue.value * 1.2);
199 onChangeLineHeight(dynamicLineHeight);
200 setLineHeightUpdateKey(dynamicLineHeight);
201 }
202 };
203 const onChangeTextStyles = (key, value) => {
204 const newValue = family?.typography[key] === value ? "" : value;
205 setAttributes({
206 [familyKey]: {
207 ...family,
208 typography: {
209 ...family.typography,
210 [key]: newValue,
211 },
212 },
213 });
214 };
215
216 return (
217 <>
218 <div className="sp-smart-post-typography sp-smart-post-component-mb sp-smart-post-tab-panel">
219 <div className={`sp-smart-post-typography-btn ${isVisible && "active"}`}>
220 <p className="sp-smart-post-component-title">{typographyLabel}</p>
221 <Button
222 aria-label={isVisible ? "open typography popup" : "close typography popup"}
223 onClick={() => toggleVisible()}
224 >
225 {<EditIcon />}
226 </Button>
227 </div>
228
229 {isVisible && (
230 <Popover shift={true} focusOnMount={false}>
231 <div className={`sp-smart-post-typography-fonts`}>
232 <div className="sp-smart-post-typography-header">
233 <h4>Typography</h4>
234 </div>
235 <div className="sp-smart-post-typography-fields">
236 <div className={`sp-smart-post-typography-family sp-smart-post-component-mb`}>
237 <div className="sp-smart-post-select-field">
238 <div className="sp-smart-post-header">
239 <span className="sp-smart-post-component-title"> Font Family</span>
240 </div>
241
242 <Select
243 options={fontFamilySelectOptions}
244 value={activeFontFamily}
245 placeholder={activeFontFamily.label}
246 onChange={(nextFont) =>
247 setAttributes({
248 [familyKey]: {
249 ...family,
250 googleFont: nextFont?.font,
251 typography: {
252 ...family.typography,
253 family:
254 "Default" !== nextFont?.font?.family
255 ? nextFont?.font?.family
256 : "",
257 fontWeight:
258 "regular" === nextFont?.font?.variants[0]
259 ? "400"
260 : nextFont?.font?.variants[0],
261 },
262 },
263 })
264 }
265 onInputChange={(inputValue) => fontSearch(inputValue)}
266 />
267 </div>
268 </div>
269 {/* <SelectField
270 label={ __(
271 'Font Style',
272 'post-carousel'
273 ) }
274 value={ family.typography.style }
275 items={ [
276 // {label: 'Default', value: 'default'},
277 { label: 'Normal', value: 'normal' },
278 { label: 'Italic', value: 'italic' },
279 { label: 'Oblique', value: 'oblique' },
280 ] }
281 // flexStyle={true}
282 onChange={ ( newStyle ) =>
283 setAttributes( {
284 [ familyKey ]: {
285 ...family,
286 typography: {
287 ...family.typography,
288 style: newStyle,
289 },
290 },
291 } )
292 }
293 __nextHasNoMarginBottom
294 />
295 <SelectField
296 label={ __(
297 'Font Weight',
298 'post-carousel'
299 ) }
300 value={ family.typography.fontWeight }
301 items={ fontWeightList }
302 // flexStyle={true}
303 onChange={ ( newWeight ) =>
304 setAttributes( {
305 [ familyKey ]: {
306 ...family,
307 typography: {
308 ...family.typography,
309 fontWeight: newWeight,
310 },
311 },
312 } )
313 }
314 __nextHasNoMarginBottom
315 /> */}
316 <SelectField
317 label={__("Font Style", "post-carousel")}
318 attributes={
319 activeFontFamily?.font?.variants.includes(`${fontWeight}${style}`)
320 ? `${fontWeight}${style}`
321 : fontWeight
322 }
323 items={getFontWeightList(activeFontFamily)}
324 onChange={(newStyle) => onChangeFontStyle(newStyle)}
325 __nextHasNoMarginBottom
326 />
327 </div>
328
329 <SPRangeControl
330 label={__("Font Size", "post-carousel")}
331 customValue={fontSize?.device?.[deviceType]}
332 attributes={fontSize}
333 attributesKey={fontSizeKey}
334 setAttributes={setAttributes}
335 onValueChange={(newValue) => onChangeFontSize(newValue)}
336 units={["Px", "%", "Em"]}
337 defaultValue={fontSizeDefault}
338 />
339 <SPRangeControl
340 key={lineHeightUpdateKey}
341 label={__("Line Height", "post-carousel")}
342 setAttributes={setAttributes}
343 attributes={lineHeight}
344 units={["px", "%", "Em"]}
345 attributesKey={lineHeightKey}
346 defaultValue={lineDefaultValue}
347 typoLineHeight={true}
348 />
349 {/* <SPRangeControl
350 label={ __(
351 'Letter Spacing',
352 'post-carousel'
353 ) }
354 setAttributes={ setAttributes }
355 attributes={ fontSpacing }
356 units={ [ 'px', 'Em' ] }
357 step={ '0.1' }
358 attributesKey={ fontSpacingKey }
359 defaultValue={ spacingDefaultValue }
360 /> */}
361 {/* <SPToggleGroupControl
362 label={ __(
363 'Text Decoration',
364 'post-carousel'
365 ) }
366 attributes={ family.typography.decoration }
367 items={ [
368 {
369 label: 'Normal',
370 value: 'none',
371 tooltip: 'none',
372 },
373 {
374 label: <DecorationUnderline />,
375 value: 'underline',
376 tooltip: 'Underline',
377 },
378 {
379 label: <DecorationLineThrough />,
380 value: 'line-through',
381 tooltip: 'Line Through',
382 },
383 {
384 label: <DecorationOverLine />,
385 value: 'overline',
386 tooltip: 'Overline',
387 },
388 ] }
389 onClick={ ( newValue ) =>
390 setAttributes( {
391 [ familyKey ]: {
392 ...family,
393 typography: {
394 ...family.typography,
395 decoration: newValue,
396 },
397 },
398 } )
399 }
400 />
401 <SPToggleGroupControl
402 label={ __(
403 'Letter Case',
404 'post-carousel'
405 ) }
406 attributes={ family.typography.transform }
407 items={ [
408 {
409 label: 'None',
410 value: 'none',
411 tooltip: 'None',
412 },
413 {
414 label: 'AB',
415 value: 'uppercase',
416 tooltip: 'Uppercase',
417 },
418 {
419 label: 'ab',
420 value: 'lowercase',
421 tooltip: 'Lowercase',
422 },
423 {
424 label: 'Ab',
425 value: 'capitalize',
426 tooltip: 'Capitalize',
427 },
428 ] }
429 onClick={ ( newValue ) =>
430 setAttributes( {
431 [ familyKey ]: {
432 ...family,
433 typography: {
434 ...family.typography,
435 transform: newValue,
436 },
437 },
438 } )
439 }
440 /> */}
441 <div className="sp-smart-post-typography-word-spacing-latter-spacing-wrapper sp-d-flex sp-gap-8px">
442 <div className="sp-smart-post-typography-line-height-picker">
443 <ComponentsTopSection
444 label={__("Letter Spacing", "post-carousel")}
445 attributes={fontSpacing}
446 attributesKey={fontSpacingKey}
447 setAttributes={setAttributes}
448 units={["px", "em"]}
449 />
450 <InputControl
451 attributes={fontSpacing?.device?.[deviceType]}
452 type="number"
453 onChange={(newValue) => {
454 setAttributes({
455 [fontSpacingKey]: {
456 ...fontSpacing,
457 device: {
458 ...fontSpacing?.device,
459 [deviceType]: newValue,
460 },
461 },
462 });
463 }}
464 min={0}
465 />
466 </div>
467 {wordSpacing && (
468 <div className="sp-smart-post-typography-letter-spacing-picker">
469 <ComponentsTopSection
470 label={__("Word Spacing", "post-carousel")}
471 attributes={wordSpacing}
472 attributesKey={wordSpacingKey}
473 setAttributes={setAttributes}
474 units={["px", "em"]}
475 />
476 <InputControl
477 attributes={wordSpacing?.device?.[deviceType]}
478 type="number"
479 onChange={(newValue) => {
480 setAttributes({
481 [wordSpacingKey]: {
482 ...wordSpacing,
483 device: {
484 ...wordSpacing?.device,
485 [deviceType]: newValue,
486 },
487 },
488 });
489 }}
490 min={0}
491 />
492 </div>
493 )}
494 </div>
495 <div className="sp-smart-post-typography-multiple-button-group sp-smart-post-component-mb">
496 <ComponentsTopSection label={__("Text Format", "post-carousel")} />
497 <div className="sp-smart-post-button-group-list">
498 {textStylesOptions?.map(({ label, key, value }, i) => (
499 <button
500 key={i}
501 className={`components-button${
502 family?.typography[key] === value ? " active" : ""
503 }`}
504 onClick={() => onChangeTextStyles(key, value)}
505 >
506 <span title={value}>{label}</span>
507 </button>
508 ))}
509 </div>
510 </div>
511 </div>
512 </Popover>
513 )}
514 </div>
515 </>
516 );
517 };
518
519 export default TypographyNew;
520