@justai/cuts 0.143.0 → 0.145.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/package.json +2 -2
- package/src/ConfirmSheet.astro +20 -1
- package/src/Toolbar.astro +13 -2
- package/src/behaviour/toolbar.ts +9 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@justai/cuts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.145.0",
|
|
4
4
|
"description": "A persona's named parts — the page shell that holds them, and the cuts themselves.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"repository": {
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"access": "public"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@justai/core": "^0.
|
|
44
|
+
"@justai/core": "^0.38.0",
|
|
45
45
|
"@justai/ui": "^0.26.0",
|
|
46
46
|
"@justai/atrium": "^0.1.9"
|
|
47
47
|
},
|
package/src/ConfirmSheet.astro
CHANGED
|
@@ -16,6 +16,13 @@ import "./ground.css";
|
|
|
16
16
|
// something can end, the safe choice wears the most confident face. iOS system red for
|
|
17
17
|
// destruction. This is /me's "Erase everything?".
|
|
18
18
|
//
|
|
19
|
+
// A THIRD CHOICE, when the safe answer is not "do nothing" (`safeActionLabel`) — Apple's own
|
|
20
|
+
// multi-action sheet. Some destructive questions have a way OUT of the loss rather than only a
|
|
21
|
+
// way around it: "your work isn't saved yet" is answered best by saving it, not by cancelling and
|
|
22
|
+
// then hunting for the Save button. That action joins the grouped card ABOVE the destructive one,
|
|
23
|
+
// because a sheet reads top to bottom and the preserving path is the one to meet first. Cancel
|
|
24
|
+
// stays detached and boldest — the anatomy does not change, it gains one row.
|
|
25
|
+
//
|
|
19
26
|
// ASK (`ask` prop) — the alert/ATT genre, for INVITATIONS: both choices live INSIDE the grouped
|
|
20
27
|
// card, stacked; the action wears the preferred bold face (Apple's preferredAction) and takes
|
|
21
28
|
// the focus; the safe choice sits beneath it in calm regular weight — equal size, equal tap,
|
|
@@ -61,10 +68,19 @@ interface Props {
|
|
|
61
68
|
* remembered as a choice, so the chosen no is stored while a slip-away stores nothing and the
|
|
62
69
|
* ask returns next visit. */
|
|
63
70
|
cancelValue?: string;
|
|
71
|
+
/** Optional THIRD choice: an action that PRESERVES rather than ends, placed above the main action
|
|
72
|
+
* inside the grouped card and painted as the preferred path. Omit it and the sheet is exactly
|
|
73
|
+
* what it always was — same DOM, same ids, same returnValues. */
|
|
74
|
+
safeActionLabel?: string;
|
|
75
|
+
/** What returnValue that third choice reports. Default "safe": three answers need three words. */
|
|
76
|
+
safeActionValue?: string;
|
|
64
77
|
/** Anything else (data-* attributes, aria overrides) lands on the <dialog> itself. */
|
|
65
78
|
[key: string]: unknown;
|
|
66
79
|
}
|
|
67
|
-
const {
|
|
80
|
+
const {
|
|
81
|
+
id, title, body, actionLabel, cancelLabel, destructive = false, ask = false, cancelValue = "",
|
|
82
|
+
safeActionLabel, safeActionValue = "safe", ...rest
|
|
83
|
+
} = Astro.props;
|
|
68
84
|
---
|
|
69
85
|
|
|
70
86
|
<dialog class="confirm" id={id} aria-labelledby={title ? `${id}-t` : `${id}-b`} aria-describedby={`${id}-b`} {...rest}>
|
|
@@ -79,6 +95,9 @@ const { id, title, body, actionLabel, cancelLabel, destructive = false, ask = fa
|
|
|
79
95
|
on a closed dialog, noise about a focus that was never going to happen. Focus is the
|
|
80
96
|
OPENER's job now, at showModal time: ask → the invitation (CONSENT_JS does it),
|
|
81
97
|
destructive → the cancel (the consumer does it). The genre decides, as before. */}
|
|
98
|
+
{safeActionLabel && (
|
|
99
|
+
<button class="confirm-act preferred" id={`${id}-safe`} value={safeActionValue}>{safeActionLabel}</button>
|
|
100
|
+
)}
|
|
82
101
|
<button class:list={["confirm-act", { destructive, preferred: ask }]} id={`${id}-act`} value="confirm">{actionLabel}</button>
|
|
83
102
|
{ask && <button class="confirm-act quiet" id={`${id}-cancel`} value={cancelValue} formnovalidate>{cancelLabel}</button>}
|
|
84
103
|
</div>
|
package/src/Toolbar.astro
CHANGED
|
@@ -88,6 +88,17 @@ interface Props {
|
|
|
88
88
|
// that nothing keeps in step. The strip is one line and its vocabulary should be one kind of
|
|
89
89
|
// thing — names or sections, not one of each — so the API says so out loud.
|
|
90
90
|
kernelTitle?: string;
|
|
91
|
+
/**
|
|
92
|
+
* Which cut a visit with no hash opens on. Defaults to the kernel, which is right for every
|
|
93
|
+
* persona whose kernel is the thing it does.
|
|
94
|
+
*
|
|
95
|
+
* app.zone is the exception this exists for: its kernel is a catalogue of the OTHER personas, so
|
|
96
|
+
* landing there opens the house on a list of its rooms and scrolls the mark, the wordmark and the
|
|
97
|
+
* sentence that say what app.zone IS past before anyone reads them. Passed to `personaScroll`
|
|
98
|
+
* through a data attribute, the same way the two title strings already travel — this cut renders
|
|
99
|
+
* markup, and the behaviour reads the markup rather than being handed a closure.
|
|
100
|
+
*/
|
|
101
|
+
landOn?: string;
|
|
91
102
|
postsTitle?: string;
|
|
92
103
|
|
|
93
104
|
// queries: toolbar shows a generic person icon · the profile icon is not my persona ·
|
|
@@ -160,7 +171,7 @@ interface Props {
|
|
|
160
171
|
import BackToZone from "./BackToZone.astro";
|
|
161
172
|
const {
|
|
162
173
|
sectionsLabel, profileLabel, kernelLabel, postsLabel,
|
|
163
|
-
files = true, filesLabel = "Files", kernelTitle, postsTitle, avatar = "/icon.svg", parent,
|
|
174
|
+
files = true, filesLabel = "Files", kernelTitle, postsTitle, landOn, avatar = "/icon.svg", parent,
|
|
164
175
|
} = Astro.props;
|
|
165
176
|
// A child's row answers UP to its parent, not out to the zone, and has no stream of its own — so
|
|
166
177
|
// both default off the moment `parent` is given, rather than each consumer remembering to say so.
|
|
@@ -172,7 +183,7 @@ import AuthMount from "./AuthMount.astro";
|
|
|
172
183
|
make this script inline and it has an import. Astro drops an attribute whose value is undefined,
|
|
173
184
|
so a persona that passes neither leaves no trace in the markup at all. -->
|
|
174
185
|
<div class="tb-slot">
|
|
175
|
-
<header class="toolbar" data-kernel-title={kernelTitle} data-posts-title={postsTitle}>
|
|
186
|
+
<header class="toolbar" data-kernel-title={kernelTitle} data-posts-title={postsTitle} data-land-on={landOn}>
|
|
176
187
|
<div class="tb-row">
|
|
177
188
|
<div class="tb-left">
|
|
178
189
|
{home && <BackToZone apex={apex} />}
|
package/src/behaviour/toolbar.ts
CHANGED
|
@@ -82,8 +82,13 @@ document.querySelector(".toolbar")?.addEventListener(
|
|
|
82
82
|
const bar = document.querySelector(".toolbar") as HTMLElement | null;
|
|
83
83
|
const kt = bar?.dataset.kernelTitle;
|
|
84
84
|
const pt = bar?.dataset.postsTitle;
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
// `landOn` travels as a data attribute for the same reason the two titles do: this file runs in a
|
|
86
|
+
// page it did not render, so the markup is the interface. Undefined when the attribute is absent,
|
|
87
|
+
// which is the option's default — the kernel.
|
|
88
|
+
const landOn = bar?.dataset.landOn;
|
|
89
|
+
personaScroll({
|
|
90
|
+
...(kt && pt
|
|
87
91
|
? { titleFor: (id: string) => (id === "kernel" ? kt : id === "posts" ? pt : "") }
|
|
88
|
-
:
|
|
89
|
-
)
|
|
92
|
+
: {}),
|
|
93
|
+
...(landOn ? { landOn } : {}),
|
|
94
|
+
});
|