From 47eec677772053ad21055ae71b06d96bd26a9422 Mon Sep 17 00:00:00 2001 From: Dirk Holtwick Date: Thu, 4 Jul 2024 16:19:07 +0200 Subject: [PATCH 1/3] feat: oui-log --- lib/basic/index.ts | 4 +- lib/basic/log.ts | 22 +++++ lib/basic/oui-log.demo.vue | 25 ++++++ lib/basic/oui-log.styl | 14 ++++ lib/basic/oui-log.vue | 149 +++++++++++++++++++++++++++++++++ lib/basic/oui-virtual-list.vue | 33 +++++--- 6 files changed, 235 insertions(+), 12 deletions(-) create mode 100644 lib/basic/log.ts create mode 100644 lib/basic/oui-log.demo.vue create mode 100644 lib/basic/oui-log.styl create mode 100644 lib/basic/oui-log.vue diff --git a/lib/basic/index.ts b/lib/basic/index.ts index 77fee42..b8e7599 100644 --- a/lib/basic/index.ts +++ b/lib/basic/index.ts @@ -1,6 +1,7 @@ export * from './_types' export * from './directives' export * from './formatters' +export * from './log' export { default as OuiButton } from './oui-button.vue' export { default as OuiCard } from './oui-card.vue' @@ -15,6 +16,7 @@ export { default as OuiFormItem } from './oui-form-item.vue' export { default as OuiInput } from './oui-input.vue' export { default as OuiInputGroup } from './oui-input-group.vue' export { default as OuiInputNumber } from './oui-input-number.vue' +export { default as OuiLog } from './oui-log.vue' export { default as OuiNotice } from './oui-notice.vue' export { default as OuiPassword } from './oui-password.vue' export { default as OuiPasswordMeter } from './oui-password-meter.vue' @@ -22,9 +24,9 @@ export { default as OuiResizeable } from './oui-resizeable.vue' export { default as OuiSelect } from './oui-select.vue' export { default as OuiSeparator } from './oui-separator.vue' export { default as OuiStars } from './oui-stars.vue' -export { default as OuiTabs } from './oui-tabs.vue' export { default as OuiTable } from './oui-table.vue' export { default as OuiTableview } from './oui-tableview.vue' +export { default as OuiTabs } from './oui-tabs.vue' export { default as OuiText } from './oui-text.vue' export { default as OuiTextarea } from './oui-textarea.vue' export { default as OuiVirtualList } from './oui-virtual-list.vue' diff --git a/lib/basic/log.ts b/lib/basic/log.ts new file mode 100644 index 0000000..0426b36 --- /dev/null +++ b/lib/basic/log.ts @@ -0,0 +1,22 @@ +import { reactive } from 'vue' +import type { LogMessage, LoggerInterface } from 'zeed' +import { LogLevelAll, LoggerContext, LoggerMemoryHandler } from 'zeed' + +export type LogOui = LoggerInterface & { + messages: LogMessage[] +} + +export function useLog(name: string): LogOui { + const messages: LogMessage[] = reactive([]) + const logger = LoggerContext() + logger.setHandlers([ + LoggerMemoryHandler({ + level: LogLevelAll, + filter: '*', + messages, + }), + ]) + const log = logger(name) as any + log.messages = messages + return log +} diff --git a/lib/basic/oui-log.demo.vue b/lib/basic/oui-log.demo.vue new file mode 100644 index 0000000..857cedd --- /dev/null +++ b/lib/basic/oui-log.demo.vue @@ -0,0 +1,25 @@ + + + diff --git a/lib/basic/oui-log.styl b/lib/basic/oui-log.styl new file mode 100644 index 0000000..96ab5c7 --- /dev/null +++ b/lib/basic/oui-log.styl @@ -0,0 +1,14 @@ +@require "../../stylus/index.styl"; + +.oui-log { + border: 1px solid var(--s2-fg); + border-radius: 4; + font-family: "Jetbrains Mono", monospace; + font-size: 12; + line-height: 1.2; + height: 200; + + ._active { + background: var(--p1-200) !important; + } +} \ No newline at end of file diff --git a/lib/basic/oui-log.vue b/lib/basic/oui-log.vue new file mode 100644 index 0000000..210fc67 --- /dev/null +++ b/lib/basic/oui-log.vue @@ -0,0 +1,149 @@ + + + diff --git a/lib/basic/oui-virtual-list.vue b/lib/basic/oui-virtual-list.vue index e5db1a0..c9445de 100644 --- a/lib/basic/oui-virtual-list.vue +++ b/lib/basic/oui-virtual-list.vue @@ -35,6 +35,7 @@ const paddingTop = ref(margin) let containerSize = 0 let isScrollBusy = false let lastScrollX = 0 +let didUserScroll = false function handleScroll() { if (!root.value) @@ -69,19 +70,14 @@ function handleScroll() { paddingTop.value = range[0] * rowHeight.value + margin emit('scrollX', root.value.scrollLeft) + + // Scroll to end + if (props.scrollToEnd && !isScrollBusy && !didUserScroll) { + root.value.scrollTop = scrollHeight.value + } }) } -watch(data, (cData) => { - scrollHeight.value = cData.length * rowHeight.value -}) - -watch(rowHeight, (cRowHeight) => { - scrollHeight.value = data.value.length * cRowHeight -}) - -watch(() => data.value.length, handleScroll) - // useOnBus('listScrollTop', () => { // if (root.value) // root.value.scrollTop = 0 @@ -99,6 +95,21 @@ function scrollToEnd() { watch(() => props.scrollToEnd, scrollToEnd) +watch(() => data.value.length, (l) => { + scrollHeight.value = l * rowHeight.value + handleScroll() +}) + +watch(rowHeight, (cRowHeight) => { + scrollHeight.value = data.value.length * cRowHeight +}) + +function handleUserScroll() { + const bottomScroll = root.value ? root.value.scrollTop + root.value.clientHeight + 1 : 0 + handleScroll() + didUserScroll = scrollHeight.value > bottomScroll +} + onMounted(() => { if (!root.value) return @@ -113,7 +124,7 @@ onMounted(() => {