@internetarchive/collection-browser 4.5.0 → 4.5.1-alpha-webdev8221.0

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 (70) hide show
  1. package/dist/index.js.map +1 -1
  2. package/dist/src/app-root.js +683 -683
  3. package/dist/src/app-root.js.map +1 -1
  4. package/dist/src/collection-browser.d.ts +0 -4
  5. package/dist/src/collection-browser.js +767 -776
  6. package/dist/src/collection-browser.js.map +1 -1
  7. package/dist/src/collection-facets/facet-row.js +143 -143
  8. package/dist/src/collection-facets/facet-row.js.map +1 -1
  9. package/dist/src/collection-facets/facets-template.js +24 -24
  10. package/dist/src/collection-facets/facets-template.js.map +1 -1
  11. package/dist/src/data-source/collection-browser-data-source-interface.d.ts +5 -0
  12. package/dist/src/data-source/collection-browser-data-source-interface.js.map +1 -1
  13. package/dist/src/data-source/collection-browser-data-source.d.ts +1 -1
  14. package/dist/src/data-source/collection-browser-data-source.js +8 -6
  15. package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
  16. package/dist/src/restoration-state-handler.js +2 -4
  17. package/dist/src/restoration-state-handler.js.map +1 -1
  18. package/dist/src/styles/tile-action-styles.js +43 -43
  19. package/dist/src/styles/tile-action-styles.js.map +1 -1
  20. package/dist/src/tiles/base-tile-component.js +11 -11
  21. package/dist/src/tiles/base-tile-component.js.map +1 -1
  22. package/dist/src/tiles/grid/item-tile.js +138 -138
  23. package/dist/src/tiles/grid/item-tile.js.map +1 -1
  24. package/dist/src/tiles/list/tile-list-compact-header.js +62 -62
  25. package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -1
  26. package/dist/src/tiles/list/tile-list-compact.js +123 -123
  27. package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
  28. package/dist/src/tiles/list/tile-list.js +310 -310
  29. package/dist/src/tiles/list/tile-list.js.map +1 -1
  30. package/dist/src/tiles/models.js.map +1 -1
  31. package/dist/src/tiles/tile-dispatcher.js +286 -286
  32. package/dist/src/tiles/tile-dispatcher.js.map +1 -1
  33. package/dist/src/tiles/tile-display-value-provider.js.map +1 -1
  34. package/dist/src/utils/date-filter-field.d.ts +6 -0
  35. package/dist/src/utils/date-filter-field.js +9 -0
  36. package/dist/src/utils/date-filter-field.js.map +1 -0
  37. package/dist/test/collection-browser.test.js +81 -0
  38. package/dist/test/collection-browser.test.js.map +1 -1
  39. package/dist/test/collection-facets/facet-row.test.js +31 -31
  40. package/dist/test/collection-facets/facet-row.test.js.map +1 -1
  41. package/dist/test/tiles/grid/item-tile.test.js +77 -77
  42. package/dist/test/tiles/grid/item-tile.test.js.map +1 -1
  43. package/dist/test/tiles/list/tile-list.test.js +134 -134
  44. package/dist/test/tiles/list/tile-list.test.js.map +1 -1
  45. package/dist/test/tiles/tile-dispatcher.test.js +92 -92
  46. package/dist/test/tiles/tile-dispatcher.test.js.map +1 -1
  47. package/index.ts +29 -29
  48. package/package.json +1 -1
  49. package/src/app-root.ts +1284 -1284
  50. package/src/collection-browser.ts +3165 -3176
  51. package/src/collection-facets/facet-row.ts +309 -309
  52. package/src/collection-facets/facets-template.ts +85 -85
  53. package/src/data-source/collection-browser-data-source-interface.ts +6 -0
  54. package/src/data-source/collection-browser-data-source.ts +16 -7
  55. package/src/restoration-state-handler.ts +5 -5
  56. package/src/styles/tile-action-styles.ts +59 -59
  57. package/src/tiles/base-tile-component.ts +124 -124
  58. package/src/tiles/grid/item-tile.ts +347 -347
  59. package/src/tiles/list/tile-list-compact-header.ts +112 -112
  60. package/src/tiles/list/tile-list-compact.ts +278 -278
  61. package/src/tiles/list/tile-list.ts +718 -718
  62. package/src/tiles/models.ts +21 -21
  63. package/src/tiles/tile-dispatcher.ts +637 -637
  64. package/src/tiles/tile-display-value-provider.ts +133 -133
  65. package/src/utils/date-filter-field.ts +11 -0
  66. package/test/collection-browser.test.ts +132 -0
  67. package/test/collection-facets/facet-row.test.ts +421 -421
  68. package/test/tiles/grid/item-tile.test.ts +520 -520
  69. package/test/tiles/list/tile-list.test.ts +576 -576
  70. package/test/tiles/tile-dispatcher.test.ts +320 -320
@@ -12,48 +12,48 @@ import { css } from 'lit';
12
12
  * - `--tileActionHoverBg` (defaults to --primaryErrorCTAFillRGB at 20% alpha)
13
13
  * - `--tileActionHoverColor` (defaults to --tileActionColor)
14
14
  */
