@crievo/omni 0.1.3 → 0.1.4
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.
- package/package.json +2 -1
- package/reference/learnings.md +12 -0
- package/studio/api/app.ts +2 -2
- package/studio/api/routes/sound.ts +22 -3
- package/studio/api/services/sound.ts +45 -0
- package/studio/studio.ts +1 -0
- package/studio/web/components/AppShell.tsx +3 -1
- package/studio/web/components/CloneVoiceDialog/RecordStep.tsx +3 -0
- package/studio/web/components/CloneVoiceDialog/RecorderBar.tsx +37 -20
- package/studio/web/components/CloneVoiceDialog/useCloneVoice.ts +39 -12
- package/studio/web/components/MissingDmsPanel/BatchSend.tsx +13 -4
- package/studio/web/components/Omni/OmniWidget.tsx +14 -5
- package/studio/web/components/Omni/PendingActions.tsx +25 -6
- package/studio/web/components/OmnichatRulePanel/RuleConfig.tsx +13 -3
- package/studio/web/components/OmnichatRulePanel/RuleEnableConfirm.tsx +14 -4
- package/studio/web/components/ResultMessage.tsx +12 -3
- package/studio/web/components/Sidebar.tsx +63 -24
- package/studio/web/components/StageStepper.tsx +105 -34
- package/studio/web/components/Toaster.tsx +25 -0
- package/studio/web/components/VoiceCarousel.tsx +19 -16
- package/studio/web/components/VoiceProfilesSettings.tsx +8 -3
- package/studio/web/components/bencho/ActionNode.tsx +456 -0
- package/studio/web/components/bencho/AssigneePicker.tsx +246 -0
- package/studio/web/components/bencho/BenchoScope.tsx +8 -0
- package/studio/web/components/bencho/Checklist.tsx +421 -0
- package/studio/web/components/bencho/CreateMenu.tsx +258 -0
- package/studio/web/components/bencho/GenerateImage.tsx +290 -0
- package/studio/web/components/bencho/ImageAccordion.tsx +273 -0
- package/studio/web/components/bencho/LiquidToggle.tsx +289 -0
- package/studio/web/components/bencho/MagnifyDock.tsx +200 -0
- package/studio/web/components/bencho/NowPlaying.tsx +403 -0
- package/studio/web/components/bencho/OneTimeCode.tsx +374 -0
- package/studio/web/components/bencho/PullToRefresh.tsx +527 -0
- package/studio/web/components/bencho/SlideToConfirm.tsx +385 -0
- package/studio/web/components/bencho/SloshSlider.tsx +394 -0
- package/studio/web/components/bencho/StackedBars.tsx +342 -0
- package/studio/web/components/bencho/ToastStack.tsx +263 -0
- package/studio/web/components/bencho/UploadDropzone.tsx +394 -0
- package/studio/web/components/bencho/VoiceNote.tsx +705 -0
- package/studio/web/components/icons.tsx +27 -0
- package/studio/web/components/ui/slider.tsx +34 -1
- package/studio/web/components/ui/switch.tsx +18 -5
- package/studio/web/index.html +1 -1
- package/studio/web/lib/omni-panel.ts +4 -1
- package/studio/web/lib/toast.ts +196 -0
- package/studio/web/lib/upload.ts +24 -0
- package/studio/web/pages/BenchoPage/index.tsx +74 -0
- package/studio/web/pages/BenchoPage/registry.ts +174 -0
- package/studio/web/pages/NewVideoPage/index.tsx +6 -2
- package/studio/web/pages/ReferencesPage/index.tsx +4 -1
- package/studio/web/pages/VideoPage/components/ChangedVoices.tsx +14 -17
- package/studio/web/pages/VideoPage/components/LineTextEditor.tsx +1 -1
- package/studio/web/pages/VideoPage/components/PublishForm.tsx +24 -17
- package/studio/web/pages/VideoPage/components/ScheduledInfo.tsx +2 -1
- package/studio/web/pages/VideoPage/components/SoundTimeline/AddSound.tsx +12 -14
- package/studio/web/pages/VideoPage/components/SoundTimeline/BedRow.tsx +27 -11
- package/studio/web/pages/VideoPage/components/SoundTimeline/CaptionSaveBar.tsx +22 -18
- package/studio/web/pages/VideoPage/components/SoundTimeline/TimelineFooter.tsx +3 -4
- package/studio/web/pages/VideoPage/components/SoundTimeline/UploadTrack.tsx +59 -0
- package/studio/web/pages/VideoPage/components/SoundTimeline/useSoundTimeline.ts +1 -0
- package/studio/web/pages/VideoPage/components/VoicePauseBanner.tsx +4 -6
- package/studio/web/pages/VideoPage/index.tsx +4 -0
- package/studio/web/pages/VideosPage/components/VideoRow.tsx +2 -4
- package/studio/web/router.tsx +8 -0
- package/studio/web/styles/components/bencho/action-node.css +227 -0
- package/studio/web/styles/components/bencho/checklist.css +182 -0
- package/studio/web/styles/components/bencho/dock.css +188 -0
- package/studio/web/styles/components/bencho/gallery.css +109 -0
- package/studio/web/styles/components/bencho/generate.css +151 -0
- package/studio/web/styles/components/bencho/image-accordion.css +37 -0
- package/studio/web/styles/components/bencho/liq-create.css +279 -0
- package/studio/web/styles/components/bencho/liq-toggle.css +106 -0
- package/studio/web/styles/components/bencho/one-time-code.css +148 -0
- package/studio/web/styles/components/bencho/picker.css +204 -0
- package/studio/web/styles/components/bencho/pull.css +313 -0
- package/studio/web/styles/components/bencho/scope.css +42 -0
- package/studio/web/styles/components/bencho/slide-confirm.css +139 -0
- package/studio/web/styles/components/bencho/slosh.css +137 -0
- package/studio/web/styles/components/bencho/sound.css +260 -0
- package/studio/web/styles/components/bencho/stacked-bars.css +334 -0
- package/studio/web/styles/components/bencho/toast-stack.css +192 -0
- package/studio/web/styles/components/bencho/tokens.css +243 -0
- package/studio/web/styles/components/bencho/upload-dropzone.css +352 -0
- package/studio/web/styles/components/bencho/voice-note.css +337 -0
- package/studio/web/styles/components/clone-voice.css +12 -2
- package/studio/web/styles/components/omni.css +6 -1
- package/studio/web/styles/components/stepper.css +123 -7
- package/studio/web/styles/components/toaster.css +10 -0
- package/studio/web/styles/components/ui/slider.css +6 -16
- package/studio/web/styles/components/ui/switch.css +2 -41
- package/studio/web/styles/components/voice-carousel.css +46 -4
- package/studio/web/styles/index.css +23 -0
- package/studio/web/styles/pages/video/layout.css +1 -4
- package/studio/web/styles/pages/video/sound-timeline.css +8 -0
- package/studio/web/styles/theme/identity/shell.css +10 -26
- package/tools/sound.mjs +67 -3
|
@@ -0,0 +1,337 @@
|
|
|
1
|
+
/* ══ Voice note ═══════════════════════════════════════════ */
|
|
2
|
+
/* a fixed frame, so opening the pill never rescales the block */
|
|
3
|
+
.bn-vn-frame {
|
|
4
|
+
position: relative;
|
|
5
|
+
width: 300px;
|
|
6
|
+
height: 156px;
|
|
7
|
+
display: grid;
|
|
8
|
+
place-items: center;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.bn-vn {
|
|
12
|
+
--red: #e5484d;
|
|
13
|
+
position: relative;
|
|
14
|
+
width: var(--w);
|
|
15
|
+
max-width: 100%;
|
|
16
|
+
height: 56px;
|
|
17
|
+
border-radius: var(--r);
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
background: var(--fill-slab, var(--card));
|
|
20
|
+
color: var(--fill-on, var(--ink));
|
|
21
|
+
font-family: var(--font-ui);
|
|
22
|
+
font-size: 16px;
|
|
23
|
+
font-weight: 500;
|
|
24
|
+
user-select: none;
|
|
25
|
+
-webkit-user-select: none;
|
|
26
|
+
touch-action: none;
|
|
27
|
+
cursor: pointer;
|
|
28
|
+
-webkit-tap-highlight-color: transparent;
|
|
29
|
+
/* y1 past 1 is the overshoot; Bounce sets it */
|
|
30
|
+
transition:
|
|
31
|
+
width 420ms cubic-bezier(0.3, var(--ov), 0.4, 1),
|
|
32
|
+
scale 220ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
33
|
+
letter-spacing: -0.01em;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
[data-stroke="on"] .bn-vn {
|
|
37
|
+
box-shadow: inset 0 0 0 1px var(--pane-edge);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.bn-vn[data-phase="clip"] {
|
|
41
|
+
cursor: default;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* tap to record, in a screen rather than on a stage: the frame is as wide as the room it is given and as tall as the
|
|
45
|
+
pill, and the red line under it takes flow space instead of the hint's reserved band */
|
|
46
|
+
.bn-vn-frame[data-mode="tap"] {
|
|
47
|
+
width: 100%;
|
|
48
|
+
height: auto;
|
|
49
|
+
display: flex;
|
|
50
|
+
flex-direction: column;
|
|
51
|
+
align-items: center;
|
|
52
|
+
gap: 8px;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/* inside a screen the pill sits on a surface almost as light as itself: a hairline holds its edge */
|
|
56
|
+
.bn-vn[data-mode="tap"] {
|
|
57
|
+
box-shadow: inset 0 0 0 1px rgba(var(--ink-rgb, 23, 24, 26), 0.1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.bn-vn[data-disabled] {
|
|
61
|
+
opacity: 0.45;
|
|
62
|
+
cursor: not-allowed;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.bn-vn:focus-visible,
|
|
66
|
+
.bn-vn[data-mode="tap"]:focus-visible {
|
|
67
|
+
outline: none;
|
|
68
|
+
box-shadow:
|
|
69
|
+
0 0 0 2px var(--fill-slab, #fff),
|
|
70
|
+
0 0 0 4px var(--signal, #2231dd);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.bn-vn-in {
|
|
74
|
+
position: absolute;
|
|
75
|
+
inset: 0;
|
|
76
|
+
display: flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
white-space: nowrap;
|
|
79
|
+
animation: bn-vn-in 240ms ease 80ms both;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.bn-vn-idle {
|
|
83
|
+
justify-content: center;
|
|
84
|
+
gap: 12px;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.bn-vn-rec {
|
|
88
|
+
gap: 12px;
|
|
89
|
+
padding: 0 24px;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.bn-vn-clip {
|
|
93
|
+
gap: 12px;
|
|
94
|
+
padding: 0 12px 0 8px;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* the stop and cancel buttons ride the end of the row; the clock and wave give up the room */
|
|
98
|
+
.bn-vn[data-mode="tap"] .bn-vn-rec {
|
|
99
|
+
gap: 8px;
|
|
100
|
+
padding: 0 6px 0 22px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.bn-vn[data-mode="tap"] .bn-vn-rec .bn-vn-time {
|
|
104
|
+
margin-right: 4px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.bn-vn[data-mode="tap"] .bn-vn-clip {
|
|
108
|
+
gap: 8px;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.bn-vn[data-mode="tap"] .bn-vn-clip .bn-vn-time {
|
|
112
|
+
margin-inline: 4px;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.bn-vn-time {
|
|
116
|
+
font-variant-numeric: tabular-nums;
|
|
117
|
+
min-width: 38px;
|
|
118
|
+
opacity: 0.6;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.bn-vn-rec .bn-vn-time {
|
|
122
|
+
opacity: 1;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.bn-vn-dot {
|
|
126
|
+
width: 9px;
|
|
127
|
+
height: 9px;
|
|
128
|
+
flex: none;
|
|
129
|
+
border-radius: 50%;
|
|
130
|
+
background: var(--red);
|
|
131
|
+
animation: bn-vn-blink 1s ease-in-out infinite;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.bn-vn-wave {
|
|
135
|
+
flex: 1;
|
|
136
|
+
height: 32px;
|
|
137
|
+
display: flex;
|
|
138
|
+
align-items: center;
|
|
139
|
+
justify-content: space-between;
|
|
140
|
+
/* the wave goes quiet as you drag toward throwing it away */
|
|
141
|
+
opacity: calc(1 - var(--pull) * 0.7);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.bn-vn-bar {
|
|
145
|
+
width: 3px;
|
|
146
|
+
flex: none;
|
|
147
|
+
height: calc(4px + var(--l) * 28px);
|
|
148
|
+
border-radius: 2px;
|
|
149
|
+
background: currentColor;
|
|
150
|
+
transition: height 160ms linear;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* each new sample grows in from the middle */
|
|
154
|
+
.bn-vn-rec .bn-vn-bar {
|
|
155
|
+
animation: bn-vn-grow 200ms cubic-bezier(0.3, 1.5, 0.4, 1) both;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/* the playhead: a bar is lit once progress has passed it */
|
|
159
|
+
.bn-vn-scrub {
|
|
160
|
+
cursor: ew-resize;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.bn-vn-scrub .bn-vn-bar {
|
|
164
|
+
transition: none;
|
|
165
|
+
opacity: clamp(0.3, calc((var(--prog) * var(--n) - var(--i)) * 99), 1);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* thrown away: the bars fold to nothing before the pill closes */
|
|
169
|
+
.bn-vn[data-phase="cancel"] .bn-vn-in {
|
|
170
|
+
animation: none;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.bn-vn[data-phase="cancel"] .bn-vn-bar {
|
|
174
|
+
scale: 1 0;
|
|
175
|
+
opacity: 0;
|
|
176
|
+
transition:
|
|
177
|
+
scale 220ms ease,
|
|
178
|
+
opacity 220ms ease;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.bn-vn[data-phase="cancel"] .bn-vn-dot,
|
|
182
|
+
.bn-vn[data-phase="cancel"] .bn-vn-time,
|
|
183
|
+
.bn-vn[data-phase="cancel"] button {
|
|
184
|
+
opacity: 0;
|
|
185
|
+
transition: opacity 160ms ease;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.bn-vn-play,
|
|
189
|
+
.bn-vn-x {
|
|
190
|
+
display: grid;
|
|
191
|
+
place-items: center;
|
|
192
|
+
flex: none;
|
|
193
|
+
padding: 0;
|
|
194
|
+
border: 0;
|
|
195
|
+
cursor: pointer;
|
|
196
|
+
font: inherit;
|
|
197
|
+
-webkit-tap-highlight-color: transparent;
|
|
198
|
+
transition:
|
|
199
|
+
scale 160ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
200
|
+
color 160ms ease;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.bn-vn-play {
|
|
204
|
+
width: 44px;
|
|
205
|
+
height: 44px;
|
|
206
|
+
border-radius: var(--inner);
|
|
207
|
+
background: var(--fill-on, var(--ink));
|
|
208
|
+
color: var(--fill-slab, var(--card));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.bn-vn-x {
|
|
212
|
+
width: 32px;
|
|
213
|
+
height: 32px;
|
|
214
|
+
border-radius: 50%;
|
|
215
|
+
background: none;
|
|
216
|
+
color: color-mix(in srgb, var(--fill-on, var(--ink)) 50%, var(--fill-slab, var(--card)));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.bn-vn-x:hover {
|
|
220
|
+
color: var(--fill-on, var(--ink));
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.bn-vn-play:active,
|
|
224
|
+
.bn-vn-x:active {
|
|
225
|
+
scale: 0.96;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.bn-vn-play:focus-visible,
|
|
229
|
+
.bn-vn-x:focus-visible {
|
|
230
|
+
outline: 2px solid var(--signal, #2231dd);
|
|
231
|
+
outline-offset: 2px;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.bn-vn-hint {
|
|
235
|
+
position: absolute;
|
|
236
|
+
left: 0;
|
|
237
|
+
right: 0;
|
|
238
|
+
top: calc(50% + 42px);
|
|
239
|
+
text-align: center;
|
|
240
|
+
font-family: var(--font-ui);
|
|
241
|
+
font-size: 13px;
|
|
242
|
+
color: var(--ink-3);
|
|
243
|
+
opacity: 0;
|
|
244
|
+
pointer-events: none;
|
|
245
|
+
transition: opacity 220ms ease;
|
|
246
|
+
letter-spacing: 0em;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.bn-vn-hint[data-on] {
|
|
250
|
+
opacity: calc(1 - var(--pull, 0));
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.bn-vn-hint[data-armed] {
|
|
254
|
+
opacity: 1;
|
|
255
|
+
color: var(--red, #e5484d);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* the row fades as it slides, so the cancel mark has the left
|
|
259
|
+
end of the pill to itself when it arrives */
|
|
260
|
+
.bn-vn-rec {
|
|
261
|
+
opacity: calc(1 - var(--pull) * 0.55);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/* the dot and the clock are gone before the mark lands on them */
|
|
265
|
+
.bn-vn-rec .bn-vn-dot,
|
|
266
|
+
.bn-vn-rec .bn-vn-time {
|
|
267
|
+
opacity: max(0, 1 - var(--pull) * 1.6);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.bn-vn-cancel {
|
|
271
|
+
position: absolute;
|
|
272
|
+
left: 14px;
|
|
273
|
+
top: 50%;
|
|
274
|
+
width: 28px;
|
|
275
|
+
height: 28px;
|
|
276
|
+
margin-top: -14px;
|
|
277
|
+
display: grid;
|
|
278
|
+
place-items: center;
|
|
279
|
+
border-radius: 50%;
|
|
280
|
+
background: #e5484d;
|
|
281
|
+
color: #fff;
|
|
282
|
+
opacity: 0;
|
|
283
|
+
scale: 0.4;
|
|
284
|
+
pointer-events: none;
|
|
285
|
+
transition:
|
|
286
|
+
opacity 160ms ease,
|
|
287
|
+
scale 160ms ease;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.bn-vn-cancel[data-on] {
|
|
291
|
+
opacity: 1;
|
|
292
|
+
scale: 1;
|
|
293
|
+
transition:
|
|
294
|
+
opacity 160ms ease,
|
|
295
|
+
scale 420ms cubic-bezier(0.24, 1.34, 0.38, 1);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.bn-vn[data-phase="cancel"] .bn-vn-cancel {
|
|
299
|
+
opacity: 0;
|
|
300
|
+
scale: 0.6;
|
|
301
|
+
transition:
|
|
302
|
+
opacity 220ms ease,
|
|
303
|
+
scale 220ms ease;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.bn-vn-note {
|
|
307
|
+
position: absolute;
|
|
308
|
+
left: 0;
|
|
309
|
+
right: 0;
|
|
310
|
+
top: calc(50% + 42px);
|
|
311
|
+
text-align: center;
|
|
312
|
+
font-family: var(--font-ui);
|
|
313
|
+
font-size: 13px;
|
|
314
|
+
color: var(--red, #e5484d);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.bn-vn-frame[data-mode="tap"] .bn-vn-note {
|
|
318
|
+
position: static;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
@keyframes bn-vn-in {
|
|
322
|
+
from {
|
|
323
|
+
opacity: 0;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
@keyframes bn-vn-blink {
|
|
328
|
+
50% {
|
|
329
|
+
opacity: 0.25;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
@keyframes bn-vn-grow {
|
|
334
|
+
from {
|
|
335
|
+
scale: 1 0.2;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
@@ -226,12 +226,22 @@
|
|
|
226
226
|
align-items: center;
|
|
227
227
|
gap: 6px;
|
|
228
228
|
}
|
|
229
|
+
/* the voice note pill takes a row of the bar to itself; the level check sits under it */
|
|
230
|
+
.clone-voicenote {
|
|
231
|
+
flex: 1 1 100%;
|
|
232
|
+
display: flex;
|
|
233
|
+
justify-content: center;
|
|
234
|
+
min-width: 0;
|
|
235
|
+
}
|
|
229
236
|
.clone-level {
|
|
230
|
-
|
|
231
|
-
text-align:
|
|
237
|
+
flex: 1 1 100%;
|
|
238
|
+
text-align: center;
|
|
232
239
|
font-size: 13px;
|
|
233
240
|
color: var(--text-3);
|
|
234
241
|
}
|
|
242
|
+
.clone-level:empty {
|
|
243
|
+
display: none;
|
|
244
|
+
}
|
|
235
245
|
.clone-level .bars {
|
|
236
246
|
display: inline-flex;
|
|
237
247
|
align-items: center;
|
|
@@ -606,8 +606,13 @@
|
|
|
606
606
|
}
|
|
607
607
|
.omni-pending-actions {
|
|
608
608
|
display: flex;
|
|
609
|
+
flex-direction: column;
|
|
609
610
|
gap: 8px;
|
|
610
|
-
|
|
611
|
+
align-items: stretch;
|
|
612
|
+
}
|
|
613
|
+
.omni-pending-actions .button {
|
|
614
|
+
align-self: center;
|
|
615
|
+
justify-content: center;
|
|
611
616
|
}
|
|
612
617
|
|
|
613
618
|
/* the Conteúdos page's floating "Agente, fila e serviços" tab sits left of Omni */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
/* StageStepper.tsx: the pipeline stepper, full and compact.
|
|
1
|
+
/* StageStepper.tsx: the pipeline stepper, full and compact. The pipeline's own steps are Bencho action-node cards
|
|
2
|
+
(.stepper.cards); the bare .step rules also serve the omnichat rule's steps (OmnichatRulePanel/RuleConfig.tsx). */
|
|
2
3
|
|
|
3
4
|
/* --- stepper ------------------------------------------------------------------------ */
|
|
4
5
|
.stepper {
|
|
@@ -12,7 +13,6 @@
|
|
|
12
13
|
min-width: 0;
|
|
13
14
|
position: relative;
|
|
14
15
|
}
|
|
15
|
-
.step > a,
|
|
16
16
|
.step > button {
|
|
17
17
|
display: flex;
|
|
18
18
|
flex-direction: column;
|
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
border-radius: var(--radius-sm);
|
|
27
27
|
text-align: center;
|
|
28
28
|
}
|
|
29
|
-
.step > a:hover,
|
|
30
29
|
.step > button:hover {
|
|
31
30
|
background: var(--surface-2);
|
|
32
31
|
}
|
|
@@ -175,10 +174,6 @@
|
|
|
175
174
|
color: var(--emerald);
|
|
176
175
|
}
|
|
177
176
|
|
|
178
|
-
.stepper.compact .step > a {
|
|
179
|
-
padding: 4px 1px 2px;
|
|
180
|
-
gap: 3px;
|
|
181
|
-
}
|
|
182
177
|
.stepper.compact .step + .step::before {
|
|
183
178
|
top: 15px;
|
|
184
179
|
left: calc(-50% + 12px);
|
|
@@ -206,3 +201,124 @@
|
|
|
206
201
|
width: 10px;
|
|
207
202
|
height: 10px;
|
|
208
203
|
}
|
|
204
|
+
|
|
205
|
+
/* --- cards: each stage as a Bencho action node ---------------------------------------------- */
|
|
206
|
+
/* a grid that wraps instead of scrolling: the fan hangs below the cards, and a scrolling box would clip it */
|
|
207
|
+
.stepper.cards {
|
|
208
|
+
--steps: 6;
|
|
209
|
+
--gap: 10px;
|
|
210
|
+
display: grid;
|
|
211
|
+
/* every step on one row when each gets at least 118px, else the row wraps; --steps is set by the component */
|
|
212
|
+
grid-template-columns: repeat(
|
|
213
|
+
auto-fit,
|
|
214
|
+
minmax(max(118px, calc((100% - var(--gap) * (var(--steps) - 1)) / var(--steps))), 1fr)
|
|
215
|
+
);
|
|
216
|
+
gap: var(--gap);
|
|
217
|
+
/* the last card's fan opens past its right edge */
|
|
218
|
+
padding-right: 22px;
|
|
219
|
+
}
|
|
220
|
+
.stepper.cards.compact {
|
|
221
|
+
--gap: 8px;
|
|
222
|
+
grid-template-columns: repeat(
|
|
223
|
+
auto-fit,
|
|
224
|
+
minmax(max(100px, calc((100% - var(--gap) * (var(--steps) - 1)) / var(--steps))), 1fr)
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
.stepper.cards .step {
|
|
228
|
+
display: flex;
|
|
229
|
+
min-width: 0;
|
|
230
|
+
}
|
|
231
|
+
/* the connector line belongs to the circles; the cards carry the sequence in their numbers */
|
|
232
|
+
.stepper.cards .step + .step::before {
|
|
233
|
+
display: none;
|
|
234
|
+
}
|
|
235
|
+
.stepper.cards .bn-nod {
|
|
236
|
+
flex: 1 1 auto;
|
|
237
|
+
min-width: 0;
|
|
238
|
+
}
|
|
239
|
+
.stepper.cards .bn-nod-card {
|
|
240
|
+
height: 100%;
|
|
241
|
+
}
|
|
242
|
+
/* the open fan sits above the neighbouring cards and what is under the stepper */
|
|
243
|
+
.stepper.cards .bn-nod:hover,
|
|
244
|
+
.stepper.cards .bn-nod:focus-within {
|
|
245
|
+
z-index: 6;
|
|
246
|
+
}
|
|
247
|
+
/* the card and its buttons are the Bencho fill, which on a page of the same colour needs an edge to be seen */
|
|
248
|
+
.stepper.cards .bn-nod-card,
|
|
249
|
+
.stepper.cards .bn-nod-act {
|
|
250
|
+
box-shadow: 0 0 0 1px rgba(var(--ink-rgb), 0.1);
|
|
251
|
+
}
|
|
252
|
+
.stepper.cards .bn-nod-card[data-selected] {
|
|
253
|
+
box-shadow: 0 0 0 2px var(--fill-on, var(--ink));
|
|
254
|
+
}
|
|
255
|
+
.stepper.cards .bn-nod-mark {
|
|
256
|
+
margin-top: 0;
|
|
257
|
+
}
|
|
258
|
+
.stepper.cards .step-mark {
|
|
259
|
+
width: 26px;
|
|
260
|
+
height: 26px;
|
|
261
|
+
font-size: 11px;
|
|
262
|
+
}
|
|
263
|
+
.stepper.cards.compact .step-mark {
|
|
264
|
+
width: 20px;
|
|
265
|
+
height: 20px;
|
|
266
|
+
font-size: 9.5px;
|
|
267
|
+
border-width: 1.5px;
|
|
268
|
+
}
|
|
269
|
+
.stepper.cards .step.chosen .step-mark {
|
|
270
|
+
transform: none;
|
|
271
|
+
box-shadow: none;
|
|
272
|
+
}
|
|
273
|
+
.stepper.cards .bn-nod-top {
|
|
274
|
+
align-items: flex-start;
|
|
275
|
+
}
|
|
276
|
+
.stepper.cards .bn-nod-name {
|
|
277
|
+
/* two lines at most: "Roteiro de motion" in a narrow cell */
|
|
278
|
+
display: -webkit-box;
|
|
279
|
+
-webkit-line-clamp: 2;
|
|
280
|
+
-webkit-box-orient: vertical;
|
|
281
|
+
overflow: hidden;
|
|
282
|
+
/* centred on the mark when it is one line */
|
|
283
|
+
align-self: center;
|
|
284
|
+
}
|
|
285
|
+
.stepper.cards .bn-nod-say {
|
|
286
|
+
overflow: hidden;
|
|
287
|
+
text-overflow: ellipsis;
|
|
288
|
+
white-space: nowrap;
|
|
289
|
+
}
|
|
290
|
+
.stepper.cards.compact .bn-nod-top {
|
|
291
|
+
gap: 4px;
|
|
292
|
+
}
|
|
293
|
+
.stepper.cards.compact .bn-nod-name {
|
|
294
|
+
font-size: 11px;
|
|
295
|
+
}
|
|
296
|
+
.stepper.cards.compact .bn-nod-say {
|
|
297
|
+
font-size: 10.5px;
|
|
298
|
+
margin-top: 4px;
|
|
299
|
+
}
|
|
300
|
+
.stepper.cards.compact .bn-nod-card {
|
|
301
|
+
padding: 6px;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/* the state in the description: the studio's signal colours, pulled toward the card's ink so they read on its fill */
|
|
305
|
+
.stepper.cards .step.done {
|
|
306
|
+
--tone: var(--emerald);
|
|
307
|
+
}
|
|
308
|
+
.stepper.cards .step:is(.running, .redoing, .queued, .scheduled) {
|
|
309
|
+
--tone: var(--running);
|
|
310
|
+
}
|
|
311
|
+
.stepper.cards .step:is(.user, .rejected, .warning, .next) {
|
|
312
|
+
--tone: var(--warning);
|
|
313
|
+
}
|
|
314
|
+
.stepper.cards .step.error {
|
|
315
|
+
--tone: var(--error);
|
|
316
|
+
}
|
|
317
|
+
.stepper.cards
|
|
318
|
+
.step:is(.done, .running, .redoing, .queued, .scheduled, .user, .rejected, .warning, .next, .error)
|
|
319
|
+
.bn-nod-say {
|
|
320
|
+
color: color-mix(in srgb, var(--tone) 80%, var(--ink));
|
|
321
|
+
}
|
|
322
|
+
.stepper.cards .step:is(.user, .error) .bn-nod-say {
|
|
323
|
+
font-weight: 600;
|
|
324
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/* Toaster.tsx: the corner the toasts live in. Above everything the studio draws (the Omni widget 60, the lightbox 70,
|
|
2
|
+
the modals and the offline screen 100, the select and date pickers 300) except the tooltips (400). The corner itself
|
|
3
|
+
is click-through; only the toasts take the pointer (bencho/toast-stack.css). */
|
|
4
|
+
.toaster {
|
|
5
|
+
position: fixed;
|
|
6
|
+
right: 20px;
|
|
7
|
+
bottom: 20px;
|
|
8
|
+
z-index: 350;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
}
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
/* --- .tdc-slider: tdc's slider (channels), web/components/ui/slider.tsx -------------------------------
|
|
4
4
|
Same CSS as its flat theme, with the tokens from here. Two variants: `line`, the thin
|
|
5
|
-
rule, and `fill`, the tall track where the fill is the value and the text lives inside
|
|
6
|
-
|
|
5
|
+
rule, and `fill`, the tall track where the fill is the value and the text lives inside (drawn by
|
|
6
|
+
components/bencho/SloshSlider.tsx, so only its height and the root are set here). The geometry stays in
|
|
7
|
+
:where() so the call site can change height and radius. */
|
|
7
8
|
:where(.tdc-slider) {
|
|
8
9
|
position: relative;
|
|
9
10
|
display: flex;
|
|
@@ -21,19 +22,15 @@
|
|
|
21
22
|
border-radius: 9999px;
|
|
22
23
|
background: var(--surface-2);
|
|
23
24
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
/* the fill variant is drawn by components/bencho/SloshSlider.tsx, which reads its track height from here */
|
|
26
|
+
:where(.tdc-slider[data-variant="fill"]) {
|
|
27
|
+
--slo-h: 2rem;
|
|
27
28
|
}
|
|
28
29
|
:where(.tdc-slider [data-slot="slider-range"]) {
|
|
29
30
|
position: absolute;
|
|
30
31
|
height: 100%;
|
|
31
32
|
background: var(--action);
|
|
32
33
|
}
|
|
33
|
-
/* in the tall track the fill is a large area: the full color would eat the number inside */
|
|
34
|
-
:where(.tdc-slider[data-variant="fill"] [data-slot="slider-range"]) {
|
|
35
|
-
background: color-mix(in srgb, var(--action) 10%, transparent);
|
|
36
|
-
}
|
|
37
34
|
:where(.tdc-slider [data-slot="slider-thumb"]) {
|
|
38
35
|
display: block;
|
|
39
36
|
height: 1rem;
|
|
@@ -48,13 +45,6 @@
|
|
|
48
45
|
:where(.tdc-slider [data-slot="slider-thumb"]):active {
|
|
49
46
|
cursor: grabbing;
|
|
50
47
|
}
|
|
51
|
-
/* thin bar instead of a disc: inside a 32 px track the disc vanishes against the fill */
|
|
52
|
-
:where(.tdc-slider[data-variant="fill"] [data-slot="slider-thumb"]) {
|
|
53
|
-
width: 4px;
|
|
54
|
-
border-radius: 2px;
|
|
55
|
-
background: var(--action);
|
|
56
|
-
box-shadow: inset 0 0 0 1px var(--action);
|
|
57
|
-
}
|
|
58
48
|
.tdc-slider [data-slot="slider-thumb"]:focus-visible {
|
|
59
49
|
outline: 2px solid color-mix(in srgb, var(--action) 60%, transparent);
|
|
60
50
|
outline-offset: 2px;
|
|
@@ -1,41 +1,2 @@
|
|
|
1
|
-
/* ui/switch.tsx (.ui-switch).
|
|
2
|
-
|
|
3
|
-
.ui-switch {
|
|
4
|
-
position: relative;
|
|
5
|
-
flex: none;
|
|
6
|
-
width: 36px;
|
|
7
|
-
height: 20px;
|
|
8
|
-
padding: 0;
|
|
9
|
-
border: 0;
|
|
10
|
-
border-radius: 999px;
|
|
11
|
-
background: var(--el-alpha-200);
|
|
12
|
-
cursor: pointer;
|
|
13
|
-
transition: background 0.15s;
|
|
14
|
-
}
|
|
15
|
-
.ui-switch[data-state="checked"] {
|
|
16
|
-
background: var(--action);
|
|
17
|
-
}
|
|
18
|
-
.ui-switch:focus-visible {
|
|
19
|
-
outline: 2px solid var(--running);
|
|
20
|
-
outline-offset: 2px;
|
|
21
|
-
}
|
|
22
|
-
.ui-switch:disabled {
|
|
23
|
-
opacity: 0.5;
|
|
24
|
-
cursor: not-allowed;
|
|
25
|
-
}
|
|
26
|
-
.ui-switch-thumb {
|
|
27
|
-
display: block;
|
|
28
|
-
width: 16px;
|
|
29
|
-
height: 16px;
|
|
30
|
-
border-radius: 50%;
|
|
31
|
-
background: #fff;
|
|
32
|
-
box-shadow: 0 1px 2px rgb(0 0 0 / 0.2);
|
|
33
|
-
transform: translateX(2px);
|
|
34
|
-
transition:
|
|
35
|
-
transform 0.15s,
|
|
36
|
-
background 0.15s;
|
|
37
|
-
}
|
|
38
|
-
.ui-switch[data-state="checked"] .ui-switch-thumb {
|
|
39
|
-
transform: translateX(18px);
|
|
40
|
-
background: var(--action-text);
|
|
41
|
-
}
|
|
1
|
+
/* ui/switch.tsx (.ui-switch). The switch draws as Bencho's liquid toggle: the box, track, droplet and focus ring live in
|
|
2
|
+
components/bencho/liq-toggle.css (.bn-liq-*). `.ui-switch` is only the hook callers and theme rules style it by. */
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
max-width: 760px;
|
|
23
23
|
}
|
|
24
24
|
.carousel-window {
|
|
25
|
+
position: relative;
|
|
25
26
|
overflow: hidden;
|
|
26
27
|
height: 196px;
|
|
27
28
|
-webkit-mask-image: linear-gradient(90deg, transparent, #000 16%, #000 84%, transparent);
|
|
@@ -44,6 +45,8 @@
|
|
|
44
45
|
background: none;
|
|
45
46
|
padding: 0;
|
|
46
47
|
cursor: pointer;
|
|
48
|
+
/* --shift pulls the voices before the center under the add ball; --s is the scale of its distance */
|
|
49
|
+
transform: translateX(var(--shift, 0px)) scale(var(--s, 1));
|
|
47
50
|
transition:
|
|
48
51
|
transform 0.5s cubic-bezier(0.22, 0.8, 0.24, 1),
|
|
49
52
|
opacity 0.4s;
|
|
@@ -54,21 +57,60 @@
|
|
|
54
57
|
transition: box-shadow 0.3s;
|
|
55
58
|
}
|
|
56
59
|
.carousel-item.d0 {
|
|
57
|
-
|
|
60
|
+
--s: 1;
|
|
58
61
|
opacity: 1;
|
|
59
62
|
}
|
|
60
63
|
.carousel-item.d1 {
|
|
61
|
-
|
|
64
|
+
--s: 0.7;
|
|
62
65
|
opacity: 0.75;
|
|
63
66
|
}
|
|
64
67
|
.carousel-item.d2 {
|
|
65
|
-
|
|
68
|
+
--s: 0.52;
|
|
66
69
|
opacity: 0.45;
|
|
67
70
|
}
|
|
68
71
|
.carousel-item.d3 {
|
|
69
|
-
|
|
72
|
+
--s: 0.4;
|
|
70
73
|
opacity: 0.25;
|
|
71
74
|
}
|
|
75
|
+
/* the voices behind the add ball: only the one right before the center stays (covered), the rest is gone */
|
|
76
|
+
.carousel-item.under {
|
|
77
|
+
opacity: 0;
|
|
78
|
+
pointer-events: none;
|
|
79
|
+
}
|
|
80
|
+
/* the add ball: always the slot before the center (centered while there is no voice) */
|
|
81
|
+
.carousel-add {
|
|
82
|
+
position: absolute;
|
|
83
|
+
top: 0;
|
|
84
|
+
left: 50%;
|
|
85
|
+
z-index: 1;
|
|
86
|
+
width: var(--slot);
|
|
87
|
+
height: 196px;
|
|
88
|
+
display: grid;
|
|
89
|
+
place-items: center;
|
|
90
|
+
border: 0;
|
|
91
|
+
background: none;
|
|
92
|
+
padding: 0;
|
|
93
|
+
cursor: pointer;
|
|
94
|
+
transform: translateX(calc(var(--add-x) * var(--slot))) scale(var(--s, 1));
|
|
95
|
+
transition:
|
|
96
|
+
transform 0.5s cubic-bezier(0.22, 0.8, 0.24, 1),
|
|
97
|
+
opacity 0.4s;
|
|
98
|
+
}
|
|
99
|
+
.carousel-add.d0 {
|
|
100
|
+
--s: 1;
|
|
101
|
+
opacity: 1;
|
|
102
|
+
}
|
|
103
|
+
.carousel-add.d1 {
|
|
104
|
+
--s: 0.7;
|
|
105
|
+
opacity: 0.75;
|
|
106
|
+
}
|
|
107
|
+
/* opaque when it covers a voice, so the one beneath doesn't show through */
|
|
108
|
+
.carousel-add.d1.covering {
|
|
109
|
+
opacity: 1;
|
|
110
|
+
}
|
|
111
|
+
.carousel-add:focus-visible {
|
|
112
|
+
outline: none;
|
|
113
|
+
}
|
|
72
114
|
/* the ring marks the chosen avatar only in the compact picker (clone voice); the voice carousel has no border */
|
|
73
115
|
.carousel.compact .carousel-item.active.d0 .voice-avatar {
|
|
74
116
|
box-shadow:
|