@@ -219,6 +219,7 @@ export function renderResults() {
219219 state . listMode = false ;
220220 state . listId = null ;
221221 state . listName = '' ;
222+ state . listDescription = '' ;
222223 state . listEntries = [ ] ;
223224 state . listSynced = false ;
224225 renderResults ( ) ;
@@ -288,6 +289,17 @@ function attachCardListeners(container) {
288289 openAddToListModal ( btn . dataset . id ) ;
289290 } ) ;
290291 } ) ;
292+ card . querySelectorAll ( '.copy-entry-link-btn' ) . forEach ( ( btn ) => {
293+ btn . addEventListener ( 'click' , ( e ) => {
294+ e . stopPropagation ( ) ;
295+ const url = `${ window . location . origin } ${ window . location . pathname } ?id=${ encodeURIComponent ( btn . dataset . id ) } ` ;
296+ navigator . clipboard . writeText ( url ) . then ( ( ) => {
297+ const prev = btn . textContent ;
298+ btn . textContent = 'Copied!' ;
299+ setTimeout ( ( ) => { btn . textContent = prev ; } , 1500 ) ;
300+ } ) . catch ( ( ) => { } ) ;
301+ } ) ;
302+ } ) ;
291303 } ) ;
292304}
293305
@@ -318,7 +330,7 @@ export function renderCardHtml(entry, expanded) {
318330<article class="result-card${ expanded ? ' expanded' : '' } " data-id="${ escapeHtml ( entry . id ) } " aria-expanded="${ expanded } ">
319331 <div class="card-header" role="button" tabindex="0" aria-label="${ escapeHtml ( entry . title ) } , ${ expanded ? 'collapse' : 'expand' } ">
320332 <div class="card-header-main">
321- <h3 class="card-title">${ state . directId === entry . id ? `<span class="card-title-link">${ escapeHtml ( entry . title ) } </span>` : `<a class="card-title-link" href="?id=${ encodeURIComponent ( entry . id ) } ">${ escapeHtml ( entry . title ) } </a>` } ${ entry . original_publication_date ? `<span class="card-title-date"> (${ escapeHtml ( formatDateShort ( entry . original_publication_date ) ) } )</span>` : '' } <button type="button" class="add-to-list-btn outline secondary" data-id="${ escapeHtml ( entry . id ) } " aria-label="Add ${ escapeHtml ( entry . title ) } to a list">+ List</button></h3>
333+ <h3 class="card-title">${ state . directId === entry . id ? `<span class="card-title-link">${ escapeHtml ( entry . title ) } </span>` : `<a class="card-title-link" href="?id=${ encodeURIComponent ( entry . id ) } ">${ escapeHtml ( entry . title ) } </a>` } ${ entry . original_publication_date ? `<span class="card-title-date"> (${ escapeHtml ( formatDateShort ( entry . original_publication_date ) ) } )</span>` : '' } <button type="button" class="add-to-list-btn outline secondary" data-id="${ escapeHtml ( entry . id ) } " aria-label="Add ${ escapeHtml ( entry . title ) } to a list">+ List</button><button type="button" class="copy-entry-link-btn outline secondary" data-id=" ${ escapeHtml ( entry . id ) } " aria-label="Copy link to ${ escapeHtml ( entry . title ) } ">Copy link</button>< /h3>
322334 ${ authorStr ? `<div class="card-byline">${ escapeHtml ( authorStr ) } </div>` : '' }
323335 ${ entry . description ? `<div class="card-description-snippet">${ escapeHtml ( entry . description ) } </div>` : '' }
324336 </div>
@@ -621,7 +633,28 @@ function renderListView() {
621633 . join ( '' ) ;
622634 }
623635
624- list . innerHTML = headerHtml + rowsHtml ;
636+ const descriptionHtml = `<textarea
637+ class="list-view-description"
638+ id="list-view-description"
639+ placeholder="Add a description…"
640+ rows="1"
641+ aria-label="List description"
642+ >${ escapeHtml ( state . listDescription || '' ) } </textarea>` ;
643+
644+ list . innerHTML = descriptionHtml + headerHtml + rowsHtml ;
645+
646+ const descEl = document . getElementById ( 'list-view-description' ) ;
647+ function autoResize ( ) {
648+ descEl . style . height = 'auto' ;
649+ descEl . style . height = descEl . scrollHeight + 'px' ;
650+ }
651+ autoResize ( ) ;
652+ descEl . addEventListener ( 'input' , autoResize ) ;
653+ descEl . addEventListener ( 'blur' , ( ) => {
654+ state . listDescription = descEl . value . trim ( ) ;
655+ autoSave ( ) ;
656+ updateUrl ( ) ;
657+ } ) ;
625658
626659 document . getElementById ( 'list-save-btn' ) ?. addEventListener ( 'click' , onSaveList ) ;
627660
@@ -848,7 +881,7 @@ export function closeAddToListModal() {
848881function onSaveList ( ) {
849882 if ( ! state . listId ) state . listId = generateListId ( ) ;
850883 state . listSynced = true ;
851- saveList ( { id : state . listId , name : state . listName || 'Untitled list' , entries : state . listEntries } ) ;
884+ saveList ( { id : state . listId , name : state . listName || 'Untitled list' , description : state . listDescription , entries : state . listEntries } ) ;
852885 updateUrl ( ) ;
853886 renderResults ( ) ;
854887}
@@ -868,7 +901,7 @@ function onCopyListUrl() {
868901
869902function autoSave ( ) {
870903 if ( state . listId && state . listSynced ) {
871- saveList ( { id : state . listId , name : state . listName || 'Untitled list' , entries : state . listEntries } ) ;
904+ saveList ( { id : state . listId , name : state . listName || 'Untitled list' , description : state . listDescription , entries : state . listEntries } ) ;
872905 }
873906}
874907
@@ -907,7 +940,7 @@ function onStartRenameList() {
907940 const newName = input . value . trim ( ) || 'Untitled list' ;
908941 state . listName = newName ;
909942 if ( state . listId && state . listSynced ) {
910- saveList ( { id : state . listId , name : newName , entries : state . listEntries } ) ;
943+ saveList ( { id : state . listId , name : newName , description : state . listDescription , entries : state . listEntries } ) ;
911944 }
912945 updateUrl ( ) ;
913946 renderResults ( ) ;
@@ -930,6 +963,7 @@ function onOpenList(id) {
930963 state . listMode = true ;
931964 state . listId = id ;
932965 state . listName = l . name || 'Untitled list' ;
966+ state . listDescription = l . description || '' ;
933967 state . listEntries = [ ...l . entries ] ;
934968 state . listSynced = true ;
935969 touchList ( id ) ;
0 commit comments