import{n as e}from"./rolldown-runtime-C0FnF6B9.js";import{n as t}from"./iframe-GrlyTB2d.js";import{i as n,r}from"./react-qN2cStNd.js";import{a as i,d as a,f as o,l as s,m as c,n as l,p as u,r as d,u as f}from"./blocks-DkLPipTQ.js";import{_ as p,a as m,c as h,d as g,f as _,g as v,h as y,i as b,l as x,m as S,n as C,o as w,p as T,r as E,s as D,t as O,u as k}from"./Table.stories-XoMMDbM6.js";function A(e){let t={code:`code`,h2:`h2`,h3:`h3`,li:`li`,p:`p`,pre:`pre`,ul:`ul`,...n(),...e.components};return(0,M.jsxs)(M.Fragment,{children:[(0,M.jsx)(s,{of:D,parameters:{docs:{toc:!0}}}),`
`,(0,M.jsx)(u,{children:`Table`}),`
`,(0,M.jsxs)(o,{children:[`Плоская таблица как React-альтернатива `,(0,M.jsx)(t.code,{children:`sap.m.Table`})]}),`
`,(0,M.jsxs)(t.p,{children:[(0,M.jsx)(t.code,{children:`Table`}),` предназначен для плоских данных и по поведению осознанно сближен с `,(0,M.jsx)(t.code,{children:`TreeTable`}),`.
Оба компонента используют общий табличный каркас, поэтому здесь совпадают states загрузки, визуальная структура, обработка выбора строк и клавиатурная активация.
`,(0,M.jsx)(t.code,{children:`Table`}),` также поддерживает декларативное форматирование через `,(0,M.jsx)(t.code,{children:`meta.formatting`}),`, formulas, безопасное pipeline-formatting и optional OData adapter.`]}),`
`,(0,M.jsx)(t.h2,{id:`основной-сценарий`,children:`Основной сценарий`}),`
`,(0,M.jsx)(f,{}),`
`,(0,M.jsx)(i,{of:O}),`
`,(0,M.jsx)(t.pre,{children:(0,M.jsx)(t.code,{className:`language-tsx`,children:`import { Table, type TableColumnDef } from "@/shared/ui";

interface DealRow {
	id: string;
	number: string;
	client: string;
	amount: string;
}

const columns: TableColumnDef<DealRow>[] = [
	{
		id: "number",
		accessorKey: "number",
		header: "Номер",
		meta: { width: "9em" }
	},
	{
		id: "client",
		accessorKey: "client",
		header: "Клиент",
		meta: { width: "14em" }
	},
	{
		id: "amount",
		accessorKey: "amount",
		header: "Сумма",
		meta: { width: "10em", align: "right" }
	}
];

export function Example({ rows }: { rows: DealRow[] }) {
	return <Table data={rows} columns={columns} getRowId={(row) => row.id} selectionMode="single" height="20em" />;
}
`})}),`
`,(0,M.jsx)(t.h2,{id:`форматирование-ячеек`,children:`Форматирование ячеек`}),`
`,(0,M.jsxs)(t.p,{children:[(0,M.jsx)(t.code,{children:`meta.formatting`}),` добавляет к колонке декларативный runtime-контракт:`]}),`
`,(0,M.jsxs)(t.ul,{children:[`
`,(0,M.jsxs)(t.li,{children:[`typed formatting по `,(0,M.jsx)(t.code,{children:`role/type`}),`;`]}),`
`,(0,M.jsx)(t.li,{children:`formula-based вычисление значения;`}),`
`,(0,M.jsxs)(t.li,{children:[`pipeline display-formatting (`,(0,M.jsx)(t.code,{children:`normalizeLeadingZeros`}),`, `,(0,M.jsx)(t.code,{children:`resolveValueState`}),`, `,(0,M.jsx)(t.code,{children:`typedValueFormat`}),`);`]}),`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`emptyWhenZero`}),` для скрытия нулевых значений;`]}),`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`overflowTooltip`}),` для длинного текста.`]}),`
`]}),`
`,(0,M.jsx)(t.p,{children:`Важно:`}),`
`,(0,M.jsxs)(t.ul,{children:[`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`meta.formatting`}),` применяется только если у колонки нет кастомного `,(0,M.jsx)(t.code,{children:`cell`}),`;`]}),`
`,(0,M.jsx)(t.li,{children:`formulas и pipeline компилируются один раз на снимок колонок;`}),`
`,(0,M.jsxs)(t.li,{children:[`ошибки formula/pipeline не роняют таблицу и не подставляют универсальный `,(0,M.jsx)(t.code,{children:`0`}),`;`]}),`
`,(0,M.jsxs)(t.li,{children:[`OData adapter остаётся внешней прослойкой, а не частью `,(0,M.jsx)(t.code,{children:`Table`}),`.`]}),`
`]}),`
`,(0,M.jsx)(t.pre,{children:(0,M.jsx)(t.code,{className:`language-tsx`,children:`const columns: TableColumnDef<Row>[] = [
	{
		id: "amount",
		accessorKey: "amount",
		header: "Сумма",
		meta: {
			align: "right",
			formatting: {
				role: "measure",
				type: "decimal",
				emptyWhenZero: true
			}
		}
	}
];
`})}),`
`,(0,M.jsxs)(t.p,{children:[`Для OData-сценариев можно не прописывать `,(0,M.jsx)(t.code,{children:`role/type`}),` вручную, а обогатить колонки через adapter:`]}),`
`,(0,M.jsx)(t.pre,{children:(0,M.jsx)(t.code,{className:`language-tsx`,children:`import { enrichTableColumnsWithODataFormatting } from "@ryuzaki13/react-foundation-lib/table";

const columns = enrichTableColumnsWithODataFormatting(manualColumns, metadata.columns);
`})}),`
`,(0,M.jsx)(t.h2,{id:`слияние-дубликатов`,children:`Слияние дубликатов`}),`
`,(0,M.jsxs)(t.p,{children:[(0,M.jsx)(t.code,{children:`meta.mergeDuplicates`}),` включает display-only слияние подряд идущих одинаковых raw-значений без изменения структуры строк.`]}),`
`,(0,M.jsx)(t.p,{children:`Важно:`}),`
`,(0,M.jsxs)(t.ul,{children:[`
`,(0,M.jsxs)(t.li,{children:[`сравнение идёт по `,(0,M.jsx)(t.code,{children:`cell.getValue()`}),`, а не по formatted display;`]}),`
`,(0,M.jsx)(t.li,{children:`объединяются только подряд идущие строки;`}),`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`null`}),`, `,(0,M.jsx)(t.code,{children:`undefined`}),` и пустая строка `,(0,M.jsx)(t.code,{children:`""`}),` не объединяются;`]}),`
`,(0,M.jsx)(t.li,{children:`повторяющееся значение остаётся только в первой строке группы, а ниже рендерятся пустые ячейки;`}),`
`,(0,M.jsx)(t.li,{children:`если сервер не отсортировал данные так, чтобы дубликаты шли подряд, слияния не будет.`}),`
`]}),`
`,(0,M.jsx)(t.pre,{children:(0,M.jsx)(t.code,{className:`language-tsx`,children:`const columns: TableColumnDef<Row>[] = [
	{
		id: "division",
		accessorKey: "division",
		header: "Дивизион",
		meta: {
			mergeDuplicates: true
		}
	}
];
`})}),`
`,(0,M.jsxs)(t.h2,{id:`хук-useodatatablecolumns`,children:[`Хук `,(0,M.jsx)(t.code,{children:`useODataTableColumns`})]}),`
`,(0,M.jsxs)(t.p,{children:[`Наиболее частый кейс - работать не с pure-helper напрямую, а с hook-слоем `,(0,M.jsx)(t.code,{children:`useODataTableColumns(...)`}),`.`]}),`
`,(0,M.jsxs)(t.p,{children:[(0,M.jsx)(t.code,{children:`build`}),` стоит выбирать, когда колонки можно полностью собрать из `,(0,M.jsx)(t.code,{children:`metadata.columns`}),`:`]}),`
`,(0,M.jsx)(t.pre,{children:(0,M.jsx)(t.code,{className:`language-tsx`,children:`import { useODataTableColumns } from "@ryuzaki13/react-foundation-api/odata";
import { Table } from "@/shared/ui";

function DealsTable({ rows }: { rows: DealRow[] }) {
	const { columns, metadata, isLoading } = useODataTableColumns<DealRow>({
		service: "ZSD_SALES_SRV",
		entity: "DealSet",
		mode: "build"
	});

	return (
		<Table
			title={metadata?.title ?? "Сделки"}
			data={rows}
			columns={columns}
			isLoading={isLoading}
			getRowId={(row) => row.id}
			selectionMode="single"
		/>
	);
}
`})}),`
`,(0,M.jsxs)(t.p,{children:[(0,M.jsx)(t.code,{children:`enrich`}),` подходит, когда колонки уже описаны вручную и нужно только дозаполнить `,(0,M.jsx)(t.code,{children:`meta.formatting.role/type`}),`:`]}),`
`,(0,M.jsx)(t.pre,{children:(0,M.jsx)(t.code,{className:`language-tsx`,children:`import { useODataTableColumns } from "@ryuzaki13/react-foundation-api/odata";
import { Table } from "@/shared/ui";

const manualColumns: TableColumnDef<DealRow>[] = [
	{ id: "product", accessorKey: "product", header: "Позиция" },
	{ id: "createdAt", accessorKey: "createdAt", header: "Создано" },
	{ id: "totalAmount", accessorKey: "totalAmount", header: "Итог", meta: { align: "right" } }
];

function DealsTable({ rows }: { rows: DealRow[] }) {
	const { columns, isLoading } = useODataTableColumns<DealRow>({
		service: "ZSD_SALES_SRV",
		entity: "DealSet",
		mode: "enrich",
		columns: manualColumns
	});

	return <Table data={rows} columns={columns} isLoading={isLoading} getRowId={(row) => row.id} selectionMode="single" />;
}
`})}),`
`,(0,M.jsx)(t.p,{children:`Практическая семантика хука:`}),`
`,(0,M.jsxs)(t.ul,{children:[`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`columns`}),` уже готовы для прямой передачи в `,(0,M.jsx)(t.code,{children:`Table`}),`;`]}),`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`metadata`}),` можно использовать для заголовка, пустых состояний или дополнительной UI-подписи;`]}),`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`isLoading`}),` нужно прокидывать в `,(0,M.jsx)(t.code,{children:`Table`}),`, чтобы сохранить единое табличное состояние загрузки;`]}),`
`,(0,M.jsxs)(t.li,{children:[`сам `,(0,M.jsx)(t.code,{children:`Table`}),` остаётся OData-независимым и получает только готовые `,(0,M.jsx)(t.code,{children:`columns`}),`.`]}),`
`]}),`
`,(0,M.jsx)(t.h2,{id:`что-важно-знать`,children:`Что важно знать`}),`
`,(0,M.jsxs)(t.ul,{children:[`
`,(0,M.jsx)(t.li,{children:`Компонент принимает именно плоский массив строк и не содержит древовидной логики.`}),`
`,(0,M.jsxs)(t.li,{children:[`Поведение `,(0,M.jsx)(t.code,{children:`selectionMode`}),` идентично `,(0,M.jsx)(t.code,{children:`TreeTable`}),`: `,(0,M.jsx)(t.code,{children:`single`}),` не снимает выбор повторным кликом по уже выбранной строке.`]}),`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`height`}),` и ширины колонок можно задавать строками в `,(0,M.jsx)(t.code,{children:`em`}),`, `,(0,M.jsx)(t.code,{children:`rem`}),`, `,(0,M.jsx)(t.code,{children:`%`}),` и других CSS-единицах; числовые значения трактуются как `,(0,M.jsx)(t.code,{children:`em`}),`.`]}),`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`onReachEnd`}),` срабатывает внутри scroll-контейнера и подходит для постепенной догрузки длинного списка.`]}),`
`,(0,M.jsxs)(t.li,{children:[(0,M.jsx)(t.code,{children:`Table`}),` не зависит от OData напрямую и продолжает работать на plain local data без metadata.`]}),`
`]}),`
`,(0,M.jsx)(t.h2,{id:`сценарии`,children:`Сценарии`}),`
`,(0,M.jsx)(t.h3,{id:`базовый-режим`,children:`Базовый режим`}),`
`,(0,M.jsx)(d,{of:O}),`
`,(0,M.jsx)(t.h3,{id:`left-pinning-столбцов`,children:`Left-pinning столбцов`}),`
`,(0,M.jsx)(d,{of:h}),`
`,(0,M.jsx)(t.h3,{id:`множественный-выбор`,children:`Множественный выбор`}),`
`,(0,M.jsx)(d,{of:m}),`
`,(0,M.jsx)(t.h3,{id:`строки-с-ограничением-выбора`,children:`Строки с ограничением выбора`}),`
`,(0,M.jsx)(d,{of:x}),`
`,(0,M.jsx)(t.h3,{id:`фоновое-обновление-данных`,children:`Фоновое обновление данных`}),`
`,(0,M.jsx)(d,{of:E}),`
`,(0,M.jsx)(t.h3,{id:`пустая-таблица`,children:`Пустая таблица`}),`
`,(0,M.jsx)(d,{of:C}),`
`,(0,M.jsx)(t.h3,{id:`достижение-конца-списка`,children:`Достижение конца списка`}),`
`,(0,M.jsx)(d,{of:w}),`
`,(0,M.jsx)(t.h3,{id:`первичная-загрузка`,children:`Первичная загрузка`}),`
`,(0,M.jsx)(d,{of:b}),`
`,(0,M.jsx)(t.h3,{id:`formula-based-колонка`,children:`Formula-based колонка`}),`
`,(0,M.jsx)(d,{of:g}),`
`,(0,M.jsx)(t.h3,{id:`pipeline-display-formatting`,children:`Pipeline display-formatting`}),`
`,(0,M.jsx)(d,{of:k}),`
`,(0,M.jsx)(t.h3,{id:`скрытие-нулевых-значений`,children:`Скрытие нулевых значений`}),`
`,(0,M.jsx)(d,{of:_}),`
`,(0,M.jsx)(t.h3,{id:`слияние-дубликатов-1`,children:`Слияние дубликатов`}),`
`,(0,M.jsx)(d,{of:T}),`
`,(0,M.jsx)(t.h3,{id:`odata-metadata-adapter`,children:`OData metadata adapter`}),`
`,(0,M.jsx)(d,{of:S}),`
`,(0,M.jsx)(t.h3,{id:`useodatatablecolumns-build`,children:`useODataTableColumns: build`}),`
`,(0,M.jsx)(d,{of:y}),`
`,(0,M.jsx)(t.h3,{id:`useodatatablecolumns-enrich`,children:`useODataTableColumns: enrich`}),`
`,(0,M.jsx)(d,{of:v}),`
`,(0,M.jsx)(t.h2,{id:`api`,children:`API`}),`
`,(0,M.jsx)(l,{of:D}),`
`,(0,M.jsx)(t.h2,{id:`все-stories`,children:`Все stories`}),`
`,(0,M.jsx)(a,{includePrimary:!1})]})}function j(e={}){let{wrapper:t}={...n(),...e.components};return t?(0,M.jsx)(t,{...e,children:(0,M.jsx)(A,{...e})}):A(e)}var M;function N(){return(N=e((()=>{M=t(),r(),c(),p()})))()}N();export{j as default};