studio-engine 0.129.0 → 0.131.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 +192 -0
- data/README.md +48 -6
- data/app/assets/tailwind/studio_engine/engine-motion.css +322 -56
- data/app/assets/tailwind/studio_engine/engine.css +737 -19
- data/app/assets/tailwind/studio_engine/theme.css +4 -0
- data/app/controllers/concerns/studio/error_handling.rb +53 -15
- data/app/controllers/concerns/studio/magic_link_issuing.rb +4 -0
- data/app/controllers/magic_links_controller.rb +25 -2
- data/app/controllers/registrations_controller.rb +58 -22
- data/app/controllers/style_controller.rb +6 -0
- data/app/helpers/studio/agent_chat_helper.rb +14 -1
- data/app/helpers/studio/crumbs_helper.rb +34 -0
- data/app/helpers/studio/fizz_helper.rb +5 -0
- data/app/helpers/studio/loader_helper.rb +79 -2
- data/app/javascript/studio/agent_chat.js +294 -6
- data/app/javascript/studio/carousel.js +99 -0
- data/app/javascript/studio/controllers/carousel_controller.js +138 -0
- data/app/javascript/studio/controllers/infinite_scroll_controller.js +17 -0
- data/app/javascript/studio/controllers/pull_to_refresh_controller.js +18 -0
- data/app/javascript/studio/controllers/style_section_nav_controller.js +4 -4
- data/app/javascript/studio/controllers/talk_to_agent_controller.js +20 -0
- data/app/javascript/studio/infinite_scroll.js +142 -0
- data/app/javascript/studio/loader.js +6 -1
- data/app/javascript/studio/page_transitions.js +65 -8
- data/app/javascript/studio/pinned_stack.js +112 -4
- data/app/javascript/studio/pull_to_refresh.js +147 -0
- data/app/javascript/studio/stimulus.js +12 -1
- data/app/javascript/studio/talk_to_agent.js +116 -0
- data/app/views/components/_geo_signpost.html.erb +2 -2
- data/app/views/components/_link_sidebar.html.erb +2 -2
- data/app/views/components/_link_sidebar_trigger.html.erb +1 -1
- data/app/views/components/_sidebar_panel.html.erb +1 -1
- data/app/views/error_logs/index.html.erb +2 -8
- data/app/views/studio/_carousel.html.erb +97 -0
- data/app/views/studio/_fizz.html.erb +26 -0
- data/app/views/studio/_fizz_layer.html.erb +4 -1
- data/app/views/studio/_hold_button.html.erb +1 -2
- data/app/views/studio/_page_header.html.erb +55 -13
- data/app/views/studio/_section_header.html.erb +23 -0
- data/app/views/studio/agent_chat/_chat.html.erb +7 -4
- data/app/views/studio/agent_chat/_talk_modal.html.erb +58 -0
- data/app/views/studio/agent_chat/_turn.html.erb +1 -1
- data/app/views/studio/loader/_infinite_scroll.html.erb +42 -0
- data/app/views/studio/loader/_loader.html.erb +20 -3
- data/app/views/studio/loader/_pull_to_refresh.html.erb +20 -0
- data/app/views/studio/loader/_skeleton.html.erb +37 -0
- data/app/views/style/_components.html.erb +3 -5
- data/app/views/style/_host.html.erb +3 -6
- data/app/views/style/_loaders.html.erb +118 -0
- data/app/views/style/_loaders_feed_page.html.erb +16 -0
- data/app/views/style/_modal_specimen.html.erb +5 -5
- data/app/views/style/_modals.html.erb +15 -5
- data/app/views/style/_site_footer.html.erb +1 -1
- data/app/views/style/_specimen.html.erb +21 -10
- data/app/views/style/_tasks.html.erb +3 -5
- data/app/views/style/_theme.html.erb +2 -2
- data/app/views/style/_tricks.html.erb +218 -217
- data/app/views/style/index.html.erb +21 -11
- data/app/views/style/loaders_feed.html.erb +7 -0
- data/lib/studio/crumbs.rb +150 -0
- data/lib/studio/loader.rb +30 -2
- data/lib/studio/version.rb +1 -1
- data/lib/studio.rb +3 -0
- metadata +22 -2
|
@@ -3,26 +3,29 @@
|
|
|
3
3
|
application.html.erb, inheriting that app's navbar and theme, so every
|
|
4
4
|
specimen restyles per app and in dark or light automatically.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Six ENGINE sections, reached by the page header below and rendered
|
|
7
7
|
as sibling partials: Theme is the landing section (the color foundation - it
|
|
8
8
|
owns the role tokens/swatches, the theme editor, the live preview, and the
|
|
9
|
-
logos and type), then
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
logos and type), then Tricks (the button/surface/motion/effect/leveling
|
|
10
|
+
primitives, framed as a board of copy-paste-for-an-agent snippets; second by
|
|
11
|
+
Alex McRitchie's ruling of 2026-11-05), Loaders (the eight loading primitives,
|
|
12
|
+
docs/LOADER.md), Modals (the shared host + engine card blocks), Tasks (the
|
|
13
|
+
shared board primitive), and
|
|
12
14
|
Components (the ViewComponent previews, linking into the gallery at
|
|
13
15
|
/admin/style/components).
|
|
14
16
|
|
|
15
|
-
A
|
|
17
|
+
A SEVENTH section is the host app's own, and appears only on an app that asks
|
|
16
18
|
for it: define app/views/style/host/_modals.html.erb in the consuming app
|
|
17
19
|
and the guide grows a section (and a nav pill) for that app's own modals,
|
|
18
|
-
between Modals and
|
|
20
|
+
between Modals and Tasks. The gem still renders the section chrome; the app
|
|
19
21
|
supplies the specimens. Full contract, including which modal store a host
|
|
20
22
|
specimen drives and why it is not the one the Modals section uses:
|
|
21
23
|
app/views/style/_host.html.erb.
|
|
22
24
|
|
|
23
25
|
HEADINGS wear the type ladder, on trial on this page only (style/_type_ladder): the one
|
|
24
26
|
<h1> is studio/_page_header's, at type-h2; a section is an <h2> at type-h3; a subsection
|
|
25
|
-
is an <h3> at type-h4.
|
|
27
|
+
is an <h3> at type-h4. The section's <h2> is studio/_section_header's, in type-h3's numbers,
|
|
28
|
+
which sticks under the page row until the next section's takes its place.
|
|
26
29
|
|
|
27
30
|
Specimens use ONLY the engine's own classes (engine.css component layer plus
|
|
28
31
|
engine-motion.css motion/effect/leveling layer), so a consumer that imports
|
|
@@ -43,8 +46,11 @@
|
|
|
43
46
|
# The section chrome and the consumer contract live in style/_host.html.erb.
|
|
44
47
|
host_modals = lookup_context.exists?("modals", ["style/host"], true)
|
|
45
48
|
|
|
49
|
+
# Tricks second, after the landing Theme (Alex McRitchie, 2026-11-05).
|
|
46
50
|
sections = [
|
|
47
51
|
["theme", "Theme"],
|
|
52
|
+
["tricks", "Tricks"],
|
|
53
|
+
["loaders", "Loaders"],
|
|
48
54
|
["modals", "Modals"]
|
|
49
55
|
]
|
|
50
56
|
# Adjacent to Modals, not appended: this page groups by SUBJECT, and a host's
|
|
@@ -52,14 +58,13 @@
|
|
|
52
58
|
# name, so the pill says whose section it is.
|
|
53
59
|
sections << ["host-modals", Studio.app_name] if host_modals
|
|
54
60
|
sections += [
|
|
55
|
-
["tricks", "Tricks"],
|
|
56
61
|
["tasks", "Tasks"],
|
|
57
62
|
["components", "Components"]
|
|
58
63
|
]
|
|
59
64
|
%>
|
|
60
65
|
<div class="max-w-6xl mx-auto px-4 pt-6 pb-16" data-type-ladder>
|
|
61
66
|
<%# The page's title and its section tabs: studio/_page_header, the row of the
|
|
62
|
-
|
|
67
|
+
pinned stack (docs/PAGE_HEADER.md). It sits at --z-sticky, above --z-raised,
|
|
63
68
|
so the live hold button's portal bubbles scroll under it rather than over it.
|
|
64
69
|
|
|
65
70
|
The style-section-nav controller moves the highlight as the page scrolls
|
|
@@ -67,6 +72,7 @@
|
|
|
67
72
|
right before the module loads. %>
|
|
68
73
|
<%= render "studio/page_header",
|
|
69
74
|
title: "Style",
|
|
75
|
+
crumbs: studio_crumbs_here,
|
|
70
76
|
meta: "v#{Studio::VERSION}",
|
|
71
77
|
meta_title: "studio-engine",
|
|
72
78
|
label: "Style guide sections",
|
|
@@ -77,13 +83,17 @@
|
|
|
77
83
|
data: { style_section_nav_target: "link" } }
|
|
78
84
|
} %>
|
|
79
85
|
|
|
80
|
-
|
|
86
|
+
<%# 6rem between sections: a first jump from the top of the page lands by the navbar's
|
|
87
|
+
collapse below the line, and the section above must be gone from the bar by then
|
|
88
|
+
(76px on the hub at phone width). %>
|
|
89
|
+
<div class="space-y-24 pt-10">
|
|
81
90
|
<%= render "style/theme" %>
|
|
91
|
+
<%= render "style/tricks" %>
|
|
92
|
+
<%= render "style/loaders" %>
|
|
82
93
|
<%= render "style/modals" %>
|
|
83
94
|
<% if host_modals %>
|
|
84
95
|
<%= render "style/host" %>
|
|
85
96
|
<% end %>
|
|
86
|
-
<%= render "style/tricks" %>
|
|
87
97
|
<%= render "style/tasks" %>
|
|
88
98
|
<%= render "style/components" %>
|
|
89
99
|
</div>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<%# The Loaders section's demo feed, one page (StyleController#loaders_feed). A
|
|
2
|
+
whole page, so "Load more" opened with no script lands somewhere real; a
|
|
3
|
+
frame request takes just the frame it asked for out of it. %>
|
|
4
|
+
<div class="max-w-xl mx-auto px-4 py-10 space-y-4">
|
|
5
|
+
<h1 class="type-h3 text-heading">Loaders demo feed</h1>
|
|
6
|
+
<%= render "style/loaders_feed_page", page: @page, feed_path: admin_style_loaders_feed_path %>
|
|
7
|
+
</div>
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Studio
|
|
4
|
+
# THE PARENT MAP behind studio/_page_header's crumb trail (docs/PAGE_HEADER.md, "Crumbs").
|
|
5
|
+
# An app names each page that has children once, with its label, its address and its own
|
|
6
|
+
# parent. A page then names only its parent, and the trail builds itself up the chain.
|
|
7
|
+
#
|
|
8
|
+
# # config/initializers/studio_crumbs.rb
|
|
9
|
+
# Studio.crumbs.draw do
|
|
10
|
+
# page :admin, "Admin", :admin_dashboard_path
|
|
11
|
+
# page :deployments, "Deployments", :deployments_path, parent: :admin
|
|
12
|
+
# page :release, ->(release:) { release.slug }, ->(release:) { release_path(release) },
|
|
13
|
+
# parent: :deployments
|
|
14
|
+
# end
|
|
15
|
+
#
|
|
16
|
+
# <%= render "studio/page_header", title: "Deployments", crumbs: studio_crumbs(:deployments) %>
|
|
17
|
+
# <%= render "studio/page_header", title: @task.title, crumbs: studio_crumbs(parent: :deployments) %>
|
|
18
|
+
#
|
|
19
|
+
# A label or an address is a String, a Symbol (a route helper, read in the view, then on
|
|
20
|
+
# main_app) or a lambda the view runs with the page's own keywords.
|
|
21
|
+
class Crumbs
|
|
22
|
+
Page = Struct.new(:key, :label, :path, :parent, keyword_init: true)
|
|
23
|
+
|
|
24
|
+
class UnknownPage < KeyError; end
|
|
25
|
+
class Cycle < ArgumentError; end
|
|
26
|
+
|
|
27
|
+
def initialize
|
|
28
|
+
@pages = {}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def draw(&block)
|
|
32
|
+
instance_eval(&block)
|
|
33
|
+
self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def page(key, label, path, parent: nil)
|
|
37
|
+
@pages[key.to_sym] = Page.new(key: key.to_sym, label: label, path: path, parent: parent&.to_sym)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def clear
|
|
41
|
+
@pages.clear
|
|
42
|
+
self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def key?(key) = @pages.key?(key.to_sym)
|
|
46
|
+
|
|
47
|
+
def fetch(key)
|
|
48
|
+
@pages.fetch(key.to_sym) { raise UnknownPage, "Studio.crumbs has no page #{key.inspect}" }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# The keys from the root down to `key`, `key` included.
|
|
52
|
+
def chain(key)
|
|
53
|
+
keys = []
|
|
54
|
+
current = key&.to_sym
|
|
55
|
+
while current
|
|
56
|
+
raise Cycle, "Studio.crumbs loops at #{current.inspect}" if keys.include?(current)
|
|
57
|
+
|
|
58
|
+
keys.unshift(current)
|
|
59
|
+
current = fetch(current).parent
|
|
60
|
+
end
|
|
61
|
+
keys
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# The trail for one page: its ancestors, root first, as [{ label:, href: }]. Name the page
|
|
65
|
+
# itself (`key`, the page in the map) or only its parent (`parent:`, a page not in the map).
|
|
66
|
+
def trail(view, key = nil, parent: nil, **locals)
|
|
67
|
+
raise ArgumentError, "name the page or its parent, not both" if key && parent
|
|
68
|
+
|
|
69
|
+
keys = key ? chain(key)[0...-1] : chain(parent)
|
|
70
|
+
keys.map do |name|
|
|
71
|
+
page = fetch(name)
|
|
72
|
+
{ label: resolve(view, page.label, locals).to_s, href: resolve(view, page.path, locals).to_s }
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# The map's page at `path`, or nil: for a page the engine draws (the style guide, the
|
|
77
|
+
# model pages), which cannot know the host's key for it. Only pages whose address
|
|
78
|
+
# needs no keywords can match.
|
|
79
|
+
def key_for_path(view, path)
|
|
80
|
+
wanted = normalize(path)
|
|
81
|
+
@pages.each_value do |page|
|
|
82
|
+
next if page.path.is_a?(Proc) && keywords(page.path, required: true).any?
|
|
83
|
+
|
|
84
|
+
address = begin
|
|
85
|
+
resolve(view, page.path, {}).to_s
|
|
86
|
+
rescue StandardError
|
|
87
|
+
next
|
|
88
|
+
end
|
|
89
|
+
return page.key if normalize(address) == wanted
|
|
90
|
+
end
|
|
91
|
+
nil
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# A name the map lacks, or a loop in it, is a mistake in the app's own code. In
|
|
95
|
+
# development and test it raises, so the mistake shows at once. Anywhere else (QA
|
|
96
|
+
# dynos run as production, so not Rails.env.production?) the page renders with no
|
|
97
|
+
# trail and the error is logged: a missing crumb is not worth a 500.
|
|
98
|
+
def self.strict?(env = (::Rails.env if defined?(::Rails) && ::Rails.respond_to?(:env)))
|
|
99
|
+
return true if env.nil?
|
|
100
|
+
|
|
101
|
+
env.development? || env.test?
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
REPORTED = {}
|
|
105
|
+
REPORTED_LOCK = Mutex.new
|
|
106
|
+
|
|
107
|
+
# Once per message per process: a layout renders on every request.
|
|
108
|
+
def self.report(error)
|
|
109
|
+
first = REPORTED_LOCK.synchronize { REPORTED[error.message] ? false : (REPORTED[error.message] = true) }
|
|
110
|
+
return unless first
|
|
111
|
+
|
|
112
|
+
if defined?(::ErrorLog) && ::ErrorLog.respond_to?(:capture!)
|
|
113
|
+
::ErrorLog.capture!(error)
|
|
114
|
+
elsif defined?(::Rails) && ::Rails.respond_to?(:logger) && ::Rails.logger
|
|
115
|
+
::Rails.logger.error("[studio-crumbs] no trail drawn: #{error.class}: #{error.message}")
|
|
116
|
+
end
|
|
117
|
+
rescue StandardError
|
|
118
|
+
nil # reporting is best-effort: the page still renders
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
# An address with no trailing slash; the root stays "/".
|
|
124
|
+
def normalize(path) = path.to_s.chomp("/").presence || "/"
|
|
125
|
+
|
|
126
|
+
def resolve(view, value, locals)
|
|
127
|
+
case value
|
|
128
|
+
when Proc then view.instance_exec(**locals.slice(*keywords(value)), &value)
|
|
129
|
+
when Symbol then route(view, value)
|
|
130
|
+
else value
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def keywords(proc, required: false)
|
|
135
|
+
kinds = required ? %i[keyreq] : %i[key keyreq]
|
|
136
|
+
proc.parameters.filter_map { |kind, name| name if kinds.include?(kind) }
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def route(view, name)
|
|
140
|
+
return view.public_send(name) if view.respond_to?(name)
|
|
141
|
+
return view.main_app.public_send(name) if view.respond_to?(:main_app)
|
|
142
|
+
|
|
143
|
+
raise NoMethodError, "Studio.crumbs: no route helper #{name}"
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def self.crumbs
|
|
148
|
+
@crumbs ||= Crumbs.new
|
|
149
|
+
end
|
|
150
|
+
end
|
data/lib/studio/loader.rb
CHANGED
|
@@ -23,6 +23,11 @@
|
|
|
23
23
|
# The icon is drawn underneath as an image; the art is inlined over it. An art
|
|
24
24
|
# file that is missing, outside public/, or has no marked layer falls back to
|
|
25
25
|
# breathe, so a typo can never blank the loader.
|
|
26
|
+
#
|
|
27
|
+
# PLAIN styles draw no icon, only the theme's colours: spinner, dots and bar.
|
|
28
|
+
# They are the small, everyday members of the same loader family, for a view to
|
|
29
|
+
# name with studio_loader(style:). They are not an app's brand, so the app's own
|
|
30
|
+
# config.loader refuses them.
|
|
26
31
|
module Studio
|
|
27
32
|
module Loader
|
|
28
33
|
class InvalidConfig < ArgumentError; end
|
|
@@ -37,7 +42,20 @@ module Studio
|
|
|
37
42
|
SETTING = "Studio.loader"
|
|
38
43
|
GENERIC_STYLES = %i[breathe liquid orbit steel].freeze
|
|
39
44
|
ART_STYLES = { weld_bead: "outline", sparkle: "spark" }.freeze
|
|
45
|
+
# The styles an app may declare as its loader: they draw its icon.
|
|
40
46
|
STYLES = (GENERIC_STYLES + ART_STYLES.keys).freeze
|
|
47
|
+
# The styles a view may name that draw no icon (docs/LOADER.md, "The family").
|
|
48
|
+
PLAIN_STYLES = %i[spinner dots bar].freeze
|
|
49
|
+
# The size each style draws at when the caller names none: the icon styles at
|
|
50
|
+
# 96px, a spinner beside text, dots in a line, and a bar across its parent.
|
|
51
|
+
DEFAULT_SIZES = { spinner: 20, dots: 32, bar: "100%" }.freeze
|
|
52
|
+
DEFAULT_SIZE = 96
|
|
53
|
+
# The style guide's live infinite-scroll specimen: a demo feed of this many
|
|
54
|
+
# pages of this many items (style/_loaders_feed_page). Here, not on
|
|
55
|
+
# StyleController, so a view can read them without loading a controller that
|
|
56
|
+
# needs the host's ApplicationController.
|
|
57
|
+
DEMO_FEED_PAGES = 3
|
|
58
|
+
DEMO_FEED_PER_PAGE = 4
|
|
41
59
|
DEFAULT_STYLE = :breathe
|
|
42
60
|
KEYS = %i[style icon art].freeze
|
|
43
61
|
|
|
@@ -62,6 +80,10 @@ module Studio
|
|
|
62
80
|
raise InvalidConfig, "#{SETTING} has unknown key :#{unknown.first} (takes #{KEYS.join(', ')})" if unknown.any?
|
|
63
81
|
|
|
64
82
|
style = style!(config[:style] || DEFAULT_STYLE)
|
|
83
|
+
if PLAIN_STYLES.include?(style)
|
|
84
|
+
raise InvalidConfig, "#{SETTING} style :#{style} draws no icon, so it cannot be the app's loader " \
|
|
85
|
+
"(one of #{STYLES.map(&:inspect).join(', ')}); a view names it with studio_loader(style: :#{style})"
|
|
86
|
+
end
|
|
65
87
|
icon = path!(config[:icon], "#{SETTING}[:icon]")
|
|
66
88
|
art = path!(config[:art], "#{SETTING}[:art]")
|
|
67
89
|
if ART_STYLES.key?(style) && art.nil?
|
|
@@ -72,13 +94,19 @@ module Studio
|
|
|
72
94
|
{ style: style, icon: icon, art: art }.freeze
|
|
73
95
|
end
|
|
74
96
|
|
|
97
|
+
# A style name as a Symbol, or InvalidConfig. Every style is a name a view may
|
|
98
|
+
# use; normalize refuses the plain ones for the app's own loader.
|
|
75
99
|
def style!(value)
|
|
76
100
|
style = value.to_s.strip.tr("-", "_").to_sym
|
|
77
|
-
return style if STYLES.include?(style)
|
|
101
|
+
return style if STYLES.include?(style) || PLAIN_STYLES.include?(style)
|
|
78
102
|
|
|
79
|
-
raise InvalidConfig, "#{SETTING} style must be one of #{STYLES.map(&:inspect).join(', ')} (got #{value.inspect})"
|
|
103
|
+
raise InvalidConfig, "#{SETTING} style must be one of #{(STYLES + PLAIN_STYLES).map(&:inspect).join(', ')} (got #{value.inspect})"
|
|
80
104
|
end
|
|
81
105
|
|
|
106
|
+
def plain_style?(style) = PLAIN_STYLES.include?(style)
|
|
107
|
+
|
|
108
|
+
def default_size(style) = DEFAULT_SIZES.fetch(style, DEFAULT_SIZE)
|
|
109
|
+
|
|
82
110
|
def path!(value, label)
|
|
83
111
|
return nil if value.nil?
|
|
84
112
|
return value.strip if value.is_a?(String) && !value.strip.empty?
|
data/lib/studio/version.rb
CHANGED
data/lib/studio.rb
CHANGED
|
@@ -77,6 +77,7 @@ require "studio/cable"
|
|
|
77
77
|
require "studio/survey"
|
|
78
78
|
require "studio/survey/breakdown"
|
|
79
79
|
require "studio/survey/export"
|
|
80
|
+
require "studio/crumbs"
|
|
80
81
|
|
|
81
82
|
module Studio
|
|
82
83
|
mattr_accessor :app_name, default: "Studio"
|
|
@@ -2248,6 +2249,8 @@ module Studio
|
|
|
2248
2249
|
|
|
2249
2250
|
# The living style guide (StyleController#index).
|
|
2250
2251
|
get "admin/style", to: "style#index", as: :admin_style
|
|
2252
|
+
# One page of the Loaders section's demo feed (its live infinite scroll).
|
|
2253
|
+
get "admin/style/loaders_feed", to: "style#loaders_feed", as: :admin_style_loaders_feed
|
|
2251
2254
|
|
|
2252
2255
|
# The component gallery: Lookbook over the engine's ViewComponent previews.
|
|
2253
2256
|
# The router refuses anyone but a signed-in admin, so a visitor and a
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: studio-engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.131.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Alex McRitchie
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-11-
|
|
11
|
+
date: 2026-11-06 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -482,6 +482,7 @@ files:
|
|
|
482
482
|
- app/helpers/studio/admin_models_table_helper.rb
|
|
483
483
|
- app/helpers/studio/agent_chat_helper.rb
|
|
484
484
|
- app/helpers/studio/at_time_helper.rb
|
|
485
|
+
- app/helpers/studio/crumbs_helper.rb
|
|
485
486
|
- app/helpers/studio/fizz_helper.rb
|
|
486
487
|
- app/helpers/studio/geo_helper.rb
|
|
487
488
|
- app/helpers/studio/link_preview_helper.rb
|
|
@@ -502,17 +503,20 @@ files:
|
|
|
502
503
|
- app/javascript/studio/birthday.js
|
|
503
504
|
- app/javascript/studio/board.js
|
|
504
505
|
- app/javascript/studio/booking.js
|
|
506
|
+
- app/javascript/studio/carousel.js
|
|
505
507
|
- app/javascript/studio/confirm_interstitial.js
|
|
506
508
|
- app/javascript/studio/controllers/agent_chat_controller.js
|
|
507
509
|
- app/javascript/studio/controllers/agent_chat_voice_controller.js
|
|
508
510
|
- app/javascript/studio/controllers/board_controller.js
|
|
509
511
|
- app/javascript/studio/controllers/booking_controller.js
|
|
512
|
+
- app/javascript/studio/controllers/carousel_controller.js
|
|
510
513
|
- app/javascript/studio/controllers/copy_text_controller.js
|
|
511
514
|
- app/javascript/studio/controllers/email_banner_scale_controller.js
|
|
512
515
|
- app/javascript/studio/controllers/footer_map_controller.js
|
|
513
516
|
- app/javascript/studio/controllers/geo_settings_controller.js
|
|
514
517
|
- app/javascript/studio/controllers/hold_button_controller.js
|
|
515
518
|
- app/javascript/studio/controllers/identity_mini_controller.js
|
|
519
|
+
- app/javascript/studio/controllers/infinite_scroll_controller.js
|
|
516
520
|
- app/javascript/studio/controllers/knowledge_transcript_controller.js
|
|
517
521
|
- app/javascript/studio/controllers/link_preview_card_controller.js
|
|
518
522
|
- app/javascript/studio/controllers/link_sidebar_controller.js
|
|
@@ -520,9 +524,11 @@ files:
|
|
|
520
524
|
- app/javascript/studio/controllers/modal_host_controller.js
|
|
521
525
|
- app/javascript/studio/controllers/nav_collapse_controller.js
|
|
522
526
|
- app/javascript/studio/controllers/page_header_controller.js
|
|
527
|
+
- app/javascript/studio/controllers/pull_to_refresh_controller.js
|
|
523
528
|
- app/javascript/studio/controllers/style_modals_controller.js
|
|
524
529
|
- app/javascript/studio/controllers/style_section_nav_controller.js
|
|
525
530
|
- app/javascript/studio/controllers/survey_controller.js
|
|
531
|
+
- app/javascript/studio/controllers/talk_to_agent_controller.js
|
|
526
532
|
- app/javascript/studio/controllers/toast_controller.js
|
|
527
533
|
- app/javascript/studio/controllers/voice_profile_controller.js
|
|
528
534
|
- app/javascript/studio/controllers/voice_recorder_controller.js
|
|
@@ -537,6 +543,7 @@ files:
|
|
|
537
543
|
- app/javascript/studio/host_fetchers.js
|
|
538
544
|
- app/javascript/studio/identity_mini.js
|
|
539
545
|
- app/javascript/studio/image_upload.js
|
|
546
|
+
- app/javascript/studio/infinite_scroll.js
|
|
540
547
|
- app/javascript/studio/knowledge_transcript.js
|
|
541
548
|
- app/javascript/studio/lazy_controllers.js
|
|
542
549
|
- app/javascript/studio/level_meter.js
|
|
@@ -555,6 +562,7 @@ files:
|
|
|
555
562
|
- app/javascript/studio/page_transitions.js
|
|
556
563
|
- app/javascript/studio/pinned_stack.js
|
|
557
564
|
- app/javascript/studio/profile_form.js
|
|
565
|
+
- app/javascript/studio/pull_to_refresh.js
|
|
558
566
|
- app/javascript/studio/sticky_table_header.js
|
|
559
567
|
- app/javascript/studio/stimulus.js
|
|
560
568
|
- app/javascript/studio/studio_confetti.js
|
|
@@ -562,6 +570,7 @@ files:
|
|
|
562
570
|
- app/javascript/studio/style_modals.js
|
|
563
571
|
- app/javascript/studio/style_section_nav.js
|
|
564
572
|
- app/javascript/studio/survey.js
|
|
573
|
+
- app/javascript/studio/talk_to_agent.js
|
|
565
574
|
- app/javascript/studio/theme_editor.js
|
|
566
575
|
- app/javascript/studio/toast.js
|
|
567
576
|
- app/javascript/studio/transition_snapshot.js
|
|
@@ -638,13 +647,16 @@ files:
|
|
|
638
647
|
- app/views/studio/_at_time_script.html.erb
|
|
639
648
|
- app/views/studio/_birthday_assets.html.erb
|
|
640
649
|
- app/views/studio/_board_assets.html.erb
|
|
650
|
+
- app/views/studio/_carousel.html.erb
|
|
641
651
|
- app/views/studio/_confirm_interstitial.html.erb
|
|
642
652
|
- app/views/studio/_cropper_assets.html.erb
|
|
653
|
+
- app/views/studio/_fizz.html.erb
|
|
643
654
|
- app/views/studio/_fizz_layer.html.erb
|
|
644
655
|
- app/views/studio/_hold_button.html.erb
|
|
645
656
|
- app/views/studio/_hold_button_guard.html.erb
|
|
646
657
|
- app/views/studio/_leveling_activity_assets.html.erb
|
|
647
658
|
- app/views/studio/_page_header.html.erb
|
|
659
|
+
- app/views/studio/_section_header.html.erb
|
|
648
660
|
- app/views/studio/_session_stamp.html.erb
|
|
649
661
|
- app/views/studio/admin_models/_arenas_table.html.erb
|
|
650
662
|
- app/views/studio/admin_models/_sessions_table.html.erb
|
|
@@ -655,6 +667,7 @@ files:
|
|
|
655
667
|
- app/views/studio/agent_chat/_chat.html.erb
|
|
656
668
|
- app/views/studio/agent_chat/_form.html.erb
|
|
657
669
|
- app/views/studio/agent_chat/_header.html.erb
|
|
670
|
+
- app/views/studio/agent_chat/_talk_modal.html.erb
|
|
658
671
|
- app/views/studio/agent_chat/_turn.html.erb
|
|
659
672
|
- app/views/studio/agent_chat/_typing.html.erb
|
|
660
673
|
- app/views/studio/agent_chat/_voice.html.erb
|
|
@@ -705,8 +718,11 @@ files:
|
|
|
705
718
|
- app/views/studio/knowledge_docs/preview.html.erb
|
|
706
719
|
- app/views/studio/knowledge_docs/show.html.erb
|
|
707
720
|
- app/views/studio/links/confirm.html.erb
|
|
721
|
+
- app/views/studio/loader/_infinite_scroll.html.erb
|
|
708
722
|
- app/views/studio/loader/_loader.html.erb
|
|
709
723
|
- app/views/studio/loader/_overlay.html.erb
|
|
724
|
+
- app/views/studio/loader/_pull_to_refresh.html.erb
|
|
725
|
+
- app/views/studio/loader/_skeleton.html.erb
|
|
710
726
|
- app/views/studio/local_emails/index.html.erb
|
|
711
727
|
- app/views/studio/mailers/_layered_banner.html.erb
|
|
712
728
|
- app/views/studio/marketing_kit/_assets.html.erb
|
|
@@ -793,6 +809,8 @@ files:
|
|
|
793
809
|
- app/views/style/_components.html.erb
|
|
794
810
|
- app/views/style/_glass.html.erb
|
|
795
811
|
- app/views/style/_host.html.erb
|
|
812
|
+
- app/views/style/_loaders.html.erb
|
|
813
|
+
- app/views/style/_loaders_feed_page.html.erb
|
|
796
814
|
- app/views/style/_modal_specimen.html.erb
|
|
797
815
|
- app/views/style/_modals.html.erb
|
|
798
816
|
- app/views/style/_scrims.html.erb
|
|
@@ -804,6 +822,7 @@ files:
|
|
|
804
822
|
- app/views/style/_type_ladder.html.erb
|
|
805
823
|
- app/views/style/board/_demo_card.html.erb
|
|
806
824
|
- app/views/style/index.html.erb
|
|
825
|
+
- app/views/style/loaders_feed.html.erb
|
|
807
826
|
- app/views/style/modals/_age_gate.html.erb
|
|
808
827
|
- app/views/style/modals/_birthday.html.erb
|
|
809
828
|
- app/views/style/modals/_ds_close_x.html.erb
|
|
@@ -855,6 +874,7 @@ files:
|
|
|
855
874
|
- lib/studio/cable.rb
|
|
856
875
|
- lib/studio/color_scale.rb
|
|
857
876
|
- lib/studio/component_gallery.rb
|
|
877
|
+
- lib/studio/crumbs.rb
|
|
858
878
|
- lib/studio/email.rb
|
|
859
879
|
- lib/studio/email_image_generator.rb
|
|
860
880
|
- lib/studio/email_smoke.rb
|