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.
This commit is contained in:
@@ -1,49 +1,38 @@
|
||||
/**
|
||||
* Barrel re-export для UI primitives.
|
||||
* @/ui — single source of truth для UI primitives.
|
||||
*
|
||||
* <p>Стратегия миграции (Phase 2 stack migration):
|
||||
* <ul>
|
||||
* <li>{@code @nstart/ui} остаётся подключённым — все его компоненты
|
||||
* pass-through через этот barrel, чтобы существующий код работал без
|
||||
* рефактора props (Checkbox.label/description, Modal.panelClassName,
|
||||
* FormActions.align, и т.п.).</li>
|
||||
* <li>shadcn-style primitives в {@code ./components/*} добавлены как
|
||||
* параллельный набор. Новый код использует их через alias'ы где они
|
||||
* чище nstart'а ({@code Button}, {@code Badge}, {@code Alert} с
|
||||
* Tailwind v4 tokens; {@code Cap}, {@code ScopeBadge}, {@code ScopeDot},
|
||||
* {@code ScopeStrip} — handoff design system primitives).</li>
|
||||
* <li>Phase 3: компоненты которые имеют bug'и или missing features в nstart
|
||||
* (Combobox vs MultiSelect, TanStack Table vs Table) — заменяются
|
||||
* per-file rewrite.</li>
|
||||
* <li>Phase 4: @nstart/ui удаляется из package.json когда все callsites
|
||||
* переписаны.</li>
|
||||
* </ul>
|
||||
* <p>Stage 3.9: @nstart/ui удалён. Все экспорты резолвят к локальным
|
||||
* shadcn primitives в `./components/`. Имена сохранены в nstart-compat форме
|
||||
* чтобы существующий код работал без массового рефактора imports.
|
||||
*
|
||||
* <p>Текущая семантика: import {X} from '@/ui' — Х берётся приоритетно из
|
||||
* наших shadcn primitives (overrides ниже), иначе passthrough из @nstart/ui.
|
||||
* Этот файл — single source of truth для UI imports.
|
||||
* <p>Группы:
|
||||
* <ol>
|
||||
* <li><b>Handoff typography utility</b> — Cap, ScopeDot/Badge/Strip.</li>
|
||||
* <li><b>Atomic</b> — Button, Badge, Alert, IconButton, Input, Label,
|
||||
* Separator, Skeleton, Switch.</li>
|
||||
* <li><b>Form fields</b> — TextInput, TextArea, Checkbox, FieldLabel/Hint/
|
||||
* Error, FormActions, DatePicker, MultiSelect, SearchInput.</li>
|
||||
* <li><b>Layout</b> — Card*, Panel, PageHeader, EmptyState, LoadingBlock,
|
||||
* Tabs (legacy items-API + Radix root primitives).</li>
|
||||
* <li><b>Overlays</b> — Modal (Dialog adapter), Drawer (Sheet adapter), Sheet*,
|
||||
* Dialog*, Popover*, DropdownMenu*, Tooltip*.</li>
|
||||
* <li><b>Switches</b> — LanguageSwitch.</li>
|
||||
* <li><b>Toast</b> — Toaster, toast (sonner).</li>
|
||||
* </ol>
|
||||
*/
|
||||
|
||||
// === Полная re-export из @nstart/ui — все компоненты, hooks, locale const ===
|
||||
// Дальше будут selective overrides где наши shadcn primitives лучше.
|
||||
export * from '@nstart/ui'
|
||||
|
||||
// === Overrides: наши shadcn primitives с Tailwind v4 tokens ===
|
||||
// Эти именованные re-export'ы перекрывают одноимённые из @nstart/ui выше
|
||||
// (TS resolves last declaration → наши берут верх). Mostly cosmetic — общий
|
||||
// API design сохранён, добавлены теневые props (loading, error-variant и т.д.).
|
||||
// === Atomic ===
|
||||
export { Button, buttonVariants, type ButtonProps } from './components/button'
|
||||
export { Badge, type BadgeProps } from './components/badge'
|
||||
export { Alert, type AlertProps } from './components/alert'
|
||||
// TextArea override — shadcn с handoff tokens. Phase 3 migration step
|
||||
// (Stage 3.8a). API совместим с @nstart/ui TextArea (label/hint/error).
|
||||
export { TextArea, type TextAreaProps } from './components/textarea'
|
||||
// PageHeader override — @nstart/ui рендерил h1 в Tektur 36px/700 (text-4xl
|
||||
// uppercase tracking-tight font-primary), что не соответствует handoff
|
||||
// page title 17/600 Inter. Наша версия использует text-title-lg utility.
|
||||
export { PageHeader } from './components/page-header'
|
||||
export { IconButton, type IconButtonProps } from './components/icon-button'
|
||||
export { Input, type InputProps } from './components/input'
|
||||
export { Label } from './components/label'
|
||||
export { Separator } from './components/separator'
|
||||
export { Skeleton } from './components/skeleton'
|
||||
export { Switch } from './components/switch'
|
||||
|
||||
// === Handoff design system primitives — новые компоненты без nstart-аналога ===
|
||||
// === Handoff design primitives ===
|
||||
export { Cap, type CapProps } from './components/cap'
|
||||
export {
|
||||
ScopeDot,
|
||||
@@ -52,23 +41,72 @@ export {
|
||||
type DataScope as ScopeKind,
|
||||
} from './components/scope'
|
||||
|
||||
// === shadcn primitives для НОВОГО кода (Phase 3) ===
|
||||
// Эти именованные exports НЕ конфликтуют с nstart (имена не пересекаются).
|
||||
// Используются в редизайне catalog/editor/drawer per handoff README.
|
||||
export { IconButton as ShadcnIconButton, type IconButtonProps } from './components/icon-button'
|
||||
export { Input as ShadcnInput, type InputProps as ShadcnInputProps } from './components/input'
|
||||
export { Label as ShadcnLabel } from './components/label'
|
||||
export { SearchInput as ShadcnSearchInput, type SearchInputProps as ShadcnSearchInputProps } from './components/search-input'
|
||||
// === Form fields ===
|
||||
export { TextInput, type TextInputProps } from './components/text-input'
|
||||
export { TextArea, type TextAreaProps } from './components/textarea'
|
||||
export { Checkbox } from './components/checkbox'
|
||||
export {
|
||||
Card as ShadcnCard,
|
||||
FieldLabel,
|
||||
FieldHint,
|
||||
FieldError,
|
||||
type FieldLabelProps,
|
||||
} from './components/field'
|
||||
export { FormActions, type FormActionsProps } from './components/form-actions'
|
||||
export { DatePicker, type DatePickerProps } from './components/date-picker'
|
||||
export {
|
||||
MultiSelect,
|
||||
type MultiSelectOption,
|
||||
type MultiSelectProps,
|
||||
} from './components/multi-select'
|
||||
export {
|
||||
SingleSelect,
|
||||
type SelectOption,
|
||||
type SingleSelectProps,
|
||||
} from './components/single-select'
|
||||
export { SearchInput, type SearchInputProps } from './components/search-input'
|
||||
|
||||
// === Layout ===
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
CardFooter,
|
||||
} from './components/card'
|
||||
export { Separator } from './components/separator'
|
||||
export { Skeleton } from './components/skeleton'
|
||||
export { Panel, type PanelProps } from './components/panel'
|
||||
export { PageHeader, type PageHeaderProps } from './components/page-header'
|
||||
export { EmptyState, type EmptyStateProps } from './components/empty-state'
|
||||
export { LoadingBlock, type LoadingBlockProps } from './components/loading-block'
|
||||
|
||||
// === Tables ===
|
||||
export {
|
||||
Table,
|
||||
TableHeader,
|
||||
TableBody,
|
||||
TableFooter,
|
||||
TableRow,
|
||||
TableHead,
|
||||
TableHeaderCell,
|
||||
TableCell,
|
||||
TableCaption,
|
||||
TableEmpty,
|
||||
type TableHeaderCellProps,
|
||||
type TableEmptyProps,
|
||||
} from './components/table'
|
||||
|
||||
// === Tabs (legacy items[] API + Radix primitives для нового кода) ===
|
||||
export { TabsSimple as Tabs, type TabItem, type TabsSimpleProps } from './components/tabs-simple'
|
||||
export {
|
||||
Tabs as TabsRoot,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
TabsContent,
|
||||
} from './components/tabs'
|
||||
|
||||
// === Overlays ===
|
||||
export { Modal, type ModalProps } from './components/modal'
|
||||
export { Drawer, type DrawerProps } from './components/drawer'
|
||||
export {
|
||||
Dialog,
|
||||
DialogTrigger,
|
||||
@@ -106,13 +144,6 @@ export {
|
||||
TooltipTrigger,
|
||||
TooltipContent,
|
||||
} from './components/tooltip'
|
||||
// Tabs из shadcn — composition API.
|
||||
export {
|
||||
Tabs as ShadcnTabsRoot,
|
||||
TabsList as ShadcnTabsList,
|
||||
TabsTrigger as ShadcnTabsTrigger,
|
||||
TabsContent as ShadcnTabsContent,
|
||||
} from './components/tabs'
|
||||
export {
|
||||
DropdownMenu,
|
||||
DropdownMenuTrigger,
|
||||
@@ -129,9 +160,13 @@ export {
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuRadioGroup,
|
||||
} from './components/dropdown-menu'
|
||||
export { Switch as ShadcnSwitch } from './components/switch'
|
||||
|
||||
// Toast notifications через sonner (rich, accessible, themable).
|
||||
// Mount <Toaster /> один раз в main.tsx; call toast.success/error/etc.
|
||||
// в callbacks / effects.
|
||||
// === Switches ===
|
||||
export {
|
||||
LanguageSwitch,
|
||||
type LanguageOption,
|
||||
type LanguageSwitchProps,
|
||||
} from './components/language-switch'
|
||||
|
||||
// === Toast (sonner) ===
|
||||
export { Toaster, toast } from './components/toaster'
|
||||
|
||||
Reference in New Issue
Block a user