{"version":3,"file":"BarList.cjs","names":[],"sources":["../../../src/components/BarList/BarList.tsx"],"sourcesContent":["import { useMemo, type HTMLAttributes } from \"react\";\n\nimport { useChartColors } from \"@/charts/use-chart-colors\";\nimport { cn } from \"@/utils/cn\";\n\nimport { buildBarListRows, type BarListItem, type BarListSort } from \"./bar-list-model\";\nimport styles from \"./BarList.module.css\";\n\nexport type { BarListItem, BarListSort } from \"./bar-list-model\";\n\nexport interface BarListProps extends Omit<HTMLAttributes<HTMLUListElement>, \"children\"> {\n    /** The rows. Entries whose value is not finite are dropped. */\n    items: readonly BarListItem[];\n    /** Render the number. Defaults to the value as-is. */\n    valueFormatter?: (value: number) => string;\n    /** Show each row's share of the total next to its value. Default `false`. */\n    showPercentage?: boolean;\n    /** Ordering. Default `\"desc\"`, which is what a ranking means. */\n    sort?: BarListSort;\n    /** Keep at most this many rows. */\n    max?: number;\n    /**\n     * Label for one aggregated row holding everything `max` cut off.\n     *\n     * Without it, `max` simply truncates. The aggregate row only appears when more\n     * than one row was cut — collapsing a single row into \"others\" hides its name\n     * for nothing.\n     */\n    otherLabel?: string;\n}\n\n/**\n * A ranked distribution: label, proportional bar, value, optional share.\n *\n * The most common chart on an admin panel, and the one the SDK kept sending\n * people to write by hand — `Progress` is a single bar and `Sparkline` is a time\n * series, so a \"users per plan\" block ended up reimplemented per screen, each\n * with its own CSS and its own `.sort()`.\n *\n * It is a **list**, not a picture: `<ul>` / `<li>` with the value written as\n * text, the bar `aria-hidden` behind it. A screen reader reads \"Free, 128, 62%\"\n * because that text is there, not because an `aria-label` restates a drawing.\n * Which is also why the label never sits on top of the bar — text over a tinted\n * fill has to be re-verified against that fill, and the SDK has been caught by\n * that twice.\n *\n * Bar width is relative to the **largest** row, so the biggest bar fills the\n * track; the percentage is the row's share of the **total**. They are different\n * numbers on purpose: a width scaled by the total leaves every bar short in a\n * long list, which is when the chart is needed most.\n *\n * Colors come from {@link useChartColors}, the same resolver every chart in the\n * SDK uses, so a theme that declares fewer series than the eight\n * `--tempest-chart-*` slots cycles within its own palette. Reading the tokens\n * through CSS `var()` could not do that: the count lives in\n * `--tempest-chart-count`, which CSS cannot use as a modulus, so a six-color\n * brand palette got the SDK's leftover defaults in rows seven and eight — the\n * exact regression that token exists to prevent. `palette.ts` imports nothing,\n * so this pulls no chart library into the slice.\n *\n * @example\n * <BarList\n *     items={[{ label: \"Free\", value: 128 }, { label: \"Pro\", value: 32 }]}\n *     valueFormatter={(n) => `${n} ativos`}\n *     showPercentage\n *     max={5}\n *     otherLabel=\"Outros\"\n * />\n *\n * @param props - Items plus presentation.\n * @returns The list.\n */\nexport function BarList({\n    items,\n    valueFormatter,\n    showPercentage = false,\n    sort = \"desc\",\n    max,\n    otherLabel,\n    className,\n    ...rest\n}: BarListProps) {\n    const rows = useMemo(\n        () => buildBarListRows({ items, sort, max, otherLabel }),\n        [items, sort, max, otherLabel],\n    );\n    const palette = useChartColors();\n\n    return (\n        <ul className={cn(styles.list, className)} {...rest}>\n            {rows.map((row) => (\n                <li key={`${row.label}-${row.index}`} className={styles.item}>\n                    <div className={styles.line}>\n                        <span className={styles.label}>{row.label}</span>\n                        <span className={styles.value}>\n                            {valueFormatter ? valueFormatter(row.value) : row.value}\n                            {showPercentage && (\n                                <span className={styles.percentage}>\n                                    {Math.round(row.percentage)}%\n                                </span>\n                            )}\n                        </span>\n                    </div>\n                    <div className={styles.track} aria-hidden=\"true\">\n                        <div\n                            className={styles.fill}\n                            style={{\n                                width: `${row.width}%`,\n                                backgroundColor: row.color ?? palette[row.index % palette.length],\n                            }}\n                        />\n                    </div>\n                </li>\n            ))}\n        </ul>\n    );\n}\n"],"mappings":"+MAwEA,SAAgB,EAAQ,CACpB,QACA,iBACA,iBAAiB,GACjB,OAAO,OACP,MACA,aACA,YACA,GAAG,GACU,CACb,IAAM,GAAA,EAAO,EAAA,QAAA,KACH,EAAA,iBAAiB,CAAE,QAAO,OAAM,MAAK,YAAW,CAAC,EACvD,CAAC,EAAO,EAAM,EAAK,CAAU,CACjC,EACM,EAAU,EAAA,eAAe,EAE/B,OACI,EAAA,EAAA,IAAA,CAAC,KAAD,CAAI,UAAW,EAAA,GAAG,EAAA,QAAO,KAAM,CAAS,EAAG,GAAI,EAC1C,SAAA,EAAK,IAAK,IACP,EAAA,EAAA,KAAA,CAAC,KAAD,CAAsC,UAAW,EAAA,QAAO,KAAxD,SAAA,EACI,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,KAAvB,SAAA,EACI,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAQ,SAAA,EAAI,KAAY,CAAA,GAChD,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,MAAxB,SAAA,CACK,EAAiB,EAAe,EAAI,KAAK,EAAI,EAAI,MACjD,IACG,EAAA,EAAA,KAAA,CAAC,OAAD,CAAM,UAAW,EAAA,QAAO,WAAxB,SAAA,CACK,KAAK,MAAM,EAAI,UAAU,EAAE,GAC1B,CAER,CAAA,CAAA,CACL,CAAA,CAAA,CACL,CAAA,GAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAW,EAAA,QAAO,MAAO,cAAY,OACtC,UAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACI,UAAW,EAAA,QAAO,KAClB,MAAO,CACH,MAAO,GAAG,EAAI,MAAM,GACpB,gBAAiB,EAAI,OAAS,EAAQ,EAAI,MAAQ,EAAQ,OAC9D,CACH,CAAA,CACA,CAAA,CACL,CArBK,EAAA,GAAG,EAAI,MAAM,GAAG,EAAI,OAqBzB,CACP,CACD,CAAA,CAEZ"}