studio-engine 0.132.0 → 0.133.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +77 -0
- data/README.md +52 -24
- data/app/assets/tailwind/studio_engine/engine.css +141 -0
- data/app/javascript/studio/application.js +1 -0
- data/app/javascript/studio/carousel.js +66 -1
- data/app/javascript/studio/controllers/carousel_controller.js +139 -8
- data/app/javascript/studio/controllers/page_header_controller.js +64 -1
- data/app/javascript/studio/controllers/style_section_nav_controller.js +26 -0
- data/app/javascript/studio/in_page_links.js +308 -0
- data/app/javascript/studio/page_header.js +17 -0
- data/app/views/studio/_carousel.html.erb +33 -5
- data/app/views/studio/_page_header.html.erb +64 -12
- data/app/views/studio/auth/_sign_in_body.html.erb +236 -0
- data/app/views/studio/auth/_sign_in_card.html.erb +50 -0
- data/app/views/studio/auth/_sign_in_modal.html.erb +36 -0
- data/app/views/studio/modals/auth/_resend_footer.html.erb +6 -0
- data/app/views/style/_glass.html.erb +4 -8
- data/app/views/style/_loaders.html.erb +11 -35
- data/app/views/style/_modals.html.erb +29 -39
- data/app/views/style/_scrims.html.erb +10 -20
- data/app/views/style/_site_footer.html.erb +10 -18
- data/app/views/style/_specimen.html.erb +13 -41
- data/app/views/style/_tasks.html.erb +4 -22
- data/app/views/style/_trick_label.html.erb +33 -0
- data/app/views/style/_tricks.html.erb +127 -207
- data/app/views/style/index.html.erb +2 -2
- data/app/views/style/modals/_wallet_connect.html.erb +2 -1
- data/config/studio_tricks.yml +470 -0
- data/lib/studio/page_header.rb +53 -0
- data/lib/studio/tricks.rb +110 -0
- data/lib/studio/version.rb +1 -1
- data/lib/studio.rb +6 -4
- metadata +9 -3
- data/app/views/style/modals/_ds_email_field.html.erb +0 -58
- data/app/views/style/modals/_ds_resend_footer.html.erb +0 -70
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.
|
|
4
|
+
version: 0.133.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex McRitchie
|
|
@@ -543,6 +543,7 @@ files:
|
|
|
543
543
|
- app/javascript/studio/host_fetchers.js
|
|
544
544
|
- app/javascript/studio/identity_mini.js
|
|
545
545
|
- app/javascript/studio/image_upload.js
|
|
546
|
+
- app/javascript/studio/in_page_links.js
|
|
546
547
|
- app/javascript/studio/infinite_scroll.js
|
|
547
548
|
- app/javascript/studio/knowledge_transcript.js
|
|
548
549
|
- app/javascript/studio/lazy_controllers.js
|
|
@@ -671,6 +672,9 @@ files:
|
|
|
671
672
|
- app/views/studio/agent_chat/_turn.html.erb
|
|
672
673
|
- app/views/studio/agent_chat/_typing.html.erb
|
|
673
674
|
- app/views/studio/agent_chat/_voice.html.erb
|
|
675
|
+
- app/views/studio/auth/_sign_in_body.html.erb
|
|
676
|
+
- app/views/studio/auth/_sign_in_card.html.erb
|
|
677
|
+
- app/views/studio/auth/_sign_in_modal.html.erb
|
|
674
678
|
- app/views/studio/banners/_app_banner.html.erb
|
|
675
679
|
- app/views/studio/banners/_button.html.erb
|
|
676
680
|
- app/views/studio/banners/_dev_mode_button.html.erb
|
|
@@ -818,6 +822,7 @@ files:
|
|
|
818
822
|
- app/views/style/_specimen.html.erb
|
|
819
823
|
- app/views/style/_tasks.html.erb
|
|
820
824
|
- app/views/style/_theme.html.erb
|
|
825
|
+
- app/views/style/_trick_label.html.erb
|
|
821
826
|
- app/views/style/_tricks.html.erb
|
|
822
827
|
- app/views/style/_type_ladder.html.erb
|
|
823
828
|
- app/views/style/board/_demo_card.html.erb
|
|
@@ -826,9 +831,7 @@ files:
|
|
|
826
831
|
- app/views/style/modals/_age_gate.html.erb
|
|
827
832
|
- app/views/style/modals/_birthday.html.erb
|
|
828
833
|
- app/views/style/modals/_ds_close_x.html.erb
|
|
829
|
-
- app/views/style/modals/_ds_email_field.html.erb
|
|
830
834
|
- app/views/style/modals/_ds_rail_row.html.erb
|
|
831
|
-
- app/views/style/modals/_ds_resend_footer.html.erb
|
|
832
835
|
- app/views/style/modals/_ds_stack_demo.html.erb
|
|
833
836
|
- app/views/style/modals/_email_change_pending.html.erb
|
|
834
837
|
- app/views/style/modals/_it_begins.html.erb
|
|
@@ -840,6 +843,7 @@ files:
|
|
|
840
843
|
- app/views/user_mailer/magic_link.html.erb
|
|
841
844
|
- app/views/user_mailer/magic_link.text.erb
|
|
842
845
|
- config/importmap.rb
|
|
846
|
+
- config/studio_tricks.yml
|
|
843
847
|
- db/migrate/20260614000000_create_studio_email_deliveries.rb
|
|
844
848
|
- db/migrate/20260620000001_create_studio_links.rb
|
|
845
849
|
- db/migrate/20260620000002_allow_null_image_cache_owner.rb
|
|
@@ -944,6 +948,7 @@ files:
|
|
|
944
948
|
- lib/studio/node_tooling/playwright_base.js
|
|
945
949
|
- lib/studio/node_tooling/versions.json
|
|
946
950
|
- lib/studio/oauth_identity.rb
|
|
951
|
+
- lib/studio/page_header.rb
|
|
947
952
|
- lib/studio/partial_block.rb
|
|
948
953
|
- lib/studio/profile_image.rb
|
|
949
954
|
- lib/studio/profile_sections.rb
|
|
@@ -963,6 +968,7 @@ files:
|
|
|
963
968
|
- lib/studio/survey/export.rb
|
|
964
969
|
- lib/studio/tailwind_entry.rb
|
|
965
970
|
- lib/studio/theme_resolver.rb
|
|
971
|
+
- lib/studio/tricks.rb
|
|
966
972
|
- lib/studio/type_scale.rb
|
|
967
973
|
- lib/studio/ui_primitives.rb
|
|
968
974
|
- lib/studio/username_generator.rb
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
<%#
|
|
2
|
-
Living style guide specimen — the modal family's email input,
|
|
3
|
-
studio/modals/shared/_email_field.
|
|
4
|
-
|
|
5
|
-
THIS IS A BLOCK DEMO, NOT A CARD. The engine does not own an auth MODAL — the
|
|
6
|
-
sign-in card is each app's, mounted on that app's own host and reviewed on that
|
|
7
|
-
app's own section of this guide. What the engine owns is the PIECES that card
|
|
8
|
-
is built from, and this is the one every app's auth card renders. It had no
|
|
9
|
-
specimen of its own until 2026-09-09 because style/modals/_auth, a mirror of
|
|
10
|
-
turf-monster's card, happened to render it — so retiring the mirror is what
|
|
11
|
-
made the gap visible.
|
|
12
|
-
|
|
13
|
-
BOTH FACES ARE SHOWN because `validator` is a real fork, not a flag. Off, the
|
|
14
|
-
partial is self-contained and the SERVER stays the only boundary; on, it wraps
|
|
15
|
-
itself in x-data="emailValidator()" and paints a right-edge spinner / check / X
|
|
16
|
-
that only works if the CONSUMER ships that factory. An app that passes
|
|
17
|
-
validator: true without the factory gets an Alpine scope error and a dead
|
|
18
|
-
indicator, so the two are drawn side by side to make the dependency legible.
|
|
19
|
-
This page ships no emailValidator, which is why the right-hand field's
|
|
20
|
-
indicator stays blank — that is the demo, not a defect.
|
|
21
|
-
|
|
22
|
-
Single root: the outer <div> is the host's required root.
|
|
23
|
-
%>
|
|
24
|
-
<div class="relative">
|
|
25
|
-
<%= render "studio/modals/blocks/close_x", modal_store: "dsModals" %>
|
|
26
|
-
|
|
27
|
-
<div class="text-center pt-1 mb-4">
|
|
28
|
-
<h3 class="text-heading font-bold text-lg leading-tight">Email field</h3>
|
|
29
|
-
<p class="text-xs text-muted mt-1">studio/modals/shared/_email_field</p>
|
|
30
|
-
</div>
|
|
31
|
-
|
|
32
|
-
<div class="space-y-4" x-data="{ email: '' }">
|
|
33
|
-
<div>
|
|
34
|
-
<p class="text-2xs font-bold text-secondary uppercase tracking-wide mb-1.5">Plain</p>
|
|
35
|
-
<%= render "studio/modals/shared/email_field",
|
|
36
|
-
name: nil, x_model: "email", required: true %>
|
|
37
|
-
<p class="text-2xs text-muted mt-1.5">
|
|
38
|
-
No dependency beyond the theme. <code class="font-mono">x_model</code>
|
|
39
|
-
resolves in the ENCLOSING scope, so the value lands on the host component
|
|
40
|
-
rather than on the field.
|
|
41
|
-
</p>
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
<div>
|
|
45
|
-
<p class="text-2xs font-bold text-secondary uppercase tracking-wide mb-1.5">With validator</p>
|
|
46
|
-
<%= render "studio/modals/shared/email_field",
|
|
47
|
-
name: nil, x_model: "email", required: true, validator: true %>
|
|
48
|
-
<p class="text-2xs text-muted mt-1.5">
|
|
49
|
-
Adds <code class="font-mono">x-data="emailValidator()"</code> and the
|
|
50
|
-
right-edge indicator. <strong>The factory is the consumer’s to
|
|
51
|
-
ship</strong> — this guide does not, so the indicator stays blank here.
|
|
52
|
-
</p>
|
|
53
|
-
</div>
|
|
54
|
-
</div>
|
|
55
|
-
|
|
56
|
-
<button type="button" @click="$store.dsModals.close()"
|
|
57
|
-
class="btn btn-primary btn-lg w-full mt-5">Done</button>
|
|
58
|
-
</div>
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
<%#
|
|
2
|
-
Living style guide specimen — the magic-link resend footer,
|
|
3
|
-
studio/modals/auth/_resend_footer.
|
|
4
|
-
|
|
5
|
-
A BLOCK DEMO, for the same reason as _ds_email_field: the engine owns this
|
|
6
|
-
fragment, not the auth card that renders it. Both of the auth card's
|
|
7
|
-
link-sent steps render it, and they are identical — which is the whole reason
|
|
8
|
-
it was extracted.
|
|
9
|
-
|
|
10
|
-
IT NEEDS A HOST, AND THAT IS THE POINT. The footer reads props.submitting,
|
|
11
|
-
props.resendCooldown and props.resendError, and calls resendMagicLink(), all
|
|
12
|
-
resolved from the ENCLOSING x-data — never from a store. So the x-data below
|
|
13
|
-
is a stand-in for the auth card's own component, and it is the contract this
|
|
14
|
-
specimen documents: drop this partial into a scope that supplies none of those
|
|
15
|
-
and nothing errors, the link simply never enables and the cooldown never
|
|
16
|
-
counts. The stub here drives a real 5s cooldown so all three states are
|
|
17
|
-
reachable: idle, in-flight, counting down.
|
|
18
|
-
|
|
19
|
-
THE COOLDOWN IS SHORTENED ON PURPOSE. Production counts 60s; a reviewer will
|
|
20
|
-
not wait 60s to watch a number tick, and a specimen nobody watches documents
|
|
21
|
-
nothing. The partial does not own the duration — the host does.
|
|
22
|
-
|
|
23
|
-
Single root: the outer <div> is the host's required root.
|
|
24
|
-
%>
|
|
25
|
-
<div class="relative"
|
|
26
|
-
x-data="{
|
|
27
|
-
props: { submitting: null, resendCooldown: 0, resendError: '' },
|
|
28
|
-
_timer: null,
|
|
29
|
-
resendMagicLink() {
|
|
30
|
-
if (this.props.submitting || this.props.resendCooldown > 0) return;
|
|
31
|
-
this.props.resendError = '';
|
|
32
|
-
this.props.submitting = 'magic-link';
|
|
33
|
-
setTimeout(() => {
|
|
34
|
-
this.props.submitting = null;
|
|
35
|
-
this.props.resendCooldown = 5;
|
|
36
|
-
this._timer = setInterval(() => {
|
|
37
|
-
this.props.resendCooldown -= 1;
|
|
38
|
-
if (this.props.resendCooldown <= 0) clearInterval(this._timer);
|
|
39
|
-
}, 1000);
|
|
40
|
-
}, 900);
|
|
41
|
-
},
|
|
42
|
-
fail() {
|
|
43
|
-
this.props.submitting = null;
|
|
44
|
-
this.props.resendCooldown = 0;
|
|
45
|
-
this.props.resendError = 'That link could not be sent. Try again in a moment.';
|
|
46
|
-
},
|
|
47
|
-
// Alpine calls destroy() when the component leaves the DOM. Without it the
|
|
48
|
-
// interval outlives the closed card and keeps decrementing a dead object.
|
|
49
|
-
destroy() { clearInterval(this._timer); }
|
|
50
|
-
}">
|
|
51
|
-
<%= render "studio/modals/blocks/close_x", modal_store: "dsModals" %>
|
|
52
|
-
|
|
53
|
-
<div class="text-center pt-1 mb-4">
|
|
54
|
-
<div class="text-2xl leading-none mb-2">📬</div>
|
|
55
|
-
<h3 class="text-heading font-bold text-lg leading-tight">Check your email</h3>
|
|
56
|
-
<p class="text-xs text-body mt-1">
|
|
57
|
-
The footer below is the shared piece — everything above it belongs to
|
|
58
|
-
the app’s own card.
|
|
59
|
-
</p>
|
|
60
|
-
</div>
|
|
61
|
-
|
|
62
|
-
<div class="border-t border-subtle pt-4">
|
|
63
|
-
<%= render "studio/modals/auth/resend_footer", modal_store: "dsModals" %>
|
|
64
|
-
</div>
|
|
65
|
-
|
|
66
|
-
<button type="button" @click="fail()"
|
|
67
|
-
class="block mx-auto mt-4 text-2xs text-muted hover:text-secondary underline underline-offset-2">
|
|
68
|
-
Show the error line
|
|
69
|
-
</button>
|
|
70
|
-
</div>
|