@jant/core 0.6.0 → 0.6.1

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.
@@ -1,4 +1,4 @@
1
- import{a as e,n as t,o as n,t as r}from"./chunks/url-pLre2DM_.js";import{_ as i,a,c as o,d as s,f as c,g as l,h as u,i as d,l as f,m as p,n as m,o as h,p as g,r as _,s as v,t as y,u as b}from"./client-Bo7sKkAQ.js";var x={maxWidth:1920,maxHeight:1920,quality:.85,mimeType:`image/webp`};function S(e){return new Promise((t,n)=>{let r=new Image;r.onload=()=>{URL.revokeObjectURL(r.src),t(r)},r.onerror=()=>n(Error(`Failed to load image`)),r.src=URL.createObjectURL(e)})}function C(e,t,n,r){if(e<=n&&t<=r)return{width:e,height:t};let i=Math.min(n/e,r/t);return{width:Math.round(e*i),height:Math.round(t*i)}}async function ee(e,t,n){let r=await new Promise((r,i)=>{e.toBlob(e=>e?r(e):i(Error(`Failed to create blob`)),t,n)});return t!==`image/png`&&r.type===`image/png`?new Promise((t,r)=>{e.toBlob(e=>e?t(e):r(Error(`Failed to create blob`)),`image/jpeg`,n)}):r}async function te(e,t={}){let n={...x,...t},r=await S(e),{width:i,height:a}=C(r.width,r.height,n.maxWidth,n.maxHeight),o=document.createElement(`canvas`);o.width=i,o.height=a;let s=o.getContext(`2d`);if(!s)throw Error(`Failed to get canvas context`);return s.drawImage(r,0,0,i,a),{blob:await ee(o,n.mimeType,n.quality),width:i,height:a}}async function ne(e,t={}){let{blob:n,width:r,height:i}=await te(e,t),a={"image/webp":`webp`,"image/jpeg":`jpg`,"image/png":`png`}[n.type]??`png`,o=`${e.name.replace(/\.[^.]+$/,``)}.${a}`;return{file:new File([n],o,{type:n.type}),width:r,height:i}}var re={process:te,processToFile:ne},ie={ICO_16:16,ICO_32:32,APPLE_TOUCH:512};function ae(e){let t=e.length*16,n=6+t,r=new ArrayBuffer(6+t),i=new DataView(r);i.setUint16(0,0,!0),i.setUint16(2,1,!0),i.setUint16(4,e.length,!0);let a=[];for(let t=0;t<e.length;t++){let r=e[t],o=6+t*16;i.setUint8(o+0,r.size<256?r.size:0),i.setUint8(o+1,r.size<256?r.size:0),i.setUint8(o+2,0),i.setUint8(o+3,0),i.setUint16(o+4,1,!0),i.setUint16(o+6,32,!0),i.setUint32(o+8,r.png.byteLength,!0),i.setUint32(o+12,n,!0),n+=r.png.byteLength,a.push(r.png)}return new Blob([r,...a],{type:`image/x-icon`})}function oe(e){return typeof e==`object`&&!!e}function w(e,t){if(!oe(e))return;let n=e[t];return typeof n==`string`?n:void 0}function se(e,t){if(!oe(e))return;let n=e[t];return typeof n==`boolean`?n:void 0}function ce(e,t){if(!oe(e))return;let n=e[t];return typeof n==`number`?n:void 0}async function le(e){let t=await e.json();return oe(t)?t:{}}var ue=180;function de(e){return new Promise((t,n)=>{let r=new Image;r.onload=()=>{URL.revokeObjectURL(r.src),t(r)},r.onerror=()=>n(Error(`Failed to load image`)),r.src=URL.createObjectURL(e)})}function fe(e,t){let n=document.createElement(`canvas`);n.width=t,n.height=t;let r=n.getContext(`2d`);if(!r)throw Error(`Failed to get canvas context`);r.imageSmoothingEnabled=!0,r.imageSmoothingQuality=`high`;let i=Math.max(t/e.width,t/e.height),a=t/i,o=t/i,s=(e.width-a)/2,c=(e.height-o)/2;return r.drawImage(e,s,c,a,o,0,0,t,t),new Promise((e,t)=>{n.toBlob(n=>{n?e(n):t(Error(`Failed to create PNG blob`))},`image/png`)})}function pe(e,t){return e.type===`image/png`&&t.width===t.height&&t.width>=ue&&t.height>=ue}async function me(e,t){let n=e.closest(`form`)?.querySelector(`label`),r=n?.textContent??``;try{n&&(n.textContent=e.dataset.textProcessing||`Processing...`);let r=await de(t),a=t,o=t.name;if(t.type!==`image/svg+xml`){let e=await fe(r,512);a=new File([e],t.name.replace(/\.[^.]+$/,`.png`),{type:`image/png`}),o=a.name}let s=pe(t,r)?Promise.resolve(t):fe(r,ie.APPLE_TOUCH),[c,l,u]=await Promise.all([fe(r,16),fe(r,32),s]),[d,f]=await Promise.all([c.arrayBuffer(),l.arrayBuffer()]),p=ae([{size:16,png:d},{size:32,png:f}]);n&&(n.textContent=e.dataset.textUploading||`Uploading...`);let m=new FormData;m.append(`file`,a,o),m.append(`favicon`,p,`favicon.ico`),m.append(`appleTouch`,u,`apple-touch-icon.png`);let h=await fetch(i(`/settings/avatar`),{method:`POST`,headers:{Accept:`application/json`},body:m});if(!h.ok){let t=e.dataset.textError||`Upload failed. Please try again.`;try{let e=await le(h);t=w(e,`error`)??w(e,`message`)??t}catch{}throw Error(t)}let g=await le(h),_=w(g,`status`),v=w(g,`url`);if(_===`redirect`&&v){window.location.href=v;return}window.location.href=i(`/settings/avatar?saved`)}catch(t){n&&(n.textContent=r),d(t instanceof Error&&t.message?t.message:e.dataset.textError||`Upload failed. Please try again.`,`error`)}e.value=``}function he(){document.addEventListener(`change`,e=>{let t=e.target.closest(`[data-avatar-upload]`);t?.files?.[0]&&(e.stopPropagation(),me(t,t.files[0]))})}he();var ge=`default`,_e=class extends c{static properties={_open:{state:!0},_title:{state:!0},_message:{state:!0},_confirmLabel:{state:!0},_cancelLabel:{state:!0},_tone:{state:!0}};#e=[];#t=null;createRenderRoot(){return this.innerHTML=``,this}constructor(){super(),this._open=!1,this._title=``,this._message=``,this._confirmLabel=``,this._cancelLabel=``,this._tone=ge}disconnectedCallback(){super.disconnectedCallback();let e=this.#t;this.#t=null,e?.resolve(!1);for(let e of this.#e.splice(0))e.resolve(!1)}async confirm(e){return await new Promise(t=>{this.#e.push({...e,tone:e.tone??ge,resolve:t}),this.#t||this.#n()})}async#n(){if(this.#t||this.#e.length===0)return;let e=this.#e.shift();if(!e)return;this.#t=e,this._title=e.title??``,this._message=e.message,this._confirmLabel=e.confirmLabel,this._cancelLabel=e.cancelLabel,this._tone=e.tone??ge,this._open=!0,await this.updateComplete;let t=this.querySelector(`.confirm-dialog`);t&&(t.open||t.showModal(),t.querySelector(`.confirm-dialog-panel`)?.focus())}#r(e){let t=this.#t;if(!t)return;this.#t=null;let n=this.querySelector(`.confirm-dialog`);n?.open&&n.close(),this._open=!1,this._title=``,this._message=``,this._confirmLabel=``,this._cancelLabel=``,this._tone=ge,t.resolve(e),queueMicrotask(()=>void this.#n())}#i=e=>{e.preventDefault(),this.#r(!1)};#a=e=>{e.target===e.currentTarget&&this.#r(!1)};#o=e=>{if(e.key===`Escape`){e.preventDefault(),e.stopPropagation(),this.#r(!1);return}let t=e.target,n=t instanceof HTMLButtonElement||t instanceof HTMLInputElement||t instanceof HTMLSelectElement||t instanceof HTMLTextAreaElement||t instanceof HTMLAnchorElement;e.key===`Enter`&&!e.defaultPrevented&&!e.metaKey&&!e.ctrlKey&&!e.altKey&&!e.shiftKey&&!n&&(e.preventDefault(),this.#r(!0))};#s(){if(this._title)return{title:this._title,message:this._message};let e=this._message.match(/^(.+?[??])\s+(.+)$/u);return e?{title:e[1],message:e[2]}:{title:this._message,message:``}}render(){if(!this._open)return g;let{title:e,message:t}=this.#s(),n=this._tone===`danger`?`btn-destructive`:`btn`;return u`
1
+ import{a as e,n as t,o as n,t as r}from"./chunks/url-pLre2DM_.js";import{_ as i,a,c as o,d as s,f as c,g as l,h as u,i as d,l as f,m as p,n as m,o as h,p as g,r as _,s as v,t as y,u as b}from"./client-BRTh1ii1.js";var x={maxWidth:1920,maxHeight:1920,quality:.85,mimeType:`image/webp`};function S(e){return new Promise((t,n)=>{let r=new Image;r.onload=()=>{URL.revokeObjectURL(r.src),t(r)},r.onerror=()=>n(Error(`Failed to load image`)),r.src=URL.createObjectURL(e)})}function C(e,t,n,r){if(e<=n&&t<=r)return{width:e,height:t};let i=Math.min(n/e,r/t);return{width:Math.round(e*i),height:Math.round(t*i)}}async function ee(e,t,n){let r=await new Promise((r,i)=>{e.toBlob(e=>e?r(e):i(Error(`Failed to create blob`)),t,n)});return t!==`image/png`&&r.type===`image/png`?new Promise((t,r)=>{e.toBlob(e=>e?t(e):r(Error(`Failed to create blob`)),`image/jpeg`,n)}):r}async function te(e,t={}){let n={...x,...t},r=await S(e),{width:i,height:a}=C(r.width,r.height,n.maxWidth,n.maxHeight),o=document.createElement(`canvas`);o.width=i,o.height=a;let s=o.getContext(`2d`);if(!s)throw Error(`Failed to get canvas context`);return s.drawImage(r,0,0,i,a),{blob:await ee(o,n.mimeType,n.quality),width:i,height:a}}async function ne(e,t={}){let{blob:n,width:r,height:i}=await te(e,t),a={"image/webp":`webp`,"image/jpeg":`jpg`,"image/png":`png`}[n.type]??`png`,o=`${e.name.replace(/\.[^.]+$/,``)}.${a}`;return{file:new File([n],o,{type:n.type}),width:r,height:i}}var re={process:te,processToFile:ne},ie={ICO_16:16,ICO_32:32,APPLE_TOUCH:512};function ae(e){let t=e.length*16,n=6+t,r=new ArrayBuffer(6+t),i=new DataView(r);i.setUint16(0,0,!0),i.setUint16(2,1,!0),i.setUint16(4,e.length,!0);let a=[];for(let t=0;t<e.length;t++){let r=e[t],o=6+t*16;i.setUint8(o+0,r.size<256?r.size:0),i.setUint8(o+1,r.size<256?r.size:0),i.setUint8(o+2,0),i.setUint8(o+3,0),i.setUint16(o+4,1,!0),i.setUint16(o+6,32,!0),i.setUint32(o+8,r.png.byteLength,!0),i.setUint32(o+12,n,!0),n+=r.png.byteLength,a.push(r.png)}return new Blob([r,...a],{type:`image/x-icon`})}function oe(e){return typeof e==`object`&&!!e}function w(e,t){if(!oe(e))return;let n=e[t];return typeof n==`string`?n:void 0}function se(e,t){if(!oe(e))return;let n=e[t];return typeof n==`boolean`?n:void 0}function ce(e,t){if(!oe(e))return;let n=e[t];return typeof n==`number`?n:void 0}async function le(e){let t=await e.json();return oe(t)?t:{}}var ue=180;function de(e){return new Promise((t,n)=>{let r=new Image;r.onload=()=>{URL.revokeObjectURL(r.src),t(r)},r.onerror=()=>n(Error(`Failed to load image`)),r.src=URL.createObjectURL(e)})}function fe(e,t){let n=document.createElement(`canvas`);n.width=t,n.height=t;let r=n.getContext(`2d`);if(!r)throw Error(`Failed to get canvas context`);r.imageSmoothingEnabled=!0,r.imageSmoothingQuality=`high`;let i=Math.max(t/e.width,t/e.height),a=t/i,o=t/i,s=(e.width-a)/2,c=(e.height-o)/2;return r.drawImage(e,s,c,a,o,0,0,t,t),new Promise((e,t)=>{n.toBlob(n=>{n?e(n):t(Error(`Failed to create PNG blob`))},`image/png`)})}function pe(e,t){return e.type===`image/png`&&t.width===t.height&&t.width>=ue&&t.height>=ue}async function me(e,t){let n=e.closest(`form`)?.querySelector(`label`),r=n?.textContent??``;try{n&&(n.textContent=e.dataset.textProcessing||`Processing...`);let r=await de(t),a=t,o=t.name;if(t.type!==`image/svg+xml`){let e=await fe(r,512);a=new File([e],t.name.replace(/\.[^.]+$/,`.png`),{type:`image/png`}),o=a.name}let s=pe(t,r)?Promise.resolve(t):fe(r,ie.APPLE_TOUCH),[c,l,u]=await Promise.all([fe(r,16),fe(r,32),s]),[d,f]=await Promise.all([c.arrayBuffer(),l.arrayBuffer()]),p=ae([{size:16,png:d},{size:32,png:f}]);n&&(n.textContent=e.dataset.textUploading||`Uploading...`);let m=new FormData;m.append(`file`,a,o),m.append(`favicon`,p,`favicon.ico`),m.append(`appleTouch`,u,`apple-touch-icon.png`);let h=await fetch(i(`/settings/avatar`),{method:`POST`,headers:{Accept:`application/json`},body:m});if(!h.ok){let t=e.dataset.textError||`Upload failed. Please try again.`;try{let e=await le(h);t=w(e,`error`)??w(e,`message`)??t}catch{}throw Error(t)}let g=await le(h),_=w(g,`status`),v=w(g,`url`);if(_===`redirect`&&v){window.location.href=v;return}window.location.href=i(`/settings/avatar?saved`)}catch(t){n&&(n.textContent=r),d(t instanceof Error&&t.message?t.message:e.dataset.textError||`Upload failed. Please try again.`,`error`)}e.value=``}function he(){document.addEventListener(`change`,e=>{let t=e.target.closest(`[data-avatar-upload]`);t?.files?.[0]&&(e.stopPropagation(),me(t,t.files[0]))})}he();var ge=`default`,_e=class extends c{static properties={_open:{state:!0},_title:{state:!0},_message:{state:!0},_confirmLabel:{state:!0},_cancelLabel:{state:!0},_tone:{state:!0}};#e=[];#t=null;createRenderRoot(){return this.innerHTML=``,this}constructor(){super(),this._open=!1,this._title=``,this._message=``,this._confirmLabel=``,this._cancelLabel=``,this._tone=ge}disconnectedCallback(){super.disconnectedCallback();let e=this.#t;this.#t=null,e?.resolve(!1);for(let e of this.#e.splice(0))e.resolve(!1)}async confirm(e){return await new Promise(t=>{this.#e.push({...e,tone:e.tone??ge,resolve:t}),this.#t||this.#n()})}async#n(){if(this.#t||this.#e.length===0)return;let e=this.#e.shift();if(!e)return;this.#t=e,this._title=e.title??``,this._message=e.message,this._confirmLabel=e.confirmLabel,this._cancelLabel=e.cancelLabel,this._tone=e.tone??ge,this._open=!0,await this.updateComplete;let t=this.querySelector(`.confirm-dialog`);t&&(t.open||t.showModal(),t.querySelector(`.confirm-dialog-panel`)?.focus())}#r(e){let t=this.#t;if(!t)return;this.#t=null;let n=this.querySelector(`.confirm-dialog`);n?.open&&n.close(),this._open=!1,this._title=``,this._message=``,this._confirmLabel=``,this._cancelLabel=``,this._tone=ge,t.resolve(e),queueMicrotask(()=>void this.#n())}#i=e=>{e.preventDefault(),this.#r(!1)};#a=e=>{e.target===e.currentTarget&&this.#r(!1)};#o=e=>{if(e.key===`Escape`){e.preventDefault(),e.stopPropagation(),this.#r(!1);return}let t=e.target,n=t instanceof HTMLButtonElement||t instanceof HTMLInputElement||t instanceof HTMLSelectElement||t instanceof HTMLTextAreaElement||t instanceof HTMLAnchorElement;e.key===`Enter`&&!e.defaultPrevented&&!e.metaKey&&!e.ctrlKey&&!e.altKey&&!e.shiftKey&&!n&&(e.preventDefault(),this.#r(!0))};#s(){if(this._title)return{title:this._title,message:this._message};let e=this._message.match(/^(.+?[??])\s+(.+)$/u);return e?{title:e[1],message:e[2]}:{title:this._message,message:``}}render(){if(!this._open)return g;let{title:e,message:t}=this.#s(),n=this._tone===`danger`?`btn-destructive`:`btn`;return u`
2
2
  <dialog
3
3
  class="dialog confirm-dialog"
4
4
  @cancel=${this.#i}
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { _ as url_exports } from "./url-umUptr5z.js";
2
- import { A as MAX_MEDIA_ATTACHMENTS, C as toMediaView, D as toPostViews, E as toPostView, F as STATUSES, I as TEXT_ATTACHMENT_CONTENT_FORMATS, M as MEDIA_KINDS, N as NAV_ITEM_TYPES, O as toSearchResultView, P as SORT_ORDERS, S as toArchiveGroupsWithMedia, T as toNavItemViews, b as createMediaContext, h as defaultFeedRenderer, j as MAX_PINNED_POSTS, k as FORMATS, t as createApp, w as toNavItemView, x as toArchiveGroups } from "./app-BIkkbVQk.js";
2
+ import { A as MAX_MEDIA_ATTACHMENTS, C as toMediaView, D as toPostViews, E as toPostView, F as STATUSES, I as TEXT_ATTACHMENT_CONTENT_FORMATS, M as MEDIA_KINDS, N as NAV_ITEM_TYPES, O as toSearchResultView, P as SORT_ORDERS, S as toArchiveGroupsWithMedia, T as toNavItemViews, b as createMediaContext, h as defaultFeedRenderer, j as MAX_PINNED_POSTS, k as FORMATS, t as createApp, w as toNavItemView, x as toArchiveGroups } from "./app-DYQdDMs8.js";
3
3
  import { T as time_exports, a as markdown_exports } from "./export-Bbn86HmS.js";
4
4
  import "./env-C7e2Nlnt.js";
5
5
  import "./github-sync-CBQPRZ8H.js";
package/dist/node.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import "./url-umUptr5z.js";
2
- import { B as isAssetPath, L as buildThemeStyle, R as BUILTIN_COLOR_THEMES, _ as sqliteSchemaBundle, a as resolveDatabaseDialect, c as resolveConfig, d as setWebhook, f as BUILTIN_FONT_THEMES, g as pgSchemaBundle, i as createSiteService, l as getWebhookUrl, m as getFontThemeCssVariables, n as createNodeCliRuntime, o as getHostBasedStartupConfigurationIssues, p as getCjkSerifCssVariables, r as createNodeRequestRuntime, s as createStorageDriver, t as createApp, u as setMyCommands, v as createNodeDatabase, y as schema_exports, z as getPublicAssetBasePath } from "./app-BIkkbVQk.js";
2
+ import { B as isAssetPath, L as buildThemeStyle, R as BUILTIN_COLOR_THEMES, _ as sqliteSchemaBundle, a as resolveDatabaseDialect, c as resolveConfig, d as setWebhook, f as BUILTIN_FONT_THEMES, g as pgSchemaBundle, i as createSiteService, l as getWebhookUrl, m as getFontThemeCssVariables, n as createNodeCliRuntime, o as getHostBasedStartupConfigurationIssues, p as getCjkSerifCssVariables, r as createNodeRequestRuntime, s as createStorageDriver, t as createApp, u as setMyCommands, v as createNodeDatabase, y as schema_exports, z as getPublicAssetBasePath } from "./app-DYQdDMs8.js";
3
3
  import { t as createExportService } from "./export-Bbn86HmS.js";
4
4
  import { C as shouldTrustProxy, S as getTelegramWebhookSecret, b as getSiteResolutionMode, d as getHostedControlPlaneBaseUrl, i as getConfiguredSingleSitePathPrefix, l as getEnvString, r as getConfiguredSingleSiteOrigin, x as getTelegramBotPool, y as getPort } from "./env-C7e2Nlnt.js";
5
5
  import "./github-sync-CBQPRZ8H.js";
@@ -529,7 +529,7 @@ async function createNodeRequestHandler(options) {
529
529
  async function start(env = process.env, app) {
530
530
  const handler = await createNodeRequestHandler({
531
531
  env,
532
- app: async () => app ?? (await import("./app-Bcr5_wZI.js")).createApp()
532
+ app: async () => app ?? (await import("./app-CMSW_AYG.js")).createApp()
533
533
  });
534
534
  const hostname = resolveHost(env);
535
535
  const port = resolvePort(env);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jant/core",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "description": "A modern, open-source microblogging platform built on Cloudflare Workers",
5
5
  "type": "module",
6
6
  "exports": {
package/src/styles/ui.css CHANGED
@@ -2661,28 +2661,28 @@
2661
2661
  );
2662
2662
  }
2663
2663
 
2664
- /* Push ancestor context into the visual background so the focused post
2665
- below the shell (latest reply on the home feed, anchor post on the
2666
- detail page) reads as the primary content. Opacity works on both real
2667
- painted content AND empty space, sidestepping the gradient-on-empty
2668
- visibility problem. The dots inside the shell get muted along with
2669
- the content, which actually reinforces the "this is background" feel
2670
- — the rail line itself lives on `.thread-group::before` and stays at
2671
- full strength. */
2664
+ /* Push ancestor context slightly into the background enough to feel
2665
+ secondary to the focused post but not so much that text becomes gray
2666
+ and hard to read. Combined with the mask-image bottom fade this gives
2667
+ a "context drifts into the background" effect without dimming the
2668
+ whole shell to the point of illegibility. */
2672
2669
  .thread-context-shell {
2673
- opacity: 0.5;
2670
+ opacity: 0.6;
2674
2671
  transition: opacity 0.22s ease;
2675
2672
  }
2676
2673
 
2677
- /* When the user expands the shell, restore full strength — they've
2678
- opted in to reading the context. */
2679
2674
  .thread-context-shell:not([data-collapsed]) {
2680
2675
  opacity: 1;
2681
2676
  }
2682
2677
 
2683
- /* Hide the legacy gradient-overlay element opacity replaces it. */
2684
- .thread-context-fade {
2685
- display: none;
2678
+ /* Tighter padding for context items inside the shell so a single-line
2679
+ root post doesn't leave 64px of empty padding pushing the toggle
2680
+ button far below the visible text. Items outside the shell (hero,
2681
+ descendants on detail pages) keep the default --site-thread-item-spacing
2682
+ so the focused post still gets generous breathing room. */
2683
+ .thread-context-shell .thread-item {
2684
+ padding-top: 16px;
2685
+ padding-bottom: 16px;
2686
2686
  }
2687
2687
 
2688
2688
  .thread-context-toggle[hidden] {
@@ -2812,9 +2812,10 @@
2812
2812
  directly before the current post), leave enough room above the scroll
2813
2813
  landing so the user can see the Show more button + a peek of the
2814
2814
  faded shell on initial load. Otherwise everything above is hidden in
2815
- the viewport and the user has to discover it by scrolling up. */
2815
+ the viewport and the user has to discover it by scrolling up. Sized
2816
+ for the ghost-style toggle (~28px) + a glimpse of the faded shell. */
2816
2817
  .thread-context-toggle + .thread-detail-item {
2817
- scroll-margin-top: 152px;
2818
+ scroll-margin-top: 120px;
2818
2819
  }
2819
2820
 
2820
2821
  .thread-group-detail .thread-item-current::before {
@@ -130,7 +130,6 @@ export const ThreadPreview: FC<ThreadPreviewProps> = ({
130
130
  {secondReplyItem}
131
131
  {gapItem}
132
132
  {penultimateItem}
133
- <div class="thread-context-fade" aria-hidden="true" />
134
133
  </div>
135
134
  <button
136
135
  type="button"
@@ -230,7 +230,6 @@ describe("getThreadPreviewState", () => {
230
230
  expect(html).toContain("thread-context-shell");
231
231
  expect(html).toContain("data-thread-context");
232
232
  expect(html).toContain("data-collapsed");
233
- expect(html).toContain("thread-context-fade");
234
233
  expect(html).toContain("data-thread-context-toggle");
235
234
  expect(html).toContain('aria-expanded="false"');
236
235
  expect(html).toMatch(/data-label-more="[^"]+"/);
@@ -67,7 +67,6 @@ const ThreadDetail: FC<{ post: PostView; threadPosts: PostView[] }> = ({
67
67
  data-collapsed=""
68
68
  >
69
69
  {ancestors.map((tp) => renderThreadItem(tp, post.id))}
70
- <div class="thread-context-fade" aria-hidden="true" />
71
70
  </div>
72
71
  <button
73
72
  type="button"