@usableapp/cardds 0.7.61 → 0.7.62
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 +5 -0
- package/README.md +3 -1
- package/css/sheet.css +16 -0
- package/dist/cardds.css +16 -0
- package/dist/sheets/Sheet.d.ts +3 -1
- package/dist/sheets/Sheet.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
> For: a project that consumes `@usableapp/cardds` and its AI — what changed between versions, written as before → after, so a screen can be brought up to date without reading the source. Newest first. A consumer never edits cardds; if something here leaves you without a way to do what you did before, report the gap.
|
|
4
4
|
|
|
5
|
+
## 0.7.62 — 2026-10-06
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **`Sheet` takes `refreshing`** (Lh 2026-10-06) — a boolean, off unless you set it. While `true`, the sheet's grab mark (the line, or the dots with `mark="dots"`) changes colour the way a stack sheet's does, and the sheet is `aria-busy`. Set it when you start reloading what the sheet shows, clear it when the data is in: `<Sheet refreshing={loading} …>`. The single sheet has no pull to refresh of its own and does not fetch — when to reload is yours. Omit it and nothing changes.
|
|
9
|
+
|
|
5
10
|
## 0.7.61 — 2026-10-06
|
|
6
11
|
|
|
7
12
|
### Changed
|
package/README.md
CHANGED
|
@@ -278,7 +278,9 @@ whose markup has rules, because the sheet's box is the step itself:
|
|
|
278
278
|
`.sheet__body` with what the member acts on. The handle and the head are
|
|
279
279
|
pinned; the body is the one thing that scrolls, to the card's own edges. The
|
|
280
280
|
handle is a line, or four dots (`mark="dots"`): both sit in the card's top
|
|
281
|
-
padding, the same distance from the edge, so the title stays put. `
|
|
281
|
+
padding, the same distance from the edge, so the title stays put. `refreshing`
|
|
282
|
+
(off unless the app sets it) changes the mark's colour while the app reloads
|
|
283
|
+
what the sheet shows, as a stack sheet's does; the sheet does not fetch. `paper` makes
|
|
282
284
|
the content white while the head keeps the sheet's colour (`tone`, as a card).
|
|
283
285
|
The same prop on a `StackSheet`, or on a `Card` in a stack: the head keeps the
|
|
284
286
|
tone, the body and the foot are white, and the gap under the head stays the tone.
|
package/css/sheet.css
CHANGED
|
@@ -231,6 +231,22 @@
|
|
|
231
231
|
background-size: var(--_dot) var(--_dot);
|
|
232
232
|
background-position: 0 0, var(--_step) 0, calc(2 * var(--_step)) 0, calc(3 * var(--_step)) 0;
|
|
233
233
|
}
|
|
234
|
+
/* the app reloads what the sheet shows (`refreshing`, off unless set): the mark changes colour exactly as a stack sheet's grip
|
|
235
|
+
does — white → black and back, so a light sheet and a dark one each get a moment it stands out. --_grip and the keyframes are
|
|
236
|
+
the stack's (stack.css): one sign for both. Nothing travels. */
|
|
237
|
+
.sheet.is-loading > .sheet__handle {
|
|
238
|
+
opacity: 1;
|
|
239
|
+
background-color: color-mix(in srgb, black calc(var(--_grip) * 100%), white);
|
|
240
|
+
animation: stack-grip-dissolve 0.4s ease-in-out infinite alternate;
|
|
241
|
+
}
|
|
242
|
+
.sheet.is-loading > .sheet__handle--dots {
|
|
243
|
+
--_ink: color-mix(in srgb, black calc(var(--_grip) * 100%), white);
|
|
244
|
+
background-color: transparent;
|
|
245
|
+
}
|
|
246
|
+
@media (prefers-reduced-motion: reduce) {
|
|
247
|
+
.sheet.is-loading > .sheet__handle { animation: none; background-color: currentColor; }
|
|
248
|
+
.sheet.is-loading > .sheet__handle--dots { --_ink: currentColor; background-color: transparent; }
|
|
249
|
+
}
|
|
234
250
|
.sheet__handle::before {
|
|
235
251
|
content: "";
|
|
236
252
|
position: absolute;
|
package/dist/cardds.css
CHANGED
|
@@ -1686,6 +1686,22 @@ button:enabled { cursor: pointer; } /* a disabled one keeps the arrow */
|
|
|
1686
1686
|
background-size: var(--_dot) var(--_dot);
|
|
1687
1687
|
background-position: 0 0, var(--_step) 0, calc(2 * var(--_step)) 0, calc(3 * var(--_step)) 0;
|
|
1688
1688
|
}
|
|
1689
|
+
/* the app reloads what the sheet shows (`refreshing`, off unless set): the mark changes colour exactly as a stack sheet's grip
|
|
1690
|
+
does — white → black and back, so a light sheet and a dark one each get a moment it stands out. --_grip and the keyframes are
|
|
1691
|
+
the stack's (stack.css): one sign for both. Nothing travels. */
|
|
1692
|
+
.sheet.is-loading > .sheet__handle {
|
|
1693
|
+
opacity: 1;
|
|
1694
|
+
background-color: color-mix(in srgb, black calc(var(--_grip) * 100%), white);
|
|
1695
|
+
animation: stack-grip-dissolve 0.4s ease-in-out infinite alternate;
|
|
1696
|
+
}
|
|
1697
|
+
.sheet.is-loading > .sheet__handle--dots {
|
|
1698
|
+
--_ink: color-mix(in srgb, black calc(var(--_grip) * 100%), white);
|
|
1699
|
+
background-color: transparent;
|
|
1700
|
+
}
|
|
1701
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1702
|
+
.sheet.is-loading > .sheet__handle { animation: none; background-color: currentColor; }
|
|
1703
|
+
.sheet.is-loading > .sheet__handle--dots { --_ink: currentColor; background-color: transparent; }
|
|
1704
|
+
}
|
|
1689
1705
|
.sheet__handle::before {
|
|
1690
1706
|
content: "";
|
|
1691
1707
|
position: absolute;
|
package/dist/sheets/Sheet.d.ts
CHANGED
|
@@ -23,6 +23,8 @@ export interface SheetProps extends Omit<ComponentProps<'article'>, 'onChange'>
|
|
|
23
23
|
handle?: boolean | string;
|
|
24
24
|
/** the grab mark. `line` (default) or `dots`: both sit in the card's top padding, the same distance from the edge, so the title does not move */
|
|
25
25
|
mark?: 'line' | 'dots';
|
|
26
|
+
/** the app is reloading what this sheet shows: while `true` the grab mark (line or dots) changes colour, as a stack sheet's does, and the sheet is `aria-busy`. Off unless the app sets it — the sheet does not fetch and has no pull to refresh of its own */
|
|
27
|
+
refreshing?: boolean;
|
|
26
28
|
/** the card tone slot, as `Card tone` — 2 and up add `card--N`. The head shows it; with `paper` the content does not */
|
|
27
29
|
tone?: 1 | 2 | 3 | 4 | 5;
|
|
28
30
|
/** the content is white paper and the head keeps the sheet's colour. The same prop on a `StackSheet` or a `Card` in a stack. Omit it and the content is the same colour as the head */
|
|
@@ -49,4 +51,4 @@ export interface SheetProps extends Omit<ComponentProps<'article'>, 'onChange'>
|
|
|
49
51
|
* crossing and never one continuous move, whatever the app's wiring (both states set in one render, or the next raised from the
|
|
50
52
|
* first's `onSettled`) — the app adds no timer.
|
|
51
53
|
*/
|
|
52
|
-
export declare function Sheet({ state, defaultState, onStateChange, onSettled, states, handle, mark, tone, paper, className, children, onFocus, ...rest }: SheetProps): import("react").JSX.Element;
|
|
54
|
+
export declare function Sheet({ state, defaultState, onStateChange, onSettled, states, handle, mark, refreshing, tone, paper, className, children, onFocus, ...rest }: SheetProps): import("react").JSX.Element;
|
package/dist/sheets/Sheet.js
CHANGED
|
@@ -38,7 +38,7 @@ function markLong(node, long) {
|
|
|
38
38
|
* crossing and never one continuous move, whatever the app's wiring (both states set in one render, or the next raised from the
|
|
39
39
|
* first's `onSettled`) — the app adds no timer.
|
|
40
40
|
*/
|
|
41
|
-
export function Sheet({ state, defaultState = 'half', onStateChange, onSettled, states, handle = true, mark = 'line', tone, paper, className, children, onFocus, ...rest }) {
|
|
41
|
+
export function Sheet({ state, defaultState = 'half', onStateChange, onSettled, states, handle = true, mark = 'line', refreshing, tone, paper, className, children, onFocus, ...rest }) {
|
|
42
42
|
const [current, request] = useControlled(state, defaultState, onStateChange);
|
|
43
43
|
const ref = useRef(null);
|
|
44
44
|
const handleRef = useRef(null);
|
|
@@ -131,5 +131,5 @@ export function Sheet({ state, defaultState = 'half', onStateChange, onSettled,
|
|
|
131
131
|
return; // the click that follows a drag is not a tap
|
|
132
132
|
request(current === 'peek' ? (allowed().includes(home.current) ? home.current : allowed().find((s) => s !== 'peek') ?? 'half') : 'peek', 'tap');
|
|
133
133
|
};
|
|
134
|
-
return (_jsxs("article", { ref: ref, className: cx('card sheet', tone && tone !== 1 && `card--${tone}`, paper && 'sheet--paper', `sheet--${shown}`, className), inert: current === 'away' || held || undefined, onFocus: focus, ...rest, children: [handle !== false && (_jsx("button", { ref: handleRef, className: cx('sheet__handle', mark === 'dots' && 'sheet__handle--dots'), type: "button", "aria-label": typeof handle === 'string' ? handle : word('resize'), onClick: tap, onPointerDown: down, onPointerMove: move, onPointerUp: up, onPointerCancel: up })), Children.map(children, (node) => markLong(node, titleLong))] }));
|
|
134
|
+
return (_jsxs("article", { ref: ref, className: cx('card sheet', tone && tone !== 1 && `card--${tone}`, paper && 'sheet--paper', `sheet--${shown}`, refreshing && 'is-loading', className), "aria-busy": refreshing || undefined, inert: current === 'away' || held || undefined, onFocus: focus, ...rest, children: [handle !== false && (_jsx("button", { ref: handleRef, className: cx('sheet__handle', mark === 'dots' && 'sheet__handle--dots'), type: "button", "aria-label": typeof handle === 'string' ? handle : word('resize'), onClick: tap, onPointerDown: down, onPointerMove: move, onPointerUp: up, onPointerCancel: up })), Children.map(children, (node) => markLong(node, titleLong))] }));
|
|
135
135
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usableapp/cardds",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.62",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "card-first mobile design system, React-first: the components in src/ are thin wrappers over the CSS contract (css/*.css stays the only truth); gallery/ shows every story live (npm run dev), tests/ measures the geometry.",
|