@usableapp/cardds 0.7.15 → 0.7.17
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 +53 -0
- package/README.md +29 -28
- package/cardds.css +3 -3
- package/css/actions.css +67 -22
- package/css/base.css +44 -18
- package/css/card.css +25 -26
- package/css/choice.css +21 -33
- package/css/forms.css +0 -3
- package/css/journey.css +1 -3
- package/css/layover.css +19 -41
- package/css/lists.css +1 -6
- package/css/media.css +9 -18
- package/css/numbers.css +6 -21
- package/css/people.css +3 -9
- package/css/sheet.css +15 -19
- package/css/stack.css +21 -29
- package/css/step.css +7 -12
- package/css/theme.template.css +2 -1
- package/css/tokens.css +22 -4
- package/dist/actions/Btn.d.ts +1 -1
- package/dist/actions/Dropdown.js +3 -9
- package/dist/actions/Fab.d.ts +1 -1
- package/dist/actions/Fab.js +3 -2
- package/dist/cardds.css +264 -267
- package/dist/cards/Card.d.ts +24 -8
- package/dist/cards/Card.js +23 -8
- package/dist/cards/CardHead.d.ts +0 -1
- package/dist/cards/CardHead.js +1 -1
- package/dist/choice/Calendar.js +2 -5
- package/dist/choice/Mood.d.ts +10 -5
- package/dist/choice/Mood.js +4 -2
- package/dist/forms/Field.js +2 -3
- package/dist/forms/FileBtn.js +1 -1
- package/dist/forms/Pin.js +7 -12
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/layover/Banner.d.ts +10 -3
- package/dist/layover/Banner.js +6 -3
- package/dist/lists/Row.d.ts +2 -1
- package/dist/lists/Row.js +5 -5
- package/dist/media/Postcard.js +3 -5
- package/dist/numbers/Band.d.ts +3 -1
- package/dist/numbers/Picker.js +3 -10
- package/dist/numbers/Track.d.ts +4 -2
- package/dist/numbers/Track.js +3 -3
- package/dist/people/AvatarPick.d.ts +3 -1
- package/dist/people/AvatarPick.js +2 -2
- package/dist/scaffold/ActionBar.d.ts +3 -3
- package/dist/scaffold/ActionBar.js +2 -2
- package/dist/scaffold/Centre.d.ts +2 -2
- package/dist/scaffold/Centre.js +2 -2
- package/dist/scaffold/PagerAt.d.ts +1 -1
- package/dist/scaffold/PagerAt.js +1 -1
- package/dist/scaffold/Screen.js +4 -7
- package/dist/scaffold/TopBar.js +3 -5
- package/dist/sheets/Drawer.js +3 -4
- package/dist/sheets/Sheet.js +9 -22
- package/dist/sheets/SheetStack.d.ts +2 -2
- package/dist/sheets/SheetStack.js +20 -13
- package/dist/sheets/SheetSteps.js +8 -11
- package/dist/sheets/StackBack.js +2 -1
- package/dist/sheets/StackSheet.d.ts +3 -2
- package/dist/sheets/StackSheet.js +7 -11
- package/dist/state.d.ts +24 -0
- package/dist/state.js +57 -0
- package/dist/templates/CallSheet.js +2 -4
- package/dist/templates/Home.d.ts +3 -2
- package/dist/templates/Home.js +2 -4
- package/dist/templates/Splash.js +3 -3
- package/dist/templates/Walkthrough.js +4 -5
- package/dist/type/Icon.js +3 -5
- package/dist/type/Text.d.ts +1 -1
- package/dist/type/textScale.d.ts +6 -0
- package/dist/type/textScale.js +12 -0
- package/package.json +7 -4
- package/dist/layover/Deck.d.ts +0 -9
- package/dist/layover/Deck.js +0 -10
package/css/numbers.css
CHANGED
|
@@ -33,7 +33,6 @@
|
|
|
33
33
|
}
|
|
34
34
|
.ring__value { font: var(--ring-value-font, var(--type-stat)); letter-spacing: var(--track-display); }
|
|
35
35
|
.ring__label { font: var(--ring-label-font, var(--type-caption)); color: var(--ring-label-ink, var(--card-muted)); }
|
|
36
|
-
.card--3 .ring__label { color: inherit; opacity: 0.7; }
|
|
37
36
|
.ring--sm { --_size: var(--avatar-xl); --_w: var(--sp-3); }
|
|
38
37
|
.ring--sm .ring__value { font: 800 var(--fs-2xl)/1 var(--font-display); }
|
|
39
38
|
.ring--xs { --_size: var(--tap-sm); --_w: var(--dot-xs); } /* inline counter (step 3 of 5) */
|
|
@@ -72,7 +71,7 @@
|
|
|
72
71
|
content: "";
|
|
73
72
|
flex: 1;
|
|
74
73
|
height: var(--sp-3);
|
|
75
|
-
background: color-mix(in srgb, var(--_ink) 30%, transparent)
|
|
74
|
+
background: var(--ink-rail); /* the track's own ink at 30% — identical to color-mix(in srgb, var(--_ink) 30%, transparent): --ink-rail already reads currentColor, and .track sets color to --_ink */
|
|
76
75
|
}
|
|
77
76
|
.track__step:first-child::before { display: none; }
|
|
78
77
|
.track__step.is-done::before { background: var(--accent); }
|
|
@@ -83,9 +82,10 @@
|
|
|
83
82
|
flex: none;
|
|
84
83
|
padding: calc((var(--tap-lg) - var(--icon)) / 2);
|
|
85
84
|
border-radius: 50%;
|
|
86
|
-
background:
|
|
85
|
+
background: var(--ink-rail);
|
|
87
86
|
color: var(--_ink);
|
|
88
87
|
}
|
|
88
|
+
.track__step > .track__dot { display: grid; place-items: center; padding: 0; font: var(--track-dot-font, var(--type-title)); font-variant-numeric: tabular-nums; } /* a number in the round (TrackStep num) */
|
|
89
89
|
.track__step.is-done > .icon,
|
|
90
90
|
.track__step.is-done > .track__dot { background: var(--accent); color: var(--on-accent); }
|
|
91
91
|
|
|
@@ -107,7 +107,6 @@
|
|
|
107
107
|
}
|
|
108
108
|
.band__num small { font-size: 0.5em; font-weight: 700; margin-right: 0.1em; } /* unit or % */
|
|
109
109
|
.band__foot { grid-area: foot; font: var(--band-foot-font, var(--type-caption)); color: var(--band-foot-ink, var(--card-muted)); }
|
|
110
|
-
.card--3 .band__foot { color: inherit; opacity: 0.7; }
|
|
111
110
|
/* band stack: ONE card boundary; bands are frameless inside it, a hairline
|
|
112
111
|
between each. Bands may still carry slot tints (card--2 / card--3). */
|
|
113
112
|
.band-stack {
|
|
@@ -154,14 +153,6 @@
|
|
|
154
153
|
@supports not (width: round(up, 1px, 1px)) {
|
|
155
154
|
.dotgrid::before { display: none; }
|
|
156
155
|
}
|
|
157
|
-
.dotgrid--stars {
|
|
158
|
-
background-image: none;
|
|
159
|
-
}
|
|
160
|
-
.dotgrid--stars,
|
|
161
|
-
.dotgrid--stars::before {
|
|
162
|
-
--_star: polygon(50% 0, 62% 38%, 100% 50%, 62% 62%, 50% 100%, 38% 62%, 0 50%, 38% 38%);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
156
|
/* ---- picker: horizontal snap picker, centre value big ----
|
|
166
157
|
<div class="picker"><div class="picker__rail"><button class="picker__item">100</button>…</div><span class="picker__unit">ml</span></div> */
|
|
167
158
|
.picker { display: grid; gap: var(--picker-gap, var(--sp-1)); justify-items: center; position: relative; }
|
|
@@ -176,20 +167,15 @@
|
|
|
176
167
|
grid-auto-columns: 100%;
|
|
177
168
|
overflow-x: auto;
|
|
178
169
|
scroll-snap-type: x mandatory;
|
|
179
|
-
scrollbar-width: none;
|
|
180
170
|
position: relative;
|
|
181
171
|
}
|
|
182
|
-
.picker__rail::-webkit-scrollbar { display: none; }
|
|
183
172
|
.picker__item {
|
|
184
173
|
scroll-snap-align: center;
|
|
185
|
-
border: 0;
|
|
186
|
-
background: transparent;
|
|
187
|
-
color: inherit;
|
|
188
174
|
padding: var(--picker-item-pad-y, var(--sp-2)) var(--picker-item-pad-x, 0);
|
|
189
175
|
font: var(--picker-item-font, var(--type-stat));
|
|
190
176
|
letter-spacing: var(--track-display);
|
|
191
177
|
font-variant-numeric: tabular-nums;
|
|
192
|
-
opacity:
|
|
178
|
+
opacity: var(--faint);
|
|
193
179
|
text-align: center;
|
|
194
180
|
}
|
|
195
181
|
.picker__item[aria-selected="true"] { opacity: 1; }
|
|
@@ -206,12 +192,11 @@
|
|
|
206
192
|
}
|
|
207
193
|
.picker::after { left: auto; right: calc(100% / 3); }
|
|
208
194
|
.picker__unit { font: var(--picker-unit-font, var(--type-caption)); color: var(--picker-unit-ink, var(--card-muted)); }
|
|
209
|
-
.card--3 .picker__unit { color: inherit; opacity: 0.7; }
|
|
210
195
|
/* the scrolled-to item lights up by position — no JS */
|
|
211
196
|
@supports (animation-timeline: view(x)) {
|
|
212
|
-
.picker__item {
|
|
197
|
+
.picker__item { animation: picker-focus linear both; animation-timeline: view(x); } /* opacity: var(--faint) already set above — the animation alone is new here */
|
|
213
198
|
@keyframes picker-focus {
|
|
214
|
-
0%, 100% { opacity:
|
|
199
|
+
0%, 100% { opacity: var(--faint); }
|
|
215
200
|
45%, 55% { opacity: 1; }
|
|
216
201
|
}
|
|
217
202
|
}
|
package/css/people.css
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
.avatar--xl { --_size: var(--avatar-xl); } /* sheet head icon ring */
|
|
32
32
|
/* outline avatar: no fill, an edge — icons in a ring, "add" slots */
|
|
33
33
|
.avatar--outline { background: transparent; color: inherit; border: var(--border-w) solid var(--avatar-outline-border, var(--outline)); }
|
|
34
|
-
.avatar--add { background: transparent; color: inherit; border: var(--border-w) dashed var(--avatar-add-border, var(--outline));
|
|
34
|
+
.avatar--add { background: transparent; color: inherit; border: var(--border-w) dashed var(--avatar-add-border, var(--outline)); }
|
|
35
35
|
/* accent avatar: the "+7" tail, the selected person */
|
|
36
36
|
.avatar--on { background: var(--avatar-on-bg, var(--accent)); color: var(--avatar-on-ink, var(--on-accent)); }
|
|
37
37
|
/* halo: faint concentric rings behind a hero avatar (decorative) */
|
|
@@ -57,10 +57,8 @@
|
|
|
57
57
|
display: flex;
|
|
58
58
|
gap: var(--avatar-pick-gap, var(--sp-4));
|
|
59
59
|
overflow-x: auto;
|
|
60
|
-
scroll-snap-type: x proximity;
|
|
61
|
-
scrollbar-width: none; /* starts at the card's padding edge, like every row */
|
|
60
|
+
scroll-snap-type: x proximity; /* starts at the card's padding edge, like every row */
|
|
62
61
|
}
|
|
63
|
-
.avatar-pick::-webkit-scrollbar { display: none; }
|
|
64
62
|
.avatar-pick__item {
|
|
65
63
|
scroll-snap-align: start;
|
|
66
64
|
flex: none;
|
|
@@ -68,12 +66,8 @@
|
|
|
68
66
|
display: grid;
|
|
69
67
|
justify-items: center;
|
|
70
68
|
gap: var(--avatar-pick-item-gap, var(--sp-2));
|
|
71
|
-
border: 0;
|
|
72
|
-
background: transparent;
|
|
73
|
-
color: inherit;
|
|
74
|
-
padding: 0;
|
|
75
69
|
text-align: center;
|
|
76
70
|
}
|
|
77
71
|
.avatar-pick__name { font: var(--avatar-pick-name-font, var(--type-label)); font-size: var(--avatar-pick-name-font-size, var(--fs-sm)); }
|
|
78
72
|
.avatar-pick__role { font: var(--avatar-pick-role-font, var(--type-caption)); color: var(--avatar-pick-role-ink, var(--card-muted)); margin-top: calc(-1 * var(--sp-1)); }
|
|
79
|
-
.
|
|
73
|
+
.avatar-pick__item[aria-pressed="true"] > .avatar { background: var(--avatar-pick-on-bg, var(--accent)); color: var(--avatar-pick-on-ink, var(--on-accent)); border-color: transparent; } /* the picked person */
|
package/css/sheet.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* ============================================================
|
|
2
2
|
cardds/sheet.css — sheet single: one card as a bottom sheet.
|
|
3
|
-
|
|
3
|
+
Five states: .sheet--peek · .sheet--half · .sheet--3q · .sheet--full · .sheet--away
|
|
4
4
|
|
|
5
5
|
A sheet is rigid material, exactly like a sheet in .sheet-stack--tap
|
|
6
6
|
(stack.css): it is ALWAYS the full height of the box that holds it —
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
the body. The handle and the head stay where they are at every
|
|
42
42
|
state; the body is what scrolls — a sheet is a card whose head is
|
|
43
43
|
pinned, not a scrolling column with a title somewhere in it.
|
|
44
|
-
|
|
45
|
-
raise; without it every state still renders.
|
|
44
|
+
The Sheet component adds the handle's click / drag / keyboard and the
|
|
45
|
+
focus raise; without it every state still renders.
|
|
46
46
|
============================================================ */
|
|
47
47
|
|
|
48
48
|
.sheet {
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
position: absolute;
|
|
71
71
|
inset: 0;
|
|
72
72
|
top: var(--_top, 0); /* a stage keeps its top bar's line free — see .sheet-stage */
|
|
73
|
-
translate: 0 calc(var(--_y) + var(--_drag, 0rem)); /* --_drag:
|
|
73
|
+
translate: 0 calc(var(--_y) + var(--_drag, 0rem)); /* --_drag: the Sheet component, only while the handle is held */
|
|
74
74
|
transition: translate var(--motion-sheet) ease;
|
|
75
75
|
|
|
76
76
|
/* handle · head · body: a column, the body takes what is left and scrolls
|
|
@@ -81,6 +81,7 @@
|
|
|
81
81
|
border-radius: var(--r-card) var(--r-card) 0 0;
|
|
82
82
|
border-bottom: 0;
|
|
83
83
|
box-shadow: var(--sheet-shadow, var(--shadow-sheet));
|
|
84
|
+
--_foot: calc(var(--card-gap) + var(--btn-h) + var(--card-pad)); /* the foot strip's height (below) — merged here, one bare .sheet rule */
|
|
84
85
|
}
|
|
85
86
|
.sheet--full { --_y: 0%; --_cover: 0rem; }
|
|
86
87
|
.sheet--half { --_y: calc(var(--sheet-half) * 100%); --_cover: calc(var(--sheet-half) * var(--_box)); }
|
|
@@ -146,9 +147,8 @@
|
|
|
146
147
|
takes no taps, its buttons do; the strip behind them is the sheet's ground, --_foot tall, and the body
|
|
147
148
|
stops that far above the sheet's edge. At peek there is only the handle and the title: the foot is gone.
|
|
148
149
|
One row, ≤ 2 buttons. <div class="card__foot"><button class="btn btn--primary btn--block">…</button></div> */
|
|
149
|
-
.sheet { --_foot: calc(var(--card-gap) + var(--btn-h) + var(--card-pad)); }
|
|
150
150
|
/* …and the link row under the button, when there is one (its line + the gap over it) */
|
|
151
|
-
.sheet:has(> .card__foot--link) { --_foot: calc(var(--card-gap) + var(--btn-h) + var(--sp-1) + calc(var(--tap-base) * 7 / 12) + var(--card-pad)); }
|
|
151
|
+
.sheet:has(> .card__foot--link) { --_foot: calc(var(--card-gap) + var(--btn-h) + var(--sp-1) + var(--link-sm-min-h, calc(var(--tap-base) * 7 / 12)) + var(--card-pad)); }
|
|
152
152
|
.sheet > .card__foot {
|
|
153
153
|
position: absolute; inset: calc(-1 * var(--border-w)) 0 0; z-index: 1; /* the sheet's border box: the same height the sheet's own % reads */
|
|
154
154
|
align-items: end;
|
|
@@ -174,7 +174,7 @@
|
|
|
174
174
|
/* grab handle — first child of the sheet. Drawn as a small bar, but it is
|
|
175
175
|
the thumb's grab area for the whole strip above the title: a pseudo widens
|
|
176
176
|
its hit box to --tap tall and wider than the bar without changing the
|
|
177
|
-
picture. touch-action: none hands a touch drag to
|
|
177
|
+
picture. touch-action: none hands a touch drag to the Sheet component instead of to
|
|
178
178
|
the scroller behind it. */
|
|
179
179
|
.sheet__handle {
|
|
180
180
|
position: relative;
|
|
@@ -248,7 +248,7 @@
|
|
|
248
248
|
.screen > .sheet-stage { margin-inline: calc(-1 * var(--screen-pad)); width: auto; } /* auto: 100% would keep the inset width */
|
|
249
249
|
/* a stage laid OVER its screen (a Modal a link opened, Lh 2026-09-23): the page shows through, the stage covers it and its bar */
|
|
250
250
|
.sheet-stage--over, .screen > .sheet-stage--over {
|
|
251
|
-
position: absolute; inset: 0; z-index:
|
|
251
|
+
position: absolute; inset: 0; z-index: var(--z-top);
|
|
252
252
|
width: auto; height: auto; max-width: none; margin: 0;
|
|
253
253
|
background: transparent;
|
|
254
254
|
--_top: 0rem;
|
|
@@ -305,7 +305,7 @@
|
|
|
305
305
|
translate: -50% -50%;
|
|
306
306
|
border-radius: 50%;
|
|
307
307
|
border: var(--border-w) solid var(--map-ring-border, var(--accent));
|
|
308
|
-
background: var(--map-ring-bg,
|
|
308
|
+
background: var(--map-ring-bg, var(--accent-soft));
|
|
309
309
|
box-shadow: var(--map-ring-shadow, var(--shadow-float));
|
|
310
310
|
pointer-events: none;
|
|
311
311
|
z-index: 1; /* above the engine's panes (Leaflet's tiles sit at 200, but inside their own stacking context) */
|
|
@@ -339,9 +339,6 @@
|
|
|
339
339
|
z-index: 1;
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
-
/* raised: the sheet floats above a footnote strip on the scrim. Its bottom
|
|
343
|
-
edge shows, so it gets its corners and border back; full still stops at
|
|
344
|
-
the top bar's line, because the top edge never moved. */
|
|
345
342
|
/* EVERY sheet has one shape (Lh, 2026-09-21): the handle and the head stay at the top and never scroll · the
|
|
346
343
|
foot's button stands at the bottom, and ABOVE the keyboard when there is one · everything between them
|
|
347
344
|
scrolls, as far as it needs to. In a .step the keyboard's room is the step's (--kb, step.css); on a stage
|
|
@@ -380,9 +377,8 @@
|
|
|
380
377
|
bottom of the body, each its title line. Every step has a thin rule on top. A step opens and folds as a 1fr ↔ 0fr grid row, so the pile rises and
|
|
381
378
|
falls — no height is written. Nothing fades: done and next read at full ink. */
|
|
382
379
|
.sheet__body:has(> .sheet-steps) { display: flex; flex-direction: column; }
|
|
383
|
-
.sheet-steps { flex-shrink: 0; min-height: calc(100% + var(--kb, 0rem)); /* the keyboard's height more: the pile of next steps stays under the keyboard, it never rises with it */ display: flex; flex-direction: column; touch-action: pan-y; }
|
|
380
|
+
.sheet-steps { flex-shrink: 0; min-height: calc(100% + var(--kb, 0rem)); /* the keyboard's height more: the pile of next steps stays under the keyboard, it never rises with it */ display: flex; flex-direction: column; touch-action: pan-y; position: relative; }
|
|
384
381
|
.sheet-steps__holder { position: absolute; top: 0; left: 0; width: 1rem; height: 1rem; padding: 0; border: 0; opacity: 0; pointer-events: none; font-size: 1rem; } /* holds the cursor (and the phone's keyboard) while a step folds; font 1rem = the browser's own size, so iOS does not zoom to it */
|
|
385
|
-
.sheet-steps { position: relative; }
|
|
386
382
|
.sheet-steps__track { list-style: none; margin: 0; padding: 0; flex: 1; display: flex; flex-direction: column; }
|
|
387
383
|
|
|
388
384
|
.sheet-step {
|
|
@@ -390,6 +386,7 @@
|
|
|
390
386
|
display: grid; grid-template-rows: auto 0fr; align-content: start; /* mid-fold the rows sum to less than the box: the spare room stays BELOW, never spread into the title row (Lh: it looked like a spring) */
|
|
391
387
|
flex: 0 0 auto;
|
|
392
388
|
transition: grid-template-rows var(--motion-sheet) ease, flex-grow var(--motion-sheet) ease;
|
|
389
|
+
--_row-h: var(--sheet-steps-row-h, calc(var(--tap-base) * 2 / 3)); /* the bar's own floor, read once (__head and __go below share it) */
|
|
393
390
|
}
|
|
394
391
|
/* the open step GROWS into the room left, so the steps not done yet wait in a pile at the bottom — and a move is an ACCORDION:
|
|
395
392
|
in one beat the step that was open folds while the new one unfolds (flex-grow and the 1fr row both ease), the piles slide
|
|
@@ -397,26 +394,25 @@
|
|
|
397
394
|
.sheet-step--now { grid-template-rows: auto 1fr; flex-grow: 1; }
|
|
398
395
|
.sheet-step + .sheet-step { margin-top: var(--sheet-steps-gap, var(--sp-1)); } /* the folded bars read as a pile, a little ground between them (Lh 2026-09-25) */
|
|
399
396
|
.sheet-step__head { /* every step's title line is a quiet BAR (a tint of the ink, not the brand — a brand bar read as a button, Lh 2026-09-25), the same height open or folded — opening shows the white room under it, never a taller bar (Lh 2026-09-25; was a thin rule on top) */
|
|
400
|
-
display: flex; align-items: center; gap: var(--sp-3); min-height: var(--
|
|
397
|
+
display: flex; align-items: center; gap: var(--sp-3); min-height: var(--_row-h); /* THIN: 32px, a summary line, not a button (Lh 2026-09-25) — the tap stays 44, see __go */
|
|
401
398
|
padding-inline: var(--sheet-step-bar-pad-x, var(--sp-3)); border-radius: var(--sheet-step-bar-radius, var(--r-chip));
|
|
402
399
|
background: var(--sheet-step-bar-bg, var(--ink-tint)); color: var(--sheet-step-bar-ink, inherit);
|
|
403
|
-
border-top: var(--sheet-step-border-w,
|
|
400
|
+
border-top: var(--sheet-step-border-w, 0rem) solid var(--sheet-step-border, currentColor); /* a rule instead of the bar: set this, the bar's bg transparent, radius 0 */
|
|
404
401
|
}
|
|
405
|
-
.sheet-step__summary { color: inherit; opacity: 0.8; }
|
|
406
402
|
.sheet-step__title { font: var(--sheet-step-title-font, var(--type-label)); margin: 0; flex: 0 1 auto; min-width: 0; outline: none; /* the label size, not a body title: a pile of rows must stay small (Lh 2026-09-24) */ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
407
403
|
.sheet-step__num { /* `numbered`: the step's number in a disc BEFORE its title (Lh 2026-09-25) — a white disc on the bar, the number in the ink */
|
|
408
404
|
flex: none; display: grid; place-items: center; inline-size: var(--sheet-step-num-size, calc(var(--tap-base) / 2)); block-size: var(--sheet-step-num-size, calc(var(--tap-base) / 2));
|
|
409
405
|
border-radius: 50%; font: var(--sheet-step-num-font, var(--type-caption)); font-variant-numeric: tabular-nums;
|
|
410
406
|
background: var(--sheet-step-num-bg, var(--card-bg)); color: var(--sheet-step-num-ink, inherit);
|
|
411
407
|
}
|
|
412
|
-
.sheet-step__summary { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
408
|
+
.sheet-step__summary { color: inherit; opacity: 0.8; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
413
409
|
.sheet-step__check { margin-inline-start: auto; }
|
|
414
410
|
.sheet-step__body { min-height: 0; overflow: clip; overflow-clip-margin: var(--sp-1); }
|
|
415
411
|
.sheet-step__inner { display: grid; gap: var(--card-gap); padding-block: var(--card-gap); }
|
|
416
412
|
.sheet-step__inner > * { min-width: 0; }
|
|
417
413
|
.sheet-step__inner > .link { justify-self: center; } /* a link of its own row in a step (skip, "change number", "set PIN again"): centred under the step, as the skip (Lh 2026-09-25) */
|
|
418
414
|
.sheet-step:not(.sheet-step--now) > .sheet-step__body { visibility: hidden; transition: visibility 0s linear var(--motion-sheet); }
|
|
419
|
-
.sheet-step__go { position: absolute; inset: min(
|
|
415
|
+
.sheet-step__go { position: absolute; inset: min(0rem, (var(--_row-h) - var(--tap-sm)) / 2) 0 auto; min-height: max(100%, var(--tap-sm)); /* a thin bar still takes a 44px tap */ margin: 0; cursor: pointer; }
|
|
420
416
|
/* the last step's finish, when the app gives one: under the steps */
|
|
421
417
|
.sheet-steps__finish { display: grid; padding-top: var(--card-gap); }
|
|
422
418
|
@media (prefers-reduced-motion: reduce) { .sheet-step { transition: none; } }
|
package/css/stack.css
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
bottom, the headroom above is the base's (block below).
|
|
33
33
|
Direct children only, five at most (slots are :nth-child below):
|
|
34
34
|
first = the back of the stack, last = the front. README "Sheet stack
|
|
35
|
-
markup".
|
|
35
|
+
markup". The SheetStack component opens and closes a --tap stack; without it the
|
|
36
36
|
stack still renders, it just won't open.
|
|
37
37
|
============================================================ */
|
|
38
38
|
|
|
@@ -45,14 +45,14 @@
|
|
|
45
45
|
track is being sized), so a long sheet grew the track past the screen and
|
|
46
46
|
every sheet's 100% then resolved against that — the bottom of every open
|
|
47
47
|
sheet sat below the screen, unreachable (timebank home, 2026-09-13). */
|
|
48
|
-
.sheet-stack { display: grid; grid-template-rows: minmax(0, 1fr); --stack-step: 5.5rem; }
|
|
49
|
-
|
|
50
48
|
/* the stack breaks out of the screen inset, edge to edge, always: the peek
|
|
51
49
|
strips and the opened sheet span the screen's full width whatever the
|
|
52
50
|
viewport (it used to bleed only under a 27em media query — a stack in a
|
|
53
51
|
phone frame on a desktop kept the inset, and read as a narrower card;
|
|
54
|
-
Lh, 2026-09-11)
|
|
55
|
-
|
|
52
|
+
Lh, 2026-09-11). --_n: how many sheets the stack holds, read from the DOM
|
|
53
|
+
by :has below so the closed geometry needs no script and no per-stack
|
|
54
|
+
declaration. */
|
|
55
|
+
.sheet-stack { display: grid; grid-template-rows: minmax(0, 1fr); --stack-step: 5.5rem; margin-inline: calc(-1 * var(--screen-pad)); --_n: 1; }
|
|
56
56
|
.sheet-stack > .card {
|
|
57
57
|
grid-area: 1 / 1; /* every card shares the stack's cell; later ones offset down */
|
|
58
58
|
border-bottom-left-radius: 0;
|
|
@@ -69,9 +69,6 @@
|
|
|
69
69
|
.sheet-stack > .card:not(:has(~ .card)) {
|
|
70
70
|
align-self: stretch; /* the front card fills the remaining stack height */
|
|
71
71
|
}
|
|
72
|
-
/* --_n: how many sheets the stack holds, read from the DOM by :has so the
|
|
73
|
-
closed geometry needs no script and no per-stack declaration */
|
|
74
|
-
.sheet-stack { --_n: 1; }
|
|
75
72
|
.sheet-stack:has(> .card:nth-child(2)) { --_n: 2; }
|
|
76
73
|
.sheet-stack:has(> .card:nth-child(3)) { --_n: 3; }
|
|
77
74
|
.sheet-stack:has(> .card:nth-child(4)) { --_n: 4; }
|
|
@@ -118,7 +115,6 @@
|
|
|
118
115
|
/* fanned stack: a toggle opens the stack wider so every peek shows more */
|
|
119
116
|
.sheet-stack--fanned { --stack-step: 9.5rem; }
|
|
120
117
|
|
|
121
|
-
.sheet-stack > .card:has(~ .card) { cursor: pointer; }
|
|
122
118
|
/* a peeked card in a plain stack hides its own body. A --tap stack does
|
|
123
119
|
NOT: there, every card is full height and full content always, and a
|
|
124
120
|
peek is simply the strip of it the next card doesn't cover — the way a
|
|
@@ -164,9 +160,10 @@
|
|
|
164
160
|
by n steps (clipped by .screen--fill), so translating it up by exactly
|
|
165
161
|
that much lands it filling the stack precisely. */
|
|
166
162
|
overflow: clip;
|
|
167
|
-
transition: translate
|
|
163
|
+
transition: translate var(--motion-sheet) ease; /* the only animated property here */
|
|
168
164
|
transition-delay: calc(var(--stagger, 0) * 70ms); /* 0 for everything
|
|
169
165
|
except a staggered is-before card, set in JS as it tucks or un-tucks */
|
|
166
|
+
--_back-size: var(--stack-back-size, calc(var(--tap-base) * 2 / 3)); /* read once, shared by the back button and the head's padding below */
|
|
170
167
|
}
|
|
171
168
|
.sheet-stack--tap > .card.is-open {
|
|
172
169
|
/* up by its own resting offset — pure movement, nothing resizes */
|
|
@@ -188,9 +185,8 @@
|
|
|
188
185
|
overscroll-behavior: contain;
|
|
189
186
|
}
|
|
190
187
|
/* a scrolling sheet shows no scrollbar (a desktop with a mouse would paint one
|
|
191
|
-
down the card's edge — Lh 2026-09-15); it still scrolls, like the page itself
|
|
192
|
-
|
|
193
|
-
.sheet-stack--tap > .card::-webkit-scrollbar { display: none; }
|
|
188
|
+
down the card's edge — Lh 2026-09-15); it still scrolls, like the page itself
|
|
189
|
+
(the hiding rule is base.css's, shared with every other scrolling track) */
|
|
194
190
|
.sheet-stack--tap > .card.is-before { translate: 0 var(--stack-step); }
|
|
195
191
|
.sheet-stack--tap > .card.is-after { translate: 0 100vh; }
|
|
196
192
|
|
|
@@ -209,7 +205,7 @@
|
|
|
209
205
|
lands flush at the top. is-before tucks one step below its resting place.
|
|
210
206
|
============================================================ */
|
|
211
207
|
.sheet-stack--closed { --_headroom: calc(100% - var(--_n) * var(--stack-step)); }
|
|
212
|
-
.sheet-stack--closed > .card { translate: 0 var(--_headroom);
|
|
208
|
+
.sheet-stack--closed > .card { translate: 0 var(--_headroom); }
|
|
213
209
|
.sheet-stack--closed > .card.is-before { translate: 0 calc(var(--_headroom) + var(--stack-step)); }
|
|
214
210
|
.sheet-stack--closed > .card.is-open { translate: 0 calc(-1 * var(--slot, 0) * var(--stack-step)); }
|
|
215
211
|
.sheet-stack--closed > .card.is-after { translate: 0 100vh; }
|
|
@@ -241,10 +237,7 @@
|
|
|
241
237
|
.sheet-stack--tap .card__head {
|
|
242
238
|
position: relative;
|
|
243
239
|
padding-left: 0;
|
|
244
|
-
transition: padding-left
|
|
245
|
-
}
|
|
246
|
-
.sheet-stack--tap > .card.is-open > .card__head {
|
|
247
|
-
padding-left: calc(var(--tap-sm) + var(--sp-3));
|
|
240
|
+
transition: padding-left var(--motion-sheet) ease;
|
|
248
241
|
}
|
|
249
242
|
.sheet-stack--tap .sheet-stack__back {
|
|
250
243
|
position: absolute;
|
|
@@ -253,7 +246,13 @@
|
|
|
253
246
|
translate: 0 -50%;
|
|
254
247
|
opacity: 0;
|
|
255
248
|
visibility: hidden;
|
|
256
|
-
transition: opacity
|
|
249
|
+
transition: opacity var(--motion-sheet) ease, visibility var(--motion-sheet);
|
|
250
|
+
/* SMALL (see "the back button, SMALL" below) */
|
|
251
|
+
width: var(--_back-size);
|
|
252
|
+
height: var(--_back-size);
|
|
253
|
+
min-width: 0;
|
|
254
|
+
min-height: 0;
|
|
255
|
+
padding: 0;
|
|
257
256
|
}
|
|
258
257
|
.sheet-stack--tap > .card.is-open .sheet-stack__back {
|
|
259
258
|
opacity: 1;
|
|
@@ -312,20 +311,13 @@
|
|
|
312
311
|
/* ---- the back button, SMALL (Lh 2026-09-23: "give the sheet head more room" — and then "a glyph alone does not read as
|
|
313
312
|
tappable"): a SMALL DISC — its ring kept, 32px instead of 44, the chevron in it at 20 — so the head gives it 32px + a gap
|
|
314
313
|
(was 56px). Its tap target stays 44px: an invisible ::after around the disc. ---- */
|
|
315
|
-
.sheet-stack--tap > .card.is-open > .card__head { padding-left: var(--stack-back-room, calc(var(--
|
|
316
|
-
.sheet-stack--tap .sheet-stack__back {
|
|
317
|
-
width: var(--stack-back-size, calc(var(--tap-base) * 2 / 3));
|
|
318
|
-
height: var(--stack-back-size, calc(var(--tap-base) * 2 / 3));
|
|
319
|
-
min-width: 0;
|
|
320
|
-
min-height: 0;
|
|
321
|
-
padding: 0;
|
|
322
|
-
}
|
|
314
|
+
.sheet-stack--tap > .card.is-open > .card__head { padding-left: var(--stack-back-room, calc(var(--_back-size) + var(--sp-2))); }
|
|
323
315
|
.sheet-stack--tap .sheet-stack__back > .icon { width: var(--stack-back-icon, calc(var(--tap-base) * 13 / 24)); height: var(--stack-back-icon, calc(var(--tap-base) * 13 / 24)); flex: none; } /* 26: the chevron fills the small disc (Lh 2026-09-23) */
|
|
324
|
-
.sheet-stack--tap .sheet-stack__back::after { content: ""; position: absolute; inset: calc((var(--
|
|
316
|
+
.sheet-stack--tap .sheet-stack__back::after { content: ""; position: absolute; inset: calc((var(--_back-size) - var(--tap-sm)) / 2); }
|
|
325
317
|
|
|
326
318
|
/* the open sheet's title folds it (SheetStack.tsx): it says so to a pointer */
|
|
327
319
|
.sheet-stack--tap > .card.is-open > .card__head > :is(h1, h2, h3) { cursor: pointer; }
|
|
328
320
|
/* a stacked sheet is a control until it is open — tapped, never read into: no text selection (a drag, a double tap, a long press),
|
|
329
321
|
no grey flash, no iOS callout; its head stays one when open. Only the OPEN sheet's body is text to select (Lh 2026-09-23) */
|
|
330
|
-
.sheet-stack--tap > .card, .sheet-stack > .card > .card__head { -webkit-user-select: none; user-select: none; -webkit-
|
|
322
|
+
.sheet-stack--tap > .card, .sheet-stack > .card > .card__head { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
|
|
331
323
|
.sheet-stack--tap > .card.is-open > :not(.card__head) { -webkit-user-select: var(--screen-select, none); user-select: var(--screen-select, none); } /* the open sheet reads as the rest of the screen: not selectable (Lh 2026-09-25; it was text) */
|
package/css/step.css
CHANGED
|
@@ -59,9 +59,6 @@
|
|
|
59
59
|
more air and a short one less; a screen with a bar keeps the bar's own room */
|
|
60
60
|
.screen > .step:first-child, .screen--lead > .step { --_lead: var(--screen-lead, 15cqh); } /* top="lead" says it; a Step first says it too */
|
|
61
61
|
|
|
62
|
-
/* a walk (the dots float on its foot): the reading block runs right to the bar's top edge — the reserve's breathing gap (--sp-6)
|
|
63
|
-
is given back, the dots keep the words clear of the bar (Lh 2026-09-23) */
|
|
64
|
-
|
|
65
62
|
/* LAYERS (Lh, 2026-09-20): the base, then the sheet over it, then the top bar. A bar is the BASE's — the
|
|
66
63
|
move of a page of words — so a step with a sheet has NO bar: the sheet finishes on its own .card__foot
|
|
67
64
|
(sheet.css), and a form lives whole in ONE sheet, never item by item on the base. That is how cardds's
|
|
@@ -81,8 +78,7 @@
|
|
|
81
78
|
--card-gap: var(--sp-4);
|
|
82
79
|
gap: var(--card-gap);
|
|
83
80
|
padding-block: 0; /* --_lead carries the top; the bar's room is the step's */
|
|
84
|
-
align-content: start
|
|
85
|
-
color: var(--on-surface);
|
|
81
|
+
color: var(--on-surface); /* align-content: start is .page's own (base.css) — not restated here */
|
|
86
82
|
}
|
|
87
83
|
/* the reading block is the .page — or the .pages that holds several of them, a walk of words
|
|
88
84
|
(card.css). Behind a PEEKED sheet the words keep the strip's room under them, so whatever is down there
|
|
@@ -90,23 +86,22 @@
|
|
|
90
86
|
.step:has(> .sheet--peek) > :is(.page, .pages) { padding-bottom: var(--sheet-peek); }
|
|
91
87
|
.step > :is(.page, .pages) {
|
|
92
88
|
flex: 0 1 auto;
|
|
93
|
-
}
|
|
94
|
-
.step > :is(.page, .pages) {
|
|
95
89
|
min-height: 0;
|
|
96
|
-
margin: var(--_lead, 0) var(--screen-pad) 0; /* the screen's gap, moved in here from above the step; the inset, taken back from the bleed */
|
|
97
90
|
overflow-y: auto;
|
|
98
91
|
overscroll-behavior: contain;
|
|
99
92
|
}
|
|
93
|
+
/* a lone .page carries the margin a walk's .pages does not (its own .page children do, below) —
|
|
94
|
+
the screen's gap, moved in here from above the step; the inset, taken back from the bleed */
|
|
95
|
+
.step > .page { margin: var(--_lead, 0) var(--screen-pad) 0; }
|
|
100
96
|
|
|
101
97
|
/* a WALK (Pages of Page) — Lh 2026-09-23, third call: no top; the picture and the words are ONE run that scrolls up together
|
|
102
98
|
(the picture is never pinned). Each page starts at the screen's lead and ends with the same room under it — the lead as
|
|
103
99
|
padding above AND below — so the words begin near the middle and, when a big text size runs them long, scroll up clear.
|
|
104
100
|
The walk shows no scrollbar. */
|
|
105
|
-
.step > .pages {
|
|
106
|
-
.step > .pages > .page { padding-inline: var(--screen-pad); } /* the words keep the inset INSIDE it */
|
|
107
|
-
.step > .pages > .page { margin-top: var(--_lead, 0rem); } /* the lead is each PAGE's margin (15% with no top, the screen's gap under a bar): the words start there and scroll up to the box's edge */
|
|
108
|
-
.step > .pages::-webkit-scrollbar { display: none; }
|
|
101
|
+
.step > .pages { touch-action: pan-y; } /* pan-y: the walk scrolls itself up and down; a sideways swipe is the Walkthrough's (it turns the page) */ /* the scrolling box is the whole content: from the step's top edge, edge to edge — no margin, the default (Lh 2026-09-23) */
|
|
109
102
|
.step > .pages > .page {
|
|
103
|
+
padding-inline: var(--screen-pad); /* the words keep the inset INSIDE it */
|
|
104
|
+
margin-top: var(--_lead, 0rem); /* the lead is each PAGE's margin (15% with no top, the screen's gap under a bar): the words start there and scroll up to the box's edge */
|
|
110
105
|
padding-bottom: var(--bottom-h, 0rem); /* exactly the bottom layer (measured by Screen): a page scrolls ONLY when the layer would cover its words, and then just far enough to clear them — at 100% nothing scrolls (Lh 2026-09-23) */
|
|
111
106
|
}
|
|
112
107
|
|
package/css/theme.template.css
CHANGED
|
@@ -48,5 +48,6 @@
|
|
|
48
48
|
--card-1-bg --card-1-ink --card-2-bg --card-2-ink --card-3-bg --card-3-ink (three card tones)
|
|
49
49
|
--card-border --card-muted --card-2-muted
|
|
50
50
|
--accent --on-accent --action-bg --action-ink --action-border
|
|
51
|
-
--pos --neg --dot-a --dot-b
|
|
51
|
+
--pos --neg --dot-a --dot-b
|
|
52
|
+
--dim (0.7: how far secondary words fade on a dark card, a drawer, a tile's sub line — one share for all) */
|
|
52
53
|
}
|
package/css/tokens.css
CHANGED
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
--btn-h: calc(var(--tap-base) * 13 / 12); /* 52 button height */
|
|
49
49
|
--btn-xl-h: calc(var(--tap-base) * 11 / 6); /* 88 the one giant CTA */
|
|
50
50
|
--chip-h: calc(var(--tap-base) * 19 / 24); /* 38 chip height */
|
|
51
|
-
--bar-h: calc(var(--tap-base) * 4 / 3); /* 64 float bar, day cell
|
|
51
|
+
--bar-h: calc(var(--tap-base) * 4 / 3); /* 64 float bar, day cell */
|
|
52
52
|
--header-h: calc(var(--tap-base) * 5 / 4); /* 60 top bar — .topbar and .appbar alike */
|
|
53
53
|
--card-pad-rest: var(--sp-5); /* 20 a card's padding before any variant — .card publishes it as --card-pad; the sheet's peek strip is built from it where no card is in scope */
|
|
54
54
|
--card-gap-rest: var(--sp-4); /* 16 …and its gap */
|
|
@@ -93,8 +93,26 @@
|
|
|
93
93
|
|
|
94
94
|
/* ---- motion ---- */
|
|
95
95
|
--motion-sheet: 0.35s;
|
|
96
|
+
--motion-quick: 0.2s; /* a small state flip that isn't a press: a chevron turning, a popover/banner opening */
|
|
96
97
|
--motion-slide: 0.22s; /* a centred card sliding out and the next in (card.css) — quick, a page turn (Lh, 2026-09-12) */
|
|
97
98
|
--motion-flip: 0.45s; /* a postcard turning over (media.css) — slow enough to read as a card in the hand */
|
|
99
|
+
--dim: 0.7; /* secondary words dimmed on a ground whose muted ink does not fit (the dark card --3, a drawer, a tile's sub line): ONE share for all */
|
|
100
|
+
--rest: 0.6; /* an unpicked choice at rest: .day, .segment__item, .float-bar__item */
|
|
101
|
+
--faint: 0.3; /* further still: rails, far dots, unselected picker items */
|
|
102
|
+
--motion-press: 0.12s; /* a control giving under the finger and springing back (actions.css PRESS) */
|
|
103
|
+
--press-scale: 0.96; /* how far a finger-sized control gives — a share of its size */
|
|
104
|
+
--press-dim: 0.6; /* how far a card-wide one (a row, a summary line, a card) fades under the finger */
|
|
105
|
+
--press-shade: 0.93; /* how far something with a thing behind it (a peeked sheet, a postcard) darkens under the finger */
|
|
106
|
+
--off: 0.4; /* a disabled control's fade */
|
|
107
|
+
|
|
108
|
+
/* ---- z-index: the few layers that stack ABOVE ordinary content, low to high ---- */
|
|
109
|
+
--z-bar: 30; /* .action-bar, .float-bar — above .sheet-stack sheets (--level 1-5) */
|
|
110
|
+
--z-fab: 31; /* .fab — above the bars it floats near */
|
|
111
|
+
--z-top: 40; /* .appbar, a stage laid OVER its screen (.sheet-stage--over) — topmost, card animations never cover it */
|
|
112
|
+
|
|
113
|
+
/* ---- shared private sizes (not a knob: two components share the exact same
|
|
114
|
+
literal by design and must not drift apart) ---- */
|
|
115
|
+
--_cover-min-h: 22.5rem; /* .card--cover's min-height; --postcard-min-h falls back to it (media.css) */
|
|
98
116
|
|
|
99
117
|
/* ---- typography: one scale, rem so it follows the root ---- */
|
|
100
118
|
--font-ui: "PK Nonthaburi", -apple-system, system-ui, sans-serif; /* fonts.css ships it; the rest is the fallback while it loads */
|
|
@@ -209,7 +227,7 @@
|
|
|
209
227
|
|
|
210
228
|
/* ============================================================
|
|
211
229
|
REGISTERED TOKENS — the two sheet lengths are typed, so that
|
|
212
|
-
|
|
230
|
+
the Sheet component can read them back RESOLVED: getComputedStyle returns a
|
|
213
231
|
registered <length> in px and a <number> as a number, where an
|
|
214
232
|
unregistered custom property only ever reads back as its text
|
|
215
233
|
("calc(1.25rem + …)"). Drag-to-snap needs to know where the states
|
|
@@ -221,7 +239,7 @@
|
|
|
221
239
|
falls back to when its own declaration cannot resolve.
|
|
222
240
|
============================================================ */
|
|
223
241
|
@property --sheet-peek { syntax: "<length>"; inherits: true; initial-value: 0px; }
|
|
224
|
-
@property --sheet-head-h { syntax: "<length>"; inherits: true; initial-value: 48px; }
|
|
225
|
-
@property --_lead { syntax: "<length>"; inherits: true; initial-value: 0px; } /* the room above a step's words: registered so a cqh share (a no-bar step, 15% of the SCREEN) resolves where it is declared — on the step, against the screen — not on the words, against the step */
|
|
242
|
+
@property --sheet-head-h { syntax: "<length>"; inherits: true; initial-value: 48px; } /* the sheet head's floor (sheet.css) — registered so the Sheet reads it resolved */
|
|
243
|
+
@property --_lead { syntax: "<length>"; inherits: true; initial-value: 0px; } /* the room above a step's words: registered so a cqh share (a no-bar step, 15% of the SCREEN) resolves where it is declared — on the step, against the screen — not on the words, against the step */
|
|
226
244
|
@property --sheet-half { syntax: "<number>"; inherits: true; initial-value: 0.5; }
|
|
227
245
|
@property --sheet-3q { syntax: "<number>"; inherits: true; initial-value: 0.25; }
|
package/dist/actions/Btn.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export interface BtnProps extends Omit<ComponentProps<'button'>, 'form'> {
|
|
|
19
19
|
* In a CardFoot up to four share the line; in an ActionBar it takes the width. An Icon xs may lead or trail the label.
|
|
20
20
|
*/
|
|
21
21
|
export declare function Btn({ primary, quiet, block, form, xl, href, className, type, ...rest }: BtnProps): import("react").DetailedReactHTMLElement<{
|
|
22
|
+
onChange?: import("react").ChangeEventHandler<HTMLButtonElement, Element> | undefined;
|
|
22
23
|
name?: string | undefined | undefined;
|
|
23
24
|
slot?: string | undefined | undefined;
|
|
24
25
|
style?: import("react").CSSProperties | undefined;
|
|
@@ -104,7 +105,6 @@ export declare function Btn({ primary, quiet, block, form, xl, href, className,
|
|
|
104
105
|
onFocusCapture?: import("react").FocusEventHandler<HTMLButtonElement> | undefined;
|
|
105
106
|
onBlur?: import("react").FocusEventHandler<HTMLButtonElement> | undefined;
|
|
106
107
|
onBlurCapture?: import("react").FocusEventHandler<HTMLButtonElement> | undefined;
|
|
107
|
-
onChange?: import("react").ChangeEventHandler<HTMLButtonElement, Element> | undefined;
|
|
108
108
|
onChangeCapture?: import("react").ChangeEventHandler<HTMLButtonElement, Element> | undefined;
|
|
109
109
|
onBeforeInput?: import("react").InputEventHandler<HTMLButtonElement> | undefined;
|
|
110
110
|
onBeforeInputCapture?: import("react").InputEventHandler<HTMLButtonElement> | undefined;
|
package/dist/actions/Dropdown.js
CHANGED
|
@@ -1,18 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Children, createContext, isValidElement, useContext, useRef
|
|
2
|
+
import { Children, createContext, isValidElement, useContext, useRef } from 'react';
|
|
3
|
+
import { useControlled } from '../state.js';
|
|
3
4
|
import { cx } from '../cx.js';
|
|
4
5
|
import { Icon } from '../type/Icon.js';
|
|
5
6
|
/* what a Menu tells its items: the value it holds (so the matching item marks itself current) and how to pick one */
|
|
6
7
|
const MenuContext = createContext(null);
|
|
7
8
|
/* a menu's value is controlled (`value` + `onChange`) or its own (`defaultValue`) — like an input */
|
|
8
|
-
|
|
9
|
-
const [inner, setInner] = useState(defaultValue);
|
|
10
|
-
const current = value ?? inner;
|
|
11
|
-
const pick = (next) => { if (value === undefined)
|
|
12
|
-
setInner(next); if (next !== current)
|
|
13
|
-
onChange?.(next); };
|
|
14
|
-
return [current, pick];
|
|
15
|
-
}
|
|
9
|
+
const useValue = (value, defaultValue, onChange) => useControlled(value, defaultValue, onChange);
|
|
16
10
|
/**
|
|
17
11
|
* Dropdown — THE select: a pill trigger + its Menu popover anchored under it (native popover: light dismiss, Esc). Never a native
|
|
18
12
|
* `<select>`. ONE component, like `<select>` is — the pill and the panel are its own anatomy. It holds a VALUE, controlled like an
|
package/dist/actions/Fab.d.ts
CHANGED
|
@@ -5,5 +5,5 @@ export interface FabProps extends ComponentProps<'button'> {
|
|
|
5
5
|
icon?: IconName;
|
|
6
6
|
invert?: boolean;
|
|
7
7
|
}
|
|
8
|
-
/** Fab — the square floating action at the bottom-right of a stage or screen (above the bar). */
|
|
8
|
+
/** Fab — the square floating action at the bottom-right of a stage or screen (above the bar): an IconBtn with the fab's place. */
|
|
9
9
|
export declare function Fab({ label, icon, invert, className, children, ...rest }: FabProps): import("react").JSX.Element;
|
package/dist/actions/Fab.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cx } from '../cx.js';
|
|
3
3
|
import { Icon } from '../type/Icon.js';
|
|
4
|
-
|
|
4
|
+
import { IconBtn } from './IconBtn.js';
|
|
5
|
+
/** Fab — the square floating action at the bottom-right of a stage or screen (above the bar): an IconBtn with the fab's place. */
|
|
5
6
|
export function Fab({ label, icon = 'plus', invert = true, className, children, ...rest }) {
|
|
6
|
-
return
|
|
7
|
+
return _jsx(IconBtn, { label: label, invert: invert, className: cx('fab', className), ...rest, children: children ?? _jsx(Icon, { name: icon }) });
|
|
7
8
|
}
|