{"version":3,"file":"bar-list-model.cjs","names":[],"sources":["../../../src/components/BarList/bar-list-model.ts"],"sourcesContent":["// The arithmetic behind BarList, kept out of the component so the decisions that\n// are easy to get wrong — an empty total, a negative value, what \"100% wide\"\n// means — are testable without rendering anything.\n\nimport { percentOf } from \"@/utils/numbers\";\n\n/** One entry of a {@link BarList}. */\nexport interface BarListItem {\n    /** What the row is called. */\n    label: string;\n    /** The measured amount. */\n    value: number;\n    /** Override the bar colour. Defaults to the chart series token for its position. */\n    color?: string;\n}\n\n/** How the list orders itself before drawing. */\nexport type BarListSort = \"desc\" | \"asc\" | \"none\";\n\n/** One row, with everything the component needs to draw it. */\nexport interface BarListRow extends BarListItem {\n    /** Share of the total, 0–100. */\n    percentage: number;\n    /** Bar width relative to the largest row, 0–100. */\n    width: number;\n    /** Position in the original palette cycle. */\n    index: number;\n}\n\n/** What {@link buildBarListRows} needs to reduce a list into rows. */\nexport interface BuildBarListRowsOptions {\n    /** The rows as given. */\n    items: readonly BarListItem[];\n    /** Ordering to apply. `\"none\"` keeps the caller's order. Default `\"desc\"`. */\n    sort?: BarListSort;\n    /** Keep at most this many rows. */\n    max?: number;\n    /** Aggregate what `max` cut into one row with this label. */\n    otherLabel?: string;\n}\n\n/**\n * Order, truncate and measure the rows.\n *\n * Two different numbers come out of this, and conflating them is the classic bug\n * in a hand-written bar list:\n *\n * - `percentage` is the row's share of the **total**, which is what the label\n *   claims when it reads \"32%\".\n * - `width` is relative to the **largest** row, so the biggest bar fills the\n *   track. Scaling width by the total instead leaves every bar short in a list of\n *   many small values, and the chart stops being readable exactly when it has the\n *   most rows.\n *\n * The total counts positive values only. A negative amount draws no bar (a bar of\n * negative width does not exist) and reports 0%, but its number is still shown —\n * hiding the row would be worse than showing an odd one.\n *\n * @param options - The rows and how to reduce them.\n * @returns The rows to draw, in order.\n */\nexport function buildBarListRows(options: BuildBarListRowsOptions): BarListRow[] {\n    const { items, sort = \"desc\", max, otherLabel } = options;\n    const usable = items.filter((item) => Number.isFinite(item.value));\n    const total = usable.reduce((sum, item) => sum + Math.max(item.value, 0), 0);\n\n    const ordered =\n        sort === \"none\"\n            ? [...usable]\n            : [...usable].sort((a, b) => (sort === \"asc\" ? a.value - b.value : b.value - a.value));\n\n    const limit = max !== undefined && max > 0 ? max : ordered.length;\n    const kept = ordered.slice(0, limit);\n    const cut = otherLabel === undefined ? [] : ordered.slice(limit);\n\n    const shown: BarListItem[] =\n        otherLabel !== undefined && cut.length > 1\n            ? [\n                  ...kept,\n                  { label: otherLabel, value: cut.reduce((sum, item) => sum + item.value, 0) },\n              ]\n            : [...kept, ...cut];\n\n    const largest = shown.reduce((high, item) => Math.max(high, item.value), 0);\n\n    return shown.map((item, index) => ({\n        ...item,\n        index,\n        percentage: percentOf(Math.max(item.value, 0), total),\n        width: percentOf(Math.max(item.value, 0), largest),\n    }));\n}\n"],"mappings":"2CA6DA,SAAgB,EAAiB,EAAgD,CAC7E,GAAM,CAAE,QAAO,OAAO,OAAQ,MAAK,cAAe,EAC5C,EAAS,EAAM,OAAQ,GAAS,OAAO,SAAS,EAAK,KAAK,CAAC,EAC3D,EAAQ,EAAO,QAAQ,EAAK,IAAS,EAAM,KAAK,IAAI,EAAK,MAAO,CAAC,EAAG,CAAC,EAErE,EACF,IAAS,OACH,CAAC,GAAG,CAAM,EACV,CAAC,GAAG,CAAM,CAAC,CAAC,MAAM,EAAG,IAAO,IAAS,MAAQ,EAAE,MAAQ,EAAE,MAAQ,EAAE,MAAQ,EAAE,KAAM,EAEvF,EAAQ,IAAQ,IAAA,IAAa,EAAM,EAAI,EAAM,EAAQ,OACrD,EAAO,EAAQ,MAAM,EAAG,CAAK,EAC7B,EAAM,IAAe,IAAA,GAAY,CAAC,EAAI,EAAQ,MAAM,CAAK,EAEzD,EACF,IAAe,IAAA,IAAa,EAAI,OAAS,EACnC,CACI,GAAG,EACH,CAAE,MAAO,EAAY,MAAO,EAAI,QAAQ,EAAK,IAAS,EAAM,EAAK,MAAO,CAAC,CAAE,CAC/E,EACA,CAAC,GAAG,EAAM,GAAG,CAAG,EAEpB,EAAU,EAAM,QAAQ,EAAM,IAAS,KAAK,IAAI,EAAM,EAAK,KAAK,EAAG,CAAC,EAE1E,OAAO,EAAM,KAAK,EAAM,KAAW,CAC/B,GAAG,EACH,QACA,WAAY,EAAA,UAAU,KAAK,IAAI,EAAK,MAAO,CAAC,EAAG,CAAK,EACpD,MAAO,EAAA,UAAU,KAAK,IAAI,EAAK,MAAO,CAAC,EAAG,CAAO,CACrD,EAAE,CACN"}