gestion_table_tournante_libre/src/interface/marques.js
Mathieu Benoit c6082c3af2 [IMP] proposals, generation, badges, preview: cards and grouped headers
The proposal table had a dozen measure columns with no grouping. Five
group headers now gather neighbouring measures without changing any
column text; numbers align right in tabular figures, and the kept
placement row wears the Retenu tint and a « retenue » pill. Generation
settings and progress, badges and the paper choice become cards, each
paper a distinct choice; the preview toolbar groups its commands. The
printed paper is unchanged. Checked: node 172, browser 162.

--- FR ---

[IMP] propositions, génération, badges, aperçu : cartes, intitulés

Le tableau des propositions alignait une douzaine de mesures sans
groupe. Cinq intitulés de groupe réunissent les mesures voisines sans
changer le texte d'aucune colonne ; les nombres s'alignent à droite en
chiffres tabulaires, la ligne du retenu porte la teinte Retenu et une
pastille « retenue ». Réglages et avancement, badges et papier
deviennent des cartes, chaque papier un choix distinct ; la barre de
l'aperçu groupe ses commandes. Le papier imprimé ne change pas.
Vérifié : node 172, navigateur 162.

Assisted-by: Claude Opus 5.5
2026-10-11 00:58:07 -04:00

197 lines
11 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// Registre des marques porteuses d'information et des textes (§ 14.5,
// § 7.5, § 7.6, § 7.7). Chaque entrée nomme le jeton qui la peint et chaque
// jeton sur lequel elle se peint ; verifierPalette (palette.js) mesure le
// seuil de chaque couple dans les deux thèmes, sous les trois dichromaties,
// et les épreuves de rendu atteignent la marque par data-marque, qui porte
// son nom.
//
// Les remplissages d'une chaise sont son fond, son remplissage plein et les
// deux couleurs de la hachure — des traits --couleur-hachure sur le fond de
// la chaise : une marque posée sur une chaise se mesure sur chacun.
//
// Deux registres de marques : MARQUES, celles que les écrans rendent sous
// data-marque et que les épreuves de rendu mesurent sur ce qui est peint
// dessous ; SIGNES, celles des pastilles, des messages, de la bande de mode
// et de l'action principale, qui se valident par calcul sur chacun de leurs
// fonds. Un signe ne porte jamais seul une information : un libellé
// l'accompagne toujours.
const c = (nom) => `--couleur-${nom}`;
const REMPLISSAGES_CHAISE = ['chaise-fond', 'chaise-pleine', 'hachure'];
function entree(nom, jeton, fonds, seuil) {
return Object.freeze({ nom, jeton: c(jeton), fonds: Object.freeze(fonds.map(c)), seuil });
}
const marque = (nom, jeton, fonds) => entree(nom, jeton, fonds, 3);
const texte = (nom, jeton, fonds) => entree(nom, jeton, fonds, 4.5);
// Les sortes de conflit : règle, marque de la trame, jeton court, forme.
const SORTES_CONFLIT = [
['separerAppartenances', 'trameAppartenance', 'conflit-appartenance', 'hachuresDescendantes'],
['nouveauxVoisins', 'trameVoisins', 'conflit-voisins', 'hachuresMontantes'],
['nouvelleTable', 'trameTable', 'conflit-table', 'points'],
];
/** Les trois sortes de conflit qu'une table porte (§ 7.5, § 12.7), une par
* règle que le moteur localise (conflitsParTable), dans son ordre — l'ordre
* du dessin, de la légende et de l'infobulle : { regle, marque, jeton,
* forme } — la règle du moteur, la marque data-marque de sa trame, le jeton
* de sa teinte, réservée à cette trame, et la forme de son motif
* (Motifs.svelte), qui la distingue sans la couleur. Deux règles violées à
* une même table superposent leurs trames : les hachures descendantes et
* montantes se croisent en quadrillage, les points se posent par-dessus. */
export const CONFLITS = Object.freeze(
SORTES_CONFLIT.map(([regle, trame, jeton, forme]) => Object.freeze({ regle, marque: trame, jeton: c(jeton), forme })),
);
/** Les jetons des teintes de conflit, dans l'ordre de CONFLITS. */
export const JETONS_CONFLIT = Object.freeze(CONFLITS.map(({ jeton }) => jeton));
/** Écarts perçus minimaux d'une teinte de conflit, en distance OKLab × 100
* mesurée en couleurs d'origine et sous chaque dichromatie (ecartPercu,
* palette.js) : entreConflits, d'une teinte de conflit à une autre — la
* couleur redit la forme de la règle ; autresMarques, d'une teinte de
* conflit à chaque autre marque du plan. Le second seuil est plus bas : les
* gris du mobilier occupent la clarté où une teinte de conflit tient 3:1
* sur le plateau sombre, et la forme distingue toujours la trame de ce
* qu'elle côtoie. Sa valeur, 5, ne vient d'aucune référence de perception :
* elle se pose juste sous la plus petite séparation que la palette tient
* entre une teinte de conflit et une autre marque, et garde la palette de
* reculer sans établir qu'un écart de 5 se perçoit. */
export const SEPARATIONS = Object.freeze({ entreConflits: 12, autresMarques: 5, entreAppartenances: 10, clarteAppartenances: 10 });
/** La palette catégorielle des appartenances, sur les listes seulement —
* jamais sur le plan, dont le canal chromatique appartient aux conflits :
* { rang, marque, fond }, rang de 1 à n, le jeton de son point et celui du
* fond de sa pastille. Ses marques se séparent deux à deux de
* SEPARATIONS.entreAppartenances sous les trois dichromaties, et deux
* teintes voisines de SEPARATIONS.clarteAppartenances en clarté
* (verifierClartes) : six teintes au plus tiennent ces deux seuils à 3:1
* sur la carte. Au-delà de n appartenances, la pastille est neutre
* (appartenances.js). */
export const TEINTES_APPARTENANCE = Object.freeze(
[1, 2, 3, 4, 5, 6].map((rang) =>
Object.freeze({ rang, marque: c(`appartenance-${rang}-marque`), fond: c(`appartenance-${rang}-fond`) }),
),
);
// Les surfaces de contenu sur lesquelles une pastille se pose.
const SURFACES = ['carte-fond', 'carte-fond-sourd', 'page-fond'];
// Les teintes d'une pastille dont la marque se pose aussi hors de son fond.
const TEINTES_DE_PASTILLE = [
['etatBrouillon', 'etat-brouillon'],
['etatPropose', 'etat-propose'],
['etatRetenu', 'etat-retenu'],
['etatBloque', 'etat-bloque'],
['neutre', 'neutre'],
...TEINTES_APPARTENANCE.map(({ rang }) => [`appartenance${rang}`, `appartenance-${rang}`]),
];
/** Les signes, même forme que MARQUES, seuil 3 : l'icône ou le point d'une
* pastille sur son fond teinté et sur les surfaces de contenu ; l'icône
* d'un message sur son fond ; l'icône de la bande de mode, de la teinte du
* cadre de mode, sur le fond de la bande ; le fond de l'action principale,
* qui délimite le bouton, sur les surfaces. */
export const SIGNES = Object.freeze([
...TEINTES_DE_PASTILLE.map(([nom, teinte]) => marque(nom, `${teinte}-marque`, [`${teinte}-fond`, ...SURFACES])),
marque('signeAvis', 'avis-marque', ['avis-fond']),
marque('signeRefus', 'refus-marque', ['refus-fond']),
marque('signeInformation', 'information-marque', ['information-fond']),
marque('bandeEcriture', 'cadre-ecriture', ['mode-ecriture-fond']),
marque('bandeLecture', 'cadre-lecture', ['mode-lecture-fond']),
marque('bandeBloque', 'cadre-bloque', ['mode-bloque-fond']),
marque('actionPrincipale', 'action-fond', SURFACES),
]);
/** Les marques porteuses d'information (§ 14.5) : { nom, jeton, fonds, seuil: 3 } — nom, la
* désignation data-marque ; jeton, celui qui la peint ; fonds, chaque jeton sur lequel elle
* se peint, chaque remplissage d'une chaise pour une marque qui passe sur une chaise. */
export const MARQUES = Object.freeze([
// Sur la chaise (§ 7.6) : cadenas posés sur ses remplissages ; l'anneau
// l'entoure, sur le sol et le bord du plateau qu'elle touche.
marque('cadenasFerme', 'marque', REMPLISSAGES_CHAISE),
marque('cadenasOuvert', 'marque', REMPLISSAGES_CHAISE),
marque('anneau', 'marque', ['sol', 'table-fond', ...REMPLISSAGES_CHAISE]),
marque('hachure', 'hachure', ['chaise-fond']),
marque('remplissagePlein', 'chaise-pleine', ['sol', 'table-fond']),
// Le conflit (§ 7.5) : contour épaissi sur le sol, commun aux trois
// règles et peint de l'encre forte du plan ; une trame par règle violée
// sur le plateau, chacune de sa teinte, ses traits détachés par un halo
// du fond du plateau ; pastille chiffrée près de la table.
marque('contourConflit', 'contour-fort', ['sol', 'table-fond']),
...SORTES_CONFLIT.map(([, trame, jeton]) => marque(trame, jeton, ['table-fond'])),
marque('pastille', 'pastille-fond', ['sol', 'table-fond']),
marque('poignee', 'poignee', ['sol']),
marque('gel', 'gel', ['sol', 'table-fond']),
// La désignation se pose sur la page, le sol, le plateau et une chaise
// vide, pourvue ou à pourvoir : chacun de ses remplissages est un fond.
marque('miseEnEvidence', 'mise-en-evidence', ['page-fond', 'sol', 'table-fond', ...REMPLISSAGES_CHAISE]),
// La sélection marque aussi une colonne du tableau des propositions, sur la
// carte, son fond sourd et la ligne du retenu.
marque('selection', 'selection', ['page-fond', 'carte-fond', 'carte-fond-sourd', 'etat-retenu-fond', 'sol', 'table-fond', ...REMPLISSAGES_CHAISE]),
// Le cadre de mode (§ 8.4) entoure le contenu de l'événement, sur la page.
marque('cadreLecture', 'cadre-lecture', ['page-fond']),
marque('cadreEcriture', 'cadre-ecriture', ['page-fond']),
marque('cadreBloque', 'cadre-bloque', ['page-fond']),
marque('focus', 'focus', ['page-fond', 'bandeau-fond', 'carte-fond', 'carte-fond-sourd', 'etat-retenu-fond', 'action-teinte', 'sol', 'table-fond', ...REMPLISSAGES_CHAISE]),
// Le mobilier sur le sol : le trait de la table, celui de la chaise, qui
// touche aussi le plateau.
marque('contourTable', 'table-trait', ['sol']),
marque('contourChaise', 'chaise-trait', ['sol', 'table-fond']),
// L'échelle graphique (§ 7.7) vit dans la surface du plan, sur le sol ou la
// page ; le fantôme d'un glissement passe sur le sol, les tables et les
// chaises.
marque('echelle', 'echelle', ['sol', 'page-fond']),
marque('fantome', 'fantome', ['sol', 'table-fond', ...REMPLISSAGES_CHAISE]),
// Le signe du chargement d'une valeur de la liste des événements (§ 8.1) :
// un arc tracé de l'encre secondaire, dans une cellule du tableau, sur la
// carte.
marque('chargement', 'page-texte-secondaire', ['carte-fond']),
// Le filigrane BROUILLON (§ 11.7) : un texte au trait, par-dessus le
// contenu d'une feuille imprimée, mesuré sur le papier, clair dans les
// deux thèmes.
marque('filigrane', 'filigrane', ['papier']),
]);
// Les fonds teintés d'une pastille : ceux de ses teintes, puis ceux des
// messages, qu'un statut reprend, et la teinte de l'action.
const FONDS_ETIQUETTE = [
...TEINTES_DE_PASTILLE.map(([, teinte]) => `${teinte}-fond`),
'avis-fond',
'refus-fond',
'information-fond',
'action-teinte',
];
/** Les textes et leurs fonds, même forme, seuil 4,5 : page, secondaire,
* bandeau, refus, avis, listes du plan sur le sol, pastille du plan ; puis
* l'encre de la page sur la carte, l'encre secondaire sur la carte, le
* texte d'une étiquette — l'encre de la page sur chaque fond teinté de
* pastille (§ 12.7) —, celui de la bande de mode, la version et la
* provenance du bandeau, le thème retenu du bandeau, aux couleurs du
* bandeau inversées, le texte de l'action principale, un lien ou un texte
* mis en valeur de l'encre de l'action, et l'information. Le refus, l'avis
* et l'information gardent l'encre de leur message, sur son fond. */
export const TEXTES = Object.freeze([
texte('page', 'page-texte', ['page-fond']),
texte('secondaire', 'page-texte-secondaire', ['page-fond']),
texte('bandeau', 'bandeau-texte', ['bandeau-fond']),
texte('refus', 'refus', ['page-fond', 'refus-fond', 'carte-fond']),
texte('avis', 'avis', ['page-fond', 'avis-fond', 'carte-fond']),
texte('listes', 'liste-texte', ['sol']),
texte('pastille', 'pastille-texte', ['pastille-fond']),
texte('carte', 'page-texte', ['carte-fond', 'carte-fond-sourd']),
texte('secondaireCarte', 'page-texte-secondaire', ['carte-fond', 'carte-fond-sourd']),
texte('etiquette', 'page-texte', FONDS_ETIQUETTE),
texte('bandeMode', 'page-texte', ['mode-ecriture-fond', 'mode-lecture-fond', 'mode-bloque-fond']),
texte('bandeauSecondaire', 'bandeau-texte-secondaire', ['bandeau-fond']),
texte('bandeauChoisi', 'bandeau-fond', ['bandeau-texte']),
texte('action', 'action-texte', ['action-fond']),
texte('lien', 'action-encre', ['page-fond', 'carte-fond', 'carte-fond-sourd', 'action-teinte']),
texte('information', 'information', ['information-fond', 'page-fond', 'carte-fond']),
]);