@ash-qw/dsh-theme-prts 2.5.2 → 2.5.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/CHANGELOG.md +26 -0
- package/lib/client.js +240 -65
- package/package.json +1 -1
- package/src/client/background-layout.js +21 -7
- package/src/client/conversation-control-adapter.js +106 -27
- package/src/client/cursor-adapter.js +4 -3
- package/src/client/custom-avatar.js +1 -1
- package/src/client/host-geometry-adapter.js +11 -5
- package/src/client/index.js +2 -0
- package/src/client/preferences.js +9 -1
- package/src/client/sidebar-control-adapter.js +64 -13
- package/src/client/theme-controller-v2.js +1 -0
- package/src/client/theme-controller.js +1 -0
- package/src/client/theme-settings-workbench.js +9 -0
- package/src/client/theme-transfer-panel.js +2 -3
- package/src/client/theme-transfer.js +4 -1
- package/src/styles/custom-background.css +12 -1
- package/src/styles/facility-vector.css +5 -2
- package/src/styles/refinement.css +1 -1
- package/src/styles/theme-settings-workbench.css +14 -1
- package/src/vendor/react-bits/GlassSurface.jsx +16 -2
package/package.json
CHANGED
|
@@ -5,7 +5,16 @@ export function createBackgroundLayout({window,document}) {
|
|
|
5
5
|
const raf=window.requestAnimationFrame?.bind(window) ?? (fn=>window.setTimeout(fn,16))
|
|
6
6
|
const caf=window.cancelAnimationFrame?.bind(window) ?? window.clearTimeout.bind(window)
|
|
7
7
|
let state={}, frame, disposed=false, enabled=false, observing=false, hostFrame, operation, sessions
|
|
8
|
-
const
|
|
8
|
+
const sidebarTargets = new Set()
|
|
9
|
+
const set=(name,value)=>{
|
|
10
|
+
const targets=name.startsWith('--prts-protected-sidebar-')?[sessions,document.querySelector('[data-prts-nav-rail]')]:[root]
|
|
11
|
+
for(const node of targets){
|
|
12
|
+
if(!node)continue
|
|
13
|
+
if(node!==root)sidebarTargets.add(node)
|
|
14
|
+
if(value===null)node.style.removeProperty(name)
|
|
15
|
+
else if(node.style.getPropertyValue(name)!==value)node.style.setProperty(name,value)
|
|
16
|
+
}
|
|
17
|
+
}
|
|
9
18
|
const update=()=>{
|
|
10
19
|
frame=undefined
|
|
11
20
|
if(disposed||!observing)return
|
|
@@ -17,6 +26,8 @@ export function createBackgroundLayout({window,document}) {
|
|
|
17
26
|
for(const node of [hostFrame||operation,sessions])if(node)resize?.observe(node)
|
|
18
27
|
}
|
|
19
28
|
const railWidth=parseFloat(window.getComputedStyle(root).getPropertyValue('--prts-nav-width'))||0
|
|
29
|
+
const writes=[]
|
|
30
|
+
const write=(...args)=>writes.push(args)
|
|
20
31
|
for(const slot of ['full','conversation','sidebar']){
|
|
21
32
|
const entry=state[slot]
|
|
22
33
|
const node=slot==='sidebar'?sessions:slot==='conversation'?(hostFrame||operation):operation
|
|
@@ -25,15 +36,16 @@ export function createBackgroundLayout({window,document}) {
|
|
|
25
36
|
const active=entry?.region && width>0 && height>0
|
|
26
37
|
if(active){
|
|
27
38
|
const p=backgroundPlacement(entry.width,entry.height,width,height,entry.region)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
if(slot==='sidebar')
|
|
39
|
+
write(`--prts-protected-${slot}-x`,`${p.x}px`)
|
|
40
|
+
write(`--prts-protected-${slot}-y`,`${p.y}px`)
|
|
41
|
+
if(slot==='sidebar')write('--prts-protected-sidebar-width',`${p.width}px`)
|
|
31
42
|
}else{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if(slot==='sidebar')
|
|
43
|
+
write(`--prts-protected-${slot}-x`,null)
|
|
44
|
+
write(`--prts-protected-${slot}-y`,null)
|
|
45
|
+
if(slot==='sidebar')write('--prts-protected-sidebar-width',null)
|
|
35
46
|
}
|
|
36
47
|
}
|
|
48
|
+
for(const args of writes)set(...args)
|
|
37
49
|
}
|
|
38
50
|
function schedule(){if(!disposed && observing && frame===undefined)frame=raf(update)}
|
|
39
51
|
// ResizeObserver runs after layout, before paint. Deferring again to rAF
|
|
@@ -48,6 +60,8 @@ export function createBackgroundLayout({window,document}) {
|
|
|
48
60
|
const attributes=new window.MutationObserver(schedule)
|
|
49
61
|
function clear(){
|
|
50
62
|
caf(frame);frame=undefined;resize?.disconnect();mutations.disconnect();attributes.disconnect();window.removeEventListener('resize',schedule)
|
|
63
|
+
for(const node of sidebarTargets)for(const axis of ['x','y','width'])node.style.removeProperty(`--prts-protected-sidebar-${axis}`)
|
|
64
|
+
sidebarTargets.clear()
|
|
51
65
|
hostFrame=undefined;operation=undefined;sessions=undefined;observing=false
|
|
52
66
|
for(const slot of ['full','conversation','sidebar'])for(const axis of ['x','y','width'])root.style.removeProperty(`--prts-protected-${slot}-${axis}`)
|
|
53
67
|
}
|
|
@@ -11,6 +11,15 @@ function closestWithClassSuffix(node, suffix) {
|
|
|
11
11
|
return null
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
function isPendingInteractionAction(button) {
|
|
15
|
+
if (!button || button.tagName !== 'BUTTON') return false
|
|
16
|
+
if (button.closest('[data-approval-key]')) return true
|
|
17
|
+
if (button.closest('[data-question-key]')) {
|
|
18
|
+
return hasClassSuffix(button, '_waitButton') || Boolean(closestWithClassSuffix(button, '_footerActions'))
|
|
19
|
+
}
|
|
20
|
+
return Boolean(button.closest('[data-plan-review-key]') && closestWithClassSuffix(button, '_actions'))
|
|
21
|
+
}
|
|
22
|
+
|
|
14
23
|
function classify(button, operation) {
|
|
15
24
|
// The host's process disclosure owns its transparent, full-width hit area.
|
|
16
25
|
if (button.hasAttribute('data-turn-process')) return null
|
|
@@ -40,6 +49,8 @@ function classify(button, operation) {
|
|
|
40
49
|
if (approval) return hasClassSuffix(button, '_reject') ? 'danger' : 'cta'
|
|
41
50
|
if (hasClassSuffix(button, '_modalAction') || button.closest('[role="dialog"]')) return 'cta'
|
|
42
51
|
|
|
52
|
+
const userRow = closestWithClassSuffix(button, '_userRow')
|
|
53
|
+
if (userRow?.matches('[data-submission-echo], [data-pending-steering]')) return 'micro'
|
|
43
54
|
if (button.closest('[data-chat-flow-kind], [data-message-role]')) return 'micro'
|
|
44
55
|
return null
|
|
45
56
|
}
|
|
@@ -120,7 +131,7 @@ export function createConversationControlAdapter({ document, window }) {
|
|
|
120
131
|
subtree: true,
|
|
121
132
|
childList: true,
|
|
122
133
|
attributes: true,
|
|
123
|
-
attributeFilter: ['class', 'data-approval-key', 'data-turn-process'],
|
|
134
|
+
attributeFilter: ['class', 'data-approval-key', 'data-turn-process', 'data-submission-echo', 'data-pending-steering', 'data-chat-flow-kind', 'data-message-role'],
|
|
124
135
|
})
|
|
125
136
|
},
|
|
126
137
|
dispose() {
|
|
@@ -138,14 +149,16 @@ function mountBodyTargetFrame(document, window, operation) {
|
|
|
138
149
|
// Nonvisual hosts can still mount the theme without an animation clock.
|
|
139
150
|
if (!window?.requestAnimationFrame || !window?.cancelAnimationFrame) return () => {}
|
|
140
151
|
const composerButton=':is([data-composer-card],[data-prts-composer-fallback]) button:not([data-slot="conversation.input.attachments"] *,[data-prts-glass-menu] *,[data-prts-floating-glass] *,[role="menu"] *,[role="listbox"] *)'
|
|
141
|
-
const selector='[data-prts-conversation-control],[data-presented-file],[data-changed-files],[data-produced-files-row] > button,[data-prts-glass-control],[data-prts-footer-action],[data-prts-transfer] button,'+composerButton
|
|
152
|
+
const selector='[data-prts-to-bottom],[data-prts-conversation-control],[data-presented-file],[data-changed-files],[data-produced-files-row] > button,[data-prts-glass-control],[data-prts-footer-action],[data-prts-transfer] button,'+composerButton
|
|
142
153
|
const frame=document.createElement('div')
|
|
143
154
|
frame.setAttribute('data-prts-body-target-frame','');frame.setAttribute('aria-hidden','true')
|
|
144
155
|
const corners=Array.from({length:4},()=>frame.appendChild(document.createElement('i')))
|
|
145
156
|
document.body.append(frame)
|
|
146
157
|
if(frame.showPopover)frame.setAttribute('popover','manual')
|
|
147
|
-
let layer=null
|
|
148
|
-
const hideFrame=()=>{
|
|
158
|
+
let layer=null, imageRetiring=false
|
|
159
|
+
const hideFrame=()=>{
|
|
160
|
+
if(frame.hidePopover && frame.matches(':popover-open'))frame.hidePopover()
|
|
161
|
+
}
|
|
149
162
|
const showFrame=()=>{
|
|
150
163
|
if(!frame.showPopover)return
|
|
151
164
|
const modal=target?.closest('dialog[open]')
|
|
@@ -153,46 +166,66 @@ function mountBodyTargetFrame(document, window, operation) {
|
|
|
153
166
|
if(!frame.matches(':popover-open'))frame.showPopover()
|
|
154
167
|
layer=modal
|
|
155
168
|
}
|
|
156
|
-
let target=null, hovered=null, focused=null, raf=0, pressed=false, disposed=false
|
|
157
|
-
let pointer={x:0,y:0}, state=null, settled=false, tween=null, bounds=null, boundsDirty=false, hitDirty=false, exitGoal=null, motionDuration=240, targetArm=7
|
|
158
|
-
|
|
169
|
+
let target=null, hovered=null, focused=null, raf=0, pressed=false, releasePending=false, disposed=false
|
|
170
|
+
let pointer={x:0,y:0}, state=null, settled=false, tween=null, bounds=null, boundsDirty=false, hitDirty=false, exitGoal=null, motionDuration=240, targetArm=7, retiringBounds=null, targetRetires=false
|
|
171
|
+
let moveRaf=0, pendingMove=null
|
|
172
|
+
const resizeObserver=window.ResizeObserver?new window.ResizeObserver(entries=>{
|
|
173
|
+
if(!target)return
|
|
174
|
+
const entry=entries.find(item=>item.target===target),size=entry?.borderBoxSize?.[0]
|
|
175
|
+
if(size && bounds && Math.abs(size.inlineSize-bounds.width)<.5 && Math.abs(size.blockSize-bounds.height)<.5)return
|
|
176
|
+
const box=target.getBoundingClientRect()
|
|
177
|
+
if(bounds && ['left','top','width','height'].every(key=>bounds[key]===box[key]))return
|
|
178
|
+
boundsDirty=true;wake()
|
|
179
|
+
}):null
|
|
159
180
|
const reduced=window.matchMedia?.('(prefers-reduced-motion: reduce)')
|
|
160
181
|
const fine=window.matchMedia?.('(hover:hover) and (pointer:fine)')
|
|
182
|
+
let activeModal=null
|
|
161
183
|
const find=node=>{
|
|
184
|
+
if(activeModal && !activeModal.contains(node))return null
|
|
162
185
|
if (!node?.closest || node.closest('[data-prts-workspace-actions],[data-prts-session-actions]')) return null
|
|
163
186
|
const card=node.closest('[data-presented-file],[data-changed-files]')
|
|
164
|
-
const
|
|
187
|
+
const button=node.closest('button')
|
|
188
|
+
const pendingAction=operation.contains(button) && isPendingInteractionAction(button) ? button : null
|
|
189
|
+
const candidate=card || pendingAction || node.closest(selector)
|
|
165
190
|
return candidate && !candidate.matches(':disabled,[aria-disabled="true"]') && !candidate.closest('[inert]') ? candidate : null
|
|
166
191
|
}
|
|
167
|
-
const measure=()=>{bounds=target.getBoundingClientRect();targetArm=7+Math.max(0,Math.min(1,(Math.min(bounds.width,bounds.height)-36)/36))*5;boundsDirty=false}
|
|
192
|
+
const measure=(box)=>{bounds=box || target.getBoundingClientRect();targetArm=7+Math.max(0,Math.min(1,(Math.min(bounds.width,bounds.height)-36)/36))*5;boundsDirty=false}
|
|
168
193
|
const wake=()=>{if(!raf && !disposed)raf=window.requestAnimationFrame(draw)}
|
|
169
194
|
const choose=()=>{
|
|
170
|
-
const next=hovered || focused
|
|
195
|
+
const next=(hovered?.isConnected?hovered:null) || (focused?.isConnected?focused:null)
|
|
171
196
|
if(next!==target){
|
|
197
|
+
const nextBounds=next?.getBoundingClientRect()
|
|
198
|
+
const retire=!next && target && !target.isConnected && targetRetires && releasePending && bounds && !reduced?.matches
|
|
199
|
+
imageRetiring=false
|
|
200
|
+
retiringBounds=retire?{left:bounds.left,top:bounds.top,width:bounds.width,height:bounds.height}:null
|
|
172
201
|
target?.removeAttribute('data-prts-corner-target')
|
|
173
|
-
|
|
202
|
+
if(retire){hovered=focused=target=null;boundsDirty=false;resizeObserver?.disconnect();wake();return}
|
|
203
|
+
pressed=false;releasePending=false;settled=false;tween=null;exitGoal=null;motionDuration=240;target=next;boundsDirty=true
|
|
174
204
|
resizeObserver?.disconnect()
|
|
175
205
|
if(target)resizeObserver?.observe(target)
|
|
176
206
|
if(target){
|
|
207
|
+
targetRetires=hasClassSuffix(target,'_toBottom') || isPendingInteractionAction(target)
|
|
177
208
|
target.setAttribute('data-prts-corner-target','');showFrame()
|
|
178
|
-
measure();const box=bounds
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
frame.style.color=
|
|
209
|
+
measure(nextBounds);const box=bounds
|
|
210
|
+
state={x:(hovered?pointer.x:box.left+box.width/2)-10,y:(hovered?pointer.y:box.top+box.height/2)-10,w:20,h:20,alpha:0,arm:7}
|
|
211
|
+
frame.style.opacity='0'
|
|
212
|
+
frame.style.color=target.getAttribute('data-prts-conversation-control')==='danger'?window.getComputedStyle(target).getPropertyValue('--prts-red'):'var(--prts-corner-color, var(--prts-yellow))'
|
|
182
213
|
}
|
|
183
214
|
}
|
|
215
|
+
if(!target && !state?.alpha)hideFrame()
|
|
184
216
|
if(!settled || !target && state?.alpha>0)wake()
|
|
185
217
|
}
|
|
186
218
|
function draw(time) {
|
|
187
219
|
raf=0
|
|
220
|
+
if(target && !target.isConnected)choose()
|
|
188
221
|
if(hitDirty){hitDirty=false;hovered=find(document.elementFromPoint(pointer.x,pointer.y));choose()}
|
|
189
|
-
if(target && !target.isConnected){target.removeAttribute('data-prts-corner-target');target=hovered=focused=null;pressed=false;settled=false;exitGoal=null}
|
|
222
|
+
if(target && !target.isConnected){target.removeAttribute('data-prts-corner-target');target=hovered=focused=null;pressed=false;releasePending=false;settled=false;exitGoal=null}
|
|
190
223
|
if(!state)return
|
|
191
224
|
if(target && boundsDirty){
|
|
192
225
|
measure()
|
|
193
|
-
if(!bounds.width && !bounds.height){target.removeAttribute('data-prts-corner-target');target=hovered=focused=null;pressed=false;settled=false;exitGoal=null;resizeObserver?.disconnect()}
|
|
226
|
+
if(!bounds.width && !bounds.height){target.removeAttribute('data-prts-corner-target');target=hovered=focused=null;pressed=false;releasePending=false;settled=false;exitGoal=null;resizeObserver?.disconnect()}
|
|
194
227
|
}
|
|
195
|
-
const box=target?bounds:
|
|
228
|
+
const box=target?bounds:retiringBounds,gap=pressed?(imageRetiring?0:3):5
|
|
196
229
|
// Freeze the exit destination: subsequent pointer motion must not restart the fade.
|
|
197
230
|
const goal=box?{x:box.left-gap,y:box.top-gap,w:box.width+gap*2,h:box.height+gap*2,alpha:1,arm:targetArm}:
|
|
198
231
|
(exitGoal ||= {x:pointer.x-10,y:pointer.y-10,w:20,h:20,alpha:0,arm:7})
|
|
@@ -206,7 +239,7 @@ function mountBodyTargetFrame(document, window, operation) {
|
|
|
206
239
|
tween={from:{...state},to:{...goal},start:time,duration:remaining,pressed}
|
|
207
240
|
}
|
|
208
241
|
// All channels share one endpoint; no separate thresholds or late position snap.
|
|
209
|
-
const progress=reduced?.matches || settled || !tween.duration?1:Math.min(1,(time-tween.start)/tween.duration)
|
|
242
|
+
const progress=reduced?.matches || settled || !tween.duration || (!state.alpha && !goal.alpha)?1:Math.min(1,(time-tween.start)/tween.duration)
|
|
210
243
|
const ease=1-(1-progress)**3
|
|
211
244
|
for(const key of keys)state[key]=tween.from[key]+(goal[key]-tween.from[key])*ease
|
|
212
245
|
const moving=progress<1
|
|
@@ -223,38 +256,82 @@ function mountBodyTargetFrame(document, window, operation) {
|
|
|
223
256
|
if(frame.style.opacity!==opacity)frame.style.opacity=opacity
|
|
224
257
|
settled=!moving
|
|
225
258
|
frame.toggleAttribute('data-pressed',pressed)
|
|
226
|
-
if(moving)
|
|
259
|
+
if(releasePending && pressed && !moving){
|
|
260
|
+
if(retiringBounds){exitGoal={...state,alpha:0};retiringBounds=null}
|
|
261
|
+
releasePending=false;pressed=false;motionDuration=imageRetiring?120:140;settled=false;wake()
|
|
262
|
+
}
|
|
263
|
+
else if(moving)wake()
|
|
227
264
|
else {tween=null;if(!state.alpha)hideFrame()}
|
|
228
265
|
}
|
|
229
|
-
const
|
|
266
|
+
const applyMove=event=>{
|
|
230
267
|
if(document.hidden || event.pointerType==='touch' || !fine?.matches)return
|
|
231
268
|
pointer={x:event.clientX,y:event.clientY}
|
|
232
269
|
const next=find(event.target)
|
|
233
270
|
if(next===hovered && (next || !state?.alpha))return
|
|
234
271
|
hovered=next;choose()
|
|
235
272
|
}
|
|
236
|
-
const
|
|
273
|
+
const clearMove=()=>{window.cancelAnimationFrame(moveRaf);moveRaf=0;pendingMove=null}
|
|
274
|
+
const flushMove=()=>{
|
|
275
|
+
const event=pendingMove;clearMove()
|
|
276
|
+
if(event)applyMove(event)
|
|
277
|
+
}
|
|
278
|
+
const move=event=>{
|
|
279
|
+
if(document.hidden || event.pointerType==='touch' || !fine?.matches)return
|
|
280
|
+
pendingMove={target:event.target,clientX:event.clientX,clientY:event.clientY,pointerType:event.pointerType}
|
|
281
|
+
if(!moveRaf)moveRaf=window.requestAnimationFrame(flushMove)
|
|
282
|
+
}
|
|
283
|
+
const leave=()=>{clearMove();hovered=null;choose()}
|
|
237
284
|
const focus=event=>{focused=event.target.matches?.(':focus-visible')?find(event.target):null;choose()}
|
|
238
285
|
const blur=()=>{focused=null;choose()}
|
|
239
286
|
const down=event=>{
|
|
287
|
+
flushMove()
|
|
240
288
|
pointer={x:event.clientX,y:event.clientY}
|
|
241
289
|
if(event.pointerType==='touch')hovered=find(event.target)
|
|
242
290
|
choose()
|
|
243
|
-
if(target && find(event.target)===target){pressed=true;motionDuration=100;settled=false;wake()}
|
|
291
|
+
if(target && find(event.target)===target){pressed=true;releasePending=false;motionDuration=100;settled=false;wake()}
|
|
292
|
+
}
|
|
293
|
+
const release=()=>{
|
|
294
|
+
// A tap can release before the first paint. Finish one contraction, then
|
|
295
|
+
// expand; one flag keeps repeated taps interruptible without a timer queue.
|
|
296
|
+
if(pressed && !settled && !reduced?.matches){releasePending=true;settled=false;wake()}
|
|
297
|
+
else {pressed=false;releasePending=false;motionDuration=140;settled=false;wake()}
|
|
244
298
|
}
|
|
245
|
-
const up=event=>{
|
|
299
|
+
const up=event=>{release();if(event.pointerType==='touch')hovered=null;choose()}
|
|
246
300
|
const reset=()=>{
|
|
301
|
+
clearMove()
|
|
247
302
|
target?.removeAttribute('data-prts-corner-target');hideFrame()
|
|
248
|
-
hovered=focused=target=null;state=tween=bounds=exitGoal=null
|
|
249
|
-
|
|
303
|
+
hovered=focused=target=null;state=tween=bounds=exitGoal=retiringBounds=null
|
|
304
|
+
imageRetiring=false
|
|
305
|
+
pressed=false;releasePending=false;settled=true;boundsDirty=hitDirty=false
|
|
250
306
|
resizeObserver?.disconnect();window.cancelAnimationFrame(raf);raf=0
|
|
251
307
|
frame.style.opacity='0';frame.removeAttribute('data-pressed')
|
|
252
308
|
}
|
|
309
|
+
const syncModal=()=>{
|
|
310
|
+
const modals=[...document.querySelectorAll('dialog[open],[role="dialog"][aria-modal="true"]')]
|
|
311
|
+
const previousModal=activeModal
|
|
312
|
+
activeModal=modals.filter(node=>!node.hidden && node.getAttribute('aria-hidden')!=='true').at(-1) ?? null
|
|
313
|
+
if(activeModal===previousModal)return
|
|
314
|
+
if(activeModal && target && !activeModal.contains(target) && target.querySelector('img') && activeModal.querySelector('img') && releasePending && bounds && !reduced?.matches){
|
|
315
|
+
// The preview is opaque: show a bounded click acknowledgment above it,
|
|
316
|
+
// then fade at the thumbnail position instead of retaining a hover target.
|
|
317
|
+
imageRetiring=true;motionDuration=120;tween=null
|
|
318
|
+
retiringBounds={left:bounds.left,top:bounds.top,width:bounds.width,height:bounds.height}
|
|
319
|
+
target.removeAttribute('data-prts-corner-target');hovered=focused=target=null
|
|
320
|
+
boundsDirty=hitDirty=false;resizeObserver?.disconnect();settled=false;wake()
|
|
321
|
+
}else if(imageRetiring || activeModal && (!target || !activeModal.contains(target)))reset()
|
|
322
|
+
}
|
|
323
|
+
// Native image previews mount a body portal without moving the pointer.
|
|
324
|
+
// Watch portal changes only, not the streaming conversation subtree.
|
|
325
|
+
const modalObserver=window.MutationObserver?new window.MutationObserver(syncModal):null
|
|
326
|
+
modalObserver?.observe(document.body,{childList:true})
|
|
327
|
+
const modalToggle=event=>{if(event.target?.matches?.('dialog'))syncModal()}
|
|
328
|
+
document.addEventListener('toggle',modalToggle,true)
|
|
329
|
+
syncModal()
|
|
253
330
|
const visibility=()=>{if(document.hidden)reset()}
|
|
254
331
|
const scroll=()=>{if(!target && !state?.alpha)return;boundsDirty=true;hitDirty=!!hovered;wake()}
|
|
255
332
|
document.addEventListener('scroll',scroll,true)
|
|
256
333
|
window.addEventListener('resize',reset)
|
|
257
|
-
const key=event=>{if(target && (event.key===' ' || event.key==='Enter')){
|
|
334
|
+
const key=event=>{if(target && (event.key===' ' || event.key==='Enter')){if(event.type==='keyup')release();else {pressed=true;releasePending=false;motionDuration=100;settled=false;wake()}}}
|
|
258
335
|
const listeners=[
|
|
259
336
|
[document,'pointermove',move],[document,'pointerleave',leave],
|
|
260
337
|
[document,'focusin',focus],[document,'focusout',blur],
|
|
@@ -264,6 +341,8 @@ function mountBodyTargetFrame(document, window, operation) {
|
|
|
264
341
|
]
|
|
265
342
|
for(const [node,event,handler] of listeners)node.addEventListener(event,handler)
|
|
266
343
|
return ()=>{
|
|
344
|
+
clearMove()
|
|
345
|
+
modalObserver?.disconnect();document.removeEventListener('toggle',modalToggle,true)
|
|
267
346
|
disposed=true;target?.removeAttribute('data-prts-corner-target');hideFrame();window.cancelAnimationFrame(raf);resizeObserver?.disconnect()
|
|
268
347
|
document.removeEventListener('scroll',scroll,true);window.removeEventListener('resize',reset)
|
|
269
348
|
for(const [node,event,handler] of listeners)node.removeEventListener(event,handler)
|
|
@@ -8,7 +8,8 @@ export function createCursorAdapter({ document, window, assets }) {
|
|
|
8
8
|
let gestureAssets = assets
|
|
9
9
|
let textTarget
|
|
10
10
|
let lastPoint
|
|
11
|
-
const
|
|
11
|
+
const heroTextSelector = '[data-phase="hero"] [class$="_titleGroup"]'
|
|
12
|
+
const contentSelector = '[data-markdown], [data-slot*="markdown" i], [class*="markdown" i], :is([data-chat-flow-kind="user"], [data-chat-flow-kind="steering"], [data-submission-echo], [data-pending-steering]) [class$="_bubble"]'
|
|
12
13
|
const controlSelector = 'a[href], button, summary, input, textarea, select, [contenteditable], [role="button"], [role="toolbar"], [role="tab"]'
|
|
13
14
|
function clearTextHit() {
|
|
14
15
|
textTarget?.removeAttribute('data-prts-text-hit')
|
|
@@ -25,8 +26,8 @@ export function createCursorAdapter({ document, window, assets }) {
|
|
|
25
26
|
if (event.pointerType !== 'mouse') return
|
|
26
27
|
lastPoint = { clientX: event.clientX, clientY: event.clientY, pointerType: 'mouse' }
|
|
27
28
|
const target = event.target?.nodeType === 1 ? event.target : event.target?.parentElement
|
|
28
|
-
const content = target?.closest?.(contentSelector)
|
|
29
|
-
if (!content
|
|
29
|
+
const content = target?.closest?.(`${contentSelector}, ${heroTextSelector}`)
|
|
30
|
+
if (!content || (!content.matches(heroTextSelector) && !content.closest('[data-chat-flow-kind], [data-message-role], [data-submission-echo], [data-pending-steering]')) || target.closest(controlSelector)) return
|
|
30
31
|
const style = window.getComputedStyle(target)
|
|
31
32
|
if (style.userSelect === 'none' || !style.cursor.includes('data:image/png')) return
|
|
32
33
|
// Caret APIs return the nearest insertion point even over empty space.
|
|
@@ -43,7 +43,7 @@ export function createAvatarStore({window,document}){
|
|
|
43
43
|
const focus=()=>{if(window.fetch)void refresh().catch(()=>{})}
|
|
44
44
|
window.addEventListener('focus',focus)
|
|
45
45
|
return{
|
|
46
|
-
snapshot:()=>state,refresh,
|
|
46
|
+
snapshot:()=>state,refresh,applySnapshot:apply,
|
|
47
47
|
subscribe(fn){listeners.add(fn);fn(state);return()=>listeners.delete(fn)},
|
|
48
48
|
async edit(role){
|
|
49
49
|
const response=await window.fetch(API+'/edit/'+role,{credentials:'same-origin',signal:controller?.signal})
|
|
@@ -17,7 +17,7 @@ export function createHostGeometryAdapter({ document, window }) {
|
|
|
17
17
|
const root = document?.documentElement
|
|
18
18
|
let frame
|
|
19
19
|
let sidebar
|
|
20
|
-
|
|
20
|
+
const sidebarWidths = new Map()
|
|
21
21
|
let resizeObserver
|
|
22
22
|
let frameRequest
|
|
23
23
|
let resizeSettleTimer
|
|
@@ -35,7 +35,11 @@ export function createHostGeometryAdapter({ document, window }) {
|
|
|
35
35
|
}
|
|
36
36
|
if (sidebar?.isConnected) {
|
|
37
37
|
const width = cssPixels(sidebar.getBoundingClientRect().width)
|
|
38
|
-
|
|
38
|
+
for (const node of [sidebar, document.querySelector('[data-prts-nav-rail]')]) {
|
|
39
|
+
if (!node) continue
|
|
40
|
+
if (!sidebarWidths.has(node)) sidebarWidths.set(node, [node.style.getPropertyValue('--prts-sidebar-width'), node.style.getPropertyPriority('--prts-sidebar-width')])
|
|
41
|
+
if (node.style.getPropertyValue('--prts-sidebar-width') !== width) node.style.setProperty('--prts-sidebar-width', width)
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
return top
|
|
41
45
|
}
|
|
@@ -103,8 +107,11 @@ export function createHostGeometryAdapter({ document, window }) {
|
|
|
103
107
|
else root.style.removeProperty(TOP_INSET_PROPERTY)
|
|
104
108
|
previousValue = undefined
|
|
105
109
|
previousPriority = undefined
|
|
106
|
-
|
|
107
|
-
|
|
110
|
+
for (const [node, [value, priority]] of sidebarWidths) {
|
|
111
|
+
if (value) node.style.setProperty('--prts-sidebar-width', value, priority)
|
|
112
|
+
else node.style.removeProperty('--prts-sidebar-width')
|
|
113
|
+
}
|
|
114
|
+
sidebarWidths.clear()
|
|
108
115
|
sidebar = undefined
|
|
109
116
|
frame = undefined
|
|
110
117
|
observedFrameHeight = undefined
|
|
@@ -121,7 +128,6 @@ export function createHostGeometryAdapter({ document, window }) {
|
|
|
121
128
|
if (started) dispose()
|
|
122
129
|
frame = nextFrame
|
|
123
130
|
sidebar = frame.querySelector?.('[data-prts-region="sessions"]')
|
|
124
|
-
previousSidebarWidth = root.style.getPropertyValue('--prts-sidebar-width')
|
|
125
131
|
previousValue = root.style.getPropertyValue(TOP_INSET_PROPERTY)
|
|
126
132
|
previousPriority = root.style.getPropertyPriority(TOP_INSET_PROPERTY)
|
|
127
133
|
started = true
|
package/src/client/index.js
CHANGED
|
@@ -208,6 +208,7 @@ export function applyPrtsPlugin(ctx, environment) {
|
|
|
208
208
|
document, window, assets, adapter, hostGeometry, customEmblemStore, avatarStore, backgroundStore,
|
|
209
209
|
themeTransfer: themeTransfer ||= createThemeTransfer({ window, getPreferences: () => nativePreferences.value,
|
|
210
210
|
savePreferences: (value, revision) => nativePreferences.replace(value, revision),
|
|
211
|
+
onAvatarConfiguration: value => avatarStore.applySnapshot(value),
|
|
211
212
|
checkWritable: () => nativePreferences.checkWritable(), checkExport: () => nativePreferences.checkReadable(), themeVersion: version }),
|
|
212
213
|
onSchemeToggle(next, interaction) {
|
|
213
214
|
return theme.setTheme(next, { ...interaction, animate: true })
|
|
@@ -222,6 +223,7 @@ export function applyPrtsPlugin(ctx, environment) {
|
|
|
222
223
|
persistAndApply(updatePreferenceValue(preferences, key, value))
|
|
223
224
|
},
|
|
224
225
|
onPreferencePreview(key, value) {
|
|
226
|
+
if (key === 'cornerColor') { document.documentElement.style.setProperty('--prts-corner-color', String(value)); return }
|
|
225
227
|
if (key === 'particleTraversalSpeed') {
|
|
226
228
|
particleField.update(updatePreferenceValue(preferences, key, value))
|
|
227
229
|
return
|
|
@@ -39,6 +39,8 @@ export const DEFAULT_PREFERENCES = Object.freeze({
|
|
|
39
39
|
bakerBlur: 8,
|
|
40
40
|
classicUserBlur: 8,
|
|
41
41
|
cursor: 'prts',
|
|
42
|
+
cornerColor: '#f0c800',
|
|
43
|
+
cornerCustomColor: '#f0c800',
|
|
42
44
|
conversationParticleDensity: 'sparse',
|
|
43
45
|
heroParticleDensity: 'light',
|
|
44
46
|
particleTraversalSpeed: PARTICLE_TRAVERSAL_SPEED_DEFAULT,
|
|
@@ -105,7 +107,7 @@ export const PREFERENCE_GROUPS = Object.freeze({
|
|
|
105
107
|
background: Object.freeze(['texture', 'backgroundMode', 'backgroundDim', 'heroContrast', 'sidebarOpacity', 'rightSidebarOpacity', 'railOpacity', 'bakerOpacity', 'classicUserOpacity', 'sidebarBlur', 'rightSidebarBlur', 'railBlur', 'bakerBlur', 'classicUserBlur']),
|
|
106
108
|
particles: Object.freeze(['conversationParticleDensity', 'heroParticleDensity', 'particleTraversalSpeed']),
|
|
107
109
|
material: Object.freeze(['glass', 'composerGlass']),
|
|
108
|
-
accessibility: Object.freeze(['motion', 'bootAnimation', 'cursor']),
|
|
110
|
+
accessibility: Object.freeze(['motion', 'bootAnimation', 'cursor', 'cornerColor', 'cornerCustomColor']),
|
|
109
111
|
aiTools: Object.freeze(['aiToolsEnabled']),
|
|
110
112
|
navigation: Object.freeze(['railDefaultHidden', 'sessionPreview', 'previewOngoing', 'previewTools', 'previewWarning', 'previewDone', 'previewDoubleClick', 'previewFollowOngoing', 'previewFollowWarning', 'previewReplyLimit']),
|
|
111
113
|
conversation: Object.freeze(['sessionFlow', 'sessionGlow', 'sessionFlowPalette', 'sessionFlowColorBack', 'sessionFlowColorCore', 'sessionFlowColorFront', 'sessionFlowSpeed', 'conversationStyle', 'bakerGroupAvatars', 'bakerLoading', 'conversationEmblem']),
|
|
@@ -229,6 +231,8 @@ export function normalizePreferences(value) {
|
|
|
229
231
|
backgroundDim: typeof input.backgroundDim === 'number' && Number.isFinite(input.backgroundDim) ? Math.min(.9, Math.max(0, input.backgroundDim)) : .45,
|
|
230
232
|
composerGlass: booleanOr(input.composerGlass, DEFAULT_PREFERENCES.composerGlass),
|
|
231
233
|
bootAnimation: booleanOr(input.bootAnimation, DEFAULT_PREFERENCES.bootAnimation),
|
|
234
|
+
cornerCustomColor: colorOr(input.cornerCustomColor, DEFAULT_PREFERENCES.cornerCustomColor),
|
|
235
|
+
cornerColor: colorOr(input.cornerColor, DEFAULT_PREFERENCES.cornerColor),
|
|
232
236
|
cursor: input.cursor === 'system' ? 'system' : DEFAULT_PREFERENCES.cursor,
|
|
233
237
|
conversationParticleDensity: enumOr(legacyDensities.conversation, PARTICLE_DENSITIES, particlePreset.conversationParticleDensity),
|
|
234
238
|
heroParticleDensity: enumOr(legacyDensities.hero, PARTICLE_DENSITIES, particlePreset.heroParticleDensity),
|
|
@@ -283,6 +287,10 @@ export function updatePreferenceValue(value, key, nextValue) {
|
|
|
283
287
|
if (key === 'preset') return applyVisualPreset(value, nextValue)
|
|
284
288
|
if (key === 'particleDetail') return applyParticleDetail(value, nextValue)
|
|
285
289
|
const current = normalizePreferences(value)
|
|
290
|
+
if (key === 'cornerCustomColor') {
|
|
291
|
+
const color = colorOr(nextValue, current.cornerCustomColor)
|
|
292
|
+
return normalizePreferences({ ...current, cornerColor: color, cornerCustomColor: color })
|
|
293
|
+
}
|
|
286
294
|
if (key === 'sessionFlowPalette') {
|
|
287
295
|
const palette = enumOr(nextValue, SESSION_FLOW_PALETTE_IDS, current.sessionFlowPalette)
|
|
288
296
|
const colors = SESSION_FLOW_PALETTES[palette]
|
|
@@ -95,9 +95,13 @@ function visibleSessionSummaries(sessions, workspaces, sessionStatus) {
|
|
|
95
95
|
})
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
function setSidebarAttribute(node, attribute, value) {
|
|
99
|
+
if (node.getAttribute(attribute) !== value) node.setAttribute(attribute, value)
|
|
100
|
+
}
|
|
101
|
+
|
|
98
102
|
function markSidebarNode(node, attribute, next) {
|
|
99
103
|
if (!node) return
|
|
100
|
-
node
|
|
104
|
+
setSidebarAttribute(node, attribute, '')
|
|
101
105
|
next.add(node)
|
|
102
106
|
}
|
|
103
107
|
|
|
@@ -174,9 +178,9 @@ function ensureFacilityFace(document, row, kind, next) {
|
|
|
174
178
|
face.setAttribute('data-prts-owned-facility', '')
|
|
175
179
|
row.insertBefore(face, row.firstChild)
|
|
176
180
|
}
|
|
177
|
-
face
|
|
178
|
-
face
|
|
179
|
-
face
|
|
181
|
+
setSidebarAttribute(face, 'data-prts-facility-face', kind)
|
|
182
|
+
setSidebarAttribute(face, 'data-prts-facility-texture', kind === 'workspace' ? 'silhouette' : 'pickup')
|
|
183
|
+
setSidebarAttribute(face, 'aria-hidden', 'true')
|
|
180
184
|
next.add(face)
|
|
181
185
|
return face
|
|
182
186
|
}
|
|
@@ -188,8 +192,8 @@ function ensureFacilitySpine(document, row, kind, next) {
|
|
|
188
192
|
spine.setAttribute('data-prts-owned-facility-spine', '')
|
|
189
193
|
row.insertBefore(spine, row.firstChild)
|
|
190
194
|
}
|
|
191
|
-
spine
|
|
192
|
-
spine
|
|
195
|
+
setSidebarAttribute(spine, 'data-prts-facility-spine', kind)
|
|
196
|
+
setSidebarAttribute(spine, 'aria-hidden', 'true')
|
|
193
197
|
next.add(spine)
|
|
194
198
|
return spine
|
|
195
199
|
}
|
|
@@ -223,6 +227,7 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
223
227
|
let statusSourcesStarted = false
|
|
224
228
|
let summaryRoot
|
|
225
229
|
let summarySignature = ''
|
|
230
|
+
let sourceSummarySignature = ''
|
|
226
231
|
let heldPreviewState
|
|
227
232
|
let hoveredSummary, summaryLeaveTimer
|
|
228
233
|
let summaryDismissed = false, pointerLeftSummary = false
|
|
@@ -327,18 +332,26 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
327
332
|
sourceRetryTimer = undefined
|
|
328
333
|
}
|
|
329
334
|
}
|
|
335
|
+
function onSummarySourceChange() {
|
|
336
|
+
// Streaming activity often republishes unchanged title/status summaries.
|
|
337
|
+
// Native DOM mutations still handle row mounts, selection and hierarchy.
|
|
338
|
+
const signature = JSON.stringify(visibleSessionSummaries(sessions, workspaces, sessionStatus))
|
|
339
|
+
if (signature === sourceSummarySignature && !pendingReveal) return
|
|
340
|
+
sourceSummarySignature = signature
|
|
341
|
+
queueScan()
|
|
342
|
+
}
|
|
330
343
|
function connectSummarySources() {
|
|
331
344
|
if (getSessions) sessions = getSessions()
|
|
332
345
|
if (getWorkspaces) workspaces = getWorkspaces()
|
|
333
346
|
if (subscribedSessions !== sessions?.list) {
|
|
334
347
|
stopSessionList()
|
|
335
348
|
subscribedSessions = sessions?.list
|
|
336
|
-
stopSessionList = subscribedSessions?.subscribe?.(
|
|
349
|
+
stopSessionList = subscribedSessions?.subscribe?.(onSummarySourceChange) ?? (() => {})
|
|
337
350
|
}
|
|
338
351
|
if (subscribedWorkspaces !== workspaces?.list) {
|
|
339
352
|
stopWorkspaceList()
|
|
340
353
|
subscribedWorkspaces = workspaces?.list
|
|
341
|
-
stopWorkspaceList = subscribedWorkspaces?.subscribe?.(
|
|
354
|
+
stopWorkspaceList = subscribedWorkspaces?.subscribe?.(onSummarySourceChange) ?? (() => {})
|
|
342
355
|
}
|
|
343
356
|
}
|
|
344
357
|
function connectSessionStatus() {
|
|
@@ -346,7 +359,7 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
346
359
|
if (source === sessionStatus) return
|
|
347
360
|
stopSessionStatus()
|
|
348
361
|
sessionStatus = source
|
|
349
|
-
stopSessionStatus = source?.subscribe?.(
|
|
362
|
+
stopSessionStatus = source?.subscribe?.(onSummarySourceChange) ?? (() => {})
|
|
350
363
|
}
|
|
351
364
|
|
|
352
365
|
let selectionTarget, selectionTargetTimer
|
|
@@ -849,6 +862,28 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
849
862
|
}
|
|
850
863
|
|
|
851
864
|
|
|
865
|
+
let pickupRow, pickupTimer, pickupRoot
|
|
866
|
+
function clearPickup() {
|
|
867
|
+
if (pickupTimer !== undefined) window.clearTimeout(pickupTimer)
|
|
868
|
+
pickupTimer = undefined
|
|
869
|
+
pickupRow?.removeAttribute('data-prts-pickup-ready')
|
|
870
|
+
pickupRow = undefined
|
|
871
|
+
}
|
|
872
|
+
function pickupOver(event) {
|
|
873
|
+
const row = event.target.closest?.('[data-prts-session-row]')
|
|
874
|
+
if (row === pickupRow) return
|
|
875
|
+
clearPickup()
|
|
876
|
+
if (!row) return
|
|
877
|
+
pickupRow = row
|
|
878
|
+
pickupTimer = window.setTimeout(() => {
|
|
879
|
+
pickupTimer = undefined
|
|
880
|
+
if (row.isConnected && pickupRow === row) row.setAttribute('data-prts-pickup-ready', '')
|
|
881
|
+
}, 100)
|
|
882
|
+
}
|
|
883
|
+
function pickupOut(event) {
|
|
884
|
+
if (pickupRow && !pickupRow.contains(event.relatedTarget)) clearPickup()
|
|
885
|
+
}
|
|
886
|
+
|
|
852
887
|
function queueScan() {
|
|
853
888
|
if (!adapterActive || scanFrame !== undefined) return
|
|
854
889
|
const requestFrame = window?.requestAnimationFrame?.bind(window) ?? (callback => window?.setTimeout?.(callback, 0))
|
|
@@ -861,6 +896,7 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
861
896
|
function scan() {
|
|
862
897
|
if (!adapterActive) return
|
|
863
898
|
syncSummarySources()
|
|
899
|
+
sourceSummarySignature = JSON.stringify(visibleSessionSummaries(sessions, workspaces, sessionStatus))
|
|
864
900
|
const root = document?.querySelector?.('[data-prts-region="sessions"] [data-slot="sidebar.workspaces"]')
|
|
865
901
|
const next = new Set()
|
|
866
902
|
const nextVectorOwners = new Set()
|
|
@@ -919,16 +955,16 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
919
955
|
}
|
|
920
956
|
markSidebarNode(row, 'data-prts-session-row', next)
|
|
921
957
|
if (state) {
|
|
922
|
-
row
|
|
958
|
+
setSidebarAttribute(row, 'data-prts-session-state', state)
|
|
923
959
|
next.add(row)
|
|
924
960
|
} else {
|
|
925
961
|
row.removeAttribute('data-prts-session-state')
|
|
926
962
|
}
|
|
927
|
-
row
|
|
963
|
+
setSidebarAttribute(row, 'data-prts-session-index', sessionIndex)
|
|
928
964
|
const title = resolveRowTitle(row, 'session', controls.actions)
|
|
929
965
|
markSidebarNode(title, 'data-prts-row-title', next)
|
|
930
966
|
markSidebarNode(resolveSessionTime(row, title, controls.actions), 'data-prts-session-time', next)
|
|
931
|
-
if (title) title
|
|
967
|
+
if (title) setSidebarAttribute(title, 'data-prts-session-index', sessionIndex)
|
|
932
968
|
row.toggleAttribute('data-prts-row-menu-open', controls.menu?.getAttribute('aria-expanded') === 'true'
|
|
933
969
|
|| row.classList.contains('menuOpen'))
|
|
934
970
|
markSidebarNode(controls.actions, 'data-prts-session-actions', next)
|
|
@@ -1007,8 +1043,18 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
1007
1043
|
if (observer || !window?.MutationObserver) return
|
|
1008
1044
|
const observationRoot = document.querySelector('[data-prts-region="sessions"]')
|
|
1009
1045
|
if (!observationRoot) return
|
|
1046
|
+
pickupRoot = observationRoot
|
|
1047
|
+
pickupRoot.addEventListener('pointerover', pickupOver)
|
|
1048
|
+
pickupRoot.addEventListener('pointerout', pickupOut)
|
|
1010
1049
|
observer = new window.MutationObserver(mutations => {
|
|
1011
|
-
const relevant = mutations.filter(mutation =>
|
|
1050
|
+
const relevant = mutations.filter(mutation => {
|
|
1051
|
+
if (mutation.target.closest?.('[data-prts-owned-session-summary]')) return false
|
|
1052
|
+
if (mutation.type === 'attributes' && mutation.attributeName === 'class' && !mutation.target.closest('[role="treeitem"]')) {
|
|
1053
|
+
const stableClasses = value => (value ?? '').split(/\s+/).filter(token => token && !token.endsWith('_quietBars')).sort().join(' ')
|
|
1054
|
+
if (stableClasses(mutation.oldValue) === stableClasses(mutation.target.getAttribute('class'))) return false
|
|
1055
|
+
}
|
|
1056
|
+
return true
|
|
1057
|
+
})
|
|
1012
1058
|
const freshRow = 'div[role="treeitem"]:not([data-prts-session-row]):not([data-prts-workspace-row])'
|
|
1013
1059
|
const mountsRows = relevant.some(mutation => mutation.type === 'childList'
|
|
1014
1060
|
&& Array.from(mutation.addedNodes).some(node => node.nodeType === 1
|
|
@@ -1026,9 +1072,14 @@ export function createSidebarControlAdapter({ document, window, sessions, worksp
|
|
|
1026
1072
|
childList: true,
|
|
1027
1073
|
attributes: true,
|
|
1028
1074
|
attributeFilter: ['aria-expanded', 'aria-selected', 'class', 'data-state'],
|
|
1075
|
+
attributeOldValue: true,
|
|
1029
1076
|
})
|
|
1030
1077
|
},
|
|
1031
1078
|
dispose() {
|
|
1079
|
+
clearPickup()
|
|
1080
|
+
pickupRoot?.removeEventListener('pointerover', pickupOver)
|
|
1081
|
+
pickupRoot?.removeEventListener('pointerout', pickupOut)
|
|
1082
|
+
pickupRoot = undefined
|
|
1032
1083
|
adapterActive = false
|
|
1033
1084
|
disconnectSummarySources()
|
|
1034
1085
|
cancelReveal()
|
|
@@ -19,6 +19,7 @@ const ROOT_ATTRIBUTES = [
|
|
|
19
19
|
'data-prts-background-mode',
|
|
20
20
|
]
|
|
21
21
|
const SESSION_FLOW_COLOR_PROPERTIES = {
|
|
22
|
+
'--prts-corner-color': 'cornerColor',
|
|
22
23
|
'--prts-session-flow-back': 'sessionFlowColorBack',
|
|
23
24
|
'--prts-session-flow-core': 'sessionFlowColorCore',
|
|
24
25
|
'--prts-session-flow-front': 'sessionFlowColorFront',
|
|
@@ -14,6 +14,7 @@ const ROOT_ATTRIBUTES = [
|
|
|
14
14
|
'data-prts-conversation-style',
|
|
15
15
|
]
|
|
16
16
|
const SESSION_FLOW_COLOR_PROPERTIES = {
|
|
17
|
+
'--prts-corner-color': 'cornerColor',
|
|
17
18
|
'--prts-session-flow-back': 'sessionFlowColorBack',
|
|
18
19
|
'--prts-session-flow-core': 'sessionFlowColorCore',
|
|
19
20
|
'--prts-session-flow-front': 'sessionFlowColorFront',
|