@trackunit/react-components 1.13.10 → 1.13.12
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/index.cjs.js +1103 -6
- package/index.esm.js +1091 -9
- package/package.json +5 -5
- package/src/components/GridAreas/GridAreas.d.ts +95 -0
- package/src/components/GridAreas/createGrid.d.ts +130 -0
- package/src/components/GridAreas/generateCss.d.ts +15 -0
- package/src/components/GridAreas/types.d.ts +104 -0
- package/src/components/GridAreas/useGridAreas.d.ts +62 -0
- package/src/components/GridAreas/validateGridConfig.d.ts +9 -0
- package/src/components/GridAreas/validateGridSlots.d.ts +9 -0
- package/src/components/ListItem/ListItem.variants.d.ts +5 -0
- package/src/components/PreferenceCard/PreferenceCard.d.ts +70 -0
- package/src/components/PreferenceCard/PreferenceCard.variants.d.ts +25 -0
- package/src/components/PreferenceCard/PreferenceCardSkeleton.d.ts +25 -0
- package/src/components/Skeleton/Skeleton.d.ts +115 -0
- package/src/components/Skeleton/Skeleton.variants.d.ts +1 -0
- package/src/components/Skeleton/index.d.ts +2 -0
- package/src/index.d.ts +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-components",
|
|
3
|
-
"version": "1.13.
|
|
3
|
+
"version": "1.13.12",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
"@floating-ui/react": "^0.26.25",
|
|
15
15
|
"string-ts": "^2.0.0",
|
|
16
16
|
"tailwind-merge": "^2.0.0",
|
|
17
|
-
"@trackunit/ui-design-tokens": "1.9.
|
|
18
|
-
"@trackunit/css-class-variance-utilities": "1.9.
|
|
19
|
-
"@trackunit/shared-utils": "1.11.
|
|
20
|
-
"@trackunit/ui-icons": "1.9.
|
|
17
|
+
"@trackunit/ui-design-tokens": "1.9.20",
|
|
18
|
+
"@trackunit/css-class-variance-utilities": "1.9.21",
|
|
19
|
+
"@trackunit/shared-utils": "1.11.21",
|
|
20
|
+
"@trackunit/ui-icons": "1.9.20",
|
|
21
21
|
"@tanstack/react-router": "1.114.29",
|
|
22
22
|
"es-toolkit": "^1.39.10",
|
|
23
23
|
"@tanstack/react-virtual": "3.13.12",
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { GridAreasResult, SlotProps } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Props for the GridAreas component.
|
|
5
|
+
*
|
|
6
|
+
* Spread the result from useGridAreas() onto this component.
|
|
7
|
+
*/
|
|
8
|
+
export type GridAreasProps<TAreaName extends string> = GridAreasResult<TAreaName> & {
|
|
9
|
+
/** Additional CSS classes to apply to the grid container */
|
|
10
|
+
className?: string;
|
|
11
|
+
/** Render prop that receives the slots object */
|
|
12
|
+
children: (slots: Record<TAreaName, SlotProps>) => ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* If true, renders as the child element instead of a div.
|
|
15
|
+
* The child must accept className and ref props.
|
|
16
|
+
*/
|
|
17
|
+
asChild?: boolean;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Component for CSS grid with dynamic grid-template-areas.
|
|
21
|
+
*
|
|
22
|
+
* Renders the style tag and container div with proper scoping.
|
|
23
|
+
* Uses a render prop pattern to provide typed slot props for children.
|
|
24
|
+
*
|
|
25
|
+
* @example Basic usage with builder pattern and hook
|
|
26
|
+
* ```tsx
|
|
27
|
+
* // Define grid config at module level (runs once)
|
|
28
|
+
* const cardGrid = createGrid()
|
|
29
|
+
* .areas(['icon', 'info'])
|
|
30
|
+
* .layout({ layout: [['icon', 'info']] })
|
|
31
|
+
* .build();
|
|
32
|
+
*
|
|
33
|
+
* function MyCard() {
|
|
34
|
+
* const gridAreas = useGridAreas(cardGrid);
|
|
35
|
+
*
|
|
36
|
+
* return (
|
|
37
|
+
* <GridAreas {...gridAreas} className="gap-4">
|
|
38
|
+
* {(slots) => (
|
|
39
|
+
* <>
|
|
40
|
+
* <Icon {...slots.icon} />
|
|
41
|
+
* <Info {...slots.info} />
|
|
42
|
+
* </>
|
|
43
|
+
* )}
|
|
44
|
+
* </GridAreas>
|
|
45
|
+
* );
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
* @example Conditional layouts
|
|
49
|
+
* ```tsx
|
|
50
|
+
* const cardGrid = createGrid()
|
|
51
|
+
* .areas(['icon', 'info', 'tag'])
|
|
52
|
+
* .layout({ layout: [['info']] })
|
|
53
|
+
* .layout({
|
|
54
|
+
* when: ['icon', 'info'],
|
|
55
|
+
* layout: [['icon', 'info']],
|
|
56
|
+
* columns: ['48px', '1fr'],
|
|
57
|
+
* })
|
|
58
|
+
* .build();
|
|
59
|
+
*
|
|
60
|
+
* function MyCard({ showIcon }) {
|
|
61
|
+
* const gridAreas = useGridAreas(cardGrid);
|
|
62
|
+
*
|
|
63
|
+
* return (
|
|
64
|
+
* <GridAreas {...gridAreas}>
|
|
65
|
+
* {(slots) => (
|
|
66
|
+
* <>
|
|
67
|
+
* {showIcon && <Icon {...slots.icon} />}
|
|
68
|
+
* <Info {...slots.info} />
|
|
69
|
+
* </>
|
|
70
|
+
* )}
|
|
71
|
+
* </GridAreas>
|
|
72
|
+
* );
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
* @example Using asChild to render a custom element
|
|
76
|
+
* ```tsx
|
|
77
|
+
* function MyCard() {
|
|
78
|
+
* const gridAreas = useGridAreas(cardGrid);
|
|
79
|
+
*
|
|
80
|
+
* return (
|
|
81
|
+
* <GridAreas {...gridAreas} asChild className="gap-4">
|
|
82
|
+
* <section aria-label="Card content">
|
|
83
|
+
* {(slots) => (
|
|
84
|
+
* <>
|
|
85
|
+
* <Icon {...slots.icon} />
|
|
86
|
+
* <Info {...slots.info} />
|
|
87
|
+
* </>
|
|
88
|
+
* )}
|
|
89
|
+
* </section>
|
|
90
|
+
* </GridAreas>
|
|
91
|
+
* );
|
|
92
|
+
* }
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export declare function GridAreas<TAreaName extends string>({ slots, css, containerProps, validationRef, className, children, asChild, }: GridAreasProps<TAreaName>): ReactNode;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { BreakpointLayoutConfig, ContainerBreakpoint, EmptyCell, GridConfig, TrackSize } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* A readonly 2D grid layout tuple for type-safe layout configuration.
|
|
4
|
+
* Each inner tuple represents a row of grid cells.
|
|
5
|
+
*/
|
|
6
|
+
type GridLayoutTuple<TCell extends string = string> = ReadonlyArray<ReadonlyArray<TCell>>;
|
|
7
|
+
/**
|
|
8
|
+
* Extracts the row count from a layout tuple.
|
|
9
|
+
*/
|
|
10
|
+
type LayoutRowCount<TLayout extends GridLayoutTuple> = TLayout["length"];
|
|
11
|
+
/**
|
|
12
|
+
* Extracts the column count from a layout tuple (from first row).
|
|
13
|
+
*/
|
|
14
|
+
type LayoutColCount<TLayout extends GridLayoutTuple> = TLayout extends readonly [
|
|
15
|
+
infer TFirstRow extends ReadonlyArray<unknown>,
|
|
16
|
+
...ReadonlyArray<unknown>
|
|
17
|
+
] ? TFirstRow["length"] : 0;
|
|
18
|
+
/**
|
|
19
|
+
* Flattens a layout tuple to get all used cell values as a union type.
|
|
20
|
+
*/
|
|
21
|
+
type FlattenLayout<TLayout extends GridLayoutTuple> = TLayout[number][number];
|
|
22
|
+
/**
|
|
23
|
+
* Finds items from TWhen that are NOT present in the layout.
|
|
24
|
+
* Returns never if all items are present, otherwise returns the missing items.
|
|
25
|
+
*/
|
|
26
|
+
type FindMissingWhenItems<TWhen extends ReadonlyArray<string>, TLayout extends GridLayoutTuple> = Exclude<TWhen[number], FlattenLayout<TLayout>>;
|
|
27
|
+
/**
|
|
28
|
+
* Strict input type for .layout() that validates all constraints.
|
|
29
|
+
* Errors appear directly on the invalid property for clear feedback.
|
|
30
|
+
*
|
|
31
|
+
* @template TAreaName - Available area names from .areas()
|
|
32
|
+
* @template TLayout - The layout tuple being validated
|
|
33
|
+
* @template TWhen - Optional when clause (subset of TAreaName)
|
|
34
|
+
* @template TRows - Optional row track sizes
|
|
35
|
+
* @template TCols - Optional column track sizes
|
|
36
|
+
*/
|
|
37
|
+
type StrictLayoutInput<TAreaName extends string, TLayout extends GridLayoutTuple<TAreaName | EmptyCell>, TWhen extends ReadonlyArray<TAreaName> | undefined, TRows extends ReadonlyArray<TrackSize> | undefined, TCols extends ReadonlyArray<TrackSize> | undefined> = {
|
|
38
|
+
/**
|
|
39
|
+
* Area names that must be present for this layout to apply.
|
|
40
|
+
* Must be a subset of the areas defined in .areas().
|
|
41
|
+
*/
|
|
42
|
+
when?: TWhen;
|
|
43
|
+
/**
|
|
44
|
+
* The grid layout. Each cell must be an area name or "." for empty.
|
|
45
|
+
* When `when` is provided, all `when` items must appear in the layout.
|
|
46
|
+
*/
|
|
47
|
+
layout: TLayout & (TWhen extends ReadonlyArray<TAreaName> ? FindMissingWhenItems<TWhen, TLayout> extends never ? unknown : {
|
|
48
|
+
_missingFromLayout: FindMissingWhenItems<TWhen, TLayout>;
|
|
49
|
+
} : unknown);
|
|
50
|
+
/**
|
|
51
|
+
* Grid row track sizes. Length must match the number of rows in layout.
|
|
52
|
+
*/
|
|
53
|
+
rows?: TRows & (TRows extends ReadonlyArray<TrackSize> ? TRows["length"] extends LayoutRowCount<TLayout> ? unknown : {
|
|
54
|
+
_rowCountError: {
|
|
55
|
+
expected: LayoutRowCount<TLayout>;
|
|
56
|
+
got: TRows["length"];
|
|
57
|
+
};
|
|
58
|
+
} : unknown);
|
|
59
|
+
/**
|
|
60
|
+
* Grid column track sizes. Length must match the number of columns in layout.
|
|
61
|
+
*/
|
|
62
|
+
columns?: TCols & (TCols extends ReadonlyArray<TrackSize> ? TCols["length"] extends LayoutColCount<TLayout> ? unknown : {
|
|
63
|
+
_columnCountError: {
|
|
64
|
+
expected: LayoutColCount<TLayout>;
|
|
65
|
+
got: TCols["length"];
|
|
66
|
+
};
|
|
67
|
+
} : unknown);
|
|
68
|
+
/**
|
|
69
|
+
* Responsive breakpoint overrides.
|
|
70
|
+
*/
|
|
71
|
+
breakpoints?: Partial<Record<ContainerBreakpoint, BreakpointLayoutConfig<TAreaName>>>;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Builder interface for adding layouts after .areas() is called.
|
|
75
|
+
* Each .layout() call is type-checked against the available areas.
|
|
76
|
+
*/
|
|
77
|
+
interface GridAreasBuilder<TAreaName extends string> {
|
|
78
|
+
/**
|
|
79
|
+
* Add a layout configuration. Can be chained multiple times.
|
|
80
|
+
* Layout cells are constrained to area names defined in .areas() plus ".".
|
|
81
|
+
*/
|
|
82
|
+
layout<const TLayout extends GridLayoutTuple<TAreaName | EmptyCell>, const TWhen extends ReadonlyArray<TAreaName> | undefined = undefined, const TRows extends ReadonlyArray<TrackSize> | undefined = undefined, const TCols extends ReadonlyArray<TrackSize> | undefined = undefined>(config: StrictLayoutInput<TAreaName, TLayout, TWhen, TRows, TCols>): GridAreasBuilder<TAreaName>;
|
|
83
|
+
/**
|
|
84
|
+
* Finalize and return the grid configuration.
|
|
85
|
+
* Pass this to the GridAreas component.
|
|
86
|
+
*/
|
|
87
|
+
build(): GridConfig<TAreaName>;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Initial builder interface before .areas() is called.
|
|
91
|
+
*/
|
|
92
|
+
interface GridAreasBuilderInit {
|
|
93
|
+
/**
|
|
94
|
+
* Define the area names for this grid.
|
|
95
|
+
* These names will be available for autocomplete in .layout() calls.
|
|
96
|
+
*/
|
|
97
|
+
areas<const TAreas extends ReadonlyArray<string>>(areas: TAreas): GridAreasBuilder<TAreas[number]>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Creates a type-safe grid configuration using a fluent builder pattern.
|
|
101
|
+
*
|
|
102
|
+
* The builder provides:
|
|
103
|
+
* - Full autocomplete for area names in layouts
|
|
104
|
+
* - Type errors on the correct property (columns, rows, layout)
|
|
105
|
+
* - Validation that layout cells match defined areas
|
|
106
|
+
* - Validation that all `when` items appear in the layout
|
|
107
|
+
*
|
|
108
|
+
* @example Module-level definition (recommended for static grids)
|
|
109
|
+
* ```tsx
|
|
110
|
+
* const cardGrid = createGrid()
|
|
111
|
+
* .areas(["icon", "info", "tag"])
|
|
112
|
+
* .layout({ layout: [["info"]] })
|
|
113
|
+
* .layout({
|
|
114
|
+
* when: ["icon", "info"],
|
|
115
|
+
* layout: [["icon", "info"]],
|
|
116
|
+
* columns: ["48px", "1fr"],
|
|
117
|
+
* })
|
|
118
|
+
* .build();
|
|
119
|
+
*
|
|
120
|
+
* function MyCard() {
|
|
121
|
+
* return (
|
|
122
|
+
* <GridAreas config={cardGrid}>
|
|
123
|
+
* {(slots) => (<>{slots.icon}...</>)}
|
|
124
|
+
* </GridAreas>
|
|
125
|
+
* );
|
|
126
|
+
* }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
export declare function createGrid(): GridAreasBuilderInit;
|
|
130
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { GridConfig, SlotProps } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a typed slots object from an array of area names.
|
|
4
|
+
*
|
|
5
|
+
* Each slot contains a data-slot attribute and gridArea style.
|
|
6
|
+
*/
|
|
7
|
+
export declare function createSlots<TAreaName extends string>(areas: ReadonlyArray<TAreaName>): Record<TAreaName, SlotProps>;
|
|
8
|
+
/**
|
|
9
|
+
* Generates CSS string from a grid configuration and id.
|
|
10
|
+
*
|
|
11
|
+
* @param id - Unique identifier for CSS scoping
|
|
12
|
+
* @param config - Grid configuration from createGrid().build()
|
|
13
|
+
* @returns {string} CSS string for use in a style tag
|
|
14
|
+
*/
|
|
15
|
+
export declare function generateCss<TAreaName extends string>(id: string, config: GridConfig<TAreaName>): string;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { StringWithAutocompleteOptions } from "@trackunit/shared-utils";
|
|
2
|
+
import { themeContainerSize } from "@trackunit/ui-design-tokens";
|
|
3
|
+
import { CSSProperties } from "react";
|
|
4
|
+
/**
|
|
5
|
+
* Tailwind CSS default container query breakpoints with @ prefix.
|
|
6
|
+
*
|
|
7
|
+
* These are the standard values used by @sm, @md, @lg, etc. in Tailwind container queries.
|
|
8
|
+
* Values are sourced from themeContainerSize in @trackunit/ui-design-tokens.
|
|
9
|
+
*
|
|
10
|
+
* @see https://tailwindcss.com/docs/responsive-design#container-queries
|
|
11
|
+
*/
|
|
12
|
+
export declare const CONTAINER_BREAKPOINTS: { [K in keyof typeof themeContainerSize as `@${K}`]: (typeof themeContainerSize)[K]; };
|
|
13
|
+
export type ContainerBreakpoint = keyof typeof CONTAINER_BREAKPOINTS;
|
|
14
|
+
/**
|
|
15
|
+
* Empty cell marker for grid-template-areas.
|
|
16
|
+
*
|
|
17
|
+
* In CSS, a "." represents an empty/unnamed cell in the grid.
|
|
18
|
+
*/
|
|
19
|
+
export type EmptyCell = ".";
|
|
20
|
+
/**
|
|
21
|
+
* A grid cell can be either an area name or an empty cell marker.
|
|
22
|
+
*/
|
|
23
|
+
export type GridCell<TAreaName extends string> = TAreaName | EmptyCell;
|
|
24
|
+
/**
|
|
25
|
+
* A 2D grid layout where each inner array represents a row.
|
|
26
|
+
* Use "." for empty cells.
|
|
27
|
+
*/
|
|
28
|
+
export type GridLayout<TAreaName extends string> = Array<Array<GridCell<TAreaName>>>;
|
|
29
|
+
/**
|
|
30
|
+
* Track size definition (e.g., "1fr", "min-content", "auto", "100px")
|
|
31
|
+
*/
|
|
32
|
+
export type TrackSize = StringWithAutocompleteOptions<"1fr" | "min-content" | "auto" | "minmax(0,1fr)">;
|
|
33
|
+
/**
|
|
34
|
+
* Layout configuration with optional conditions and track sizes.
|
|
35
|
+
* This is the runtime type - compile-time validation is done by the builder.
|
|
36
|
+
*/
|
|
37
|
+
export type LayoutConfig<TAreaName extends string> = {
|
|
38
|
+
/** The grid layout to apply. Use "." for empty cells. */
|
|
39
|
+
layout: GridLayout<TAreaName>;
|
|
40
|
+
/** Grid row track sizes. */
|
|
41
|
+
rows?: Array<TrackSize>;
|
|
42
|
+
/** Grid column track sizes. */
|
|
43
|
+
columns?: Array<TrackSize>;
|
|
44
|
+
/** Area names that must be present for this layout to apply. */
|
|
45
|
+
when?: Array<TAreaName>;
|
|
46
|
+
/** Responsive breakpoint overrides */
|
|
47
|
+
breakpoints?: Partial<Record<ContainerBreakpoint, BreakpointLayoutConfig<TAreaName>>>;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Breakpoint layout override - can include different layout and/or track sizes
|
|
51
|
+
*/
|
|
52
|
+
export type BreakpointLayoutConfig<TAreaName extends string> = {
|
|
53
|
+
layout: GridLayout<TAreaName>;
|
|
54
|
+
rows?: Array<TrackSize>;
|
|
55
|
+
columns?: Array<TrackSize>;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Grid configuration output from the builder.
|
|
59
|
+
* Contains the layout structure - id is generated at render time.
|
|
60
|
+
*/
|
|
61
|
+
export type GridConfig<TAreaName extends string> = {
|
|
62
|
+
/** Array of area names - selectors are auto-generated as [data-slot=name] */
|
|
63
|
+
areas: ReadonlyArray<TAreaName>;
|
|
64
|
+
/** Layout configurations */
|
|
65
|
+
layouts: Array<LayoutConfig<TAreaName>>;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Slot props object for spreading on elements.
|
|
69
|
+
*
|
|
70
|
+
* Includes both the data-slot attribute (for CSS :has() selectors)
|
|
71
|
+
* and the style with gridArea (for grid placement).
|
|
72
|
+
*/
|
|
73
|
+
export type SlotProps = {
|
|
74
|
+
"data-slot": string;
|
|
75
|
+
style: {
|
|
76
|
+
gridArea: string;
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* Nested styles object for container queries and conditional selectors
|
|
81
|
+
*/
|
|
82
|
+
export interface NestedStyles {
|
|
83
|
+
[key: string]: CSSProperties[keyof CSSProperties] | NestedStyles | undefined;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* CSS-in-JS compatible styles object with nested selectors
|
|
87
|
+
*/
|
|
88
|
+
export type GridStyles = NestedStyles;
|
|
89
|
+
/**
|
|
90
|
+
* Result type from useGridAreas hook.
|
|
91
|
+
* Contains everything needed to render a GridAreas component.
|
|
92
|
+
*/
|
|
93
|
+
export type GridAreasResult<TAreaName extends string> = {
|
|
94
|
+
/** Props to spread on elements, keyed by area name. Includes data-slot and style.gridArea */
|
|
95
|
+
slots: Record<TAreaName, SlotProps>;
|
|
96
|
+
/** CSS string for use in a <style> tag */
|
|
97
|
+
css: string;
|
|
98
|
+
/** Data attribute to add to the container element for CSS scoping */
|
|
99
|
+
containerProps: {
|
|
100
|
+
"data-grid-id": string;
|
|
101
|
+
};
|
|
102
|
+
/** Ref callback for development-only DOM validation. Attach to the grid container element. */
|
|
103
|
+
validationRef: (element: HTMLElement | null) => void;
|
|
104
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { GridAreasResult, GridConfig } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* React hook for creating type-safe CSS grid-template-areas with automatic :has() selector generation.
|
|
4
|
+
*
|
|
5
|
+
* Automatically generates a unique id using React's useId() hook.
|
|
6
|
+
* Returns memoized grid configuration including slots, CSS, and container props.
|
|
7
|
+
*
|
|
8
|
+
* In development mode, validates the grid configuration and logs warnings for:
|
|
9
|
+
* - Empty areas or layouts
|
|
10
|
+
* - Unknown area names in layouts or when clauses
|
|
11
|
+
* - Mismatched row/column counts
|
|
12
|
+
* - Missing when items in layouts
|
|
13
|
+
*
|
|
14
|
+
* Also returns a validationRef callback that validates DOM children when attached.
|
|
15
|
+
*
|
|
16
|
+
* @example Basic usage with builder pattern
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const cardGrid = createGrid()
|
|
19
|
+
* .areas(["icon", "info"])
|
|
20
|
+
* .layout({ layout: [["icon", "info"]] })
|
|
21
|
+
* .build();
|
|
22
|
+
*
|
|
23
|
+
* function MyCard() {
|
|
24
|
+
* const gridAreas = useGridAreas(cardGrid);
|
|
25
|
+
*
|
|
26
|
+
* return (
|
|
27
|
+
* <GridAreas {...gridAreas}>
|
|
28
|
+
* {(slots) => (
|
|
29
|
+
* <>
|
|
30
|
+
* <Icon {...slots.icon} />
|
|
31
|
+
* <Info {...slots.info} />
|
|
32
|
+
* </>
|
|
33
|
+
* )}
|
|
34
|
+
* </GridAreas>
|
|
35
|
+
* );
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
* @example Conditional layouts with row/column sizing
|
|
39
|
+
* ```tsx
|
|
40
|
+
* const cardGrid = createGrid()
|
|
41
|
+
* .areas(["icon", "title", "description"])
|
|
42
|
+
* .layout({ layout: [["title"]] })
|
|
43
|
+
* .layout({
|
|
44
|
+
* when: ["icon", "title", "description"],
|
|
45
|
+
* layout: [
|
|
46
|
+
* ["icon", "title"],
|
|
47
|
+
* ["icon", "description"],
|
|
48
|
+
* ],
|
|
49
|
+
* rows: ["auto", "1fr"],
|
|
50
|
+
* columns: ["48px", "1fr"],
|
|
51
|
+
* })
|
|
52
|
+
* .build();
|
|
53
|
+
*
|
|
54
|
+
* function Card() {
|
|
55
|
+
* const gridAreas = useGridAreas(cardGrid);
|
|
56
|
+
* // ...
|
|
57
|
+
* }
|
|
58
|
+
* ```
|
|
59
|
+
* @param config - Grid configuration from createGrid().build()
|
|
60
|
+
* @returns {GridAreasResult} Object with slots, css, containerProps, and validationRef to spread on GridAreas
|
|
61
|
+
*/
|
|
62
|
+
export declare function useGridAreas<TAreaName extends string>(config: GridConfig<TAreaName>): GridAreasResult<TAreaName>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { GridConfig } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Validates a grid configuration and returns an array of error messages.
|
|
4
|
+
* Returns an empty array if the configuration is valid.
|
|
5
|
+
*
|
|
6
|
+
* @param config - The grid configuration to validate
|
|
7
|
+
* @returns {Array<string>} Array of error message strings
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateGridConfig<TAreaName extends string>(config: GridConfig<TAreaName>): Array<string>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validates that all direct children of a grid container have proper slot props.
|
|
3
|
+
* Checks for both data-slot attribute and gridArea style, and validates they match.
|
|
4
|
+
*
|
|
5
|
+
* @param container - The grid container element
|
|
6
|
+
* @param areas - Array of valid area names
|
|
7
|
+
* @returns {Array<string>} Array of warning message strings
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateGridSlots(container: HTMLElement, areas: ReadonlyArray<string>): Array<string>;
|
|
@@ -3,3 +3,8 @@ export declare const cvaMainInformationClass: (props?: ({
|
|
|
3
3
|
hasThumbnail?: boolean | null | undefined;
|
|
4
4
|
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
5
5
|
export declare const cvaThumbnailContainer: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
6
|
+
export declare const cvaTextContainer: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
7
|
+
export declare const cvaTitleRow: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
8
|
+
export declare const cvaDescriptionRow: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
9
|
+
export declare const cvaMetaRow: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
10
|
+
export declare const cvaDetailsContainer: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { VariantProps } from "@trackunit/css-class-variance-utilities";
|
|
2
|
+
import { MappedOmit } from "@trackunit/shared-utils";
|
|
3
|
+
import { IconName } from "@trackunit/ui-icons";
|
|
4
|
+
import { ReactElement, ReactNode } from "react";
|
|
5
|
+
import { CommonProps } from "../../common/CommonProps";
|
|
6
|
+
import { TagProps } from "../Tag";
|
|
7
|
+
import { cvaPreferenceCard } from "./PreferenceCard.variants";
|
|
8
|
+
/**
|
|
9
|
+
* Grid layout configuration for the PreferenceCard content area.
|
|
10
|
+
* Defined at module level for optimal performance (runs once).
|
|
11
|
+
*/
|
|
12
|
+
export declare const preferenceCardGrid: import("../..").GridConfig<"icon" | "information" | "cardTag">;
|
|
13
|
+
type IconDetails = {
|
|
14
|
+
type: "icon";
|
|
15
|
+
name: IconName;
|
|
16
|
+
containerClassName: string;
|
|
17
|
+
};
|
|
18
|
+
type ImageDetails = {
|
|
19
|
+
type: "image";
|
|
20
|
+
src: string;
|
|
21
|
+
alt: string;
|
|
22
|
+
containerClassName?: string;
|
|
23
|
+
};
|
|
24
|
+
export interface PreferenceCardProps extends CommonProps, MappedOmit<VariantProps<typeof cvaPreferenceCard>, "className"> {
|
|
25
|
+
/**
|
|
26
|
+
* The title of the preference card
|
|
27
|
+
*/
|
|
28
|
+
title: string;
|
|
29
|
+
/**
|
|
30
|
+
* The description text for the preference card
|
|
31
|
+
*/
|
|
32
|
+
description: string;
|
|
33
|
+
/**
|
|
34
|
+
* The icon or image to display in the card
|
|
35
|
+
*/
|
|
36
|
+
icon?: IconDetails | ImageDetails;
|
|
37
|
+
/**
|
|
38
|
+
* Input component to display in the card (e.g., Checkbox, RadioItem, ToggleSwitch)
|
|
39
|
+
*/
|
|
40
|
+
input?: ReactElement<HTMLInputElement>;
|
|
41
|
+
/**
|
|
42
|
+
* Tag displayed inline next to the title - if provided, shows the tag component
|
|
43
|
+
*/
|
|
44
|
+
titleTag?: {
|
|
45
|
+
title: string;
|
|
46
|
+
color: TagProps["color"];
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Tag displayed at the right end of the card - if provided, shows the tag component
|
|
50
|
+
*/
|
|
51
|
+
cardTag?: {
|
|
52
|
+
title: string;
|
|
53
|
+
color: TagProps["color"];
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Whether the card is disabled
|
|
57
|
+
*/
|
|
58
|
+
disabled?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Extra content to display at the bottom of the card
|
|
61
|
+
*/
|
|
62
|
+
children?: ReactNode;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* PreferenceCard is a flexible component for displaying add-ons or settings configuration options
|
|
66
|
+
* with various states and visual treatments.
|
|
67
|
+
* It is recommended to be primarily used as an input component, as it supports checkboxes, radio buttons and toggles.
|
|
68
|
+
*/
|
|
69
|
+
export declare const PreferenceCard: ({ title, description, icon, input, titleTag, cardTag, disabled, className, "data-testid": dataTestId, children, }: PreferenceCardProps) => ReactNode;
|
|
70
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keeps the data-slot attribute name usage in sync with the tailwind has() selector
|
|
3
|
+
* by having them both satisfy the same template literal type containing the data-slot attribute name.
|
|
4
|
+
*/
|
|
5
|
+
export type StringContainingDataInputContainerAttr = `${string}input-container${string}`;
|
|
6
|
+
export declare const cvaPreferenceCard: (props?: ({
|
|
7
|
+
disabled?: boolean | null | undefined;
|
|
8
|
+
clickable?: boolean | null | undefined;
|
|
9
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
10
|
+
export declare const cvaInputContainer: (props?: ({
|
|
11
|
+
itemPlacement?: "center" | "start" | null | undefined;
|
|
12
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
13
|
+
export declare const cvaContentContainer: (props?: ({
|
|
14
|
+
itemPlacement?: "center" | "start" | null | undefined;
|
|
15
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
16
|
+
export declare const cvaTitleCard: (props?: ({
|
|
17
|
+
disabled?: boolean | null | undefined;
|
|
18
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
19
|
+
export declare const cvaDescriptionCard: (props?: ({
|
|
20
|
+
disabled?: boolean | null | undefined;
|
|
21
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
22
|
+
export declare const cvaIconBackground: (props?: ({
|
|
23
|
+
disabled?: boolean | null | undefined;
|
|
24
|
+
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
25
|
+
export declare const cvaContentWrapper: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Default property values for PreferenceCardSkeleton component.
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_SKELETON_PREFERENCE_CARD_PROPS: {
|
|
6
|
+
readonly hasIcon: false;
|
|
7
|
+
readonly hasTitleTag: false;
|
|
8
|
+
readonly hasCardTag: false;
|
|
9
|
+
readonly hasInput: false;
|
|
10
|
+
};
|
|
11
|
+
export interface PreferenceCardSkeletonProps {
|
|
12
|
+
/** Whether to show an icon skeleton */
|
|
13
|
+
hasIcon?: boolean;
|
|
14
|
+
/** Whether to show a title tag skeleton (inline with title) */
|
|
15
|
+
hasTitleTag?: boolean;
|
|
16
|
+
/** Whether to show a card tag skeleton (right-aligned tag) */
|
|
17
|
+
hasCardTag?: boolean;
|
|
18
|
+
/** Whether to show an input skeleton */
|
|
19
|
+
hasInput?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Skeleton loading indicator that mimics the PreferenceCard component structure.
|
|
23
|
+
* Uses the same grid layout, spacing, and visual hierarchy as PreferenceCard.
|
|
24
|
+
*/
|
|
25
|
+
export declare const PreferenceCardSkeleton: ({ hasIcon, hasTitleTag, hasCardTag, hasInput, }: PreferenceCardSkeletonProps) => ReactElement;
|