@cpany/app
Advanced tools
Comparing version 0.0.10 to 0.0.11
{ | ||
"name": "@cpany/app", | ||
"version": "0.0.10", | ||
"version": "0.0.11", | ||
"description": "CPany web app", | ||
@@ -12,3 +12,3 @@ "repository": { | ||
"dependencies": { | ||
"@cpany/types": "0.0.10", | ||
"@cpany/types": "0.0.11", | ||
"vue": "^3.1.4", | ||
@@ -15,0 +15,0 @@ "vue-router": "4" |
@@ -14,2 +14,7 @@ import { defineComponent, toRefs, h } from 'vue'; | ||
default: false | ||
}, | ||
sort: Function, | ||
mobileHeaderClass: { | ||
type: Array, | ||
default: [] | ||
} | ||
@@ -19,10 +24,5 @@ }, | ||
const { align, center } = toRefs(props); | ||
const style = { | ||
borderWidth: '0 0 1px 0' | ||
}; | ||
const className = [ | ||
'px-3', | ||
'py-2', | ||
'border-solid', | ||
'border-[#dbdbdb]', | ||
align.value === 'center' || center.value | ||
@@ -38,3 +38,2 @@ ? 'text-center' | ||
{ | ||
style, | ||
class: className | ||
@@ -41,0 +40,0 @@ }, |
@@ -1,6 +0,37 @@ | ||
import { defineComponent, h, toRefs, VNode } from 'vue'; | ||
import { | ||
defineComponent, | ||
h, | ||
ref, | ||
Ref, | ||
unref, | ||
computed, | ||
toRefs, | ||
VNode, | ||
resolveComponent, | ||
onUnmounted | ||
} from 'vue'; | ||
import IconDown from 'virtual:vite-icons/mdi/arrow-down'; | ||
import IconUp from 'virtual:vite-icons/mdi/arrow-up'; | ||
import CTableColumn from './c-table-column'; | ||
import { isDef } from '@/utils'; | ||
export function useIsMobile(mobileWidth: Ref<number> | number) { | ||
const width = ref(window.innerWidth); | ||
const isMobile = ref(width.value <= unref(mobileWidth)); | ||
const handler = () => { | ||
width.value = window.innerWidth; | ||
isMobile.value = width.value <= unref(mobileWidth); | ||
}; | ||
const clean = () => window.removeEventListener('resize', handler); | ||
window.addEventListener('resize', handler, { passive: true }); | ||
return { width, isMobile, clean }; | ||
} | ||
export default defineComponent({ | ||
name: 'CTable', | ||
components: { | ||
IconDown, | ||
IconUp | ||
}, | ||
props: { | ||
@@ -10,15 +41,65 @@ data: { | ||
default: [] | ||
}, | ||
mobile: { | ||
type: Number, | ||
default: 768 | ||
}, | ||
defaultSort: { | ||
type: String | ||
}, | ||
defaultSortOrder: { | ||
type: String, | ||
default: 'asc' | ||
} | ||
}, | ||
setup(props, { slots }) { | ||
const { data } = toRefs(props); | ||
const { data, defaultSort, defaultSortOrder, mobile } = toRefs(props); | ||
const { isMobile, clean } = useIsMobile(mobile); | ||
onUnmounted(() => clean()); | ||
const sortField = ref(defaultSort.value); | ||
const sortOrder = ref<'asc' | 'desc'>( | ||
defaultSortOrder.value as 'asc' | 'desc' | ||
); | ||
const setSortField = (label: string) => { | ||
sortField.value = label; | ||
sortOrder.value = defaultSort.value as 'asc' | 'desc'; | ||
}; | ||
const filpSortOrder = () => { | ||
if (sortOrder.value === 'desc') sortOrder.value = 'asc'; | ||
else sortOrder.value = 'desc'; | ||
}; | ||
const filterColumn = (slots?: VNode[]) => | ||
slots ? slots.filter((slot) => slot.type === CTableColumn) : []; | ||
return () => { | ||
const columns = filterColumn(slots.columns ? slots.columns({}) : []); | ||
const columns = filterColumn(slots.columns ? slots.columns({}) : []); | ||
const sortedData = computed(() => { | ||
const sorted = (data: any[]) => { | ||
if (isDef(sortField.value)) { | ||
for (const slot of columns) { | ||
const label = slot.props?.label ?? ''; | ||
if (label === sortField.value) { | ||
const arr = data.sort(slot.props?.sort); | ||
return sortOrder.value === 'desc' ? arr.reverse() : arr; | ||
} | ||
} | ||
return data; | ||
} else { | ||
return data; | ||
} | ||
}; | ||
return sorted(data.value); | ||
}); | ||
const renderDestop = () => { | ||
const renderHead = () => | ||
columns.map((column) => { | ||
const hasSort = isDef(column.props?.sort); | ||
const isActiveSort = | ||
hasSort && (column.props?.label ?? '') === sortField.value; | ||
const style = { | ||
@@ -28,3 +109,13 @@ width: column.props?.width, | ||
}; | ||
const align = | ||
column.props?.align === 'center' || | ||
(isDef(column.props?.center) && column.props?.center !== false) | ||
? 'justify-center' | ||
: column.props?.align === 'right' | ||
? 'justify-end' | ||
: 'justify-start'; | ||
const className = [ | ||
'select-none', | ||
'font-600', | ||
@@ -34,15 +125,38 @@ 'px-3', | ||
'border-solid', | ||
'border-[#dbdbdb]', | ||
column.props?.align === 'center' || | ||
column.props?.center === '' || | ||
column.props?.center === true | ||
? 'text-center' | ||
: column.props?.align === 'right' | ||
? 'text-right' | ||
: 'text-left' | ||
!isActiveSort ? 'border-[#dbdbdb]' : 'border-[#7a7a7a]', | ||
hasSort ? 'cursor-pointer' : null, | ||
hasSort ? 'hover:border-[#7a7a7a]' : null | ||
]; | ||
return h( | ||
'th', | ||
{ style, class: className }, | ||
h('div', {}, column.props?.label) | ||
h( | ||
'div', | ||
{ | ||
class: ['flex', 'items-center', align], | ||
onClick: hasSort | ||
? () => { | ||
if (isActiveSort) { | ||
filpSortOrder(); | ||
} else { | ||
setSortField(column.props?.label ?? ''); | ||
} | ||
} | ||
: undefined | ||
}, | ||
[ | ||
hasSort | ||
? h( | ||
sortOrder.value === 'desc' | ||
? resolveComponent('icon-down') | ||
: resolveComponent('icon-up'), | ||
{ | ||
class: [!isActiveSort && 'text-transparent'] | ||
} | ||
) | ||
: '', | ||
h('span', {}, column.props?.label) | ||
] | ||
) | ||
); | ||
@@ -67,3 +181,3 @@ }); | ||
h('thead', {}, h('tr', {}, renderHead())), | ||
h('tbody', {}, renderBody(data.value)), | ||
h('tbody', {}, renderBody(sortedData.value)), | ||
h('tfoot', {}, []) | ||
@@ -73,3 +187,48 @@ ] | ||
}; | ||
const renderMobile = () => { | ||
const renderBody = () => { | ||
return sortedData.value.map((row, index) => { | ||
const columns = filterColumn( | ||
slots.columns && slots.columns({ row, index, mobile: true }) | ||
); | ||
return h( | ||
'div', | ||
{ class: ['box', 'p-0', 'mb-4'] }, | ||
columns.map((column) => { | ||
const customHeader = | ||
(column.props && column.props['mobile-header-class']) ?? []; | ||
return h( | ||
'div', | ||
{ | ||
class: [ | ||
'pl-3', | ||
'border', | ||
'flex', | ||
'flex-shrink', | ||
'justify-between', | ||
'justify-items-stretch' | ||
] | ||
}, | ||
[ | ||
h( | ||
'div', | ||
{ | ||
class: ['py-2', 'font-600', 'text-left', ...customHeader] | ||
}, | ||
column.props?.label | ||
), | ||
h(column, { class: ['block'] }) | ||
] | ||
); | ||
}) | ||
); | ||
}); | ||
}; | ||
return h('div', { class: ['mobile-table'] }, renderBody()); | ||
}; | ||
return () => (!isMobile.value ? renderDestop() : renderMobile()); | ||
} | ||
}); |
import { Ref, ref, unref } from 'vue'; | ||
export function isUndef<T>( | ||
object: T | undefined | null | ||
): object is undefined | null { | ||
return object === undefined || object === null; | ||
} | ||
export function isDef<T>(object: T | undefined | null): object is T { | ||
return object !== undefined && object !== null; | ||
} | ||
function alignNumber(value: number) { | ||
@@ -4,0 +14,0 @@ return (value < 10 ? '0' : '') + value; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
289394
1019
56
1
+ Added@cpany/types@0.0.11(transitive)
- Removed@cpany/types@0.0.10(transitive)
Updated@cpany/types@0.0.11