studio-engine 0.61.0 → 0.61.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.
- checksums.yaml +4 -4
- data/app/views/style/_modals.html.erb +67 -0
- data/app/views/style/modals/_ds_buy_entry_token.html.erb +40 -0
- data/app/views/style/modals/_ds_cdp_ramp.html.erb +41 -0
- data/app/views/style/modals/_ds_newsletter_success.html.erb +67 -0
- data/lib/studio/version.rb +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0082dfd62bcd08f1a3a540bc351c6171c27a563d85aa50d7492c1f0bb1f0271a'
|
|
4
|
+
data.tar.gz: 920156a74de7a1bbc1953a29ef01cac6b79c7d5aaad81a9f223d64d72924702d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ff49493b81e76496c8977d2403d1b3855e8146db9f4c452a0f81707bf2aebca3c8607202d90e3c91c91c5e8e56b152b5113750b3c051dbf83c5e9340484406ea
|
|
7
|
+
data.tar.gz: 525b285e971042834e9761b78cd359b7fc24a431bdf6e06ba6a1082fd80603ae1b7f7e1f8fbb68d69d22a174da53c429a6da505b4c534066df03b76bf7d3fbc3
|
|
@@ -390,6 +390,15 @@
|
|
|
390
390
|
<template x-if="$store.dsModals.current().id === 'ds-onramp-hub'">
|
|
391
391
|
<div><%= render "style/modals/ds_onramp_hub" %></div>
|
|
392
392
|
</template>
|
|
393
|
+
<template x-if="$store.dsModals.current().id === 'ds-buy-entry-token'">
|
|
394
|
+
<div><%= render "style/modals/ds_buy_entry_token" %></div>
|
|
395
|
+
</template>
|
|
396
|
+
<template x-if="$store.dsModals.current().id === 'ds-cdp-ramp'">
|
|
397
|
+
<div><%= render "style/modals/ds_cdp_ramp" %></div>
|
|
398
|
+
</template>
|
|
399
|
+
<template x-if="$store.dsModals.current().id === 'ds-newsletter-success'">
|
|
400
|
+
<div><%= render "style/modals/ds_newsletter_success" %></div>
|
|
401
|
+
</template>
|
|
393
402
|
<template x-if="$store.dsModals.current().id === 'rate-limit-general'">
|
|
394
403
|
<div><%= render "style/modals/rate_limit_general" %></div>
|
|
395
404
|
</template>
|
|
@@ -935,6 +944,28 @@
|
|
|
935
944
|
</div>
|
|
936
945
|
<% end %>
|
|
937
946
|
|
|
947
|
+
<%# ds-newsletter-success — the STANDALONE celebration, and its two forks. %>
|
|
948
|
+
<%= render layout: "style/modal_specimen", locals: {
|
|
949
|
+
label: "Subscribed! (standalone)",
|
|
950
|
+
reference: %(the standalone newsletter celebration (style/modals/_ds_newsletter_success) — turf-monster's modals/_newsletter_success. Distinct from the card above, which is the leveling activity celebrating IN PLACE on the card the person was already on; this one arrives on its own — swapped in from the subscribe modal, or opened from the /account newsletter row — so it has to carry its own way forward. TWO FORKS, NEITHER VISIBLE IN THE MARKUP, which is why it is carded separately rather than folded in. THE SEEDS BAR IS FIRST-JOIN ONLY: a re-subscribe earns nothing, and the card HIDES the bar rather than showing a flat "0 seeds", which would read to the person as a bug about their own account rather than an accurate zero. THE CTA IS SERVER-DECIDED: with the username quest still open (current_user.next_quest == :username) the button nudges straight into it, otherwise it sends them to browse contests — showing only one of those hides the funnel this celebration doubles as. Both are toggles here so the cabinet can walk all four combinations; in the app the CTA fork is SERVER-rendered, precisely so the button never flashes the wrong option at someone whose quest is already done. Open with $store.dsModals.open('ds-newsletter-success', { firstJoin: true, questOpen: true })),
|
|
951
|
+
card_data: "opts: { firstJoin: true, questOpen: true }",
|
|
952
|
+
toggles: [{ model: "opts.firstJoin", label: "First join" },
|
|
953
|
+
{ model: "opts.questOpen", label: "Quest open" }],
|
|
954
|
+
open_expr: "$store.dsModals.open('ds-newsletter-success', { firstJoin: opts.firstJoin, questOpen: opts.questOpen })",
|
|
955
|
+
glow_when: ds_glow.call("ds-newsletter-success") } do %>
|
|
956
|
+
<div class="pointer-events-none w-40 rounded-lg bg-surface border border-subtle shadow p-4 text-center space-y-2">
|
|
957
|
+
<div class="text-2xl leading-none">🌱</div>
|
|
958
|
+
<span class="block h-2 w-20 mx-auto rounded" style="background: var(--color-text); opacity: .18"></span>
|
|
959
|
+
<%# the first-join seeds bar %>
|
|
960
|
+
<span class="flex gap-1">
|
|
961
|
+
<span class="flex-1 h-2 rounded" style="background: var(--color-cta)"></span>
|
|
962
|
+
<span class="flex-1 h-2 rounded" style="background: var(--color-cta); opacity:.35"></span>
|
|
963
|
+
<span class="flex-1 h-2 rounded" style="background: var(--color-cta); opacity:.18"></span>
|
|
964
|
+
</span>
|
|
965
|
+
<span class="block h-4 w-full rounded" style="background: var(--color-cta)"></span>
|
|
966
|
+
</div>
|
|
967
|
+
<% end %>
|
|
968
|
+
|
|
938
969
|
<%# THE WAY OUT. The three cards above walk a user IN; a section that only
|
|
939
970
|
ever demonstrates opt-in is showing the happy half of a flow, not the
|
|
940
971
|
flow. These two are the exit, and they are a PAIR — the confirm card
|
|
@@ -1304,6 +1335,42 @@
|
|
|
1304
1335
|
</div>
|
|
1305
1336
|
<% end %>
|
|
1306
1337
|
|
|
1338
|
+
<%# ds-buy-entry-token — reached with a lineup picked and no way to pay. %>
|
|
1339
|
+
<%= render layout: "style/modal_specimen", locals: {
|
|
1340
|
+
label: "Buy entry token",
|
|
1341
|
+
reference: %(the entry-token purchase (style/modals/_ds_buy_entry_token) — turf-monster's modals/_buy_entry_token, built from blocks/_close_x and two blocks/_rail_row. Reached when a player has picked a lineup and has no way to pay for it, which is why the copy says the lineup is SAVED: losing their picks is the one thing they are afraid of at that moment. The ranking is a PRODUCT decision rather than a visual one — Coinflow leads and carries the "New" badge because it mints a spendable entry token directly, the shortest path from here to being in the contest, while Stripe swaps into the auth wizard's tokens picker, the older and longer path, and defers. Open with $store.dsModals.open('ds-buy-entry-token')),
|
|
1342
|
+
open_expr: "$store.dsModals.open('ds-buy-entry-token')",
|
|
1343
|
+
glow_when: ds_glow.call("ds-buy-entry-token"),
|
|
1344
|
+
disabled: !web3_on, openable: true } do %>
|
|
1345
|
+
<div class="pointer-events-none w-40 rounded-lg bg-surface border border-subtle shadow p-4 space-y-2">
|
|
1346
|
+
<span class="block h-2 w-24 mx-auto rounded" style="background: var(--color-text); opacity: .18"></span>
|
|
1347
|
+
<span class="flex items-center gap-1.5 rounded-md p-1.5" style="border: 2px solid var(--color-primary)">
|
|
1348
|
+
<span class="block h-4 w-4 rounded" style="background: var(--color-cta)"></span>
|
|
1349
|
+
<span class="block h-1.5 flex-1 rounded" style="background: var(--color-text); opacity: .3"></span>
|
|
1350
|
+
</span>
|
|
1351
|
+
<span class="flex items-center gap-1.5 rounded-md p-1.5 border border-subtle">
|
|
1352
|
+
<span class="block h-4 w-4 rounded" style="background: var(--color-text); opacity: .25"></span>
|
|
1353
|
+
<span class="block h-1.5 flex-1 rounded" style="background: var(--color-text); opacity: .18"></span>
|
|
1354
|
+
</span>
|
|
1355
|
+
</div>
|
|
1356
|
+
<% end %>
|
|
1357
|
+
|
|
1358
|
+
<%# ds-cdp-ramp — ONE of thirteen states, and the card says so. %>
|
|
1359
|
+
<%= render layout: "style/modal_specimen", locals: {
|
|
1360
|
+
label: "Coinbase ramp (preflight)",
|
|
1361
|
+
reference: %(the Coinbase ramp's BUY PREFLIGHT (style/modals/_ds_cdp_ramp) — turf-monster's modals/_cdp_ramp. DELIBERATELY PARTIAL: that modal is a TWO-FLOW step machine (buy and cash-out) across THIRTEEN states — preflight, opening, waiting, awaiting-cdp, send, settling and the rest — and this cards exactly one of them, the buy preflight, which is the state both funding cards hand off to and therefore the only one a player reaches without already being mid-flow. The other twelve are uncarded BY DECISION (operator, 2026-08-26), which is a different thing from an oversight — a cabinet that shows one state of a thirteen-state machine without admitting it teaches a reader that the machine is simpler than it is. /tasks/port-cdp-ramp-specimen holds the full state map if that decision reverses. Open with $store.dsModals.open('ds-cdp-ramp')),
|
|
1362
|
+
open_expr: "$store.dsModals.open('ds-cdp-ramp')",
|
|
1363
|
+
glow_when: ds_glow.call("ds-cdp-ramp"),
|
|
1364
|
+
disabled: !web3_on, openable: true } do %>
|
|
1365
|
+
<div class="pointer-events-none w-40 rounded-lg bg-surface border border-subtle shadow p-4 text-center space-y-2 relative">
|
|
1366
|
+
<span class="absolute top-1 right-2 text-secondary leading-none">×</span>
|
|
1367
|
+
<span class="block h-2 w-28 mx-auto rounded" style="background: var(--color-text); opacity: .18"></span>
|
|
1368
|
+
<span class="block h-1.5 w-full rounded" style="background: var(--color-text); opacity: .12"></span>
|
|
1369
|
+
<span class="block h-1.5 w-24 mx-auto rounded" style="background: var(--color-text); opacity: .12"></span>
|
|
1370
|
+
<span class="block h-4 w-full rounded" style="background: var(--color-cta)"></span>
|
|
1371
|
+
</div>
|
|
1372
|
+
<% end %>
|
|
1373
|
+
|
|
1307
1374
|
<%# Entry confirmed — the GENERIC web3 celebration (tx link + heading + drain
|
|
1308
1375
|
CTA). seedsEarned: 0 so no seeds bar even where leveling is on: this card
|
|
1309
1376
|
demos the clean success a web3-only app gets. The seeds variant lives in
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
<%#
|
|
2
|
+
Living style guide specimen — Buy an Entry Token.
|
|
3
|
+
|
|
4
|
+
APP-SPECIFIC flow, engine chrome throughout (blocks/_close_x + two
|
|
5
|
+
blocks/_rail_row). Reached when a player has picked a lineup and has no way to
|
|
6
|
+
pay for it, which is why the copy says the lineup is SAVED: the one thing they
|
|
7
|
+
are afraid of at that moment is losing their picks.
|
|
8
|
+
|
|
9
|
+
TWO RAILS, RANKED, and the ranking is a product decision rather than a visual
|
|
10
|
+
one. Coinflow leads and carries the "New" badge because it mints a spendable
|
|
11
|
+
entry token directly — it is the shortest path from here to being in the
|
|
12
|
+
contest. Stripe still swaps into the auth wizard's tokens picker, which is the
|
|
13
|
+
older, longer path, so it defers.
|
|
14
|
+
|
|
15
|
+
Single root: the outer <div> is the host's required root.
|
|
16
|
+
%>
|
|
17
|
+
<div class="relative">
|
|
18
|
+
<%= render "studio/modals/blocks/close_x", modal_store: "dsModals" %>
|
|
19
|
+
|
|
20
|
+
<div class="text-center pt-1 mb-2">
|
|
21
|
+
<h3 class="text-heading font-bold text-lg leading-tight">Buy an Entry Token</h3>
|
|
22
|
+
</div>
|
|
23
|
+
<p class="text-xs text-body mb-4 text-center">
|
|
24
|
+
1 token = 1 contest entry. Your lineup is saved — pick how to pay.
|
|
25
|
+
</p>
|
|
26
|
+
|
|
27
|
+
<div class="space-y-3">
|
|
28
|
+
<%= render "studio/modals/blocks/rail_row",
|
|
29
|
+
emphasis: :primary, on_click: "$store.dsModals.close()",
|
|
30
|
+
icon_label: "CF", icon_bg: "#14B8A6",
|
|
31
|
+
title: "Coinflow · $19", subtitle: "Buy 1 entry with a card · fastest",
|
|
32
|
+
badge: "New", data: { ds_rail: "coinflow" } %>
|
|
33
|
+
|
|
34
|
+
<%= render "studio/modals/blocks/rail_row",
|
|
35
|
+
on_click: "$store.dsModals.close()",
|
|
36
|
+
icon_label: "S", icon_bg: "#635BFF",
|
|
37
|
+
title: "Card · $19", subtitle: "Buy an entry token with a card",
|
|
38
|
+
data: { ds_rail: "stripe" } %>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<%#
|
|
2
|
+
Living style guide specimen — the Coinbase ramp, BUY PREFLIGHT only.
|
|
3
|
+
|
|
4
|
+
DELIBERATELY PARTIAL, and saying so is the point. turf's modals/_cdp_ramp is a
|
|
5
|
+
TWO-FLOW step machine — buy and cash-out — across thirteen states: preflight,
|
|
6
|
+
opening, waiting, awaiting-cdp, send, settling and the rest. This cards ONE of
|
|
7
|
+
them: the buy preflight, which is the state both funding cards hand off to and
|
|
8
|
+
therefore the only one a player reaches without already being mid-flow.
|
|
9
|
+
|
|
10
|
+
The other twelve are uncarded BY DECISION (operator, 2026-08-26: minimal
|
|
11
|
+
migration is fine here). That is a different thing from an oversight, and the
|
|
12
|
+
reference blurb on this card says so, because a cabinet that shows one state of
|
|
13
|
+
a thirteen-state machine without admitting it teaches a reader that the machine
|
|
14
|
+
is simpler than it is. /tasks/port-cdp-ramp-specimen holds the full state map
|
|
15
|
+
if the decision reverses.
|
|
16
|
+
|
|
17
|
+
APP-SPECIFIC, engine chrome: blocks/_close_x plus the centred title this whole
|
|
18
|
+
funding family uses.
|
|
19
|
+
|
|
20
|
+
Single root: the outer <div> is the host's required root.
|
|
21
|
+
%>
|
|
22
|
+
<div class="relative">
|
|
23
|
+
<%= render "studio/modals/blocks/close_x", modal_store: "dsModals" %>
|
|
24
|
+
|
|
25
|
+
<div class="text-center pt-1 mb-3">
|
|
26
|
+
<h3 class="text-heading font-bold text-lg leading-tight">Buy USDC with Coinbase</h3>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<p class="text-xs text-body mb-4 text-center">
|
|
30
|
+
You’ll finish the purchase in a Coinbase tab. We’ll update here
|
|
31
|
+
automatically once the USDC lands in your wallet.
|
|
32
|
+
</p>
|
|
33
|
+
|
|
34
|
+
<button type="button" @click="$store.dsModals.close()"
|
|
35
|
+
class="btn btn-primary btn-lg w-full">Continue to Coinbase</button>
|
|
36
|
+
|
|
37
|
+
<button type="button" @click="$store.dsModals.close()"
|
|
38
|
+
class="block mx-auto mt-3 text-sm text-secondary hover:text-heading transition">
|
|
39
|
+
Not now
|
|
40
|
+
</button>
|
|
41
|
+
</div>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<%#
|
|
2
|
+
Living style guide specimen — Subscribed!, the standalone newsletter
|
|
3
|
+
celebration.
|
|
4
|
+
|
|
5
|
+
APP-SPECIFIC, engine chrome (blocks/_card_header at :lg). Distinct from the
|
|
6
|
+
Profile Leveling "Subscribed!" beat, which is the leveling activity celebrating
|
|
7
|
+
IN PLACE on the card the person was already on. This one arrives on its own —
|
|
8
|
+
swapped in from the subscribe modal, or opened from the /account newsletter
|
|
9
|
+
row — so it has to carry its own way forward.
|
|
10
|
+
|
|
11
|
+
TWO FORKS, AND NEITHER IS VISIBLE TO A READER OF THE MARKUP. That is the whole
|
|
12
|
+
reason this card exists separately rather than being folded into the leveling
|
|
13
|
+
beat:
|
|
14
|
+
|
|
15
|
+
· THE SEEDS BAR IS FIRST-JOIN ONLY. A re-subscribe earns nothing, and the
|
|
16
|
+
card HIDES the bar rather than showing a flat "0 seeds" — which would read
|
|
17
|
+
to the person as a bug about their own account rather than as an accurate
|
|
18
|
+
zero.
|
|
19
|
+
· THE CTA IS SERVER-DECIDED. If the username quest is still open
|
|
20
|
+
(current_user.next_quest == :username) the button nudges straight into it;
|
|
21
|
+
otherwise it sends them off to browse contests. Showing only one of those
|
|
22
|
+
hides the funnel that this celebration doubles as.
|
|
23
|
+
|
|
24
|
+
Both are gated on props here so the cabinet can walk all four combinations.
|
|
25
|
+
In the app the CTA fork is SERVER-rendered, precisely so the button never
|
|
26
|
+
flashes the wrong option at someone whose quest is already done.
|
|
27
|
+
|
|
28
|
+
Single root: the outer <div> is the host's required root.
|
|
29
|
+
%>
|
|
30
|
+
<div x-data="{
|
|
31
|
+
get props() { var c = $store.dsModals.current(); return (c && c.props) || {} },
|
|
32
|
+
get firstJoin() { return !!this.props.firstJoin },
|
|
33
|
+
get questOpen() { return !!this.props.questOpen }
|
|
34
|
+
}">
|
|
35
|
+
<%= render "studio/modals/blocks/card_header",
|
|
36
|
+
size: :lg,
|
|
37
|
+
icon_emoji: "🌱",
|
|
38
|
+
title: "Subscribed!",
|
|
39
|
+
subtitle: "You're on the list. We'll keep the sports news and contest updates coming." %>
|
|
40
|
+
|
|
41
|
+
<%# First join only. The engine's :leveling seeds bar — the bar is the
|
|
42
|
+
engine's, the numbers are the app's. %>
|
|
43
|
+
<template x-if="firstJoin">
|
|
44
|
+
<div class="mb-5">
|
|
45
|
+
<%= render "studio/modals/blocks/seeds_bar",
|
|
46
|
+
seeds_earned_key: "25",
|
|
47
|
+
seeds_total_key: "125",
|
|
48
|
+
seeds_per_level: 100,
|
|
49
|
+
free_entry_label: "Free Entry Token 🎟️" %>
|
|
50
|
+
</div>
|
|
51
|
+
</template>
|
|
52
|
+
|
|
53
|
+
<template x-if="questOpen">
|
|
54
|
+
<button type="button" @click="$store.dsModals.close()"
|
|
55
|
+
class="btn btn-primary btn-lg w-full">Next Quest</button>
|
|
56
|
+
</template>
|
|
57
|
+
|
|
58
|
+
<template x-if="!questOpen">
|
|
59
|
+
<button type="button" @click="$store.dsModals.close()"
|
|
60
|
+
class="btn btn-primary btn-lg w-full">Check Out Contests</button>
|
|
61
|
+
</template>
|
|
62
|
+
|
|
63
|
+
<button type="button" @click="$store.dsModals.close()"
|
|
64
|
+
class="block mx-auto mt-3 text-sm text-secondary hover:text-heading transition">
|
|
65
|
+
Close
|
|
66
|
+
</button>
|
|
67
|
+
</div>
|
data/lib/studio/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: studio-engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.61.
|
|
4
|
+
version: 0.61.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex McRitchie
|
|
@@ -509,7 +509,10 @@ files:
|
|
|
509
509
|
- app/views/style/modals/_auth.html.erb
|
|
510
510
|
- app/views/style/modals/_birthday.html.erb
|
|
511
511
|
- app/views/style/modals/_cosign_rejected.html.erb
|
|
512
|
+
- app/views/style/modals/_ds_buy_entry_token.html.erb
|
|
513
|
+
- app/views/style/modals/_ds_cdp_ramp.html.erb
|
|
512
514
|
- app/views/style/modals/_ds_close_x.html.erb
|
|
515
|
+
- app/views/style/modals/_ds_newsletter_success.html.erb
|
|
513
516
|
- app/views/style/modals/_ds_onramp_hub.html.erb
|
|
514
517
|
- app/views/style/modals/_ds_rail_row.html.erb
|
|
515
518
|
- app/views/style/modals/_ds_wallet_topup.html.erb
|