@internetarchive/collection-browser 2.7.2-alpha.2 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/src/collection-browser.d.ts +2 -0
  2. package/dist/src/collection-browser.js +59 -11
  3. package/dist/src/collection-browser.js.map +1 -1
  4. package/dist/src/collection-facets/smart-facets/dedupe.d.ts +10 -0
  5. package/dist/src/collection-facets/smart-facets/dedupe.js +34 -0
  6. package/dist/src/collection-facets/smart-facets/dedupe.js.map +1 -0
  7. package/dist/src/collection-facets/smart-facets/heuristics/browser-language-heuristic.d.ts +5 -0
  8. package/dist/src/collection-facets/smart-facets/heuristics/browser-language-heuristic.js +24 -0
  9. package/dist/src/collection-facets/smart-facets/heuristics/browser-language-heuristic.js.map +1 -0
  10. package/dist/src/collection-facets/smart-facets/heuristics/wikidata-heuristic.js +40 -2
  11. package/dist/src/collection-facets/smart-facets/heuristics/wikidata-heuristic.js.map +1 -1
  12. package/dist/src/collection-facets/smart-facets/models.d.ts +2 -0
  13. package/dist/src/collection-facets/smart-facets/models.js.map +1 -1
  14. package/dist/src/collection-facets/smart-facets/smart-facet-bar.d.ts +3 -0
  15. package/dist/src/collection-facets/smart-facets/smart-facet-bar.js +82 -40
  16. package/dist/src/collection-facets/smart-facets/smart-facet-bar.js.map +1 -1
  17. package/dist/src/collection-facets/smart-facets/smart-facet-button.d.ts +1 -0
  18. package/dist/src/collection-facets/smart-facets/smart-facet-button.js +10 -1
  19. package/dist/src/collection-facets/smart-facets/smart-facet-button.js.map +1 -1
  20. package/dist/src/collection-facets/smart-facets/smart-facet-dropdown.js +4 -2
  21. package/dist/src/collection-facets/smart-facets/smart-facet-dropdown.js.map +1 -1
  22. package/dist/src/collection-facets/smart-facets/smart-facet-equals.d.ts +1 -1
  23. package/dist/src/collection-facets/smart-facets/smart-facet-equals.js +3 -5
  24. package/dist/src/collection-facets/smart-facets/smart-facet-equals.js.map +1 -1
  25. package/dist/src/collection-facets/smart-facets/smart-facet-heuristics.d.ts +1 -9
  26. package/dist/src/collection-facets/smart-facets/smart-facet-heuristics.js +9 -20
  27. package/dist/src/collection-facets/smart-facets/smart-facet-heuristics.js.map +1 -1
  28. package/package.json +4 -4
  29. package/src/collection-browser.ts +60 -14
  30. package/src/collection-facets/smart-facets/dedupe.ts +43 -0
  31. package/src/collection-facets/smart-facets/heuristics/browser-language-heuristic.ts +27 -0
  32. package/src/collection-facets/smart-facets/heuristics/wikidata-heuristic.ts +40 -2
  33. package/src/collection-facets/smart-facets/models.ts +2 -0
  34. package/src/collection-facets/smart-facets/smart-facet-bar.ts +97 -48
  35. package/src/collection-facets/smart-facets/smart-facet-button.ts +11 -2
  36. package/src/collection-facets/smart-facets/smart-facet-dropdown.ts +20 -12
  37. package/src/collection-facets/smart-facets/smart-facet-equals.ts +8 -8
  38. package/src/collection-facets/smart-facets/smart-facet-heuristics.ts +12 -22
