@internetarchive/elements 0.2.2 → 0.2.3-alpha-webdev8378.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.
@@ -0,0 +1,105 @@
1
+ import { LitElement, TemplateResult } from 'lit';
2
+ import type { AdvancedSearchStyle, SearchCategory } from './models.js';
3
+ import '@internetarchive/ia-clearable-text-input';
4
+ import '@internetarchive/ia-dropdown';
5
+ import '../../elements/ia-status-indicator/ia-status-indicator.js';
6
+ export declare class IADropdownSearchBar extends LitElement {
7
+ /** ID used for the special Advanced Search dropdown option */
8
+ static readonly ADVANCED_SEARCH_OPTION_ID = "__advanced_search__";
9
+ /** The query that appears in the search bar */
10
+ query?: string;
11
+ /** Dropdown menu options (tab IDs + labels) */
12
+ categories: SearchCategory[];
13
+ /** The currently selected dropdown category ID */
14
+ selectedCategory?: string;
15
+ /** The base URL for internal navigation within the site */
16
+ navBaseUrl?: string;
17
+ /**
18
+ * Where to display the Advanced Search option:
19
+ * - `link` (default): as a text link below the search bar
20
+ * - `dropdown`: as an item at the bottom of the category dropdown
21
+ * - `none`: hidden entirely
22
+ */
23
+ advancedSearchStyle: AdvancedSearchStyle;
24
+ /** Placeholder text for the search input */
25
+ placeholder: string;
26
+ /** Whether to use the mobile layout */
27
+ useMobileView: boolean;
28
+ /** Whether to hide the category dropdown to the left of the search bar */
29
+ hideDropdown: boolean;
30
+ /** Whether the search button should show its loading state */
31
+ loading: boolean;
32
+ private searchInput;
33
+ /** The effective selected category, falling back to the first in the list. */
34
+ private get resolvedCategory();
35
+ render(): TemplateResult;
36
+ /**
37
+ * Template for the category dropdown on the left side of the search bar.
38
+ */
39
+ private get dropdownTemplate();
40
+ /**
41
+ * Template for the main text entry box of the search bar.
42
+ */
43
+ private get textBoxTemplate();
44
+ /**
45
+ * Template for the "magnifying glass" search button to the right of the search bar.
46
+ */
47
+ private get searchButtonTemplate();
48
+ /**
49
+ * Converts the `categories` array into the `optionInterface[]` format
50
+ * expected by `ia-dropdown`.
51
+ */
52
+ private get dropdownOptions();
53
+ /**
54
+ * Builds the Advanced Search URL using the given query string and the
55
+ * provided `navBaseUrl`. Returns `undefined` if no `navBaseUrl` is set.
56
+ */
57
+ private buildAdvancedSearchUrl;
58
+ /**
59
+ * The display label for the currently selected category.
60
+ */
61
+ private get selectedCategoryLabel();
62
+ /**
63
+ * The current search query with +'s replaced by spaces.
64
+ */
65
+ private get spacedQuery();
66
+ /**
67
+ * Template for the search links area beneath the search bar
68
+ * (Advanced Search link and any slotted content).
69
+ */
70
+ private get searchLinksTemplate();
71
+ /**
72
+ * Template for the "Advanced Search" link, built from `navBaseUrl` and
73
+ * the current query. Only rendered when `advancedSearchStyle` is `'link'`.
74
+ */
75
+ private get advancedSearchTemplate();
76
+ /**
77
+ * Handler for when the search bar's clear button is pressed.
78
+ */
79
+ private searchFieldCleared;
80
+ /**
81
+ * Handler for Enter key or search button click.
82
+ */
83
+ private handleSubmit;
84
+ /**
85
+ * Handler for when the user selects a category from the dropdown.
86
+ *
87
+ * Sets `selectedCategory` locally for immediate visual feedback (semi-controlled
88
+ * pattern). The parent also binds this property and may re-set it on re-render.
89
+ */
90
+ private handleCategorySelected;
91
+ /**
92
+ * Navigates the browser to the Advanced Search page with the current query.
93
+ */
94
+ private navigateToAdvancedSearch;
95
+ /**
96
+ * Handler for clicks on the advanced search link/option
97
+ */
98
+ private advancedSearchClicked;
99
+ /**
100
+ * Emits a `searchRequested` event with the current query and category.
101
+ */
102
+ private emitSearchRequested;
103
+ static get styles(): import("lit").CSSResult[];
104
+ }
105
+ //# sourceMappingURL=ia-dropdown-search-bar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ia-dropdown-search-bar.d.ts","sourceRoot":"","sources":["../../../../src/elements/ia-dropdown-search-bar/ia-dropdown-search-bar.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,UAAU,EAAW,cAAc,EAAE,MAAM,KAAK,CAAC;AAIrE,OAAO,KAAK,EACV,mBAAmB,EACnB,cAAc,EAEf,MAAM,UAAU,CAAC;AAKlB,OAAO,0CAA0C,CAAC;AAClD,OAAO,8BAA8B,CAAC;AACtC,OAAO,uDAAuD,CAAC;AAW/D,qBACa,mBAAoB,SAAQ,UAAU;IACjD,8DAA8D;IAC9D,MAAM,CAAC,QAAQ,CAAC,yBAAyB,yBAAyB;IAElE,+CAA+C;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IAE3C,+CAA+C;IACpB,UAAU,EAAE,cAAc,EAAE,CAAM;IAE7D,kDAAkD;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAEtD,2DAA2D;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IAEhD;;;;;OAKG;IACyB,mBAAmB,EAAE,mBAAmB,CAAU;IAE9E,4CAA4C;IAChB,WAAW,SAAiB;IAExD,uCAAuC;IACV,aAAa,UAAS;IAEnD,0EAA0E;IAC7C,YAAY,UAAS;IAElD,8DAA8D;IACjC,OAAO,UAAS;IAG7C,OAAO,CAAC,WAAW,CAAwB;IAE3C,8EAA8E;IAC9E,OAAO,KAAK,gBAAgB,GAE3B;IAED,MAAM,IAAI,cAAc;IAgBxB;;OAEG;IACH,OAAO,KAAK,gBAAgB,GAkB3B;IAED;;OAEG;IACH,OAAO,KAAK,eAAe,GAe1B;IAED;;OAEG;IACH,OAAO,KAAK,oBAAoB,GAkB/B;IAED;;;OAGG;IACH,OAAO,KAAK,eAAe,GAoB1B;IAED;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAM9B;;OAEG;IACH,OAAO,KAAK,qBAAqB,GAGhC;IAED;;OAEG;IACH,OAAO,KAAK,WAAW,GAEtB;IAED;;;OAGG;IACH,OAAO,KAAK,mBAAmB,GAiB9B;IAED;;;OAGG;IACH,OAAO,KAAK,sBAAsB,GAcjC;IAED;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAM1B;;OAEG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAwB9B;;OAEG;IACH,OAAO,CAAC,wBAAwB;IAahC;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAI7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAW3B,MAAM,KAAK,MAAM,8BA+KhB;CACF"}
@@ -0,0 +1,483 @@
1
+ var IADropdownSearchBar_1;
2
+ import { __decorate } from "tslib";
3
+ import { msg } from '@lit/localize';
4
+ import { css, html, LitElement, nothing } from 'lit';
5
+ import { customElement, property, query } from 'lit/decorators.js';
6
+ import themeStyles from '../../themes/theme-styles.js';
7
+ import searchIcon from './search.svg';
8
+ import '@internetarchive/ia-clearable-text-input';
9
+ import '@internetarchive/ia-dropdown';
10
+ import '../../elements/ia-status-indicator/ia-status-indicator.js';
11
+ /**
12
+ * Event names emitted by this component
13
+ */
14
+ const Events = {
15
+ AdvancedSearchClicked: 'advancedSearchClicked',
16
+ CategoryChanged: 'categoryChanged',
17
+ SearchRequested: 'searchRequested',
18
+ };
19
+ let IADropdownSearchBar = IADropdownSearchBar_1 = class IADropdownSearchBar extends LitElement {
20
+ constructor() {
21
+ super(...arguments);
22
+ /** Dropdown menu options (tab IDs + labels) */
23
+ this.categories = [];
24
+ /**
25
+ * Where to display the Advanced Search option:
26
+ * - `link` (default): as a text link below the search bar
27
+ * - `dropdown`: as an item at the bottom of the category dropdown
28
+ * - `none`: hidden entirely
29
+ */
30
+ this.advancedSearchStyle = 'link';
31
+ /** Placeholder text for the search input */
32
+ this.placeholder = msg('Search');
33
+ /** Whether to use the mobile layout */
34
+ this.useMobileView = false;
35
+ /** Whether to hide the category dropdown to the left of the search bar */
36
+ this.hideDropdown = false;
37
+ /** Whether the search button should show its loading state */
38
+ this.loading = false;
39
+ }
40
+ /** The effective selected category, falling back to the first in the list. */
41
+ get resolvedCategory() {
42
+ return this.selectedCategory ?? this.categories[0]?.id ?? '';
43
+ }
44
+ render() {
45
+ return html `
46
+ <div id="container" part="container" role="search">
47
+ <div
48
+ id="main-bar"
49
+ part="main-bar"
50
+ class=${this.hideDropdown ? 'no-dropdown' : nothing}
51
+ >
52
+ ${this.hideDropdown ? nothing : this.dropdownTemplate}
53
+ ${this.textBoxTemplate} ${this.searchButtonTemplate}
54
+ </div>
55
+ ${this.searchLinksTemplate}
56
+ </div>
57
+ `;
58
+ }
59
+ /**
60
+ * Template for the category dropdown on the left side of the search bar.
61
+ */
62
+ get dropdownTemplate() {
63
+ return html `
64
+ <ia-dropdown
65
+ id="category-dropdown"
66
+ part="category-dropdown"
67
+ displayCaret
68
+ includeSelectedOption
69
+ closeOnSelect
70
+ closeOnEscape
71
+ closeOnBackdropClick
72
+ openViaButton
73
+ .selectedOption=${this.resolvedCategory}
74
+ .options=${this.dropdownOptions}
75
+ @optionSelected=${this.handleCategorySelected}
76
+ >
77
+ <span slot="dropdown-label">${this.selectedCategoryLabel}</span>
78
+ </ia-dropdown>
79
+ `;
80
+ }
81
+ /**
82
+ * Template for the main text entry box of the search bar.
83
+ */
84
+ get textBoxTemplate() {
85
+ return html `
86
+ <ia-clearable-text-input
87
+ id="search-input"
88
+ part="search-input"
89
+ .value=${this.spacedQuery}
90
+ placeholder=${this.placeholder}
91
+ clearButtonScreenReaderLabel=${msg('Clear search query')}
92
+ screenReaderLabel=${msg('Search the Archive. Filters and Advanced Search available below.')}
93
+ @clear=${this.searchFieldCleared}
94
+ @submit=${this.handleSubmit}
95
+ ></ia-clearable-text-input>
96
+ `;
97
+ }
98
+ /**
99
+ * Template for the "magnifying glass" search button to the right of the search bar.
100
+ */
101
+ get searchButtonTemplate() {
102
+ return html `
103
+ <button
104
+ id="search-button"
105
+ part="search-button"
106
+ class=${this.loading ? 'loading' : nothing}
107
+ type="button"
108
+ aria-label=${msg('Search')}
109
+ @click=${this.handleSubmit}
110
+ >
111
+ ${this.loading
112
+ ? html `<ia-status-indicator
113
+ mode="loading"
114
+ class="search-button-loading-icon"
115
+ ></ia-status-indicator>`
116
+ : html `<img src=${searchIcon} alt="" />`}
117
+ </button>
118
+ `;
119
+ }
120
+ /**
121
+ * Converts the `categories` array into the `optionInterface[]` format
122
+ * expected by `ia-dropdown`.
123
+ */
124
+ get dropdownOptions() {
125
+ const options = this.categories.map((cat) => ({
126
+ id: cat.id,
127
+ label: html `<span>${cat.label}</span>`,
128
+ }));
129
+ if (this.advancedSearchStyle === 'dropdown' &&
130
+ this.navBaseUrl !== undefined) {
131
+ options.push({
132
+ id: IADropdownSearchBar_1.ADVANCED_SEARCH_OPTION_ID,
133
+ // Add a separator border above the Advanced Search option
134
+ label: html `<span style="border-top: 1px solid #999;">
135
+ ${msg('Go to Advanced Search...')}
136
+ </span>`,
137
+ });
138
+ }
139
+ return options;
140
+ }
141
+ /**
142
+ * Builds the Advanced Search URL using the given query string and the
143
+ * provided `navBaseUrl`. Returns `undefined` if no `navBaseUrl` is set.
144
+ */
145
+ buildAdvancedSearchUrl(query) {
146
+ if (this.navBaseUrl === undefined)
147
+ return undefined;
148
+ const queryArg = query ? `?q=${encodeURIComponent(query)}` : '';
149
+ return `${this.navBaseUrl}/advancedsearch.php${queryArg}`;
150
+ }
151
+ /**
152
+ * The display label for the currently selected category.
153
+ */
154
+ get selectedCategoryLabel() {
155
+ const match = this.categories.find((c) => c.id === this.resolvedCategory);
156
+ return match?.label ?? this.resolvedCategory;
157
+ }
158
+ /**
159
+ * The current search query with +'s replaced by spaces.
160
+ */
161
+ get spacedQuery() {
162
+ return this.query?.replace(/\+/g, ' ') ?? '';
163
+ }
164
+ /**
165
+ * Template for the search links area beneath the search bar
166
+ * (Advanced Search link and any slotted content).
167
+ */
168
+ get searchLinksTemplate() {
169
+ return html `
170
+ <div id="search-links-area">
171
+ <slot name="before-search-links"></slot>
172
+ <div
173
+ id="search-links"
174
+ part="search-links"
175
+ class=${this.useMobileView ? 'mobile' : nothing}
176
+ >
177
+ <slot name="search-links-top"></slot>
178
+ ${this.advancedSearchTemplate}
179
+ <div id="search-links-end">
180
+ <slot name="search-links"></slot>
181
+ </div>
182
+ </div>
183
+ </div>
184
+ `;
185
+ }
186
+ /**
187
+ * Template for the "Advanced Search" link, built from `navBaseUrl` and
188
+ * the current query. Only rendered when `advancedSearchStyle` is `'link'`.
189
+ */
190
+ get advancedSearchTemplate() {
191
+ if (this.advancedSearchStyle !== 'link')
192
+ return nothing;
193
+ const href = this.buildAdvancedSearchUrl(this.query ?? '');
194
+ if (!href)
195
+ return nothing;
196
+ return html `<a
197
+ id="advanced-search-link"
198
+ part="advanced-search-link"
199
+ href=${href}
200
+ @click=${this.advancedSearchClicked}
201
+ >
202
+ ${msg('Advanced Search')}
203
+ </a>`;
204
+ }
205
+ /**
206
+ * Handler for when the search bar's clear button is pressed.
207
+ */
208
+ searchFieldCleared() {
209
+ if (this.query) {
210
+ this.emitSearchRequested();
211
+ }
212
+ }
213
+ /**
214
+ * Handler for Enter key or search button click.
215
+ */
216
+ handleSubmit() {
217
+ this.emitSearchRequested();
218
+ }
219
+ /**
220
+ * Handler for when the user selects a category from the dropdown.
221
+ *
222
+ * Sets `selectedCategory` locally for immediate visual feedback (semi-controlled
223
+ * pattern). The parent also binds this property and may re-set it on re-render.
224
+ */
225
+ handleCategorySelected(e) {
226
+ const newCategoryId = e.detail.option.id;
227
+ if (newCategoryId === IADropdownSearchBar_1.ADVANCED_SEARCH_OPTION_ID) {
228
+ this.navigateToAdvancedSearch();
229
+ return;
230
+ }
231
+ if (newCategoryId === this.resolvedCategory)
232
+ return;
233
+ this.selectedCategory = newCategoryId;
234
+ // On next tick, focus the text input bar (seemingly fails in Safari without the delay)
235
+ setTimeout(() => this.searchInput.focus());
236
+ this.dispatchEvent(new CustomEvent(Events.CategoryChanged, {
237
+ detail: newCategoryId,
238
+ }));
239
+ }
240
+ /**
241
+ * Navigates the browser to the Advanced Search page with the current query.
242
+ */
243
+ navigateToAdvancedSearch() {
244
+ // Schedule a re-render so ia-dropdown resets its internal selectedOption
245
+ // back to the real category (in case navigation is delayed or prevented)
246
+ this.requestUpdate();
247
+ const query = this.searchInput?.value ?? this.query ?? '';
248
+ const href = this.buildAdvancedSearchUrl(query);
249
+ if (!href)
250
+ return;
251
+ this.advancedSearchClicked();
252
+ window.location.href = href;
253
+ }
254
+ /**
255
+ * Handler for clicks on the advanced search link/option
256
+ */
257
+ advancedSearchClicked() {
258
+ this.dispatchEvent(new CustomEvent(Events.AdvancedSearchClicked));
259
+ }
260
+ /**
261
+ * Emits a `searchRequested` event with the current query and category.
262
+ */
263
+ emitSearchRequested() {
264
+ this.dispatchEvent(new CustomEvent(Events.SearchRequested, {
265
+ detail: {
266
+ query: this.searchInput.value,
267
+ category: this.resolvedCategory,
268
+ },
269
+ }));
270
+ }
271
+ static get styles() {
272
+ const ownStyles = css `
273
+ :host {
274
+ --search-bar-height--: var(--search-bar-height, 30px);
275
+ --search-bar-width--: var(--search-bar-width, 300px);
276
+ --search-bar-internal-padding--: var(--padding-sm, 5px);
277
+ --clear-button-offset--: var(--clear-button-offset, 0);
278
+ }
279
+
280
+ #container {
281
+ display: inline-block;
282
+ width: var(--search-bar-width--);
283
+ }
284
+
285
+ #main-bar {
286
+ display: flex;
287
+ height: var(--search-bar-height--, 30px);
288
+ margin-bottom: 10px;
289
+ flex: 1;
290
+ }
291
+
292
+ #category-dropdown {
293
+ display: flex;
294
+ flex-shrink: 0;
295
+ height: 100%;
296
+ box-sizing: border-box;
297
+
298
+ background-color: #f5f5f7;
299
+ border: 1px solid #999;
300
+ border-radius: 5px 0 0 5px;
301
+
302
+ --dropdownMainButtonPadding: 0 var(--search-bar-internal-padding--, 5px);
303
+ --dropdownBgColor: #2c2c2c;
304
+ --dropdownTextColor: #fff;
305
+ --dropdownBorderColor: #ddd;
306
+ --dropdownCaretColor: var(--ia-theme-primary-text-color, #2c2c2c);
307
+ --dropdownHoverBgColor: rgba(255, 255, 255, 0.3);
308
+ --dropdownHoverTextColor: #fff;
309
+ --dropdownSelectedBgColor: rgba(255, 255, 255, 0.3);
310
+ --dropdownSelectedTextColor: #fff;
311
+ --dropdownWhiteSpace: nowrap;
312
+ --dropdownOffsetTop: 2px;
313
+ --caretHeight: 8px;
314
+ --caretWidth: 12px;
315
+ --caretPadding: 0 0 0 5px;
316
+ --dropdownFontSize: inherit;
317
+ --dropdownBorderRadius: 4px;
318
+ --buttonSlotPaddingRight: 0;
319
+ --dropdownTextAlign: left;
320
+ }
321
+
322
+ #category-dropdown [slot='dropdown-label'] {
323
+ color: var(--ia-theme-primary-text-color, #2c2c2c);
324
+ font-size: inherit;
325
+ font-family: inherit;
326
+ white-space: nowrap;
327
+ }
328
+
329
+ .no-dropdown #search-input {
330
+ border-left: 1px solid #999;
331
+ border-radius: 5px 0 0 5px;
332
+ overflow: hidden;
333
+ }
334
+
335
+ #search-input {
336
+ width: 100%;
337
+ height: 100%;
338
+ box-sizing: border-box;
339
+ border-top: 1px solid #999;
340
+ border-bottom: 1px solid #999;
341
+ font-size: inherit;
342
+
343
+ --input-height: calc(var(--search-bar-height--) - 2px);
344
+ --input-padding: 0 var(--search-bar-internal-padding--, 5px);
345
+ --input-background-color: var(
346
+ --ia-theme-secondary-background-color,
347
+ #fff
348
+ );
349
+ --input-border-radius: 0;
350
+ --input-border-width: 0;
351
+ --input-box-shadow: none;
352
+ --input-focused-box-shadow: none;
353
+ --input-font-size: auto;
354
+ --clear-button-top: var(--clear-button-offset--, 0);
355
+ --clear-button-right: 2px;
356
+ }
357
+
358
+ #search-button {
359
+ appearance: none;
360
+ box-sizing: border-box;
361
+ border-radius: 0 5px 5px 0;
362
+ background-color: var(--ia-theme-secondary-background-color, #fff);
363
+ border: 1px solid #999;
364
+ border-left: 0;
365
+ padding: 0 var(--search-bar-internal-padding--, 5px) 0 5px;
366
+ min-width: 30px;
367
+ height: 100%;
368
+ cursor: pointer;
369
+ display: flex;
370
+ align-items: center;
371
+ justify-content: center;
372
+ flex-shrink: 0;
373
+ }
374
+
375
+ #search-button img {
376
+ width: 18px;
377
+ height: 18px;
378
+ }
379
+
380
+ .search-button-loading-icon {
381
+ --icon-width: 20px;
382
+ margin-top: 2px;
383
+ }
384
+
385
+ #search-links-area {
386
+ display: flex;
387
+ align-items: flex-start;
388
+ justify-content: space-between;
389
+ margin-top: 5px;
390
+ font-size: inherit;
391
+ }
392
+
393
+ #search-links {
394
+ display: flex;
395
+ column-gap: 10px;
396
+ width: 100%;
397
+ }
398
+
399
+ #search-links > a:not(:last-child) {
400
+ margin-bottom: 2px;
401
+ }
402
+
403
+ #advanced-search-link {
404
+ margin-left: auto;
405
+ padding-left: 5px;
406
+ }
407
+
408
+ #search-links-end {
409
+ display: contents;
410
+ }
411
+
412
+ .mobile #advanced-search-link {
413
+ margin-left: 0;
414
+ }
415
+
416
+ .mobile #search-links-end {
417
+ display: flex;
418
+ margin-left: auto;
419
+ column-gap: 10px;
420
+ }
421
+
422
+ a:link {
423
+ text-decoration: none;
424
+ display: block;
425
+ flex: 0 1 auto;
426
+ color: var(--ia-theme-link-color, #4b64ff);
427
+ white-space: nowrap;
428
+ }
429
+
430
+ a:hover {
431
+ text-decoration: underline;
432
+ }
433
+
434
+ a:visited {
435
+ color: var(--ia-theme-link-color, #4b64ff);
436
+ }
437
+
438
+ ::slotted(#action-bar-spacing) {
439
+ --iconLabelGutterWidth: 3px;
440
+ margin-top: -4px; /* Better icon alignment */
441
+ height: fit-content;
442
+ }
443
+ `;
444
+ return [themeStyles, ownStyles];
445
+ }
446
+ };
447
+ /** ID used for the special Advanced Search dropdown option */
448
+ IADropdownSearchBar.ADVANCED_SEARCH_OPTION_ID = '__advanced_search__';
449
+ __decorate([
450
+ property({ type: String })
451
+ ], IADropdownSearchBar.prototype, "query", void 0);
452
+ __decorate([
453
+ property({ type: Array })
454
+ ], IADropdownSearchBar.prototype, "categories", void 0);
455
+ __decorate([
456
+ property({ type: String })
457
+ ], IADropdownSearchBar.prototype, "selectedCategory", void 0);
458
+ __decorate([
459
+ property({ type: String })
460
+ ], IADropdownSearchBar.prototype, "navBaseUrl", void 0);
461
+ __decorate([
462
+ property({ type: String })
463
+ ], IADropdownSearchBar.prototype, "advancedSearchStyle", void 0);
464
+ __decorate([
465
+ property({ type: String })
466
+ ], IADropdownSearchBar.prototype, "placeholder", void 0);
467
+ __decorate([
468
+ property({ type: Boolean })
469
+ ], IADropdownSearchBar.prototype, "useMobileView", void 0);
470
+ __decorate([
471
+ property({ type: Boolean })
472
+ ], IADropdownSearchBar.prototype, "hideDropdown", void 0);
473
+ __decorate([
474
+ property({ type: Boolean })
475
+ ], IADropdownSearchBar.prototype, "loading", void 0);
476
+ __decorate([
477
+ query('#search-input')
478
+ ], IADropdownSearchBar.prototype, "searchInput", void 0);
479
+ IADropdownSearchBar = IADropdownSearchBar_1 = __decorate([
480
+ customElement('ia-dropdown-search-bar')
481
+ ], IADropdownSearchBar);
482
+ export { IADropdownSearchBar };
483
+ //# sourceMappingURL=ia-dropdown-search-bar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ia-dropdown-search-bar.js","sourceRoot":"","sources":["../../../../src/elements/ia-dropdown-search-bar/ia-dropdown-search-bar.ts"],"names":[],"mappings":"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","sourcesContent":["import { msg } from '@lit/localize';\r\nimport { css, html, LitElement, nothing, TemplateResult } from 'lit';\r\nimport { customElement, property, query } from 'lit/decorators.js';\r\nimport type { IaClearableTextInput } from '@internetarchive/ia-clearable-text-input';\r\nimport type { optionInterface } from '@internetarchive/ia-dropdown';\r\nimport type {\r\n AdvancedSearchStyle,\r\n SearchCategory,\r\n SearchRequestedDetail,\r\n} from './models';\r\n\r\nimport themeStyles from '@src/themes/theme-styles';\r\nimport searchIcon from './search.svg';\r\n\r\nimport '@internetarchive/ia-clearable-text-input';\r\nimport '@internetarchive/ia-dropdown';\r\nimport '@src/elements/ia-status-indicator/ia-status-indicator';\r\n\r\n/**\r\n * Event names emitted by this component\r\n */\r\nconst Events = {\r\n AdvancedSearchClicked: 'advancedSearchClicked',\r\n CategoryChanged: 'categoryChanged',\r\n SearchRequested: 'searchRequested',\r\n};\r\n\r\n@customElement('ia-dropdown-search-bar')\r\nexport class IADropdownSearchBar extends LitElement {\r\n /** ID used for the special Advanced Search dropdown option */\r\n static readonly ADVANCED_SEARCH_OPTION_ID = '__advanced_search__';\r\n\r\n /** The query that appears in the search bar */\r\n @property({ type: String }) query?: string;\r\n\r\n /** Dropdown menu options (tab IDs + labels) */\r\n @property({ type: Array }) categories: SearchCategory[] = [];\r\n\r\n /** The currently selected dropdown category ID */\r\n @property({ type: String }) selectedCategory?: string;\r\n\r\n /** The base URL for internal navigation within the site */\r\n @property({ type: String }) navBaseUrl?: string;\r\n\r\n /**\r\n * Where to display the Advanced Search option:\r\n * - `link` (default): as a text link below the search bar\r\n * - `dropdown`: as an item at the bottom of the category dropdown\r\n * - `none`: hidden entirely\r\n */\r\n @property({ type: String }) advancedSearchStyle: AdvancedSearchStyle = 'link';\r\n\r\n /** Placeholder text for the search input */\r\n @property({ type: String }) placeholder = msg('Search');\r\n\r\n /** Whether to use the mobile layout */\r\n @property({ type: Boolean }) useMobileView = false;\r\n\r\n /** Whether to hide the category dropdown to the left of the search bar */\r\n @property({ type: Boolean }) hideDropdown = false;\r\n\r\n /** Whether the search button should show its loading state */\r\n @property({ type: Boolean }) loading = false;\r\n\r\n @query('#search-input')\r\n private searchInput!: IaClearableTextInput;\r\n\r\n /** The effective selected category, falling back to the first in the list. */\r\n private get resolvedCategory(): string {\r\n return this.selectedCategory ?? this.categories[0]?.id ?? '';\r\n }\r\n\r\n render(): TemplateResult {\r\n return html`\r\n <div id=\"container\" part=\"container\" role=\"search\">\r\n <div\r\n id=\"main-bar\"\r\n part=\"main-bar\"\r\n class=${this.hideDropdown ? 'no-dropdown' : nothing}\r\n >\r\n ${this.hideDropdown ? nothing : this.dropdownTemplate}\r\n ${this.textBoxTemplate} ${this.searchButtonTemplate}\r\n </div>\r\n ${this.searchLinksTemplate}\r\n </div>\r\n `;\r\n }\r\n\r\n /**\r\n * Template for the category dropdown on the left side of the search bar.\r\n */\r\n private get dropdownTemplate(): TemplateResult {\r\n return html`\r\n <ia-dropdown\r\n id=\"category-dropdown\"\r\n part=\"category-dropdown\"\r\n displayCaret\r\n includeSelectedOption\r\n closeOnSelect\r\n closeOnEscape\r\n closeOnBackdropClick\r\n openViaButton\r\n .selectedOption=${this.resolvedCategory}\r\n .options=${this.dropdownOptions}\r\n @optionSelected=${this.handleCategorySelected}\r\n >\r\n <span slot=\"dropdown-label\">${this.selectedCategoryLabel}</span>\r\n </ia-dropdown>\r\n `;\r\n }\r\n\r\n /**\r\n * Template for the main text entry box of the search bar.\r\n */\r\n private get textBoxTemplate(): TemplateResult {\r\n return html`\r\n <ia-clearable-text-input\r\n id=\"search-input\"\r\n part=\"search-input\"\r\n .value=${this.spacedQuery}\r\n placeholder=${this.placeholder}\r\n clearButtonScreenReaderLabel=${msg('Clear search query')}\r\n screenReaderLabel=${msg(\r\n 'Search the Archive. Filters and Advanced Search available below.',\r\n )}\r\n @clear=${this.searchFieldCleared}\r\n @submit=${this.handleSubmit}\r\n ></ia-clearable-text-input>\r\n `;\r\n }\r\n\r\n /**\r\n * Template for the \"magnifying glass\" search button to the right of the search bar.\r\n */\r\n private get searchButtonTemplate(): TemplateResult {\r\n return html`\r\n <button\r\n id=\"search-button\"\r\n part=\"search-button\"\r\n class=${this.loading ? 'loading' : nothing}\r\n type=\"button\"\r\n aria-label=${msg('Search')}\r\n @click=${this.handleSubmit}\r\n >\r\n ${this.loading\r\n ? html`<ia-status-indicator\r\n mode=\"loading\"\r\n class=\"search-button-loading-icon\"\r\n ></ia-status-indicator>`\r\n : html`<img src=${searchIcon} alt=\"\" />`}\r\n </button>\r\n `;\r\n }\r\n\r\n /**\r\n * Converts the `categories` array into the `optionInterface[]` format\r\n * expected by `ia-dropdown`.\r\n */\r\n private get dropdownOptions(): optionInterface[] {\r\n const options: optionInterface[] = this.categories.map((cat) => ({\r\n id: cat.id,\r\n label: html`<span>${cat.label}</span>`,\r\n }));\r\n\r\n if (\r\n this.advancedSearchStyle === 'dropdown' &&\r\n this.navBaseUrl !== undefined\r\n ) {\r\n options.push({\r\n id: IADropdownSearchBar.ADVANCED_SEARCH_OPTION_ID,\r\n // Add a separator border above the Advanced Search option\r\n label: html`<span style=\"border-top: 1px solid #999;\">\r\n ${msg('Go to Advanced Search...')}\r\n </span>`,\r\n });\r\n }\r\n\r\n return options;\r\n }\r\n\r\n /**\r\n * Builds the Advanced Search URL using the given query string and the\r\n * provided `navBaseUrl`. Returns `undefined` if no `navBaseUrl` is set.\r\n */\r\n private buildAdvancedSearchUrl(query: string): string | undefined {\r\n if (this.navBaseUrl === undefined) return undefined;\r\n const queryArg = query ? `?q=${encodeURIComponent(query)}` : '';\r\n return `${this.navBaseUrl}/advancedsearch.php${queryArg}`;\r\n }\r\n\r\n /**\r\n * The display label for the currently selected category.\r\n */\r\n private get selectedCategoryLabel(): string {\r\n const match = this.categories.find((c) => c.id === this.resolvedCategory);\r\n return match?.label ?? this.resolvedCategory;\r\n }\r\n\r\n /**\r\n * The current search query with +'s replaced by spaces.\r\n */\r\n private get spacedQuery(): string {\r\n return this.query?.replace(/\\+/g, ' ') ?? '';\r\n }\r\n\r\n /**\r\n * Template for the search links area beneath the search bar\r\n * (Advanced Search link and any slotted content).\r\n */\r\n private get searchLinksTemplate(): TemplateResult {\r\n return html`\r\n <div id=\"search-links-area\">\r\n <slot name=\"before-search-links\"></slot>\r\n <div\r\n id=\"search-links\"\r\n part=\"search-links\"\r\n class=${this.useMobileView ? 'mobile' : nothing}\r\n >\r\n <slot name=\"search-links-top\"></slot>\r\n ${this.advancedSearchTemplate}\r\n <div id=\"search-links-end\">\r\n <slot name=\"search-links\"></slot>\r\n </div>\r\n </div>\r\n </div>\r\n `;\r\n }\r\n\r\n /**\r\n * Template for the \"Advanced Search\" link, built from `navBaseUrl` and\r\n * the current query. Only rendered when `advancedSearchStyle` is `'link'`.\r\n */\r\n private get advancedSearchTemplate(): TemplateResult | typeof nothing {\r\n if (this.advancedSearchStyle !== 'link') return nothing;\r\n\r\n const href = this.buildAdvancedSearchUrl(this.query ?? '');\r\n if (!href) return nothing;\r\n\r\n return html`<a\r\n id=\"advanced-search-link\"\r\n part=\"advanced-search-link\"\r\n href=${href}\r\n @click=${this.advancedSearchClicked}\r\n >\r\n ${msg('Advanced Search')}\r\n </a>`;\r\n }\r\n\r\n /**\r\n * Handler for when the search bar's clear button is pressed.\r\n */\r\n private searchFieldCleared(): void {\r\n if (this.query) {\r\n this.emitSearchRequested();\r\n }\r\n }\r\n\r\n /**\r\n * Handler for Enter key or search button click.\r\n */\r\n private handleSubmit(): void {\r\n this.emitSearchRequested();\r\n }\r\n\r\n /**\r\n * Handler for when the user selects a category from the dropdown.\r\n *\r\n * Sets `selectedCategory` locally for immediate visual feedback (semi-controlled\r\n * pattern). The parent also binds this property and may re-set it on re-render.\r\n */\r\n private handleCategorySelected(\r\n e: CustomEvent<{ option: optionInterface }>,\r\n ): void {\r\n const newCategoryId = e.detail.option.id;\r\n\r\n if (newCategoryId === IADropdownSearchBar.ADVANCED_SEARCH_OPTION_ID) {\r\n this.navigateToAdvancedSearch();\r\n return;\r\n }\r\n\r\n if (newCategoryId === this.resolvedCategory) return;\r\n\r\n this.selectedCategory = newCategoryId;\r\n\r\n // On next tick, focus the text input bar (seemingly fails in Safari without the delay)\r\n setTimeout(() => this.searchInput.focus());\r\n\r\n this.dispatchEvent(\r\n new CustomEvent<string>(Events.CategoryChanged, {\r\n detail: newCategoryId,\r\n }),\r\n );\r\n }\r\n\r\n /**\r\n * Navigates the browser to the Advanced Search page with the current query.\r\n */\r\n private navigateToAdvancedSearch(): void {\r\n // Schedule a re-render so ia-dropdown resets its internal selectedOption\r\n // back to the real category (in case navigation is delayed or prevented)\r\n this.requestUpdate();\r\n\r\n const query = this.searchInput?.value ?? this.query ?? '';\r\n const href = this.buildAdvancedSearchUrl(query);\r\n if (!href) return;\r\n\r\n this.advancedSearchClicked();\r\n window.location.href = href;\r\n }\r\n\r\n /**\r\n * Handler for clicks on the advanced search link/option\r\n */\r\n private advancedSearchClicked(): void {\r\n this.dispatchEvent(new CustomEvent(Events.AdvancedSearchClicked));\r\n }\r\n\r\n /**\r\n * Emits a `searchRequested` event with the current query and category.\r\n */\r\n private emitSearchRequested(): void {\r\n this.dispatchEvent(\r\n new CustomEvent<SearchRequestedDetail>(Events.SearchRequested, {\r\n detail: {\r\n query: this.searchInput.value,\r\n category: this.resolvedCategory,\r\n },\r\n }),\r\n );\r\n }\r\n\r\n static get styles() {\r\n const ownStyles = css`\r\n :host {\r\n --search-bar-height--: var(--search-bar-height, 30px);\r\n --search-bar-width--: var(--search-bar-width, 300px);\r\n --search-bar-internal-padding--: var(--padding-sm, 5px);\r\n --clear-button-offset--: var(--clear-button-offset, 0);\r\n }\r\n\r\n #container {\r\n display: inline-block;\r\n width: var(--search-bar-width--);\r\n }\r\n\r\n #main-bar {\r\n display: flex;\r\n height: var(--search-bar-height--, 30px);\r\n margin-bottom: 10px;\r\n flex: 1;\r\n }\r\n\r\n #category-dropdown {\r\n display: flex;\r\n flex-shrink: 0;\r\n height: 100%;\r\n box-sizing: border-box;\r\n\r\n background-color: #f5f5f7;\r\n border: 1px solid #999;\r\n border-radius: 5px 0 0 5px;\r\n\r\n --dropdownMainButtonPadding: 0 var(--search-bar-internal-padding--, 5px);\r\n --dropdownBgColor: #2c2c2c;\r\n --dropdownTextColor: #fff;\r\n --dropdownBorderColor: #ddd;\r\n --dropdownCaretColor: var(--ia-theme-primary-text-color, #2c2c2c);\r\n --dropdownHoverBgColor: rgba(255, 255, 255, 0.3);\r\n --dropdownHoverTextColor: #fff;\r\n --dropdownSelectedBgColor: rgba(255, 255, 255, 0.3);\r\n --dropdownSelectedTextColor: #fff;\r\n --dropdownWhiteSpace: nowrap;\r\n --dropdownOffsetTop: 2px;\r\n --caretHeight: 8px;\r\n --caretWidth: 12px;\r\n --caretPadding: 0 0 0 5px;\r\n --dropdownFontSize: inherit;\r\n --dropdownBorderRadius: 4px;\r\n --buttonSlotPaddingRight: 0;\r\n --dropdownTextAlign: left;\r\n }\r\n\r\n #category-dropdown [slot='dropdown-label'] {\r\n color: var(--ia-theme-primary-text-color, #2c2c2c);\r\n font-size: inherit;\r\n font-family: inherit;\r\n white-space: nowrap;\r\n }\r\n\r\n .no-dropdown #search-input {\r\n border-left: 1px solid #999;\r\n border-radius: 5px 0 0 5px;\r\n overflow: hidden;\r\n }\r\n\r\n #search-input {\r\n width: 100%;\r\n height: 100%;\r\n box-sizing: border-box;\r\n border-top: 1px solid #999;\r\n border-bottom: 1px solid #999;\r\n font-size: inherit;\r\n\r\n --input-height: calc(var(--search-bar-height--) - 2px);\r\n --input-padding: 0 var(--search-bar-internal-padding--, 5px);\r\n --input-background-color: var(\r\n --ia-theme-secondary-background-color,\r\n #fff\r\n );\r\n --input-border-radius: 0;\r\n --input-border-width: 0;\r\n --input-box-shadow: none;\r\n --input-focused-box-shadow: none;\r\n --input-font-size: auto;\r\n --clear-button-top: var(--clear-button-offset--, 0);\r\n --clear-button-right: 2px;\r\n }\r\n\r\n #search-button {\r\n appearance: none;\r\n box-sizing: border-box;\r\n border-radius: 0 5px 5px 0;\r\n background-color: var(--ia-theme-secondary-background-color, #fff);\r\n border: 1px solid #999;\r\n border-left: 0;\r\n padding: 0 var(--search-bar-internal-padding--, 5px) 0 5px;\r\n min-width: 30px;\r\n height: 100%;\r\n cursor: pointer;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n flex-shrink: 0;\r\n }\r\n\r\n #search-button img {\r\n width: 18px;\r\n height: 18px;\r\n }\r\n\r\n .search-button-loading-icon {\r\n --icon-width: 20px;\r\n margin-top: 2px;\r\n }\r\n\r\n #search-links-area {\r\n display: flex;\r\n align-items: flex-start;\r\n justify-content: space-between;\r\n margin-top: 5px;\r\n font-size: inherit;\r\n }\r\n\r\n #search-links {\r\n display: flex;\r\n column-gap: 10px;\r\n width: 100%;\r\n }\r\n\r\n #search-links > a:not(:last-child) {\r\n margin-bottom: 2px;\r\n }\r\n\r\n #advanced-search-link {\r\n margin-left: auto;\r\n padding-left: 5px;\r\n }\r\n\r\n #search-links-end {\r\n display: contents;\r\n }\r\n\r\n .mobile #advanced-search-link {\r\n margin-left: 0;\r\n }\r\n\r\n .mobile #search-links-end {\r\n display: flex;\r\n margin-left: auto;\r\n column-gap: 10px;\r\n }\r\n\r\n a:link {\r\n text-decoration: none;\r\n display: block;\r\n flex: 0 1 auto;\r\n color: var(--ia-theme-link-color, #4b64ff);\r\n white-space: nowrap;\r\n }\r\n\r\n a:hover {\r\n text-decoration: underline;\r\n }\r\n\r\n a:visited {\r\n color: var(--ia-theme-link-color, #4b64ff);\r\n }\r\n\r\n ::slotted(#action-bar-spacing) {\r\n --iconLabelGutterWidth: 3px;\r\n margin-top: -4px; /* Better icon alignment */\r\n height: fit-content;\r\n }\r\n `;\r\n\r\n return [themeStyles, ownStyles];\r\n }\r\n}\r\n"]}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * A category to include in the dropdown. Consists of an internal `id` string that is
3
+ * emitted on selection, an a human-readable `label` to display in the dropdown.
4
+ */
5
+ export type SearchCategory = {
6
+ id: string;
7
+ label: string;
8
+ };
9
+ /**
10
+ * Detail object emitted with `searchRequested` events.
11
+ */
12
+ export type SearchRequestedDetail = {
13
+ query: string;
14
+ category: string;
15
+ };
16
+ /**
17
+ * Options for where to display Advanced Search:
18
+ * - `link` (default): as a text link below the search bar
19
+ * - `dropdown`: as an item at the bottom of the category dropdown
20
+ * - `none`: hidden entirely
21
+ */
22
+ export type AdvancedSearchStyle = 'link' | 'dropdown' | 'none';
23
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../../../src/elements/ia-dropdown-search-bar/models.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../../../src/elements/ia-dropdown-search-bar/models.ts"],"names":[],"mappings":"","sourcesContent":["/**\r\n * A category to include in the dropdown. Consists of an internal `id` string that is\r\n * emitted on selection, an a human-readable `label` to display in the dropdown.\r\n */\r\nexport type SearchCategory = {\r\n id: string;\r\n label: string;\r\n};\r\n\r\n/**\r\n * Detail object emitted with `searchRequested` events.\r\n */\r\nexport type SearchRequestedDetail = {\r\n query: string;\r\n category: string;\r\n};\r\n\r\n/**\r\n * Options for where to display Advanced Search:\r\n * - `link` (default): as a text link below the search bar\r\n * - `dropdown`: as an item at the bottom of the category dropdown\r\n * - `none`: hidden entirely\r\n */\r\nexport type AdvancedSearchStyle = 'link' | 'dropdown' | 'none';\r\n"]}