Polish calculator large number readability
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s
This commit is contained in:
parent
9176f3b8a8
commit
e4803aa14f
2 changed files with 61 additions and 13 deletions
|
|
@ -5,6 +5,8 @@ import { useInlineEdit } from "../../../hooks/useInlineEdit.js";
|
|||
import { moveItem, useGroupedReorder } from "../../../hooks/useGroupedReorder.js";
|
||||
import { TextExchangeActions } from "./TextExchangeActions.jsx";
|
||||
|
||||
const DISPLAY_NUMBER_FORMATTER = new Intl.NumberFormat("fr-FR", { maximumFractionDigits: 6 });
|
||||
|
||||
function calculateExpression(expression) {
|
||||
const normalized = String(expression || "").replaceAll(",", ".").trim();
|
||||
if (!normalized || !/^[\d\s+\-*/().]+$/.test(normalized)) return null;
|
||||
|
|
@ -24,13 +26,13 @@ function formatResult(value) {
|
|||
|
||||
function formatDisplayResult(value) {
|
||||
if (!Number.isFinite(value)) return "";
|
||||
return new Intl.NumberFormat("fr-FR", { maximumFractionDigits: 6 }).format(Number.parseFloat(value.toFixed(6)));
|
||||
return DISPLAY_NUMBER_FORMATTER.format(Number.parseFloat(value.toFixed(6)));
|
||||
}
|
||||
|
||||
function getResultLengthClass(value) {
|
||||
const length = formatResult(value).replace(/[^\d]/g, "").length;
|
||||
if (length >= 16) return "is-compact";
|
||||
if (length >= 12) return "is-long";
|
||||
if (length >= 13) return "is-compact";
|
||||
if (length >= 9) return "is-long";
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
@ -47,6 +49,21 @@ function getEntriesInTreeOrder(entries, parentId = "") {
|
|||
return getChildren(entries, parentId).flatMap((entry) => [entry, ...getEntriesInTreeOrder(entries, entry.id)]);
|
||||
}
|
||||
|
||||
function FormattedCalculatorNumber({ value }) {
|
||||
if (!Number.isFinite(value)) return "-";
|
||||
let integerGroupIndex = 0;
|
||||
const normalized = Number.parseFloat(value.toFixed(6));
|
||||
return DISPLAY_NUMBER_FORMATTER.formatToParts(normalized).map((part, index) => {
|
||||
if (part.type === "integer") {
|
||||
const className = `calculator-number-group ${integerGroupIndex % 2 ? "is-muted" : "is-strong"}`;
|
||||
integerGroupIndex += 1;
|
||||
return <span className={className} key={`${part.type}-${index}`}>{part.value}</span>;
|
||||
}
|
||||
if (part.type === "group") return <span className="calculator-number-separator" key={`${part.type}-${index}`}>{part.value}</span>;
|
||||
return <span key={`${part.type}-${index}`}>{part.value}</span>;
|
||||
});
|
||||
}
|
||||
|
||||
export function CalculatorModule({ toolboxId, moduleId, context, editing }) {
|
||||
const data = context.normalizeCalculatorData(context.getModuleData(toolboxId, moduleId, { entries: [] }));
|
||||
const textContent = context.moduleText?.calculator || {};
|
||||
|
|
@ -165,7 +182,9 @@ export function CalculatorModule({ toolboxId, moduleId, context, editing }) {
|
|||
</label>
|
||||
<div className={`calculator-result ${result == null ? "" : getResultLengthClass(result)}`} aria-live="polite">
|
||||
<span>{textContent.resultLabel || "Résultat"}</span>
|
||||
<strong>{result == null ? "-" : formatDisplayResult(result)}</strong>
|
||||
<strong aria-label={result == null ? "-" : formatDisplayResult(result)}>
|
||||
<FormattedCalculatorNumber value={result} />
|
||||
</strong>
|
||||
</div>
|
||||
<label>
|
||||
<span>{textContent.labelLabel || "Libellé"}</span>
|
||||
|
|
@ -245,14 +264,18 @@ function CalculatorEntries({ entries, parentId, getScopedParentId, activeParentI
|
|||
{entry.id === editingId ? (
|
||||
<>
|
||||
<span className="tool-split-entry-value is-readonly" title={textContent.readonlyValueTitle || "Quantité non modifiable"}>
|
||||
<strong>{formatDisplayResult(entry.value)}</strong>
|
||||
<strong className={getResultLengthClass(entry.value)} aria-label={formatDisplayResult(entry.value)}>
|
||||
<FormattedCalculatorNumber value={entry.value} />
|
||||
</strong>
|
||||
</span>
|
||||
<EditableCalculatorLabel entry={entry} textContent={textContent} onRename={onRename} onDone={() => setEditingId("")} />
|
||||
</>
|
||||
) : (
|
||||
<button className="tool-split-entry-summary" type="button" onClick={() => onUse(entry)} title={textContent.useEntryTitle || "Utiliser comme base"}>
|
||||
<span>
|
||||
<strong>{formatDisplayResult(entry.value)}</strong>
|
||||
<strong className={getResultLengthClass(entry.value)} aria-label={formatDisplayResult(entry.value)}>
|
||||
<FormattedCalculatorNumber value={entry.value} />
|
||||
</strong>
|
||||
{entry.label && <em>{entry.label}</em>}
|
||||
</span>
|
||||
</button>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue