2 changed files with 242 additions and 0 deletions
@ -0,0 +1,124 @@ |
|||
<template> |
|||
<div class="flex flex-nowrap py-2"> |
|||
<div ref="titleContainerRef" class="flex items-end text-subtitle2 text-no-wrap">{{ title }}</div> |
|||
<q-space /> |
|||
<div ref="actionContainerRef" class="flex flex-nowrap"> |
|||
<!-- baseActions --> |
|||
<template v-for="(action, index) in baseActions" :key="'baseAction_' + index"> |
|||
<q-separator |
|||
v-if="action.separator" |
|||
vertical |
|||
class="class-action-item" |
|||
:style="{ |
|||
'margin-left': '5px', |
|||
'margin-right': '5px', |
|||
}" |
|||
/> |
|||
<q-btn |
|||
v-else |
|||
v-bind="action" |
|||
:id="action.name" |
|||
:disable="action.enableIf ? !action.enableIf() : false" |
|||
no-wrap |
|||
class="class-action-item" |
|||
:style="{ |
|||
'margin-left': '5px', |
|||
'margin-right': '5px', |
|||
}" |
|||
@click="action.click" |
|||
/> |
|||
</template> |
|||
|
|||
<!-- moreActions --> |
|||
<q-btn-dropdown v-if="moreActions && moreActions.length > 0" :label="$t('more')" class="class-action-item" style="margin-left: 5px"> |
|||
<q-list> |
|||
<template v-for="(action, index) in moreActions" :key="'moreAction_' + index"> |
|||
<q-separator v-if="action.separator" /> |
|||
<q-item v-else v-close-popup clickable @click="action.click"> |
|||
<q-item-section avatar style="min-width: 28px; padding-right: 0px"> |
|||
<q-icon :name="action.icon" size="20px" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label :v-bind="action">{{ action.label }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</template> |
|||
</q-list> |
|||
</q-btn-dropdown> |
|||
</div> |
|||
<q-resize-observer @resize="onResize" /> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform/utils'; |
|||
|
|||
const props = defineProps({ |
|||
title: { type: String, default: '' }, |
|||
noActionIcon: { type: Boolean, default: false }, |
|||
actions: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
}); |
|||
|
|||
const titleContainerRef = ref(); |
|||
const actionContainerRef = ref(); |
|||
|
|||
const actions = props.actions; |
|||
if (actions && actions.length > 0 && props.noActionIcon) { |
|||
for (const action of actions) { |
|||
action.icon = undefined; |
|||
} |
|||
} |
|||
const baseActions = ref(actions); |
|||
const moreActions = ref([]); |
|||
const isActionWidthInitializedRef = ref(false); |
|||
const moreActionWidth = 100; |
|||
|
|||
const onResize = (size) => { |
|||
if (Tools.isUndefinedOrNull(titleContainerRef.value) || Tools.isUndefinedOrNull(actionContainerRef.value)) { |
|||
return; |
|||
} |
|||
|
|||
if (!isActionWidthInitializedRef.value) { |
|||
const nodes = actionContainerRef.value.getElementsByClassName('class-action-item'); |
|||
for (let i = 0; i < actions.length; i++) { |
|||
actions[i].width = nodes[i].clientWidth + 10; |
|||
} |
|||
isActionWidthInitializedRef.value = true; |
|||
} |
|||
|
|||
const _baseActions = []; |
|||
const _moreActions = []; |
|||
const length = actions.length; |
|||
let availableWidth = size.width - titleContainerRef.value.clientWidth; |
|||
let width = 0; |
|||
let index = 0; |
|||
|
|||
for (; index < length; index++) { |
|||
console.log(index, width + actions[index].width, availableWidth); |
|||
if (width + actions[index].width > availableWidth) { |
|||
availableWidth -= moreActionWidth; |
|||
while (width > availableWidth) { |
|||
index--; |
|||
width -= actions[index].width; |
|||
_baseActions.pop(); |
|||
} |
|||
break; |
|||
} else { |
|||
_baseActions.push(actions[index]); |
|||
width += actions[index].width; |
|||
} |
|||
} |
|||
|
|||
for (; index < length; index++) { |
|||
_moreActions.push(actions[index]); |
|||
} |
|||
|
|||
baseActions.value = _baseActions; |
|||
moreActions.value = _moreActions; |
|||
}; |
|||
</script> |
@ -0,0 +1,118 @@ |
|||
<template> |
|||
<div class="flex flex-nowrap py-2"> |
|||
<div ref="titleContainerRef" class="flex items-end text-subtitle2 text-no-wrap">{{ title }}</div> |
|||
<q-space /> |
|||
<div ref="actionContainerRef" class="flex flex-nowrap"> |
|||
<!-- baseActions --> |
|||
<template v-for="(action, index) in baseActions" :key="'baseAction_' + index"> |
|||
<q-separator |
|||
v-if="action.separator" |
|||
vertical |
|||
class="class-action-item" |
|||
:style="{ |
|||
'margin-left': '5px', |
|||
'margin-right': '5px', |
|||
}" |
|||
/> |
|||
<q-btn |
|||
v-else |
|||
v-bind="action" |
|||
:id="action.name" |
|||
:disable="action.enableIf ? !action.enableIf() : false" |
|||
no-wrap |
|||
class="class-action-item" |
|||
:style="{ |
|||
'margin-left': '5px', |
|||
'margin-right': '5px', |
|||
}" |
|||
@click="action.click" |
|||
/> |
|||
</template> |
|||
|
|||
<!-- moreActions --> |
|||
<q-btn-dropdown v-if="moreActions && moreActions.length > 0" :label="$t('more')" class="class-action-item" style="margin-left: 5px"> |
|||
<q-list> |
|||
<template v-for="(action, index) in moreActions" :key="'moreAction_' + index"> |
|||
<q-separator v-if="action.separator" /> |
|||
<q-item v-else v-close-popup clickable @click="action.click"> |
|||
<q-item-section avatar style="min-width: 28px; padding-right: 0px"> |
|||
<q-icon :name="action.icon" size="20px" /> |
|||
</q-item-section> |
|||
<q-item-section> |
|||
<q-item-label :v-bind="action">{{ action.label }}</q-item-label> |
|||
</q-item-section> |
|||
</q-item> |
|||
</template> |
|||
</q-list> |
|||
</q-btn-dropdown> |
|||
</div> |
|||
<q-resize-observer @resize="onResize" /> |
|||
</div> |
|||
</template> |
|||
<script setup lang="ts"> |
|||
import { ref } from 'vue'; |
|||
import { Tools } from '@/platform/utils'; |
|||
|
|||
const props = defineProps({ |
|||
title: { type: String, default: '' }, |
|||
actions: { |
|||
type: Array, |
|||
default: () => { |
|||
return []; |
|||
}, |
|||
}, |
|||
}); |
|||
|
|||
const titleContainerRef = ref(); |
|||
const actionContainerRef = ref(); |
|||
|
|||
const actions = props.actions; |
|||
const baseActions = ref(actions); |
|||
const moreActions = ref([]); |
|||
const isActionWidthInitializedRef = ref(false); |
|||
const moreActionWidth = 100; |
|||
|
|||
const onResize = (size) => { |
|||
if (Tools.isUndefinedOrNull(titleContainerRef.value) || Tools.isUndefinedOrNull(actionContainerRef.value)) { |
|||
return; |
|||
} |
|||
|
|||
if (!isActionWidthInitializedRef.value) { |
|||
const nodes = actionContainerRef.value.getElementsByClassName('class-action-item'); |
|||
for (let i = 0; i < actions.length; i++) { |
|||
actions[i].width = nodes[i].clientWidth + 10; |
|||
} |
|||
isActionWidthInitializedRef.value = true; |
|||
} |
|||
|
|||
const _baseActions = []; |
|||
const _moreActions = []; |
|||
const length = actions.length; |
|||
let availableWidth = size.width - titleContainerRef.value.clientWidth; |
|||
let width = 0; |
|||
let index = 0; |
|||
|
|||
for (; index < length; index++) { |
|||
console.log(index, width + actions[index].width, availableWidth); |
|||
if (width + actions[index].width > availableWidth) { |
|||
availableWidth -= moreActionWidth; |
|||
while (width > availableWidth) { |
|||
index--; |
|||
width -= actions[index].width; |
|||
_baseActions.pop(); |
|||
} |
|||
break; |
|||
} else { |
|||
_baseActions.push(actions[index]); |
|||
width += actions[index].width; |
|||
} |
|||
} |
|||
|
|||
for (; index < length; index++) { |
|||
_moreActions.push(actions[index]); |
|||
} |
|||
|
|||
baseActions.value = _baseActions; |
|||
moreActions.value = _moreActions; |
|||
}; |
|||
</script> |
Loading…
Reference in new issue