11<template >
2- <!-- Search mode - horizontal layout -->
3- <article
4- v-if =" search"
5- class =" p-4 bg-white hover:bg-gray-some border border-gray-default fr-enlarge-link relative"
6- >
7- <div
8- v-if =" reuse.private || reuse.archived"
9- class =" absolute top-0 fr-grid-row fr-grid-row--middle fr-mt-n3v fr-ml-n1v"
10- >
11- <p
12- v-if =" reuse.private"
13- class =" fr-badge fr-badge--sm fr-badge--mention-grey text-gray-medium mr-2"
14- >
15- <RiLockLine class="size-4 mr-1" />
16- {{ t('Brouillon') }}
17- </p >
18- <p
19- v-if =" reuse.archived"
20- class =" fr-badge fr-badge--sm fr-badge--mention-grey text-gray-medium mr-2"
21- >
22- <RiLockLine class="size-4 mr-1" />
23- {{ t('Archivé') }}
24- </p >
25- </div >
26- <div class =" flex flex-wrap md:flex-nowrap gap-4 items-start" >
27- <div class =" flex-none" >
28- <div
29- class =" flex justify-center items-center border border-gray-lower bg-[#fff] rounded-md overflow-hidden"
30- style =" width : 240px ; height : 160px ;"
31- >
32- <img
33- v-if =" reuse.image"
34- :src =" reuse.image"
35- class =" w-full h-full object-cover"
36- :alt =" reuse.title"
37- >
38- <Placeholder
39- v-else
40- type="Reuse"
41- class="w-full h-full"
42- />
43- </div >
44- </div >
45- <div class =" flex-1 overflow-hidden" >
46- <h4 class =" w-full text-base mb-0 flex" >
47- <AppLink
48- :to =" reuseUrl "
49- class="text-gray-title text-base bg-none flex items-center w-full truncate gap-1"
50- >
51- <svg
52- width =" 16"
53- height =" 16"
54- viewBox =" 0 0 16 16"
55- fill =" none"
56- xmlns =" http://www.w3.org/2000/svg"
57- class =" flex-none"
58- >
59- <path
60- d =" M3.33333 2V12.6667H14V14H2V2H3.33333ZM13.5287 4.19533L14.4713 5.138L10.6667 8.94267L8.66667 6.94333L5.80467 9.80467L4.862 8.862L8.66667 5.05733L10.6667 7.05667L13.5287 4.19533Z"
61- fill =" #3A3A3A"
62- />
63- </svg >
64- <span class =" block truncate flex-1" >{{ reuse.title }}</span >
65- <span class =" absolute inset-0" />
66- </AppLink >
67- </h4 >
68- <div
69- v-if =" reuse.organization || ownerName"
70- class =" text-sm m-0 flex flex-wrap md:flex-nowrap gap-y-1 items-center truncate"
71- >
72- <template v-if =" reuse .organization " >
73- <div class =" -mr-0.5 flex-initial truncate" >
74- <AppLink
75- v-if =" organizationUrl "
76- class="link text-sm overflow-hidden flex items-center relative z-[2] truncate"
77- :to =" organizationUrl "
78- >
79- <OrganizationNameWithCertificate :organization =" reuse .organization " />
80- </AppLink >
81- <OrganizationNameWithCertificate
82- v-else
83- :organization =" reuse .organization "
84- />
85- </div >
86- </template >
87- <div
88- v-else-if =" ownerName"
89- class =" mr-1 truncate"
90- >
91- {{ ownerName }}
92- </div >
93- </div >
94- <div class =" mx-0 -mb-1 flex flex-wrap items-center text-sm text-gray-medium mt-1" >
95- <ReuseDetails :reuse />
96- </div >
97- <p
98- v-if =" descriptionShort"
99- class =" fr-text--sm fr-mt-1w fr-mb-0 overflow-wrap-anywhere hidden sm:block line-clamp-2"
100- >
101- {{ descriptionShort }}
102- </p >
103- <div
104- v-if =" matchingBadges.length > 0"
105- class =" flex flex-wrap gap-2 mt-2"
106- >
107- <span
108- v-for =" badge in matchingBadges"
109- :key =" badge.value"
110- class =" px-2 py-1 rounded text-white text-xs font-bold"
111- :style =" { backgroundColor: badge.color }"
112- >
113- {{ badge.name }}
114- </span >
115- </div >
116- </div >
117- </div >
118- </article >
119-
120- <!-- Default mode - vertical layout -->
121- <article
122- v-else
123- class =" fr-enlarge-link group/reuse-card bg-white border border-gray-default hover:bg-gray-some flex flex-col relative"
124- >
2+ <article class =" fr-enlarge-link group/reuse-card bg-white border border-gray-default hover:bg-gray-some flex flex-col relative" >
1253 <div class =" flex flex-col h-full flex-1 order-2 px-8" >
1264 <div class =" order-1 flex flex-col px-4 py-1 h-full -mx-8" >
1275 <h3 class =" font-bold text-base mt-1 mb-0 truncate" >
14422 </div >
14523 <ReuseDetails :reuse />
14624 </div >
147- <div
148- v-if =" matchingBadges.length > 0"
149- class =" flex flex-wrap gap-2 mt-2"
150- >
151- <span
152- v-for =" badge in matchingBadges"
153- :key =" badge.value"
154- class =" px-2 py-1 rounded text-white text-xs font-bold"
155- :style =" { backgroundColor: badge.color }"
156- >
157- {{ badge.name }}
158- </span >
159- </div >
16025 </div >
16126 </div >
16227 <div class =" order-1 relative flex-auto" >
19762
19863<script setup lang="ts">
19964import { RiLockLine , RiSubtractLine } from ' @remixicon/vue'
200- import { computed , ref , watchEffect } from ' vue'
65+ import { computed } from ' vue'
20166import type { RouteLocationRaw } from ' vue-router'
20267import { useFormatDate } from ' ../functions/dates'
20368import type { Reuse } from ' ../types/reuses'
20469import { useTranslation } from ' ../composables/useTranslation'
205- import { removeMarkdown } from ' ../functions/markdown'
20670import AppLink from ' ./AppLink.vue'
20771import ObjectCardOwner from ' ./ObjectCardOwner.vue'
20872import ReuseDetails from ' ./ReuseDetails.vue'
20973import Placeholder from ' ./Placeholder.vue'
21074
211- type TagIntoBadge = {
212- name: string
213- value: string
214- color: string
215- }
216-
217- const props = withDefaults (defineProps <{
75+ const props = defineProps <{
21876 reuse: Reuse
21977
22078 /**
@@ -228,34 +86,10 @@ const props = withDefaults(defineProps<{
22886 * It is used as a separate prop to allow other sites using the package to define their own organization pages.
22987 */
23088 organizationUrl? : RouteLocationRaw
231-
232- /**
233- * Enable search mode - displays the card in horizontal layout
234- */
235- search? : boolean
236-
237- tagIntoBadge? : TagIntoBadge []
238- }>(), {
239- search: false ,
240- })
89+ }>()
24190
24291const { t } = useTranslation ()
24392const { formatRelativeIfRecentDate } = useFormatDate ()
24493
24594const reuseUrl = computed (() => props .reuseUrl || props .reuse .page )
246-
247- const descriptionShort = ref (' ' )
248- watchEffect (async () => {
249- if (props .search && props .reuse .description ) {
250- const cleaned = await removeMarkdown (props .reuse .description )
251- // Limit to ~200 characters
252- descriptionShort .value = cleaned .length > 200 ? cleaned .substring (0 , 200 ) + ' ...' : cleaned
253- }
254- })
255-
256- const matchingBadges = computed (() => {
257- if (! props .tagIntoBadge || ! props .reuse .tags ) return []
258- const reuseTags = new Set (props .reuse .tags )
259- return props .tagIntoBadge .filter (badge => reuseTags .has (badge .value ))
260- })
26195 </script >
0 commit comments