@internetarchive/collection-browser 4.3.0 → 4.3.1-alpha-webdev8257.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.
- package/dist/index.d.ts +1 -0
- package/dist/index.js.map +1 -1
- package/dist/src/app-root.d.ts +11 -0
- package/dist/src/app-root.js +107 -0
- package/dist/src/app-root.js.map +1 -1
- package/dist/src/collection-browser.d.ts +8 -4
- package/dist/src/collection-browser.js +19 -20
- package/dist/src/collection-browser.js.map +1 -1
- package/dist/src/data-source/collection-browser-data-source.js.map +1 -1
- package/dist/src/manage/manage-bar.d.ts +7 -2
- package/dist/src/manage/manage-bar.js +25 -3
- package/dist/src/manage/manage-bar.js.map +1 -1
- package/dist/src/styles/tile-action-styles.d.ts +14 -0
- package/dist/src/styles/tile-action-styles.js +52 -0
- package/dist/src/styles/tile-action-styles.js.map +1 -0
- package/dist/src/tiles/base-tile-component.d.ts +17 -1
- package/dist/src/tiles/base-tile-component.js +48 -1
- package/dist/src/tiles/base-tile-component.js.map +1 -1
- package/dist/src/tiles/grid/item-tile.js +1 -0
- package/dist/src/tiles/grid/item-tile.js.map +1 -1
- package/dist/src/tiles/list/tile-list-compact-header.js +66 -46
- package/dist/src/tiles/list/tile-list-compact-header.js.map +1 -1
- package/dist/src/tiles/list/tile-list-compact.d.ts +1 -1
- package/dist/src/tiles/list/tile-list-compact.js +132 -100
- package/dist/src/tiles/list/tile-list-compact.js.map +1 -1
- package/dist/src/tiles/list/tile-list.d.ts +1 -1
- package/dist/src/tiles/list/tile-list.js +316 -298
- package/dist/src/tiles/list/tile-list.js.map +1 -1
- package/dist/src/tiles/models.d.ts +14 -0
- package/dist/src/tiles/models.js.map +1 -1
- package/dist/src/tiles/tile-dispatcher.d.ts +14 -0
- package/dist/src/tiles/tile-dispatcher.js +107 -4
- package/dist/src/tiles/tile-dispatcher.js.map +1 -1
- package/dist/src/tiles/tile-display-value-provider.js.map +1 -1
- package/dist/test/data-source/collection-browser-data-source.test.js +2 -2
- package/dist/test/data-source/collection-browser-data-source.test.js.map +1 -1
- package/dist/test/manage/manage-bar.test.d.ts +1 -0
- package/dist/test/manage/manage-bar.test.js +123 -1
- package/dist/test/manage/manage-bar.test.js.map +1 -1
- package/dist/test/tiles/list/tile-list-compact-header.test.js +12 -12
- package/dist/test/tiles/list/tile-list-compact-header.test.js.map +1 -1
- package/dist/test/tiles/list/tile-list.test.js +134 -134
- package/dist/test/tiles/list/tile-list.test.js.map +1 -1
- package/index.ts +1 -0
- package/package.json +1 -1
- package/src/app-root.ts +115 -0
- package/src/collection-browser.ts +16 -30
- package/src/data-source/collection-browser-data-source.ts +1465 -1465
- package/src/manage/manage-bar.ts +33 -4
- package/src/styles/tile-action-styles.ts +52 -0
- package/src/tiles/base-tile-component.ts +57 -1
- package/src/tiles/grid/item-tile.ts +1 -0
- package/src/tiles/list/tile-list-compact-header.ts +106 -86
- package/src/tiles/list/tile-list-compact.ts +273 -239
- package/src/tiles/list/tile-list.ts +718 -700
- package/src/tiles/models.ts +16 -0
- package/src/tiles/tile-dispatcher.ts +114 -4
- package/src/tiles/tile-display-value-provider.ts +134 -134
- package/test/data-source/collection-browser-data-source.test.ts +193 -193
- package/test/manage/manage-bar.test.ts +192 -2
- package/test/tiles/list/tile-list-compact-header.test.ts +43 -43
- package/test/tiles/list/tile-list.test.ts +576 -576
- package/.claude/settings.local.json +0 -11
package/src/manage/manage-bar.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { msg } from '@lit/localize';
|
|
1
|
+
import { msg, str } from '@lit/localize';
|
|
2
2
|
import { LitElement, html, css, TemplateResult, CSSResultGroup } from 'lit';
|
|
3
3
|
import { customElement, property } from 'lit/decorators.js';
|
|
4
4
|
import { when } from 'lit/directives/when.js';
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type ModalManagerInterface,
|
|
8
8
|
} from '@internetarchive/modal-manager';
|
|
9
9
|
import type { ManageableItem } from '../models';
|
|
10
|
+
import { PageElementName } from '@internetarchive/search-service';
|
|
10
11
|
import iaButtonStyle from '../styles/ia-button';
|
|
11
12
|
import './remove-items-modal-content';
|
|
12
13
|
|
|
@@ -25,12 +26,12 @@ export class ManageBar extends LitElement {
|
|
|
25
26
|
/**
|
|
26
27
|
* Array of items that have been selected for management
|
|
27
28
|
*/
|
|
28
|
-
@property({ type:
|
|
29
|
+
@property({ type: Array }) selectedItems: Array<ManageableItem> = [];
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
|
-
*
|
|
32
|
+
* Which section of the profile page searches are for (e.g., uploads, reviews, ...)
|
|
32
33
|
*/
|
|
33
|
-
@property({ type: String })
|
|
34
|
+
@property({ type: String }) profileElement?: PageElementName;
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Whether to show the "Select All" button (default false)
|
|
@@ -105,6 +106,34 @@ export class ManageBar extends LitElement {
|
|
|
105
106
|
`;
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
/**
|
|
110
|
+
* Message to show in the manage view modal, depending on context.
|
|
111
|
+
*/
|
|
112
|
+
private get manageViewModalMsg(): string {
|
|
113
|
+
const pluralize = this.selectedItems.length > 1;
|
|
114
|
+
const subject = pluralize ? 'these items' : 'this item';
|
|
115
|
+
|
|
116
|
+
let listName = '';
|
|
117
|
+
|
|
118
|
+
switch (this.profileElement) {
|
|
119
|
+
case 'uploads':
|
|
120
|
+
listName = 'uploads list';
|
|
121
|
+
break;
|
|
122
|
+
case 'web_archives':
|
|
123
|
+
listName = 'web archives list';
|
|
124
|
+
break;
|
|
125
|
+
case 'favorites':
|
|
126
|
+
listName = 'favorites list';
|
|
127
|
+
break;
|
|
128
|
+
default:
|
|
129
|
+
return '';
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return msg(
|
|
133
|
+
str`Note: It may take a few minutes for ${subject} to stop appearing in your ${listName}.`,
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
108
137
|
private cancelClicked(): void {
|
|
109
138
|
this.dispatchEvent(new CustomEvent('cancel'));
|
|
110
139
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { css } from 'lit';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared styles for tile action buttons rendered in grid, list-detail, and
|
|
5
|
+
* list-compact display modes. Layout positioning is handled by each tile
|
|
6
|
+
* component; these styles cover only the button appearance and the row
|
|
7
|
+
* container's default flex behavior.
|
|
8
|
+
*
|
|
9
|
+
* Customizable via CSS custom properties:
|
|
10
|
+
* - `--tileActionColor` (default: #d9534f)
|
|
11
|
+
* - `--tileActionBg` (default: #fff)
|
|
12
|
+
* - `--tileActionBorderColor` (default: #d9534f)
|
|
13
|
+
* - `--tileActionHoverBg` (default: rgba(217, 83, 79, 0.1))
|
|
14
|
+
* - `--tileActionHoverColor` (defaults to --tileActionColor)
|
|
15
|
+
*/
|
|
16
|
+
export const tileActionStyles = css`
|
|
17
|
+
.tile-actions {
|
|
18
|
+
flex-shrink: 0;
|
|
19
|
+
display: flex;
|
|
20
|
+
gap: var(--tileActionGap, 0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.tile-action-btn {
|
|
24
|
+
flex: 1;
|
|
25
|
+
padding: 6px 5px;
|
|
26
|
+
border: 2px solid var(--tileActionBorderColor, #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, #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(--tileActionHoverBg, rgba(217, 83, 79, 0.2));
|
|
50
|
+
color: var(--tileActionHoverColor, var(--tileActionColor, #d9534f));
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { LitElement, PropertyValues } from 'lit';
|
|
1
|
+
import { html, LitElement, nothing, PropertyValues, TemplateResult } from 'lit';
|
|
2
2
|
import { property } from 'lit/decorators.js';
|
|
3
3
|
import type { SortParam } from '@internetarchive/search-service';
|
|
4
4
|
import { TileDisplayValueProvider } from './tile-display-value-provider';
|
|
5
5
|
import type { TileModel } from '../models';
|
|
6
6
|
import { DateFormat, formatDate } from '../utils/format-date';
|
|
7
|
+
import type { TileAction } from './models';
|
|
7
8
|
|
|
8
9
|
export abstract class BaseTileComponent extends LitElement {
|
|
9
10
|
@property({ type: Object }) model?: TileModel;
|
|
10
11
|
|
|
12
|
+
/** Action buttons to display on this tile (rendered by subclasses) */
|
|
13
|
+
@property({ type: Array }) tileActions: TileAction[] = [];
|
|
14
|
+
|
|
11
15
|
@property({ type: Number }) currentWidth?: number;
|
|
12
16
|
|
|
13
17
|
@property({ type: Number }) currentHeight?: number;
|
|
@@ -62,4 +66,56 @@ export abstract class BaseTileComponent extends LitElement {
|
|
|
62
66
|
const { useLocalTime } = this;
|
|
63
67
|
return formatDate(date, format, { useLocalTime });
|
|
64
68
|
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Renders the action buttons configured for this tile, or `nothing` if
|
|
72
|
+
* there are none. Optional `extraClass` is appended to the container's
|
|
73
|
+
* class list so subclasses can target their own layout tweaks.
|
|
74
|
+
*/
|
|
75
|
+
protected renderTileActions(
|
|
76
|
+
extraClass: string = '',
|
|
77
|
+
): TemplateResult | typeof nothing {
|
|
78
|
+
if (!this.tileActions.length) return nothing;
|
|
79
|
+
|
|
80
|
+
const containerClass = extraClass
|
|
81
|
+
? `tile-actions ${extraClass}`
|
|
82
|
+
: 'tile-actions';
|
|
83
|
+
return html`
|
|
84
|
+
<div class=${containerClass}>
|
|
85
|
+
${this.tileActions.map(
|
|
86
|
+
action => html`
|
|
87
|
+
<button
|
|
88
|
+
class="tile-action-btn"
|
|
89
|
+
@click=${(e: Event) => this.handleTileActionClick(e, action)}
|
|
90
|
+
>
|
|
91
|
+
${action.label}
|
|
92
|
+
</button>
|
|
93
|
+
`,
|
|
94
|
+
)}
|
|
95
|
+
</div>
|
|
96
|
+
`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Click handler for tile action buttons. Stops propagation so the click
|
|
101
|
+
* doesn't activate a wrapping tile link, and dispatches a
|
|
102
|
+
* `tileActionClicked` event (bubbling + composed) carrying the action ID
|
|
103
|
+
* and the tile model.
|
|
104
|
+
*/
|
|
105
|
+
protected handleTileActionClick(e: Event, action: TileAction): void {
|
|
106
|
+
e.preventDefault();
|
|
107
|
+
e.stopPropagation();
|
|
108
|
+
// Pre-set the hover pane controller's clicking flag so that focus
|
|
109
|
+
// restoration after a consumer-opened modal won't trigger the hover pane.
|
|
110
|
+
this.dispatchEvent(
|
|
111
|
+
new PointerEvent('pointerdown', { bubbles: true, composed: true }),
|
|
112
|
+
);
|
|
113
|
+
this.dispatchEvent(
|
|
114
|
+
new CustomEvent('tileActionClicked', {
|
|
115
|
+
detail: { actionId: action.id, model: this.model },
|
|
116
|
+
bubbles: true,
|
|
117
|
+
composed: true,
|
|
118
|
+
}),
|
|
119
|
+
);
|
|
120
|
+
}
|
|
65
121
|
}
|
|
@@ -24,6 +24,7 @@ export class ItemTile extends BaseTileComponent {
|
|
|
24
24
|
/*
|
|
25
25
|
* Reactive properties inherited from BaseTileComponent:
|
|
26
26
|
* - model?: TileModel;
|
|
27
|
+
* - tileActions: TileAction[] = [];
|
|
27
28
|
* - currentWidth?: number;
|
|
28
29
|
* - currentHeight?: number;
|
|
29
30
|
* - baseNavigationUrl?: string;
|
|
@@ -1,86 +1,106 @@
|
|
|
1
|
-
import { css, html } from 'lit';
|
|
2
|
-
import { customElement } from 'lit/decorators.js';
|
|
3
|
-
import { msg } from '@lit/localize';
|
|
4
|
-
import { BaseTileComponent } from '../base-tile-component';
|
|
5
|
-
|
|
6
|
-
@customElement('tile-list-compact-header')
|
|
7
|
-
export class TileListCompactHeader extends BaseTileComponent {
|
|
8
|
-
/*
|
|
9
|
-
* Reactive properties inherited from BaseTileComponent:
|
|
10
|
-
* - model?: TileModel;
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
16
|
-
* -
|
|
17
|
-
* -
|
|
18
|
-
* -
|
|
19
|
-
* -
|
|
20
|
-
* -
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
<div id="
|
|
30
|
-
|
|
31
|
-
</div>
|
|
32
|
-
<div id="
|
|
33
|
-
<div id="
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
return
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
font-size:
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
#views {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
#list-line-header.
|
|
82
|
-
grid-template-columns:
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
1
|
+
import { css, html, nothing } from 'lit';
|
|
2
|
+
import { customElement } from 'lit/decorators.js';
|
|
3
|
+
import { msg } from '@lit/localize';
|
|
4
|
+
import { BaseTileComponent } from '../base-tile-component';
|
|
5
|
+
|
|
6
|
+
@customElement('tile-list-compact-header')
|
|
7
|
+
export class TileListCompactHeader extends BaseTileComponent {
|
|
8
|
+
/*
|
|
9
|
+
* Reactive properties inherited from BaseTileComponent:
|
|
10
|
+
* - model?: TileModel;
|
|
11
|
+
* - tileActions: TileAction[] = [];
|
|
12
|
+
* - currentWidth?: number;
|
|
13
|
+
* - currentHeight?: number;
|
|
14
|
+
* - baseNavigationUrl?: string;
|
|
15
|
+
* - baseImageUrl?: string;
|
|
16
|
+
* - collectionPagePath?: string;
|
|
17
|
+
* - sortParam: SortParam | null = null;
|
|
18
|
+
* - creatorFilter?: string;
|
|
19
|
+
* - mobileBreakpoint?: number;
|
|
20
|
+
* - loggedIn = false;
|
|
21
|
+
* - suppressBlurring = false;
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
render() {
|
|
25
|
+
const hasActions = this.tileActions.length > 0;
|
|
26
|
+
const headerClasses = `${this.classSize}${hasActions ? ' has-actions' : ''}`;
|
|
27
|
+
return html`
|
|
28
|
+
<div id="list-line-header" class="${headerClasses}">
|
|
29
|
+
<div id="thumb"></div>
|
|
30
|
+
${hasActions ? html`<div id="actions-header"></div>` : nothing}
|
|
31
|
+
<div id="title">${msg('Title')}</div>
|
|
32
|
+
<div id="creator">${msg('Creator')}</div>
|
|
33
|
+
<div id="date">
|
|
34
|
+
${this.displayValueProvider.dateLabel || msg('Published')}
|
|
35
|
+
</div>
|
|
36
|
+
<div id="icon">${msg('Type')}</div>
|
|
37
|
+
<div id="views">${this.displayValueProvider.viewsLabel}</div>
|
|
38
|
+
</div>
|
|
39
|
+
`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private get classSize(): string {
|
|
43
|
+
if (
|
|
44
|
+
this.mobileBreakpoint &&
|
|
45
|
+
this.currentWidth &&
|
|
46
|
+
this.currentWidth < this.mobileBreakpoint
|
|
47
|
+
) {
|
|
48
|
+
return 'mobile';
|
|
49
|
+
}
|
|
50
|
+
return 'desktop';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static get styles() {
|
|
54
|
+
return css`
|
|
55
|
+
html {
|
|
56
|
+
font-size: unset;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
div {
|
|
60
|
+
font-size: 14px;
|
|
61
|
+
font-weight: bold;
|
|
62
|
+
line-height: 20px;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.mobile #views {
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
#views {
|
|
70
|
+
text-align: right;
|
|
71
|
+
padding-right: 8px;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
#list-line-header {
|
|
75
|
+
display: grid;
|
|
76
|
+
column-gap: 10px;
|
|
77
|
+
align-items: flex-end;
|
|
78
|
+
padding-bottom: 2px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#list-line-header.mobile {
|
|
82
|
+
grid-template-columns: 36px 3fr 2fr 68px 35px;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
#list-line-header.desktop {
|
|
86
|
+
grid-template-columns: 51px 3fr 2fr 95px 30px 115px;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/*
|
|
90
|
+
* When tile actions are present in the rows below, reserve a matching
|
|
91
|
+
* column here so the columns stay aligned with each row.
|
|
92
|
+
*/
|
|
93
|
+
#list-line-header.mobile.has-actions {
|
|
94
|
+
grid-template-columns:
|
|
95
|
+
36px var(--tileActionColumnWidth, 90px) 3fr 2fr
|
|
96
|
+
68px 35px;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
#list-line-header.desktop.has-actions {
|
|
100
|
+
grid-template-columns:
|
|
101
|
+
51px var(--tileActionColumnWidth, 100px) 3fr 2fr
|
|
102
|
+
95px 30px 115px;
|
|
103
|
+
}
|
|
104
|
+
`;
|
|
105
|
+
}
|
|
106
|
+
}
|