@exxatdesignux/ui 0.5.5 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/consumer-extras/cursor-rules/exxat-ds-agents.mdc +16 -5
- package/consumer-extras/cursor-rules/exxat-ux-discovery-protocol.mdc +122 -0
- package/consumer-extras/cursor-rules/exxat-ux-principles.mdc +186 -0
- package/consumer-extras/cursor-skills/exxat-senior-ux/SKILL.md +145 -0
- package/consumer-extras/patterns/jobs/README.md +59 -0
- package/consumer-extras/patterns/jobs/record-detail.md +177 -0
- package/consumer-extras/patterns/modern-saas-patterns.md +165 -0
- package/dist/components/data-table/index.js +28 -22
- package/dist/components/data-table/index.js.map +1 -1
- package/dist/components/data-table/pagination.js +28 -22
- package/dist/components/data-table/pagination.js.map +1 -1
- package/dist/components/data-table/use-table-state.js +20 -17
- package/dist/components/data-table/use-table-state.js.map +1 -1
- package/dist/components/data-views/hub-table.js +28 -22
- package/dist/components/data-views/hub-table.js.map +1 -1
- package/dist/components/data-views/index.js +28 -22
- package/dist/components/data-views/index.js.map +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/banner.d.ts +3 -3
- package/dist/components/ui/button.d.ts +2 -2
- package/dist/components/ui/tabs.d.ts +1 -1
- package/dist/hooks/use-app-theme.d.ts +1 -1
- package/dist/index.js +28 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/data-table/index.tsx +10 -6
- package/src/components/data-table/use-table-state.ts +33 -26
- package/template/docs/jobs/README.md +59 -0
- package/template/docs/jobs/record-detail.md +177 -0
- package/template/docs/modern-saas-patterns.md +165 -0
- package/tokens/hooks-index.json +2 -2
|
@@ -4,7 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const badgeVariants: (props?: ({
|
|
7
|
-
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" |
|
|
7
|
+
variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare function Badge({ className, variant, asChild, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
|
|
10
10
|
asChild?: boolean;
|
|
@@ -4,9 +4,9 @@ import * as React from 'react';
|
|
|
4
4
|
import { VariantProps } from 'class-variance-authority';
|
|
5
5
|
|
|
6
6
|
declare const systemBannerVariants: (props?: ({
|
|
7
|
-
variant?: "
|
|
7
|
+
variant?: "error" | "success" | "warning" | "info" | "promo" | null | undefined;
|
|
8
8
|
emphasis?: "prominent" | "subtle" | null | undefined;
|
|
9
|
-
actionPosition?: "
|
|
9
|
+
actionPosition?: "bottom" | "inline" | null | undefined;
|
|
10
10
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
11
11
|
interface SystemBannerProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof systemBannerVariants> {
|
|
12
12
|
/** Banner title (optional — adds a bold heading) */
|
|
@@ -32,7 +32,7 @@ interface SystemBannerProps extends React.HTMLAttributes<HTMLDivElement>, Varian
|
|
|
32
32
|
}
|
|
33
33
|
declare function SystemBanner({ children, title, variant, emphasis, dismissible, onDismiss, action, actionPosition, icon, decorativeOverlay, className, style, ...props }: SystemBannerProps): react_jsx_runtime.JSX.Element | null;
|
|
34
34
|
declare const localBannerVariants: (props?: ({
|
|
35
|
-
variant?: "
|
|
35
|
+
variant?: "error" | "success" | "warning" | "info" | "promo" | null | undefined;
|
|
36
36
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
37
37
|
interface LocalBannerProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof localBannerVariants> {
|
|
38
38
|
/** Banner title (optional) */
|
|
@@ -3,11 +3,11 @@ import * as React from 'react';
|
|
|
3
3
|
import { VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
5
|
declare const buttonVariants: (props?: ({
|
|
6
|
-
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" |
|
|
6
|
+
variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | null | undefined;
|
|
7
7
|
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
8
8
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
9
9
|
declare const Button: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLButtonElement> & React.ButtonHTMLAttributes<HTMLButtonElement> & VariantProps<(props?: ({
|
|
10
|
-
variant?: "default" | "outline" | "secondary" | "ghost" | "destructive" |
|
|
10
|
+
variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | null | undefined;
|
|
11
11
|
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
12
12
|
} & class_variance_authority_types.ClassProp) | undefined) => string> & {
|
|
13
13
|
asChild?: boolean;
|
|
@@ -6,7 +6,7 @@ import { Tabs as Tabs$1 } from 'radix-ui';
|
|
|
6
6
|
|
|
7
7
|
declare function Tabs({ className, orientation, ...props }: React.ComponentProps<typeof Tabs$1.Root>): react_jsx_runtime.JSX.Element;
|
|
8
8
|
declare const tabsListVariants: (props?: ({
|
|
9
|
-
variant?: "
|
|
9
|
+
variant?: "line" | "default" | null | undefined;
|
|
10
10
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
11
11
|
declare function TabsList({ className, variant, ...props }: React.ComponentProps<typeof Tabs$1.List> & VariantProps<typeof tabsListVariants>): react_jsx_runtime.JSX.Element;
|
|
12
12
|
declare function TabsTrigger({ className, ...props }: React.ComponentProps<typeof Tabs$1.Trigger>): react_jsx_runtime.JSX.Element;
|
|
@@ -10,7 +10,7 @@ declare function useAppTheme(): {
|
|
|
10
10
|
brand: Brand;
|
|
11
11
|
setBrand: (b: Brand) => void;
|
|
12
12
|
/** The user's preference: "system" | "normal" | "high" | "windows" */
|
|
13
|
-
contrastPref: "
|
|
13
|
+
contrastPref: "normal" | "high" | "system" | "windows";
|
|
14
14
|
/** The resolved contrast mode actually applied to the DOM. */
|
|
15
15
|
contrast: ContrastMode;
|
|
16
16
|
/** Set the contrast preference. */
|
package/dist/index.js
CHANGED
|
@@ -1905,15 +1905,6 @@ function useTableState(data, columns, defaultSort, paginationOverride, syncedSea
|
|
|
1905
1905
|
});
|
|
1906
1906
|
return [...groups.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([key, groupRows]) => ({ groupKey: key, groupLabel: key, rows: groupRows }));
|
|
1907
1907
|
}, [rows, groupBy]);
|
|
1908
|
-
const LOCKED_KEYS = React10.useMemo(() => new Set(Object.keys(lockedPins)), [lockedPins]);
|
|
1909
|
-
const effectivePins = React10.useMemo(() => {
|
|
1910
|
-
if (isReflowViewport || !isOverflowing) return {};
|
|
1911
|
-
const result = {};
|
|
1912
|
-
for (const [key, pin] of Object.entries(colPins)) {
|
|
1913
|
-
result[key] = pin;
|
|
1914
|
-
}
|
|
1915
|
-
return result;
|
|
1916
|
-
}, [colPins, isOverflowing, isReflowViewport]);
|
|
1917
1908
|
const displayCols = React10.useMemo(() => {
|
|
1918
1909
|
const leftPinned = [];
|
|
1919
1910
|
const free = [];
|
|
@@ -1933,6 +1924,19 @@ function useTableState(data, columns, defaultSort, paginationOverride, syncedSea
|
|
|
1933
1924
|
}
|
|
1934
1925
|
return out;
|
|
1935
1926
|
}, [colOrder, colPins, hiddenCols, columnsByKey]);
|
|
1927
|
+
const totalWidth = React10.useMemo(
|
|
1928
|
+
() => displayCols.reduce((s, c) => s + (colWidths[c.key] ?? c.width ?? 100), 0),
|
|
1929
|
+
[displayCols, colWidths]
|
|
1930
|
+
);
|
|
1931
|
+
const LOCKED_KEYS = React10.useMemo(() => new Set(Object.keys(lockedPins)), [lockedPins]);
|
|
1932
|
+
const effectivePins = React10.useMemo(() => {
|
|
1933
|
+
if (isReflowViewport || !isOverflowing) return {};
|
|
1934
|
+
const result = {};
|
|
1935
|
+
for (const [key, pin] of Object.entries(colPins)) {
|
|
1936
|
+
result[key] = pin;
|
|
1937
|
+
}
|
|
1938
|
+
return result;
|
|
1939
|
+
}, [colPins, isOverflowing, isReflowViewport]);
|
|
1936
1940
|
function startResize(key, e) {
|
|
1937
1941
|
e.preventDefault();
|
|
1938
1942
|
e.stopPropagation();
|
|
@@ -1993,18 +1997,21 @@ function useTableState(data, columns, defaultSort, paginationOverride, syncedSea
|
|
|
1993
1997
|
function toggleWrap(key) {
|
|
1994
1998
|
setColWrap((p) => ({ ...p, [key]: !p[key] }));
|
|
1995
1999
|
}
|
|
1996
|
-
|
|
2000
|
+
const checkOverflow = React10.useCallback(() => {
|
|
1997
2001
|
const el = scrollRef.current;
|
|
1998
2002
|
if (!el) return;
|
|
1999
|
-
setIsOverflowing(
|
|
2000
|
-
}
|
|
2003
|
+
setIsOverflowing(totalWidth > el.clientWidth + 1);
|
|
2004
|
+
}, [totalWidth]);
|
|
2001
2005
|
function handleScroll() {
|
|
2002
2006
|
const el = scrollRef.current;
|
|
2003
2007
|
if (!el) return;
|
|
2004
2008
|
setScrolled(el.scrollLeft > 1);
|
|
2005
2009
|
setScrollEnd(el.scrollLeft >= el.scrollWidth - el.clientWidth - 1);
|
|
2006
|
-
setIsOverflowing(
|
|
2010
|
+
setIsOverflowing(totalWidth > el.clientWidth + 1);
|
|
2007
2011
|
}
|
|
2012
|
+
React10.useLayoutEffect(() => {
|
|
2013
|
+
checkOverflow();
|
|
2014
|
+
}, [checkOverflow]);
|
|
2008
2015
|
function getRowId(row, index, getIdFn) {
|
|
2009
2016
|
return getIdFn ? getIdFn(row, index) : row.id ?? index;
|
|
2010
2017
|
}
|
|
@@ -2057,10 +2064,6 @@ function useTableState(data, columns, defaultSort, paginationOverride, syncedSea
|
|
|
2057
2064
|
},
|
|
2058
2065
|
[effectivePins, isReflowViewport, stickyOffsets]
|
|
2059
2066
|
);
|
|
2060
|
-
const totalWidth = React10.useMemo(
|
|
2061
|
-
() => displayCols.reduce((s, c) => s + (colWidths[c.key] ?? c.width ?? 100), 0),
|
|
2062
|
-
[displayCols, colWidths]
|
|
2063
|
-
);
|
|
2064
2067
|
return {
|
|
2065
2068
|
// Sort
|
|
2066
2069
|
sortRules,
|
|
@@ -2800,7 +2803,7 @@ function DataTableInner({
|
|
|
2800
2803
|
setSheetOpen,
|
|
2801
2804
|
setSheetInitialPanel
|
|
2802
2805
|
} = state;
|
|
2803
|
-
React10.
|
|
2806
|
+
React10.useLayoutEffect(() => {
|
|
2804
2807
|
const syncScrollport = () => {
|
|
2805
2808
|
const el2 = scrollRef.current;
|
|
2806
2809
|
if (el2) {
|
|
@@ -2813,8 +2816,10 @@ function DataTableInner({
|
|
|
2813
2816
|
if (!el) return;
|
|
2814
2817
|
const ro = new ResizeObserver(syncScrollport);
|
|
2815
2818
|
ro.observe(el);
|
|
2819
|
+
const table = el.querySelector("table");
|
|
2820
|
+
if (table) ro.observe(table);
|
|
2816
2821
|
return () => ro.disconnect();
|
|
2817
|
-
}, []);
|
|
2822
|
+
}, [totalWidth, displayCols.length, checkOverflow, scrollRef]);
|
|
2818
2823
|
const columnMenuPendingActionRef = React10.useRef(null);
|
|
2819
2824
|
const pinnedScrollHintDoneRef = React10.useRef(false);
|
|
2820
2825
|
React10.useEffect(() => {
|
|
@@ -3051,11 +3056,12 @@ function DataTableInner({
|
|
|
3051
3056
|
children: /* @__PURE__ */ jsxs(
|
|
3052
3057
|
"table",
|
|
3053
3058
|
{
|
|
3054
|
-
className: "
|
|
3059
|
+
className: "text-sm border-separate border-spacing-0",
|
|
3055
3060
|
style: {
|
|
3056
3061
|
tableLayout: "fixed",
|
|
3057
|
-
|
|
3058
|
-
|
|
3062
|
+
// Explicit column-sum width — `w-full` made the grid stretch to the scrollport
|
|
3063
|
+
// so scrollWidth === clientWidth and the overflow-gated pin rule never fired.
|
|
3064
|
+
width: totalWidth
|
|
3059
3065
|
},
|
|
3060
3066
|
children: [
|
|
3061
3067
|
/* @__PURE__ */ jsx("colgroup", { children: displayCols.map((col) => /* @__PURE__ */ jsx("col", { style: { width: colWidths[col.key] ?? col.width ?? 100 } }, col.key)) }),
|