Skip to content

Commit

Permalink
Merge pull request #288 from qor5/feat-ui-reborn
Browse files Browse the repository at this point in the history
style: style adjusting of gap
  • Loading branch information
danni-cool authored Sep 20, 2024
2 parents da883a8 + f158b41 commit 1da33ad
Show file tree
Hide file tree
Showing 13 changed files with 980 additions and 240 deletions.
2 changes: 1 addition & 1 deletion ui/vuetifyx/vuetifyxjs/dist/assets/vuetifyx.min.css

Large diffs are not rendered by default.

68 changes: 34 additions & 34 deletions ui/vuetifyx/vuetifyxjs/dist/vuetifyx.min.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@
border-collapse: collapse;
margin: 20px 0;
overflow-x: auto;
word-break: unset;
}

.vp-doc tr {
Expand Down
345 changes: 338 additions & 7 deletions ui/vuetifyx/vuetifyxjs/docs/Components/VXDialog/index.md

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions ui/vuetifyx/vuetifyxjs/docs/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,14 @@ export default {
text: 'TiptapEditor 富文本编辑器',
link: '/Components/TiptapEditor/'
},
{
text: 'SendVariables 组件',
link: '/Components/VXField/sendVariables'
},
{
text: 'DatePicker 时间选择器',
link: '/Components/DatePicker/'
}
]
},
{
text: '数据展示',
text: '数据和展示',
items: [
{
text: 'Label 标签',
Expand All @@ -44,6 +40,10 @@ export default {
{
text: 'Toolbar 提示条',
link: '/Components/VXToolbar/'
},
{
text: 'Filter 筛选组件',
link: '/Components/Filter/'
}
]
},
Expand All @@ -56,7 +56,7 @@ export default {
},
{
text: 'Dialog 弹窗',
link: '/components/VXDialog/'
link: '/Components/VXDialog/'
}
]
},
Expand All @@ -66,6 +66,10 @@ export default {
{
text: 'ScrollIframe 组件',
link: '/Components/ScrollIframe/'
},
{
text: 'SendVariables 组件',
link: '/Components/VXField/sendVariables'
}
]
}
Expand Down
2 changes: 1 addition & 1 deletion ui/vuetifyx/vuetifyxjs/scripts/new-demo-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const __dirname = path.dirname(__filename);

const rootDir = path.resolve(__dirname, '../');
const docsDir = path.join(rootDir, 'docs');
const componentsDir = path.join(docsDir, 'components');
const componentsDir = path.join(docsDir, 'Components')
const sidebarFile = path.join(docsDir, 'sidebar.ts');

// Read and parse the sidebar.ts file
Expand Down
233 changes: 226 additions & 7 deletions ui/vuetifyx/vuetifyxjs/src/lib/Common/VXDialog.vue
Original file line number Diff line number Diff line change
@@ -1,32 +1,251 @@
<template>
<div class="vx-dialog-wrap">
<v-dialog :model-value="dialogVisible" v-bind="filteredAttrs"></v-dialog>
<v-dialog
scrollable
width="auto"
:model-value="dialogVisible"
v-bind="filteredAttrs"
:persistent="persistent"
@update:model-value="onUpdateModelValue"
>
<template v-slot:activator="{ isActive, props: activatorProps }">
<slot name="activator" :props="{ isActive, activatorProps }" />
</template>

<template v-slot:default="{ isActive }">
<v-card :title="title">
<template v-slot:prepend v-if="prependIcon.icon">
<v-icon :color="prependIcon.color" size="small" :icon="prependIcon.icon" />
</template>

<template v-slot:append v-if="!hideClose">
<v-icon color="#757575" size="small" icon="mdi-close" @click="onClose(isActive)" />
</template>

<v-card-text :style="[contentWidth, contentMaxWidth, contentHeightStyle]">
<slot
:isActive="isActive"
><span class="dialog-content-text">{{ text }}</span></slot
>
</v-card-text>
<v-card-actions :class="props.size" v-if="!hideCancel || !hideOk">
<slot :isActive="isActive" name="action-btn">
<v-btn
v-if="!hideCancel"
color="grey-darken-3"
:size="props.size === 'default' ? 'small' : 'default'"
variant="tonal"
@click="onCancel(isActive)"
>{{ cancelText }}</v-btn
>
<v-btn
v-if="!hideOk"
color="primary"
:size="props.size === 'default' ? 'small' : 'default'"
:loading="isOkBtnLoading"
variant="flat"
@click="onOk(isActive)"
>{{ okText }}</v-btn
>
</slot>
</v-card-actions>
</v-card>
</template>
</v-dialog>
</div>
</template>