@@ -1 +1 @@
1
- {"version":3,"file":"smart-facet-dropdown.js","sourceRoot":"","sources":["../../../../src/collection-facets/smart-facets/smart-facet-dropdown.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, CSSResultGroup, nothing } from 'lit';\nimport { customElement, property, query } from 'lit/decorators.js';\nimport type { IaDropdown, optionInterface } from '@internetarchive/ia-dropdown';\nimport type { FacetRef, SmartFacet, SmartFacetEvent } from './models';\n\n@customElement('smart-facet-dropdown')\nexport class SmartFacetDropdown extends LitElement {\n @property({ type: Array }) facetInfo?: SmartFacet[];\n\n @property({ type: String }) labelPrefix?: string;\n\n @property({ type: Object }) activeFacetRef?: FacetRef;\n\n @query('ia-dropdown') dropdown?: IaDropdown;\n\n //\n // COMPONENT LIFECYCLE METHODS\n //\n\n render() {\n if (!this.facetInfo || !this.activeFacetRef) return nothing;\n if (this.facetInfo.length === 0) return nothing;\n\n const displayText = this.activeFacetRef.displayText ?? this.activeFacetRef.bucketKey;\n if (!displayText) return nothing;\n\n return html`\n <div class=\"dropdown-container\">\n <ia-dropdown\n class=\"dropdown\"\n displayCaret\n openViaButton\n closeOnSelect\n includeSelectedOption\n .options=${this.dropdownOptions}\n .selectedOption=${this.activeDropdownOption}\n @optionSelected=${this.optionSelected}\n >\n <span class=\"dropdown-label\" slot=\"dropdown-label\"\n >${this.labelPrefix ?? nothing} ${displayText}</span\n >\n </ia-dropdown>\n </div>\n `;\n }\n\n //\n // OTHER METHODS\n //\n\n private get dropdownOptions(): optionInterface[] {\n return (\n this.facetInfo?.map(smartFacet => {\n const firstFacet = smartFacet.facets[0];\n return {\n id: firstFacet.bucketKey,\n label: smartFacet.label ?? firstFacet.displayText ?? firstFacet.bucketKey,\n };\n }) ?? []\n );\n }\n\n private get activeDropdownOption(): optionInterface | undefined {\n if (!this.activeFacetRef) return undefined;\n return this.dropdownOptions.find(opt => opt.id === this.activeFacetRef?.bucketKey);\n }\n\n private optionSelected(e: CustomEvent<{ option: optionInterface }>): void {\n if (!this.facetInfo || !this.activeFacetRef) return;\n\n let selectedSmartFacet;\n for (const smartFacet of this.facetInfo) {\n const selectedRef = smartFacet.facets.find(b => b.bucketKey === e.detail.option.id);\n if (selectedRef) {\n this.activeFacetRef = selectedRef;\n selectedSmartFacet = smartFacet;\n }\n }\n\n if (!selectedSmartFacet) return;\n\n this.dispatchEvent(\n new CustomEvent<SmartFacetEvent>('facetClick', {\n detail: {\n smartFacet: selectedSmartFacet,\n details: [{\n facetType: this.activeFacetRef.facetType,\n bucket: {\n key: this.activeFacetRef.bucketKey,\n count: 0,\n state: 'selected',\n },\n negative: false,\n }],\n },\n })\n );\n }\n\n //\n // STYLES\n //\n\n static get styles(): CSSResultGroup {\n return css`\n .dropdown-container {\n padding: 5px 8px;\n border-radius: 5px;\n background: #194880;\n color: white;\n font-size: 1.6rem;\n font-family: inherit;\n box-shadow: 1px 1px rgba(0, 0, 0, 0.4);\n }\n\n .dropdown-label {\n font-size: 1.6rem;\n font-family: inherit;\n }\n\n .dropdown {\n --dropdownBorderWidth: 5px;\n --dropdownBorderColor: transparent;\n --caretWidth: 14px;\n --caretHeight: 14px;\n }\n `;\n }\n}\n"]}
1
+ {"version":3,"file":"smart-facet-dropdown.js","sourceRoot":"","sources":["../../../../src/collection-facets/smart-facets/smart-facet-dropdown.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, html, LitElement, CSSResultGroup, nothing } from 'lit';\nimport { customElement, property, query } from 'lit/decorators.js';\nimport type { IaDropdown, optionInterface } from '@internetarchive/ia-dropdown';\nimport type { FacetRef, SmartFacet, SmartFacetEvent } from './models';\n\n@customElement('smart-facet-dropdown')\nexport class SmartFacetDropdown extends LitElement {\n @property({ type: Array }) facetInfo?: SmartFacet[];\n\n @property({ type: String }) labelPrefix?: string;\n\n @property({ type: Object }) activeFacetRef?: FacetRef;\n\n @query('ia-dropdown') dropdown?: IaDropdown;\n\n //\n // COMPONENT LIFECYCLE METHODS\n //\n\n render() {\n if (!this.facetInfo || !this.activeFacetRef) return nothing;\n if (this.facetInfo.length === 0) return nothing;\n\n const displayText =\n this.activeFacetRef.displayText ?? this.activeFacetRef.bucketKey;\n if (!displayText) return nothing;\n\n return html`\n <div class=\"dropdown-container\">\n <ia-dropdown\n class=\"dropdown\"\n displayCaret\n openViaButton\n closeOnSelect\n includeSelectedOption\n .options=${this.dropdownOptions}\n .selectedOption=${this.activeDropdownOption}\n @optionSelected=${this.optionSelected}\n >\n <span class=\"dropdown-label\" slot=\"dropdown-label\"\n >${this.labelPrefix ?? nothing} ${displayText}</span\n >\n </ia-dropdown>\n </div>\n `;\n }\n\n //\n // OTHER METHODS\n //\n\n private get dropdownOptions(): optionInterface[] {\n return (\n this.facetInfo?.map(smartFacet => {\n const firstFacet = smartFacet.facets[0];\n return {\n id: firstFacet.bucketKey,\n label:\n smartFacet.label ?? firstFacet.displayText ?? firstFacet.bucketKey,\n };\n }) ?? []\n );\n }\n\n private get activeDropdownOption(): optionInterface | undefined {\n if (!this.activeFacetRef) return undefined;\n return this.dropdownOptions.find(\n opt => opt.id === this.activeFacetRef?.bucketKey\n );\n }\n\n private optionSelected(e: CustomEvent<{ option: optionInterface }>): void {\n if (!this.facetInfo || !this.activeFacetRef) return;\n\n let selectedSmartFacet;\n for (const smartFacet of this.facetInfo) {\n const selectedRef = smartFacet.facets.find(\n b => b.bucketKey === e.detail.option.id\n );\n if (selectedRef) {\n this.activeFacetRef = selectedRef;\n selectedSmartFacet = smartFacet;\n }\n }\n\n if (!selectedSmartFacet) return;\n\n this.dispatchEvent(\n new CustomEvent<SmartFacetEvent>('facetClick', {\n detail: {\n smartFacet: selectedSmartFacet,\n details: [\n {\n facetType: this.activeFacetRef.facetType,\n bucket: {\n key: this.activeFacetRef.bucketKey,\n count: 0,\n state: 'selected',\n },\n negative: false,\n },\n ],\n },\n })\n );\n }\n\n //\n // STYLES\n //\n\n static get styles(): CSSResultGroup {\n return css`\n .dropdown-container {\n padding: 5px 8px;\n border-radius: 5px;\n background: #194880;\n color: white;\n font-size: 1.6rem;\n font-family: inherit;\n box-shadow: 1px 1px rgba(0, 0, 0, 0.4);\n }\n\n .dropdown-label {\n font-size: 1.6rem;\n font-family: inherit;\n }\n\n .dropdown {\n --dropdownBorderWidth: 5px;\n --dropdownBorderColor: transparent;\n --caretWidth: 14px;\n --caretHeight: 14px;\n }\n `;\n }\n}\n"]}
@@ -1,2 +1,2 @@
1
- import type { SmartFacet } from "./models";
1
+ import type { SmartFacet } from './models';
2
2
  export declare function smartFacetEquals(sf1: SmartFacet, sf2: SmartFacet): boolean;
