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 { moveItem, useGroupedReorder } from "../../../hooks/useGroupedReorder.js";
|
||||||
import { TextExchangeActions } from "./TextExchangeActions.jsx";
|
import { TextExchangeActions } from "./TextExchangeActions.jsx";
|
||||||
|
|
||||||
|
const DISPLAY_NUMBER_FORMATTER = new Intl.NumberFormat("fr-FR", { maximumFractionDigits: 6 });
|
||||||
|
|
||||||
function calculateExpression(expression) {
|
function calculateExpression(expression) {
|
||||||
const normalized = String(expression || "").replaceAll(",", ".").trim();
|
const normalized = String(expression || "").replaceAll(",", ".").trim();
|
||||||
if (!normalized || !/^[\d\s+\-*/().]+$/.test(normalized)) return null;
|
if (!normalized || !/^[\d\s+\-*/().]+$/.test(normalized)) return null;
|
||||||
|
|
@ -24,13 +26,13 @@ function formatResult(value) {
|
||||||
|
|
||||||
function formatDisplayResult(value) {
|
function formatDisplayResult(value) {
|
||||||
if (!Number.isFinite(value)) return "";
|
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) {
|
function getResultLengthClass(value) {
|
||||||
const length = formatResult(value).replace(/[^\d]/g, "").length;
|
const length = formatResult(value).replace(/[^\d]/g, "").length;
|
||||||
if (length >= 16) return "is-compact";
|
if (length >= 13) return "is-compact";
|
||||||
if (length >= 12) return "is-long";
|
if (length >= 9) return "is-long";
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -47,6 +49,21 @@ function getEntriesInTreeOrder(entries, parentId = "") {
|
||||||
return getChildren(entries, parentId).flatMap((entry) => [entry, ...getEntriesInTreeOrder(entries, entry.id)]);
|
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 }) {
|
export function CalculatorModule({ toolboxId, moduleId, context, editing }) {
|
||||||
const data = context.normalizeCalculatorData(context.getModuleData(toolboxId, moduleId, { entries: [] }));
|
const data = context.normalizeCalculatorData(context.getModuleData(toolboxId, moduleId, { entries: [] }));
|
||||||
const textContent = context.moduleText?.calculator || {};
|
const textContent = context.moduleText?.calculator || {};
|
||||||
|
|
@ -165,7 +182,9 @@ export function CalculatorModule({ toolboxId, moduleId, context, editing }) {
|
||||||
</label>
|
</label>
|
||||||
<div className={`calculator-result ${result == null ? "" : getResultLengthClass(result)}`} aria-live="polite">
|
<div className={`calculator-result ${result == null ? "" : getResultLengthClass(result)}`} aria-live="polite">
|
||||||
<span>{textContent.resultLabel || "Résultat"}</span>
|
<span>{textContent.resultLabel || "Résultat"}</span>
|
||||||
<strong>{result == null ? "-" : formatDisplayResult(result)}</strong>
|
<strong aria-label={result == null ? "-" : formatDisplayResult(result)}>
|
||||||
|
<FormattedCalculatorNumber value={result} />
|
||||||
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
<label>
|
<label>
|
||||||
<span>{textContent.labelLabel || "Libellé"}</span>
|
<span>{textContent.labelLabel || "Libellé"}</span>
|
||||||
|
|
@ -245,14 +264,18 @@ function CalculatorEntries({ entries, parentId, getScopedParentId, activeParentI
|
||||||
{entry.id === editingId ? (
|
{entry.id === editingId ? (
|
||||||
<>
|
<>
|
||||||
<span className="tool-split-entry-value is-readonly" title={textContent.readonlyValueTitle || "Quantité non modifiable"}>
|
<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>
|
</span>
|
||||||
<EditableCalculatorLabel entry={entry} textContent={textContent} onRename={onRename} onDone={() => setEditingId("")} />
|
<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"}>
|
<button className="tool-split-entry-summary" type="button" onClick={() => onUse(entry)} title={textContent.useEntryTitle || "Utiliser comme base"}>
|
||||||
<span>
|
<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>}
|
{entry.label && <em>{entry.label}</em>}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -5216,13 +5216,24 @@ button.combo-input-token.combo-value-grab .ui-icon {
|
||||||
.calculator-entry .tool-split-entry-summary strong,
|
.calculator-entry .tool-split-entry-summary strong,
|
||||||
.calculator-entry .tool-split-entry-value strong {
|
.calculator-entry .tool-split-entry-value strong {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
text-overflow: ellipsis;
|
font-variant-numeric: tabular-nums;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calculator-entry .tool-split-entry-summary strong {
|
.calculator-entry .tool-split-entry-summary strong {
|
||||||
flex: 0 1 auto;
|
flex: 0 0 auto;
|
||||||
|
font-size: var(--font-size-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculator-entry .tool-split-entry-summary strong.is-long,
|
||||||
|
.calculator-entry .tool-split-entry-value strong.is-long {
|
||||||
|
font-size: var(--font-size-xs);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculator-entry .tool-split-entry-summary strong.is-compact,
|
||||||
|
.calculator-entry .tool-split-entry-value strong.is-compact {
|
||||||
|
font-size: 0.68rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calculator-entry .tool-split-entry-summary em {
|
.calculator-entry .tool-split-entry-summary em {
|
||||||
|
|
@ -5235,6 +5246,20 @@ button.combo-input-token.combo-value-grab .ui-icon {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.calculator-number-group {
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculator-number-group.is-muted,
|
||||||
|
.calculator-number-separator {
|
||||||
|
color: rgba(180, 189, 211, 0.68);
|
||||||
|
}
|
||||||
|
|
||||||
|
.calculator-number-separator {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 0.24em;
|
||||||
|
}
|
||||||
|
|
||||||
.calculator-form label span,
|
.calculator-form label span,
|
||||||
.calculator-result span,
|
.calculator-result span,
|
||||||
.tool-split-root-button {
|
.tool-split-root-button {
|
||||||
|
|
@ -5258,23 +5283,23 @@ button.combo-input-token.combo-value-grab .ui-icon {
|
||||||
display: block;
|
display: block;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
overflow: hidden;
|
overflow: visible;
|
||||||
color: var(--color-text-primary);
|
color: var(--color-text-primary);
|
||||||
font-size: clamp(1.55rem, 3vw, 2.15rem);
|
font-size: clamp(1.55rem, 3vw, 2.15rem);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
font-weight: 900;
|
font-weight: 900;
|
||||||
line-height: 0.95;
|
line-height: 0.95;
|
||||||
text-align: right;
|
text-align: right;
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calculator-result.is-long strong {
|
.calculator-result.is-long strong {
|
||||||
font-size: 1.55rem;
|
font-size: 1.18rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.calculator-result.is-compact strong {
|
.calculator-result.is-compact strong {
|
||||||
font-size: 1.25rem;
|
font-size: 0.92rem;
|
||||||
line-height: 1.05;
|
line-height: 1.05;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue