Files
mdm-ordinis/ordinis-admin-ui/src/ui/components/table.tsx
T
Zimin A.N. 5007e0f4eb feat(ui): drop @nstart/ui dependency (Stage 3.9)
Все font cascade bugs из последних MR были вызваны @nstart/ui pollution
(Tektur inheritance от Card parent'ов, Onest font в Button, font-primary
class overrides). Решили обрезать раньше plan'а.

What changed:

New primitives (8 файлов в src/ui/components/):
  - panel.tsx           — container с border/surface
  - field.tsx           — FieldLabel/Hint/Error typography helpers
  - text-input.tsx      — Input + label/hint/error composite
  - table.tsx           — Table/TableHeader/Body/Row/HeaderCell/Cell/Empty
  - date-picker.tsx     — native <input type=date> wrapper с label/hint/error
  - multi-select.tsx    — Radix Popover + inline checkboxes
  - single-select.tsx   — native <select> с label/hint/error chrome
  - language-switch.tsx — segmented control в Tektur uppercase

Compatibility shims (existing components extended):
  - checkbox.tsx        — + label/description/error/onChange (nstart-compat
                          synthetic event), wrap в <label> когда есть chrome
  - modal.tsx           — + panelClassName / bodyClassName props
  - form-actions.tsx    — + align prop (start/end/between)
  - tabs-simple.tsx     — TabItem.count alias for .trailing (nstart-compat)
  - table TableHead     — alias TableHeaderCell с align prop

Barrel rewrite (src/ui/index.ts):
  - Удалён 'export * from @nstart/ui'
  - Explicit exports для всех 45+ нужных символов
  - SelectOption / MultiSelectOption / LanguageOption теперь {id, label}
    с optional 'value' alias — nstart-compat без массового codemod call-sites

styles.css cleanup:
  - Removed @import @nstart/ui/styles/{fonts,theme}.css
  - Removed @source nstart/dist directive (Tailwind v4 scan)
  - Removed --text-sm: 13px override (был костыль для @nstart/ui dist)
  - Legacy color tokens (--color-carbon/ultramarain/orbit/regolith/asteroid)
    sсодержали fallback mappings — оставлены, но callsites больше не используют

Codemod: 9 файлов конвертированы legacy colors → handoff tokens
  carbon → ink, ultramarain → accent, orbit → warn, regolith → line, asteroid → mute

main.tsx:
  - NStartUiProvider → TooltipProvider (Radix)
  - DatePickerProvider убран (наш DatePicker native, no provider needed)

routes/dictionaries.$name.tsx:
  - Removed useRef-based <input>.indeterminate hack
  - Radix Checkbox принимает checked='indeterminate' declaratively

package.json: -@nstart/ui (was 0.1.3)

Bundle impact:
  before: vendor-nstart-ui chunk = 1228 KB
  after:  no nstart chunk, всё в vendor-misc (+~70 KB Radix wrappers)
  net savings: ~1.15 MB minified, ~440 KB gzip

Tests: 116 pass (1 fixed: tab role from 'button' → 'tab', Radix semantically correct).
TS strict: clean.
Browser-verified (preview): 7 utilities computed correctly, nstart bundle absent.
2026-05-11 15:17:37 +03:00

157 lines
4.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import * as React from 'react'
import { cn } from '@/lib/utils'
/**
* Table primitives — shadcn-style atomic wrappers. Замена @nstart/ui Table*.
*
* <p>Per handoff: table cell text = text-cell (12.5/500). Применяется на
* &lt;td/th&gt; через CSS rule в `<tbody>` — но проще baked-in via TableCell
* className. Caller может override через className prop.
*
* <p>TableEmpty — single full-width row для empty state.
*/
export const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(
function Table({ className, ...props }, ref) {
return (
<div className="w-full overflow-x-auto">
<table
ref={ref}
className={cn('w-full caption-bottom text-cell', className)}
{...props}
/>
</div>
)
},
)
export const TableHeader = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(function TableHeader({ className, ...props }, ref) {
return (
<thead
ref={ref}
className={cn('[&_tr]:border-b [&_tr]:border-line', className)}
{...props}
/>
)
})
export const TableBody = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(function TableBody({ className, ...props }, ref) {
return (
<tbody
ref={ref}
className={cn('[&_tr:last-child]:border-0', className)}
{...props}
/>
)
})
export const TableFooter = React.forwardRef<
HTMLTableSectionElement,
React.HTMLAttributes<HTMLTableSectionElement>
>(function TableFooter({ className, ...props }, ref) {
return (
<tfoot
ref={ref}
className={cn(
'border-t border-line bg-surface-2 font-medium [&>tr]:last:border-b-0',
className,
)}
{...props}
/>
)
})
export const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(
function TableRow({ className, ...props }, ref) {
return (
<tr
ref={ref}
className={cn(
'border-b border-line transition-colors hover:bg-surface-2/40 data-[state=selected]:bg-accent-bg',
className,
)}
{...props}
/>
)
},
)
export type TableHeaderCellProps = React.ThHTMLAttributes<HTMLTableCellElement> & {
align?: 'left' | 'center' | 'right'
}
export const TableHeaderCell = React.forwardRef<HTMLTableCellElement, TableHeaderCellProps>(
function TableHeaderCell({ className, align = 'left', ...props }, ref) {
return (
<th
ref={ref}
className={cn(
'h-9 px-3 align-middle text-cap text-mute',
align === 'right' && 'text-right',
align === 'center' && 'text-center',
align === 'left' && 'text-left',
'[&:has([role=checkbox])]:pr-0',
className,
)}
{...props}
/>
)
},
)
// Alias for shadcn convention.
export const TableHead = TableHeaderCell
export const TableCell = React.forwardRef<
HTMLTableCellElement,
React.TdHTMLAttributes<HTMLTableCellElement>
>(function TableCell({ className, ...props }, ref) {
return (
<td
ref={ref}
className={cn('px-3 py-2 align-middle [&:has([role=checkbox])]:pr-0', className)}
{...props}
/>
)
})
export const TableCaption = React.forwardRef<
HTMLTableCaptionElement,
React.HTMLAttributes<HTMLTableCaptionElement>
>(function TableCaption({ className, ...props }, ref) {
return (
<caption
ref={ref}
className={cn('mt-3 text-cell text-mute', className)}
{...props}
/>
)
})
/**
* TableEmpty — full-width row с заглушкой "ничего не найдено".
* Замена @nstart/ui TableEmptyRow API: <TableEmpty colSpan={N}>{text}</TableEmpty>.
*/
export type TableEmptyProps = React.TdHTMLAttributes<HTMLTableCellElement> & {
colSpan: number
}
export function TableEmpty({ colSpan, className, children, ...props }: TableEmptyProps) {
return (
<tr>
<td
colSpan={colSpan}
className={cn('py-10 text-center text-cell text-mute', className)}
{...props}
>
{children}
</td>
</tr>
)
}