@@ -95,29 +95,70 @@ const {
9595 },
9696)
9797
98+ function maybePrefetchReadmeMarkdown() {
99+ if (import .meta .server ) return
100+ if (! readmeData .value .mdExists ) return
101+ if (readmeMarkdownStatus .value !== ' idle' ) return
102+ void fetchReadmeMarkdown ()
103+ }
104+
105+ watch ([() => readmeData .value .mdExists , readmeMarkdownStatus ], () => {
106+ maybePrefetchReadmeMarkdown ()
107+ }, { immediate: true })
108+
98109// copy README file as Markdown
99110const { copied : copiedReadme, copy : copyReadme } = useClipboard ({
100111 source : () => ' ' ,
101112 copiedDuring: 2000 ,
102113 legacy: true ,
103114})
115+ const isCopyingReadme = shallowRef (false )
116+
117+ const readmeCopyTooltip = computed (() =>
118+ isCopyingReadme .value ? $t (' common.loading' ) : $t (' package.readme.copy_as_markdown' ),
119+ )
120+
121+ const readmeCopyAriaLabel = computed (() => {
122+ if (isCopyingReadme .value ) return $t (' common.loading' )
123+ if (copiedReadme .value ) return $t (' common.copied' )
124+ return $t (' package.readme.copy_as_markdown' )
125+ })
126+
127+ const readmeCopyIcon = computed (() => {
128+ if (isCopyingReadme .value ) return ' i-svg-spinners:ring-resize'
129+ if (copiedReadme .value ) return ' i-lucide:check'
130+ return ' i-simple-icons:markdown'
131+ })
132+
133+ const readmeCopyText = computed (() => {
134+ if (isCopyingReadme .value ) return $t (' common.loading' )
135+ if (copiedReadme .value ) return $t (' common.copied' )
136+ return $t (' common.copy' )
137+ })
104138
105139function prefetchReadmeMarkdown() {
106- if (readmeMarkdownStatus .value === ' idle' ) {
107- fetchReadmeMarkdown ()
108- }
140+ maybePrefetchReadmeMarkdown ()
109141}
110142
111143async function copyReadmeHandler() {
112- let markdown = readmeMarkdownData .value ?.markdown
113- if (! markdown ) {
114- await fetchReadmeMarkdown ()
115- markdown = readmeMarkdownData .value ?.markdown
116- }
144+ if (isCopyingReadme .value ) return
117145
118- if (! markdown ) return
146+ isCopyingReadme .value = true
147+
148+ try {
149+ let markdown = readmeMarkdownData .value ?.markdown
150+ if (! markdown ) {
151+ await fetchReadmeMarkdown ()
152+ markdown = readmeMarkdownData .value ?.markdown
153+ }
119154
120- await copyReadme (markdown )
155+ if (! markdown ) return
156+
157+ await copyReadme (markdown )
158+ }
159+ finally {
160+ isCopyingReadme .value = false
161+ }
121162}
122163
123164// Track active TOC item based on scroll position
@@ -988,20 +1029,20 @@ const showSkeleton = shallowRef(false)
9881029 <!-- Copy readme as Markdown button -->
9891030 <TooltipApp
9901031 v-if =" readmeData?.mdExists"
991- :text =" $t('package.readme.copy_as_markdown') "
1032+ :text =" readmeCopyTooltip "
9921033 position =" bottom"
9931034 >
9941035 <ButtonBase
9951036 @mouseenter =" prefetchReadmeMarkdown"
9961037 @focus =" prefetchReadmeMarkdown"
9971038 @click =" copyReadmeHandler()"
1039+ :disabled =" isCopyingReadme"
1040+ :aria-busy =" isCopyingReadme ? 'true' : 'false'"
9981041 :aria-pressed =" copiedReadme"
999- :aria-label ="
1000- copiedReadme ? $t('common.copied') : $t('package.readme.copy_as_markdown')
1001- "
1002- :classicon =" copiedReadme ? 'i-lucide:check' : 'i-simple-icons:markdown'"
1042+ :aria-label =" readmeCopyAriaLabel"
1043+ :classicon =" readmeCopyIcon"
10031044 >
1004- {{ copiedReadme ? $t('common.copied') : $t('common.copy') }}
1045+ {{ readmeCopyText }}
10051046 </ButtonBase >
10061047 </TooltipApp >
10071048 <ReadmeTocDropdown
0 commit comments