15
- export const tileActionStyles = css `
16
- .tile-actions {
17
- flex-shrink: 0;
18
- display: flex;
19
- gap: var(--tileActionGap, 0);
20
- }
21
-
22
- .tile-action-btn {
23
- flex: 1;
24
- padding: 6px 5px;
25
- border: 2px solid
26
- var(--tileActionBorderColor, var(--primaryErrorCTAFill, #d9534f));
27
- border-radius: var(--tileActionBorderRadius, 0);
28
- /* Inherit from the surrounding tile rather than the UA default for <button> */
29
- font-family: inherit;
30
- font-size: 1.2rem;
31
- font-weight: bold;
32
- cursor: pointer;
33
- color: var(--tileActionColor, var(--primaryErrorCTAFill, #d9534f));
34
- background: var(--tileActionBg, #fff);
35
- transition:
36
- background 0.15s,
37
- color 0.15s;
38
- }
39
-
40
- /*
41
- * When buttons are flush against each other (no gap), overlap their shared
42
- * edge by 1px so adjacent borders don't double up.
43
- */
44
- .tile-action-btn + .tile-action-btn {
45
- margin-left: -1px;
46
- }
47
-
48
- .tile-action-btn:hover {
49
- background: var(
50
- --tileActionHoverBg,
51
- rgba(var(--primaryErrorCTAFillRGB, 229, 28, 38), 0.2)
52
- );
53
- color: var(
54
- --tileActionHoverColor,
55
- var(--tileActionColor, var(--primaryErrorCTAFill, #d9534f))
56
- );
57
- }
15
+ export const tileActionStyles = css `
16
+ .tile-actions {
17
+ flex-shrink: 0;
18
+ display: flex;
19
+ gap: var(--tileActionGap, 0);
20
+ }
21
+
22
+ .tile-action-btn {
23
+ flex: 1;
24
+ padding: 6px 5px;
25
+ border: 2px solid
26
+ var(--tileActionBorderColor, var(--primaryErrorCTAFill, #d9534f));
27
+ border-radius: var(--tileActionBorderRadius, 0);
28
+ /* Inherit from the surrounding tile rather than the UA default for <button> */
29
+ font-family: inherit;
30
+ font-size: 1.2rem;
31
+ font-weight: bold;
32
+ cursor: pointer;
33
+ color: var(--tileActionColor, var(--primaryErrorCTAFill, #d9534f));
34
+ background: var(--tileActionBg, #fff);
35
+ transition:
36
+ background 0.15s,
37
+ color 0.15s;
38
+ }
39
+
40
+ /*
41
+ * When buttons are flush against each other (no gap), overlap their shared
42
+ * edge by 1px so adjacent borders don't double up.
43
+ */
44
+ .tile-action-btn + .tile-action-btn {
45
+ margin-left: -1px;
46
+ }
47
+
48
+ .tile-action-btn:hover {
49
+ background: var(
50
+ --tileActionHoverBg,
51
+ rgba(var(--primaryErrorCTAFillRGB, 229, 28, 38), 0.2)
52
+ );
53
+ color: var(
54
+ --tileActionHoverColor,
55
+ var(--tileActionColor, var(--primaryErrorCTAFill, #d9534f))
56
+ );
57
+ }
58
58
  `;
59
59
  //# sourceMappingURL=tile-action-styles.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tile-action-styles.js","sourceRoot":"","sources":["../../../src/styles/tile-action-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ClC,CAAC","sourcesContent":["import { css } from 'lit';\r\n\r\n/**\r\n * Shared styles for tile action buttons rendered in grid, list-detail, and\r\n * list-compact display modes. Layout positioning is handled by each tile\r\n * component; these styles cover only the button appearance and the row\r\n * container's default flex behavior.\r\n *\r\n * Customizable via CSS custom properties:\r\n * - `--tileActionColor` (defaults to --primaryErrorCTAFill, then #d9534f)\r\n * - `--tileActionBg` (default: #fff)\r\n * - `--tileActionBorderColor` (defaults to --primaryErrorCTAFill, then #d9534f)\r\n * - `--tileActionHoverBg` (defaults to --primaryErrorCTAFillRGB at 20% alpha)\r\n * - `--tileActionHoverColor` (defaults to --tileActionColor)\r\n */\r\nexport const tileActionStyles = css`\r\n .tile-actions {\r\n flex-shrink: 0;\r\n display: flex;\r\n gap: var(--tileActionGap, 0);\r\n }\r\n\r\n .tile-action-btn {\r\n flex: 1;\r\n padding: 6px 5px;\r\n border: 2px solid\r\n var(--tileActionBorderColor, var(--primaryErrorCTAFill, #d9534f));\r\n border-radius: var(--tileActionBorderRadius, 0);\r\n /* Inherit from the surrounding tile rather than the UA default for <button> */\r\n font-family: inherit;\r\n font-size: 1.2rem;\r\n font-weight: bold;\r\n cursor: pointer;\r\n color: var(--tileActionColor, var(--primaryErrorCTAFill, #d9534f));\r\n background: var(--tileActionBg, #fff);\r\n transition:\r\n background 0.15s,\r\n color 0.15s;\r\n }\r\n\r\n /*\r\n * When buttons are flush against each other (no gap), overlap their shared\r\n * edge by 1px so adjacent borders don't double up.\r\n */\r\n .tile-action-btn + .tile-action-btn {\r\n margin-left: -1px;\r\n }\r\n\r\n .tile-action-btn:hover {\r\n background: var(\r\n --tileActionHoverBg,\r\n rgba(var(--primaryErrorCTAFillRGB, 229, 28, 38), 0.2)\r\n );\r\n color: var(\r\n --tileActionHoverColor,\r\n var(--tileActionColor, var(--primaryErrorCTAFill, #d9534f))\r\n );\r\n }\r\n`;\r\n"]}
1
+ {"version":3,"file":"tile-action-styles.js","sourceRoot":"","sources":["../../../src/styles/tile-action-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2ClC,CAAC","sourcesContent":["import { css } from 'lit';\n\n/**\n * Shared styles for tile action buttons rendered in grid, list-detail, and\n * list-compact display modes. Layout positioning is handled by each tile\n * component; these styles cover only the button appearance and the row\n * container's default flex behavior.\n *\n * Customizable via CSS custom properties:\n * - `--tileActionColor` (defaults to --primaryErrorCTAFill, then #d9534f)\n * - `--tileActionBg` (default: #fff)\n * - `--tileActionBorderColor` (defaults to --primaryErrorCTAFill, then #d9534f)\n * - `--tileActionHoverBg` (defaults to --primaryErrorCTAFillRGB at 20% alpha)\n * - `--tileActionHoverColor` (defaults to --tileActionColor)\n */\nexport const tileActionStyles = css`\n .tile-actions {\n flex-shrink: 0;\n display: flex;\n gap: var(--tileActionGap, 0);\n }\n\n .tile-action-btn {\n flex: 1;\n padding: 6px 5px;\n border: 2px solid\n var(--tileActionBorderColor, var(--primaryErrorCTAFill, #d9534f));\n border-radius: var(--tileActionBorderRadius, 0);\n /* Inherit from the surrounding tile rather than the UA default for <button> */\n font-family: inherit;\n font-size: 1.2rem;\n font-weight: bold;\n cursor: pointer;\n color: var(--tileActionColor, var(--primaryErrorCTAFill, #d9534f));\n background: var(--tileActionBg, #fff);\n transition:\n background 0.15s,\n color 0.15s;\n }\n\n /*\n * When buttons are flush against each other (no gap), overlap their shared\n * edge by 1px so adjacent borders don't double up.\n */\n .tile-action-btn + .tile-action-btn {\n margin-left: -1px;\n }\n\n .tile-action-btn:hover {\n background: var(\n --tileActionHoverBg,\n rgba(var(--primaryErrorCTAFillRGB, 229, 28, 38), 0.2)\n );\n color: var(\n --tileActionHoverColor,\n var(--tileActionColor, var(--primaryErrorCTAFill, #d9534f))\n );\n }\n`;\n"]}
@@ -53,17 +53,17 @@ export class BaseTileComponent extends LitElement {
53
53
  'tile-actions': true,
54
54
  ...(extraClass && { [extraClass]: true }),
55
55
  });
56
- return html `
57
- <div class=${containerClasses}>
58
- ${this.tileActions.map(action => html `
59
- <button
60
- class="tile-action-btn"
61
- @click=${(e) => this.handleTileActionClick(e, action)}
62
- >
63
- ${action.label}
64
- </button>
65
- `)}
66
- </div>
56
+ return html `
57
+ <div class=${containerClasses}>
58
+ ${this.tileActions.map(action => html `
59
+ <button
60
+ class="tile-action-btn"
61
+ @click=${(e) => this.handleTileActionClick(e, action)}
62
+ >
63
+ ${action.label}
64
+ </button>
65
+ `)}
66
+ </div>
67
67
  `;
68
68
  }
69
69
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"base-tile-component.js","sourceRoot":"","sources":["../../../src/tiles/base-tile-component.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit';\r\nimport { property } from 'lit/decorators.js';\r\nimport { classMap } from 'lit/directives/class-map.js';\r\nimport type { SortParam } from '@internetarchive/search-service';\r\nimport { TileDisplayValueProvider } from './tile-display-value-provider';\r\nimport type { TileModel } from '../models';\r\nimport { DateFormat, formatDate } from '../utils/format-date';\r\nimport type { TileAction } from './models';\r\n\r\nexport abstract class BaseTileComponent extends LitElement {\r\n @property({ type: Object }) model?: TileModel;\r\n\r\n /** Action buttons to display on this tile (rendered by subclasses) */\r\n @property({ type: Array }) tileActions: TileAction[] = [];\r\n\r\n @property({ type: Number }) currentWidth?: number;\r\n\r\n @property({ type: Number }) currentHeight?: number;\r\n\r\n @property({ type: String }) baseNavigationUrl?: string;\r\n\r\n @property({ type: String }) baseImageUrl?: string;\r\n\r\n @property({ type: String }) collectionPagePath?: string;\r\n\r\n @property({ type: Object }) sortParam: SortParam | null = null;\r\n\r\n @property({ type: Object }) defaultSortParam: SortParam | null = null;\r\n\r\n @property({ type: String }) creatorFilter?: string;\r\n\r\n @property({ type: Number }) mobileBreakpoint?: number;\r\n\r\n @property({ type: Boolean }) loggedIn = false;\r\n\r\n @property({ type: Boolean }) suppressBlurring = false;\r\n\r\n @property({ type: Boolean }) useLocalTime = false;\r\n\r\n protected displayValueProvider = new TileDisplayValueProvider();\r\n\r\n protected willUpdate(changed: PropertyValues<this>) {\r\n // Ensure the TileDisplayValueProvider stays up-to-date as properties change\r\n if (\r\n changed.has('model') ||\r\n changed.has('baseNavigationUrl') ||\r\n changed.has('collectionPagePath') ||\r\n changed.has('sortParam') ||\r\n changed.has('defaultSortParam') ||\r\n changed.has('creatorFilter')\r\n ) {\r\n this.displayValueProvider = new TileDisplayValueProvider({\r\n model: this.model,\r\n baseNavigationUrl: this.baseNavigationUrl,\r\n collectionPagePath: this.collectionPagePath,\r\n sortParam: this.sortParam ?? this.defaultSortParam ?? undefined,\r\n creatorFilter: this.creatorFilter,\r\n });\r\n }\r\n }\r\n\r\n /**\r\n * The formatted date string for given date and format type, taking into\r\n * account whether this tile component should be using local time or UTC.\r\n */\r\n protected getFormattedDate(date?: Date, format?: DateFormat): string {\r\n const { useLocalTime } = this;\r\n return formatDate(date, format, { useLocalTime });\r\n }\r\n\r\n /**\r\n * Renders the action buttons configured for this tile, or `nothing` if\r\n * there are none. Optional `extraClass` is appended to the container's\r\n * class list so subclasses can target their own layout tweaks.\r\n */\r\n protected renderTileActions(\r\n extraClass: string = '',\r\n ): TemplateResult | typeof nothing {\r\n if (!this.tileActions.length) return nothing;\r\n\r\n const containerClasses = classMap({\r\n 'tile-actions': true,\r\n ...(extraClass && { [extraClass]: true }),\r\n });\r\n\r\n return html`\r\n <div class=${containerClasses}>\r\n ${this.tileActions.map(\r\n action => html`\r\n <button\r\n class=\"tile-action-btn\"\r\n @click=${(e: Event) => this.handleTileActionClick(e, action)}\r\n >\r\n ${action.label}\r\n </button>\r\n `,\r\n )}\r\n </div>\r\n `;\r\n }\r\n\r\n /**\r\n * Click handler for tile action buttons. Stops propagation so the click\r\n * doesn't activate a wrapping tile link, and dispatches a\r\n * `tileActionClicked` event (bubbling + composed) carrying the action ID\r\n * and the tile model.\r\n */\r\n protected handleTileActionClick(e: Event, action: TileAction): void {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // Pre-set the hover pane controller's clicking flag so that focus\r\n // restoration after a consumer-opened modal won't trigger the hover pane.\r\n this.dispatchEvent(\r\n new PointerEvent('pointerdown', { bubbles: true, composed: true }),\r\n );\r\n this.dispatchEvent(\r\n new CustomEvent('tileActionClicked', {\r\n detail: { actionId: action.id, model: this.model },\r\n bubbles: true,\r\n composed: true,\r\n }),\r\n );\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"base-tile-component.js","sourceRoot":"","sources":["../../../src/tiles/base-tile-component.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit';\nimport { property } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport type { SortParam } from '@internetarchive/search-service';\nimport { TileDisplayValueProvider } from './tile-display-value-provider';\nimport type { TileModel } from '../models';\nimport { DateFormat, formatDate } from '../utils/format-date';\nimport type { TileAction } from './models';\n\nexport abstract class BaseTileComponent extends LitElement {\n @property({ type: Object }) model?: TileModel;\n\n /** Action buttons to display on this tile (rendered by subclasses) */\n @property({ type: Array }) tileActions: TileAction[] = [];\n\n @property({ type: Number }) currentWidth?: number;\n\n @property({ type: Number }) currentHeight?: number;\n\n @property({ type: String }) baseNavigationUrl?: string;\n\n @property({ type: String }) baseImageUrl?: string;\n\n @property({ type: String }) collectionPagePath?: string;\n\n @property({ type: Object }) sortParam: SortParam | null = null;\n\n @property({ type: Object }) defaultSortParam: SortParam | null = null;\n\n @property({ type: String }) creatorFilter?: string;\n\n @property({ type: Number }) mobileBreakpoint?: number;\n\n @property({ type: Boolean }) loggedIn = false;\n\n @property({ type: Boolean }) suppressBlurring = false;\n\n @property({ type: Boolean }) useLocalTime = false;\n\n protected displayValueProvider = new TileDisplayValueProvider();\n\n protected willUpdate(changed: PropertyValues<this>) {\n // Ensure the TileDisplayValueProvider stays up-to-date as properties change\n if (\n changed.has('model') ||\n changed.has('baseNavigationUrl') ||\n changed.has('collectionPagePath') ||\n changed.has('sortParam') ||\n changed.has('defaultSortParam') ||\n changed.has('creatorFilter')\n ) {\n this.displayValueProvider = new TileDisplayValueProvider({\n model: this.model,\n baseNavigationUrl: this.baseNavigationUrl,\n collectionPagePath: this.collectionPagePath,\n sortParam: this.sortParam ?? this.defaultSortParam ?? undefined,\n creatorFilter: this.creatorFilter,\n });\n }\n }\n\n /**\n * The formatted date string for given date and format type, taking into\n * account whether this tile component should be using local time or UTC.\n */\n protected getFormattedDate(date?: Date, format?: DateFormat): string {\n const { useLocalTime } = this;\n return formatDate(date, format, { useLocalTime });\n }\n\n /**\n * Renders the action buttons configured for this tile, or `nothing` if\n * there are none. Optional `extraClass` is appended to the container's\n * class list so subclasses can target their own layout tweaks.\n */\n protected renderTileActions(\n extraClass: string = '',\n ): TemplateResult | typeof nothing {\n if (!this.tileActions.length) return nothing;\n\n const containerClasses = classMap({\n 'tile-actions': true,\n ...(extraClass && { [extraClass]: true }),\n });\n\n return html`\n <div class=${containerClasses}>\n ${this.tileActions.map(\n action => html`\n <button\n class=\"tile-action-btn\"\n @click=${(e: Event) => this.handleTileActionClick(e, action)}\n >\n ${action.label}\n </button>\n `,\n )}\n </div>\n `;\n }\n\n /**\n * Click handler for tile action buttons. Stops propagation so the click\n * doesn't activate a wrapping tile link, and dispatches a\n * `tileActionClicked` event (bubbling + composed) carrying the action ID\n * and the tile model.\n */\n protected handleTileActionClick(e: Event, action: TileAction): void {\n e.preventDefault();\n e.stopPropagation();\n // Pre-set the hover pane controller's clicking flag so that focus\n // restoration after a consumer-opened modal won't trigger the hover pane.\n this.dispatchEvent(\n new PointerEvent('pointerdown', { bubbles: true, composed: true }),\n );\n this.dispatchEvent(\n new CustomEvent('tileActionClicked', {\n detail: { actionId: action.id, model: this.model },\n bubbles: true,\n composed: true,\n }),\n );\n }\n}\n"]}
@@ -47,30 +47,30 @@ let ItemTile = class ItemTile extends BaseTileComponent {
47
47
  'snippets-only': this.layoutType === 'snippets-only',
48
48
  minimal: this.layoutType === 'minimal',
49
49
  });
50
- return html `
51
- <div class=${containerClasses}>
52
- ${this.infoButtonTemplate}
53
- <div class="tile-details">
54
- <div class="item-info">
55
- ${this.imageBlockTemplate}
56
-
57
- <div id="title">
58
- <h3 class="truncated" title=${ifDefined(itemTitle)}>
59
- ${itemTitle}
60
- </h3>
61
- </div>
62
-
63
- ${this.volumeIssueTemplate}
50
+ return html `
51
+ <div class=${containerClasses}>
52
+ ${this.infoButtonTemplate}
53
+ <div class="tile-details">
54
+ <div class="item-info">
55
+ ${this.imageBlockTemplate}
56
+
57
+ <div id="title">
58
+ <h3 class="truncated" title=${ifDefined(itemTitle)}>
59
+ ${itemTitle}
60
+ </h3>
61
+ </div>
62
+
63
+ ${this.volumeIssueTemplate}
64
64
  ${this.isSortedByDate
65
65
  ? this.sortedDateInfoTemplate
66
- : this.creatorTemplate}
67
- ${this.webArchivesCaptureDatesTemplate} ${this.textSnippetsTemplate}
68
- ${this.reviewBlockTemplate}
69
- </div>
70
-
71
- ${this.tileStatsTemplate}
72
- </div>
73
- </div>
66
+ : this.creatorTemplate}
67
+ ${this.webArchivesCaptureDatesTemplate} ${this.textSnippetsTemplate}
68
+ ${this.reviewBlockTemplate}
69
+ </div>
70
+
71
+ ${this.tileStatsTemplate}
72
+ </div>
73
+ </div>
74
74
  `;
75
75
  }
76
76
  /**
@@ -80,26 +80,26 @@ let ItemTile = class ItemTile extends BaseTileComponent {
80
80
  const displayedCreator = this.displayValueProvider.firstCreatorMatchingFilter;
81
81
  if (!displayedCreator)
82
82
  return nothing;
83
- return html `
84
- <div class="created-by">
85
- <span class="truncated" title=${displayedCreator}>
86
- by&nbsp;${displayedCreator}
87
- </span>
88
- </div>
83
+ return html `
84
+ <div class="created-by">
85
+ <span class="truncated" title=${displayedCreator}>
86
+ by&nbsp;${displayedCreator}
87
+ </span>
88
+ </div>
89
89
  `;
90
90
  }
91
91
  get imageBlockTemplate() {
92
- return html `
93
- <image-block
94
- .model=${this.model}
95
- .baseImageUrl=${this.baseImageUrl}
96
- .loggedIn=${this.loggedIn}
97
- .suppressBlurring=${this.suppressBlurring}
98
- .isCompactTile=${false}
99
- .isListTile=${false}
100
- .viewSize=${'grid'}
101
- >
102
- </image-block>
92
+ return html `
93
+ <image-block
94
+ .model=${this.model}
95
+ .baseImageUrl=${this.baseImageUrl}
96
+ .loggedIn=${this.loggedIn}
97
+ .suppressBlurring=${this.suppressBlurring}
98
+ .isCompactTile=${false}
99
+ .isListTile=${false}
100
+ .viewSize=${'grid'}
101
+ >
102
+ </image-block>
103
103
  `;
104
104
  }
105
105
  get sortedDateInfoTemplate() {
@@ -130,18 +130,18 @@ let ItemTile = class ItemTile extends BaseTileComponent {
130
130
  return nothing;
131
131
  }
132
132
  const formattedDate = this.getFormattedDate(sortedValue.value, format);
133
- return html `
134
- <div class="date-sorted-by truncated">
135
- <span>${sortedValue.field} ${formattedDate}</span>
136
- </div>
133
+ return html `
134
+ <div class="date-sorted-by truncated">
135
+ <span>${sortedValue.field} ${formattedDate}</span>
136
+ </div>
137
137
  `;
138
138
  }
139
139
  get infoButtonTemplate() {
140
140
  // &#9432; is an information icon
141
141
  return this.showInfoButton
142
- ? html `<button class="info-button" @click=${this.infoButtonPressed}>
143
- &#9432;
144
- <span class="sr-only">${msg('More info')}</span>
142
+ ? html `<button class="info-button" @click=${this.infoButtonPressed}>
143
+ &#9432;
144
+ <span class="sr-only">${msg('More info')}</span>
145
145
  </button>`
146
146
  : nothing;
147
147
  }
@@ -149,14 +149,14 @@ let ItemTile = class ItemTile extends BaseTileComponent {
149
149
  if (!this.model?.review)
150
150
  return nothing;
151
151
  const { reviewtitle, reviewbody, stars } = this.model.review;
152
- return html `
153
- <review-block
154
- viewsize="grid"
155
- title=${ifDefined(reviewtitle)}
156
- body=${ifDefined(reviewbody)}
157
- starRating=${ifDefined(stars)}
158
- >
159
- </review-block>
152
+ return html `
153
+ <review-block
154
+ viewsize="grid"
155
+ title=${ifDefined(reviewtitle)}
156
+ body=${ifDefined(reviewbody)}
157
+ starRating=${ifDefined(stars)}
158
+ >
159
+ </review-block>
160
160
  `;
161
161
  }
162
162
  get textSnippetsTemplate() {
@@ -165,31 +165,31 @@ let ItemTile = class ItemTile extends BaseTileComponent {
165
165
  if (['stats-only', 'minimal'].includes(this.layoutType)) {
166
166
  return nothing;
167
167
  }
168
- return html `
169
- <text-snippet-block viewsize="grid" .snippets=${this.model?.snippets}>
170
- </text-snippet-block>
168
+ return html `
169
+ <text-snippet-block viewsize="grid" .snippets=${this.model?.snippets}>
170
+ </text-snippet-block>
171
171
  `;
172
172
  }
173
173
  get volumeIssueTemplate() {
174
174
  if (!this.model?.volume || !this.model?.issue)
175
175
  return nothing;
176
- return html `
177
- <div class="volume-issue">
178
- <span class="truncated" title="volume|issue">
179
- Volume&nbsp;${this.model?.volume}, Issue&nbsp;${this.model?.issue}
180
- </span>
181
- </div>
176
+ return html `
177
+ <div class="volume-issue">
178
+ <span class="truncated" title="volume|issue">
179
+ Volume&nbsp;${this.model?.volume}, Issue&nbsp;${this.model?.issue}
180
+ </span>
181
+ </div>
182
182
  `;
183
183
  }
184
184
  get webArchivesCaptureDatesTemplate() {
185
185
  if (!this.model?.captureDates || !this.model.title)
186
186
  return nothing;
187
- return html `
188
- <ul class="capture-dates">
189
- ${map(this.model.captureDates, date => html `<li>
190
- ${this.displayValueProvider.webArchivesCaptureLink(this.model.title, date)}
191
- </li>`)}
192
- </ul>
187
+ return html `
188
+ <ul class="capture-dates">
189
+ ${map(this.model.captureDates, date => html `<li>
190
+ ${this.displayValueProvider.webArchivesCaptureLink(this.model.title, date)}
191
+ </li>`)}
192
+ </ul>
193
193
  `;
194
194
  }
195
195
  /**
@@ -203,18 +203,18 @@ let ItemTile = class ItemTile extends BaseTileComponent {
203
203
  const [viewCount, viewLabel] = effectiveSort?.field === 'week'
204
204
  ? [this.model?.weeklyViewCount, 'weekly views']
205
205
  : [this.model?.viewCount, 'all-time views'];
206
- return html `
207
- <tile-stats
208
- .model=${this.model}
209
- .mediatype=${this.model?.mediatype}
210
- .viewCount=${viewCount}
211
- .viewLabel=${viewLabel}
212
- .favCount=${this.model?.favCount}
213
- .commentCount=${this.model?.commentCount}
214
- .tvClipCount=${this.model?.tvClipCount}
215
- .showTvClips=${this.showTvClips}
216
- >
217
- </tile-stats>
206
+ return html `
207
+ <tile-stats
208
+ .model=${this.model}
209
+ .mediatype=${this.model?.mediatype}
210
+ .viewCount=${viewCount}
211
+ .viewLabel=${viewLabel}
212
+ .favCount=${this.model?.favCount}
213
+ .commentCount=${this.model?.commentCount}
214
+ .tvClipCount=${this.model?.tvClipCount}
215
+ .showTvClips=${this.showTvClips}
216
+ >
217
+ </tile-stats>
218
218
  `;
219
219
  }
220
220
  get isSortedByDate() {
@@ -241,63 +241,63 @@ let ItemTile = class ItemTile extends BaseTileComponent {
241
241
  const tileBorderColor = css `var(--tileBorderColor, #dddddd)`;
242
242
  return [
243
243
  baseTileStyles,
244
- css `
245
- a:link {
246
- text-decoration: none;
247
- color: var(--ia-theme-link-color, #4b64ff);
248
- }
249
- a:hover {
250
- text-decoration: underline;
251
- }
252
-
253
- .container {
254
- border: 1px solid ${tileBorderColor};
255
- }
256
-
257
- .simple #title > .truncated {
258
- -webkit-line-clamp: 2;
259
- }
260
-
261
- .simple .created-by > .truncated,
262
- .simple .date-sorted-by > .truncated,
263
- .simple .volume-issue > .truncated {
264
- -webkit-line-clamp: 1;
265
- }
266
-
267
- .simple.snippets-only .item-info,
268
- .simple.minimal .item-info {
269
- padding-bottom: 5px;
270
- }
271
-
272
- .simple.snippets-only text-snippet-block {
273
- margin-top: auto; /* Force the snippets to the bottom of the tile */
274
- }
275
-
276
- .capture-dates {
277
- margin: 0;
278
- padding: 0 5px;
279
- list-style-type: none;
280
- }
281
-
282
- review-block,
283
- text-snippet-block {
284
- --containerLeftMargin: 5px;
285
- --containerTopMargin: 5px;
286
- }
287
-
288
- /**
289
- * iOS Safari long-press on tiles (to bring up hover pane)
290
- * gets messy without this
291
- */
292
- @media screen and (pointer: coarse) and (hover: none) {
293
- .container {
294
- -webkit-touch-callout: none;
295
- }
296
-
297
- .truncated {
298
- -webkit-touch-callout: default;
299
- }
300
- }
244
+ css `
245
+ a:link {
246
+ text-decoration: none;
247
+ color: var(--ia-theme-link-color, #4b64ff);
248
+ }
249
+ a:hover {
250
+ text-decoration: underline;
251
+ }
252
+
253
+ .container {
254
+ border: 1px solid ${tileBorderColor};
255
+ }
256
+
257
+ .simple #title > .truncated {
258
+ -webkit-line-clamp: 2;
259
+ }
260
+
261
+ .simple .created-by > .truncated,
262
+ .simple .date-sorted-by > .truncated,
263
+ .simple .volume-issue > .truncated {
264
+ -webkit-line-clamp: 1;
265
+ }
266
+
267
+ .simple.snippets-only .item-info,
268
+ .simple.minimal .item-info {
269
+ padding-bottom: 5px;
270
+ }
271
+
272
+ .simple.snippets-only text-snippet-block {
273
+ margin-top: auto; /* Force the snippets to the bottom of the tile */
274
+ }
275
+
276
+ .capture-dates {
277
+ margin: 0;
278
+ padding: 0 5px;
279
+ list-style-type: none;
280
+ }
281
+
282
+ review-block,
283
+ text-snippet-block {
284
+ --containerLeftMargin: 5px;
285
+ --containerTopMargin: 5px;
286
+ }
287
+
288
+ /**
289
+ * iOS Safari long-press on tiles (to bring up hover pane)
290
+ * gets messy without this
291
+ */
292
+ @media screen and (pointer: coarse) and (hover: none) {
293
+ .container {
294
+ -webkit-touch-callout: none;
295
+ }
296
+
297
+ .truncated {
298
+ -webkit-touch-callout: default;
299
+ }
300
+ }
301
301
  `,
302
302
  ];
303
303
  }
@@ -1 +1 @@
1
- {"version":3,"file":"item-tile.js","sourceRoot":"","sources":["../../../../src/tiles/grid/item-tile.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, CSSResultGroup, html, nothing, TemplateResult } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport { ifDefined } from 'lit/directives/if-defined.js';\r\nimport { map } from 'lit/directives/map.js';\r\nimport { classMap } from 'lit/directives/class-map.js';\r\nimport { msg } from '@lit/localize';\r\n\r\nimport type { SortParam } from '@internetarchive/search-service';\r\nimport type { DateFormat } from '../../utils/format-date';\r\nimport { isFirstMillisecondOfUTCYear } from '../../utils/local-date-from-utc';\r\nimport { BaseTileComponent } from '../base-tile-component';\r\nimport { baseTileStyles } from './styles/tile-grid-shared-styles';\r\nimport { LayoutType } from '../models';\r\n\r\nimport '../image-block';\r\nimport '../review-block';\r\nimport '../text-snippet-block';\r\nimport '../item-image';\r\nimport '../tile-mediatype-icon';\r\nimport './tile-stats';\r\n\r\n@customElement('item-tile')\r\nexport class ItemTile extends BaseTileComponent {\r\n /*\r\n * Reactive properties inherited from BaseTileComponent:\r\n * - model?: TileModel;\r\n * - tileActions: TileAction[] = [];\r\n * - currentWidth?: number;\r\n * - currentHeight?: number;\r\n * - baseNavigationUrl?: string;\r\n * - baseImageUrl?: string;\r\n * - collectionPagePath?: string;\r\n * - sortParam: SortParam | null = null;\r\n * - defaultSortParam: SortParam | null = null;\r\n * - creatorFilter?: string;\r\n * - mobileBreakpoint?: number;\r\n * - loggedIn = false;\r\n * - suppressBlurring = false;\r\n * - useLocalTime = false;\r\n */\r\n\r\n @property({ type: Boolean }) showInfoButton = false;\r\n\r\n @property({ type: Boolean }) showTvClips = false;\r\n\r\n @property({ type: String }) layoutType: LayoutType = 'default';\r\n\r\n render() {\r\n const itemTitle = this.model?.title;\r\n const containerClasses = classMap({\r\n container: true,\r\n simple: this.layoutType !== 'default',\r\n 'stats-only': this.layoutType === 'stats-only',\r\n 'snippets-only': this.layoutType === 'snippets-only',\r\n minimal: this.layoutType === 'minimal',\r\n });\r\n\r\n return html`\r\n <div class=${containerClasses}>\r\n ${this.infoButtonTemplate}\r\n <div class=\"tile-details\">\r\n <div class=\"item-info\">\r\n ${this.imageBlockTemplate}\r\n\r\n <div id=\"title\">\r\n <h3 class=\"truncated\" title=${ifDefined(itemTitle)}>\r\n ${itemTitle}\r\n </h3>\r\n </div>\r\n\r\n ${this.volumeIssueTemplate}\r\n ${this.isSortedByDate\r\n ? this.sortedDateInfoTemplate\r\n : this.creatorTemplate}\r\n ${this.webArchivesCaptureDatesTemplate} ${this.textSnippetsTemplate}\r\n ${this.reviewBlockTemplate}\r\n </div>\r\n\r\n ${this.tileStatsTemplate}\r\n </div>\r\n </div>\r\n `;\r\n }\r\n\r\n /**\r\n * Templates\r\n */\r\n private get creatorTemplate(): TemplateResult | typeof nothing {\r\n const displayedCreator =\r\n this.displayValueProvider.firstCreatorMatchingFilter;\r\n if (!displayedCreator) return nothing;\r\n\r\n return html`\r\n <div class=\"created-by\">\r\n <span class=\"truncated\" title=${displayedCreator}>\r\n by&nbsp;${displayedCreator}\r\n </span>\r\n </div>\r\n `;\r\n }\r\n\r\n private get imageBlockTemplate(): TemplateResult {\r\n return html`\r\n <image-block\r\n .model=${this.model}\r\n .baseImageUrl=${this.baseImageUrl}\r\n .loggedIn=${this.loggedIn}\r\n .suppressBlurring=${this.suppressBlurring}\r\n .isCompactTile=${false}\r\n .isListTile=${false}\r\n .viewSize=${'grid'}\r\n >\r\n </image-block>\r\n `;\r\n }\r\n\r\n private get sortedDateInfoTemplate() {\r\n let sortedValue;\r\n let format: DateFormat = 'long';\r\n switch (this.effectiveSort?.field) {\r\n case 'date': {\r\n const datePublished = this.model?.datePublished;\r\n sortedValue = { field: 'published', value: datePublished };\r\n if (isFirstMillisecondOfUTCYear(datePublished)) {\r\n format = 'year-only';\r\n }\r\n break;\r\n }\r\n case 'reviewdate':\r\n sortedValue = { field: 'reviewed', value: this.model?.dateReviewed };\r\n break;\r\n case 'addeddate':\r\n sortedValue = { field: 'added', value: this.model?.dateAdded };\r\n break;\r\n case 'publicdate':\r\n sortedValue = { field: 'archived', value: this.model?.dateArchived };\r\n break;\r\n default:\r\n break;\r\n }\r\n\r\n if (!sortedValue?.value) {\r\n return nothing;\r\n }\r\n\r\n const formattedDate = this.getFormattedDate(sortedValue.value, format);\r\n return html`\r\n <div class=\"date-sorted-by truncated\">\r\n <span>${sortedValue.field} ${formattedDate}</span>\r\n </div>\r\n `;\r\n }\r\n\r\n private get infoButtonTemplate(): TemplateResult | typeof nothing {\r\n // &#9432; is an information icon\r\n return this.showInfoButton\r\n ? html`<button class=\"info-button\" @click=${this.infoButtonPressed}>\r\n &#9432;\r\n <span class=\"sr-only\">${msg('More info')}</span>\r\n </button>`\r\n : nothing;\r\n }\r\n\r\n private get reviewBlockTemplate(): TemplateResult | typeof nothing {\r\n if (!this.model?.review) return nothing;\r\n\r\n const { reviewtitle, reviewbody, stars } = this.model.review;\r\n return html`\r\n <review-block\r\n viewsize=\"grid\"\r\n title=${ifDefined(reviewtitle)}\r\n body=${ifDefined(reviewbody)}\r\n starRating=${ifDefined(stars)}\r\n >\r\n </review-block>\r\n `;\r\n }\r\n\r\n private get textSnippetsTemplate(): TemplateResult | typeof nothing {\r\n if (!this.hasSnippets) return nothing;\r\n if (['stats-only', 'minimal'].includes(this.layoutType)) {\r\n return nothing;\r\n }\r\n\r\n return html`\r\n <text-snippet-block viewsize=\"grid\" .snippets=${this.model?.snippets}>\r\n </text-snippet-block>\r\n `;\r\n }\r\n\r\n private get volumeIssueTemplate(): TemplateResult | typeof nothing {\r\n if (!this.model?.volume || !this.model?.issue) return nothing;\r\n\r\n return html`\r\n <div class=\"volume-issue\">\r\n <span class=\"truncated\" title=\"volume|issue\">\r\n Volume&nbsp;${this.model?.volume}, Issue&nbsp;${this.model?.issue}\r\n </span>\r\n </div>\r\n `;\r\n }\r\n\r\n private get webArchivesCaptureDatesTemplate():\r\n | TemplateResult\r\n | typeof nothing {\r\n if (!this.model?.captureDates || !this.model.title) return nothing;\r\n\r\n return html`\r\n <ul class=\"capture-dates\">\r\n ${map(\r\n this.model.captureDates,\r\n date =>\r\n html`<li>\r\n ${this.displayValueProvider.webArchivesCaptureLink(\r\n this.model!.title,\r\n date,\r\n )}\r\n </li>`,\r\n )}\r\n </ul>\r\n `;\r\n }\r\n\r\n /**\r\n * Template for the stats row along the bottom of the tile.\r\n */\r\n private get tileStatsTemplate(): TemplateResult | typeof nothing {\r\n if (['snippets-only', 'minimal'].includes(this.layoutType)) {\r\n return nothing;\r\n }\r\n\r\n const effectiveSort = this.sortParam ?? this.defaultSortParam;\r\n const [viewCount, viewLabel] =\r\n effectiveSort?.field === 'week'\r\n ? [this.model?.weeklyViewCount, 'weekly views']\r\n : [this.model?.viewCount, 'all-time views'];\r\n\r\n return html`\r\n <tile-stats\r\n .model=${this.model}\r\n .mediatype=${this.model?.mediatype}\r\n .viewCount=${viewCount}\r\n .viewLabel=${viewLabel}\r\n .favCount=${this.model?.favCount}\r\n .commentCount=${this.model?.commentCount}\r\n .tvClipCount=${this.model?.tvClipCount}\r\n .showTvClips=${this.showTvClips}\r\n >\r\n </tile-stats>\r\n `;\r\n }\r\n\r\n private get isSortedByDate(): boolean {\r\n return ['date', 'reviewdate', 'addeddate', 'publicdate'].includes(\r\n this.effectiveSort?.field as string,\r\n );\r\n }\r\n\r\n /**\r\n * Returns the active sort param if one is set, or the default sort param otherwise.\r\n */\r\n private get effectiveSort(): SortParam | null {\r\n return this.sortParam ?? this.defaultSortParam;\r\n }\r\n\r\n private get hasSnippets(): boolean {\r\n return !!this.model?.snippets?.length;\r\n }\r\n\r\n private infoButtonPressed(e: PointerEvent): void {\r\n e.preventDefault();\r\n const event = new CustomEvent<{ x: number; y: number }>(\r\n 'infoButtonPressed',\r\n { detail: { x: e.clientX, y: e.clientY } },\r\n );\r\n this.dispatchEvent(event);\r\n }\r\n\r\n /**\r\n * CSS\r\n */\r\n static get styles(): CSSResultGroup {\r\n const tileBorderColor = css`var(--tileBorderColor, #dddddd)`;\r\n\r\n return [\r\n baseTileStyles,\r\n css`\r\n a:link {\r\n text-decoration: none;\r\n color: var(--ia-theme-link-color, #4b64ff);\r\n }\r\n a:hover {\r\n text-decoration: underline;\r\n }\r\n\r\n .container {\r\n border: 1px solid ${tileBorderColor};\r\n }\r\n\r\n .simple #title > .truncated {\r\n -webkit-line-clamp: 2;\r\n }\r\n\r\n .simple .created-by > .truncated,\r\n .simple .date-sorted-by > .truncated,\r\n .simple .volume-issue > .truncated {\r\n -webkit-line-clamp: 1;\r\n }\r\n\r\n .simple.snippets-only .item-info,\r\n .simple.minimal .item-info {\r\n padding-bottom: 5px;\r\n }\r\n\r\n .simple.snippets-only text-snippet-block {\r\n margin-top: auto; /* Force the snippets to the bottom of the tile */\r\n }\r\n\r\n .capture-dates {\r\n margin: 0;\r\n padding: 0 5px;\r\n list-style-type: none;\r\n }\r\n\r\n review-block,\r\n text-snippet-block {\r\n --containerLeftMargin: 5px;\r\n --containerTopMargin: 5px;\r\n }\r\n\r\n /**\r\n * iOS Safari long-press on tiles (to bring up hover pane)\r\n * gets messy without this\r\n */\r\n @media screen and (pointer: coarse) and (hover: none) {\r\n .container {\r\n -webkit-touch-callout: none;\r\n }\r\n\r\n .truncated {\r\n -webkit-touch-callout: default;\r\n }\r\n }\r\n `,\r\n ];\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"item-tile.js","sourceRoot":"","sources":["../../../../src/tiles/grid/item-tile.ts"],"names":[],"mappings":"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","sourcesContent":["import { css, CSSResultGroup, html, nothing, TemplateResult } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { map } from 'lit/directives/map.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { msg } from '@lit/localize';\n\nimport type { SortParam } from '@internetarchive/search-service';\nimport type { DateFormat } from '../../utils/format-date';\nimport { isFirstMillisecondOfUTCYear } from '../../utils/local-date-from-utc';\nimport { BaseTileComponent } from '../base-tile-component';\nimport { baseTileStyles } from './styles/tile-grid-shared-styles';\nimport { LayoutType } from '../models';\n\nimport '../image-block';\nimport '../review-block';\nimport '../text-snippet-block';\nimport '../item-image';\nimport '../tile-mediatype-icon';\nimport './tile-stats';\n\n@customElement('item-tile')\nexport class ItemTile extends BaseTileComponent {\n /*\n * Reactive properties inherited from BaseTileComponent:\n * - model?: TileModel;\n * - tileActions: TileAction[] = [];\n * - currentWidth?: number;\n * - currentHeight?: number;\n * - baseNavigationUrl?: string;\n * - baseImageUrl?: string;\n * - collectionPagePath?: string;\n * - sortParam: SortParam | null = null;\n * - defaultSortParam: SortParam | null = null;\n * - creatorFilter?: string;\n * - mobileBreakpoint?: number;\n * - loggedIn = false;\n * - suppressBlurring = false;\n * - useLocalTime = false;\n */\n\n @property({ type: Boolean }) showInfoButton = false;\n\n @property({ type: Boolean }) showTvClips = false;\n\n @property({ type: String }) layoutType: LayoutType = 'default';\n\n render() {\n const itemTitle = this.model?.title;\n const containerClasses = classMap({\n container: true,\n simple: this.layoutType !== 'default',\n 'stats-only': this.layoutType === 'stats-only',\n 'snippets-only': this.layoutType === 'snippets-only',\n minimal: this.layoutType === 'minimal',\n });\n\n return html`\n <div class=${containerClasses}>\n ${this.infoButtonTemplate}\n <div class=\"tile-details\">\n <div class=\"item-info\">\n ${this.imageBlockTemplate}\n\n <div id=\"title\">\n <h3 class=\"truncated\" title=${ifDefined(itemTitle)}>\n ${itemTitle}\n </h3>\n </div>\n\n ${this.volumeIssueTemplate}\n ${this.isSortedByDate\n ? this.sortedDateInfoTemplate\n : this.creatorTemplate}\n ${this.webArchivesCaptureDatesTemplate} ${this.textSnippetsTemplate}\n ${this.reviewBlockTemplate}\n </div>\n\n ${this.tileStatsTemplate}\n </div>\n </div>\n `;\n }\n\n /**\n * Templates\n */\n private get creatorTemplate(): TemplateResult | typeof nothing {\n const displayedCreator =\n this.displayValueProvider.firstCreatorMatchingFilter;\n if (!displayedCreator) return nothing;\n\n return html`\n <div class=\"created-by\">\n <span class=\"truncated\" title=${displayedCreator}>\n by&nbsp;${displayedCreator}\n </span>\n </div>\n `;\n }\n\n private get imageBlockTemplate(): TemplateResult {\n return html`\n <image-block\n .model=${this.model}\n .baseImageUrl=${this.baseImageUrl}\n .loggedIn=${this.loggedIn}\n .suppressBlurring=${this.suppressBlurring}\n .isCompactTile=${false}\n .isListTile=${false}\n .viewSize=${'grid'}\n >\n </image-block>\n `;\n }\n\n private get sortedDateInfoTemplate() {\n let sortedValue;\n let format: DateFormat = 'long';\n switch (this.effectiveSort?.field) {\n case 'date': {\n const datePublished = this.model?.datePublished;\n sortedValue = { field: 'published', value: datePublished };\n if (isFirstMillisecondOfUTCYear(datePublished)) {\n format = 'year-only';\n }\n break;\n }\n case 'reviewdate':\n sortedValue = { field: 'reviewed', value: this.model?.dateReviewed };\n break;\n case 'addeddate':\n sortedValue = { field: 'added', value: this.model?.dateAdded };\n break;\n case 'publicdate':\n sortedValue = { field: 'archived', value: this.model?.dateArchived };\n break;\n default:\n break;\n }\n\n if (!sortedValue?.value) {\n return nothing;\n }\n\n const formattedDate = this.getFormattedDate(sortedValue.value, format);\n return html`\n <div class=\"date-sorted-by truncated\">\n <span>${sortedValue.field} ${formattedDate}</span>\n </div>\n `;\n }\n\n private get infoButtonTemplate(): TemplateResult | typeof nothing {\n // &#9432; is an information icon\n return this.showInfoButton\n ? html`<button class=\"info-button\" @click=${this.infoButtonPressed}>\n &#9432;\n <span class=\"sr-only\">${msg('More info')}</span>\n </button>`\n : nothing;\n }\n\n private get reviewBlockTemplate(): TemplateResult | typeof nothing {\n if (!this.model?.review) return nothing;\n\n const { reviewtitle, reviewbody, stars } = this.model.review;\n return html`\n <review-block\n viewsize=\"grid\"\n title=${ifDefined(reviewtitle)}\n body=${ifDefined(reviewbody)}\n starRating=${ifDefined(stars)}\n >\n </review-block>\n `;\n }\n\n private get textSnippetsTemplate(): TemplateResult | typeof nothing {\n if (!this.hasSnippets) return nothing;\n if (['stats-only', 'minimal'].includes(this.layoutType)) {\n return nothing;\n }\n\n return html`\n <text-snippet-block viewsize=\"grid\" .snippets=${this.model?.snippets}>\n </text-snippet-block>\n `;\n }\n\n private get volumeIssueTemplate(): TemplateResult | typeof nothing {\n if (!this.model?.volume || !this.model?.issue) return nothing;\n\n return html`\n <div class=\"volume-issue\">\n <span class=\"truncated\" title=\"volume|issue\">\n Volume&nbsp;${this.model?.volume}, Issue&nbsp;${this.model?.issue}\n </span>\n </div>\n `;\n }\n\n private get webArchivesCaptureDatesTemplate():\n | TemplateResult\n | typeof nothing {\n if (!this.model?.captureDates || !this.model.title) return nothing;\n\n return html`\n <ul class=\"capture-dates\">\n ${map(\n this.model.captureDates,\n date =>\n html`<li>\n ${this.displayValueProvider.webArchivesCaptureLink(\n this.model!.title,\n date,\n )}\n </li>`,\n )}\n </ul>\n `;\n }\n\n /**\n * Template for the stats row along the bottom of the tile.\n */\n private get tileStatsTemplate(): TemplateResult | typeof nothing {\n if (['snippets-only', 'minimal'].includes(this.layoutType)) {\n return nothing;\n }\n\n const effectiveSort = this.sortParam ?? this.defaultSortParam;\n const [viewCount, viewLabel] =\n effectiveSort?.field === 'week'\n ? [this.model?.weeklyViewCount, 'weekly views']\n : [this.model?.viewCount, 'all-time views'];\n\n return html`\n <tile-stats\n .model=${this.model}\n .mediatype=${this.model?.mediatype}\n .viewCount=${viewCount}\n .viewLabel=${viewLabel}\n .favCount=${this.model?.favCount}\n .commentCount=${this.model?.commentCount}\n .tvClipCount=${this.model?.tvClipCount}\n .showTvClips=${this.showTvClips}\n >\n </tile-stats>\n `;\n }\n\n private get isSortedByDate(): boolean {\n return ['date', 'reviewdate', 'addeddate', 'publicdate'].includes(\n this.effectiveSort?.field as string,\n );\n }\n\n /**\n * Returns the active sort param if one is set, or the default sort param otherwise.\n */\n private get effectiveSort(): SortParam | null {\n return this.sortParam ?? this.defaultSortParam;\n }\n\n private get hasSnippets(): boolean {\n return !!this.model?.snippets?.length;\n }\n\n private infoButtonPressed(e: PointerEvent): void {\n e.preventDefault();\n const event = new CustomEvent<{ x: number; y: number }>(\n 'infoButtonPressed',\n { detail: { x: e.clientX, y: e.clientY } },\n );\n this.dispatchEvent(event);\n }\n\n /**\n * CSS\n */\n static get styles(): CSSResultGroup {\n const tileBorderColor = css`var(--tileBorderColor, #dddddd)`;\n\n return [\n baseTileStyles,\n css`\n a:link {\n text-decoration: none;\n color: var(--ia-theme-link-color, #4b64ff);\n }\n a:hover {\n text-decoration: underline;\n }\n\n .container {\n border: 1px solid ${tileBorderColor};\n }\n\n .simple #title > .truncated {\n -webkit-line-clamp: 2;\n }\n\n .simple .created-by > .truncated,\n .simple .date-sorted-by > .truncated,\n .simple .volume-issue > .truncated {\n -webkit-line-clamp: 1;\n }\n\n .simple.snippets-only .item-info,\n .simple.minimal .item-info {\n padding-bottom: 5px;\n }\n\n .simple.snippets-only text-snippet-block {\n margin-top: auto; /* Force the snippets to the bottom of the tile */\n }\n\n .capture-dates {\n margin: 0;\n padding: 0 5px;\n list-style-type: none;\n }\n\n review-block,\n text-snippet-block {\n --containerLeftMargin: 5px;\n --containerTopMargin: 5px;\n }\n\n /**\n * iOS Safari long-press on tiles (to bring up hover pane)\n * gets messy without this\n */\n @media screen and (pointer: coarse) and (hover: none) {\n .container {\n -webkit-touch-callout: none;\n }\n\n .truncated {\n -webkit-touch-callout: default;\n }\n }\n `,\n ];\n }\n}\n"]}