From 3efef8b2e1510d66747115c278014ecb8cf887b4 Mon Sep 17 00:00:00 2001 From: Mike Wilkerson <11575183+mlwilkerson@users.noreply.github.com> Date: Fri, 6 Oct 2023 15:37:56 -0500 Subject: [PATCH 01/34] families and styles in dropdown selects --- .../fa-icon-chooser/fa-icon-chooser.tsx | 465 ++++-------------- 1 file changed, 99 insertions(+), 366 deletions(-) diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx index fc71c03..90fcce2 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx @@ -165,6 +165,57 @@ export class FaIconChooser { @State() fatalError: boolean = false; + @State() familyStyles: object = { + classic: { + solid: { + prefix: 'fas' + }, + regular: { + prefix: 'far' + }, + light: { + prefix: 'fal' + }, + thin: { + prefix: 'fat' + }, + brands: { + prefix: 'fab' + } + }, + duotone: { + solid: { + prefix: 'fad' + } + }, + sharp: { + solid: { + prefix: 'fass' + }, + regular: { + prefix: 'fasr' + }, + light: { + prefix: 'fasl' + } + }, + kit: { + custom: + { + prefix: 'fak' + } + }, + 'kit-duotone': { + custom: { + prefix: 'fakd' + } + } + }; + + @State() selectedFamily: string = 'classic'; + + @State() selectedStyle: string = 'solid'; + svgApi?: any; svgFetchBaseUrl?: string; @@ -179,6 +230,40 @@ export class FaIconChooser { this.toggleStyleFilter = this.toggleStyleFilter.bind(this); } + familyNameToLabel(name: string): string { + return name + } + + styleNameToLabel(name: string): string { + return name + } + + getFamilies(): string[] { + return Object.keys(this.familyStyles) + } + + selectFamily(e: any): void { + const fam = e.target.value + if ('string' === typeof fam && 'object' === typeof this.familyStyles[fam]) { + this.selectedFamily = fam + } + } + + selectStyle(e: any): void { + const style = e.target.value + if ('string' === typeof style && 'string' === typeof this.selectedFamily && 'object' === typeof this.familyStyles[this.selectedFamily]) { + this.selectedStyle = style + } + } + + getStylesForSelectedFamily(): string[] { + if ('string' === typeof this.selectedFamily && 'object' === typeof this.familyStyles[this.selectedFamily]) { + return Object.keys(this.familyStyles[this.selectedFamily]) + } else { + return [] + } + } + async loadKitMetadata() { const response = await this.handleQuery( ` @@ -539,372 +624,20 @@ export class FaIconChooser { > -
-
- this.toggleStyleFilter('fas')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - -
-
- this.toggleStyleFilter('far')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - -
-
- this.toggleStyleFilter('fal')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - - {this.slot('light-requires-pro')} -
-
- this.toggleStyleFilter('fat')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - - {this.slot('thin-requires-pro')} -
-
- this.toggleStyleFilter('fad')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - - {this.slot('duotone-requires-pro')} -
-
- this.toggleStyleFilter('fass')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - - {this.slot('sharp-solid-requires-pro')} -
-
- this.toggleStyleFilter('fasr')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - - {this.slot('sharp-regular-requires-pro')} -
-
- this.toggleStyleFilter('fasl')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - - {this.slot('sharp-light-requires-pro')} -
-
- this.toggleStyleFilter('fab')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - -
-
- this.toggleStyleFilter('fak')} - type="checkbox" - name="icons-style" - class="input-checkbox-custom" - > - - {this.slot('uploaded-requires-pro')} -
-
+ + + + +

{this.pro() ? this.slot('searching-pro') : this.slot('searching-free')} {this.resolvedVersion()} From 38ebb286f3fc6885086110d5788db67bc5ea3845 Mon Sep 17 00:00:00 2001 From: Frances Botsford Date: Wed, 15 May 2024 16:19:25 -0400 Subject: [PATCH 02/34] capitalize Kit --- packages/fa-icon-chooser/src/utils/slots.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/fa-icon-chooser/src/utils/slots.tsx b/packages/fa-icon-chooser/src/utils/slots.tsx index a273e2a..51d5d40 100644 --- a/packages/fa-icon-chooser/src/utils/slots.tsx +++ b/packages/fa-icon-chooser/src/utils/slots.tsx @@ -30,19 +30,19 @@ slotDefaults['searching-free'] = "You're searching Font Awesome Free icons in ve slotDefaults['searching-pro'] = "You're searching Font Awesome Pro icons in version"; -slotDefaults['light-requires-pro'] = 'You need to use a Pro kit to get Light icons.'; +slotDefaults['light-requires-pro'] = 'You need to use a Pro Kit to get Light icons.'; -slotDefaults['thin-requires-pro'] = 'You need to use a Pro kit with Version 6 to get Thin icons.'; +slotDefaults['thin-requires-pro'] = 'You need to use a Pro Kit with Version 6 to get Thin icons.'; -slotDefaults['duotone-requires-pro'] = 'You need to use a Pro kit with Version 5.10 or later to get Duotone icons.'; +slotDefaults['duotone-requires-pro'] = 'You need to use a Pro Kit with Version 5.10 or later to get Duotone icons.'; -slotDefaults['sharp-solid-requires-pro'] = 'You need to use a Pro kit with Version 6.2.0 or later to get Sharp Solid icons.'; +slotDefaults['sharp-solid-requires-pro'] = 'You need to use a Pro Kit with Version 6.2.0 or later to get Sharp Solid icons.'; -slotDefaults['sharp-regular-requires-pro'] = 'You need to use a Pro kit with Version 6.3.0 or later to get Sharp Regular icons.'; +slotDefaults['sharp-regular-requires-pro'] = 'You need to use a Pro Kit with Version 6.3.0 or later to get Sharp Regular icons.'; -slotDefaults['sharp-light-requires-pro'] = 'You need to use a Pro kit with Version 6.4.0 or later to get Sharp Light icons.'; +slotDefaults['sharp-light-requires-pro'] = 'You need to use a Pro Kit with Version 6.4.0 or later to get Sharp Light icons.'; -slotDefaults['uploaded-requires-pro'] = 'You need to use a Pro kit to get Uploaded icons.'; +slotDefaults['uploaded-requires-pro'] = 'You need to use a Pro Kit to get Uploaded icons.'; slotDefaults['kit-has-no-uploaded-icons'] = 'This kit contains no uploaded icons.'; @@ -56,7 +56,7 @@ slotDefaults['suggest-icon-upload'] = ( upload your own icon {' '} - to a Pro kit! + to a Pro Kit! ); From 46d252ef02f4ccc8b81d49bb4f03cb5d7b15ee1b Mon Sep 17 00:00:00 2001 From: Frances Botsford Date: Wed, 15 May 2024 17:41:08 -0400 Subject: [PATCH 03/34] halfway styling for putting family and styles in dropdowns --- .../fa-icon-chooser/fa-icon-chooser.css | 88 +------------------ .../fa-icon-chooser/fa-icon-chooser.tsx | 32 ++++--- 2 files changed, 21 insertions(+), 99 deletions(-) diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.css b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.css index 4f16def..0b1f366 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.css +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.css @@ -6,9 +6,11 @@ --icon-details-preview-line-height: 1; --icon-details-unicode-glyphs-label-min-width: var(--spacing-5xl); --icon-listing-roomy-font-size: var(--font-size-2xl); /* 32px */ - --icon-listing-roomy-gap-x: var(--spacing-xl); /* 36px */ + --icon-listing-roomy-gap-x: var(--spacing-md); /* 16px */ --icon-listing-roomy-gap-y: var(--spacing-md); /* 16px */ --icon-listing-roomy-size: calc(var(--spacing-base) * 8); /* 128px */ + --input-border-color: var(--fa-navy); + --input-border-width: .15rem; } :host { @@ -24,71 +26,9 @@ .wrap-search { --input-with-icon-color: var(--fa-navy); - --input-border-color: var(--fa-navy); --input-placeholder-color: var(--fa-md-gravy); } -.icons-style-menu-listing .wrap-icons-style-choice { - position: relative; -} - -.icons-style-menu-listing .input-checkbox-custom { - display: none; -} - -.icons-style-menu-listing .icons-style-choice { - display: flex; - cursor: pointer; - border: 2px solid var(--fa-lt-gravy); - border-radius: var(--border-radius-md); - color: var(--fa-dk-blue); - text-transform: capitalize; - text-align: center; -} - -.icons-style-menu-listing .icons-style-choice:hover { - border-color: var(--fa-dk-blue); - background-color: var(--fa-dk-blue); - color: var(--white); -} - -.icons-style-menu-listing .input-checkbox-custom:checked ~ .icons-style-choice { - color: var(--white); - background-color: var(--fa-navy); - border: 2px solid var(--fa-navy); -} - -.icons-style-menu-listing .input-checkbox-custom:disabled ~ .icons-style-choice { - color: var(--fa-gravy); - background-color: var(--white); - border: 2px solid var(--fa-lt-gravy); - cursor: default; -} - -.wrap-icons-style-choice .disabled-tooltip { - transform: translate(-50%, -50%); - position: absolute; - top: -2.5rem; - left: 50%; - border-radius: var(--border-radius-md); - background-color: rgba(16, 50, 87, 0.9); - padding: var(--spacing-2xs) var(--spacing-sm); - color: var(--white); - text-align: center; - line-height: 1.3; - width: 160%; - display: none; -} - -.wrap-icons-style-choice .input-checkbox-custom:disabled ~ .icons-style-choice:hover + .disabled-tooltip { - display: block; -} - -.icons-style-menu-listing .icons-style-choice > span, -.icons-style-menu-listing .icons-style-choice > .svg-inline--fa { - vertical-align: middle; -} - .wrap-icon-listing { background: var(--fa-lt-gravy); padding: var(--spacing-lg) var(--spacing-md); @@ -137,25 +77,3 @@ button.icon fa-icon { --paragraph-margin-bottom: var(--spacing-md); --paragraph-margin-top: var(--spacing-2xl); } - -.icons-style-menu-listing { - flex-wrap: wrap; -} - -.icons-style-menu-listing .wrap-icons-style-choice:nth-child(4n) { - break-after: always; -} - -/* custom > tablet */ - -@media (min-width: 62.625rem) { - .icons-style-menu-listing { - flex-wrap: nowrap; - } -} - -@media (min-width: 89rem) { - .icons-style-menu-listing .icons-style-choice { - display: flex; - } -} diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx index 90fcce2..647f585 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx @@ -610,7 +610,7 @@ export class FaIconChooser { -

+
- - - +
+
+ +
+
+ +
+
-

+

{this.pro() ? this.slot('searching-pro') : this.slot('searching-free')} {this.resolvedVersion()}

From 6b8f52d3c5e1cbfbf0fbb8dc8f05c10065ca858b Mon Sep 17 00:00:00 2001 From: Mike Wilkerson <11575183+mlwilkerson@users.noreply.github.com> Date: Tue, 21 May 2024 10:14:34 -0700 Subject: [PATCH 04/34] WIP: cleanup and generalize familyStyles --- .../fa-icon-chooser/fa-icon-chooser.tsx | 497 ++++++++++-------- 1 file changed, 280 insertions(+), 217 deletions(-) diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx index 647f585..440ad56 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx @@ -1,29 +1,35 @@ -import { Component, Event, Element, EventEmitter, Prop, State, h } from '@stencil/core'; -import { get, size, debounce } from 'lodash'; import { - freeCdnBaseUrl, - kitAssetsBaseUrl, + Component, + Element, + Event, + EventEmitter, + h, + Prop, + State, +} from "@stencil/core"; +import { debounce, get, size } from "lodash"; +import { buildIconChooserResult, + CONSOLE_MESSAGE_PREFIX, createFontAwesomeScriptElement, - IconUpload, defaultIcons, familyStyleToPrefix, - IconUploadLookup, + freeCdnBaseUrl, IconChooserResult, - UrlTextFetcher, - CONSOLE_MESSAGE_PREFIX, - isValidSemver, IconLookup, -} from '../../utils/utils'; -import { faSadTear, faTire } from '../../utils/icons'; -import { slotDefaults } from '../../utils/slots'; -import { IconPrefix } from '@fortawesome/fontawesome-common-types'; -import semver from 'semver'; + IconUpload, + IconUploadLookup, + isValidSemver, + kitAssetsBaseUrl, + UrlTextFetcher, +} from "../../utils/utils"; +import { faSadTear, faTire } from "../../utils/icons"; +import { slotDefaults } from "../../utils/slots"; export type QueryHandler = (document: string) => Promise; export type StyleFilters = { - [prefix in IconPrefix]: boolean; + [key: string]: boolean; }; type KitMetadata = { @@ -34,8 +40,6 @@ type KitMetadata = { iconUploads: Array | null; }; -const DISPLAY_NONE = { display: 'none' }; - /** * @slot fatal-error-heading - heading for fatal error message * @slot fatal-error-detail - details for fatal error message @@ -72,35 +76,39 @@ const DISPLAY_NONE = { display: 'none' }; * @slot uploaded-style-filter-sr-message - screen reader only message for style filter: uploaded */ @Component({ - tag: 'fa-icon-chooser', - styleUrl: 'fa-icon-chooser.css', + tag: "fa-icon-chooser", + styleUrl: "fa-icon-chooser.css", shadow: true, }) export class FaIconChooser { /** * The host element for this component's Shadow DOM. */ - @Element() host: HTMLElement; + @Element() + host: HTMLElement; /** * A kit token identifying a kit in which to find icons. Takes precedent over * version prop if both are present. */ - @Prop() kitToken?: string; + @Prop() + kitToken?: string; /** * Version to use for finding and loading icons when kitToken is not provided. * Must be a valid semantic version, as parsed by the [semver NPM](https://www.npmjs.com/package/semver), * like 5.5.13 or 6.0.0-beta1. */ - @Prop() version?: string; + @Prop() + version?: string; /** * Placeholder text for search form. * * Use this to provide translatable text. */ - @Prop() searchInputPlaceholder?: string; + @Prop() + searchInputPlaceholder?: string; /** * Required callback function which is responsible for taking a given GraphQL @@ -115,106 +123,80 @@ export class FaIconChooser { * drive the Icon Chooser, it will be necessary to authorize GraphQL API requests * sent to api.fontawesome.com with the [`kits_read` scope](https://fontawesome.com/v5.15/how-to-use/graphql-api/auth/scopes). */ - @Prop() handleQuery: QueryHandler; + @Prop() + handleQuery: QueryHandler; /** * Callback function that returns the text body of a response that * corresponds to an HTTP GET request for the given URL. For example, it * would be the result of [Response.text()](https://developer.mozilla.org/en-US/docs/Web/API/Response/text). */ - @Prop() getUrlText: UrlTextFetcher; + @Prop() + getUrlText: UrlTextFetcher; /** * Clients of the Icon Chooser should listen for this event in order to handle * the result of the user's interaction. */ @Event({ - eventName: 'finish', + eventName: "finish", composed: true, cancelable: true, bubbles: true, }) finish: EventEmitter; - @State() query: string = ''; + @State() + query: string = ""; - @State() isQuerying: boolean = false; + @State() + isQuerying: boolean = false; - @State() isInitialLoading: boolean = false; + @State() + isInitialLoading: boolean = false; - @State() hasQueried: boolean = false; + @State() + hasQueried: boolean = false; - @State() icons: IconLookup[] = []; + @State() + icons: IconLookup[] = []; - @State() styleFilterEnabled: boolean = false; + @State() + styleFilterEnabled: boolean = false; - @State() styleFilters: StyleFilters = { + @State() + styleFilters: StyleFilters = { fas: false, far: false, - fad: false, - fat: false, fab: false, - fal: false, - fak: false, - fass: false, - fasr: false, - fasl: false, }; - @State() kitMetadata: KitMetadata; + @State() + kitMetadata: KitMetadata; - @State() fatalError: boolean = false; + @State() + fatalError: boolean = false; - @State() familyStyles: object = { + @State() + familyStyles: object = { classic: { solid: { - prefix: 'fas' + prefix: "fas", }, regular: { - prefix: 'far' - }, - light: { - prefix: 'fal' - }, - thin: { - prefix: 'fat' + prefix: "far", }, brands: { - prefix: 'fab' - } - }, - duotone: { - solid: { - prefix: 'fad' - } - }, - sharp: { - solid: { - prefix: 'fass' - }, - regular: { - prefix: 'fasr' + prefix: "fab", }, - light: { - prefix: 'fasl' - } - }, - kit: { - custom: - { - prefix: 'fak' - } }, - 'kit-duotone': { - custom: { - prefix: 'fakd' - } - } }; - @State() selectedFamily: string = 'classic'; + @State() + selectedFamily: string = "classic"; - @State() selectedStyle: string = 'solid'; + @State() + selectedStyle: string = "solid"; svgApi?: any; @@ -231,36 +213,42 @@ export class FaIconChooser { } familyNameToLabel(name: string): string { - return name + return name; } styleNameToLabel(name: string): string { - return name + return name; } getFamilies(): string[] { - return Object.keys(this.familyStyles) + return Object.keys(this.familyStyles); } selectFamily(e: any): void { - const fam = e.target.value - if ('string' === typeof fam && 'object' === typeof this.familyStyles[fam]) { - this.selectedFamily = fam + const fam = e.target.value; + if ("string" === typeof fam && "object" === typeof this.familyStyles[fam]) { + this.selectedFamily = fam; } } selectStyle(e: any): void { - const style = e.target.value - if ('string' === typeof style && 'string' === typeof this.selectedFamily && 'object' === typeof this.familyStyles[this.selectedFamily]) { - this.selectedStyle = style + const style = e.target.value; + if ( + "string" === typeof style && "string" === typeof this.selectedFamily && + "object" === typeof this.familyStyles[this.selectedFamily] + ) { + this.selectedStyle = style; } } getStylesForSelectedFamily(): string[] { - if ('string' === typeof this.selectedFamily && 'object' === typeof this.familyStyles[this.selectedFamily]) { - return Object.keys(this.familyStyles[this.selectedFamily]) + if ( + "string" === typeof this.selectedFamily && + "object" === typeof this.familyStyles[this.selectedFamily] + ) { + return Object.keys(this.familyStyles[this.selectedFamily]); } else { - return [] + return []; } } @@ -291,12 +279,15 @@ export class FaIconChooser { `, ); - if (get(response, 'errors')) { - console.error('Font Awesome Icon Chooser GraphQL query errors', response.errors); + if (get(response, "errors")) { + console.error( + "Font Awesome Icon Chooser GraphQL query errors", + response.errors, + ); throw new Error(); } - const kit = get(response, 'data.me.kit'); + const kit = get(response, "data.me.kit"); this.kitMetadata = kit; } @@ -307,11 +298,11 @@ export class FaIconChooser { } resolvedVersion() { - return get(this, 'kitMetadata.release.version') || this.version; + return get(this, "kitMetadata.release.version") || this.version; } pro(): boolean { - return get(this, 'kitMetadata.licenseSelected') === 'pro'; + return get(this, "kitMetadata.licenseSelected") === "pro"; } async preload() { @@ -326,7 +317,9 @@ export class FaIconChooser { // a default. setupSlots() { for (const slotName in slotDefaults) { - const slotContentElement = this.host.querySelector(`[slot="${slotName}"]`); + const slotContentElement = this.host.querySelector( + `[slot="${slotName}"]`, + ); if (!slotContentElement) { this.activeSlotDefaults[slotName] = slotDefaults[slotName]; } @@ -334,17 +327,22 @@ export class FaIconChooser { } slot(name: string) { - return (this.activeSlotDefaults && this.activeSlotDefaults[name]) || ; + return (this.activeSlotDefaults && this.activeSlotDefaults[name]) || ( + + ); } componentWillLoad() { if (!this.kitToken && !isValidSemver(this.version)) { - console.error(`${CONSOLE_MESSAGE_PREFIX}: either a kit-token or valid semantic version is required.`, this); + console.error( + `${CONSOLE_MESSAGE_PREFIX}: either a kit-token or valid semantic version is required.`, + this, + ); this.fatalError = true; return; } - this.query = ''; + this.query = ""; this.isInitialLoading = true; @@ -354,13 +352,16 @@ export class FaIconChooser { .then(() => { const pro = this.pro(); - const baseUrl = this.kitToken ? kitAssetsBaseUrl(pro) : freeCdnBaseUrl(); + const baseUrl = this.kitToken + ? kitAssetsBaseUrl(pro) + : freeCdnBaseUrl(); if (pro) { - this.svgFetchBaseUrl = `${baseUrl}/releases/v${this.resolvedVersion()}/svgs`; + this.svgFetchBaseUrl = + `${baseUrl}/releases/v${this.resolvedVersion()}/svgs`; } - const svgApi = get(window, 'FontAwesome'); + const svgApi = get(window, "FontAwesome"); if (svgApi) { // If FA SVG/JS is already present in the outer DOM, just use it. @@ -369,17 +370,23 @@ export class FaIconChooser { // Otherwise, we'll add it to the outer DOM, but disable it from doing // anything automated that would have global affect--other than assigning // itself to the global window.FontAwesome. - return createFontAwesomeScriptElement(this.getUrlText, pro, this.resolvedVersion(), baseUrl, this.kitToken).then(scriptElement => { + return createFontAwesomeScriptElement( + this.getUrlText, + pro, + this.resolvedVersion(), + baseUrl, + this.kitToken, + ).then((scriptElement) => { document.head.appendChild(scriptElement); - return get(window, 'FontAwesome'); + return get(window, "FontAwesome"); }); } }) - .then(svgApi => { + .then((svgApi) => { this.svgApi = svgApi; - const dom = get(window, 'FontAwesome.dom'); - const style = document.createElement('STYLE'); - style.setAttribute('type', 'text/css'); + const dom = get(window, "FontAwesome.dom"); + const style = document.createElement("STYLE"); + style.setAttribute("type", "text/css"); const css = document.createTextNode(dom.css()); style.appendChild(css); this.host.shadowRoot.appendChild(style); @@ -389,12 +396,15 @@ export class FaIconChooser { this.activateDefaultStyleFilters(); - if (this.mayHaveIconUploads() && size(get(this, 'kitMetadata.iconUploads')) > 0) { + if ( + this.mayHaveIconUploads() && + size(get(this, "kitMetadata.iconUploads")) > 0 + ) { this.styleFilters.fak = true; } this.commonFaIconProps = { - svgApi: get(window, 'FontAwesome'), + svgApi: get(window, "FontAwesome"), pro: this.pro(), svgFetchBaseUrl: this.svgFetchBaseUrl, kitToken: this.kitToken, @@ -403,7 +413,7 @@ export class FaIconChooser { this.isInitialLoading = false; }) - .catch(e => { + .catch((e) => { console.error(e); this.isInitialLoading = false; this.fatalError = true; @@ -435,14 +445,19 @@ export class FaIconChooser { }`, ); - const filteredIconUploads = this.iconUploadsAsIconUploadLookups().filter(({ iconName }) => { - return iconName.indexOf(query) > -1; - }); + const filteredIconUploads = this.iconUploadsAsIconUploadLookups().filter( + ({ iconName }) => { + return iconName.indexOf(query) > -1; + }, + ); let iconSearchResults = response; - if (!Array.isArray(get(iconSearchResults, 'data.search'))) { - console.warn(`${CONSOLE_MESSAGE_PREFIX}: search results may be inaccurate since 'handleQuery' returned an unexpected value:`, response); + if (!Array.isArray(get(iconSearchResults, "data.search"))) { + console.warn( + `${CONSOLE_MESSAGE_PREFIX}: search results may be inaccurate since 'handleQuery' returned an unexpected value:`, + response, + ); iconSearchResults = { data: { search: [] } }; } @@ -453,30 +468,35 @@ export class FaIconChooser { } iconUploadsAsIconUploadLookups(): Array { - return get(this, 'kitMetadata.iconUploads', []).map(i => { - return { prefix: 'fak', iconName: i.name, iconUpload: i }; + return get(this, "kitMetadata.iconUploads", []).map((i) => { + return { prefix: "fak", iconName: i.name, iconUpload: i }; }); } setIcons(searchResultIcons: any, iconUploads: Array) { - this.icons = (get(searchResultIcons, 'data.search') || []).reduce((acc: Array, result: any) => { - const { id, familyStylesByLicense } = result; - - const familyStyles = this.pro() ? familyStylesByLicense.pro : familyStylesByLicense.free; - - familyStyles.map(familyStyle => { - acc.push({ - iconName: id, - prefix: familyStyleToPrefix(familyStyle), + this.icons = (get(searchResultIcons, "data.search") || []).reduce( + (acc: Array, result: any) => { + const { id, familyStylesByLicense } = result; + + const familyStyles = this.pro() + ? familyStylesByLicense.pro + : familyStylesByLicense.free; + + familyStyles.map((familyStyle) => { + acc.push({ + iconName: id, + prefix: familyStyleToPrefix(familyStyle), + }); }); - }); - return acc; - }, iconUploads); + return acc; + }, + iconUploads, + ); } - updateQueryResultsWithDebounce = debounce(query => { - this.updateQueryResults(query).catch(e => { + updateQueryResultsWithDebounce = debounce((query) => { + this.updateQueryResults(query).catch((e) => { console.error(e); this.fatalError = true; }); @@ -489,7 +509,7 @@ export class FaIconChooser { } resetStyleFilter(): void { - Object.keys(this.styleFilters).forEach(style => { + Object.keys(this.styleFilters).forEach((style) => { this.styleFilters[style] = false; }); @@ -498,11 +518,12 @@ export class FaIconChooser { isOnlyEnabledStyleFilter(style: string): boolean { if (this.styleFilters[style]) { - const foundAnotherEnabledStyleFilter = !!Object.keys(this.styleFilters).find(styleFilter => { - if (styleFilter === style) return false; // the current style doesn't count + const foundAnotherEnabledStyleFilter = !!Object.keys(this.styleFilters) + .find((styleFilter) => { + if (styleFilter === style) return false; // the current style doesn't count - return this.styleFilters[styleFilter]; - }); + return this.styleFilters[styleFilter]; + }); return !foundAnotherEnabledStyleFilter; } @@ -519,11 +540,17 @@ export class FaIconChooser { // If we're turning "off" the last style filter, this has the effect // if disabling the master style filter as well. if (this.isOnlyEnabledStyleFilter(style)) { - this.styleFilters = { ...this.styleFilters, [style]: !this.styleFilters[style] }; + this.styleFilters = { + ...this.styleFilters, + [style]: !this.styleFilters[style], + }; this.styleFilterEnabled = false; } else { // simply toggle this style - this.styleFilters = { ...this.styleFilters, [style]: !this.styleFilters[style] }; + this.styleFilters = { + ...this.styleFilters, + [style]: !this.styleFilters[style], + }; } } else { this.styleFilters = { ...this.styleFilters, [style]: true }; @@ -533,23 +560,7 @@ export class FaIconChooser { isV6() { const version = this.resolvedVersion(); - return version && version[0] === '6'; - } - - isDuotoneAvailable() { - return this.pro() && !!this.resolvedVersion().match('(5.[1-9][0-9]+.)|^6.'); - } - - isSharpSolidAvailable() { - return this.pro() && semver.satisfies(this.resolvedVersion(), '>=6.2.0'); - } - - isSharpLightAvailable() { - return this.pro() && semver.satisfies(this.resolvedVersion(), '>=6.4.0'); - } - - isSharpRegularAvailable() { - return this.pro() && semver.satisfies(this.resolvedVersion(), '>=6.3.0'); + return version && version[0] === "6"; } mayHaveIconUploads() { @@ -557,7 +568,7 @@ export class FaIconChooser { } hasIconUploads() { - return size(get(this, 'kitMetadata.iconUploads')); + return size(get(this, "kitMetadata.iconUploads")); } onKeyUp(e: any): void { @@ -575,20 +586,12 @@ export class FaIconChooser { } render() { - const falDisabled = !this.pro(); - const faslDisabled = !this.isSharpLightAvailable(); - const fassDisabled = !this.isSharpSolidAvailable(); - const fasrDisabled = !this.isSharpRegularAvailable(); - const fatDisabled = !(this.isV6() && this.pro()); - const fadDisabled = !this.isDuotoneAvailable(); - const fakDisabled = !this.mayHaveIconUploads(); - if (this.fatalError) { return (
-

{this.slot('fatal-error-heading')}

-

{this.slot('fatal-error-detail')}

+

{this.slot("fatal-error-heading")}

+

{this.slot("fatal-error-detail")}

); @@ -607,12 +610,23 @@ export class FaIconChooser { return (
-
From 3488016c217b7741f19492b922cff322e75bb838 Mon Sep 17 00:00:00 2001 From: Mike Wilkerson <11575183+mlwilkerson@users.noreply.github.com> Date: Fri, 24 May 2024 17:41:00 -0700 Subject: [PATCH 24/34] update handleQuery to take optional second arg for variables --- packages/fa-icon-chooser/dev/runtime.js | 370 +++++++++--------- .../fa-icon-chooser/fa-icon-chooser.tsx | 118 +++--- .../src/components/fa-icon-chooser/readme.md | 14 +- 3 files changed, 267 insertions(+), 235 deletions(-) diff --git a/packages/fa-icon-chooser/dev/runtime.js b/packages/fa-icon-chooser/dev/runtime.js index 9ae2082..f7e3e58 100644 --- a/packages/fa-icon-chooser/dev/runtime.js +++ b/packages/fa-icon-chooser/dev/runtime.js @@ -1,268 +1,286 @@ // This dev-only module isn't processed by the bundler like the others, // so we can't use a node env var to set this. Just hardcode it in one // place at the top. -const API_URL='https://api.fontawesome.com' +const API_URL = "https://api.fontawesome.com"; const FaIconChooserDevExports = (function () { - let showingIconChooser = false - let localConfig = undefined - const localDevMissingMsg = 'DEV: your local dev config in local.json is required but has not yet been loaded.' + let showingIconChooser = false; + let localConfig = undefined; + const localDevMissingMsg = + "DEV: your local dev config in local.json is required but has not yet been loaded."; function getUrlText(url) { // To simulate a fatal error, uncomment the following line: // return Promise.reject('simulated fatal error') return fetch(url) - .then(response => { - if(response.ok) { - return response.text() - } else { - throw new Error(`DEBUG: bad query for url: ${url}`) - } - }) + .then((response) => { + if (response.ok) { + return response.text(); + } else { + throw new Error(`DEBUG: bad query for url: ${url}`); + } + }); } - function handleQuery(query) { + function handleQuery(query, variables) { return new Promise((resolve, reject) => { const headers = { - 'Content-Type': 'application/json' - } + "Content-Type": "application/json", + }; getAccessToken() - .then(token => { - - if(token) { - headers['Authorization'] = `Bearer ${ token }` - console.log('handleQuery: using fresh access token to issue authorized request') - } else { - console.log('handleQuery: no access token found -- sending an unauthorized request') - } - - return fetch( API_URL, { - method: 'POST', + .then((token) => { + if (token) { + headers["Authorization"] = `Bearer ${token}`; + console.log( + "handleQuery: using fresh access token to issue authorized request", + ); + } else { + console.log( + "handleQuery: no access token found -- sending an unauthorized request", + ); + } + + const cleanedQuery = query.replace(/\s+/g, " "); + + return fetch(API_URL, { + method: "POST", headers, - body: JSON.stringify({ query }) - }, - ) - }) - .then(response => { - if(response.ok) { - response.json() - .then(json => resolve(json)) - .catch(e => reject(e)) - } else { - reject('bad query') - } - }) - .catch(e => reject(e)) - }) + body: JSON.stringify({ + query: cleanedQuery, + variables, + }), + }); + }) + .then((response) => { + if (response.ok) { + response.json() + .then((json) => resolve(json)) + .catch((e) => reject(e)); + } else { + reject("bad query"); + } + }) + .catch((e) => reject(e)); + }); } function handleResult(result) { - const resultElement = document.querySelector("#result") - const preElement = document.createElement('pre') - const text = document.createTextNode(JSON.stringify(result.detail)) - preElement.appendChild(text) - resultElement.appendChild(preElement) + const resultElement = document.querySelector("#result"); + const preElement = document.createElement("pre"); + const text = document.createTextNode(JSON.stringify(result.detail)); + preElement.appendChild(text); + resultElement.appendChild(preElement); } function clearResult() { - document.querySelectorAll("#result pre").forEach(child => child.remove()) + document.querySelectorAll("#result pre").forEach((child) => child.remove()); } function addIconChooser(props) { - const container = document.querySelector('#fa-icon-chooser-container') - const el = document.createElement('fa-icon-chooser') - el.handleQuery = handleQuery - el.getUrlText = getUrlText - el.addEventListener('finish', handleResult) - - const slotFatalErrorHeader = document.createElement('p') - slotFatalErrorHeader.setAttribute('slot', 'fatal-error-heading') - const slotFatalErrorHeaderMsg = document.createTextNode('Fatal Error') - slotFatalErrorHeader.appendChild(slotFatalErrorHeaderMsg) - el.appendChild(slotFatalErrorHeader) - - Object.keys(props).map(prop => { - el.setAttribute(prop, props[prop]) - }) - - container.appendChild(el) + const container = document.querySelector("#fa-icon-chooser-container"); + const el = document.createElement("fa-icon-chooser"); + el.handleQuery = handleQuery; + el.getUrlText = getUrlText; + el.addEventListener("finish", handleResult); + + const slotFatalErrorHeader = document.createElement("p"); + slotFatalErrorHeader.setAttribute("slot", "fatal-error-heading"); + const slotFatalErrorHeaderMsg = document.createTextNode("Fatal Error"); + slotFatalErrorHeader.appendChild(slotFatalErrorHeaderMsg); + el.appendChild(slotFatalErrorHeader); + + Object.keys(props).map((prop) => { + el.setAttribute(prop, props[prop]); + }); + + container.appendChild(el); } function closeIconChooser() { - document.querySelector('fa-icon-chooser').remove() + document.querySelector("fa-icon-chooser").remove(); } function setupHead() { - if(!localConfig) throw new Error(localDevMissingMsg) + if (!localConfig) throw new Error(localDevMissingMsg); // If there's no head config, we have nothing left to do here. - if(!localConfig.head) return + if (!localConfig.head) return; - const { head } = localConfig + const { head } = localConfig; - Object.keys(head).map(elementType => { - const el = document.createElement(elementType) - Object.keys(head[elementType]).map(attr => { - el.setAttribute(attr, head[elementType][attr]) - }) - document.head.appendChild(el) - }) + Object.keys(head).map((elementType) => { + const el = document.createElement(elementType); + Object.keys(head[elementType]).map((attr) => { + el.setAttribute(attr, head[elementType][attr]); + }); + document.head.appendChild(el); + }); } function toggleIconChooser() { - if(showingIconChooser) { - closeIconChooser() + if (showingIconChooser) { + closeIconChooser(); - const toggleIconContainer = document.querySelector('#toggle-icon-container') - if(toggleIconContainer) { + const toggleIconContainer = document.querySelector( + "#toggle-icon-container", + ); + if (toggleIconContainer) { while (toggleIconContainer.firstChild) { - toggleIconContainer.removeChild(toggleIconContainer.firstChild) + toggleIconContainer.removeChild(toggleIconContainer.firstChild); } - const newIcon = document.createElement('i') - newIcon.setAttribute('class', 'fas fa-toggle-off') - toggleIconContainer.appendChild(newIcon) + const newIcon = document.createElement("i"); + newIcon.setAttribute("class", "fas fa-toggle-off"); + toggleIconContainer.appendChild(newIcon); } - clearResult() - showingIconChooser = false + clearResult(); + showingIconChooser = false; } else { - showIconChooser() + showIconChooser(); - const toggleIconContainer = document.querySelector('#toggle-icon-container') - if(toggleIconContainer) { + const toggleIconContainer = document.querySelector( + "#toggle-icon-container", + ); + if (toggleIconContainer) { while (toggleIconContainer.firstChild) { - toggleIconContainer.removeChild(toggleIconContainer.firstChild) + toggleIconContainer.removeChild(toggleIconContainer.firstChild); } - const newIcon = document.createElement('i') - newIcon.setAttribute('class', 'fas fa-toggle-on') - toggleIconContainer.appendChild(newIcon) + const newIcon = document.createElement("i"); + newIcon.setAttribute("class", "fas fa-toggle-on"); + toggleIconContainer.appendChild(newIcon); } - showingIconChooser = true + showingIconChooser = true; } } function loadLocalConfig() { - const failMsg = 'DEV: failed request to get local.json:' - - return fetch('/dev/local.json') - .then(response => { - if(response.ok){ - return response.json() - } else { - return Promise.reject(response) - } - }) - .then(config => { - localConfig = config - }) - .catch(e => { - console.error(failMsg, e) - return Promise.reject(failMsg) - }) + const failMsg = "DEV: failed request to get local.json:"; + + return fetch("/dev/local.json") + .then((response) => { + if (response.ok) { + return response.json(); + } else { + return Promise.reject(response); + } + }) + .then((config) => { + localConfig = config; + }) + .catch((e) => { + console.error(failMsg, e); + return Promise.reject(failMsg); + }); } function getAccessToken() { - const apiToken = localConfig && localConfig.apiToken - if(!apiToken) { + const apiToken = localConfig && localConfig.apiToken; + if (!apiToken) { // If there's no apiToken, then it's not an error to resolve an undefined access token. - return Promise.resolve(undefined) + return Promise.resolve(undefined); } - const tokenJSON = window.localStorage.getItem('token') - const tokenObj = tokenJSON ? JSON.parse(tokenJSON) : undefined - const freshToken = (tokenObj && Math.floor(Date.now() / 1000) <= tokenObj.expiresAtEpochSeconds) + const tokenJSON = window.localStorage.getItem("token"); + const tokenObj = tokenJSON ? JSON.parse(tokenJSON) : undefined; + const freshToken = (tokenObj && + Math.floor(Date.now() / 1000) <= tokenObj.expiresAtEpochSeconds) ? tokenObj.token - : undefined + : undefined; - if(freshToken) return Promise.resolve(freshToken) + if (freshToken) return Promise.resolve(freshToken); return fetch(`${API_URL}/token`, { - method: 'POST', + method: "POST", headers: { - authorization: `Bearer ${ localConfig.apiToken }` - } + authorization: `Bearer ${localConfig.apiToken}`, + }, }) - .then(response => { - if(response.ok) { - response.json() - .then(obj => { - const expiresAtEpochSeconds = Math.floor(Date.now() / 1000) + obj['expires_in'] - - // WARNING: storing an access token in localStorage may not be good enough - // security in other situations. This is a development-only situation - // intended to run on a local development machine, so this seems like - // good enough security for that use case. - window.localStorage.setItem( - 'token', - JSON.stringify({ - token: obj['access_token'], - expiresAtEpochSeconds + .then((response) => { + if (response.ok) { + response.json() + .then((obj) => { + const expiresAtEpochSeconds = Math.floor(Date.now() / 1000) + + obj["expires_in"]; + + // WARNING: storing an access token in localStorage may not be good enough + // security in other situations. This is a development-only situation + // intended to run on a local development machine, so this seems like + // good enough security for that use case. + window.localStorage.setItem( + "token", + JSON.stringify({ + token: obj["access_token"], + expiresAtEpochSeconds, + }), + ); }) - ) - }) - .catch(e => { - throw e - }) - } else { - const msg = 'DEV: unexpected token endpoint response' - console.error(msg, response) - throw new Error(msg) - } - }) - .catch(e => { - throw e - }) + .catch((e) => { + throw e; + }); + } else { + const msg = "DEV: unexpected token endpoint response"; + console.error(msg, response); + throw new Error(msg); + } + }) + .catch((e) => { + throw e; + }); } function showIconChooser() { - if(!localConfig) throw new Error(localDevMissingMsg) - if(!localConfig.props) throw new Error('DEV: missing props key in your local.json') + if (!localConfig) throw new Error(localDevMissingMsg); + if (!localConfig.props) { + throw new Error("DEV: missing props key in your local.json"); + } - const { props } = localConfig + const { props } = localConfig; - if(!props['kit-token']) { - if(!props.version) { - throw new Error('DEV: your local.json must have a props key with either a version subkey or a kit-token subkey') + if (!props["kit-token"]) { + if (!props.version) { + throw new Error( + "DEV: your local.json must have a props key with either a version subkey or a kit-token subkey", + ); } - addIconChooser(props) - return + addIconChooser(props); + return; } getAccessToken() - .then(_token => addIconChooser(props)) - .catch(e => { - throw e - }) + .then((_token) => addIconChooser(props)) + .catch((e) => { + throw e; + }); } function getLocalConfig() { - return localConfig + return localConfig; } loadLocalConfig() - .then(setupHead) - .catch(e => { - throw e - }) + .then(setupHead) + .catch((e) => { + throw e; + }); - document.addEventListener('DOMContentLoaded', function() { - const toggle = document.querySelector('#fa-icon-chooser-toggle') + document.addEventListener("DOMContentLoaded", function () { + const toggle = document.querySelector("#fa-icon-chooser-toggle"); - if(toggle) { - toggle.addEventListener('click', toggleIconChooser) + if (toggle) { + toggle.addEventListener("click", toggleIconChooser); } - }) + }); return { toggleIconChooser, handleQuery, handleResult, getLocalConfig, - getUrlText - } -})() + getUrlText, + }; +})(); -if('undefined' !== typeof module) { - module.exports = FaIconChooserDevExports +if ("undefined" !== typeof module) { + module.exports = FaIconChooserDevExports; } diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx index d41cca5..3c753e7 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx @@ -5,14 +5,14 @@ import { EventEmitter, h, Prop, - State + State, } from "@stencil/core"; import { capitalize, debounce, find, get, set, size } from "lodash"; import { + buildDefaultIconsSearchResult, buildIconChooserResult, CONSOLE_MESSAGE_PREFIX, createFontAwesomeScriptElement, - buildDefaultIconsSearchResult, freeCdnBaseUrl, IconChooserResult, IconLookup, @@ -25,7 +25,10 @@ import { import { faSadTear, faTire } from "../../utils/icons"; import { slotDefaults } from "../../utils/slots"; -export type QueryHandler = (document: string) => Promise; +export type QueryHandler = ( + document: string, + variables?: object, +) => Promise; type KitMetadata = { version: string; @@ -200,8 +203,8 @@ export class FaIconChooser { const fam = e.target.value; if ("string" === typeof fam && "object" === typeof this.familyStyles[fam]) { this.selectedFamily = fam; - const styles = this.getStylesForSelectedFamily() - this.selectedStyle = styles[0] + const styles = this.getStylesForSelectedFamily(); + this.selectedStyle = styles[0]; } } @@ -215,12 +218,15 @@ export class FaIconChooser { } } - getPrefixForFamilyStyle(family: string, style: string) : string | undefined { - return get(this.familyStyles, [family, style, 'prefix']) + getPrefixForFamilyStyle(family: string, style: string): string | undefined { + return get(this.familyStyles, [family, style, "prefix"]); } - getSelectedPrefix() : string | undefined { - return this.getPrefixForFamilyStyle(this.selectedFamily, this.selectedStyle) + getSelectedPrefix(): string | undefined { + return this.getPrefixForFamilyStyle( + this.selectedFamily, + this.selectedStyle, + ); } getStylesForSelectedFamily(): string[] { @@ -235,40 +241,38 @@ export class FaIconChooser { } buildFamilyStyleReverseLookup(): void { - const acc = {} + const acc = {}; - for(const family in this.familyStyles) { - for(const style in this.familyStyles[family]) { - acc[this.familyStyles[family][style].prefix] = {family, style} + for (const family in this.familyStyles) { + for (const style in this.familyStyles[family]) { + acc[this.familyStyles[family][style].prefix] = { family, style }; } } - this.prefixToFamilyStyle = acc + this.prefixToFamilyStyle = acc; } prefixToFamilyStylePathSegment(prefix: string): string | undefined { - const family = get(this.prefixToFamilyStyle, [prefix, 'family']) - const style = get(this.prefixToFamilyStyle, [prefix, 'style']) + const family = get(this.prefixToFamilyStyle, [prefix, "family"]); + const style = get(this.prefixToFamilyStyle, [prefix, "style"]); - if(!family || !style) { - return + if (!family || !style) { + return; } - if('duotone' === family && 'solid' === style) { - return 'duotone' + if ("duotone" === family && "solid" === style) { + return "duotone"; } - return 'classic' === family - ? style - : `${family}-${style}` + return "classic" === family ? style : `${family}-${style}`; } async loadKitMetadata() { const response = await this.handleQuery( ` - query { + query KitMetadata($token: String!) { me { - kit(token:"${this.kitToken}") { + kit(token: $token) { version technologySelected licenseSelected @@ -293,6 +297,7 @@ export class FaIconChooser { } } `, + { token: this.kitToken }, ); if (get(response, "errors")) { @@ -307,22 +312,22 @@ export class FaIconChooser { this.kitMetadata = kit; this.updateFamilyStyles(get(kit, "release.familyStyles", [])); - const kitFamilyStyles = [] - const iconUploads = get(response, "data.me.kit.iconUploads", []) + const kitFamilyStyles = []; + const iconUploads = get(response, "data.me.kit.iconUploads", []); if (find(iconUploads, (i) => i.pathData.length === 1)) { kitFamilyStyles.push( - {family: 'kit', style: 'custom', prefix: 'fak'} - ) + { family: "kit", style: "custom", prefix: "fak" }, + ); } if (find(iconUploads, (i) => i.pathData.length > 1)) { kitFamilyStyles.push( - {family: 'kit-duotone', style: 'custom', prefix: 'fakd'}, - ) + { family: "kit-duotone", style: "custom", prefix: "fakd" }, + ); } - if(kitFamilyStyles.length > 0) { + if (kitFamilyStyles.length > 0) { this.updateFamilyStyles(kitFamilyStyles); } } @@ -332,7 +337,7 @@ export class FaIconChooser { set(this.familyStyles, [fs.family, fs.style, "prefix"], fs.prefix); } - this.buildFamilyStyleReverseLookup() + this.buildFamilyStyleReverseLookup(); } resolvedVersion() { @@ -371,7 +376,7 @@ export class FaIconChooser { } componentWillLoad() { - this.buildFamilyStyleReverseLookup() + this.buildFamilyStyleReverseLookup(); if (!this.kitToken && !isValidSemver(this.version)) { console.error( @@ -430,7 +435,7 @@ export class FaIconChooser { const css = document.createTextNode(dom.css()); style.appendChild(css); this.host.shadowRoot.appendChild(style); - this.defaultIcons = buildDefaultIconsSearchResult(this.familyStyles) + this.defaultIcons = buildDefaultIconsSearchResult(this.familyStyles); this.setIcons(this.defaultIcons, this.iconUploadsAsIconUploadLookups()); @@ -458,8 +463,8 @@ export class FaIconChooser { const response = await this.handleQuery( ` - query { - search(version:"${this.resolvedVersion()}", query: "${query}", first: 100) { + query Search($version: String!, $query: String!) { + search(version: $version, query: $query, first: 100) { id label familyStylesByLicense { @@ -474,6 +479,7 @@ export class FaIconChooser { } } }`, + { version: this.resolvedVersion(), query }, ); const filteredIconUploads = this.iconUploadsAsIconUploadLookups().filter( @@ -517,10 +523,10 @@ export class FaIconChooser { : familyStylesByLicense.free; familyStyles.map((fs) => { - const prefix = this.getPrefixForFamilyStyle(fs.family, fs.style) + const prefix = this.getPrefixForFamilyStyle(fs.family, fs.style); acc.push({ iconName: id, - prefix + prefix, }); }); @@ -538,10 +544,10 @@ export class FaIconChooser { }, 500); filteredIcons(): Array { - const selectedPrefix = this.getSelectedPrefix() + const selectedPrefix = this.getSelectedPrefix(); - if(!selectedPrefix) { - return [] + if (!selectedPrefix) { + return []; } return this.icons.filter(({ prefix }) => prefix === selectedPrefix); @@ -561,7 +567,7 @@ export class FaIconChooser { } onKeyUp(e: any): void { - if(this.query === e.target.value) { + if (this.query === e.target.value) { // If the user selects the contents of the query field using keystrokes, // those selection keystrokes will not change the query value and should // not trigger a new query. @@ -580,11 +586,11 @@ export class FaIconChooser { e.stopPropagation(); } - labelForFamilyOrStyle(labelOrFamily: string) : string { + labelForFamilyOrStyle(labelOrFamily: string): string { return labelOrFamily - .split('-') - .map((term) => capitalize(term)) - .join(' ') + .split("-") + .map((term) => capitalize(term)) + .join(" "); } render() { @@ -625,7 +631,9 @@ export class FaIconChooser { @@ -651,7 +659,9 @@ export class FaIconChooser { onChange={this.selectFamily.bind(this)} > {this.getFamilies().map((family: string) => ( - + ))}
@@ -662,7 +672,9 @@ export class FaIconChooser { onChange={this.selectStyle.bind(this)} > {this.getStylesForSelectedFamily().map((style: string) => ( - + ))}
@@ -675,7 +687,8 @@ export class FaIconChooser {

{!this.isQuerying && this.mayHaveIconUploads() && - !this.hasIconUploads() && (['kit', 'kit-duotone'].includes(this.selectedFamily)) && ( + !this.hasIconUploads() && + (["kit", "kit-duotone"].includes(this.selectedFamily)) && (

{this.slot("kit-has-no-uploaded-icons")} @@ -722,7 +735,8 @@ export class FaIconChooser { {...this.commonFaIconProps} size="2x" stylePrefix={iconLookup.prefix} - familyStylePathSegment={this.prefixToFamilyStylePathSegment(iconLookup.prefix)} + familyStylePathSegment={this + .prefixToFamilyStylePathSegment(iconLookup.prefix)} name={iconLookup.iconName} iconUpload={get(iconLookup, "iconUpload")} /> diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/readme.md b/packages/fa-icon-chooser/src/components/fa-icon-chooser/readme.md index d2f7720..2d70d50 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/readme.md +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/readme.md @@ -5,13 +5,13 @@ ## Properties -| Property | Attribute | Description | Type | Default | -| ------------------------ | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------ | ----------- | -| `getUrlText` | -- | Callback function that returns the text body of a response that corresponds to an HTTP GET request for the given URL. For example, it would be the result of [Response.text()](https://developer.mozilla.org/en-US/docs/Web/API/Response/text). | `(url: string) => Promise` | `undefined` | -| `handleQuery` | -- | Required callback function which is responsible for taking a given GraphQL query document and returns a Promise that resolves to a JavaScript object corresponding to the body of the associated network request, same as what would be produced by [Response.json()](https://developer.mozilla.org/en-US/docs/Web/API/Response/json). The query document is compliant with the GraphQL API at [api.fontawesome.com](https://fontawesome.com/v5.15/how-to-use/graphql-api/intro/getting-started). The implementation is responsible for handling any authorization that may be necessary to fulfill the request. For example, any time a kit is used to drive the Icon Chooser, it will be necessary to authorize GraphQL API requests sent to api.fontawesome.com with the [`kits_read` scope](https://fontawesome.com/v5.15/how-to-use/graphql-api/auth/scopes). | `(document: string) => Promise` | `undefined` | -| `kitToken` | `kit-token` | A kit token identifying a kit in which to find icons. Takes precedent over version prop if both are present. | `string` | `undefined` | -| `searchInputPlaceholder` | `search-input-placeholder` | Placeholder text for search form. Use this to provide translatable text. | `string` | `undefined` | -| `version` | `version` | Version to use for finding and loading icons when kitToken is not provided. Must be a valid semantic version, as parsed by the [semver NPM](https://www.npmjs.com/package/semver), like 5.5.13 or 6.0.0-beta1. | `string` | `undefined` | +| Property | Attribute | Description | Type | Default | +| ------------------------ | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ----------- | +| `getUrlText` | -- | Callback function that returns the text body of a response that corresponds to an HTTP GET request for the given URL. For example, it would be the result of [Response.text()](https://developer.mozilla.org/en-US/docs/Web/API/Response/text). | `(url: string) => Promise` | `undefined` | +| `handleQuery` | -- | Required callback function which is responsible for taking a given GraphQL query document and returns a Promise that resolves to a JavaScript object corresponding to the body of the associated network request, same as what would be produced by [Response.json()](https://developer.mozilla.org/en-US/docs/Web/API/Response/json). The query document is compliant with the GraphQL API at [api.fontawesome.com](https://fontawesome.com/v5.15/how-to-use/graphql-api/intro/getting-started). The implementation is responsible for handling any authorization that may be necessary to fulfill the request. For example, any time a kit is used to drive the Icon Chooser, it will be necessary to authorize GraphQL API requests sent to api.fontawesome.com with the [`kits_read` scope](https://fontawesome.com/v5.15/how-to-use/graphql-api/auth/scopes). | `(document: string, variables?: object) => Promise` | `undefined` | +| `kitToken` | `kit-token` | A kit token identifying a kit in which to find icons. Takes precedent over version prop if both are present. | `string` | `undefined` | +| `searchInputPlaceholder` | `search-input-placeholder` | Placeholder text for search form. Use this to provide translatable text. | `string` | `undefined` | +| `version` | `version` | Version to use for finding and loading icons when kitToken is not provided. Must be a valid semantic version, as parsed by the [semver NPM](https://www.npmjs.com/package/semver), like 5.5.13 or 6.0.0-beta1. | `string` | `undefined` | ## Events From 98a8945c6dc91631b5da76edb4ddde8ba188d060 Mon Sep 17 00:00:00 2001 From: Mike Wilkerson <11575183+mlwilkerson@users.noreply.github.com> Date: Wed, 29 May 2024 17:04:04 -0700 Subject: [PATCH 25/34] for search input field, respond to onInput instead of onKeyUp --- .../src/components/fa-icon-chooser/fa-icon-chooser.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx index 3c753e7..fcf2917 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx @@ -566,13 +566,7 @@ export class FaIconChooser { return size(get(this, "kitMetadata.iconUploads")); } - onKeyUp(e: any): void { - if (this.query === e.target.value) { - // If the user selects the contents of the query field using keystrokes, - // those selection keystrokes will not change the query value and should - // not trigger a new query. - return; - } + onSearchInputChange(e: any): void { this.query = e.target.value; if (size(this.query) === 0) { this.setIcons(this.defaultIcons, this.iconUploadsAsIconUploadLookups()); @@ -644,7 +638,7 @@ export class FaIconChooser { id="search" class="rounded" value={this.query} - onKeyUp={this.onKeyUp.bind(this)} + onInput={this.onSearchInputChange.bind(this)} placeholder={this.searchInputPlaceholder || slotDefaults["search-field-placeholder"]} > From 48adf528ec088c504c63d8018aa7e5521cf3ff96 Mon Sep 17 00:00:00 2001 From: Mike Wilkerson <11575183+mlwilkerson@users.noreply.github.com> Date: Wed, 5 Jun 2024 13:54:04 -0700 Subject: [PATCH 26/34] add selected attr to style drop down necessary to ensure that it re-renders when this.selectedFamily or this.selectedState changes --- .../src/components/fa-icon-chooser/fa-icon-chooser.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx index fcf2917..08d2e9b 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.tsx @@ -666,7 +666,7 @@ export class FaIconChooser { onChange={this.selectStyle.bind(this)} > {this.getStylesForSelectedFamily().map((style: string) => ( - ))} From 55b4c70756f11a3996120f4759c9436ecef27eac Mon Sep 17 00:00:00 2001 From: Mike Wilkerson <11575183+mlwilkerson@users.noreply.github.com> Date: Wed, 5 Jun 2024 14:22:51 -0700 Subject: [PATCH 27/34] fix test --- .../fa-icon-chooser/fa-icon-chooser.spec.ts | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.spec.ts b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.spec.ts index f843d82..c08315b 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.spec.ts +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.spec.ts @@ -79,17 +79,28 @@ describe('fa-icon-chooser', () => { expect(foundFaScript).toBe(true); - const defaultIcons = buildDefaultIconsSearchResult([ - {family: "classic", style: "solid"}, - {family: "classic", style: "regular"}, - {family: "classic", style: "brands"} - ]) + const defaultIcons = buildDefaultIconsSearchResult({ + classic: { + solid: { + prefix: 'fas' + }, + regular: { + prefix: 'far' + }, + brands: { + prefix: 'fab' + } + } + }) // The initial default icons should have be shown get(defaultIcons, 'data.search', []) .filter(i => i.familyStylesByLicense.free.length > 0) - .forEach(({ id }) => { - expect(page.root.shadowRoot.innerHTML).toEqual(expect.stringMatching(new RegExp(` { + const isNonBrandIcon = familyStylesByLicense.free.some(({ family, style}) => 'brands' !== family && 'brands' !== style) + if ( isNonBrandIcon ) { + expect(page.root.shadowRoot.innerHTML).toEqual(expect.stringMatching(new RegExp(` Date: Wed, 5 Jun 2024 14:23:23 -0700 Subject: [PATCH 28/34] auto-formatting --- .../fa-icon-chooser/fa-icon-chooser.css | 2 +- .../fa-icon-chooser/fa-icon-chooser.spec.ts | 16 +- .../fa-icon-chooser/fa-icon-chooser.tsx | 383 +++++++----------- .../src/components/fa-icon-chooser/readme.md | 23 +- .../src/components/fa-icon/fa-icon.tsx | 2 +- .../src/components/fa-icon/readme.md | 9 +- packages/fa-icon-chooser/src/utils/utils.ts | 67 ++- 7 files changed, 191 insertions(+), 311 deletions(-) diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.css b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.css index 0b1f366..abe5a27 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.css +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.css @@ -10,7 +10,7 @@ --icon-listing-roomy-gap-y: var(--spacing-md); /* 16px */ --icon-listing-roomy-size: calc(var(--spacing-base) * 8); /* 128px */ --input-border-color: var(--fa-navy); - --input-border-width: .15rem; + --input-border-width: 0.15rem; } :host { diff --git a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.spec.ts b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.spec.ts index c08315b..afaea0b 100644 --- a/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.spec.ts +++ b/packages/fa-icon-chooser/src/components/fa-icon-chooser/fa-icon-chooser.spec.ts @@ -82,23 +82,23 @@ describe('fa-icon-chooser', () => { const defaultIcons = buildDefaultIconsSearchResult({ classic: { solid: { - prefix: 'fas' + prefix: 'fas', }, regular: { - prefix: 'far' + prefix: 'far', }, brands: { - prefix: 'fab' - } - } - }) + prefix: 'fab', + }, + }, + }); // The initial default icons should have be shown get(defaultIcons, 'data.search', []) .filter(i => i.familyStylesByLicense.free.length > 0) .forEach(({ id, familyStylesByLicense }) => { - const isNonBrandIcon = familyStylesByLicense.free.some(({ family, style}) => 'brands' !== family && 'brands' !== style) - if ( isNonBrandIcon ) { + const isNonBrandIcon = familyStylesByLicense.free.some(({ family, style }) => 'brands' !== family && 'brands' !== style); + if (isNonBrandIcon) { expect(page.root.shadowRoot.innerHTML).toEqual(expect.stringMatching(new RegExp(` Promise; +export type QueryHandler = (document: string, variables?: object) => Promise; type KitMetadata = { version: string; @@ -57,8 +46,8 @@ type KitMetadata = { * @slot get-fontawesome-pro - message about getting Font Awesome Pro with link to fontawesome.com */ @Component({ - tag: "fa-icon-chooser", - styleUrl: "fa-icon-chooser.css", + tag: 'fa-icon-chooser', + styleUrl: 'fa-icon-chooser.css', shadow: true, }) export class FaIconChooser { @@ -120,7 +109,7 @@ export class FaIconChooser { * the result of the user's interaction. */ @Event({ - eventName: "finish", + eventName: 'finish', composed: true, cancelable: true, bubbles: true, @@ -128,7 +117,7 @@ export class FaIconChooser { finish: EventEmitter; @State() - query: string = ""; + query: string = ''; @State() isQuerying: boolean = false; @@ -156,13 +145,13 @@ export class FaIconChooser { familyStyles: object = { classic: { solid: { - prefix: "fas", + prefix: 'fas', }, regular: { - prefix: "far", + prefix: 'far', }, brands: { - prefix: "fab", + prefix: 'fab', }, }, }; @@ -172,10 +161,10 @@ export class FaIconChooser { prefixToFamilyStyle: object = {}; @State() - selectedFamily: string = "classic"; + selectedFamily: string = 'classic'; @State() - selectedStyle: string = "solid"; + selectedStyle: string = 'solid'; svgApi?: any; @@ -201,7 +190,7 @@ export class FaIconChooser { selectFamily(e: any): void { const fam = e.target.value; - if ("string" === typeof fam && "object" === typeof this.familyStyles[fam]) { + if ('string' === typeof fam && 'object' === typeof this.familyStyles[fam]) { this.selectedFamily = fam; const styles = this.getStylesForSelectedFamily(); this.selectedStyle = styles[0]; @@ -210,30 +199,21 @@ export class FaIconChooser { selectStyle(e: any): void { const style = e.target.value; - if ( - "string" === typeof style && "string" === typeof this.selectedFamily && - "object" === typeof this.familyStyles[this.selectedFamily] - ) { + if ('string' === typeof style && 'string' === typeof this.selectedFamily && 'object' === typeof this.familyStyles[this.selectedFamily]) { this.selectedStyle = style; } } getPrefixForFamilyStyle(family: string, style: string): string | undefined { - return get(this.familyStyles, [family, style, "prefix"]); + return get(this.familyStyles, [family, style, 'prefix']); } getSelectedPrefix(): string | undefined { - return this.getPrefixForFamilyStyle( - this.selectedFamily, - this.selectedStyle, - ); + return this.getPrefixForFamilyStyle(this.selectedFamily, this.selectedStyle); } getStylesForSelectedFamily(): string[] { - if ( - "string" === typeof this.selectedFamily && - "object" === typeof this.familyStyles[this.selectedFamily] - ) { + if ('string' === typeof this.selectedFamily && 'object' === typeof this.familyStyles[this.selectedFamily]) { return Object.keys(this.familyStyles[this.selectedFamily]); } else { return []; @@ -253,18 +233,18 @@ export class FaIconChooser { } prefixToFamilyStylePathSegment(prefix: string): string | undefined { - const family = get(this.prefixToFamilyStyle, [prefix, "family"]); - const style = get(this.prefixToFamilyStyle, [prefix, "style"]); + const family = get(this.prefixToFamilyStyle, [prefix, 'family']); + const style = get(this.prefixToFamilyStyle, [prefix, 'style']); if (!family || !style) { return; } - if ("duotone" === family && "solid" === style) { - return "duotone"; + if ('duotone' === family && 'solid' === style) { + return 'duotone'; } - return "classic" === family ? style : `${family}-${style}`; + return 'classic' === family ? style : `${family}-${style}`; } async loadKitMetadata() { @@ -300,31 +280,24 @@ export class FaIconChooser { { token: this.kitToken }, ); - if (get(response, "errors")) { - console.error( - "Font Awesome Icon Chooser GraphQL query errors", - response.errors, - ); + if (get(response, 'errors')) { + console.error('Font Awesome Icon Chooser GraphQL query errors', response.errors); throw new Error(); } - const kit = get(response, "data.me.kit"); + const kit = get(response, 'data.me.kit'); this.kitMetadata = kit; - this.updateFamilyStyles(get(kit, "release.familyStyles", [])); + this.updateFamilyStyles(get(kit, 'release.familyStyles', [])); const kitFamilyStyles = []; - const iconUploads = get(response, "data.me.kit.iconUploads", []); + const iconUploads = get(response, 'data.me.kit.iconUploads', []); - if (find(iconUploads, (i) => i.pathData.length === 1)) { - kitFamilyStyles.push( - { family: "kit", style: "custom", prefix: "fak" }, - ); + if (find(iconUploads, i => i.pathData.length === 1)) { + kitFamilyStyles.push({ family: 'kit', style: 'custom', prefix: 'fak' }); } - if (find(iconUploads, (i) => i.pathData.length > 1)) { - kitFamilyStyles.push( - { family: "kit-duotone", style: "custom", prefix: "fakd" }, - ); + if (find(iconUploads, i => i.pathData.length > 1)) { + kitFamilyStyles.push({ family: 'kit-duotone', style: 'custom', prefix: 'fakd' }); } if (kitFamilyStyles.length > 0) { @@ -334,18 +307,18 @@ export class FaIconChooser { updateFamilyStyles(familyStyles: Array) { for (const fs of familyStyles) { - set(this.familyStyles, [fs.family, fs.style, "prefix"], fs.prefix); + set(this.familyStyles, [fs.family, fs.style, 'prefix'], fs.prefix); } this.buildFamilyStyleReverseLookup(); } resolvedVersion() { - return get(this, "kitMetadata.release.version") || this.version; + return get(this, 'kitMetadata.release.version') || this.version; } pro(): boolean { - return get(this, "kitMetadata.licenseSelected") === "pro"; + return get(this, 'kitMetadata.licenseSelected') === 'pro'; } async preload() { @@ -360,9 +333,7 @@ export class FaIconChooser { // a default. setupSlots() { for (const slotName in slotDefaults) { - const slotContentElement = this.host.querySelector( - `[slot="${slotName}"]`, - ); + const slotContentElement = this.host.querySelector(`[slot="${slotName}"]`); if (!slotContentElement) { this.activeSlotDefaults[slotName] = slotDefaults[slotName]; } @@ -370,24 +341,19 @@ export class FaIconChooser { } slot(name: string) { - return (this.activeSlotDefaults && this.activeSlotDefaults[name]) || ( - - ); + return (this.activeSlotDefaults && this.activeSlotDefaults[name]) || ; } componentWillLoad() { this.buildFamilyStyleReverseLookup(); if (!this.kitToken && !isValidSemver(this.version)) { - console.error( - `${CONSOLE_MESSAGE_PREFIX}: either a kit-token or valid semantic version is required.`, - this, - ); + console.error(`${CONSOLE_MESSAGE_PREFIX}: either a kit-token or valid semantic version is required.`, this); this.fatalError = true; return; } - this.query = ""; + this.query = ''; this.isInitialLoading = true; @@ -397,16 +363,13 @@ export class FaIconChooser { .then(() => { const pro = this.pro(); - const baseUrl = this.kitToken - ? kitAssetsBaseUrl(pro) - : freeCdnBaseUrl(); + const baseUrl = this.kitToken ? kitAssetsBaseUrl(pro) : freeCdnBaseUrl(); if (pro) { - this.svgFetchBaseUrl = - `${baseUrl}/releases/v${this.resolvedVersion()}/svgs`; + this.svgFetchBaseUrl = `${baseUrl}/releases/v${this.resolvedVersion()}/svgs`; } - const svgApi = get(window, "FontAwesome"); + const svgApi = get(window, 'FontAwesome'); if (svgApi) { // If FA SVG/JS is already present in the outer DOM, just use it. @@ -415,23 +378,17 @@ export class FaIconChooser { // Otherwise, we'll add it to the outer DOM, but disable it from doing // anything automated that would have global affect--other than assigning // itself to the global window.FontAwesome. - return createFontAwesomeScriptElement( - this.getUrlText, - pro, - this.resolvedVersion(), - baseUrl, - this.kitToken, - ).then((scriptElement) => { + return createFontAwesomeScriptElement(this.getUrlText, pro, this.resolvedVersion(), baseUrl, this.kitToken).then(scriptElement => { document.head.appendChild(scriptElement); - return get(window, "FontAwesome"); + return get(window, 'FontAwesome'); }); } }) - .then((svgApi) => { + .then(svgApi => { this.svgApi = svgApi; - const dom = get(window, "FontAwesome.dom"); - const style = document.createElement("STYLE"); - style.setAttribute("type", "text/css"); + const dom = get(window, 'FontAwesome.dom'); + const style = document.createElement('STYLE'); + style.setAttribute('type', 'text/css'); const css = document.createTextNode(dom.css()); style.appendChild(css); this.host.shadowRoot.appendChild(style); @@ -440,7 +397,7 @@ export class FaIconChooser { this.setIcons(this.defaultIcons, this.iconUploadsAsIconUploadLookups()); this.commonFaIconProps = { - svgApi: get(window, "FontAwesome"), + svgApi: get(window, 'FontAwesome'), pro: this.pro(), svgFetchBaseUrl: this.svgFetchBaseUrl, kitToken: this.kitToken, @@ -449,7 +406,7 @@ export class FaIconChooser { this.isInitialLoading = false; }) - .catch((e) => { + .catch(e => { console.error(e); this.isInitialLoading = false; this.fatalError = true; @@ -482,19 +439,14 @@ export class FaIconChooser { { version: this.resolvedVersion(), query }, ); - const filteredIconUploads = this.iconUploadsAsIconUploadLookups().filter( - ({ iconName }) => { - return iconName.indexOf(query) > -1; - }, - ); + const filteredIconUploads = this.iconUploadsAsIconUploadLookups().filter(({ iconName }) => { + return iconName.indexOf(query) > -1; + }); let iconSearchResults = response; - if (!Array.isArray(get(iconSearchResults, "data.search"))) { - console.warn( - `${CONSOLE_MESSAGE_PREFIX}: search results may be inaccurate since 'handleQuery' returned an unexpected value:`, - response, - ); + if (!Array.isArray(get(iconSearchResults, 'data.search'))) { + console.warn(`${CONSOLE_MESSAGE_PREFIX}: search results may be inaccurate since 'handleQuery' returned an unexpected value:`, response); iconSearchResults = { data: { search: [] } }; } @@ -505,39 +457,32 @@ export class FaIconChooser { } iconUploadsAsIconUploadLookups(): Array { - return get(this, "kitMetadata.iconUploads", []).map((i) => { - const [prefix, pathData] = i.pathData.length > 1 - ? ["fakd", i.pathData] - : ["fak", i.pathData[0]]; + return get(this, 'kitMetadata.iconUploads', []).map(i => { + const [prefix, pathData] = i.pathData.length > 1 ? ['fakd', i.pathData] : ['fak', i.pathData[0]]; return { prefix, iconName: i.name, iconUpload: { ...i, pathData } }; }); } setIcons(searchResultIcons: any, iconUploads: Array) { - this.icons = (get(searchResultIcons, "data.search") || []).reduce( - (acc: Array, result: any) => { - const { id, familyStylesByLicense } = result; - - const familyStyles = this.pro() - ? familyStylesByLicense.pro - : familyStylesByLicense.free; - - familyStyles.map((fs) => { - const prefix = this.getPrefixForFamilyStyle(fs.family, fs.style); - acc.push({ - iconName: id, - prefix, - }); + this.icons = (get(searchResultIcons, 'data.search') || []).reduce((acc: Array, result: any) => { + const { id, familyStylesByLicense } = result; + + const familyStyles = this.pro() ? familyStylesByLicense.pro : familyStylesByLicense.free; + + familyStyles.map(fs => { + const prefix = this.getPrefixForFamilyStyle(fs.family, fs.style); + acc.push({ + iconName: id, + prefix, }); + }); - return acc; - }, - iconUploads, - ); + return acc; + }, iconUploads); } - updateQueryResultsWithDebounce = debounce((query) => { - this.updateQueryResults(query).catch((e) => { + updateQueryResultsWithDebounce = debounce(query => { + this.updateQueryResults(query).catch(e => { console.error(e); this.fatalError = true; }); @@ -555,7 +500,7 @@ export class FaIconChooser { isV6() { const version = this.resolvedVersion(); - return version && version[0] === "6"; + return version && version[0] === '6'; } mayHaveIconUploads() { @@ -563,7 +508,7 @@ export class FaIconChooser { } hasIconUploads() { - return size(get(this, "kitMetadata.iconUploads")); + return size(get(this, 'kitMetadata.iconUploads')); } onSearchInputChange(e: any): void { @@ -582,9 +527,9 @@ export class FaIconChooser { labelForFamilyOrStyle(labelOrFamily: string): string { return labelOrFamily - .split("-") - .map((term) => capitalize(term)) - .join(" "); + .split('-') + .map(term => capitalize(term)) + .join(' '); } render() { @@ -592,8 +537,8 @@ export class FaIconChooser { return (

-

{this.slot("fatal-error-heading")}

-

{this.slot("fatal-error-detail")}

+

{this.slot('fatal-error-heading')}

+

{this.slot('fatal-error-detail')}

); @@ -612,26 +557,18 @@ export class FaIconChooser { return (
-