studio-engine 0.61.1 → 0.61.2
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.
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e8e859fc4ea59dafad01b2aef524f8ff75bb2b5040bc05611ac17eec335c5c0a
|
|
4
|
+
data.tar.gz: ca4d9a0ed867017686c50d329190ef26d7488ea28349fa65996bd8b859ff4eee
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 805ad1e2f8d05504bb4ca7e782ab27fab96589dbe3acd5714502c24b0803de69631241a1a3374da1d7f92a762b1c21f6eb4122ba7c6cdafc3231844f2f03b479
|
|
7
|
+
data.tar.gz: 5cc030a1e38828fc0db6212f8686f6438253f00adf8a84dfa26faad576bf86fdda137b2d806e79d78a241b2b21ac706c39de6f99b694eedccfa034ec37669012
|
data/CHANGELOG.md
CHANGED
|
@@ -233,6 +233,31 @@ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This pro
|
|
|
233
233
|
|
|
234
234
|
### Fixed
|
|
235
235
|
|
|
236
|
+
- **The age gate's back link now returns the date the person already entered.**
|
|
237
|
+
`blocks/_age_gate`'s "Update your Birthday" swapped back to `blocks/_birthday`
|
|
238
|
+
with an EMPTY props object, discarding the `dobYear`/`dobMonth`/`dobDay` parts
|
|
239
|
+
the birthday factory had just handed across the store — and the factory started
|
|
240
|
+
its three fields at `""` and never read them anyway. So the correction path came
|
|
241
|
+
back BLANK: a mistyped year cost all three picks, on a card whose own header
|
|
242
|
+
comment promised "a correction, not a restart".
|
|
243
|
+
|
|
244
|
+
Both sides of the seam moved. `back()` forwards the three date parts — and only
|
|
245
|
+
those three, deliberately: `minAge`, `state` and `message` describe the refusal,
|
|
246
|
+
and `validates` is load-bearing by its ABSENCE (the style guide specimen reads an
|
|
247
|
+
absent prop as validating, and a forwarded stale one would let the refusal pick
|
|
248
|
+
the next card's mode). `window.birthdayModal` gained an `init` that re-picks the
|
|
249
|
+
three selects from the props of the modal entry it mounted in, clamping a day
|
|
250
|
+
that the restored month cannot hold.
|
|
251
|
+
|
|
252
|
+
**The gate is not weakened.** Restoring the date restores the DATE and never the
|
|
253
|
+
verdict: the card comes back submittable and the app's endpoint re-decides on the
|
|
254
|
+
next submit exactly as it did on the first. `e2e/birthday_gate.spec.js` asserts a
|
|
255
|
+
restored under-age date is refused again.
|
|
256
|
+
|
|
257
|
+
**No consumer action.** A host that renders `blocks/_age_gate` and
|
|
258
|
+
`studio/_birthday_assets` gets this by upgrading; nothing in the call signature
|
|
259
|
+
changed and no host wiring moves.
|
|
260
|
+
|
|
236
261
|
- **The Geo signpost now reaches every app whose admin chrome the engine owns.**
|
|
237
262
|
The row added last release went into `components/_admin_dropdown` alone, on the
|
|
238
263
|
premise that the shared dropdown reaches every app from one change. It does
|
|
@@ -29,6 +29,13 @@
|
|
|
29
29
|
age-gate card instead. `_finish` is unchanged: the success path still flips
|
|
30
30
|
session.ageVerified and dispatches `age-verified`, which is the hook consuming
|
|
31
31
|
apps already listen on, so nothing downstream had to change.
|
|
32
|
+
|
|
33
|
+
AND THE HANDOFF RETURNS (2026-08-26). `_reject` sends dobYear/dobMonth/dobDay
|
|
34
|
+
across the store; the gate card's back() hands the same three parts back; and
|
|
35
|
+
`init` re-picks the three selects from them, so the correction the gate card
|
|
36
|
+
offers costs one scroll rather than all three fields. The date is restored,
|
|
37
|
+
never the VERDICT: the card comes back submittable and the app's endpoint
|
|
38
|
+
re-decides on the next submit exactly as it did on the first.
|
|
32
39
|
%>
|
|
33
40
|
<script>
|
|
34
41
|
(function () {
|
|
@@ -89,6 +96,56 @@
|
|
|
89
96
|
if (this.day && parseInt(this.day, 10) > this.dayOptions.length) this.day = "";
|
|
90
97
|
this.error = "";
|
|
91
98
|
},
|
|
99
|
+
// THE RETURN TRIP. _reject writes dobYear/dobMonth/dobDay onto the store
|
|
100
|
+
// on the way out to the age-gate card, and that card's back() hands the
|
|
101
|
+
// same three parts straight back — so a card mounted from a return trip
|
|
102
|
+
// finds the person's date on its own modal entry and re-picks the three
|
|
103
|
+
// selects. Without this the factory started at "" whatever it was handed,
|
|
104
|
+
// and a mistyped year cost all three fields (fixed 2026-08-26).
|
|
105
|
+
//
|
|
106
|
+
// Read off the STORE rather than taken as an opt: that is where this
|
|
107
|
+
// factory already meets the store (_reject writes to the same object
|
|
108
|
+
// through the same guard), the ERB locals in blocks/_birthday are
|
|
109
|
+
// server-side and cannot carry a client value anyway, and it means a
|
|
110
|
+
// consuming app that renders the card needs no change at all.
|
|
111
|
+
//
|
|
112
|
+
// STRINGS, because that is what the selects produce: the options render
|
|
113
|
+
// :value="m.n" — a number stringified by the DOM — and x-model writes
|
|
114
|
+
// that string back. Seeding a Number would leave the field holding a type
|
|
115
|
+
// the person's own pick never produces.
|
|
116
|
+
_returnedDob() {
|
|
117
|
+
var props;
|
|
118
|
+
try {
|
|
119
|
+
var entry = Alpine.store(this.store).current();
|
|
120
|
+
props = (entry && entry.props) || {};
|
|
121
|
+
} catch (e) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
var y = parseInt(props.dobYear, 10),
|
|
125
|
+
m = parseInt(props.dobMonth, 10),
|
|
126
|
+
d = parseInt(props.dobDay, 10);
|
|
127
|
+
if (!y || !m || !d) return null;
|
|
128
|
+
return { year: String(y), month: String(m), day: String(d) };
|
|
129
|
+
},
|
|
130
|
+
// Alpine calls init() on the data object at MOUNT, synchronously, inside
|
|
131
|
+
// the x-data directive and before it walks the three <select>s below
|
|
132
|
+
// (Alpine 3.16.1 as vendored: `a.init && T(t, a.init)`). So this is the
|
|
133
|
+
// fields' initial state rather than a later mutation of them, and x-model
|
|
134
|
+
// paints the selects from it. Measured in chromium: all three hold the
|
|
135
|
+
// restored values on the FIRST frame the card exists, six runs out of six
|
|
136
|
+
// — no deferral needed, and e2e/birthday_gate.spec.js is what watches it.
|
|
137
|
+
init() {
|
|
138
|
+
var dob = this._returnedDob();
|
|
139
|
+
if (!dob) return;
|
|
140
|
+
this.year = dob.year;
|
|
141
|
+
this.month = dob.month;
|
|
142
|
+
// Day LAST, and clamped: dayOptions is only the restored month's list
|
|
143
|
+
// once month and year are set, and an impossible pair from a hand-built
|
|
144
|
+
// props bag (Feb 30) must land empty rather than leave the select
|
|
145
|
+
// holding a value its own options do not contain — which would read as
|
|
146
|
+
// complete and submit a date nobody picked.
|
|
147
|
+
this.day = parseInt(dob.day, 10) <= this.dayOptions.length ? dob.day : "";
|
|
148
|
+
},
|
|
92
149
|
// Success path: flip a session flag if present, close via the app's store,
|
|
93
150
|
// and let the app resume its own flow (the entry gate listens for this).
|
|
94
151
|
_finish() {
|
|
@@ -16,7 +16,14 @@
|
|
|
16
16
|
the back link — the thing they might NEED. A wrong birthday is an ordinary
|
|
17
17
|
typo (a mis-picked year is one scroll away), and a gate with no
|
|
18
18
|
way back turns a typo into a locked door. swap()s back to the
|
|
19
|
-
birthday card, so
|
|
19
|
+
birthday card CARRYING THE DATE, so a mistyped year costs one
|
|
20
|
+
scroll and not all three fields. That is what makes this a
|
|
21
|
+
correction rather than a restart: back() forwards the dobYear /
|
|
22
|
+
dobMonth / dobDay parts _reject handed across the store on the
|
|
23
|
+
way in, and the birthday factory seeds its three selects from
|
|
24
|
+
them. Until 2026-08-26 it swapped with an EMPTY props object and
|
|
25
|
+
the card came back blank, which is the restart this paragraph
|
|
26
|
+
disclaimed.
|
|
20
27
|
|
|
21
28
|
DELIBERATELY NOT DISMISSIBLE-BY-DEFAULT-ONLY: the host still decides via
|
|
22
29
|
props.dismissible at open() time, exactly like every other card. What this
|
|
@@ -146,7 +153,26 @@
|
|
|
146
153
|
// sibling cards that poll: modals/_web3_step_up, blocks/_cta_redirect,
|
|
147
154
|
// blocks/_seeds_bar.
|
|
148
155
|
destroy() { this.stop(); },
|
|
149
|
-
|
|
156
|
+
// THE DATE RIDES BACK. _reject put these three parts on the store on the
|
|
157
|
+
// way here so this card could say WHEN; handing them back is what makes
|
|
158
|
+
// the return trip a correction instead of a blank form. This swapped with
|
|
159
|
+
// an empty object until 2026-08-26, and a mistyped year cost all three
|
|
160
|
+
// picks.
|
|
161
|
+
//
|
|
162
|
+
// THE THREE PARTS ONLY, deliberately not the whole props bag. minAge,
|
|
163
|
+
// state and message describe the REFUSAL: message would land as an error
|
|
164
|
+
// line on a card nobody has submitted yet, and `validates` is load-bearing
|
|
165
|
+
// by its ABSENCE — the style guide specimen reads an absent prop as
|
|
166
|
+
// validating, so forwarding a stale one would let this card pick the next
|
|
167
|
+
// card's mode (style/modals/_birthday.html.erb).
|
|
168
|
+
back() {
|
|
169
|
+
var p = this.props;
|
|
170
|
+
$store.<%= modal_store %>.swap('<%= j birthday_modal_id.to_s %>', {
|
|
171
|
+
dobYear: p.dobYear || null,
|
|
172
|
+
dobMonth: p.dobMonth || null,
|
|
173
|
+
dobDay: p.dobDay || null
|
|
174
|
+
});
|
|
175
|
+
}
|
|
150
176
|
}"
|
|
151
177
|
<% if countdown %>x-init="start()"<% end %>
|
|
152
178
|
class="relative">
|
|
@@ -211,7 +237,9 @@
|
|
|
211
237
|
|
|
212
238
|
<% if birthday_modal_id.present? %>
|
|
213
239
|
<%# The correction path. A mis-picked year is one scroll away from a right
|
|
214
|
-
one, and without this the typo is indistinguishable from the verdict.
|
|
240
|
+
one, and without this the typo is indistinguishable from the verdict.
|
|
241
|
+
back() carries the date across, so what comes back is the same three
|
|
242
|
+
picks with the wrong one still selected. %>
|
|
215
243
|
<button type="button" @click="back()"
|
|
216
244
|
class="block mx-auto mt-3 text-sm text-secondary hover:text-heading transition underline-offset-2 hover:underline">
|
|
217
245
|
<%= back_label %>
|
|
@@ -23,11 +23,17 @@
|
|
|
23
23
|
|
|
24
24
|
Why absent is not "no bar": the only card that can REACH the age gate is the
|
|
25
25
|
validating one — the no-bar card carries no min_age, so the factory's _reject
|
|
26
|
-
never fires. So every arrival with no
|
|
27
|
-
and `back()`
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
never fires. So every arrival with no `validates` is a return trip from the
|
|
27
|
+
gate, and `back()` never sends one: it forwards the dobYear/dobMonth/dobDay
|
|
28
|
+
parts and NOTHING ELSE, deliberately, so the refusal cannot pick this
|
|
29
|
+
specimen's mode (blocks/_age_gate.html.erb). Reading undefined as falsy sent
|
|
30
|
+
that return trip to the NO-BAR card, where resubmitting the SAME under-age
|
|
31
|
+
date was accepted — the guide demonstrating an age gate being bypassed.
|
|
32
|
+
Caught in review, 2026-08-25.
|
|
33
|
+
|
|
34
|
+
So the default is still load-bearing, and it is load-bearing in the same way
|
|
35
|
+
after the gate started carrying the date back (2026-08-26): the props bag on
|
|
36
|
+
a return trip is no longer empty, but `validates` is still absent from it.
|
|
31
37
|
|
|
32
38
|
The engine primitive is right and is NOT changed: in a real host the mode
|
|
33
39
|
comes from ERB locals, not from a prop, so this is a two-mode SPECIMEN's
|
data/lib/studio/version.rb
CHANGED