@usableapp/cardds 0.2.2 → 0.4.0
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/README.md +35 -107
- package/cardds.js +6 -449
- package/css/actions.css +41 -35
- package/css/base.css +9 -9
- package/css/card.css +26 -25
- package/css/choice.css +50 -50
- package/css/forms.css +18 -18
- package/css/journey.css +16 -16
- package/css/layover.css +45 -45
- package/css/lists.css +43 -43
- package/css/media.css +33 -33
- package/css/numbers.css +25 -25
- package/css/people.css +11 -11
- package/css/sheet.css +29 -29
- package/css/step.css +6 -6
- package/css/theme.template.css +6 -3
- package/css/tokens.css +2 -0
- package/dist/actions/Btn.d.ts +109 -108
- package/dist/actions/BtnRow.d.ts +2 -2
- package/dist/actions/Chip.d.ts +102 -101
- package/dist/actions/Dot.d.ts +2 -2
- package/dist/actions/Dropdown.d.ts +36 -19
- package/dist/actions/Dropdown.js +41 -11
- package/dist/actions/Fab.d.ts +2 -2
- package/dist/actions/IconBtn.d.ts +298 -10
- package/dist/actions/IconBtn.js +6 -8
- package/dist/actions/Link.d.ts +105 -104
- package/dist/actions/Segment.d.ts +3 -3
- package/dist/cardds.css +354 -345
- package/dist/cards/Card.d.ts +99 -98
- package/dist/cards/CardFoot.d.ts +2 -2
- package/dist/cards/CardHead.d.ts +2 -2
- package/dist/cards/CardParts.d.ts +7 -7
- package/dist/cards/Placeholder.d.ts +2 -2
- package/dist/cards/Stat.d.ts +7 -5
- package/dist/cards/Stat.js +2 -2
- package/dist/choice/Calendar.d.ts +17 -6
- package/dist/choice/Calendar.js +9 -3
- package/dist/choice/Check.d.ts +3 -3
- package/dist/choice/DayStrip.d.ts +3 -3
- package/dist/choice/Mood.d.ts +2 -2
- package/dist/choice/Slider.d.ts +3 -3
- package/dist/choice/Slider.js +12 -8
- package/dist/forms/AddRow.d.ts +2 -2
- package/dist/forms/Composer.d.ts +2 -2
- package/dist/forms/Field.d.ts +2 -2
- package/dist/forms/FileBtn.d.ts +2 -2
- package/dist/forms/Pin.d.ts +10 -7
- package/dist/forms/Pin.js +47 -18
- package/dist/journey/NoteRow.d.ts +2 -2
- package/dist/journey/Route.d.ts +2 -2
- package/dist/journey/TileBadge.d.ts +2 -2
- package/dist/layover/Banner.d.ts +2 -2
- package/dist/layover/Callout.d.ts +2 -2
- package/dist/layover/Deck.d.ts +3 -3
- package/dist/lists/Bubble.d.ts +3 -3
- package/dist/lists/Kv.d.ts +5 -5
- package/dist/lists/Legend.d.ts +3 -3
- package/dist/lists/Row.d.ts +5 -4
- package/dist/lists/Timeline.d.ts +3 -3
- package/dist/media/MapArea.d.ts +2 -2
- package/dist/media/Mosaic.d.ts +3 -3
- package/dist/media/Postcard.d.ts +9 -5
- package/dist/media/Postcard.js +8 -3
- package/dist/media/Quote.d.ts +2 -2
- package/dist/media/Tile.d.ts +5 -4
- package/dist/numbers/Badge.d.ts +2 -2
- package/dist/numbers/Band.d.ts +3 -3
- package/dist/numbers/Bars.d.ts +3 -3
- package/dist/numbers/DotGrid.d.ts +2 -2
- package/dist/numbers/Picker.d.ts +20 -8
- package/dist/numbers/Picker.js +51 -13
- package/dist/numbers/Ring.d.ts +2 -2
- package/dist/numbers/Track.d.ts +3 -3
- package/dist/people/Avatar.d.ts +100 -99
- package/dist/people/AvatarPick.d.ts +3 -3
- package/dist/scaffold/ActionBar.d.ts +3 -3
- package/dist/scaffold/AppBar.d.ts +2 -2
- package/dist/scaffold/BaseContent.d.ts +7 -7
- package/dist/scaffold/BaseContent.js +4 -4
- package/dist/scaffold/Centre.d.ts +3 -3
- package/dist/scaffold/EmptyState.d.ts +2 -2
- package/dist/scaffold/FilterRow.d.ts +2 -2
- package/dist/scaffold/FloatBar.d.ts +105 -104
- package/dist/scaffold/PagerAt.d.ts +2 -2
- package/dist/scaffold/Screen.d.ts +100 -99
- package/dist/scaffold/TopBar.d.ts +2 -2
- package/dist/sheets/CardBack.d.ts +2 -2
- package/dist/sheets/Drawer.d.ts +19 -8
- package/dist/sheets/Drawer.js +29 -5
- package/dist/sheets/Sheet.d.ts +29 -16
- package/dist/sheets/Sheet.js +157 -11
- package/dist/sheets/SheetBody.d.ts +2 -2
- package/dist/sheets/SheetHead.d.ts +2 -2
- package/dist/sheets/SheetStack.d.ts +15 -3
- package/dist/sheets/SheetStack.js +74 -2
- package/dist/sheets/SheetStage.d.ts +2 -2
- package/dist/sheets/Step.d.ts +2 -2
- package/dist/type/Icon.d.ts +22 -7
- package/dist/type/Icon.js +27 -4
- package/dist/type/Text.d.ts +7 -1
- package/dist/type/Text.js +2 -2
- package/package.json +3 -2
|
@@ -1,7 +1,14 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export interface SheetStackProps extends
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
export interface SheetStackProps extends ComponentProps<'div'> {
|
|
3
3
|
/** `tap` (default): a tapped head brings its sheet to the front, its back button returns it · `display`: the giant title is the peek (recents, a library) · `static`: peeks only, the last sheet open */
|
|
4
4
|
mode?: 'tap' | 'display' | 'static';
|
|
5
|
+
/** CONTROLLED (tap mode): which sheet is open — its index among the children, first = 0 — or `null` for none. The app owns it (a route, a
|
|
6
|
+
* button anywhere, the back button): pair it with `onOpenChange`, or the stack cannot move. */
|
|
7
|
+
open?: number | null;
|
|
8
|
+
/** UNCONTROLLED: the sheet open on arrival (default none); the stack then keeps its own */
|
|
9
|
+
defaultOpen?: number | null;
|
|
10
|
+
/** the stack ASKS: a peeked head was tapped (its index), or the open sheet's `CardBack` (`null`) */
|
|
11
|
+
onOpenChange?: (open: number | null) => void;
|
|
5
12
|
/** wider peeks so more of each title shows (display stacks) */
|
|
6
13
|
fanned?: boolean;
|
|
7
14
|
/** nothing open on arrival (tap mode): every sheet, the front one too, peeks at the stack's bottom; the room above is the base's (`base`). A tap opens any sheet over it */
|
|
@@ -17,5 +24,10 @@ export interface SheetStackProps extends ComponentPropsWithoutRef<'div'> {
|
|
|
17
24
|
* never the `heading` prop (it wraps the h2 in a div; the stack's one-line peek needs the bare h2). Put it last in a `Screen fill`, it bleeds
|
|
18
25
|
* off the bottom. `closed`: nothing open on arrival — every head peeks at the bottom and the base above shows `base` (a home screen
|
|
19
26
|
* with a picture over the menu); the `base` slot is rendered after the sheets, so it never takes a sheet's slot. This is the sheet STACK; a single bottom sheet is `Sheet`.
|
|
27
|
+
*
|
|
28
|
+
* A COMPONENT, not a wiring: WHICH sheet is open is the app's (`open` + `onOpenChange`, or `defaultOpen`) — so a button anywhere, a route or
|
|
29
|
+
* the phone's back button can open and close a section. Its own behaviour stays inside and only asks: a tap on a peeked head, the open
|
|
30
|
+
* sheet's CardBack. How the sheets MOVE is its own too: sheets are rigid — the tapped one slides up, the ones after it leave below, the ones
|
|
31
|
+
* before tuck under nearest-first; closing reverses in two beats. Only `translate` (stack.css); it sets classes, never a size.
|
|
20
32
|
*/
|
|
21
|
-
export declare function SheetStack({ mode, fanned, closed, base, className, children, ...rest }: SheetStackProps): import("react").JSX.Element;
|
|
33
|
+
export declare function SheetStack({ mode, open, defaultOpen, onOpenChange, fanned, closed, base, className, children, onClick, ...rest }: SheetStackProps): import("react").JSX.Element;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useLayoutEffect, useRef, useState } from 'react';
|
|
2
3
|
import { cx } from '../cx.js';
|
|
4
|
+
const PHASE = 380; // ms before the before-pack un-tucks on close, so the after-pack is clear first
|
|
5
|
+
/* the stack's sheets, in slot order: its direct children — or, where a host wraps each child in one box of its own, the first .card in
|
|
6
|
+
each. Never deeper: a card inside a sheet's content is content. The base is what shows behind the sheets, never a sheet. */
|
|
7
|
+
const sheetsOf = (stack) => [...stack.children]
|
|
8
|
+
.filter((c) => !c.classList.contains('sheet-stack__base'))
|
|
9
|
+
.map((c) => (c.classList.contains('card') ? c : c.querySelector(':scope > .card')))
|
|
10
|
+
.filter((c) => c instanceof HTMLElement);
|
|
3
11
|
/**
|
|
4
12
|
* SheetStack — the MENU: sheets stacked like paper at the middle of the home screen, every one a main section.
|
|
5
13
|
* Children are Cards, direct children only, at most five: first = the back of the stack, last = the front (open) sheet.
|
|
@@ -8,7 +16,71 @@ import { cx } from '../cx.js';
|
|
|
8
16
|
* never the `heading` prop (it wraps the h2 in a div; the stack's one-line peek needs the bare h2). Put it last in a `Screen fill`, it bleeds
|
|
9
17
|
* off the bottom. `closed`: nothing open on arrival — every head peeks at the bottom and the base above shows `base` (a home screen
|
|
10
18
|
* with a picture over the menu); the `base` slot is rendered after the sheets, so it never takes a sheet's slot. This is the sheet STACK; a single bottom sheet is `Sheet`.
|
|
19
|
+
*
|
|
20
|
+
* A COMPONENT, not a wiring: WHICH sheet is open is the app's (`open` + `onOpenChange`, or `defaultOpen`) — so a button anywhere, a route or
|
|
21
|
+
* the phone's back button can open and close a section. Its own behaviour stays inside and only asks: a tap on a peeked head, the open
|
|
22
|
+
* sheet's CardBack. How the sheets MOVE is its own too: sheets are rigid — the tapped one slides up, the ones after it leave below, the ones
|
|
23
|
+
* before tuck under nearest-first; closing reverses in two beats. Only `translate` (stack.css); it sets classes, never a size.
|
|
11
24
|
*/
|
|
12
|
-
export function SheetStack({ mode = 'tap', fanned, closed, base, className, children, ...rest }) {
|
|
13
|
-
|
|
25
|
+
export function SheetStack({ mode = 'tap', open, defaultOpen = null, onOpenChange, fanned, closed, base, className, children, onClick, ...rest }) {
|
|
26
|
+
const [inner, setInner] = useState(defaultOpen);
|
|
27
|
+
const current = open !== undefined ? open : inner;
|
|
28
|
+
const ref = useRef(null);
|
|
29
|
+
const was = useRef(null);
|
|
30
|
+
const untuck = useRef(null);
|
|
31
|
+
const request = (next) => {
|
|
32
|
+
if (next === current)
|
|
33
|
+
return;
|
|
34
|
+
if (open === undefined)
|
|
35
|
+
setInner(next);
|
|
36
|
+
onOpenChange?.(next);
|
|
37
|
+
};
|
|
38
|
+
/* paint the state onto the sheets — after every render, so a re-rendered Card never loses its place */
|
|
39
|
+
useLayoutEffect(() => {
|
|
40
|
+
const stack = ref.current;
|
|
41
|
+
if (!stack || mode !== 'tap')
|
|
42
|
+
return;
|
|
43
|
+
const sheets = sheetsOf(stack);
|
|
44
|
+
const prev = was.current;
|
|
45
|
+
was.current = current;
|
|
46
|
+
if (current != null) {
|
|
47
|
+
if (untuck.current) {
|
|
48
|
+
clearTimeout(untuck.current);
|
|
49
|
+
untuck.current = null;
|
|
50
|
+
}
|
|
51
|
+
sheets.forEach((c, i) => {
|
|
52
|
+
c.classList.toggle('is-open', i === current);
|
|
53
|
+
c.classList.toggle('is-before', i < current); // already behind it — tuck under the next strip and get covered…
|
|
54
|
+
c.classList.toggle('is-after', i > current); // in front of it — these leave below
|
|
55
|
+
c.style.setProperty('--stagger', String(i < current ? current - 1 - i : 0)); // …nearest one first
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (prev != null && prev !== current) {
|
|
60
|
+
// beat 1: the after-pack comes back in while the opened sheet drops into its slot, over the still-covered before-pack
|
|
61
|
+
sheets.forEach((c) => c.classList.remove('is-open', 'is-after'));
|
|
62
|
+
// beat 2: then the before-pack slides back up from behind it, the same order it tucked away
|
|
63
|
+
untuck.current = setTimeout(() => { untuck.current = null; if (ref.current)
|
|
64
|
+
sheetsOf(ref.current).forEach((c) => c.classList.remove('is-before')); }, PHASE);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (!untuck.current)
|
|
68
|
+
sheets.forEach((c) => c.classList.remove('is-open', 'is-before', 'is-after'));
|
|
69
|
+
});
|
|
70
|
+
const click = (e) => {
|
|
71
|
+
onClick?.(e);
|
|
72
|
+
const stack = ref.current;
|
|
73
|
+
if (!stack || mode !== 'tap')
|
|
74
|
+
return;
|
|
75
|
+
const target = e.target;
|
|
76
|
+
const sheets = sheetsOf(stack);
|
|
77
|
+
const at = sheets.findIndex((c) => c.contains(target)); // the sheet the tap landed in — not the nearest .card: a content card inside an open sheet must not count
|
|
78
|
+
if (target.closest('.card__back')) {
|
|
79
|
+
request(null);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (at >= 0 && current == null)
|
|
83
|
+
request(at);
|
|
84
|
+
};
|
|
85
|
+
return (_jsxs("div", { ref: ref, onClick: click, className: cx('sheet-stack', mode !== 'static' && `sheet-stack--${mode}`, fanned && 'sheet-stack--fanned', closed && 'sheet-stack--closed', className), ...rest, children: [children, base != null && _jsx("div", { className: "sheet-stack__base", children: base })] }));
|
|
14
86
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export interface SheetStageProps extends
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
export interface SheetStageProps extends ComponentProps<'div'> {
|
|
3
3
|
/** what sits behind the sheet: a map, previous cards, page copy */
|
|
4
4
|
bg?: ReactNode;
|
|
5
5
|
/** ONE thing shown in the band a half sheet leaves open (a postcard being made), centred there */
|
package/dist/sheets/Step.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export interface StepProps extends
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
export interface StepProps extends ComponentProps<'section'> {
|
|
3
3
|
}
|
|
4
4
|
/**
|
|
5
5
|
* Step — one screen, one task. Children: a BaseContent first (what the member READS — words on the base, not a card), an optional Sheet last
|
package/dist/type/Icon.d.ts
CHANGED
|
@@ -1,16 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { type IconName as StockIconName } from './icons.js';
|
|
3
|
+
/** an icon's name: one of the stock symbols (autocompleted) — or any name a project registered with `registerIcons` */
|
|
4
|
+
export type IconName = StockIconName | (string & {});
|
|
5
|
+
/**
|
|
6
|
+
* registerIcons — a project's OWN icons, by name: after this, `icon="map-pin"` works on every component that takes an icon (Icon, IconBtn,
|
|
7
|
+
* Field, MenuItem, Tile…), exactly like a stock one. Call it once at startup. A drawing is the INSIDE of the `<svg>` as a string (paths on a
|
|
8
|
+
* 24×24 box, drawn with the shared stroke), or `{ body, attrs }` to bring its own viewBox / fill. A registered name wins over a stock one —
|
|
9
|
+
* that is how a project swaps a symbol for its own. Returns nothing; safe to call again (later drawings replace earlier ones).
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerIcons(icons: Record<string, string | {
|
|
12
|
+
body: string;
|
|
13
|
+
attrs?: Record<string, string>;
|
|
14
|
+
}>): void;
|
|
15
|
+
export interface IconProps extends Omit<React.ComponentProps<'svg'>, 'children' | 'name'> {
|
|
16
|
+
/** a stock symbol (arrow-left, bell, check, chevron-down, id-card, plus, x, …) or a name the project registered (`registerIcons`). Omit it to draw with `children`. */
|
|
17
|
+
name?: IconName;
|
|
18
|
+
/** a ONE-OFF drawing: the svg's own children (`<path d="…" />`), on a 24×24 box with the shared stroke — for an icon not worth registering */
|
|
19
|
+
children?: ReactNode;
|
|
6
20
|
/** xs = 16px, inside captions, chips and links · sm = in a small icon button or a field (28px today — one size everywhere, tokens.css) · md (default) = the 28px icon · lg = 32px, empty states */
|
|
7
21
|
size?: 'xs' | 'sm' | 'md' | 'lg';
|
|
8
22
|
/** an accessible name makes the icon meaningful (role="img"); without one it is decorative and hidden from assistive tech */
|
|
9
23
|
label?: string;
|
|
10
24
|
}
|
|
11
25
|
/**
|
|
12
|
-
* Icon — a
|
|
26
|
+
* Icon — a stroke icon, inlined (no sprite file at runtime): one of the stock Lucide symbols, one of the project's OWN (`registerIcons`), or a
|
|
27
|
+
* one-off drawn with `children`. The set is open — a project never comes to cardds for an icon.
|
|
13
28
|
* Sizes are the tokens the CSS defines: `.icon` 28px, `--sm` 28px (a semantic size, same as md today), `--xs` 16px, `--lg` 32px.
|
|
14
29
|
* Keep it big: inside a button or a row the default 28px icon is the norm; xs only sits in text.
|
|
15
30
|
*/
|
|
16
|
-
export declare function Icon({ name, size, label, className, ...rest }: IconProps): import("react").JSX.Element;
|
|
31
|
+
export declare function Icon({ name, children, size, label, className, ...rest }: IconProps): import("react").JSX.Element;
|
package/dist/type/Icon.js
CHANGED
|
@@ -1,12 +1,35 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cx } from '../cx.js';
|
|
3
3
|
import { ICONS } from './icons.js';
|
|
4
|
+
/* the stroke style every stock symbol shares (Lucide): a project's drawing takes it unless it brings its own attrs */
|
|
5
|
+
const STROKE = { viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round' };
|
|
6
|
+
const OWN = new Map();
|
|
4
7
|
/**
|
|
5
|
-
*
|
|
8
|
+
* registerIcons — a project's OWN icons, by name: after this, `icon="map-pin"` works on every component that takes an icon (Icon, IconBtn,
|
|
9
|
+
* Field, MenuItem, Tile…), exactly like a stock one. Call it once at startup. A drawing is the INSIDE of the `<svg>` as a string (paths on a
|
|
10
|
+
* 24×24 box, drawn with the shared stroke), or `{ body, attrs }` to bring its own viewBox / fill. A registered name wins over a stock one —
|
|
11
|
+
* that is how a project swaps a symbol for its own. Returns nothing; safe to call again (later drawings replace earlier ones).
|
|
12
|
+
*/
|
|
13
|
+
export function registerIcons(icons) {
|
|
14
|
+
for (const [name, d] of Object.entries(icons))
|
|
15
|
+
OWN.set(name, typeof d === 'string' ? { attrs: STROKE, body: d } : { attrs: { ...STROKE, ...d.attrs }, body: d.body });
|
|
16
|
+
}
|
|
17
|
+
const warned = new Set();
|
|
18
|
+
/**
|
|
19
|
+
* Icon — a stroke icon, inlined (no sprite file at runtime): one of the stock Lucide symbols, one of the project's OWN (`registerIcons`), or a
|
|
20
|
+
* one-off drawn with `children`. The set is open — a project never comes to cardds for an icon.
|
|
6
21
|
* Sizes are the tokens the CSS defines: `.icon` 28px, `--sm` 28px (a semantic size, same as md today), `--xs` 16px, `--lg` 32px.
|
|
7
22
|
* Keep it big: inside a button or a row the default 28px icon is the norm; xs only sits in text.
|
|
8
23
|
*/
|
|
9
|
-
export function Icon({ name, size = 'md', label, className, ...rest }) {
|
|
10
|
-
const icon = ICONS[name];
|
|
11
|
-
|
|
24
|
+
export function Icon({ name, children, size = 'md', label, className, ...rest }) {
|
|
25
|
+
const icon = name === undefined ? undefined : OWN.get(name) ?? ICONS[name];
|
|
26
|
+
if (name !== undefined && !icon && !warned.has(name)) {
|
|
27
|
+
warned.add(name);
|
|
28
|
+
console.warn(`cardds Icon: no icon named "${name}" — a stock name is misspelt, or the project has not registered it (registerIcons)`);
|
|
29
|
+
}
|
|
30
|
+
const shared = { className: cx('icon', size !== 'md' && `icon--${size}`, className), role: label ? 'img' : undefined, 'aria-label': label, 'aria-hidden': label ? undefined : true };
|
|
31
|
+
// an unknown name draws nothing but keeps its box — a missing icon never takes a screen down
|
|
32
|
+
if (!icon)
|
|
33
|
+
return _jsx("svg", { ...STROKE, ...shared, ...rest, children: children });
|
|
34
|
+
return _jsx("svg", { ...icon.attrs, ...shared, dangerouslySetInnerHTML: { __html: icon.body }, ...rest });
|
|
12
35
|
}
|
package/dist/type/Text.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export type TextLevel = 'display' | 'h1' | 'h2' | 'title' | 'body' | 'label' | 'caption' | 'overline' | 'stat';
|
|
2
2
|
export interface TextProps extends React.HTMLAttributes<HTMLElement> {
|
|
3
|
+
/** the element it renders (React 19 passes `ref` as a prop) */
|
|
4
|
+
ref?: React.Ref<HTMLElement>;
|
|
3
5
|
/** the type level: display (hero words) · h1 · h2 (a card's heading) · title · body · label · caption · overline (small caps above a heading) · stat (a big number) */
|
|
4
6
|
level: TextLevel;
|
|
5
7
|
/** stat only: the one giant number on a sheet (`.t-stat--xl`) */
|
|
@@ -8,6 +10,8 @@ export interface TextProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
8
10
|
mono?: boolean;
|
|
9
11
|
/** muted ink — follows the card it sits in */
|
|
10
12
|
muted?: boolean;
|
|
13
|
+
/** takes the remaining room of a row (a heading beside a chip in a flex head) */
|
|
14
|
+
grow?: boolean;
|
|
11
15
|
/** uppercase */
|
|
12
16
|
caps?: boolean;
|
|
13
17
|
/** the element; defaults per level (h2 for display/h1/h2, p for title/body/stat, span for the rest) */
|
|
@@ -18,7 +22,9 @@ export interface TextProps extends React.HTMLAttributes<HTMLElement> {
|
|
|
18
22
|
* Headings inside a card head are h2 by default; a screen title in a TopBar is h1.
|
|
19
23
|
* Everything scales from the root font-size, so there are no pixel sizes to pick.
|
|
20
24
|
*/
|
|
21
|
-
export declare function Text({ level, xl, mono, muted, caps, as, className, ...rest }: TextProps): import("react").DetailedReactHTMLElement<{
|
|
25
|
+
export declare function Text({ level, xl, mono, muted, caps, grow, as, className, ...rest }: TextProps): import("react").DetailedReactHTMLElement<{
|
|
26
|
+
/** the element it renders (React 19 passes `ref` as a prop) */
|
|
27
|
+
ref?: React.Ref<HTMLElement>;
|
|
22
28
|
defaultChecked?: boolean | undefined;
|
|
23
29
|
defaultValue?: string | number | readonly string[] | undefined;
|
|
24
30
|
suppressContentEditableWarning?: boolean | undefined;
|
package/dist/type/Text.js
CHANGED
|
@@ -8,9 +8,9 @@ const DEFAULT_AS = {
|
|
|
8
8
|
* Headings inside a card head are h2 by default; a screen title in a TopBar is h1.
|
|
9
9
|
* Everything scales from the root font-size, so there are no pixel sizes to pick.
|
|
10
10
|
*/
|
|
11
|
-
export function Text({ level, xl, mono, muted, caps, as, className, ...rest }) {
|
|
11
|
+
export function Text({ level, xl, mono, muted, caps, grow, as, className, ...rest }) {
|
|
12
12
|
return createElement(as ?? DEFAULT_AS[level] ?? 'span', {
|
|
13
|
-
className: cx(`t-${level}`, level === 'stat' && xl && 't-stat--xl', level === 'stat' && mono && 't-stat--mono', muted && 't-muted', caps && 't-caps', className),
|
|
13
|
+
className: cx(`t-${level}`, level === 'stat' && xl && 't-stat--xl', level === 'stat' && mono && 't-stat--mono', muted && 't-muted', caps && 't-caps', grow && 'grow', className),
|
|
14
14
|
...rest,
|
|
15
15
|
});
|
|
16
16
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@usableapp/cardds",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
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.",
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"build": "node scripts/build-icons.mjs && tsc -p tsconfig.json && node scripts/flatten-css.mjs",
|
|
14
14
|
"test": "playwright test",
|
|
15
15
|
"validate:inbox": "node scripts/validate-inbox.mjs",
|
|
16
|
-
"prepack": "npm run build"
|
|
16
|
+
"prepack": "npm run build",
|
|
17
|
+
"knobs": "node scripts/knobs.mjs"
|
|
17
18
|
},
|
|
18
19
|
"devDependencies": {
|
|
19
20
|
"@playwright/test": "1.58.2",
|