// Catalogue visuel des primitives officielles.
// Accessible en développement avec ?ui-kit=1, sans session ni données métier.
// L’encre du « rien à faire ici » : le hachuré des heures révolues et le fond
// des journées de congé partagent la même teinte neutre, à la même densité.
const UI_KIT_ABSENT_TINT = 'rgba(10,10,10,0.06)';
const UI_KIT_ABSENT_HATCH = 'repeating-linear-gradient(135deg, rgba(10,10,10,0.05) 0 5px, rgba(10,10,10,0) 5px 11px)';
function VascoUiKitSection({ title, children }) {
const tokens = window.VascoUI.tokens;
return
{title}
{children}
;
}
function VascoUiKitIcon({ kind }) {
const paths = {
profile: <>>,
bell: <>>,
trash: ,
};
return paths[kind] || paths.profile;
}
// Contexte manquant du catalogue : un panneau qui se ferme sur un appui né
// hors de sa boîte, comme la cloche « Rappels » de la référence gelée. Ce n'est
// pas une primitive concurrente, c'est le décor qui permet de démontrer qu'une
// feuille du socle ne laisse pas fuir ses appuis jusqu'à `document`. Sans cette
// retenue, le premier jour touché dans le calendrier fermait ce panneau et
// emportait la feuille avec lui.
function VascoUiKitOutsidePanel({ children }) {
const { tokens, Button } = window.VascoUI;
const [open, setOpen] = React.useState(false);
const boxRef = React.useRef(null);
React.useEffect(() => {
if (!open) return undefined;
const closeOutside = (event) => {
if (!boxRef.current?.contains(event.target)) setOpen(false);
};
document.addEventListener('mousedown', closeOutside);
return () => document.removeEventListener('mousedown', closeOutside);
}, [open]);
return
{open &&
{children}
}
;
}
// Deux populations de démonstration, sans donnée réelle : le catalogue montre
// ce que l'onglet change, le filtrage vrai reste au serveur.
const UI_KIT_SCOPED_PATIENTS = {
living: [
['kit-p1', 'MARTIN Jean', 'IPP VASCO-000001 · 62 ans'],
['kit-p2', 'PETIT Aline', 'IPP VASCO-000002 · 54 ans'],
],
deceased: [
['kit-p3', 'THOMAS Gabriel', 'IPP VASCO-000006 · décédé'],
],
};
function VascoUiKitScreen() {
const { tokens, Button, IconButton, InlineAction, ChoiceChip, InteractiveRow, StatusNotice,
SettingGroup, SettingRow, Toggle,
FormSheet, BottomSheet, DetailSheet, ConfirmDialog,
Field, TextField, SimpleSelect, SearchSelect, CreatableSelect, DayPicker,
ScreenHeader, icons } = window.VascoUI;
const [notifications, setNotifications] = React.useState(true);
const [displayName, setDisplayName] = React.useState('Dr. Camille Martin');
const [multiline, setMultiline] = React.useState('');
const [days, setDays] = React.useState('3');
const [invalidText, setInvalidText] = React.useState('Valeur refusée');
const [role, setRole] = React.useState('doctor');
const [practitioner, setPractitioner] = React.useState('martin');
// La recherche à onglets : deux populations distinctes, une seule primitive.
// Le catalogue joue le filtrage que le serveur fait en vrai.
const [scope, setScope] = React.useState('living');
const [scopedPatient, setScopedPatient] = React.useState(null);
const [category, setCategory] = React.useState('cro');
// Les dates du catalogue sont fixes : une démonstration ne doit pas changer
// de rendu selon le jour où on la regarde.
const [controlDay, setControlDay] = React.useState('2026-09-24');
const [compactDay, setCompactDay] = React.useState('2026-09-24');
const [leave, setLeave] = React.useState({ start: '2026-09-10', end: '2026-09-13' });
const [due, setDue] = React.useState('2026-09-24T18:00');
const [panelDue, setPanelDue] = React.useState('2026-09-24T18:00');
const [categories, setCategories] = React.useState([
['cro', 'Compte rendu opératoire'], ['staff', 'Compte rendu de staff'],
['biology', 'Biologie'],
]);
const [sheetOpen, setSheetOpen] = React.useState(false);
const [bottomSheetOpen, setBottomSheetOpen] = React.useState(false);
const [detailOpen, setDetailOpen] = React.useState(false);
const [sideDetailOpen, setSideDetailOpen] = React.useState(false);
const [confirmOpen, setConfirmOpen] = React.useState(false);
const swatches = [
['Accent', tokens.color.accent], ['Succès', tokens.color.success],
['Attention', tokens.color.warning], ['Danger', tokens.color.danger],
];
return RÉFÉRENCE} />
Les écrans Vasco réutilisent ces composants et leurs états. Une variation métier compose ces primitives ; elle ne les redessine pas.
{swatches.map(([label, color]) =>
{label}
)}
ModifierSupprimerActifsArchivés
} style={{ marginTop: 10 }} />
} label="Ligne interactive"
sub="Information secondaire" onClick={() => {}} />
} label="Notifications"
sub="État contrôlé par la ligne" role="switch" checked={notifications}
onClick={() => setNotifications((value) => !value)}
right={} />
} label="Action indisponible"
reason="La raison reste visible." danger />
Le panneau se ferme dès qu'un appui naît hors de sa boîte. Une feuille du
socle ouverte depuis lui retient ses propres appuis : choisir un jour, une
heure, puis « Terminé » ne le referme pas, et toucher le fond de la feuille
la referme sans changer la valeur.
{/* Une journée sans travail possible : congé posé, heures révolues. Elle
se lit en GRIS, jamais en rouge – le rouge est celui du danger, et
partir en vacances n’en est pas un. La même encre sert au hachuré de
l’axe et au fond de la cellule de jour, pour que « rien à faire ici »
se dise d’une seule façon. Ce qui reste posé dessus se lit par-dessus :
la hachure ne cache rien. */}