zz-meridian 0.25.0 → 0.25.1
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/package.json +1 -1
- package/payload/CHANGELOG.md +8 -1
- package/payload/package.json +1 -1
- package/payload/scripts/audit.ts +3 -3
- package/payload/src/components/patterns/data-table/index.tsx +1 -1
- package/payload/src/components/ui/table/index.tsx +6 -4
- package/payload/tests/table-cut-align.test.tsx +29 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zz-meridian",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "Bring ZZ Meridian, a dashboard design system, into a Next.js project, or start a new dashboard on it. Copies the files in; nothing depends on this package at runtime.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
package/payload/CHANGELOG.md
CHANGED
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
Every release of ZZ Meridian, newest first. Versions follow semver: a removed or renamed token, prop or card is major; a new card, token or variant is minor; a corrected value is a patch. Each entry says what breaks and what to do instead.
|
|
4
4
|
|
|
5
|
+
## [0.25.1] · 2026-10-21
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **A right-aligned or centred cut cell keeps its alignment.** Since 0.25.0 a `truncate` cell's value sits in a grid track as wide as the value, and the cell's `text-align` does not move a track, so a numeric or right-aligned `truncate` cell drew its value at the left. `Cut` takes `align` now and `TableCell` and `DataTable` pass the cell's own; a hand-built cell that uses `Cut` in a right-aligned column passes `align="right"`.
|
|
10
|
+
- **The audit's title check reaches a title column with phone words.** A cut name inside a link and a flex row in a column with `mobileCell` sits seven levels under the cell that carries its title, one more than the walk read, so the audit reported the name as cut without its whole text. The walk reads eight levels.
|
|
11
|
+
|
|
5
12
|
## [0.25.0] · 2026-10-21
|
|
6
13
|
|
|
7
14
|
### Breaking
|
|
8
15
|
|
|
9
|
-
- **Every table column shares the spare width, and `TableHeader`'s `flexible` prop is removed.** A cut cell used to zero its own width (`max-w-0`) and the lead head claimed all the rest (`w-full`), so the record's name sat in empty room while the columns beside it were held at their minimum, cramped at both ends and wrapping. Now every column asks for its content width and a table with room to spare shares it across all of its columns in proportion to those widths. A column whose cells `truncate` asks for its whole content width too and shrinks only when the table lacks room for every column; a column given `width` keeps that width and takes no spare; the `grow` column keeps its floor, 160px, 256px once the table is 672px wide. Drop `flexible` from any `TableHeader`: a `truncate` column now asks for its own width.
|
|
16
|
+
- **Every table column shares the spare width, and `TableHeader`'s `flexible` prop is removed.** A cut cell used to zero its own width (`max-w-0`) and the lead head claimed all the rest (`w-full`), so the record's name sat in empty room while the columns beside it were held at their minimum, cramped at both ends and wrapping. Now every column asks for its content width and a table with room to spare shares it across all of its columns in proportion to those widths. A column whose cells `truncate` asks for its whole content width too and shrinks only when the table lacks room for every column; a column given `width` keeps that width and takes no spare; the `grow` column keeps its floor, 160px, 256px once the table is 672px wide. Drop `flexible` from any `TableHeader`: a `truncate` column now asks for its own width. Before 1.0, Meridian marks a breaking change with the minor version, as semver allows for 0.x.
|
|
10
17
|
|
|
11
18
|
### New
|
|
12
19
|
|
package/payload/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zz-meridian-template",
|
|
3
|
-
"version": "0.25.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "ZZ Meridian: a dashboard design system and starter. Six layers, from DTCG tokens through four layers of React components to product workspaces, and a Design Atlas, in a light and a dark theme.",
|
package/payload/scripts/audit.ts
CHANGED
|
@@ -148,9 +148,9 @@ const MEASURE = `(() => {
|
|
|
148
148
|
// cell titled "Orders" over a cut account id passed as keeping it.
|
|
149
149
|
const whole = (s) => (s || '').replace(/\\s+/g, ' ').trim();
|
|
150
150
|
const keeps = (el, title) => { const t = whole(title), own = whole(el.textContent); return t.length > 0 && own.length > 0 && t.includes(own); };
|
|
151
|
-
// The walk reaches through a table cell's wrapper: a name span in a flex row in a link in
|
|
152
|
-
// wrapper is
|
|
153
|
-
const titled = (el) => { for (let n = el, i = 0; n && i <
|
|
151
|
+
// The walk reaches through a table cell's wrapper: a name span in a flex row in a link in a phone column's own span in
|
|
152
|
+
// the cut span in the wrapper in the cell is seven levels, so the cell's title is still found, with one to spare.
|
|
153
|
+
const titled = (el) => { for (let n = el, i = 0; n && i < 8; n = deepParent(n), i++) if (keeps(el, n.getAttribute('title'))) return true; return [...el.querySelectorAll('[title]')].some((n) => keeps(el, n.getAttribute('title'))); };
|
|
154
154
|
const inked = [];
|
|
155
155
|
const ringSig = (c) => [c.outlineStyle, c.outlineWidth, c.outlineColor, c.boxShadow, c.borderTopStyle, c.borderTopWidth, c.borderTopColor, c.borderBottomColor, c.borderLeftColor, c.borderRightColor].join('|');
|
|
156
156
|
const texts = [];
|
|
@@ -357,7 +357,7 @@ export function DataTable<R>({
|
|
|
357
357
|
<span className="hidden @max-[640px]:contents">{c.mobileCell(r)}</span>
|
|
358
358
|
</>
|
|
359
359
|
) : content;
|
|
360
|
-
return c.truncate ? <Cut>{body}</Cut> : body;
|
|
360
|
+
return c.truncate ? <Cut align={c.align ?? (c.numeric ? 'right' : 'left')}>{body}</Cut> : body;
|
|
361
361
|
})()}
|
|
362
362
|
</td>
|
|
363
363
|
);
|
|
@@ -16,6 +16,7 @@ export type Breakpoint = 'sm' | 'md' | 'lg' | 'xl';
|
|
|
16
16
|
/* Literal strings: Tailwind finds classes by reading the source. */
|
|
17
17
|
const HIDE: Record<Breakpoint, string> = { sm: '@max-[512px]:hidden', md: '@max-[672px]:hidden', lg: '@max-[896px]:hidden', xl: '@max-[1152px]:hidden' };
|
|
18
18
|
const ALIGN = { left: 'text-left', right: 'text-right', center: 'text-center' } as const;
|
|
19
|
+
const JUSTIFY = { left: undefined, right: 'justify-end', center: 'justify-center' } as const;
|
|
19
20
|
|
|
20
21
|
export function Table({ className, caption, children, ...rest }: HTMLAttributes<HTMLTableElement> & { caption?: string }) {
|
|
21
22
|
return (
|
|
@@ -131,11 +132,12 @@ export function TableHeader({
|
|
|
131
132
|
/**
|
|
132
133
|
* A cut value: it asks for its whole content's width and shrinks only when the table has no room. One grid track of
|
|
133
134
|
* `minmax(0, max-content)` gives the cell that ask, where `max-w-0` on the cell zeroed it and sent every spare pixel to
|
|
134
|
-
* the lead column.
|
|
135
|
+
* the lead column. The track is as wide as the value and the cell's `text-align` does not move it, so it takes the
|
|
136
|
+
* cell's alignment itself.
|
|
135
137
|
*/
|
|
136
|
-
export function Cut({ children }: { children?: ReactNode }) {
|
|
138
|
+
export function Cut({ align = 'left', children }: { align?: keyof typeof ALIGN; children?: ReactNode }) {
|
|
137
139
|
return (
|
|
138
|
-
<span className=
|
|
140
|
+
<span className={cn('grid min-w-0 grid-cols-[minmax(0,max-content)]', JUSTIFY[align])}>
|
|
139
141
|
<span className="truncate">{children}</span>
|
|
140
142
|
</span>
|
|
141
143
|
);
|
|
@@ -169,7 +171,7 @@ export function TableCell({
|
|
|
169
171
|
)}
|
|
170
172
|
{...rest}
|
|
171
173
|
>
|
|
172
|
-
{truncate ? <Cut>{children}</Cut> : children}
|
|
174
|
+
{truncate ? <Cut align={align ?? (numeric ? 'right' : 'left')}>{children}</Cut> : children}
|
|
173
175
|
</td>
|
|
174
176
|
);
|
|
175
177
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
import { Table, TableBody, TableCell, TableRow } from '@/components/ui/table';
|
|
4
|
+
|
|
5
|
+
const wrapOf = (td: Element) => td.firstElementChild!.getAttribute('class')?.split(/\s+/) ?? [];
|
|
6
|
+
|
|
7
|
+
/** The cut track is as wide as the value, so the cell's text-align cannot move it: the wrapper carries the alignment. */
|
|
8
|
+
describe('a cut cell keeps its alignment', () => {
|
|
9
|
+
it('justifies a right-aligned, numeric or centred value and leaves a left one alone', () => {
|
|
10
|
+
const { container } = render(
|
|
11
|
+
<Table>
|
|
12
|
+
<TableBody>
|
|
13
|
+
<TableRow>
|
|
14
|
+
<TableCell truncate>left</TableCell>
|
|
15
|
+
<TableCell truncate align="right">right</TableCell>
|
|
16
|
+
<TableCell truncate numeric>1,204</TableCell>
|
|
17
|
+
<TableCell truncate align="center">centre</TableCell>
|
|
18
|
+
</TableRow>
|
|
19
|
+
</TableBody>
|
|
20
|
+
</Table>,
|
|
21
|
+
);
|
|
22
|
+
const [left, right, numeric, centre] = [...container.querySelectorAll('td')].map(wrapOf);
|
|
23
|
+
expect(left).not.toContain('justify-end');
|
|
24
|
+
expect(left).not.toContain('justify-center');
|
|
25
|
+
expect(right).toContain('justify-end');
|
|
26
|
+
expect(numeric).toContain('justify-end');
|
|
27
|
+
expect(centre).toContain('justify-center');
|
|
28
|
+
});
|
|
29
|
+
});
|