@
Quality / quality (ubuntu-latest) (push) Failing after 12m30s
Quality / quality (windows-latest) (push) Canceled after 0s

feat(ui): add DataTable and Toaster, drop the legacy Table, fix overlay dialogs

DataTable replaces the 20-line Table scaffold entirely: columns, sorting,
filtering, pagination, selection, bulk actions, comparison layout, sticky
first column, custom HTML cells, and a remote source driven by a `request`
output rather than a function prop (props travel as HTML attributes, so a
function arrives as its own source text).

Toaster replaces the hand-rolled status div: tone icons, actions, hover
pause/resume and a progress bar.

Overlays audit -- Modal and Drawer declared aria-modal="true" but nothing
ever moved focus into the panel, so the @keydown handler on their root
never ran and closeOnEscape did nothing. Focus, focus restore, a Tab trap
and a body scroll lock now live in the reactive runtime, shared by both.

ContextMenu placed pointer menus by subtracting a guessed 340x420 from the
viewport, which pushed every menu that was not that size away from the
pointer; it now positions at the pointer and lets the anchored clamp pull
it back once it can be measured.

The reactive runtime size budget moves 150k -> 175k to cover anchored
overlays, dialog behaviour, the toaster and the DataTable client half.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@
This commit is contained in:
2026-08-07 14:57:17 +05:30
parent 296728d51d
commit cc98bccd6c
151 changed files with 14350 additions and 9189 deletions
+336 -10
View File
@@ -110,6 +110,7 @@ export interface Routes {
"/components/timeline": Record<string, never>;
"/components/toast": Record<string, never>;
"/components/toast-notifications": Record<string, never>;
"/components/toaster": Record<string, never>;
"/components/toggle-count": Record<string, never>;
"/components/toggle-password": Record<string, never>;
"/components/tooltip": Record<string, never>;
@@ -134,9 +135,169 @@ export interface Routes {
"/tables": Record<string, never>;
"/templates": Record<string, never>;
"/themes": Record<string, never>;
"/v06-functions": Record<string, never>;
"/v06-imports": Record<string, never>;
"/v06-migration": Record<string, never>;
"/v06-outputs": Record<string, never>;
"/v06-runtime": Record<string, never>;
"/v06-state": Record<string, never>;
"/v06-stores": Record<string, never>;
"/v06-types": Record<string, never>;
}
export interface RouteNames {
"index": "/";
"accessibility": "/accessibility";
"advanced.forms": "/advanced-forms";
"base": "/base";
"block.library": "/block-library";
"colors": "/colors";
"components.accordion": "/components/accordion";
"components.advanced.date.picker": "/components/advanced-date-picker";
"components.advanced.range.slider": "/components/advanced-range-slider";
"components.advanced.select": "/components/advanced-select";
"components.alert": "/components/alert";
"components.announcement.bar": "/components/announcement-bar";
"components.auth.form": "/components/auth-form";
"components.auth.split.layout": "/components/auth-split-layout";
"components.avatar": "/components/avatar";
"components.avatar.group": "/components/avatar-group";
"components.back.to.top": "/components/back-to-top";
"components.badge": "/components/badge";
"components.blockquote": "/components/blockquote";
"components.breadcrumb": "/components/breadcrumb";
"components.button": "/components/button";
"components.button.group": "/components/button-group";
"components.card": "/components/card";
"components.carousel": "/components/carousel";
"components.chart": "/components/chart";
"components.chat.bubble": "/components/chat-bubble";
"components.checkbox": "/components/checkbox";
"components.clipboard": "/components/clipboard";
"components.collapse": "/components/collapse";
"components.color.picker": "/components/color-picker";
"components.columns": "/components/columns";
"components.combo.box": "/components/combo-box";
"components.confetti": "/components/confetti";
"components.container": "/components/container";
"components.context.menu": "/components/context-menu";
"components.copy.markup": "/components/copy-markup";
"components.ctasection": "/components/ctasection";
"components.custom.scrollbar": "/components/custom-scrollbar";
"components.data.map": "/components/data-map";
"components.data.table": "/components/data-table";
"components.date.picker": "/components/date-picker";
"components.device.frame": "/components/device-frame";
"components.divider": "/components/divider";
"components.drag.and.drop": "/components/drag-and-drop";
"components.drawer": "/components/drawer";
"components.dropdown": "/components/dropdown";
"components.feature.card": "/components/feature-card";
"components.feature.grid": "/components/feature-grid";
"components.feature.icon.card": "/components/feature-icon-card";
"components.file.input": "/components/file-input";
"components.file.upload": "/components/file-upload";
"components.file.upload.progress": "/components/file-upload-progress";
"components.footer": "/components/footer";
"components.grid": "/components/grid";
"components.hero": "/components/hero";
"components.hero.actions": "/components/hero-actions";
"components.image": "/components/image";
"components.input": "/components/input";
"components.input.group": "/components/input-group";
"components.input.number": "/components/input-number";
"components.kbd": "/components/kbd";
"components.layout.splitter": "/components/layout-splitter";
"components.legend.indicator": "/components/legend-indicator";
"components.link": "/components/link";
"components.list": "/components/list";
"components.list.group": "/components/list-group";
"components.map": "/components/map";
"components.marketing.section.header": "/components/marketing-section-header";
"components.marquee": "/components/marquee";
"components.mega.menu": "/components/mega-menu";
"components.metric.card": "/components/metric-card";
"components.metric.grid": "/components/metric-grid";
"components.modal": "/components/modal";
"components.nav": "/components/nav";
"components.navbar": "/components/navbar";
"components.page.header": "/components/page-header";
"components.pagination": "/components/pagination";
"components.pin.input": "/components/pin-input";
"components.popover": "/components/popover";
"components.portal.dashboard": "/components/portal-dashboard";
"components.preference.switcher": "/components/preference-switcher";
"components.progress": "/components/progress";
"components.public.page.shell": "/components/public-page-shell";
"components.radio": "/components/radio";
"components.range.slider": "/components/range-slider";
"components.rating": "/components/rating";
"components.scrollspy": "/components/scrollspy";
"components.search.box": "/components/search-box";
"components.section": "/components/section";
"components.section.header": "/components/section-header";
"components.select": "/components/select";
"components.sidebar": "/components/sidebar";
"components.skeleton": "/components/skeleton";
"components.spinner": "/components/spinner";
"components.split.hero": "/components/split-hero";
"components.stats.bar": "/components/stats-bar";
"components.stepper": "/components/stepper";
"components.strong.password": "/components/strong-password";
"components.styled.icon": "/components/styled-icon";
"components.switch": "/components/switch";
"components.table": "/components/table";
"components.tabs": "/components/tabs";
"components.text.link": "/components/text-link";
"components.textarea": "/components/textarea";
"components.time.picker": "/components/time-picker";
"components.timeline": "/components/timeline";
"components.toast": "/components/toast";
"components.toast.notifications": "/components/toast-notifications";
"components.toaster": "/components/toaster";
"components.toggle.count": "/components/toggle-count";
"components.toggle.password": "/components/toggle-password";
"components.tooltip": "/components/tooltip";
"components.tree.view": "/components/tree-view";
"components.typography": "/components/typography";
"components.wysiwyg.editor": "/components/wysiwyg-editor";
"core": "/core";
"dark.mode": "/dark-mode";
"data": "/data";
"docs": "/docs";
"fonts": "/fonts";
"forms": "/forms";
"framework.guides": "/framework-guides";
"installation": "/installation";
"integrations": "/integrations";
"layout": "/layout";
"marketing": "/marketing";
"navigation": "/navigation";
"overlays": "/overlays";
"resources": "/resources";
"sizing": "/sizing";
"tables": "/tables";
"templates": "/templates";
"themes": "/themes";
"v06.functions": "/v06-functions";
"v06.imports": "/v06-imports";
"v06.migration": "/v06-migration";
"v06.outputs": "/v06-outputs";
"v06.runtime": "/v06-runtime";
"v06.state": "/v06-state";
"v06.stores": "/v06-stores";
"v06.types": "/v06-types";
}
export interface RouteQueries {
[path: string]: Record<string, string | number | boolean | null | undefined>;
}
export type RoutePath = keyof Routes;
export type RouteName = keyof RouteNames;
export type RouteQuery<P extends RoutePath> = P extends keyof RouteQueries
? RouteQueries[P]
: Record<string, string | number | boolean | null | undefined>;
type RouteValue = string | readonly string[] | undefined;
function encodeRouteValue(value: RouteValue, catchAll: boolean): string {
@@ -145,17 +306,9 @@ function encodeRouteValue(value: RouteValue, catchAll: boolean): string {
return values.map((part) => encodeURIComponent(part)).join("/");
}
export function href<P extends RoutePath>(
path: P,
...args: keyof Routes[P] extends never
? []
: Record<string, never> extends Routes[P]
? [params?: Routes[P]]
: [params: Routes[P]]
): string {
const params = (args[0] ?? {}) as Record<string, RouteValue>;
function buildHref(path: string, params: Record<string, RouteValue> = {}): string {
const output: string[] = [];
for (const segment of String(path).split("/").filter(Boolean)) {
for (const segment of path.split("/").filter(Boolean)) {
let name: string | undefined;
let optional = false;
let catchAll = false;
@@ -184,3 +337,176 @@ export function href<P extends RoutePath>(
}
return "/" + output.filter(Boolean).join("/");
}
export function href<P extends RoutePath>(
path: P,
...args: keyof Routes[P] extends never
? []
: Record<string, never> extends Routes[P]
? [params?: Routes[P]]
: [params: Routes[P]]
): string {
const params = (args[0] ?? {}) as Record<string, RouteValue>;
return buildHref(String(path), params);
}
export function route<N extends RouteName>(
name: N,
...args: keyof Routes[RouteNames[N]] extends never
? [params?: Routes[RouteNames[N]], query?: RouteQuery<RouteNames[N]>]
: Record<string, never> extends Routes[RouteNames[N]]
? [params?: Routes[RouteNames[N]], query?: RouteQuery<RouteNames[N]>]
: [params: Routes[RouteNames[N]], query?: RouteQuery<RouteNames[N]>]
): string {
const paths: Record<RouteName, RoutePath> = {
"index": "/",
"accessibility": "/accessibility",
"advanced.forms": "/advanced-forms",
"base": "/base",
"block.library": "/block-library",
"colors": "/colors",
"components.accordion": "/components/accordion",
"components.advanced.date.picker": "/components/advanced-date-picker",
"components.advanced.range.slider": "/components/advanced-range-slider",
"components.advanced.select": "/components/advanced-select",
"components.alert": "/components/alert",
"components.announcement.bar": "/components/announcement-bar",
"components.auth.form": "/components/auth-form",
"components.auth.split.layout": "/components/auth-split-layout",
"components.avatar": "/components/avatar",
"components.avatar.group": "/components/avatar-group",
"components.back.to.top": "/components/back-to-top",
"components.badge": "/components/badge",
"components.blockquote": "/components/blockquote",
"components.breadcrumb": "/components/breadcrumb",
"components.button": "/components/button",
"components.button.group": "/components/button-group",
"components.card": "/components/card",
"components.carousel": "/components/carousel",
"components.chart": "/components/chart",
"components.chat.bubble": "/components/chat-bubble",
"components.checkbox": "/components/checkbox",
"components.clipboard": "/components/clipboard",
"components.collapse": "/components/collapse",
"components.color.picker": "/components/color-picker",
"components.columns": "/components/columns",
"components.combo.box": "/components/combo-box",
"components.confetti": "/components/confetti",
"components.container": "/components/container",
"components.context.menu": "/components/context-menu",
"components.copy.markup": "/components/copy-markup",
"components.ctasection": "/components/ctasection",
"components.custom.scrollbar": "/components/custom-scrollbar",
"components.data.map": "/components/data-map",
"components.data.table": "/components/data-table",
"components.date.picker": "/components/date-picker",
"components.device.frame": "/components/device-frame",
"components.divider": "/components/divider",
"components.drag.and.drop": "/components/drag-and-drop",
"components.drawer": "/components/drawer",
"components.dropdown": "/components/dropdown",
"components.feature.card": "/components/feature-card",
"components.feature.grid": "/components/feature-grid",
"components.feature.icon.card": "/components/feature-icon-card",
"components.file.input": "/components/file-input",
"components.file.upload": "/components/file-upload",
"components.file.upload.progress": "/components/file-upload-progress",
"components.footer": "/components/footer",
"components.grid": "/components/grid",
"components.hero": "/components/hero",
"components.hero.actions": "/components/hero-actions",
"components.image": "/components/image",
"components.input": "/components/input",
"components.input.group": "/components/input-group",
"components.input.number": "/components/input-number",
"components.kbd": "/components/kbd",
"components.layout.splitter": "/components/layout-splitter",
"components.legend.indicator": "/components/legend-indicator",
"components.link": "/components/link",
"components.list": "/components/list",
"components.list.group": "/components/list-group",
"components.map": "/components/map",
"components.marketing.section.header": "/components/marketing-section-header",
"components.marquee": "/components/marquee",
"components.mega.menu": "/components/mega-menu",
"components.metric.card": "/components/metric-card",
"components.metric.grid": "/components/metric-grid",
"components.modal": "/components/modal",
"components.nav": "/components/nav",
"components.navbar": "/components/navbar",
"components.page.header": "/components/page-header",
"components.pagination": "/components/pagination",
"components.pin.input": "/components/pin-input",
"components.popover": "/components/popover",
"components.portal.dashboard": "/components/portal-dashboard",
"components.preference.switcher": "/components/preference-switcher",
"components.progress": "/components/progress",
"components.public.page.shell": "/components/public-page-shell",
"components.radio": "/components/radio",
"components.range.slider": "/components/range-slider",
"components.rating": "/components/rating",
"components.scrollspy": "/components/scrollspy",
"components.search.box": "/components/search-box",
"components.section": "/components/section",
"components.section.header": "/components/section-header",
"components.select": "/components/select",
"components.sidebar": "/components/sidebar",
"components.skeleton": "/components/skeleton",
"components.spinner": "/components/spinner",
"components.split.hero": "/components/split-hero",
"components.stats.bar": "/components/stats-bar",
"components.stepper": "/components/stepper",
"components.strong.password": "/components/strong-password",
"components.styled.icon": "/components/styled-icon",
"components.switch": "/components/switch",
"components.table": "/components/table",
"components.tabs": "/components/tabs",
"components.text.link": "/components/text-link",
"components.textarea": "/components/textarea",
"components.time.picker": "/components/time-picker",
"components.timeline": "/components/timeline",
"components.toast": "/components/toast",
"components.toast.notifications": "/components/toast-notifications",
"components.toaster": "/components/toaster",
"components.toggle.count": "/components/toggle-count",
"components.toggle.password": "/components/toggle-password",
"components.tooltip": "/components/tooltip",
"components.tree.view": "/components/tree-view",
"components.typography": "/components/typography",
"components.wysiwyg.editor": "/components/wysiwyg-editor",
"core": "/core",
"dark.mode": "/dark-mode",
"data": "/data",
"docs": "/docs",
"fonts": "/fonts",
"forms": "/forms",
"framework.guides": "/framework-guides",
"installation": "/installation",
"integrations": "/integrations",
"layout": "/layout",
"marketing": "/marketing",
"navigation": "/navigation",
"overlays": "/overlays",
"resources": "/resources",
"sizing": "/sizing",
"tables": "/tables",
"templates": "/templates",
"themes": "/themes",
"v06.functions": "/v06-functions",
"v06.imports": "/v06-imports",
"v06.migration": "/v06-migration",
"v06.outputs": "/v06-outputs",
"v06.runtime": "/v06-runtime",
"v06.state": "/v06-state",
"v06.stores": "/v06-stores",
"v06.types": "/v06-types"
} as Record<RouteName, RoutePath>;
const output = buildHref(paths[name], (args[0] ?? {}) as Record<string, RouteValue>);
const query = args[1];
if (!query) return output;
const search = new URLSearchParams();
for (const [key, value] of Object.entries(query))
if (value !== undefined && value !== null) search.set(key, String(value));
const text = search.toString();
return text ? `${output}?${text}` : output;
}