@mhmo91/schmancy 0.10.34 → 0.10.35
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/custom-elements.json +2 -31
- package/dist/agent/schmancy.agent.js +51 -59
- package/dist/agent/schmancy.agent.js.map +1 -1
- package/dist/agent/schmancy.manifest.json +2 -21
- package/dist/badge.cjs +1 -1
- package/dist/badge.js +1 -1
- package/dist/boat-Vqjgo10B.cjs +33 -0
- package/dist/boat-Vqjgo10B.cjs.map +1 -0
- package/dist/boat-lr7MPZ7H.js +207 -0
- package/dist/boat-lr7MPZ7H.js.map +1 -0
- package/dist/boat.cjs +1 -1
- package/dist/boat.js +1 -1
- package/dist/content-drawer.cjs +1 -1
- package/dist/content-drawer.js +1 -1
- package/dist/handover/agent-runtime-followups.md +1 -1
- package/dist/handover/agent-runtime-v1.md +3 -3
- package/dist/index.cjs +1 -1
- package/dist/index.js +2 -2
- package/dist/nav-drawer.cjs +1 -1
- package/dist/nav-drawer.js +1 -1
- package/dist/navigation-bar.cjs +1 -1
- package/dist/navigation-bar.js +1 -1
- package/dist/{src-DoOhMBtI.js → src-C5g3p1J5.js} +1 -1
- package/dist/{src-DoOhMBtI.js.map → src-C5g3p1J5.js.map} +1 -1
- package/dist/{src-Bm1vop0l.cjs → src-qzUpLbje.cjs} +1 -1
- package/dist/{src-Bm1vop0l.cjs.map → src-qzUpLbje.cjs.map} +1 -1
- package/dist/teleport.cjs +1 -1
- package/dist/teleport.js +1 -1
- package/package.json +1 -1
- package/src/boat/boat.ts +67 -84
- package/types/src/boat/boat.d.ts +15 -18
- package/dist/boat-BgpWcLnV.cjs +0 -38
- package/dist/boat-BgpWcLnV.cjs.map +0 -1
- package/dist/boat-Y5UMiJCV.js +0 -216
- package/dist/boat-Y5UMiJCV.js.map +0 -1
package/src/boat/boat.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { SchmancyElement } from '@mixins/index'
|
|
2
|
-
import { css, html,
|
|
2
|
+
import { css, html, type PropertyValues } from 'lit'
|
|
3
3
|
import { customElement, property, queryAssignedElements, state } from 'lit/decorators.js'
|
|
4
4
|
import { classMap } from 'lit/directives/class-map.js'
|
|
5
5
|
import { createRef, ref } from 'lit/directives/ref.js'
|
|
6
6
|
import { styleMap } from 'lit/directives/style-map.js'
|
|
7
|
-
import { when } from 'lit/directives/when.js'
|
|
8
7
|
import { filter, finalize, fromEvent, map, merge, type Subscription, switchMap, takeUntil, tap } from 'rxjs'
|
|
9
|
-
import { SPRING_SMOOTH } from '../utils/animation.js'
|
|
10
8
|
import { reducedMotion$ } from '../directives/reduced-motion'
|
|
11
9
|
import { show } from '../overlay/overlay.service'
|
|
12
10
|
import { theme } from '../theme/theme.service.js'
|
|
11
|
+
import { SPRING_SMOOTH } from '../utils/animation.js'
|
|
13
12
|
|
|
14
13
|
const DRAG_THRESHOLD = 5
|
|
15
14
|
const POSITION_STORAGE_KEY_PREFIX = 'schmancy-boat-'
|
|
@@ -38,25 +37,22 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
38
37
|
}
|
|
39
38
|
`]
|
|
40
39
|
|
|
40
|
+
/** Identity for localStorage drag-position persistence. */
|
|
41
41
|
@property({ type: String }) id: string = 'default'
|
|
42
|
-
@property({ type: String }) icon?: string
|
|
43
|
-
@property({ type: String }) label?: string
|
|
44
|
-
/** When true, uses a lower elevation shadow on the FAB. */
|
|
45
|
-
@property({ type: Boolean, reflect: true }) lowered: boolean = false
|
|
46
42
|
/** Corner the FAB is anchored to. */
|
|
47
43
|
@property({ type: String }) corner: Corner = 'bottom-right'
|
|
48
44
|
/** Open state. Bind `?open=${…}` to drive the overlay; reflected to the attribute. */
|
|
49
45
|
@property({ type: Boolean, reflect: true }) open: boolean = false
|
|
50
46
|
|
|
51
47
|
@state() private isDragging = false
|
|
52
|
-
@state() private
|
|
48
|
+
@state() private currentCorner: Corner = 'bottom-right'
|
|
53
49
|
|
|
54
|
-
@queryAssignedElements() private
|
|
50
|
+
@queryAssignedElements() private slotted!: Element[]
|
|
55
51
|
|
|
56
|
-
private
|
|
57
|
-
private
|
|
58
|
-
private
|
|
59
|
-
private
|
|
52
|
+
private position: Position = { x: 16, y: 16 }
|
|
53
|
+
private containerRef = createRef<HTMLElement>()
|
|
54
|
+
private headerRef = createRef<HTMLElement>()
|
|
55
|
+
private currentAnimation?: Animation
|
|
60
56
|
|
|
61
57
|
#ready = false
|
|
62
58
|
#sub?: Subscription
|
|
@@ -66,76 +62,76 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
66
62
|
// POSITION MANAGEMENT
|
|
67
63
|
// ============================================
|
|
68
64
|
|
|
69
|
-
private
|
|
70
|
-
const container = this.
|
|
65
|
+
private applyContainerPosition() {
|
|
66
|
+
const container = this.containerRef.value
|
|
71
67
|
if (!container) return
|
|
72
68
|
container.style.removeProperty('left')
|
|
73
69
|
container.style.removeProperty('right')
|
|
74
70
|
container.style.removeProperty('top')
|
|
75
71
|
container.style.removeProperty('bottom')
|
|
76
|
-
const { x, y } = this.
|
|
77
|
-
if (this.
|
|
72
|
+
const { x, y } = this.position
|
|
73
|
+
if (this.currentCorner.includes('right')) {
|
|
78
74
|
container.style.right = `${x}px`
|
|
79
75
|
} else {
|
|
80
76
|
container.style.left = `${x}px`
|
|
81
77
|
}
|
|
82
|
-
if (this.
|
|
78
|
+
if (this.currentCorner.includes('bottom')) {
|
|
83
79
|
container.style.bottom = `${y + theme.bottomOffset}px`
|
|
84
80
|
} else {
|
|
85
81
|
container.style.top = `${y}px`
|
|
86
82
|
}
|
|
87
83
|
}
|
|
88
84
|
|
|
89
|
-
private
|
|
85
|
+
private loadPosition() {
|
|
90
86
|
try {
|
|
91
87
|
const saved = localStorage.getItem(POSITION_STORAGE_KEY_PREFIX + this.id)
|
|
92
88
|
if (saved) {
|
|
93
89
|
const parsed = JSON.parse(saved) as { x: number; y: number; anchor: Corner }
|
|
94
|
-
this.
|
|
95
|
-
this.
|
|
90
|
+
this.position = { x: parsed.x, y: parsed.y }
|
|
91
|
+
this.currentCorner = parsed.anchor
|
|
96
92
|
}
|
|
97
93
|
} catch {
|
|
98
94
|
// ignore localStorage errors
|
|
99
95
|
}
|
|
100
96
|
}
|
|
101
97
|
|
|
102
|
-
private
|
|
98
|
+
private savePosition() {
|
|
103
99
|
try {
|
|
104
100
|
localStorage.setItem(
|
|
105
101
|
POSITION_STORAGE_KEY_PREFIX + this.id,
|
|
106
|
-
JSON.stringify({ ...this.
|
|
102
|
+
JSON.stringify({ ...this.position, anchor: this.currentCorner }),
|
|
107
103
|
)
|
|
108
104
|
} catch {
|
|
109
105
|
// ignore localStorage errors
|
|
110
106
|
}
|
|
111
107
|
}
|
|
112
108
|
|
|
113
|
-
private
|
|
114
|
-
const container = this.
|
|
109
|
+
private validateBounds() {
|
|
110
|
+
const container = this.containerRef.value
|
|
115
111
|
if (!container) return
|
|
116
112
|
const rect = container.getBoundingClientRect()
|
|
117
113
|
if (rect.width === 0) return
|
|
118
114
|
const vw = window.innerWidth
|
|
119
115
|
const vh = window.innerHeight
|
|
120
|
-
const isRight = this.
|
|
121
|
-
const isBottom = this.
|
|
122
|
-
const actualLeft = isRight ? vw - this.
|
|
123
|
-
const actualTop = isBottom ? vh - this.
|
|
116
|
+
const isRight = this.currentCorner.includes('right')
|
|
117
|
+
const isBottom = this.currentCorner.includes('bottom')
|
|
118
|
+
const actualLeft = isRight ? vw - this.position.x - rect.width : this.position.x
|
|
119
|
+
const actualTop = isBottom ? vh - this.position.y - rect.height : this.position.y
|
|
124
120
|
const newLeft = Math.max(0, Math.min(actualLeft, vw - rect.width))
|
|
125
121
|
const newTop = Math.max(0, Math.min(actualTop, vh - rect.height))
|
|
126
|
-
this.
|
|
122
|
+
this.position = {
|
|
127
123
|
x: isRight ? vw - newLeft - rect.width : newLeft,
|
|
128
124
|
y: isBottom ? vh - newTop - rect.height : newTop,
|
|
129
125
|
}
|
|
130
|
-
this.
|
|
126
|
+
this.applyContainerPosition()
|
|
131
127
|
}
|
|
132
128
|
|
|
133
129
|
// ============================================
|
|
134
130
|
// CORNER SNAPPING (FLIP)
|
|
135
131
|
// ============================================
|
|
136
132
|
|
|
137
|
-
private
|
|
138
|
-
const container = this.
|
|
133
|
+
private reorientToNearestCorner(): void {
|
|
134
|
+
const container = this.containerRef.value
|
|
139
135
|
if (!container) return
|
|
140
136
|
|
|
141
137
|
const rect = container.getBoundingClientRect()
|
|
@@ -143,12 +139,12 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
143
139
|
const fabCenterY = rect.top + rect.height / 2
|
|
144
140
|
const side = fabCenterX > window.innerWidth / 2 ? 'right' : 'left'
|
|
145
141
|
const vert = fabCenterY > window.innerHeight / 2 ? 'bottom' : 'top'
|
|
146
|
-
this.
|
|
147
|
-
this.
|
|
148
|
-
this.
|
|
142
|
+
this.currentCorner = `${vert}-${side}` as Corner
|
|
143
|
+
this.position = { x: 16, y: 16 }
|
|
144
|
+
this.applyContainerPosition()
|
|
149
145
|
|
|
150
146
|
if (reducedMotion$.value) {
|
|
151
|
-
this.
|
|
147
|
+
this.savePosition()
|
|
152
148
|
return
|
|
153
149
|
}
|
|
154
150
|
|
|
@@ -157,7 +153,7 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
157
153
|
const dy = rect.top - newRect.top
|
|
158
154
|
container.style.transform = `translate(${dx}px, ${dy}px)`
|
|
159
155
|
|
|
160
|
-
this.
|
|
156
|
+
this.currentAnimation?.cancel()
|
|
161
157
|
const anim = container.animate(
|
|
162
158
|
[{ transform: container.style.transform }, { transform: 'translate(0,0)' }],
|
|
163
159
|
{
|
|
@@ -166,22 +162,22 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
166
162
|
fill: 'forwards',
|
|
167
163
|
},
|
|
168
164
|
)
|
|
169
|
-
this.
|
|
165
|
+
this.currentAnimation = anim
|
|
170
166
|
anim.finished.then(() => {
|
|
171
167
|
if (container.isConnected) container.style.transform = ''
|
|
172
168
|
return
|
|
173
169
|
})
|
|
174
170
|
|
|
175
|
-
this.
|
|
171
|
+
this.savePosition()
|
|
176
172
|
}
|
|
177
173
|
|
|
178
174
|
// ============================================
|
|
179
175
|
// DRAG PIPELINE
|
|
180
176
|
// ============================================
|
|
181
177
|
|
|
182
|
-
private
|
|
183
|
-
const header = this.
|
|
184
|
-
const container = this.
|
|
178
|
+
private setupDrag() {
|
|
179
|
+
const header = this.headerRef.value
|
|
180
|
+
const container = this.containerRef.value
|
|
185
181
|
if (!header || !container) return
|
|
186
182
|
|
|
187
183
|
let didDrag = false
|
|
@@ -228,16 +224,16 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
228
224
|
const vh = window.innerHeight
|
|
229
225
|
const left = Math.max(0, Math.min(clientX - offsetX, vw - rect.width))
|
|
230
226
|
const top = Math.max(0, Math.min(clientY - offsetY, vh - rect.height))
|
|
231
|
-
this.
|
|
232
|
-
x: this.
|
|
233
|
-
y: this.
|
|
227
|
+
this.position = {
|
|
228
|
+
x: this.currentCorner.includes('right') ? vw - left - rect.width : left,
|
|
229
|
+
y: this.currentCorner.includes('bottom') ? vh - top - rect.height : top,
|
|
234
230
|
}
|
|
235
|
-
this.
|
|
231
|
+
this.applyContainerPosition()
|
|
236
232
|
}),
|
|
237
233
|
takeUntil(end$),
|
|
238
234
|
finalize(() => {
|
|
239
235
|
if (didDrag) {
|
|
240
|
-
this.
|
|
236
|
+
this.reorientToNearestCorner()
|
|
241
237
|
this.isDragging = false
|
|
242
238
|
didDrag = false
|
|
243
239
|
} else {
|
|
@@ -257,12 +253,12 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
257
253
|
// OVERLAY DELEGATION
|
|
258
254
|
// ============================================
|
|
259
255
|
|
|
260
|
-
private
|
|
256
|
+
private openOverlay() {
|
|
261
257
|
if (this.#sub) return
|
|
262
|
-
const anchor = this.
|
|
258
|
+
const anchor = this.containerRef.value
|
|
263
259
|
const wrapper = document.createElement('div')
|
|
264
260
|
wrapper.className = 'flex flex-col'
|
|
265
|
-
this.#captured = [...this.
|
|
261
|
+
this.#captured = [...this.slotted]
|
|
266
262
|
this.#captured.forEach(node => wrapper.appendChild(node))
|
|
267
263
|
|
|
268
264
|
this.#sub = show(wrapper, {
|
|
@@ -271,7 +267,7 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
271
267
|
historyStrategy: 'silent',
|
|
272
268
|
})
|
|
273
269
|
.pipe(
|
|
274
|
-
finalize(() => this.
|
|
270
|
+
finalize(() => this.restoreSlotted()),
|
|
275
271
|
takeUntil(this.disconnecting),
|
|
276
272
|
)
|
|
277
273
|
.subscribe()
|
|
@@ -279,7 +275,7 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
279
275
|
this.dispatchScopedEvent('toggle', 'open')
|
|
280
276
|
}
|
|
281
277
|
|
|
282
|
-
private
|
|
278
|
+
private restoreSlotted() {
|
|
283
279
|
this.#captured.forEach(node => this.appendChild(node))
|
|
284
280
|
this.#captured = []
|
|
285
281
|
this.#sub = undefined
|
|
@@ -296,33 +292,33 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
296
292
|
|
|
297
293
|
fromEvent(window, 'resize')
|
|
298
294
|
.pipe(takeUntil(this.disconnecting))
|
|
299
|
-
.subscribe(() => this.
|
|
295
|
+
.subscribe(() => this.validateBounds())
|
|
300
296
|
|
|
301
297
|
theme.bottomOffset$.pipe(
|
|
302
|
-
tap(() => this.
|
|
298
|
+
tap(() => this.applyContainerPosition()),
|
|
303
299
|
takeUntil(this.disconnecting),
|
|
304
300
|
).subscribe()
|
|
305
301
|
}
|
|
306
302
|
|
|
307
303
|
firstUpdated() {
|
|
308
|
-
this.
|
|
309
|
-
this.
|
|
310
|
-
if (!this.
|
|
311
|
-
this.
|
|
312
|
-
this.
|
|
304
|
+
this.currentCorner = this.corner
|
|
305
|
+
this.loadPosition()
|
|
306
|
+
if (!this.containerRef.value) return
|
|
307
|
+
this.applyContainerPosition()
|
|
308
|
+
this.setupDrag()
|
|
313
309
|
this.#ready = true
|
|
314
|
-
if (this.open) this.
|
|
310
|
+
if (this.open) this.openOverlay()
|
|
315
311
|
}
|
|
316
312
|
|
|
317
313
|
protected willUpdate(changed: PropertyValues<this>) {
|
|
318
314
|
if (!this.#ready || !changed.has('open')) return
|
|
319
|
-
if (this.open && !this.#sub) this.
|
|
315
|
+
if (this.open && !this.#sub) this.openOverlay()
|
|
320
316
|
else if (!this.open && this.#sub) this.#sub.unsubscribe()
|
|
321
317
|
}
|
|
322
318
|
|
|
323
319
|
disconnectedCallback() {
|
|
324
320
|
super.disconnectedCallback()
|
|
325
|
-
this.
|
|
321
|
+
this.currentAnimation?.cancel()
|
|
326
322
|
this.#sub?.unsubscribe()
|
|
327
323
|
}
|
|
328
324
|
|
|
@@ -357,50 +353,37 @@ export default class SchmancyBoat extends SchmancyElement {
|
|
|
357
353
|
|
|
358
354
|
const fabClasses = classMap({
|
|
359
355
|
'h-14': true,
|
|
356
|
+
'min-w-14': true,
|
|
357
|
+
'px-4': true,
|
|
360
358
|
'rounded-full': true,
|
|
361
359
|
flex: true,
|
|
362
360
|
'items-center': true,
|
|
361
|
+
'justify-center': true,
|
|
363
362
|
'gap-3': true,
|
|
364
363
|
'select-none': true,
|
|
365
364
|
'touch-none': true,
|
|
366
365
|
'cursor-grabbing': this.isDragging,
|
|
367
366
|
'cursor-pointer': !this.isDragging,
|
|
368
|
-
'px-5': !!this.label,
|
|
369
|
-
'w-14': !this.label,
|
|
370
|
-
'justify-center': !this.label,
|
|
371
367
|
})
|
|
372
368
|
|
|
373
369
|
return html`
|
|
374
370
|
<schmancy-surface
|
|
375
|
-
${ref(this.
|
|
371
|
+
${ref(this.containerRef)}
|
|
376
372
|
type="glass"
|
|
377
|
-
.elevation=${
|
|
373
|
+
.elevation=${3}
|
|
378
374
|
class=${containerClasses}
|
|
379
375
|
style=${containerStyles}
|
|
380
376
|
aria-expanded=${this.open}
|
|
381
377
|
>
|
|
382
378
|
<div
|
|
383
|
-
${ref(this.
|
|
379
|
+
${ref(this.headerRef)}
|
|
384
380
|
class=${fabClasses}
|
|
385
381
|
role="button"
|
|
386
382
|
tabindex="0"
|
|
387
|
-
aria-label
|
|
383
|
+
aria-label="Open panel"
|
|
388
384
|
title="Drag to move · click to open"
|
|
389
385
|
>
|
|
390
|
-
<slot name="header">
|
|
391
|
-
${when(
|
|
392
|
-
!!this.icon,
|
|
393
|
-
() => html`<schmancy-icon>${this.icon}</schmancy-icon>`,
|
|
394
|
-
() => nothing,
|
|
395
|
-
)}
|
|
396
|
-
</slot>
|
|
397
|
-
${when(
|
|
398
|
-
!!this.label,
|
|
399
|
-
() => html`<schmancy-typography type="label" token="lg" class="whitespace-nowrap">
|
|
400
|
-
${this.label}
|
|
401
|
-
</schmancy-typography>`,
|
|
402
|
-
() => nothing,
|
|
403
|
-
)}
|
|
386
|
+
<slot name="header"></slot>
|
|
404
387
|
<slot name="summary"></slot>
|
|
405
388
|
</div>
|
|
406
389
|
|
package/types/src/boat/boat.d.ts
CHANGED
|
@@ -11,30 +11,27 @@ type Corner = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
|
11
11
|
export default class SchmancyBoat extends SchmancyElement {
|
|
12
12
|
#private;
|
|
13
13
|
static styles: import("lit").CSSResult[];
|
|
14
|
+
/** Identity for localStorage drag-position persistence. */
|
|
14
15
|
id: string;
|
|
15
|
-
icon?: string;
|
|
16
|
-
label?: string;
|
|
17
|
-
/** When true, uses a lower elevation shadow on the FAB. */
|
|
18
|
-
lowered: boolean;
|
|
19
16
|
/** Corner the FAB is anchored to. */
|
|
20
17
|
corner: Corner;
|
|
21
18
|
/** Open state. Bind `?open=${…}` to drive the overlay; reflected to the attribute. */
|
|
22
19
|
open: boolean;
|
|
23
20
|
private isDragging;
|
|
24
|
-
private
|
|
25
|
-
private
|
|
26
|
-
private
|
|
27
|
-
private
|
|
28
|
-
private
|
|
29
|
-
private
|
|
30
|
-
private
|
|
31
|
-
private
|
|
32
|
-
private
|
|
33
|
-
private
|
|
34
|
-
private
|
|
35
|
-
private
|
|
36
|
-
private
|
|
37
|
-
private
|
|
21
|
+
private currentCorner;
|
|
22
|
+
private slotted;
|
|
23
|
+
private position;
|
|
24
|
+
private containerRef;
|
|
25
|
+
private headerRef;
|
|
26
|
+
private currentAnimation?;
|
|
27
|
+
private applyContainerPosition;
|
|
28
|
+
private loadPosition;
|
|
29
|
+
private savePosition;
|
|
30
|
+
private validateBounds;
|
|
31
|
+
private reorientToNearestCorner;
|
|
32
|
+
private setupDrag;
|
|
33
|
+
private openOverlay;
|
|
34
|
+
private restoreSlotted;
|
|
38
35
|
connectedCallback(): void;
|
|
39
36
|
firstUpdated(): void;
|
|
40
37
|
protected willUpdate(changed: PropertyValues<this>): void;
|
package/dist/boat-BgpWcLnV.cjs
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
require(`./chunk-CncqDLb2.cjs`);const e=require(`./SchmancyElement-CYIif26I.cjs`);require(`./mixins-CGXSzZc7.cjs`);const t=require(`./animation-CCOIW4wJ.cjs`),n=require(`./reduced-motion-Ds-HjMzn.cjs`),r=require(`./theme.service-p61RsJBF.cjs`),i=require(`./overlay.service-C8RsQzgM.cjs`);let a=require(`rxjs`),o=require(`lit/directives/class-map.js`),s=require(`lit/directives/style-map.js`),c=require(`lit/decorators.js`),l=require(`lit`),u=require(`lit/directives/ref.js`),d=require(`lit/directives/when.js`);var f=`schmancy-boat-`,p=class extends e.t{constructor(...e){super(...e),this.id=`default`,this.lowered=!1,this.corner=`bottom-right`,this.open=!1,this.isDragging=!1,this._currentCorner=`bottom-right`,this._position={x:16,y:16},this._containerRef=(0,u.createRef)(),this._headerRef=(0,u.createRef)(),this.#e=!1,this.#n=[]}static{this.styles=[l.css`
|
|
2
|
-
:host {
|
|
3
|
-
display: contents;
|
|
4
|
-
}
|
|
5
|
-
:host([hidden]) {
|
|
6
|
-
display: none !important;
|
|
7
|
-
}
|
|
8
|
-
`]}#e;#t;#n;_applyContainerPosition(){let e=this._containerRef.value;if(!e)return;e.style.removeProperty(`left`),e.style.removeProperty(`right`),e.style.removeProperty(`top`),e.style.removeProperty(`bottom`);let{x:t,y:n}=this._position;this._currentCorner.includes(`right`)?e.style.right=`${t}px`:e.style.left=`${t}px`,this._currentCorner.includes(`bottom`)?e.style.bottom=`${n+r.n.bottomOffset}px`:e.style.top=`${n}px`}_loadPosition(){try{let e=localStorage.getItem(f+this.id);if(e){let t=JSON.parse(e);this._position={x:t.x,y:t.y},this._currentCorner=t.anchor}}catch{}}_savePosition(){try{localStorage.setItem(f+this.id,JSON.stringify({...this._position,anchor:this._currentCorner}))}catch{}}_validateBounds(){let e=this._containerRef.value;if(!e)return;let t=e.getBoundingClientRect();if(t.width===0)return;let n=window.innerWidth,r=window.innerHeight,i=this._currentCorner.includes(`right`),a=this._currentCorner.includes(`bottom`),o=i?n-this._position.x-t.width:this._position.x,s=a?r-this._position.y-t.height:this._position.y,c=Math.max(0,Math.min(o,n-t.width)),l=Math.max(0,Math.min(s,r-t.height));this._position={x:i?n-c-t.width:c,y:a?r-l-t.height:l},this._applyContainerPosition()}_reorientToNearestCorner(){let e=this._containerRef.value;if(!e)return;let r=e.getBoundingClientRect(),i=r.left+r.width/2,a=r.top+r.height/2,o=i>window.innerWidth/2?`right`:`left`,s=a>window.innerHeight/2?`bottom`:`top`;if(this._currentCorner=`${s}-${o}`,this._position={x:16,y:16},this._applyContainerPosition(),n.t.value)return void this._savePosition();let c=e.getBoundingClientRect(),l=r.left-c.left,u=r.top-c.top;e.style.transform=`translate(${l}px, ${u}px)`,this._currentAnimation?.cancel();let d=e.animate([{transform:e.style.transform},{transform:`translate(0,0)`}],{duration:t.d.duration,easing:t.d.easingFallback,fill:`forwards`});this._currentAnimation=d,d.finished.then(()=>{e.isConnected&&(e.style.transform=``)}),this._savePosition()}_setupDrag(){let e=this._headerRef.value,t=this._containerRef.value;if(!e||!t)return;let n=!1;(0,a.fromEvent)(e,`pointerdown`).pipe((0,a.filter)(e=>e.button===0),(0,a.tap)(t=>{t.preventDefault(),t.stopPropagation(),e.setPointerCapture(t.pointerId)}),(0,a.map)(e=>{let r=t.getBoundingClientRect();return n=!1,{pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,offsetX:e.clientX-r.left,offsetY:e.clientY-r.top,rect:r}}),(0,a.switchMap)(({pointerId:e,startX:t,startY:r,offsetX:i,offsetY:o,rect:s})=>{let c=t=>t.pointerId===e,l=(0,a.fromEvent)(window,`pointermove`).pipe((0,a.filter)(c)),u=(0,a.merge)((0,a.fromEvent)(window,`pointerup`),(0,a.fromEvent)(window,`pointercancel`)).pipe((0,a.filter)(c));return l.pipe((0,a.tap)(({clientX:e,clientY:a})=>{let c=e-t,l=a-r;if(Math.sqrt(c*c+l*l)>5&&!n&&(n=!0,this.isDragging=!0),!n)return;let u=window.innerWidth,d=window.innerHeight,f=Math.max(0,Math.min(e-i,u-s.width)),p=Math.max(0,Math.min(a-o,d-s.height));this._position={x:this._currentCorner.includes(`right`)?u-f-s.width:f,y:this._currentCorner.includes(`bottom`)?d-p-s.height:p},this._applyContainerPosition()}),(0,a.takeUntil)(u),(0,a.finalize)(()=>{n?(this._reorientToNearestCorner(),this.isDragging=!1,n=!1):(this.isDragging=!1,n=!1,this.toggle())}))}),(0,a.takeUntil)(this.disconnecting)).subscribe()}_openOverlay(){if(this.#t)return;let e=this._containerRef.value,t=document.createElement(`div`);t.className=`flex flex-col`,this.#n=[...this._slotted],this.#n.forEach(e=>t.appendChild(e)),this.#t=i.o(t,{anchor:e??void 0,dismissable:!0,historyStrategy:`silent`}).pipe((0,a.finalize)(()=>this._restoreSlotted()),(0,a.takeUntil)(this.disconnecting)).subscribe(),this.dispatchScopedEvent(`toggle`,`open`)}_restoreSlotted(){this.#n.forEach(e=>this.appendChild(e)),this.#n=[],this.#t=void 0,this.open&&=!1,this.dispatchScopedEvent(`toggle`,`closed`)}connectedCallback(){super.connectedCallback(),(0,a.fromEvent)(window,`resize`).pipe((0,a.takeUntil)(this.disconnecting)).subscribe(()=>this._validateBounds()),r.n.bottomOffset$.pipe((0,a.tap)(()=>this._applyContainerPosition()),(0,a.takeUntil)(this.disconnecting)).subscribe()}firstUpdated(){this._currentCorner=this.corner,this._loadPosition(),this._containerRef.value&&(this._applyContainerPosition(),this._setupDrag(),this.#e=!0,this.open&&this._openOverlay())}willUpdate(e){this.#e&&e.has(`open`)&&(this.open&&!this.#t?this._openOverlay():!this.open&&this.#t&&this.#t.unsubscribe())}disconnectedCallback(){super.disconnectedCallback(),this._currentAnimation?.cancel(),this.#t?.unsubscribe()}toggle(){this.open=!this.open}render(){let e=(0,o.classMap)({"inline-flex":!0,"rounded-full":!0,"overflow-hidden":!0,"transition-opacity":!0,"duration-200":!0,"opacity-85":this.isDragging,"scale-95":this.isDragging}),t=(0,s.styleMap)({position:`fixed`,"pointer-events":`auto`}),n=(0,o.classMap)({"h-14":!0,"rounded-full":!0,flex:!0,"items-center":!0,"gap-3":!0,"select-none":!0,"touch-none":!0,"cursor-grabbing":this.isDragging,"cursor-pointer":!this.isDragging,"px-5":!!this.label,"w-14":!this.label,"justify-center":!this.label});return l.html`
|
|
9
|
-
<schmancy-surface
|
|
10
|
-
${(0,u.ref)(this._containerRef)}
|
|
11
|
-
type="glass"
|
|
12
|
-
.elevation=${this.lowered?1:3}
|
|
13
|
-
class=${e}
|
|
14
|
-
style=${t}
|
|
15
|
-
aria-expanded=${this.open}
|
|
16
|
-
>
|
|
17
|
-
<div
|
|
18
|
-
${(0,u.ref)(this._headerRef)}
|
|
19
|
-
class=${n}
|
|
20
|
-
role="button"
|
|
21
|
-
tabindex="0"
|
|
22
|
-
aria-label=${this.label??`Open panel`}
|
|
23
|
-
title="Drag to move · click to open"
|
|
24
|
-
>
|
|
25
|
-
<slot name="header">
|
|
26
|
-
${(0,d.when)(!!this.icon,()=>l.html`<schmancy-icon>${this.icon}</schmancy-icon>`,()=>l.nothing)}
|
|
27
|
-
</slot>
|
|
28
|
-
${(0,d.when)(!!this.label,()=>l.html`<schmancy-typography type="label" token="lg" class="whitespace-nowrap">
|
|
29
|
-
${this.label}
|
|
30
|
-
</schmancy-typography>`,()=>l.nothing)}
|
|
31
|
-
<slot name="summary"></slot>
|
|
32
|
-
</div>
|
|
33
|
-
|
|
34
|
-
<!-- Default-slot content parks here (hidden) while collapsed;
|
|
35
|
-
relocated into the show() overlay on open. -->
|
|
36
|
-
<div hidden><slot></slot></div>
|
|
37
|
-
</schmancy-surface>
|
|
38
|
-
`}};e.u([(0,c.property)({type:String})],p.prototype,`id`,void 0),e.u([(0,c.property)({type:String})],p.prototype,`icon`,void 0),e.u([(0,c.property)({type:String})],p.prototype,`label`,void 0),e.u([(0,c.property)({type:Boolean,reflect:!0})],p.prototype,`lowered`,void 0),e.u([(0,c.property)({type:String})],p.prototype,`corner`,void 0),e.u([(0,c.property)({type:Boolean,reflect:!0})],p.prototype,`open`,void 0),e.u([(0,c.state)()],p.prototype,`isDragging`,void 0),e.u([(0,c.state)()],p.prototype,`_currentCorner`,void 0),e.u([(0,c.queryAssignedElements)()],p.prototype,`_slotted`,void 0);var m=p=e.u([(0,c.customElement)(`schmancy-boat`)],p);Object.defineProperty(exports,`t`,{enumerable:!0,get:function(){return m}});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"boat-BgpWcLnV.cjs","names":["#sub","#captured","#ready"],"sources":["../src/boat/boat.ts"],"sourcesContent":["import { SchmancyElement } from '@mixins/index'\nimport { css, html, nothing, type PropertyValues } from 'lit'\nimport { customElement, property, queryAssignedElements, state } from 'lit/decorators.js'\nimport { classMap } from 'lit/directives/class-map.js'\nimport { createRef, ref } from 'lit/directives/ref.js'\nimport { styleMap } from 'lit/directives/style-map.js'\nimport { when } from 'lit/directives/when.js'\nimport { filter, finalize, fromEvent, map, merge, type Subscription, switchMap, takeUntil, tap } from 'rxjs'\nimport { SPRING_SMOOTH } from '../utils/animation.js'\nimport { reducedMotion$ } from '../directives/reduced-motion'\nimport { show } from '../overlay/overlay.service'\nimport { theme } from '../theme/theme.service.js'\n\nconst DRAG_THRESHOLD = 5\nconst POSITION_STORAGE_KEY_PREFIX = 'schmancy-boat-'\n\ntype Corner = 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left'\ninterface Position {\n\tx: number\n\ty: number\n}\n\n/**\n * Material-3 extended FAB that delegates its expanded panel to the `show()`\n * overlay service. Collapsed: a draggable, corner-anchored pill (icon + label,\n * circular when no label). Activated: the default-slot content blooms from the\n * FAB as an overlay (backdrop / Esc / back-button / sheet-on-narrow handled by\n * the overlay primitive).\n */\n@customElement('schmancy-boat')\nexport default class SchmancyBoat extends SchmancyElement {\n\tstatic styles = [css`\n\t\t:host {\n\t\t\tdisplay: contents;\n\t\t}\n\t\t:host([hidden]) {\n\t\t\tdisplay: none !important;\n\t\t}\n\t`]\n\n\t@property({ type: String }) id: string = 'default'\n\t@property({ type: String }) icon?: string\n\t@property({ type: String }) label?: string\n\t/** When true, uses a lower elevation shadow on the FAB. */\n\t@property({ type: Boolean, reflect: true }) lowered: boolean = false\n\t/** Corner the FAB is anchored to. */\n\t@property({ type: String }) corner: Corner = 'bottom-right'\n\t/** Open state. Bind `?open=${…}` to drive the overlay; reflected to the attribute. */\n\t@property({ type: Boolean, reflect: true }) open: boolean = false\n\n\t@state() private isDragging = false\n\t@state() private _currentCorner: Corner = 'bottom-right'\n\n\t@queryAssignedElements() private _slotted!: Element[]\n\n\tprivate _position: Position = { x: 16, y: 16 }\n\tprivate _containerRef = createRef<HTMLElement>()\n\tprivate _headerRef = createRef<HTMLElement>()\n\tprivate _currentAnimation?: Animation\n\n\t#ready = false\n\t#sub?: Subscription\n\t#captured: Element[] = []\n\n\t// ============================================\n\t// POSITION MANAGEMENT\n\t// ============================================\n\n\tprivate _applyContainerPosition() {\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\t\tcontainer.style.removeProperty('left')\n\t\tcontainer.style.removeProperty('right')\n\t\tcontainer.style.removeProperty('top')\n\t\tcontainer.style.removeProperty('bottom')\n\t\tconst { x, y } = this._position\n\t\tif (this._currentCorner.includes('right')) {\n\t\t\tcontainer.style.right = `${x}px`\n\t\t} else {\n\t\t\tcontainer.style.left = `${x}px`\n\t\t}\n\t\tif (this._currentCorner.includes('bottom')) {\n\t\t\tcontainer.style.bottom = `${y + theme.bottomOffset}px`\n\t\t} else {\n\t\t\tcontainer.style.top = `${y}px`\n\t\t}\n\t}\n\n\tprivate _loadPosition() {\n\t\ttry {\n\t\t\tconst saved = localStorage.getItem(POSITION_STORAGE_KEY_PREFIX + this.id)\n\t\t\tif (saved) {\n\t\t\t\tconst parsed = JSON.parse(saved) as { x: number; y: number; anchor: Corner }\n\t\t\t\tthis._position = { x: parsed.x, y: parsed.y }\n\t\t\t\tthis._currentCorner = parsed.anchor\n\t\t\t}\n\t\t} catch {\n\t\t\t// ignore localStorage errors\n\t\t}\n\t}\n\n\tprivate _savePosition() {\n\t\ttry {\n\t\t\tlocalStorage.setItem(\n\t\t\t\tPOSITION_STORAGE_KEY_PREFIX + this.id,\n\t\t\t\tJSON.stringify({ ...this._position, anchor: this._currentCorner }),\n\t\t\t)\n\t\t} catch {\n\t\t\t// ignore localStorage errors\n\t\t}\n\t}\n\n\tprivate _validateBounds() {\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\t\tconst rect = container.getBoundingClientRect()\n\t\tif (rect.width === 0) return\n\t\tconst vw = window.innerWidth\n\t\tconst vh = window.innerHeight\n\t\tconst isRight = this._currentCorner.includes('right')\n\t\tconst isBottom = this._currentCorner.includes('bottom')\n\t\tconst actualLeft = isRight ? vw - this._position.x - rect.width : this._position.x\n\t\tconst actualTop = isBottom ? vh - this._position.y - rect.height : this._position.y\n\t\tconst newLeft = Math.max(0, Math.min(actualLeft, vw - rect.width))\n\t\tconst newTop = Math.max(0, Math.min(actualTop, vh - rect.height))\n\t\tthis._position = {\n\t\t\tx: isRight ? vw - newLeft - rect.width : newLeft,\n\t\t\ty: isBottom ? vh - newTop - rect.height : newTop,\n\t\t}\n\t\tthis._applyContainerPosition()\n\t}\n\n\t// ============================================\n\t// CORNER SNAPPING (FLIP)\n\t// ============================================\n\n\tprivate _reorientToNearestCorner(): void {\n\t\tconst container = this._containerRef.value\n\t\tif (!container) return\n\n\t\tconst rect = container.getBoundingClientRect()\n\t\tconst fabCenterX = rect.left + rect.width / 2\n\t\tconst fabCenterY = rect.top + rect.height / 2\n\t\tconst side = fabCenterX > window.innerWidth / 2 ? 'right' : 'left'\n\t\tconst vert = fabCenterY > window.innerHeight / 2 ? 'bottom' : 'top'\n\t\tthis._currentCorner = `${vert}-${side}` as Corner\n\t\tthis._position = { x: 16, y: 16 }\n\t\tthis._applyContainerPosition()\n\n\t\tif (reducedMotion$.value) {\n\t\t\tthis._savePosition()\n\t\t\treturn\n\t\t}\n\n\t\tconst newRect = container.getBoundingClientRect()\n\t\tconst dx = rect.left - newRect.left\n\t\tconst dy = rect.top - newRect.top\n\t\tcontainer.style.transform = `translate(${dx}px, ${dy}px)`\n\n\t\tthis._currentAnimation?.cancel()\n\t\tconst anim = container.animate(\n\t\t\t[{ transform: container.style.transform }, { transform: 'translate(0,0)' }],\n\t\t\t{\n\t\t\t\tduration: SPRING_SMOOTH.duration,\n\t\t\t\teasing: SPRING_SMOOTH.easingFallback,\n\t\t\t\tfill: 'forwards',\n\t\t\t},\n\t\t)\n\t\tthis._currentAnimation = anim\n\t\tanim.finished.then(() => {\n\t\t\tif (container.isConnected) container.style.transform = ''\n\t\t\treturn\n\t\t})\n\n\t\tthis._savePosition()\n\t}\n\n\t// ============================================\n\t// DRAG PIPELINE\n\t// ============================================\n\n\tprivate _setupDrag() {\n\t\tconst header = this._headerRef.value\n\t\tconst container = this._containerRef.value\n\t\tif (!header || !container) return\n\n\t\tlet didDrag = false\n\n\t\tfromEvent<PointerEvent>(header, 'pointerdown')\n\t\t\t.pipe(\n\t\t\t\tfilter(e => e.button === 0),\n\t\t\t\ttap(e => {\n\t\t\t\t\te.preventDefault()\n\t\t\t\t\te.stopPropagation()\n\t\t\t\t\theader.setPointerCapture(e.pointerId)\n\t\t\t\t}),\n\t\t\t\tmap(e => {\n\t\t\t\t\tconst rect = container.getBoundingClientRect()\n\t\t\t\t\tdidDrag = false\n\t\t\t\t\treturn {\n\t\t\t\t\t\tpointerId: e.pointerId,\n\t\t\t\t\t\tstartX: e.clientX,\n\t\t\t\t\t\tstartY: e.clientY,\n\t\t\t\t\t\toffsetX: e.clientX - rect.left,\n\t\t\t\t\t\toffsetY: e.clientY - rect.top,\n\t\t\t\t\t\trect,\n\t\t\t\t\t}\n\t\t\t\t}),\n\t\t\t\tswitchMap(({ pointerId, startX, startY, offsetX, offsetY, rect }) => {\n\t\t\t\t\tconst sameId = (e: PointerEvent) => e.pointerId === pointerId\n\t\t\t\t\tconst move$ = fromEvent<PointerEvent>(window, 'pointermove').pipe(filter(sameId))\n\t\t\t\t\tconst end$ = merge(\n\t\t\t\t\t\tfromEvent<PointerEvent>(window, 'pointerup'),\n\t\t\t\t\t\tfromEvent<PointerEvent>(window, 'pointercancel'),\n\t\t\t\t\t).pipe(filter(sameId))\n\n\t\t\t\t\treturn move$.pipe(\n\t\t\t\t\t\ttap(({ clientX, clientY }) => {\n\t\t\t\t\t\t\tconst dx = clientX - startX\n\t\t\t\t\t\t\tconst dy = clientY - startY\n\t\t\t\t\t\t\tif (Math.sqrt(dx * dx + dy * dy) > DRAG_THRESHOLD && !didDrag) {\n\t\t\t\t\t\t\t\tdidDrag = true\n\t\t\t\t\t\t\t\tthis.isDragging = true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (!didDrag) return\n\n\t\t\t\t\t\t\tconst vw = window.innerWidth\n\t\t\t\t\t\t\tconst vh = window.innerHeight\n\t\t\t\t\t\t\tconst left = Math.max(0, Math.min(clientX - offsetX, vw - rect.width))\n\t\t\t\t\t\t\tconst top = Math.max(0, Math.min(clientY - offsetY, vh - rect.height))\n\t\t\t\t\t\t\tthis._position = {\n\t\t\t\t\t\t\t\tx: this._currentCorner.includes('right') ? vw - left - rect.width : left,\n\t\t\t\t\t\t\t\ty: this._currentCorner.includes('bottom') ? vh - top - rect.height : top,\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tthis._applyContainerPosition()\n\t\t\t\t\t\t}),\n\t\t\t\t\t\ttakeUntil(end$),\n\t\t\t\t\t\tfinalize(() => {\n\t\t\t\t\t\t\tif (didDrag) {\n\t\t\t\t\t\t\t\tthis._reorientToNearestCorner()\n\t\t\t\t\t\t\t\tthis.isDragging = false\n\t\t\t\t\t\t\t\tdidDrag = false\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.isDragging = false\n\t\t\t\t\t\t\t\tdidDrag = false\n\t\t\t\t\t\t\t\tthis.toggle()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}),\n\t\t\t\t\t)\n\t\t\t\t}),\n\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t)\n\t\t\t.subscribe()\n\t}\n\n\t// ============================================\n\t// OVERLAY DELEGATION\n\t// ============================================\n\n\tprivate _openOverlay() {\n\t\tif (this.#sub) return\n\t\tconst anchor = this._containerRef.value\n\t\tconst wrapper = document.createElement('div')\n\t\twrapper.className = 'flex flex-col'\n\t\tthis.#captured = [...this._slotted]\n\t\tthis.#captured.forEach(node => wrapper.appendChild(node))\n\n\t\tthis.#sub = show(wrapper, {\n\t\t\tanchor: anchor ?? undefined,\n\t\t\tdismissable: true,\n\t\t\thistoryStrategy: 'silent',\n\t\t})\n\t\t\t.pipe(\n\t\t\t\tfinalize(() => this._restoreSlotted()),\n\t\t\t\ttakeUntil(this.disconnecting),\n\t\t\t)\n\t\t\t.subscribe()\n\n\t\tthis.dispatchScopedEvent('toggle', 'open')\n\t}\n\n\tprivate _restoreSlotted() {\n\t\tthis.#captured.forEach(node => this.appendChild(node))\n\t\tthis.#captured = []\n\t\tthis.#sub = undefined\n\t\tif (this.open) this.open = false\n\t\tthis.dispatchScopedEvent('toggle', 'closed')\n\t}\n\n\t// ============================================\n\t// LIFECYCLE\n\t// ============================================\n\n\tconnectedCallback() {\n\t\tsuper.connectedCallback()\n\n\t\tfromEvent(window, 'resize')\n\t\t\t.pipe(takeUntil(this.disconnecting))\n\t\t\t.subscribe(() => this._validateBounds())\n\n\t\ttheme.bottomOffset$.pipe(\n\t\t\ttap(() => this._applyContainerPosition()),\n\t\t\ttakeUntil(this.disconnecting),\n\t\t).subscribe()\n\t}\n\n\tfirstUpdated() {\n\t\tthis._currentCorner = this.corner\n\t\tthis._loadPosition()\n\t\tif (!this._containerRef.value) return\n\t\tthis._applyContainerPosition()\n\t\tthis._setupDrag()\n\t\tthis.#ready = true\n\t\tif (this.open) this._openOverlay()\n\t}\n\n\tprotected willUpdate(changed: PropertyValues<this>) {\n\t\tif (!this.#ready || !changed.has('open')) return\n\t\tif (this.open && !this.#sub) this._openOverlay()\n\t\telse if (!this.open && this.#sub) this.#sub.unsubscribe()\n\t}\n\n\tdisconnectedCallback() {\n\t\tsuper.disconnectedCallback()\n\t\tthis._currentAnimation?.cancel()\n\t\tthis.#sub?.unsubscribe()\n\t}\n\n\t// ============================================\n\t// PUBLIC API\n\t// ============================================\n\n\t/** Flip open ↔ closed. */\n\ttoggle() {\n\t\tthis.open = !this.open\n\t}\n\n\t// ============================================\n\t// RENDER\n\t// ============================================\n\n\tprotected render(): unknown {\n\t\tconst containerClasses = classMap({\n\t\t\t'inline-flex': true,\n\t\t\t'rounded-full': true,\n\t\t\t'overflow-hidden': true,\n\t\t\t'transition-opacity': true,\n\t\t\t'duration-200': true,\n\t\t\t'opacity-85': this.isDragging,\n\t\t\t'scale-95': this.isDragging,\n\t\t})\n\n\t\tconst containerStyles = styleMap({\n\t\t\tposition: 'fixed',\n\t\t\t'pointer-events': 'auto',\n\t\t})\n\n\t\tconst fabClasses = classMap({\n\t\t\t'h-14': true,\n\t\t\t'rounded-full': true,\n\t\t\tflex: true,\n\t\t\t'items-center': true,\n\t\t\t'gap-3': true,\n\t\t\t'select-none': true,\n\t\t\t'touch-none': true,\n\t\t\t'cursor-grabbing': this.isDragging,\n\t\t\t'cursor-pointer': !this.isDragging,\n\t\t\t'px-5': !!this.label,\n\t\t\t'w-14': !this.label,\n\t\t\t'justify-center': !this.label,\n\t\t})\n\n\t\treturn html`\n\t\t\t<schmancy-surface\n\t\t\t\t${ref(this._containerRef)}\n\t\t\t\ttype=\"glass\"\n\t\t\t\t.elevation=${this.lowered ? 1 : 3}\n\t\t\t\tclass=${containerClasses}\n\t\t\t\tstyle=${containerStyles}\n\t\t\t\taria-expanded=${this.open}\n\t\t\t>\n\t\t\t\t<div\n\t\t\t\t\t${ref(this._headerRef)}\n\t\t\t\t\tclass=${fabClasses}\n\t\t\t\t\trole=\"button\"\n\t\t\t\t\ttabindex=\"0\"\n\t\t\t\t\taria-label=${this.label ?? 'Open panel'}\n\t\t\t\t\ttitle=\"Drag to move · click to open\"\n\t\t\t\t>\n\t\t\t\t\t<slot name=\"header\">\n\t\t\t\t\t\t${when(\n\t\t\t\t\t\t\t!!this.icon,\n\t\t\t\t\t\t\t() => html`<schmancy-icon>${this.icon}</schmancy-icon>`,\n\t\t\t\t\t\t\t() => nothing,\n\t\t\t\t\t\t)}\n\t\t\t\t\t</slot>\n\t\t\t\t\t${when(\n\t\t\t\t\t\t!!this.label,\n\t\t\t\t\t\t() => html`<schmancy-typography type=\"label\" token=\"lg\" class=\"whitespace-nowrap\">\n\t\t\t\t\t\t\t${this.label}\n\t\t\t\t\t\t</schmancy-typography>`,\n\t\t\t\t\t\t() => nothing,\n\t\t\t\t\t)}\n\t\t\t\t\t<slot name=\"summary\"></slot>\n\t\t\t\t</div>\n\n\t\t\t\t<!-- Default-slot content parks here (hidden) while collapsed;\n\t\t\t\t relocated into the show() overlay on open. -->\n\t\t\t\t<div hidden><slot></slot></div>\n\t\t\t</schmancy-surface>\n\t\t`\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'schmancy-boat': SchmancyBoat\n\t}\n}\n"],"mappings":"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"}
|