studio-engine 0.96.2.rc1 → 0.97.0.rc1
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 +183 -0
- data/app/assets/tailwind/studio_engine/engine-motion.css +57 -0
- data/app/assets/tailwind/studio_engine/engine.css +8 -0
- data/app/javascript/studio/alpine_shims.js +23 -0
- data/app/javascript/studio/application.js +9 -21
- data/app/javascript/studio/board.js +593 -0
- data/app/javascript/studio/booking.js +176 -0
- data/app/javascript/studio/controllers/board_controller.js +41 -0
- data/app/javascript/studio/controllers/booking_controller.js +24 -0
- data/app/javascript/studio/controllers/email_banner_scale_controller.js +22 -0
- data/app/javascript/studio/controllers/footer_map_controller.js +22 -0
- data/app/javascript/studio/controllers/geo_settings_controller.js +24 -0
- data/app/javascript/studio/controllers/hold_button_controller.js +64 -0
- data/app/javascript/studio/controllers/link_preview_card_controller.js +25 -0
- data/app/javascript/studio/controllers/link_sidebar_controller.js +18 -0
- data/app/javascript/studio/controllers/survey_controller.js +18 -0
- data/app/javascript/studio/controllers/toast_controller.js +26 -0
- data/app/javascript/studio/email_banner.js +277 -0
- data/app/javascript/studio/email_banner_scale.js +60 -0
- data/app/javascript/studio/footer_map.js +143 -0
- data/app/javascript/studio/geo_settings.js +105 -0
- data/app/javascript/studio/hold_button.js +416 -0
- data/app/javascript/studio/hold_button_hooks.js +162 -0
- data/app/javascript/studio/lazy_controllers.js +138 -0
- data/app/javascript/studio/leveling_activity.js +252 -0
- data/app/javascript/studio/link_preview_card.js +34 -0
- data/app/javascript/studio/link_sidebar.js +157 -0
- data/app/javascript/studio/stimulus.js +72 -0
- data/app/javascript/studio/survey.js +316 -0
- data/app/javascript/studio/theme_editor.js +197 -0
- data/app/javascript/studio/toast.js +270 -0
- data/app/views/components/_link_sidebar.html.erb +5 -100
- data/app/views/components/_link_sidebar_trigger.html.erb +2 -2
- data/app/views/layouts/studio/_flash.html.erb +13 -118
- data/app/views/layouts/studio/_head.html.erb +30 -14
- data/app/views/studio/_board_assets.html.erb +9 -452
- data/app/views/studio/_hold_button.html.erb +38 -445
- data/app/views/studio/_hold_button_guard.html.erb +172 -0
- data/app/views/studio/_leveling_activity_assets.html.erb +9 -283
- data/app/views/studio/board/_board.html.erb +16 -5
- data/app/views/studio/booking/_assets.html.erb +5 -139
- data/app/views/studio/booking/_frame.html.erb +3 -3
- data/app/views/studio/booking/_popup.html.erb +4 -4
- data/app/views/studio/emails/_banner_editor.html.erb +4 -152
- data/app/views/studio/emails/_banner_scale.html.erb +5 -56
- data/app/views/studio/emails/index.html.erb +0 -1
- data/app/views/studio/geo_settings/edit.html.erb +1 -97
- data/app/views/studio/site_footer/_map.html.erb +7 -5
- data/app/views/studio/site_footer/_map_assets.html.erb +5 -129
- data/app/views/studio/site_identities/edit.html.erb +1 -24
- data/app/views/studio/surveys/show.html.erb +4 -5
- data/app/views/style/_tasks.html.erb +3 -8
- data/app/views/style/_theme.html.erb +2 -52
- data/app/views/theme_settings/edit.html.erb +3 -82
- data/config/importmap.rb +6 -0
- data/docs/BOOKING.md +6 -5
- data/docs/SITE_FOOTER.md +16 -12
- data/lib/studio/version.rb +1 -1
- metadata +28 -3
- data/app/views/studio/emails/_recipient_repaint.html.erb +0 -122
- data/app/views/studio/surveys/_script.html.erb +0 -309
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ee44de927b41f3860880f106cf5abc81b69d076a7d35f4de767bd904533b63c4
|
|
4
|
+
data.tar.gz: 200c6bdb2758bc78fadded463649a281dadc7042b18d9a8634a33ab6efd5ddc2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d92ba31d0fd6a1ff1c5a2dd0d140fb6dc3c396e2e7813ab034d64666520c611a9497ec396d99307e59f67793b53295b88988c10f1b23e3025e142d1ade370834
|
|
7
|
+
data.tar.gz: ce67bc16e6c58eda9afa49a401d2b079b635340244d01320bc0cd67873d189e10c30b47e5fb53b6c52176c378fe79b17f399d6bcf9b3a94ac424df968b83376d
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,189 @@ The format is [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). This pro
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.97.0 — 2026-10-09
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **The toast queue, the link sidebar and the hold button move to ES modules and
|
|
12
|
+
Stimulus controllers.** `layouts/studio/_flash`, `components/_link_sidebar`
|
|
13
|
+
and `studio/_hold_button` render markup only; their inline scripts are gone.
|
|
14
|
+
Rendered markup and styling are unchanged apart from the attributes named
|
|
15
|
+
here.
|
|
16
|
+
- **Toast.** The queue is `studio/toast`, registered as `$store.toasts`. The
|
|
17
|
+
partial's root is a bare `x-data` carrying `data-studio-controller="toast"`
|
|
18
|
+
and the flash as `data-toast-initial-value`. The API is unchanged: dispatch
|
|
19
|
+
the `toast` window event. A page's Turbo snapshot no longer keeps its
|
|
20
|
+
flash, so Back does not replay it.
|
|
21
|
+
- **Link sidebar.** `$store.sidebars.linkTreeOpen` and the document click and
|
|
22
|
+
Escape handlers are `studio/link_sidebar`; the partial renders one
|
|
23
|
+
`<template data-studio-controller="link-sidebar">` anchor. The flag
|
|
24
|
+
registers only on a page that renders the panel, and a host's own
|
|
25
|
+
`sidebars` store keeps its keys.
|
|
26
|
+
- **Hold button.** The timeline, the idle nudge and the fizz portal are
|
|
27
|
+
`studio/hold_button`, on a `hold-button` controller that sits on the
|
|
28
|
+
`.hold-stack`; the button's presses are `data-studio-action`s. The idle
|
|
29
|
+
nudge runs only on a button the partial rendered, from the moment it
|
|
30
|
+
connects. `studio/stimulus` imports the controller statically, so it is
|
|
31
|
+
preloaded with the page and a button that renders later (a modal's) makes
|
|
32
|
+
no further request before its first press.
|
|
33
|
+
- `layouts/studio/_head` imports `studio/toast`, `studio/link_sidebar` and
|
|
34
|
+
`studio/stimulus` by their own nonced module tags, as it does
|
|
35
|
+
`studio/alpine_stores` and `studio/modal_host`, so a boot that fails to
|
|
36
|
+
load keeps a page its flash, its sidebar and its hold button.
|
|
37
|
+
- **The engine's Stimulus application is `studio/stimulus`.**
|
|
38
|
+
`studio/application` still exports `application` and `schema`. A controller
|
|
39
|
+
for one kind of page is listed in `studio/stimulus`'s `LAZY` and registered by
|
|
40
|
+
`studio/lazy_controllers` the first time an element names it; the list starts
|
|
41
|
+
empty. A lazy load that fails is final for the document, as it is in a
|
|
42
|
+
browser: the registry imports a controller once, reports a failure once, and
|
|
43
|
+
marks each element naming it with `data-studio-controller-failed`.
|
|
44
|
+
- **The admin pages, the email manager, booking, the footer map and the survey
|
|
45
|
+
stepper move to ES modules.** Their inline scripts are gone; rendered markup
|
|
46
|
+
and styling are unchanged apart from the `data-studio-controller` attributes
|
|
47
|
+
named here. Six controllers register lazily, each fetched only by a page that
|
|
48
|
+
names it:
|
|
49
|
+
- `geo-settings` on `/admin/geo`'s root (`studio/geo_settings`), and
|
|
50
|
+
`link-preview-card` on `/admin/link_preview`'s root
|
|
51
|
+
(`studio/link_preview_card`).
|
|
52
|
+
- `email-banner-scale` on the `<template>` anchor `studio/emails/_banner_scale`
|
|
53
|
+
renders (`studio/email_banner_scale`).
|
|
54
|
+
- `booking` on the frame's wrapper and the popup's dialog (`studio/booking`),
|
|
55
|
+
and `footer-map` on the map element (`studio/footer_map`). Both install
|
|
56
|
+
once per document under the same guards (`__studioBookingFramesArmed`,
|
|
57
|
+
`__studioBookingPopupArmed`, `__studioFooterMapsArmed`) and
|
|
58
|
+
`window.__studioBookingLoad` is still published. Until the booking
|
|
59
|
+
controller connects, a booking link is an ordinary link to the booking page.
|
|
60
|
+
- `survey` on the survey's root (`studio/survey`). Until it connects, and if
|
|
61
|
+
it never does, the page is the plain form.
|
|
62
|
+
- The theme editors and the email manager's editors stay Alpine factories:
|
|
63
|
+
`themeEditor` and `dsThemeEditor` are `studio/theme_editor`, and
|
|
64
|
+
`emailBannerEditor` and `emailRecipients` are `studio/email_banner`.
|
|
65
|
+
`studio/alpine_shims` publishes all four on every page, because an `x-data`
|
|
66
|
+
is evaluated the moment Alpine starts. `themeEditor` takes its colours as
|
|
67
|
+
an argument.
|
|
68
|
+
- **`test/views/no_inline_script_test.rb` holds the views to it.** A view with
|
|
69
|
+
an inline script fails unless it is on the test's allow-list, where each entry
|
|
70
|
+
names the task that owns it; an entry whose script is gone fails too. Two are
|
|
71
|
+
left inline on purpose: `studio/_at_time_script`, whose first pass runs before
|
|
72
|
+
first paint, and `solana_sessions/phantom_callback`, the wallet's return leg.
|
|
73
|
+
|
|
74
|
+
- **The board primitive and the leveling activity modals move to ES modules.**
|
|
75
|
+
`studio/_board_assets` and `studio/_leveling_activity_assets` render nothing;
|
|
76
|
+
their inline scripts are gone. A consumer's `render` of either keeps working
|
|
77
|
+
and can be deleted. Rendered markup is unchanged apart from
|
|
78
|
+
`data-studio-controller="board"` on the board's `<section>`.
|
|
79
|
+
- **Board.** The factory is `studio/board`. `x-data="studioBoard({...})"`
|
|
80
|
+
still resolves: `studio/alpine_shims` publishes `window.studioBoard` on
|
|
81
|
+
every page, and every name on the scope is unchanged (`state`, `toasts`,
|
|
82
|
+
`toast`, `updateCounts`, `animateCardExit`, the state helpers). The zones
|
|
83
|
+
are made draggable by a `board` controller, registered lazily, once
|
|
84
|
+
SortableJS has loaded; `data-alpine-ready` is set after that, so it still
|
|
85
|
+
means "the board drags". A board written by hand with only the `x-data`
|
|
86
|
+
names the controller on itself.
|
|
87
|
+
- **A board whose controller fails to load says so.** The board controller is
|
|
88
|
+
lazy, and a failed lazy load is final for the document. The board's section
|
|
89
|
+
then carries `data-studio-controller-failed="board"` and shows "This board
|
|
90
|
+
could not load its controls. Reload the page." above its cards, which stay
|
|
91
|
+
readable; the notice is revealed by a rule in `engine.css`, so an app sees
|
|
92
|
+
it once its Tailwind build includes this engine's `engine.css`.
|
|
93
|
+
- **Leveling activity.** The factory is `studio/leveling_activity`, published
|
|
94
|
+
as `window.levelingActionModal`. Its opts and JSON contract are unchanged.
|
|
95
|
+
- **SortableJS loads only on a page that drags.** `layouts/studio/_head` no
|
|
96
|
+
longer loads `studio/sortable` on every page. The vendored build is pinned as
|
|
97
|
+
`sortablejs` and imported by `studio/board` on the first board a page
|
|
98
|
+
renders. `window.Sortable` is a shim until then: `Sortable.create(el, options)`
|
|
99
|
+
in a page script loads the library and then creates the sortable, so a host
|
|
100
|
+
that calls it (the hub's deploy board) needs no change. The shim's `create`
|
|
101
|
+
returns nothing; `await Sortable.load()` resolves with SortableJS for a
|
|
102
|
+
caller that needs the instance. canvas-confetti and `studio_confetti` stay in
|
|
103
|
+
the head: `fireSuccessConfetti` and consumer scripts call them on any page.
|
|
104
|
+
|
|
105
|
+
### Added
|
|
106
|
+
|
|
107
|
+
- **The hold button dispatches `hold-button:guard`, `hold-button:start`,
|
|
108
|
+
`hold-button:validate`, `hold-button:early` and `hold-button:success`**, on
|
|
109
|
+
the button, bubbling, each with `detail.id` (the `hold_id`). `preventDefault()`
|
|
110
|
+
on `guard` refuses the hold, on `early` takes the action over, and on
|
|
111
|
+
`success` leaves the button's state to the listener;
|
|
112
|
+
`$event.detail.waitUntil(answer)` on `validate` takes a boolean or a promise,
|
|
113
|
+
and a false or failed answer aborts the hold. The string locals (`guard:`,
|
|
114
|
+
`on_hold_start:`, `validate:`, `early_action:`, `early_action_guard:`,
|
|
115
|
+
`on_success:`) still work and are heard beside the events; write new call
|
|
116
|
+
sites against the events. `validate_at:` and `early_action_at:` are honoured
|
|
117
|
+
without their string local.
|
|
118
|
+
- **The hold button fails safe.** A `guard:` that throws, or that has no Alpine
|
|
119
|
+
scope to run in, refuses the hold (it used to let the hold through); a second
|
|
120
|
+
press without a release restarts the hold, so one hold confirms once; a
|
|
121
|
+
validation answer for a press that was released does not abort the next one;
|
|
122
|
+
nothing of the timeline runs after the hold completes.
|
|
123
|
+
|
|
124
|
+
### Fixed
|
|
125
|
+
|
|
126
|
+
- **The style guide's theme editor sends a save once.** The controller answers
|
|
127
|
+
a save with a 302 to `/admin/theme`, and a fetch that follows a 302 keeps a
|
|
128
|
+
PATCH a PATCH, so Save sent the theme twenty-one times and then toasted "Save
|
|
129
|
+
failed". The request no longer follows the redirect.
|
|
130
|
+
- **The email manager's banner editor repaints the banner on the email's own
|
|
131
|
+
page.** `studio/emails/_banner_preview` isolates the banner in an iframe, and
|
|
132
|
+
the editor looked for its nodes in the page's own document only, so typing a
|
|
133
|
+
header, sub-text or tint changed nothing there. The editor now reaches into
|
|
134
|
+
the frame, as the emails list already did.
|
|
135
|
+
- **Two boards on one page no longer drive each other's zones.** A board made
|
|
136
|
+
every `.kanban-dropzone` on the page sortable and counted cards by document
|
|
137
|
+
id, so the first board's group, filter and lock rule governed every board
|
|
138
|
+
after it: on `/admin/style` the depth-chart specimen's cards left their
|
|
139
|
+
lanes and its locked starters dragged. A board now wires, watches and counts
|
|
140
|
+
only the zones inside its own element.
|
|
141
|
+
- **A hold button that cannot work says so.** The button runs on five modules,
|
|
142
|
+
and a browser keeps a failed module request for the life of the document, so
|
|
143
|
+
one failure among them at page load left the button rendered, enabled and
|
|
144
|
+
deaf: a full hold sent nothing and showed nothing until a reload. The head
|
|
145
|
+
now carries a small inline, nonced guard (`studio/_hold_button_guard`) that
|
|
146
|
+
imports nothing. A `.hold-stack` whose controller has not connected 1.5 s
|
|
147
|
+
after `DOMContentLoaded` (or shortly after it arrives later, by a Turbo visit
|
|
148
|
+
or a modal's `x-if`) is marked `data-studio-controller-failed="hold-button"`:
|
|
149
|
+
the button dims and is `aria-disabled`, the bubbles stop, and "This button
|
|
150
|
+
could not load. Reload the page." shows under it in a `role="status"`
|
|
151
|
+
region; a press says it again. The controller writes
|
|
152
|
+
`data-hold-button-connected` on its stack and clears the mark the moment it
|
|
153
|
+
connects, however late. `studio/_hold_button` renders one more element, an
|
|
154
|
+
empty `<span class="hold-notice" role="status">` held out of the layout, so
|
|
155
|
+
a working button measures as before. A host with a nonce-based
|
|
156
|
+
`script-src` needs nothing new; one that allow-lists inline scripts by hash
|
|
157
|
+
adds this script's.
|
|
158
|
+
|
|
159
|
+
### Breaking
|
|
160
|
+
|
|
161
|
+
- **`window.toastManager` is gone.** Nothing binds it: the flash partial reads
|
|
162
|
+
`$store.toasts`. A template that wrote `x-data="toastManager(...)"` of its own
|
|
163
|
+
renders `layouts/studio/flash` and dispatches the `toast` event instead.
|
|
164
|
+
- **`window.holdBtnStart`, `window.holdBtnEnd` and `window._holdBtnInit` are
|
|
165
|
+
gone.** The button binds its own presses; a page that called either function
|
|
166
|
+
dispatches the pointer events on the button, or renders the partial.
|
|
167
|
+
- **`window.__studioLinkSidebarBridge` is gone.** It was the inline script's
|
|
168
|
+
run-once flag; a test that looked for it in a page's HTML looks for
|
|
169
|
+
`data-studio-controller="link-sidebar"`.
|
|
170
|
+
- **`studio/emails/_recipient_repaint` and `studio/surveys/_script` are gone.**
|
|
171
|
+
Each rendered only a script. The engine's own pages no longer render them; a
|
|
172
|
+
host template that did deletes the line.
|
|
173
|
+
- **The footer's and the booking primitives' scripts are no longer in the
|
|
174
|
+
page's HTML.** A test that looked for `__studioFooterMapsArmed`,
|
|
175
|
+
`__studioBookingFramesArmed` or `__studioBookingPopupArmed` in a response body
|
|
176
|
+
looks for `data-studio-controller="footer-map"` on the map, or
|
|
177
|
+
`data-studio-controller="booking"` on the frame's wrapper and the dialog. The
|
|
178
|
+
globals themselves are still set, once the controller has connected.
|
|
179
|
+
`window.__studioSurveyBound` and `window.__studioSurveyTurboHook` are gone;
|
|
180
|
+
nothing outside the survey's script read them.
|
|
181
|
+
- **`window.Sortable` is not SortableJS until a page asks for it.** On a page
|
|
182
|
+
with no board it is the loading shim, which has `create` and `load` and
|
|
183
|
+
nothing else: `new Sortable(...)`, `Sortable.get` and the other statics fail
|
|
184
|
+
until the library has loaded. A page script that needs more than `create`
|
|
185
|
+
awaits `Sortable.load()` first. A page that loads its own SortableJS is
|
|
186
|
+
unaffected. A test that looked for `window.studioBoard =` or a
|
|
187
|
+
`studio/sortable` script tag in a page's HTML looks for
|
|
188
|
+
`data-studio-controller="board"` on the board.
|
|
189
|
+
|
|
7
190
|
## 0.96.2 — 2026-10-08
|
|
8
191
|
|
|
9
192
|
### Added
|
|
@@ -1733,6 +1733,63 @@ body.modal-open { overflow: visible; }
|
|
|
1733
1733
|
z-index: 1;
|
|
1734
1734
|
}
|
|
1735
1735
|
|
|
1736
|
+
/* THE BUTTON THAT COULD NOT LOAD. The guard in the head
|
|
1737
|
+
(studio/_hold_button_guard) marks a stack whose controller never connected
|
|
1738
|
+
data-studio-controller-failed="hold-button" and fills its .hold-notice. Until
|
|
1739
|
+
then the notice is an empty live region held out of the layout, so a working
|
|
1740
|
+
button measures exactly as it does without one. Marked, the button reads as
|
|
1741
|
+
unavailable, the bubbles stop, and the notice sits under the button in the
|
|
1742
|
+
danger ink, which the theme resolver holds to AA on every surface. */
|
|
1743
|
+
.hold-stack > .hold-notice {
|
|
1744
|
+
position: absolute;
|
|
1745
|
+
width: 1px;
|
|
1746
|
+
height: 1px;
|
|
1747
|
+
overflow: hidden;
|
|
1748
|
+
clip-path: inset(50%);
|
|
1749
|
+
white-space: nowrap;
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
.hold-stack[data-studio-controller-failed~="hold-button"] > .hold-btn {
|
|
1753
|
+
opacity: 0.45;
|
|
1754
|
+
filter: grayscale(0.7);
|
|
1755
|
+
cursor: not-allowed;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
.hold-stack[data-studio-controller-failed~="hold-button"] > .hold-fizz,
|
|
1759
|
+
.hold-stack[data-studio-controller-failed~="hold-button"] > .hold-fizz-portal {
|
|
1760
|
+
display: none;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
.hold-stack[data-studio-controller-failed~="hold-button"] > .hold-notice {
|
|
1764
|
+
position: static;
|
|
1765
|
+
display: block;
|
|
1766
|
+
width: auto;
|
|
1767
|
+
height: auto;
|
|
1768
|
+
overflow: visible;
|
|
1769
|
+
clip-path: none;
|
|
1770
|
+
white-space: normal;
|
|
1771
|
+
margin-top: 0.5rem;
|
|
1772
|
+
font-size: 0.8125rem;
|
|
1773
|
+
font-weight: 600;
|
|
1774
|
+
line-height: 1.35;
|
|
1775
|
+
text-align: center;
|
|
1776
|
+
color: var(--color-danger-ink, var(--color-danger));
|
|
1777
|
+
}
|
|
1778
|
+
|
|
1779
|
+
/* A press on the marked button: the notice answers it, with a pulse only for
|
|
1780
|
+
a reader who has not asked for less motion. */
|
|
1781
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1782
|
+
.hold-stack[data-hold-notice-pressed] > .hold-notice {
|
|
1783
|
+
animation: hold-notice-pressed 0.45s ease-out;
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
@keyframes hold-notice-pressed {
|
|
1788
|
+
0% { transform: scale(1); }
|
|
1789
|
+
35% { transform: scale(1.06); }
|
|
1790
|
+
100% { transform: scale(1); }
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1736
1793
|
.hold-stack > .hold-fizz,
|
|
1737
1794
|
.hold-stack > .hold-fizz-portal,
|
|
1738
1795
|
.hold-fizz-portal > .hold-fizz {
|
|
@@ -565,3 +565,11 @@ body.modal-open .studio-app-banner {
|
|
|
565
565
|
}
|
|
566
566
|
}
|
|
567
567
|
}
|
|
568
|
+
|
|
569
|
+
/* A board whose controller failed to load (studio/lazy_controllers marks its
|
|
570
|
+
section data-studio-controller-failed="board") shows the notice
|
|
571
|
+
studio/board/_board renders with an inline display: none. !important is what
|
|
572
|
+
lets a stylesheet rule answer an inline style. */
|
|
573
|
+
.studio-board[data-studio-controller-failed~="board"] > .studio-board-failed {
|
|
574
|
+
display: block !important;
|
|
575
|
+
}
|
|
@@ -19,6 +19,10 @@ import { NavCollapse } from "studio/nav_collapse"
|
|
|
19
19
|
import {
|
|
20
20
|
showNavSpinner, hideNavSpinner, installSpinnerReset, fireSuccessConfetti
|
|
21
21
|
} from "studio/head_chrome"
|
|
22
|
+
import { studioBoard, loadSortable, sortableShim } from "studio/board"
|
|
23
|
+
import { levelingActionModal } from "studio/leveling_activity"
|
|
24
|
+
import { themeEditor, dsThemeEditor } from "studio/theme_editor"
|
|
25
|
+
import { emailBannerEditor, emailRecipients } from "studio/email_banner"
|
|
22
26
|
|
|
23
27
|
// x-data="navCollapse()": the hub's own header. A host that defines its own
|
|
24
28
|
// window.navCollapse (turf-monster does, inline, before this runs) keeps it.
|
|
@@ -41,5 +45,24 @@ export function installAlpineShims() {
|
|
|
41
45
|
if (!window.showNavSpinner) window.showNavSpinner = showNavSpinner
|
|
42
46
|
if (!window.hideNavSpinner) window.hideNavSpinner = hideNavSpinner
|
|
43
47
|
if (!window.fireSuccessConfetti) window.fireSuccessConfetti = fireSuccessConfetti
|
|
48
|
+
// x-data="studioBoard({...})": studio/board/_board, and any board a host
|
|
49
|
+
// writes by hand. Alpine passes the opts alone.
|
|
50
|
+
if (!window.studioBoard) window.studioBoard = (opts) => studioBoard(opts)
|
|
51
|
+
// x-data="levelingActionModal({...})": studio/modals/blocks/_leveling_activity
|
|
52
|
+
// and _change_username.
|
|
53
|
+
if (!window.levelingActionModal) window.levelingActionModal = (opts) => levelingActionModal(opts)
|
|
54
|
+
// Sortable.create(el, options) in a page script (the hub's deploy board):
|
|
55
|
+
// no page carries SortableJS until something asks for it, so the call loads
|
|
56
|
+
// it. SortableJS replaces this object when it arrives; a page that loads its
|
|
57
|
+
// own copy (turf-monster's slate page) replaces it the same way.
|
|
58
|
+
if (!window.Sortable) window.Sortable = sortableShim(() => loadSortable())
|
|
59
|
+
// x-data="themeEditor({...})" (theme_settings/edit) and
|
|
60
|
+
// x-data="dsThemeEditor({...})" (style/_theme). Alpine passes the seed alone.
|
|
61
|
+
if (!window.themeEditor) window.themeEditor = (seed) => themeEditor(seed)
|
|
62
|
+
if (!window.dsThemeEditor) window.dsThemeEditor = (seed) => dsThemeEditor(seed)
|
|
63
|
+
// x-data="emailBannerEditor({...})" (studio/emails/show) and
|
|
64
|
+
// x-data="emailRecipients({...})" (studio/emails/index).
|
|
65
|
+
if (!window.emailBannerEditor) window.emailBannerEditor = (config) => emailBannerEditor(config)
|
|
66
|
+
if (!window.emailRecipients) window.emailRecipients = (config) => emailRecipients(config)
|
|
44
67
|
installSpinnerReset()
|
|
45
68
|
}
|
|
@@ -2,38 +2,26 @@
|
|
|
2
2
|
// layouts/studio/_head (javascript_import_module_tag, which carries the
|
|
3
3
|
// request's CSP nonce).
|
|
4
4
|
//
|
|
5
|
-
// The
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// so a host's Stimulus application never sees an engine controller. That is not
|
|
10
|
-
// tidiness: stimulus-loading's lazy loader (cyvasse) imports
|
|
11
|
-
// "controllers/<identifier>_controller" for every data-controller it meets, and
|
|
12
|
-
// would log "Failed to autoload controller" for each engine element. Values and
|
|
13
|
-
// classes keep Stimulus' own naming (data-nav-collapse-scrolled-class).
|
|
14
|
-
// "@hotwired/stimulus" resolves to the engine's vendored copy unless the host
|
|
15
|
-
// pins its own.
|
|
5
|
+
// The Stimulus application itself, its attribute schema, the hold button and
|
|
6
|
+
// the lazily registered page-specific controllers are studio/stimulus. This
|
|
7
|
+
// file registers the every-page chrome on it.
|
|
16
8
|
//
|
|
17
9
|
// Everything this file imports statically is preloaded on every page
|
|
18
10
|
// (Studio::Engine.javascript_boot_graph), so the boot costs one round trip.
|
|
19
|
-
import {
|
|
11
|
+
import { application, schema } from "studio/stimulus"
|
|
20
12
|
import NavCollapseController from "studio/controllers/nav_collapse_controller"
|
|
21
13
|
import ModalHostController from "studio/controllers/modal_host_controller"
|
|
14
|
+
import ToastController from "studio/controllers/toast_controller"
|
|
15
|
+
import LinkSidebarController from "studio/controllers/link_sidebar_controller"
|
|
22
16
|
import { startPinnedStack } from "studio/pinned_stack"
|
|
23
17
|
import { installAlpineShims } from "studio/alpine_shims"
|
|
24
18
|
|
|
25
19
|
installAlpineShims()
|
|
26
20
|
startPinnedStack()
|
|
27
21
|
|
|
28
|
-
export const schema = {
|
|
29
|
-
...defaultSchema,
|
|
30
|
-
controllerAttribute: "data-studio-controller",
|
|
31
|
-
actionAttribute: "data-studio-action",
|
|
32
|
-
targetAttribute: "data-studio-target"
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const application = Application.start(document.documentElement, schema)
|
|
36
22
|
application.register("nav-collapse", NavCollapseController)
|
|
37
23
|
application.register("modal-host", ModalHostController)
|
|
24
|
+
application.register("toast", ToastController)
|
|
25
|
+
application.register("link-sidebar", LinkSidebarController)
|
|
38
26
|
|
|
39
|
-
export { application }
|
|
27
|
+
export { application, schema }
|