@usableapp/cardds 0.3.0 → 0.4.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/README.md +12 -8
- package/css/actions.css +38 -27
- package/css/base.css +9 -9
- package/css/card.css +24 -23
- package/css/choice.css +50 -50
- package/css/forms.css +18 -18
- package/css/journey.css +16 -16
- package/css/layover.css +57 -60
- package/css/lists.css +52 -43
- package/css/media.css +96 -60
- package/css/numbers.css +41 -25
- package/css/people.css +11 -11
- package/css/sheet.css +28 -24
- package/css/stack.css +3 -3
- package/css/theme.template.css +6 -3
- 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 +4 -4
- package/dist/actions/Fab.d.ts +2 -2
- package/dist/actions/IconBtn.d.ts +107 -106
- package/dist/actions/Link.d.ts +105 -104
- package/dist/actions/Segment.d.ts +3 -3
- package/dist/cardds.css +443 -369
- 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 +2 -2
- 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 +2 -2
- 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 +2 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- 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 +14 -285
- package/dist/lists/Row.js +10 -3
- 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 +17 -7
- package/dist/media/Postcard.js +8 -5
- 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 +3 -3
- package/dist/numbers/Progress.d.ts +9 -0
- package/dist/numbers/Progress.js +7 -0
- 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 +3 -3
- 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/Drawer.d.ts +7 -7
- package/dist/sheets/Drawer.js +1 -1
- package/dist/sheets/Sheet.d.ts +3 -5
- package/dist/sheets/Sheet.js +2 -2
- package/dist/sheets/SheetBody.d.ts +2 -2
- package/dist/sheets/SheetHead.d.ts +2 -2
- package/dist/sheets/SheetStack.d.ts +5 -5
- package/dist/sheets/SheetStack.js +3 -3
- package/dist/sheets/SheetStage.d.ts +5 -7
- package/dist/sheets/SheetStage.js +3 -3
- package/dist/sheets/StackBack.d.ts +7 -0
- package/dist/sheets/StackBack.js +7 -0
- 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
- package/dist/sheets/CardBack.d.ts +0 -7
- package/dist/sheets/CardBack.js +0 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type ComponentProps } from 'react';
|
|
2
2
|
export type Palette = 'clay' | 'shine' | 'field' | 'roast' | 'hydro';
|
|
3
|
-
export interface ScreenProps extends
|
|
3
|
+
export interface ScreenProps extends ComponentProps<'div'> {
|
|
4
4
|
/** exactly one phone height (100dvh), clipped: the box a Step or a SheetStack fills — an app screen, not a scrolling page */
|
|
5
5
|
fill?: boolean;
|
|
6
6
|
/** a colour preset from palette.css; omit for the black-and-white wireframe */
|
|
@@ -14,74 +14,119 @@ export interface ScreenProps extends ComponentPropsWithoutRef<'div'> {
|
|
|
14
14
|
* Put an AppBar/TopBar first, the content next, and an ActionBar AFTER the screen (outside it).
|
|
15
15
|
*/
|
|
16
16
|
export declare function Screen({ fill, palette, as, className, ...rest }: ScreenProps): import("react").DetailedReactHTMLElement<{
|
|
17
|
-
|
|
17
|
+
ref?: import("react").Ref<HTMLDivElement> | undefined;
|
|
18
|
+
key?: import("react").Key | null | undefined;
|
|
19
|
+
defaultChecked?: boolean | undefined;
|
|
20
|
+
defaultValue?: string | number | readonly string[] | undefined;
|
|
21
|
+
suppressContentEditableWarning?: boolean | undefined;
|
|
22
|
+
suppressHydrationWarning?: boolean | undefined;
|
|
23
|
+
accessKey?: string | undefined;
|
|
24
|
+
autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | (string & {});
|
|
25
|
+
autoFocus?: boolean | undefined;
|
|
26
|
+
contentEditable?: (boolean | "true" | "false") | "inherit" | "plaintext-only" | undefined;
|
|
27
|
+
contextMenu?: string | undefined;
|
|
28
|
+
dir?: string | undefined;
|
|
29
|
+
draggable?: (boolean | "true" | "false") | undefined;
|
|
30
|
+
enterKeyHint?: "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | undefined;
|
|
31
|
+
hidden?: boolean | undefined;
|
|
32
|
+
id?: string | undefined;
|
|
33
|
+
lang?: string | undefined;
|
|
34
|
+
nonce?: string | undefined;
|
|
35
|
+
slot?: string | undefined;
|
|
36
|
+
spellCheck?: (boolean | "true" | "false") | undefined;
|
|
18
37
|
style?: import("react").CSSProperties | undefined;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
lang?: string | undefined | undefined;
|
|
24
|
-
nonce?: string | undefined | undefined;
|
|
25
|
-
part?: string | undefined | undefined;
|
|
38
|
+
tabIndex?: number | undefined;
|
|
39
|
+
title?: string | undefined;
|
|
40
|
+
translate?: "yes" | "no" | undefined;
|
|
41
|
+
radioGroup?: string | undefined;
|
|
26
42
|
role?: import("react").AriaRole | undefined;
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
about?: string | undefined;
|
|
44
|
+
content?: string | undefined;
|
|
45
|
+
datatype?: string | undefined;
|
|
46
|
+
inlist?: any;
|
|
47
|
+
prefix?: string | undefined;
|
|
48
|
+
property?: string | undefined;
|
|
49
|
+
rel?: string | undefined;
|
|
50
|
+
resource?: string | undefined;
|
|
51
|
+
rev?: string | undefined;
|
|
52
|
+
typeof?: string | undefined;
|
|
53
|
+
vocab?: string | undefined;
|
|
54
|
+
autoCorrect?: string | undefined;
|
|
55
|
+
autoSave?: string | undefined;
|
|
56
|
+
color?: string | undefined;
|
|
57
|
+
itemProp?: string | undefined;
|
|
58
|
+
itemScope?: boolean | undefined;
|
|
59
|
+
itemType?: string | undefined;
|
|
60
|
+
itemID?: string | undefined;
|
|
61
|
+
itemRef?: string | undefined;
|
|
62
|
+
results?: number | undefined;
|
|
63
|
+
security?: string | undefined;
|
|
64
|
+
unselectable?: "on" | "off" | undefined;
|
|
65
|
+
popover?: "" | "auto" | "manual" | "hint" | undefined;
|
|
66
|
+
popoverTargetAction?: "toggle" | "show" | "hide" | undefined;
|
|
67
|
+
popoverTarget?: string | undefined;
|
|
68
|
+
inert?: boolean | undefined;
|
|
69
|
+
inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined;
|
|
70
|
+
is?: string | undefined;
|
|
71
|
+
exportparts?: string | undefined;
|
|
72
|
+
part?: string | undefined;
|
|
73
|
+
"aria-activedescendant"?: string | undefined;
|
|
29
74
|
"aria-atomic"?: (boolean | "true" | "false") | undefined;
|
|
30
|
-
"aria-autocomplete"?: "none" | "inline" | "list" | "both" | undefined
|
|
31
|
-
"aria-braillelabel"?: string | undefined
|
|
32
|
-
"aria-brailleroledescription"?: string | undefined
|
|
75
|
+
"aria-autocomplete"?: "none" | "inline" | "list" | "both" | undefined;
|
|
76
|
+
"aria-braillelabel"?: string | undefined;
|
|
77
|
+
"aria-brailleroledescription"?: string | undefined;
|
|
33
78
|
"aria-busy"?: (boolean | "true" | "false") | undefined;
|
|
34
|
-
"aria-checked"?: boolean | "false" | "mixed" | "true" | undefined
|
|
35
|
-
"aria-colcount"?: number | undefined
|
|
36
|
-
"aria-colindex"?: number | undefined
|
|
37
|
-
"aria-colindextext"?: string | undefined
|
|
38
|
-
"aria-colspan"?: number | undefined
|
|
39
|
-
"aria-controls"?: string | undefined
|
|
40
|
-
"aria-current"?: boolean | "false" | "true" | "page" | "step" | "location" | "date" | "time" | undefined
|
|
41
|
-
"aria-describedby"?: string | undefined
|
|
42
|
-
"aria-description"?: string | undefined
|
|
43
|
-
"aria-details"?: string | undefined
|
|
79
|
+
"aria-checked"?: boolean | "false" | "mixed" | "true" | undefined;
|
|
80
|
+
"aria-colcount"?: number | undefined;
|
|
81
|
+
"aria-colindex"?: number | undefined;
|
|
82
|
+
"aria-colindextext"?: string | undefined;
|
|
83
|
+
"aria-colspan"?: number | undefined;
|
|
84
|
+
"aria-controls"?: string | undefined;
|
|
85
|
+
"aria-current"?: boolean | "false" | "true" | "page" | "step" | "location" | "date" | "time" | undefined;
|
|
86
|
+
"aria-describedby"?: string | undefined;
|
|
87
|
+
"aria-description"?: string | undefined;
|
|
88
|
+
"aria-details"?: string | undefined;
|
|
44
89
|
"aria-disabled"?: (boolean | "true" | "false") | undefined;
|
|
45
|
-
"aria-dropeffect"?: "none" | "copy" | "execute" | "link" | "move" | "popup" | undefined
|
|
46
|
-
"aria-errormessage"?: string | undefined
|
|
90
|
+
"aria-dropeffect"?: "none" | "copy" | "execute" | "link" | "move" | "popup" | undefined;
|
|
91
|
+
"aria-errormessage"?: string | undefined;
|
|
47
92
|
"aria-expanded"?: (boolean | "true" | "false") | undefined;
|
|
48
|
-
"aria-flowto"?: string | undefined
|
|
93
|
+
"aria-flowto"?: string | undefined;
|
|
49
94
|
"aria-grabbed"?: (boolean | "true" | "false") | undefined;
|
|
50
|
-
"aria-haspopup"?: boolean | "false" | "true" | "menu" | "listbox" | "tree" | "grid" | "dialog" | undefined
|
|
95
|
+
"aria-haspopup"?: boolean | "false" | "true" | "menu" | "listbox" | "tree" | "grid" | "dialog" | undefined;
|
|
51
96
|
"aria-hidden"?: (boolean | "true" | "false") | undefined;
|
|
52
|
-
"aria-invalid"?: boolean | "false" | "true" | "grammar" | "spelling" | undefined
|
|
53
|
-
"aria-keyshortcuts"?: string | undefined
|
|
54
|
-
"aria-label"?: string | undefined
|
|
55
|
-
"aria-labelledby"?: string | undefined
|
|
56
|
-
"aria-level"?: number | undefined
|
|
57
|
-
"aria-live"?: "off" | "assertive" | "polite" | undefined
|
|
97
|
+
"aria-invalid"?: boolean | "false" | "true" | "grammar" | "spelling" | undefined;
|
|
98
|
+
"aria-keyshortcuts"?: string | undefined;
|
|
99
|
+
"aria-label"?: string | undefined;
|
|
100
|
+
"aria-labelledby"?: string | undefined;
|
|
101
|
+
"aria-level"?: number | undefined;
|
|
102
|
+
"aria-live"?: "off" | "assertive" | "polite" | undefined;
|
|
58
103
|
"aria-modal"?: (boolean | "true" | "false") | undefined;
|
|
59
104
|
"aria-multiline"?: (boolean | "true" | "false") | undefined;
|
|
60
105
|
"aria-multiselectable"?: (boolean | "true" | "false") | undefined;
|
|
61
|
-
"aria-orientation"?: "horizontal" | "vertical" | undefined
|
|
62
|
-
"aria-owns"?: string | undefined
|
|
63
|
-
"aria-placeholder"?: string | undefined
|
|
64
|
-
"aria-posinset"?: number | undefined
|
|
65
|
-
"aria-pressed"?: boolean | "false" | "mixed" | "true" | undefined
|
|
106
|
+
"aria-orientation"?: "horizontal" | "vertical" | undefined;
|
|
107
|
+
"aria-owns"?: string | undefined;
|
|
108
|
+
"aria-placeholder"?: string | undefined;
|
|
109
|
+
"aria-posinset"?: number | undefined;
|
|
110
|
+
"aria-pressed"?: boolean | "false" | "mixed" | "true" | undefined;
|
|
66
111
|
"aria-readonly"?: (boolean | "true" | "false") | undefined;
|
|
67
|
-
"aria-relevant"?: "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined
|
|
112
|
+
"aria-relevant"?: "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text" | "text additions" | "text removals" | undefined;
|
|
68
113
|
"aria-required"?: (boolean | "true" | "false") | undefined;
|
|
69
|
-
"aria-roledescription"?: string | undefined
|
|
70
|
-
"aria-rowcount"?: number | undefined
|
|
71
|
-
"aria-rowindex"?: number | undefined
|
|
72
|
-
"aria-rowindextext"?: string | undefined
|
|
73
|
-
"aria-rowspan"?: number | undefined
|
|
114
|
+
"aria-roledescription"?: string | undefined;
|
|
115
|
+
"aria-rowcount"?: number | undefined;
|
|
116
|
+
"aria-rowindex"?: number | undefined;
|
|
117
|
+
"aria-rowindextext"?: string | undefined;
|
|
118
|
+
"aria-rowspan"?: number | undefined;
|
|
74
119
|
"aria-selected"?: (boolean | "true" | "false") | undefined;
|
|
75
|
-
"aria-setsize"?: number | undefined
|
|
76
|
-
"aria-sort"?: "none" | "ascending" | "descending" | "other" | undefined
|
|
77
|
-
"aria-valuemax"?: number | undefined
|
|
78
|
-
"aria-valuemin"?: number | undefined
|
|
79
|
-
"aria-valuenow"?: number | undefined
|
|
80
|
-
"aria-valuetext"?: string | undefined
|
|
81
|
-
children?: import("react").ReactNode;
|
|
120
|
+
"aria-setsize"?: number | undefined;
|
|
121
|
+
"aria-sort"?: "none" | "ascending" | "descending" | "other" | undefined;
|
|
122
|
+
"aria-valuemax"?: number | undefined;
|
|
123
|
+
"aria-valuemin"?: number | undefined;
|
|
124
|
+
"aria-valuenow"?: number | undefined;
|
|
125
|
+
"aria-valuetext"?: string | undefined;
|
|
126
|
+
children?: import("react").ReactNode | undefined;
|
|
82
127
|
dangerouslySetInnerHTML?: {
|
|
83
128
|
__html: string | TrustedHTML;
|
|
84
|
-
} | undefined
|
|
129
|
+
} | undefined;
|
|
85
130
|
onCopy?: import("react").ClipboardEventHandler<HTMLDivElement> | undefined;
|
|
86
131
|
onCopyCapture?: import("react").ClipboardEventHandler<HTMLDivElement> | undefined;
|
|
87
132
|
onCut?: import("react").ClipboardEventHandler<HTMLDivElement> | undefined;
|
|
@@ -250,50 +295,6 @@ export declare function Screen({ fill, palette, as, className, ...rest }: Screen
|
|
|
250
295
|
onTransitionRunCapture?: import("react").TransitionEventHandler<HTMLDivElement> | undefined;
|
|
251
296
|
onTransitionStart?: import("react").TransitionEventHandler<HTMLDivElement> | undefined;
|
|
252
297
|
onTransitionStartCapture?: import("react").TransitionEventHandler<HTMLDivElement> | undefined;
|
|
253
|
-
key?: import("react").Key | null | undefined;
|
|
254
|
-
defaultChecked?: boolean | undefined | undefined;
|
|
255
|
-
defaultValue?: string | number | readonly string[] | undefined;
|
|
256
|
-
suppressContentEditableWarning?: boolean | undefined | undefined;
|
|
257
|
-
accessKey?: string | undefined | undefined;
|
|
258
|
-
autoCapitalize?: "off" | "none" | "on" | "sentences" | "words" | "characters" | undefined | (string & {}) | undefined;
|
|
259
|
-
autoFocus?: boolean | undefined | undefined;
|
|
260
|
-
contentEditable?: (boolean | "true" | "false") | "inherit" | "plaintext-only" | undefined;
|
|
261
|
-
contextMenu?: string | undefined | undefined;
|
|
262
|
-
dir?: string | undefined | undefined;
|
|
263
|
-
draggable?: (boolean | "true" | "false") | undefined;
|
|
264
|
-
enterKeyHint?: "enter" | "done" | "go" | "next" | "previous" | "search" | "send" | undefined | undefined;
|
|
265
|
-
hidden?: boolean | undefined | undefined;
|
|
266
|
-
spellCheck?: (boolean | "true" | "false") | undefined;
|
|
267
|
-
translate?: "yes" | "no" | undefined | undefined;
|
|
268
|
-
radioGroup?: string | undefined | undefined;
|
|
269
|
-
about?: string | undefined | undefined;
|
|
270
|
-
content?: string | undefined | undefined;
|
|
271
|
-
datatype?: string | undefined | undefined;
|
|
272
|
-
inlist?: any;
|
|
273
|
-
prefix?: string | undefined | undefined;
|
|
274
|
-
property?: string | undefined | undefined;
|
|
275
|
-
rel?: string | undefined | undefined;
|
|
276
|
-
resource?: string | undefined | undefined;
|
|
277
|
-
rev?: string | undefined | undefined;
|
|
278
|
-
typeof?: string | undefined | undefined;
|
|
279
|
-
vocab?: string | undefined | undefined;
|
|
280
|
-
autoCorrect?: string | undefined | undefined;
|
|
281
|
-
autoSave?: string | undefined | undefined;
|
|
282
|
-
itemProp?: string | undefined | undefined;
|
|
283
|
-
itemScope?: boolean | undefined | undefined;
|
|
284
|
-
itemType?: string | undefined | undefined;
|
|
285
|
-
itemID?: string | undefined | undefined;
|
|
286
|
-
itemRef?: string | undefined | undefined;
|
|
287
|
-
results?: number | undefined | undefined;
|
|
288
|
-
security?: string | undefined | undefined;
|
|
289
|
-
unselectable?: "on" | "off" | undefined | undefined;
|
|
290
|
-
popover?: "" | "auto" | "manual" | "hint" | undefined | undefined;
|
|
291
|
-
popoverTargetAction?: "toggle" | "show" | "hide" | undefined | undefined;
|
|
292
|
-
popoverTarget?: string | undefined | undefined;
|
|
293
|
-
inert?: boolean | undefined | undefined;
|
|
294
|
-
inputMode?: "none" | "text" | "tel" | "url" | "email" | "numeric" | "decimal" | "search" | undefined | undefined;
|
|
295
|
-
is?: string | undefined | undefined;
|
|
296
|
-
exportparts?: string | undefined | undefined;
|
|
297
298
|
className: string;
|
|
298
299
|
'data-palette': Palette | undefined;
|
|
299
|
-
},
|
|
300
|
+
}, HTMLDivElement>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export interface TopBarProps extends Omit<
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
export interface TopBarProps extends Omit<ComponentProps<'header'>, 'title'> {
|
|
3
3
|
/** the screen title (uppercase, ellipsised on one line) */
|
|
4
4
|
title: ReactNode;
|
|
5
5
|
/** a leading control — usually `<IconBtn sm icon="arrow-left" label="Back" />` */
|
package/dist/sheets/Drawer.d.ts
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
export interface ModalProps extends
|
|
1
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
2
|
+
export interface ModalProps extends ComponentProps<'article'> {
|
|
3
3
|
/** CONTROLLED: on the screen or not (default `true`). The app owns it. Set it `false` and the modal leaves the way it came — its
|
|
4
|
-
* opening played backwards — then calls `onClosed`, where the app stops rendering it (and its `SheetStage
|
|
4
|
+
* opening played backwards — then calls `onClosed`, where the app stops rendering it (and its `SheetStage dim`). */
|
|
5
5
|
open?: boolean;
|
|
6
6
|
/** the leaving has finished (at once, when motion is reduced) — unmount here */
|
|
7
7
|
onClosed?: () => void;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* Modal — the ask: ONE card at the centre of a `SheetStage
|
|
10
|
+
* Modal — the ask: ONE card at the centre of a `SheetStage dim`, two parts — a `Lift` (the thing being asked about, light, scrolls
|
|
11
11
|
* when tall) and a `Drawer` (the dark end that asks). No border. Two beats on appearing: drops in from above, then the drawer comes
|
|
12
12
|
* out below while the lift moves up.
|
|
13
13
|
* A COMPONENT, not a wiring: it does not know its buttons. They are plain `IconBtn`s / `Btn`s with the app's `onClick` — the app
|
|
14
14
|
* records the answer and sets `open={false}`; the modal's one behaviour is how it leaves.
|
|
15
15
|
*/
|
|
16
16
|
export declare function Modal({ open, onClosed, className, ...rest }: ModalProps): import("react").JSX.Element;
|
|
17
|
-
export interface LiftProps extends
|
|
17
|
+
export interface LiftProps extends ComponentProps<'div'> {
|
|
18
18
|
}
|
|
19
19
|
/** Lift — the light part of a `Modal`: the case, request or item the question is about (a CardHead, rows, a timeline); scrolls inside when tall. */
|
|
20
20
|
export declare function Lift({ className, ...rest }: LiftProps): import("react").JSX.Element;
|
|
21
|
-
export interface DrawerProps extends Omit<
|
|
21
|
+
export interface DrawerProps extends Omit<ComponentProps<'div'>, 'title'> {
|
|
22
22
|
/** the question */
|
|
23
23
|
title: ReactNode;
|
|
24
24
|
/** the fine print under it */
|
|
@@ -26,7 +26,7 @@ export interface DrawerProps extends Omit<ComponentPropsWithoutRef<'div'>, 'titl
|
|
|
26
26
|
}
|
|
27
27
|
/** Drawer — the dark end of a `Modal`: the question, its fine print, and a `BtnTrio` (or two buttons) — plain buttons with the app's `onClick`; the Drawer does nothing with them. */
|
|
28
28
|
export declare function Drawer({ title, caption, className, children, ...rest }: DrawerProps): import("react").JSX.Element;
|
|
29
|
-
export interface BtnTrioProps extends
|
|
29
|
+
export interface BtnTrioProps extends ComponentProps<'div'> {
|
|
30
30
|
}
|
|
31
31
|
/** BtnTrio — three round buttons with dotted connectors between them (× · ? · ✓); the middle one inverted. */
|
|
32
32
|
export declare function BtnTrio({ className, children, ...rest }: BtnTrioProps): import("react").JSX.Element;
|
package/dist/sheets/Drawer.js
CHANGED
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Children, Fragment, useEffect, useRef } from 'react';
|
|
3
3
|
import { cx } from '../cx.js';
|
|
4
4
|
/**
|
|
5
|
-
* Modal — the ask: ONE card at the centre of a `SheetStage
|
|
5
|
+
* Modal — the ask: ONE card at the centre of a `SheetStage dim`, two parts — a `Lift` (the thing being asked about, light, scrolls
|
|
6
6
|
* when tall) and a `Drawer` (the dark end that asks). No border. Two beats on appearing: drops in from above, then the drawer comes
|
|
7
7
|
* out below while the lift moves up.
|
|
8
8
|
* A COMPONENT, not a wiring: it does not know its buttons. They are plain `IconBtn`s / `Btn`s with the app's `onClick` — the app
|
package/dist/sheets/Sheet.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
2
|
/** how far the sheet slid. `away` = not on the screen (slid out, inert) — a state the app sets, never one a drag or a tap lands on */
|
|
3
3
|
export type SheetState = 'peek' | 'half' | '3q' | 'full' | 'away';
|
|
4
4
|
/** what asked for the change: the handle's `tap`, a `drag` released, `focus` in a peeked sheet, the `keyboard` (or anything else) moving the cut */
|
|
5
5
|
export type SheetChangeReason = 'tap' | 'drag' | 'focus' | 'keyboard';
|
|
6
6
|
declare const ORDER: readonly ["peek", "half", "3q", "full"];
|
|
7
7
|
type Resting = (typeof ORDER)[number];
|
|
8
|
-
export interface SheetProps extends Omit<
|
|
8
|
+
export interface SheetProps extends Omit<ComponentProps<'article'>, 'onChange'> {
|
|
9
9
|
/** CONTROLLED: where the sheet is. The app owns it — pair it with `onStateChange`, or the sheet cannot move (like `value` without `onChange`).
|
|
10
10
|
* `peek` (handle + title row) · `half` · `3q` · `full` (its top edge at the top bar) · `away` (not on the screen). A class, never a height. */
|
|
11
11
|
state?: SheetState;
|
|
@@ -16,8 +16,6 @@ export interface SheetProps extends Omit<ComponentPropsWithoutRef<'article'>, 'o
|
|
|
16
16
|
onStateChange?: (state: SheetState, reason: SheetChangeReason) => void;
|
|
17
17
|
/** the states a drag snaps to and a reveal may climb through — "peek half full", or an array (default all four) */
|
|
18
18
|
states?: string | readonly Resting[];
|
|
19
|
-
/** floats above a footnote strip on a dim stage (bottom corners and border back) */
|
|
20
|
-
raised?: boolean;
|
|
21
19
|
/** the grab handle; `false` for a sheet with no handle, a string sets its accessible name */
|
|
22
20
|
handle?: boolean | string;
|
|
23
21
|
}
|
|
@@ -33,5 +31,5 @@ export interface SheetProps extends Omit<ComponentPropsWithoutRef<'article'>, 'o
|
|
|
33
31
|
* a drag snaps to the nearest of `states`, focus in a peeked sheet raises it, and when the cut moves (the keyboard) it
|
|
34
32
|
* climbs until the focused control has room above the foot.
|
|
35
33
|
*/
|
|
36
|
-
export declare function Sheet({ state, defaultState, onStateChange, states,
|
|
34
|
+
export declare function Sheet({ state, defaultState, onStateChange, states, handle, className, children, onFocus, ...rest }: SheetProps): import("react").JSX.Element;
|
|
37
35
|
export {};
|
package/dist/sheets/Sheet.js
CHANGED
|
@@ -15,7 +15,7 @@ const TAP_REM = 0.5; // = --sp-2: a move shorter than this is a tap, not a drag
|
|
|
15
15
|
* a drag snaps to the nearest of `states`, focus in a peeked sheet raises it, and when the cut moves (the keyboard) it
|
|
16
16
|
* climbs until the focused control has room above the foot.
|
|
17
17
|
*/
|
|
18
|
-
export function Sheet({ state, defaultState = 'half', onStateChange, states,
|
|
18
|
+
export function Sheet({ state, defaultState = 'half', onStateChange, states, handle = true, className, children, onFocus, ...rest }) {
|
|
19
19
|
const [inner, setInner] = useState(defaultState);
|
|
20
20
|
const current = state ?? inner;
|
|
21
21
|
const controlled = state !== undefined;
|
|
@@ -158,5 +158,5 @@ export function Sheet({ state, defaultState = 'half', onStateChange, states, rai
|
|
|
158
158
|
skipClick.current = true;
|
|
159
159
|
requestAnimationFrame(() => { skipClick.current = false; });
|
|
160
160
|
};
|
|
161
|
-
return (_jsxs("article", { ref: ref, className: cx('card sheet', `sheet--${current}`,
|
|
161
|
+
return (_jsxs("article", { ref: ref, className: cx('card sheet', `sheet--${current}`, className), inert: current === 'away' || undefined, onFocus: focus, ...rest, children: [handle !== false && (_jsx("button", { ref: handleRef, className: "sheet__handle", type: "button", "aria-label": typeof handle === 'string' ? handle : 'Resize', onClick: tap, onPointerDown: down, onPointerMove: move, onPointerUp: up, onPointerCancel: up })), children] }));
|
|
162
162
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export interface SheetBodyProps extends
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
export interface SheetBodyProps extends ComponentProps<'div'> {
|
|
3
3
|
}
|
|
4
4
|
/** SheetBody — everything under a Sheet's head: the one thing that scrolls; its scroll padding keeps a focused control above the cut. Content never goes straight into the Sheet. */
|
|
5
5
|
export declare function SheetBody({ className, ...rest }: SheetBodyProps): import("react").JSX.Element;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export interface SheetHeadProps extends Omit<
|
|
1
|
+
import type { ComponentProps, ReactNode } from 'react';
|
|
2
|
+
export interface SheetHeadProps extends Omit<ComponentProps<'div'>, 'title'> {
|
|
3
3
|
/** the round button on the left (an IconBtn sm) */
|
|
4
4
|
lead?: ReactNode;
|
|
5
5
|
/** the centred title */
|
|
@@ -1,5 +1,5 @@
|
|
|
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
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
|
|
@@ -7,7 +7,7 @@ export interface SheetStackProps extends ComponentPropsWithoutRef<'div'> {
|
|
|
7
7
|
open?: number | null;
|
|
8
8
|
/** UNCONTROLLED: the sheet open on arrival (default none); the stack then keeps its own */
|
|
9
9
|
defaultOpen?: number | null;
|
|
10
|
-
/** the stack ASKS: a peeked head was tapped (its index), or the open sheet's `
|
|
10
|
+
/** the stack ASKS: a peeked head was tapped (its index), or the open sheet's `StackBack` (`null`) */
|
|
11
11
|
onOpenChange?: (open: number | null) => void;
|
|
12
12
|
/** wider peeks so more of each title shows (display stacks) */
|
|
13
13
|
fanned?: boolean;
|
|
@@ -20,14 +20,14 @@ export interface SheetStackProps extends ComponentPropsWithoutRef<'div'> {
|
|
|
20
20
|
* SheetStack — the MENU: sheets stacked like paper at the middle of the home screen, every one a main section.
|
|
21
21
|
* Children are Cards, direct children only, at most five: first = the back of the stack, last = the front (open) sheet.
|
|
22
22
|
* Every sheet is the stack's full height; a peek is the strip the next sheet doesn't cover. A stack head is a CardHead
|
|
23
|
-
* with CHILDREN, in this order: `<
|
|
23
|
+
* with CHILDREN, in this order: `<StackBack />` (tap mode), `<Text level="h2" caps>Shopping</Text>`, an `<IconRow>` of Icons —
|
|
24
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
|
|
25
25
|
* off the bottom. `closed`: nothing open on arrival — every head peeks at the bottom and the base above shows `base` (a home screen
|
|
26
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
27
|
*
|
|
28
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
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
|
|
30
|
+
* sheet's StackBack. 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
31
|
* before tuck under nearest-first; closing reverses in two beats. Only `translate` (stack.css); it sets classes, never a size.
|
|
32
32
|
*/
|
|
33
33
|
export declare function SheetStack({ mode, open, defaultOpen, onOpenChange, fanned, closed, base, className, children, onClick, ...rest }: SheetStackProps): import("react").JSX.Element;
|
|
@@ -12,14 +12,14 @@ const sheetsOf = (stack) => [...stack.children]
|
|
|
12
12
|
* SheetStack — the MENU: sheets stacked like paper at the middle of the home screen, every one a main section.
|
|
13
13
|
* Children are Cards, direct children only, at most five: first = the back of the stack, last = the front (open) sheet.
|
|
14
14
|
* Every sheet is the stack's full height; a peek is the strip the next sheet doesn't cover. A stack head is a CardHead
|
|
15
|
-
* with CHILDREN, in this order: `<
|
|
15
|
+
* with CHILDREN, in this order: `<StackBack />` (tap mode), `<Text level="h2" caps>Shopping</Text>`, an `<IconRow>` of Icons —
|
|
16
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
|
|
17
17
|
* off the bottom. `closed`: nothing open on arrival — every head peeks at the bottom and the base above shows `base` (a home screen
|
|
18
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
19
|
*
|
|
20
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
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
|
|
22
|
+
* sheet's StackBack. 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
23
|
* before tuck under nearest-first; closing reverses in two beats. Only `translate` (stack.css); it sets classes, never a size.
|
|
24
24
|
*/
|
|
25
25
|
export function SheetStack({ mode = 'tap', open, defaultOpen = null, onOpenChange, fanned, closed, base, className, children, onClick, ...rest }) {
|
|
@@ -75,7 +75,7 @@ export function SheetStack({ mode = 'tap', open, defaultOpen = null, onOpenChang
|
|
|
75
75
|
const target = e.target;
|
|
76
76
|
const sheets = sheetsOf(stack);
|
|
77
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('.
|
|
78
|
+
if (target.closest('.sheet-stack__back')) {
|
|
79
79
|
request(null);
|
|
80
80
|
return;
|
|
81
81
|
}
|
|
@@ -1,20 +1,18 @@
|
|
|
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 */
|
|
6
6
|
hero?: ReactNode;
|
|
7
7
|
/** blur and darken the background (the dim page sheet) */
|
|
8
8
|
dim?: boolean;
|
|
9
|
-
/**
|
|
10
|
-
ask?: boolean;
|
|
11
|
-
/** a footnote strip on the scrim under a raised sheet */
|
|
9
|
+
/** a footnote strip at the stage's bottom, on the scrim */
|
|
12
10
|
foot?: ReactNode;
|
|
13
11
|
}
|
|
14
12
|
/**
|
|
15
13
|
* SheetStage — a page-level overlay stage, its own 100dvh page: a Sheet over a map (or over a `hero` — one
|
|
16
14
|
* thing centred in the band a half sheet leaves open), the dim page sheet
|
|
17
|
-
* (`dim` +
|
|
15
|
+
* (`dim` + a `Modal`), the ask (`dim` + a `Modal`, which centres itself — or a Modal on a clean ground, no `dim`). Full stops under the top bar's line.
|
|
18
16
|
* NEVER inside a Step — an app screen where the member acts is a Step.
|
|
19
17
|
*/
|
|
20
|
-
export declare function SheetStage({ bg, hero, dim,
|
|
18
|
+
export declare function SheetStage({ bg, hero, dim, foot, className, children, ...rest }: SheetStageProps): import("react").JSX.Element;
|
|
@@ -3,9 +3,9 @@ import { cx } from '../cx.js';
|
|
|
3
3
|
/**
|
|
4
4
|
* SheetStage — a page-level overlay stage, its own 100dvh page: a Sheet over a map (or over a `hero` — one
|
|
5
5
|
* thing centred in the band a half sheet leaves open), the dim page sheet
|
|
6
|
-
* (`dim` +
|
|
6
|
+
* (`dim` + a `Modal`), the ask (`dim` + a `Modal`, which centres itself — or a Modal on a clean ground, no `dim`). Full stops under the top bar's line.
|
|
7
7
|
* NEVER inside a Step — an app screen where the member acts is a Step.
|
|
8
8
|
*/
|
|
9
|
-
export function SheetStage({ bg, hero, dim,
|
|
10
|
-
return (_jsxs("div", { className: cx('sheet-stage', dim && 'sheet-stage--dim',
|
|
9
|
+
export function SheetStage({ bg, hero, dim, foot, className, children, ...rest }) {
|
|
10
|
+
return (_jsxs("div", { className: cx('sheet-stage', dim && 'sheet-stage--dim', className), ...rest, children: [bg != null && _jsx("div", { className: "sheet-stage__bg", children: bg }), hero != null && _jsx("div", { className: "sheet-stage__hero", children: hero }), children, foot != null && _jsx("p", { className: "sheet-stage__foot", children: foot })] }));
|
|
11
11
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ComponentProps } from 'react';
|
|
2
|
+
export interface StackBackProps extends ComponentProps<'button'> {
|
|
3
|
+
/** accessible name */
|
|
4
|
+
label?: string;
|
|
5
|
+
}
|
|
6
|
+
/** StackBack — the back button a tapped stack sheet reveals in its head; first child of that sheet's CardHead. Hidden until the sheet is open. */
|
|
7
|
+
export declare function StackBack({ label, className, ...rest }: StackBackProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cx } from '../cx.js';
|
|
3
|
+
import { Icon } from '../type/Icon.js';
|
|
4
|
+
/** StackBack — the back button a tapped stack sheet reveals in its head; first child of that sheet's CardHead. Hidden until the sheet is open. */
|
|
5
|
+
export function StackBack({ label = 'Back', className, ...rest }) {
|
|
6
|
+
return (_jsx("button", { type: "button", className: cx('icon-btn icon-btn--sm sheet-stack__back', className), "aria-label": label, ...rest, children: _jsx(Icon, { name: "arrow-left" }) }));
|
|
7
|
+
}
|
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;
|