@@ -3,13 +3,11 @@ function facetRefEquals(ref1, ref2) {
3
3
  return ref2 !== undefined;
4
4
  if (ref2 === undefined)
5
5
  return ref1 !== undefined;
6
- return ref1.facetType === ref2.facetType &&
7
- ref1.bucketKey === ref2.bucketKey &&
8
- ref1.displayText === ref2.displayText;
6
+ return ref1.facetType === ref2.facetType && ref1.bucketKey === ref2.bucketKey;
9
7
  }
10
8
  export function smartFacetEquals(sf1, sf2) {
11
- return sf1.label === sf2.label &&
9
+ return (sf1.label === sf2.label &&
12
10
  sf1.facets.length === sf2.facets.length &&
13
- sf1.facets.every((sf, i) => facetRefEquals(sf, sf2.facets[i]));
11
+ sf1.facets.every((sf, i) => facetRefEquals(sf, sf2.facets[i])));
14
12
  }
15
13
  //# sourceMappingURL=smart-facet-equals.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"smart-facet-equals.js","sourceRoot":"","sources":["../../../../src/collection-facets/smart-facets/smart-facet-equals.ts"],"names":[],"mappings":"AAEA,SAAS,cAAc,CAAC,IAAe,EAAE,IAAe;IACtD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,KAAK,SAAS,CAAC;IAClD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,KAAK,SAAS,CAAC;IAElD,OAAO,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;QACtC,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS;QACjC,IAAI,CAAC,WAAW,KAAK,IAAI,CAAC,WAAW,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAe,EAAE,GAAe;IAC/D,OAAO,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK;QAC5B,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM;QACvC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import type { FacetRef, SmartFacet } from \"./models\";\n\nfunction facetRefEquals(ref1?: FacetRef, ref2?: FacetRef): boolean {\n if (ref1 === undefined) return ref2 !== undefined;\n if (ref2 === undefined) return ref1 !== undefined;\n \n return ref1.facetType === ref2.facetType &&\n ref1.bucketKey === ref2.bucketKey &&\n ref1.displayText === ref2.displayText;\n}\n\nexport function smartFacetEquals(sf1: SmartFacet, sf2: SmartFacet) {\n return sf1.label === sf2.label &&\n sf1.facets.length === sf2.facets.length &&\n sf1.facets.every((sf, i) => facetRefEquals(sf, sf2.facets[i]));\n}"]}
