|
46 | 46 | </div> |
47 | 47 | </template> |
48 | 48 |
|
49 | | - <script lang="ts" setup> |
50 | | - import { h, ref, useTemplateRef, type HTMLAttributes } from 'vue'; |
51 | | - import styles from '@patternfly/react-styles/css/components/Label/label-group'; |
52 | | - import labelStyles from '@patternfly/react-styles/css/components/Label/label'; |
53 | | - import CircleXmarkIcon from '@vue-patternfly/icons/circle-xmark-icon'; |
54 | | - import PfLabel from './Label.vue'; |
55 | | - import PfButton from '../Button.vue'; |
56 | | - import PfTooltip from '../Tooltip/Tooltip.vue'; |
57 | | - import { findChildrenVNodes, fillTemplate } from '../../util'; |
58 | | - import { useElementOverflow } from '../../use'; |
59 | | - import { useOUIAProps, type OUIAProps } from '../../helpers/ouia'; |
60 | | - import type { Placement } from '../../helpers/FloatingUi.vue'; |
61 | | -
|
62 | | - defineOptions({ |
63 | | - name: 'PfLabelGroup', |
64 | | - }); |
65 | | -
|
66 | | - interface Props extends OUIAProps, /* @vue-ignore */ Omit<HTMLAttributes, 'onClick'> { |
67 | | - id?: string; |
68 | | - /** Flag for having the label group default to expanded */ |
69 | | - defaultOpen?: boolean; |
70 | | - /** Flag if label group can be closed */ |
71 | | - closable?: boolean; |
72 | | - /** Flag indicating the labels in the group are compact */ |
73 | | - compact?: boolean; |
74 | | - /** Flag to implement a vertical layout */ |
75 | | - vertical?: boolean; |
76 | | - /** Flag indicating contained labels are editable. Allows spacing for a text input after the labels. */ |
77 | | - editable?: boolean; |
78 | | - /** Flag indicating the editable label group should be appended with a textarea. */ |
79 | | - editableTextarea?: boolean; |
80 | | - /** Additional props passed to the editable textarea. */ |
81 | | - editableTextareaProps?: any; |
82 | | - /** Category name text for the label group category. If this prop is supplied the label group with have a label and category styling applied */ |
83 | | - category?: string; |
84 | | - /** Set number of labels to show before overflow */ |
85 | | - numLabels?: number; |
86 | | - /** Position of the tooltip which is displayed if the category name text is longer */ |
87 | | - tooltipPosition?: Placement; |
88 | | - /** Aria label for close button */ |
89 | | - closeBtnAriaLabel?: string; |
90 | | - /** Aria label for label group that does not have a category name */ |
91 | | - ariaLabel?: string; |
92 | | - /** Customizable "Show Less" text string */ |
93 | | - expandedText?: string; |
94 | | - /** Customizable template string. Use variable "${remaining}" for the overflow label count. */ |
95 | | - collapsedText?: string; |
| 49 | +<script lang="ts" setup> |
| 50 | +import { h, ref, useTemplateRef, type HTMLAttributes } from 'vue'; |
| 51 | +import styles from '@patternfly/react-styles/css/components/Label/label-group'; |
| 52 | +import labelStyles from '@patternfly/react-styles/css/components/Label/label'; |
| 53 | +import CircleXmarkIcon from '@vue-patternfly/icons/circle-xmark-icon'; |
| 54 | +import PfLabel from './Label.vue'; |
| 55 | +import PfButton from '../Button.vue'; |
| 56 | +import PfTooltip from '../Tooltip/Tooltip.vue'; |
| 57 | +import { findChildrenVNodes, fillTemplate } from '../../util'; |
| 58 | +import { useElementOverflow } from '../../use'; |
| 59 | +import { useOUIAProps, type OUIAProps } from '../../helpers/ouia'; |
| 60 | +import type { Placement } from '../../helpers/FloatingUi.vue'; |
| 61 | +
|
| 62 | +defineOptions({ |
| 63 | + name: 'PfLabelGroup', |
| 64 | +}); |
| 65 | +
|
| 66 | +interface Props extends OUIAProps, /* @vue-ignore */ Omit<HTMLAttributes, 'onClick'> { |
| 67 | + id?: string; |
| 68 | + /** Flag for having the label group default to expanded */ |
| 69 | + defaultOpen?: boolean; |
| 70 | + /** Flag if label group can be closed */ |
| 71 | + closable?: boolean; |
| 72 | + /** Flag indicating the labels in the group are compact */ |
| 73 | + compact?: boolean; |
| 74 | + /** Flag to implement a vertical layout */ |
| 75 | + vertical?: boolean; |
| 76 | + /** Flag indicating contained labels are editable. Allows spacing for a text input after the labels. */ |
| 77 | + editable?: boolean; |
| 78 | + /** Flag indicating the editable label group should be appended with a textarea. */ |
| 79 | + editableTextarea?: boolean; |
| 80 | + /** Additional props passed to the editable textarea. */ |
| 81 | + editableTextareaProps?: any; |
| 82 | + /** Category name text for the label group category. If this prop is supplied the label group with have a label and category styling applied */ |
| 83 | + category?: string; |
| 84 | + /** Set number of labels to show before overflow */ |
| 85 | + numLabels?: number; |
| 86 | + /** Position of the tooltip which is displayed if the category name text is longer */ |
| 87 | + tooltipPosition?: Placement; |
| 88 | + /** Aria label for close button */ |
| 89 | + closeBtnAriaLabel?: string; |
| 90 | + /** Aria label for label group that does not have a category name */ |
| 91 | + ariaLabel?: string; |
| 92 | + /** Customizable "Show Less" text string */ |
| 93 | + expandedText?: string; |
| 94 | + /** Customizable template string. Use variable "${remaining}" for the overflow label count. */ |
| 95 | + collapsedText?: string; |
| 96 | +} |
| 97 | +
|
| 98 | +const props = withDefaults(defineProps<Props>(), { |
| 99 | + numLabels: 3, |
| 100 | + tooltipPosition: 'top', |
| 101 | + closeBtnAriaLabel: 'Close chip group', |
| 102 | + ariaLabel: 'Chip group category', |
| 103 | + expandedText: 'Show Less', |
| 104 | + collapsedText: '${remaining} more', |
| 105 | +}); |
| 106 | +const ouiaProps = useOUIAProps({id: props.ouiaId, safe: props.ouiaSafe}); |
| 107 | +
|
| 108 | +const emit = defineEmits<{ |
| 109 | + (name: 'click', e: PointerEvent): void; |
| 110 | + (name: 'overflowChipClick', e: PointerEvent): void; |
| 111 | +}>(); |
| 112 | +
|
| 113 | +const slots = defineSlots<{ |
| 114 | + default?: (props?: Record<never, never>) => any; |
| 115 | + 'add-label-control'?: (props?: Record<never, never>) => any; |
| 116 | +}>(); |
| 117 | +
|
| 118 | +const label = useTemplateRef('labelRef'); |
| 119 | +const labelOverflowing = useElementOverflow(label); |
| 120 | +const open = ref(props.defaultOpen); |
| 121 | +
|
| 122 | +function overflowChipClick(e: PointerEvent) { |
| 123 | + toggleCollapse(); |
| 124 | + emit('overflowChipClick', e); |
| 125 | +} |
| 126 | +
|
| 127 | +function toggleCollapse() { |
| 128 | + open.value = !open.value; |
| 129 | +} |
| 130 | +
|
| 131 | +function render() { |
| 132 | + const children = slots.default ? findChildrenVNodes(slots.default({})) : []; |
| 133 | +
|
| 134 | + const chipArray = open.value ? children : children.slice(0, props.numLabels); |
| 135 | +
|
| 136 | + const lis = chipArray.map((child, i) => h('li', { key: i, class: styles.labelGroupListItem }, child)); |
| 137 | +
|
| 138 | + if (children.length > props.numLabels) { |
| 139 | + const collapsedTextResult = fillTemplate(props.collapsedText, { |
| 140 | + remaining: children.length - chipArray.length, |
| 141 | + }); |
| 142 | + lis.push(h('li', { class: styles.labelGroupListItem }, [ |
| 143 | + h(PfLabel, { |
| 144 | + class: { [labelStyles.modifiers.compact]: props.compact }, |
| 145 | + component: 'button', |
| 146 | + overflow: true, |
| 147 | + onClick: overflowChipClick as (e: Event) => void, |
| 148 | + }, |
| 149 | + () => open.value ? props.expandedText : collapsedTextResult, |
| 150 | + ), |
| 151 | + ])); |
96 | 152 | } |
97 | 153 |
|
98 | | - const props = withDefaults(defineProps<Props>(), { |
99 | | - numLabels: 3, |
100 | | - tooltipPosition: 'top', |
101 | | - closeBtnAriaLabel: 'Close chip group', |
102 | | - ariaLabel: 'Chip group category', |
103 | | - expandedText: 'Show Less', |
104 | | - collapsedText: '${remaining} more', |
105 | | - }); |
106 | | - const ouiaProps = useOUIAProps({id: props.ouiaId, safe: props.ouiaSafe}); |
107 | | -
|
108 | | - const emit = defineEmits<{ |
109 | | - (name: 'click', e: PointerEvent): void; |
110 | | - (name: 'overflowChipClick', e: PointerEvent): void; |
111 | | - }>(); |
112 | | -
|
113 | | - const slots = defineSlots<{ |
114 | | - default?: (props?: Record<never, never>) => any; |
115 | | - 'add-label-control'?: (props?: Record<never, never>) => any; |
116 | | - }>(); |
117 | | -
|
118 | | - const label = useTemplateRef('labelRef'); |
119 | | - const labelOverflowing = useElementOverflow(label); |
120 | | - const open = ref(props.defaultOpen); |
121 | | -
|
122 | | - function overflowChipClick(e: PointerEvent) { |
123 | | - toggleCollapse(); |
124 | | - emit('overflowChipClick', e); |
125 | | - } |
126 | | -
|
127 | | - function toggleCollapse() { |
128 | | - open.value = !open.value; |
129 | | - } |
130 | | -
|
131 | | - function render() { |
132 | | - const children = slots.default ? findChildrenVNodes(slots.default({})) : []; |
133 | | -
|
134 | | - const chipArray = open.value ? children : children.slice(0, props.numLabels); |
135 | | -
|
136 | | - const lis = chipArray.map((child, i) => h('li', { key: i, class: styles.labelGroupListItem }, child)); |
137 | | -
|
138 | | - if (children.length > props.numLabels) { |
139 | | - const collapsedTextResult = fillTemplate(props.collapsedText, { |
140 | | - remaining: children.length - chipArray.length, |
141 | | - }); |
142 | | - lis.push(h('li', { class: styles.labelGroupListItem }, [ |
143 | | - h(PfLabel, { |
144 | | - class: { [labelStyles.modifiers.compact]: props.compact }, |
145 | | - component: 'button', |
146 | | - overflow: true, |
147 | | - onClick: overflowChipClick as (e: Event) => void, |
148 | | - }, |
149 | | - () => open.value ? props.expandedText : collapsedTextResult, |
150 | | - ), |
151 | | - ])); |
152 | | - } |
153 | | -
|
154 | | - return lis; |
155 | | - } |
156 | | - </script> |
| 154 | + return lis; |
| 155 | +} |
| 156 | +</script> |
0 commit comments