@citizenplane/pimp 9.1.0 → 9.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@citizenplane/pimp",
3
- "version": "9.1.0",
3
+ "version": "9.1.1",
4
4
  "scripts": {
5
5
  "dev": "storybook dev -p 8080",
6
6
  "build-storybook": "storybook build --output-dir ./docs",
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <context-menu ref="menu" :model="items" :pt="passThroughConfig">
3
3
  <template #item="{ item, props }">
4
- <cp-menu-item v-bind="{ ...item, ...props.action }" />
4
+ <cp-menu-item v-bind="{ ...item, ...props.action }" @on-async-command-complete="hide" />
5
5
  </template>
6
6
  </context-menu>
7
7
  </template>
@@ -5,7 +5,7 @@
5
5
  class="cpMenuItem__button"
6
6
  :class="dynamicClass"
7
7
  :disabled="disabled"
8
- @click.stop="handleItemClick"
8
+ @click="handleItemClick"
9
9
  >
10
10
  <transition name="fade" :duration="100" mode="out-in">
11
11
  <span v-if="isLoading" class="cpMenuItem__loaderWrapper">
@@ -28,6 +28,7 @@ import { computed } from 'vue'
28
28
  import type { MenuItem } from 'primevue/menuitem'
29
29
 
30
30
  interface Props {
31
+ isAsync?: boolean
31
32
  isCritical?: boolean
32
33
  isDisabled?: boolean
33
34
  isLoading?: boolean
@@ -44,9 +45,10 @@ const props = withDefaults(defineProps<Props & Omit<MenuItem, 'class' | 'disable
44
45
  isLoading: false,
45
46
  isDisabled: false,
46
47
  isCritical: false,
48
+ isAsync: false,
47
49
  })
48
50
 
49
- const emit = defineEmits(['onItemClick'])
51
+ const emit = defineEmits(['onItemClick', 'onAsyncCommandComplete'])
50
52
 
51
53
  const dynamicClass = computed(() => ({
52
54
  'cpMenuItem__button--reverseLabel': props.reverseLabel,
@@ -55,12 +57,18 @@ const dynamicClass = computed(() => ({
55
57
 
56
58
  const disabled = computed(() => props.isLoading || props.isDisabled)
57
59
 
58
- const handleItemClick = (event: Event) => {
59
- if (props.command) {
60
- props.command({
61
- originalEvent: event,
62
- item: props,
63
- })
60
+ const handleItemClick = async (event: Event) => {
61
+ if (!props.command) return
62
+
63
+ if (props.isAsync) {
64
+ // Stop the event from bubbling up to prevent menu auto close
65
+ event.stopPropagation()
66
+
67
+ await props.command({ originalEvent: event, item: props })
68
+
69
+ emit('onAsyncCommandComplete')
70
+ } else {
71
+ props.command({ originalEvent: event, item: props })
64
72
  }
65
73
 
66
74
  emit('onItemClick')
@@ -108,7 +108,12 @@
108
108
  </div>
109
109
  </div>
110
110
  <div class="cpTable__overlay" />
111
- <cp-contextual-menu v-if="hasRowOptions" ref="contextualMenu" :items="contextualMenuItems" />
111
+ <cp-contextual-menu
112
+ v-if="hasRowOptions"
113
+ ref="contextualMenu"
114
+ :items="contextualMenuItems"
115
+ @hide="resetCurrentRowData"
116
+ />
112
117
  </div>
113
118
  </template>
114
119
 
@@ -152,6 +157,7 @@ interface RowOptions {
152
157
  action: (rowData: Record<string, unknown>, $event: MouseEvent) => void
153
158
  icon: string
154
159
  id: string
160
+ isAsync?: boolean
155
161
  isCritical?: boolean
156
162
  isDisabled?: boolean
157
163
  isLoading?: boolean
@@ -378,6 +384,7 @@ const handleContextMenu = (
378
384
 
379
385
  const showContextualMenu = (event: MouseEvent) => contextualMenu.value?.show(event)
380
386
  const hideContextualMenu = () => contextualMenu.value?.hide()
387
+ const resetCurrentRowData = () => (currentRowData.value = {})
381
388
 
382
389
  const getQuickOptionTooltip = (option: RowOptions) => (!option.isDisabled ? option.label : '')
383
390
 
@@ -45,11 +45,16 @@ export const Default: Story = {
45
45
  label: 'Download',
46
46
  icon: 'download',
47
47
  isLoading: isLoading.value,
48
- command: () => {
48
+ isAsync: true,
49
+ command: async () => {
49
50
  isLoading.value = true
50
- setTimeout(() => (isLoading.value = false), 2000)
51
+ await new Promise((resolve) => setTimeout(resolve, 2000))
52
+ isLoading.value = false
51
53
  },
52
54
  },
55
+ {
56
+ separator: true,
57
+ },
53
58
  {
54
59
  label: 'Delete',
55
60
  icon: 'trash-2',
@@ -1,3 +1,5 @@
1
+ import { ref, computed } from 'vue'
2
+
1
3
  import type { Meta, StoryObj } from '@storybook/vue3'
2
4
 
3
5
  import CpTable from '@/components/CpTable.vue'
@@ -184,42 +186,52 @@ export const WithCustomRowOptions: Story = {
184
186
  args: {
185
187
  ...Default.args,
186
188
  enableRowOptions: true,
187
- rowOptions: [
188
- {
189
- id: 'see',
190
- label: 'See',
191
- icon: 'eye',
192
- action: () => console.log('See'),
193
- },
194
- {
195
- id: 'edit',
196
- label: 'Edit',
197
- icon: 'edit-2',
198
- action: (payload) => console.log('Edit', payload),
199
- },
200
- {
201
- id: 'disable',
202
- label: 'Disable',
203
- icon: 'history',
204
- isDisabled: true,
205
- action: () => console.log('History'),
206
- },
207
- {
208
- id: 'delete',
209
- label: 'Delete',
210
- icon: 'trash',
211
- isCritical: true,
212
- action: () => console.log('Delete'),
213
- },
214
- ],
215
189
  },
216
190
  render: (args) => ({
217
191
  components: { CpTable },
218
192
  setup() {
219
- return { args }
193
+ const isEditLoading = ref(false)
194
+
195
+ const rowOptions = computed(() => [
196
+ {
197
+ id: 'see',
198
+ label: 'See',
199
+ icon: 'eye',
200
+ action: () => console.log('See'),
201
+ },
202
+ {
203
+ id: 'edit',
204
+ label: 'Edit',
205
+ icon: 'edit-2',
206
+ isAsync: true,
207
+ isLoading: isEditLoading.value,
208
+ action: async (payload) => {
209
+ isEditLoading.value = true
210
+ console.log('Edit', payload)
211
+ await new Promise((resolve) => setTimeout(resolve, 2000))
212
+ isEditLoading.value = false
213
+ },
214
+ },
215
+ {
216
+ id: 'disable',
217
+ label: 'Disable',
218
+ icon: 'history',
219
+ isDisabled: true,
220
+ action: () => console.log('History'),
221
+ },
222
+ {
223
+ id: 'delete',
224
+ label: 'Delete',
225
+ icon: 'trash',
226
+ isCritical: true,
227
+ action: () => console.log('Delete'),
228
+ },
229
+ ])
230
+
231
+ return { args, isEditLoading, rowOptions }
220
232
  },
221
233
  template: `
222
- <CpTable v-bind="args">
234
+ <CpTable v-bind="args" :row-options="rowOptions">
223
235
  <template #status="{ cell }">
224
236
  <span :style="{
225
237
  padding: '4px 8px',