Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | 76x 53x 12x 12x 72x 318x 282x 53x 312x 126x 267x 119x 22x 53x 97x | import { useMemo } from "react";
import objectDefinitions from "@/data/objects.json";
import {
type AggregateSuggestion,
getAggregateFunctionOptions,
getAggregateKeyInsertionText,
} from "./aggregateFormula";
type AggregatePropertySchema = {
/** Human-facing property label from the object schema. */
displayName?: string;
/** Indexed properties are excluded because aggregate formulas are scalar. */
indexSets?: string[];
/** Only numeric properties can participate in aggregate expressions. */
type?: string;
};
type AggregateSourceObject = {
/** Object schema key used to discover which property keys are available. */
objectType?: string | null;
};
type AggregateFormulaSuggestions = {
/** All scalar numeric property keys available on the current flowsheet. */
aggregateKeyOptions: AggregateSuggestion[];
/** Plain-text snippets offered by the aggregate function mention source. */
aggregateFunctionSuggestions: AggregateSuggestion[];
/** Plain-text snippets offered by the aggregate property-key mention source. */
aggregateKeySuggestions: AggregateSuggestion[];
};
type AggregateFormulaSuggestionParams = {
/** Unit operations currently present in the flowsheet. */
flowsheetUnitOps?: AggregateSourceObject[];
/** User-visible formula text, with mention markup converted to display text. */
plainFormula: string;
/** Caret position in `plainFormula`. */
cursorPosition: number;
};
const aggregateObjectDefinitions = objectDefinitions as unknown as Record<
string,
{ properties?: Record<string, AggregatePropertySchema> }
>;
/**
* Build autocomplete data for aggregate formula authoring.
*
* `flowsheetUnitOps` determines the property keys that can be suggested.
* `plainFormula` and `cursorPosition` let property-key suggestions decide
* whether the selected key should also insert the closing aggregate paren.
*
* The returned suggestions are consumed by `react-mentions` with a temporary
* aggregate markup that `useFormulaEditorState` immediately unwraps, so
* aggregate selections persist as plain formula text instead of property
* mention markup.
*/
export function useAggregateFormulaSuggestions({
flowsheetUnitOps,
plainFormula,
cursorPosition,
}: AggregateFormulaSuggestionParams): AggregateFormulaSuggestions {
const aggregateKeyOptions = useMemo<AggregateSuggestion[]>(() => {
const keys = new Map<string, string>();
// Aggregate formulas are authored by stable property key, not property ID.
// The backend remains the source of truth for which values actually
// participate in a solve; this list is just an authoring aid.
flowsheetUnitOps?.forEach((obj) => {
const objectSchema = aggregateObjectDefinitions[obj.objectType ?? ""];
Object.entries(objectSchema?.properties ?? {}).forEach(([key, value]) => {
if (value.type === "numeric" && !value.indexSets?.length) {
keys.set(key, `${key} (${value.displayName})`);
}
});
});
return Array.from(keys.entries())
.sort(([left], [right]) => left.localeCompare(right))
.map(([id, display]) => ({ id, display }));
}, [flowsheetUnitOps]);
const aggregateKeySuggestions = useMemo(
() =>
aggregateKeyOptions.map(({ id, display }) => ({
id: `@${getAggregateKeyInsertionText(id, plainFormula, cursorPosition)}`,
display,
})),
[aggregateKeyOptions, cursorPosition, plainFormula],
);
return {
aggregateKeyOptions,
aggregateFunctionSuggestions: getAggregateFunctionOptions(""),
aggregateKeySuggestions,
};
}
|