1
+ {"version":3,"file":"smart-facet-equals.js","sourceRoot":"","sources":["../../../../src/collection-facets/smart-facets/smart-facet-equals.ts"],"names":[],"mappings":"AAEA,SAAS,cAAc,CAAC,IAAe,EAAE,IAAe;IACtD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,KAAK,SAAS,CAAC;IAClD,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,KAAK,SAAS,CAAC;IAElD,OAAO,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,CAAC;AAChF,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAe,EAAE,GAAe;IAC/D,OAAO,CACL,GAAG,CAAC,KAAK,KAAK,GAAG,CAAC,KAAK;QACvB,GAAG,CAAC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,MAAM;QACvC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAC/D,CAAC;AACJ,CAAC","sourcesContent":["import type { FacetRef, SmartFacet } from './models';\n\nfunction facetRefEquals(ref1?: FacetRef, ref2?: FacetRef): boolean {\n if (ref1 === undefined) return ref2 !== undefined;\n if (ref2 === undefined) return ref1 !== undefined;\n\n return ref1.facetType === ref2.facetType && ref1.bucketKey === ref2.bucketKey;\n}\n\nexport function smartFacetEquals(sf1: SmartFacet, sf2: SmartFacet) {\n return (\n sf1.label === sf2.label &&\n sf1.facets.length === sf2.facets.length &&\n sf1.facets.every((sf, i) => facetRefEquals(sf, sf2.facets[i]))\n );\n}\n"]}
@@ -1,13 +1,5 @@
1
1
  import type { SmartFacet, SmartQueryHeuristic } from './models';
2
2
  export declare class SmartQueryHeuristicGroup implements SmartQueryHeuristic {
3
+ private static readonly HEURISTICS;
3
4
  getRecommendedFacets(query: string): Promise<SmartFacet[]>;
4
- /**
5
- * Removes any duplicated smart facets from the given array.
6
- * Smart facets are equal if they have the same `label` and same
7
- * set of facet refs. Only the first occurrence of a given smart
8
- * facet is kept.
9
- * @param facets The array of smart facets to deduplicate
10
- * @returns A new array containing the deduplicated set of facets
11
- */
12
- private dedupe;
13
5
  }
@@ -1,27 +1,16 @@
1
+ import { dedupe } from './dedupe';
2
+ import { BrowserLanguageHeuristic } from './heuristics/browser-language-heuristic';
1
3
  import { QueryKeywordsHeuristic } from './heuristics/query-keywords-heuristic';
2
4
  import { WikidataHeuristic } from './heuristics/wikidata-heuristic';
3
- import { smartFacetEquals } from './smart-facet-equals';
4
5
  export class SmartQueryHeuristicGroup {
5
6
  async getRecommendedFacets(query) {
6
- return this.dedupe([
7
- ...(await new QueryKeywordsHeuristic().getRecommendedFacets(query)),
8
- ...(await new WikidataHeuristic().getRecommendedFacets(query)),
9
- ]);
10
- }
11
- /**
12
- * Removes any duplicated smart facets from the given array.
13
- * Smart facets are equal if they have the same `label` and same
14
- * set of facet refs. Only the first occurrence of a given smart
15
- * facet is kept.
16
- * @param facets The array of smart facets to deduplicate
17
- * @returns A new array containing the deduplicated set of facets
18
- */
19
- dedupe(facets) {
20
- let result = [...facets];
21
- for (const curFacet of facets) {
22
- result = result.filter(sf => curFacet === sf || !smartFacetEquals(curFacet, sf));
23
- }
24
- return result;
7
+ const promises = SmartQueryHeuristicGroup.HEURISTICS.map(HeuristicCtor => new HeuristicCtor().getRecommendedFacets(query));
8
+ return dedupe((await Promise.all(promises)).flat());
25
9
  }
26
10
  }
11
+ SmartQueryHeuristicGroup.HEURISTICS = [
12
+ QueryKeywordsHeuristic,
13
+ WikidataHeuristic,
14
+ BrowserLanguageHeuristic,
15
+ ];
27
16
  //# sourceMappingURL=smart-facet-heuristics.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"smart-facet-heuristics.js","sourceRoot":"","sources":["../../../../src/collection-facets/smart-facets/smart-facet-heuristics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAEpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,MAAM,OAAO,wBAAwB;IACnC,KAAK,CAAC,oBAAoB,CAAC,KAAa;QACtC,OAAO,IAAI,CAAC,MAAM,CAAC;YACjB,GAAG,CAAC,MAAM,IAAI,sBAAsB,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;YACnE,GAAG,CAAC,MAAM,IAAI,iBAAiB,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;SAC/D,CAAC,CAAC;IACL,CAAC;IAED;;;;;;;OAOG;IACK,MAAM,CAAC,MAAoB;QACjC,IAAI,MAAM,GAAiB,CAAC,GAAG,MAAM,CAAC,CAAC;QACvC,KAAK,MAAM,QAAQ,IAAI,MAAM,EAAE;YAC7B,MAAM,GAAG,MAAM,CAAC,MAAM,CACpB,EAAE,CAAC,EAAE,CAAC,QAAQ,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,EAAE,CAAC,CACzD,CAAC;SACH;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF","sourcesContent":["import { QueryKeywordsHeuristic } from './heuristics/query-keywords-heuristic';\nimport { WikidataHeuristic } from './heuristics/wikidata-heuristic';\nimport type { SmartFacet, SmartQueryHeuristic } from './models';\nimport { smartFacetEquals } from './smart-facet-equals';\n\nexport class SmartQueryHeuristicGroup implements SmartQueryHeuristic {\n async getRecommendedFacets(query: string): Promise<SmartFacet[]> {\n return this.dedupe([\n ...(await new QueryKeywordsHeuristic().getRecommendedFacets(query)),\n ...(await new WikidataHeuristic().getRecommendedFacets(query)),\n ]);\n }\n\n /**\n * Removes any duplicated smart facets from the given array.\n * Smart facets are equal if they have the same `label` and same\n * set of facet refs. Only the first occurrence of a given smart\n * facet is kept.\n * @param facets The array of smart facets to deduplicate\n * @returns A new array containing the deduplicated set of facets\n */\n private dedupe(facets: SmartFacet[]): SmartFacet[] {\n let result: SmartFacet[] = [...facets];\n for (const curFacet of facets) {\n result = result.filter(\n sf => curFacet === sf || !smartFacetEquals(curFacet, sf)\n );\n }\n return result;\n }\n}\n"]}
1
+ {"version":3,"file":"smart-facet-heuristics.js","sourceRoot":"","sources":["../../../../src/collection-facets/smart-facets/smart-facet-heuristics.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAC;AACnF,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAGpE,MAAM,OAAO,wBAAwB;IAOnC,KAAK,CAAC,oBAAoB,CAAC,KAAa;QACtC,MAAM,QAAQ,GAAG,wBAAwB,CAAC,UAAU,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CACvE,IAAI,aAAa,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAChD,CAAC;QAEF,OAAO,MAAM,CAAC,CAAC,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;;AAZuB,mCAAU,GAAG;IACnC,sBAAsB;IACtB,iBAAiB;IACjB,wBAAwB;CACzB,CAAC","sourcesContent":["import { dedupe } from './dedupe';\nimport { BrowserLanguageHeuristic } from './heuristics/browser-language-heuristic';\nimport { QueryKeywordsHeuristic } from './heuristics/query-keywords-heuristic';\nimport { WikidataHeuristic } from './heuristics/wikidata-heuristic';\nimport type { SmartFacet, SmartQueryHeuristic } from './models';\n\nexport class SmartQueryHeuristicGroup implements SmartQueryHeuristic {\n private static readonly HEURISTICS = [\n QueryKeywordsHeuristic,\n WikidataHeuristic,\n BrowserLanguageHeuristic,\n ];\n\n async getRecommendedFacets(query: string): Promise<SmartFacet[]> {\n const promises = SmartQueryHeuristicGroup.HEURISTICS.map(HeuristicCtor =>\n new HeuristicCtor().getRecommendedFacets(query)\n );\n\n return dedupe((await Promise.all(promises)).flat());\n }\n}\n"]}
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "description": "The Internet Archive Collection Browser.",
4
4
  "license": "AGPL-3.0-only",
5
5
  "author": "Internet Archive",
6
- "version": "2.7.2-alpha.2",
6
+ "version": "2.7.2",
7
7
  "main": "dist/index.js",
8
8
  "module": "dist/index.js",
9
9
  "scripts": {
@@ -31,10 +31,10 @@
31
31
  "@internetarchive/ia-dropdown": "^1.3.8",
32
32
  "@internetarchive/infinite-scroller": "1.0.1",
33
33
  "@internetarchive/modal-manager": "^0.2.8",
34
- "@internetarchive/search-service": "^1.4.0",
34
+ "@internetarchive/search-service": "^1.4.1",
35
35
  "@internetarchive/shared-resize-observer": "^0.2.0",
36
36
  "@lit/localize": "^0.11.2",
37
- "dompurify": "^2.5.7",
37
+ "dompurify": "^3.1.7",
38
38
  "eslint-plugin-lit": "^1.6.1",
39
39
  "lit": "^2.2.2",
40
40
  "typescript-cookie": "^1.0.3"
@@ -43,7 +43,7 @@
43
43
  "@internetarchive/result-type": "^0.0.1",
44
44
  "@open-wc/eslint-config": "^8.0.2",
45
45
  "@open-wc/testing": "^3.0.3",
46
- "@types/dompurify": "^2.3.3",
46
+ "@types/dompurify": "^3.0.5",
47
47
  "@typescript-eslint/eslint-plugin": "^5.3.1",
48
48
  "@typescript-eslint/parser": "^5.3.1",
49
49
  "@web/dev-server": "^0.1.28",
@@ -250,6 +250,9 @@ export class CollectionBrowser
250
250
  /** Whether to replace the default sort options with a slot for customization (default: false) */
251
251
  @property({ type: Boolean }) enableSortOptionsSlot = false;
252
252
 
253
+ /** Whether to display a smart results carousel above the full results */
254
+ @property({ type: Boolean, reflect: true }) showSmartResults = false;
255
+
253
256
  /**
254
257
  * The results per page so we can paginate.
255
258
  *
@@ -615,7 +618,11 @@ export class CollectionBrowser
615
618
  */
616
619
  private get desktopLeftColumnTemplate(): TemplateResult {
617
620
  return html`
618
- <div id="left-column" class="column" ?hidden=${!this.facetPaneVisible}>
621
+ <div
622
+ id="left-column"
623
+ class="column"
624
+ ?hidden=${this.showSmartFacetBar && !this.facetPaneVisible}
625
+ >
619
626
  ${this.facetTopViewSlot}
620
627
  <div id="facets-header-container">
621
628
  <h2 id="facets-header" class="sr-only">Filters</h2>
@@ -671,18 +678,31 @@ export class CollectionBrowser
671
678
  */
672
679
  private get rightColumnTemplate(): TemplateResult {
673
680
  return html`
674
- <div id="right-column" class="column">
675
- <div id="cb-top-view">
676
- <slot name="cb-top-slot"></slot>
677
- </div>
678
- ${this.isManageView
679
- ? this.manageBarTemplate
680
- : this.sortFilterBarTemplate}
681
- <slot name="cb-results"></slot>
682
- ${this.displayMode === `list-compact` && this.totalResults
683
- ? this.listHeaderTemplate
681
+ <div
682
+ id="right-column"
683
+ class="column ${this.showSmartResults ? 'smart-results-spacing' : ''}"
684
+ >
685
+ ${this.showSmartResults
686
+ ? html`<slot name="smart-results"></slot>`
684
687
  : nothing}
685
- ${this.suppressResultTiles ? nothing : this.infiniteScrollerTemplate}
688
+ <section id="results">
689
+ ${this.showSmartResults
690
+ ? html`<h2 class="results-section-heading">
691
+ ${msg('All results')}
692
+ </h2>`
693
+ : nothing}
694
+ <div id="cb-top-view">
695
+ <slot name="cb-top-slot"></slot>
696
+ </div>
697
+ ${this.isManageView
698
+ ? this.manageBarTemplate
699
+ : this.sortFilterBarTemplate}
700
+ <slot name="cb-results"></slot>
701
+ ${this.displayMode === `list-compact` && this.totalResults
702
+ ? this.listHeaderTemplate
703
+ : nothing}
704
+ ${this.suppressResultTiles ? nothing : this.infiniteScrollerTemplate}
705
+ </section>
686
706
  </div>
687
707
  `;
688
708
  }
@@ -2091,14 +2111,34 @@ export class CollectionBrowser
2091
2111
  min-height: 90vh;
2092
2112
  border-left: 1px solid rgb(232, 232, 232);
2093
2113
  border-right: 1px solid rgb(232, 232, 232);
2094
- padding-left: 1rem;
2095
- padding-right: 1rem;
2096
2114
  margin-top: var(--rightColumnMarginTop, 0);
2097
2115
  background: #fff;
2098
2116
  }
2099
2117
 
2118
+ #right-column.smart-results-spacing {
2119
+ padding-top: 0.5rem;
2120
+ border-right: none;
2121
+ background: transparent;
2122
+ min-width: 0;
2123
+ }
2124
+
2125
+ #results {
2126
+ background: #fff;
2127
+ padding-left: 1rem;
2128
+ padding-right: 1rem;
2129
+ }
2130
+
2131
+ #right-column.smart-results-spacing #results {
2132
+ border-radius: 10px 10px 0px 0px;
2133
+ padding-top: 0.5rem;
2134
+ margin-top: 1rem;
2135
+ }
2136
+
2100
2137
  .mobile #right-column {
2101
2138
  border-left: none;
2139
+ }
2140
+
2141
+ .mobile #results {
2102
2142
  padding: 5px 5px 0;
2103
2143
  }
2104
2144
 
@@ -2287,6 +2327,12 @@ export class CollectionBrowser
2287
2327
  max-height: 2000px;
2288
2328
  }
2289
2329
 
2330
+ .results-section-heading {
2331
+ margin: 0.5rem 0.3rem;
2332
+ font-size: 2rem;
2333
+ line-height: 25px;
2334
+ }
2335
+
2290
2336
  #results-total {
2291
2337
  display: flex;
2292
2338
  align-items: baseline;
@@ -0,0 +1,43 @@
1
+ import type { SmartFacet } from './models';
2
+ import { smartFacetEquals } from './smart-facet-equals';
3
+
4
+ /**
5
+ * Removes any duplicated smart facets from the given array.
6
+ * Smart facets are equal if they have the same `label` and same
7
+ * set of facet refs. Only the first occurrence of a given smart
8
+ * facet is kept.
9
+ * @param facets The array of smart facets to deduplicate
10
+ * @returns A new array containing the deduplicated set of facets
11
+ */
12
+ export function dedupe<T extends SmartFacet[] | SmartFacet[][]>(facets: T): T {
13
+ if (!Array.isArray(facets[0])) {
14
+ const facetsUnnested = facets as SmartFacet[];
15
+
16
+ let result: SmartFacet[] = [...facetsUnnested];
17
+ for (const curFacet of facetsUnnested) {
18
+ result = result.filter(
19
+ sf => curFacet === sf || !smartFacetEquals(curFacet, sf)
20
+ );
21
+ }
22
+
23
+ return result as T;
24
+ }
25
+
26
+ const facetsNested = facets as SmartFacet[][];
27
+
28
+ const result: SmartFacet[][] = [];
29
+ for (const curFacetArray of facetsNested) {
30
+ const subresult: SmartFacet[] = [];
31
+ for (const curFacet of curFacetArray) {
32
+ const existing = result.find(sfa =>
33
+ sfa.find(sf => smartFacetEquals(curFacet, sf))
34
+ );
35
+ if (!existing) subresult.push(curFacet);
36
+ }
37
+ if (subresult.length > 0) {
38
+ result.push(subresult);
39
+ }
40
+ }
41
+
42
+ return result as T;
43
+ }
@@ -0,0 +1,27 @@
1
+ import type { SmartQueryHeuristic, SmartFacet } from '../models';
2
+
3
+ export class BrowserLanguageHeuristic implements SmartQueryHeuristic {
4
+ async getRecommendedFacets(): Promise<SmartFacet[]> {
5
+ const browserLanguageCode = navigator.language;
6
+ const languageName =
7
+ BrowserLanguageHeuristic.getLanguageDisplayName(browserLanguageCode);
8
+ if (!languageName) return [];
9
+
10
+ return [
11
+ {
12
+ facets: [
13
+ {
14
+ facetType: 'language',
15
+ bucketKey: languageName,
16
+ },
17
+ ],
18
+ },
19
+ ];
20
+ }
21
+
22
+ private static getLanguageDisplayName(langCode: string): string | undefined {
23
+ // Strip off any script/region/variant codes for greater generality
24
+ const languageOnly = langCode.split('-')[0];
25
+ return new Intl.DisplayNames(['en'], { type: 'language' }).of(languageOnly);
26
+ }
27
+ }
@@ -15,7 +15,9 @@ import type {
15
15
  // etc.
16
16
  export class WikidataHeuristic implements SmartQueryHeuristic {
17
17
  private static readonly ENTITIES: KeywordFacetMap = {
18
- 'written work': [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],
18
+ 'written work': [
19
+ { facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] },
20
+ ],
19
21
  literature: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],
20
22
  book: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],
21
23
  novel: [{ facets: [{ facetType: 'mediatype', bucketKey: 'texts' }] }],
@@ -73,6 +75,24 @@ export class WikidataHeuristic implements SmartQueryHeuristic {
73
75
  ],
74
76
  },
75
77
  ],
78
+ 'visual artist': [
79
+ {
80
+ label: 'Images by __QUERY',
81
+ facets: [
82
+ { facetType: 'mediatype', bucketKey: 'image' },
83
+ { facetType: 'creator', bucketKey: '__QUERY' },
84
+ ],
85
+ },
86
+ ],
87
+ 'graphic artist': [
88
+ {
89
+ label: 'Images by __QUERY',
90
+ facets: [
91
+ { facetType: 'mediatype', bucketKey: 'image' },
92
+ { facetType: 'creator', bucketKey: '__QUERY' },
93
+ ],
94
+ },
95
+ ],
76
96
  singer: [
77
97
  {
78
98
  label: 'Music by __QUERY',
@@ -100,6 +120,24 @@ export class WikidataHeuristic implements SmartQueryHeuristic {
100
120
  ],
101
121
  },
102
122
  ],
123
+ composer: [
124
+ {
125
+ label: 'Music by __QUERY',
126
+ facets: [
127
+ { facetType: 'mediatype', bucketKey: 'audio' },
128
+ { facetType: 'creator', bucketKey: '__QUERY' },
129
+ ],
130
+ },
131
+ ],
132
+ pianist: [
133
+ {
134
+ label: 'Music by __QUERY',
135
+ facets: [
136
+ { facetType: 'mediatype', bucketKey: 'audio' },
137
+ { facetType: 'creator', bucketKey: '__QUERY' },
138
+ ],
139
+ },
140
+ ],
103
141
  };
104
142
 
105
143
  async getRecommendedFacets(query: string): Promise<SmartFacet[]> {
@@ -116,7 +154,7 @@ export class WikidataHeuristic implements SmartQueryHeuristic {
116
154
  for (const [keyword, facets] of Object.entries(
117
155
  WikidataHeuristic.ENTITIES
118
156
  )) {
119
- const keywordRegex = new RegExp('\\b' + keyword + '\\b');
157
+ const keywordRegex = new RegExp(`\\b${keyword}\\b`);
120
158
  if (keywordRegex.test(searchResults.search[0]?.description)) {
121
159
  const entityName = searchResults.search[0].label;
122
160
  recommendations.push(
@@ -9,11 +9,13 @@ export interface FacetRef {
9
9
  interface LabeledSmartFacet {
10
10
  label: string;
11
11
  facets: FacetRef[];
12
+ selected?: boolean;
12
13
  }
13
14
 
14
15
  interface UnlabeledSmartFacet {
15
16
  label?: string;
16
17
  facets: [FacetRef];
18
+ selected?: boolean;
17
19
  }
18
20
 
19
21
  export type SmartFacet = LabeledSmartFacet | UnlabeledSmartFacet;