🎨
This commit is contained in:
		
							parent
							
								
									43fafc8d57
								
							
						
					
					
						commit
						d147181a82
					
				
					 5 changed files with 83 additions and 22 deletions
				
			
		|  | @ -131,7 +131,7 @@ export default defineComponent({ | ||||||
| 
 | 
 | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
| .container-toggle-enter-active, .container-toggle-leave-active { | .container-toggle-enter-active, .container-toggle-leave-active { | ||||||
| 	overflow-y: hidden; | 	overflow-y: clip; | ||||||
| 	transition: opacity 0.5s, height 0.5s !important; | 	transition: opacity 0.5s, height 0.5s !important; | ||||||
| } | } | ||||||
| .container-toggle-enter-from { | .container-toggle-enter-from { | ||||||
|  |  | ||||||
|  | @ -98,7 +98,7 @@ export default defineComponent({ | ||||||
| 
 | 
 | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
| .folder-toggle-enter-active, .folder-toggle-leave-active { | .folder-toggle-enter-active, .folder-toggle-leave-active { | ||||||
| 	overflow-y: hidden; | 	overflow-y: clip; | ||||||
| 	transition: opacity 0.5s, height 0.5s !important; | 	transition: opacity 0.5s, height 0.5s !important; | ||||||
| } | } | ||||||
| .folder-toggle-enter-from { | .folder-toggle-enter-from { | ||||||
|  |  | ||||||
|  | @ -1,5 +1,5 @@ | ||||||
| <template> | <template> | ||||||
| <div class="dwzlatin" :class="{ opened }"> | <div class="dwzlatin" :class="{ opened }" ref="root"> | ||||||
| 	<div class="header _button" @click="toggle"> | 	<div class="header _button" @click="toggle"> | ||||||
| 		<span class="icon"><slot name="icon"></slot></span> | 		<span class="icon"><slot name="icon"></slot></span> | ||||||
| 		<span class="text"><slot name="label"></slot></span> | 		<span class="text"><slot name="label"></slot></span> | ||||||
|  | @ -9,17 +9,29 @@ | ||||||
| 			<i v-else class="ti ti-chevron-down icon"></i> | 			<i v-else class="ti ti-chevron-down icon"></i> | ||||||
| 		</span> | 		</span> | ||||||
| 	</div> | 	</div> | ||||||
|  | 	<div v-if="openedAtLeastOnce" class="body"> | ||||||
|  | 		<Transition | ||||||
|  | 			:name="$store.state.animation ? 'folder-toggle' : ''" | ||||||
|  | 			@enter="enter" | ||||||
|  | 			@after-enter="afterEnter" | ||||||
|  | 			@leave="leave" | ||||||
|  | 			@after-leave="afterLeave" | ||||||
|  | 		> | ||||||
| 			<KeepAlive> | 			<KeepAlive> | ||||||
| 		<div v-if="openedAtLeastOnce" v-show="opened" class="body"> | 				<div v-show="opened"> | ||||||
| 			<MkSpacer :margin-min="14" :margin-max="22"> | 					<MkSpacer :margin-min="14" :margin-max="22" :container="root"> | ||||||
| 						<slot></slot> | 						<slot></slot> | ||||||
| 					</MkSpacer> | 					</MkSpacer> | ||||||
| 				</div> | 				</div> | ||||||
| 			</KeepAlive> | 			</KeepAlive> | ||||||
|  | 		</Transition> | ||||||
|  | 	</div> | ||||||
| </div> | </div> | ||||||
| </template> | </template> | ||||||
| 
 | 
 | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
|  | import { nextTick } from 'vue'; | ||||||
|  | 
 | ||||||
| const props = withDefaults(defineProps<{ | const props = withDefaults(defineProps<{ | ||||||
| 	defaultOpen: boolean; | 	defaultOpen: boolean; | ||||||
| }>(), { | }>(), { | ||||||
|  | @ -28,16 +40,50 @@ const props = withDefaults(defineProps<{ | ||||||
| 
 | 
 | ||||||
| let opened = $ref(props.defaultOpen); | let opened = $ref(props.defaultOpen); | ||||||
| let openedAtLeastOnce = $ref(props.defaultOpen); | let openedAtLeastOnce = $ref(props.defaultOpen); | ||||||
|  | let root = $ref<HTMLElement>(); | ||||||
| 
 | 
 | ||||||
| const toggle = () => { | function enter(el) { | ||||||
| 	opened = !opened; | 	const elementHeight = el.getBoundingClientRect().height; | ||||||
| 	if (opened) { | 	el.style.height = 0; | ||||||
|  | 	el.offsetHeight; // reflow | ||||||
|  | 	el.style.height = elementHeight + 'px'; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function afterEnter(el) { | ||||||
|  | 	el.style.height = null; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function leave(el) { | ||||||
|  | 	const elementHeight = el.getBoundingClientRect().height; | ||||||
|  | 	el.style.height = elementHeight + 'px'; | ||||||
|  | 	el.offsetHeight; // reflow | ||||||
|  | 	el.style.height = 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function afterLeave(el) { | ||||||
|  | 	el.style.height = null; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function toggle() { | ||||||
|  | 	if (!opened) { | ||||||
| 		openedAtLeastOnce = true; | 		openedAtLeastOnce = true; | ||||||
| 	} | 	} | ||||||
| }; | 
 | ||||||
|  | 	nextTick(() => { | ||||||
|  | 		opened = !opened; | ||||||
|  | 	}); | ||||||
|  | } | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
|  | .folder-toggle-enter-active, .folder-toggle-leave-active { | ||||||
|  | 	overflow-y: clip; | ||||||
|  | 	transition: opacity 0.3s, height 0.3s, transform 0.3s !important; | ||||||
|  | } | ||||||
|  | .folder-toggle-enter-from, .folder-toggle-leave-to { | ||||||
|  | 	opacity: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .dwzlatin { | .dwzlatin { | ||||||
| 	display: block; | 	display: block; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -59,16 +59,17 @@ const finalValue = computed(() => { | ||||||
| 	} | 	} | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const thumbWidth = computed(() => { | const getThumbWidth = () => { | ||||||
| 	if (thumbEl.value == null) return 0; | 	if (thumbEl.value == null) return 0; | ||||||
| 	return thumbEl.value!.offsetWidth; | 	return thumbEl.value!.offsetWidth; | ||||||
| }); | }; | ||||||
| const thumbPosition = ref(0); | const thumbPosition = ref(0); | ||||||
| const calcThumbPosition = () => { | const calcThumbPosition = () => { | ||||||
| 	if (containerEl.value == null) { | 	if (containerEl.value == null) { | ||||||
| 		thumbPosition.value = 0; | 		thumbPosition.value = 0; | ||||||
| 	} else { | 	} else { | ||||||
| 		thumbPosition.value = (containerEl.value.offsetWidth - thumbWidth.value) * steppedRawValue.value; | 		thumbPosition.value = (containerEl.value.offsetWidth - getThumbWidth()) * steppedRawValue.value; | ||||||
|  | 		console.log(containerEl.value.offsetWidth, getThumbWidth()); | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| watch([steppedRawValue, containerEl], calcThumbPosition); | watch([steppedRawValue, containerEl], calcThumbPosition); | ||||||
|  | @ -110,12 +111,14 @@ const onMousedown = (ev: MouseEvent | TouchEvent) => { | ||||||
| 	style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }')); | 	style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }')); | ||||||
| 	document.head.appendChild(style); | 	document.head.appendChild(style); | ||||||
| 
 | 
 | ||||||
|  | 	const thumbWidth = getThumbWidth(); | ||||||
|  | 
 | ||||||
| 	const onDrag = (ev: MouseEvent | TouchEvent) => { | 	const onDrag = (ev: MouseEvent | TouchEvent) => { | ||||||
| 		ev.preventDefault(); | 		ev.preventDefault(); | ||||||
| 		const containerRect = containerEl.value!.getBoundingClientRect(); | 		const containerRect = containerEl.value!.getBoundingClientRect(); | ||||||
| 		const pointerX = ev.touches && ev.touches.length > 0 ? ev.touches[0].clientX : ev.clientX; | 		const pointerX = ev.touches && ev.touches.length > 0 ? ev.touches[0].clientX : ev.clientX; | ||||||
| 		const pointerPositionOnContainer = pointerX - (containerRect.left + (thumbWidth.value / 2)); | 		const pointerPositionOnContainer = pointerX - (containerRect.left + (thumbWidth / 2)); | ||||||
| 		rawValue.value = Math.min(1, Math.max(0, pointerPositionOnContainer / (containerEl.value!.offsetWidth - thumbWidth.value))); | 		rawValue.value = Math.min(1, Math.max(0, pointerPositionOnContainer / (containerEl.value!.offsetWidth - thumbWidth))); | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	let beforeValue = finalValue.value; | 	let beforeValue = finalValue.value; | ||||||
|  |  | ||||||
|  | @ -14,6 +14,9 @@ const props = withDefaults(defineProps<{ | ||||||
| 	contentMax?: number | null; | 	contentMax?: number | null; | ||||||
| 	marginMin?: number; | 	marginMin?: number; | ||||||
| 	marginMax?: number; | 	marginMax?: number; | ||||||
|  | 
 | ||||||
|  | 	// MkFolderとかで開閉アニメーションの際にheightを正しく伝えるため | ||||||
|  | 	container?: HTMLElement, | ||||||
| }>(), { | }>(), { | ||||||
| 	contentMax: null, | 	contentMax: null, | ||||||
| 	marginMin: 12, | 	marginMin: 12, | ||||||
|  | @ -23,7 +26,7 @@ const props = withDefaults(defineProps<{ | ||||||
| let ro: ResizeObserver; | let ro: ResizeObserver; | ||||||
| let root = $ref<HTMLElement>(); | let root = $ref<HTMLElement>(); | ||||||
| let content = $ref<HTMLElement>(); | let content = $ref<HTMLElement>(); | ||||||
| let margin = $ref(0); | let margin = $ref(props.marginMin); | ||||||
| const widthHistory = [null, null] as [number | null, number | null]; | const widthHistory = [null, null] as [number | null, number | null]; | ||||||
| const heightHistory = [null, null] as [number | null, number | null]; | const heightHistory = [null, null] as [number | null, number | null]; | ||||||
| const shouldSpacerMin = inject('shouldSpacerMin', false); | const shouldSpacerMin = inject('shouldSpacerMin', false); | ||||||
|  | @ -41,6 +44,15 @@ const adjust = (rect: { width: number; height: number; }) => { | ||||||
| 	} | 	} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | if (props.container) { | ||||||
|  | 	const width = props.container.offsetWidth; | ||||||
|  | 	const height = props.container.offsetHeight; | ||||||
|  | 	adjust({ | ||||||
|  | 		width, | ||||||
|  | 		height, | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| onMounted(() => { | onMounted(() => { | ||||||
| 	ro = new ResizeObserver((entries) => { | 	ro = new ResizeObserver((entries) => { | ||||||
| 		/* iOSが対応していない | 		/* iOSが対応していない | ||||||
|  | @ -50,8 +62,8 @@ onMounted(() => { | ||||||
| 		}); | 		}); | ||||||
| 		*/ | 		*/ | ||||||
| 
 | 
 | ||||||
| 		const width = root!.offsetWidth; | 		const width = props.container ? props.container.offsetWidth : root!.offsetWidth; | ||||||
| 		const height = root!.offsetHeight; | 		const height = props.container ? props.container.offsetHeight : root!.offsetHeight; | ||||||
| 
 | 
 | ||||||
| 		//#region Prevent infinite resizing | 		//#region Prevent infinite resizing | ||||||
| 		// https://github.com/misskey-dev/misskey/issues/9076 | 		// https://github.com/misskey-dev/misskey/issues/9076 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue