import {Controls, Canvas, Meta, Source} from '@storybook/addon-docs/blocks';
import '../../stories/styles/shared.css';

import * as FilePreviewStories from './FilePreview.stories.ts'

<Meta of={FilePreviewStories} />

<div className="header">
  <h1>FilePreview</h1>
  <p>L'élément `FilePreview` est utilisé pour afficher l'aperçu d'un fichier.</p>
</div>

{/* func-version-start */}
<p className="func-version-badge">Dernière mise à jour fonctionnelle : V1.1.3 - 27/07/2026</p>
{/* func-version-end */}
{/* a11y-version-start */}
<p className="a11y-version-badge">Dernière mise à jour accessibilité : V1.1.3 - 22/07/2026</p>
{/* a11y-version-end */}


<Canvas of={FilePreviewStories.Default} />

# API

<Controls of={FilePreviewStories.Default} />

# Exemple

## Afficher un fichier depuis une API

Vous pouvez afficher une image ou un fichier PDF récupéré depuis une API sous forme de `Blob`.

<Canvas
	of={FilePreviewStories.FromApi}
	source={{
		language: 'html',
		format: 'dedent',
		code: `
		<script lang="ts" setup>
			import { onMounted, ref } from 'vue'
			import { FilePreview } from '@cnamts/synapse'

			const file = ref<File | Blob | undefined>()

			onMounted(() => {
				fetch('https://picsum.photos/seed/picsum/750/350')
					.then(res => res.blob())
					.then(blob => file.value = blob)
			})
		</script>

		<template>
			<FilePreview :file="file" />
		</template>
		`,
	}}
/>

## Fichier non supporté

Lorsque le fichier n'est pas supporté, un message d'erreur est affiché.

<Canvas of={FilePreviewStories.UnsupportedFile} />

## Usage avec `FileUpload`

Vous pouvez utiliser ce composant en combinaison avec `FileUpload` pour afficher un aperçu du fichier avant de l'envoyer.

<Canvas
	of={FilePreviewStories.WithFileUpload}
	source={{
		language: 'html',
		format: 'dedent',
		code: `
		<script lang="ts" setup>
			import { ref } from 'vue'
			import { FilePreview, FileUpload } from '@cnamts/synapse'

			const files = ref<File[]>
([])
		</script>
		<template>
			<div>
				<FileUpload v-model="files" class="mb-4"/>
				<FilePreview :file="files[0]"/>
			</div>
		</template>
		`,
	}}
/>

## Aperçu en lecture seule (sans téléchargement)

Par défaut, l'aperçu PDF utilise le lecteur natif du navigateur (`<object>`), qui affiche une barre d'outils (téléchargement, impression, annotation…). Le viewer natif **ne permet pas** de masquer ces actions de façon fiable (`#toolbar=0` n'est pas honoré partout, et `Ctrl/Cmd+S` reste possible).

Pour un aperçu **en lecture seule** — l'utilisateur peut consulter le document mais pas le télécharger, l'imprimer ni l'annoter — activez la prop **`readonly`**. Le PDF est alors rendu via **pdf.js** (chargé à la demande), sans aucune barre d'outils native.

> **Événement `@loaded`** — émis avec le nombre de pages dès que le PDF est rendu via pdf.js (que ce soit en `readonly` ou en `track-consultation`). C'est un signal de **rendu**, indépendant du suivi de consultation. Il n'est **pas** émis en mode natif par défaut (`<object>`) ni pour les images.

<Canvas of={FilePreviewStories.ReadOnly} />

<Source dark code={`
<template>
  <FilePreview :file="file" readonly />
</template>

<script setup lang="ts">
  import { ref } from 'vue'
  import { FilePreview } from '@cnamts/synapse'

  const file = ref<File | undefined>()
</script>
`} />

> **Limite** : côté navigateur, aucun rendu ne garantit l'inviolabilité absolue (capture d'écran, récupération du flux via les outils de développement…). `readonly` retire les chemins **normaux** d'export (barre d'outils, téléchargement, impression, clic droit), ce qui couvre le besoin métier, mais ne constitue pas une protection de type DRM.

## Suivi de consultation (lecture obligatoire)

Par défaut, l'aperçu PDF utilise le lecteur natif du navigateur (`<object>`), qui ne permet pas de savoir si le document a été consulté.

Pour les parcours où une action (cocher une case, activer un bouton…) doit être conditionnée à la **consultation complète** d'un PDF, activez la prop **`track-consultation`**. Le PDF est alors rendu via **pdf.js** (chargé à la demande, donc sans impact sur le bundle si la fonctionnalité n'est pas utilisée) dans un conteneur scrollable. L'état de consultation est exposé via **`v-model:complete`** :

- **`v-model:complete`** — booléen synchronisé : passe à `true` quand l'utilisateur a fait défiler le document jusqu'à la fin (ou si le document tient entièrement dans le conteneur sans scroll), et revient à `false` au chargement d'un nouveau document.

L'événement **`@loaded`** (décrit dans la section [Aperçu en lecture seule](#aperçu-en-lecture-seule-sans-téléchargement)) est également disponible ici, comme pour tout rendu pdf.js.

<Canvas of={FilePreviewStories.MandatoryReading} />

<Source dark code={`
<template>
  <FilePreview
    :file="file"
    track-consultation
    v-model:complete="hasRead"
  />

  <SyCheckbox
    v-model="acknowledged"
    color="primary"
    :disabled="!hasRead"
    label="J'ai pris connaissance de l'intégralité du document"
  />
</template>

<script setup lang="ts">
  import { ref } from 'vue'
  import { FilePreview, SyCheckbox } from '@cnamts/synapse'

  const file = ref<File | undefined>()
  const hasRead = ref(false)
  const acknowledged = ref(false)
</script>
`} />

### Points d'attention

- **Rétrocompatibilité** : `track-consultation` et `readonly` sont `false` par défaut → comportement actuel (`<object>`) inchangé. N'ont d'effet que sur les fichiers PDF.
- **Combinables** : `readonly` et `track-consultation` reposent sur le même rendu pdf.js et se cumulent — par ex. un contrat à lire en entier **sans** pouvoir le télécharger : `<FilePreview readonly track-consultation v-model:complete="hasRead" />`.
- **Worker pdf.js** : le worker bundlé est utilisé par défaut. Si votre chaîne de build ne le résout pas, fournissez une URL via la prop `pdf-worker-src`.
- **Accessibilité** : le rendu pdf.js (canvas) n'est pas restituable au lecteur d'écran ; prévoyez un accès alternatif au contenu si nécessaire (lien de téléchargement…).