<script setup lang="ts">
import { defineEmits, ref, watch } from 'vue'
import {
defineEmits,
ref,
watch,
defineProps,
computed,
PropType,
Ref,
getCurrentInstance
} from 'vue'
import { useFilteredAttrs } from '@/lib/composables/useFilteredAttrs'
import { useHasEventListener } from '@/lib/composables/useEventListener'
const { filteredAttrs } = useFilteredAttrs()
const emit = defineEmits(['update:modelValue'])
const { hasEventListener } = useHasEventListener()
const emit = defineEmits(['update:modelValue', 'click:ok', 'click:cancel', 'click:close'])
const props = defineProps({
modelValue: Boolean
modelValue: Boolean,
type: {
type: String as PropType<'default' | 'warn' | 'error' | 'info'>,
default: 'default'
},
size: {
type: String,
default: 'default'
},
text: String,
hideOk: {
type: Boolean,
default: false
},
hideCancel: {
type: Boolean,
default: false
},
hideClose: {
type: Boolean,
default: false
},
okText: {
type: String,
default: 'OK'
},
cancelText: {
type: String,
default: 'Cancel'
},
persistent: Boolean,
contentHeight: {
type: [Number, String],
default: 'auto'
},
width: {
type: [Number, String],
default: ''
},
maxWidth: {
type: [Number, String],
default: 665
},
title: String
})
const dialogVisible = ref(props.modelValue)
watch(
() => props.modelValue,
(newValue) => {
dialogVisible.value = newValue
}
)
const isOkBtnLoading = ref(false)
const dialogVisible = ref(props.modelValue)
const contentMaxWidth = computed(() => {
return `max-width:${Math.max(+props.width, +props.maxWidth)}px`
})
const contentWidth = computed(() => {
let contentWidthStyle
if (props.size === 'default' && props.width === '') {
contentWidthStyle = 'width:461px'
} else {
contentWidthStyle = `width:${props.width}px`
}
return contentWidthStyle
})
const contentHeightStyle = computed(() => `height:${props.contentHeight}px`)
const prependIcon = computed(() => {
const vCardTitleIconMap = {
default: {
icon: '',
color: ''
},
info: {
color: 'primary',
icon: 'mdi-alert-circle'
},
warn: {
color: 'warning',
icon: 'mdi-alert-circle'
},
success: {
color: 'success',
icon: 'mdi-check-circle'
},
error: {
color: 'error',
icon: 'mdi-alert-circle'
}
}
return vCardTitleIconMap[props.type]
})
function onUpdateModelValue(value: any) {
emit('update:modelValue', value)
dialogVisible.value = value
}
const instance = getCurrentInstance()
// const hasEventListener = (event: Parameters<typeof emit>[0]) => {
// // Convert event name to the format used in vnode.props (e.g., 'click:ok' becomes 'onClick:ok')
// const eventName = 'on' + event.charAt(0).toUpperCase() + event.slice(1);
// debugger
// return !!instance?.vnode.props?.[eventName]
// }
function onOk(isActive: Ref<boolean>) {
if (hasEventListener('click:ok')) {
emit('click:ok', { isActive, isLoading: isOkBtnLoading })
} else {
isActive.value = false
}
}
function onCancel(isActive: Ref<boolean>) {
if (hasEventListener('click:cancel')) {
emit('click:cancel', { isActive })
} else {
isActive.value = false
}
}
function onClose(isActive: Ref<boolean>) {
if (hasEventListener('click-close')) {
emit('click:close', isActive)
} else {
isActive.value = false
}
}
</script>

<style lang="sass" scoped></style>
<style lang="scss" scoped>
.dialog-content-text {
font-size: 14px;
font-weight: 400;
line-height: 20px;
color: rgb(var(--v-theme-grey-darken-2));
}
.v-card-text {
padding-bottom: 12px !important;
}
.v-card-actions {
padding: 12px 24px 24px;
&.default {
.v-btn.v-btn--size-small {
min-width: initial;
padding: 0 12px;
font-size: 12px;
font-weight: 400;
&:deep(.v-btn__content) {
letter-spacing: 0.04px;
}
}
}
.v-btn.v-btn--size-default {
min-width: initial;
padding: 0 16px;
font-weight: 500;
&:deep(.v-btn__content) {
letter-spacing: 0.25px;
}
}
.v-btn ~ .v-btn:not(.v-btn-toggle .v-btn) {
margin-inline-start: 10px;
}
}
</style>
8 changes: 7 additions & 1 deletion ui/vuetifyx/vuetifyxjs/src/lib/Common/VXLabel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</template>

<v-tooltip v-if="tooltip">
<pre>{{ tooltip }}</pre>
<pre class="tooltip-display">{{ tooltip }}</pre>
<template v-slot:activator="{ props }">
<v-icon
:icon="icon"
Expand Down Expand Up @@ -102,4 +102,10 @@ const onClickToggleLabel = () => {
font-size: 16px;
}
}
.tooltip-display {
max-width: 50vw;
white-space: pre-wrap;
word-break: break-all;
}
</style>
39 changes: 39 additions & 0 deletions ui/vuetifyx/vuetifyxjs/src/lib/composables/useEventListener.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { getCurrentInstance } from 'vue'

// return a utils function: hasEventListener
// this function is used to check if some event callback is applied to some components
/**
* hasEventListener('click:ok'); // Should log 'onClick:ok'
* hasEventListener('click-ok'); // Should log 'onClickOk'
* hasEventListener('my-custom:event'); // Should log 'onMyCustom:event'
* hasEventListener('multiple-parts-to-test'); // Should log 'onMultiplePartsToTest'
*/
export function useHasEventListener() {
const instance = getCurrentInstance()

const hasEventListener = (event: string): boolean => {
// Match the separator '-' or ':'
const separator = event.match(/[-:]/)?.[0]

// Split the event name by '-' or ':'
const parts = event.split(/[-:]/)

let eventName = ''

if (separator === '-') {
// Capitalize each part and join without a separator for '-'
const capitalizedParts = parts.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
eventName = 'on' + capitalizedParts.join('')
} else if (separator === ':') {
// Capitalize the first part and keep the second part as is for ':'
eventName = 'on' + parts[0].charAt(0).toUpperCase() + parts[0].slice(1) + ':' + parts[1]
}

// console.log(eventName) // For testing purpose

// Check if the event listener exists in vnode.props (assumed instance)
return !!instance?.vnode.props?.[eventName]
}

return { hasEventListener }
}
Loading

0 comments on commit 1da33ad

Please sign in to comment.