@citizenplane/pimp 9.0.1 → 9.1.0

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.0.1",
3
+ "version": "9.1.0",
4
4
  "scripts": {
5
5
  "dev": "storybook dev -p 8080",
6
6
  "build-storybook": "storybook build --output-dir ./docs",
@@ -37,7 +37,7 @@
37
37
  :class="getRowClasses(rowData, rowIndex)"
38
38
  :tabindex="getTabindex(rowData)"
39
39
  @click="handleRowClick(rowData, rowIndex)"
40
- @click.right="handleRowRightClick({ rowData, rowIndex }, $event)"
40
+ @contextmenu.prevent="handleContextMenu({ rowData, rowIndex }, $event)"
41
41
  @keydown.enter="handleRowClick(rowData, rowIndex)"
42
42
  >
43
43
  <slot name="row" :row="rowData">
@@ -65,8 +65,8 @@
65
65
  type="button"
66
66
  class="cpTable__action"
67
67
  :class="getQuickOptionClasses(option)"
68
- :disabled="option.disabled"
69
- @click.stop="option.action({ rowData, rowIndex }, $event)"
68
+ :disabled="option.isDisabled"
69
+ @click.stop="($event) => option.action(rowData, $event)"
70
70
  >
71
71
  <cp-icon :type="option.icon" size="16" />
72
72
  </button>
@@ -74,7 +74,7 @@
74
74
  <button
75
75
  type="button"
76
76
  class="cpTable__defaultAction"
77
- @click.stop="handleRowRightClick({ rowData, rowIndex }, $event)"
77
+ @click.stop="handleContextMenu({ rowData, rowIndex }, $event)"
78
78
  >
79
79
  <cp-icon type="more-vertical" size="16" />
80
80
  </button>
@@ -108,12 +108,14 @@
108
108
  </div>
109
109
  </div>
110
110
  <div class="cpTable__overlay" />
111
+ <cp-contextual-menu v-if="hasRowOptions" ref="contextualMenu" :items="contextualMenuItems" />
111
112
  </div>
112
113
  </template>
113
114
 
114
115
  <script setup lang="ts">
115
116
  import { ref, computed } from 'vue'
116
117
 
118
+ import CpContextualMenu from '@/components/CpContextualMenu.vue'
117
119
  import CpTableEmptyState from '@/components/CpTableEmptyState.vue'
118
120
 
119
121
  import { camelize, decamelize } from '@/helpers/string'
@@ -123,7 +125,6 @@ import { randomString } from '@/helpers'
123
125
 
124
126
  interface Emits {
125
127
  (e: 'onRowClick', data: Record<string, unknown>): void
126
- (e: 'onRowRightClick', payload: { data: Record<string, unknown>; event: Event }): void
127
128
  (e: 'onNextClick'): void
128
129
  (e: 'onPreviousClick'): void
129
130
  }
@@ -148,11 +149,12 @@ interface Pagination {
148
149
  }
149
150
 
150
151
  interface RowOptions {
151
- action: (payload: { rowData: Record<string, unknown>; rowIndex: number }, event: Event) => void
152
- disabled?: boolean
152
+ action: (rowData: Record<string, unknown>, $event: MouseEvent) => void
153
153
  icon: string
154
154
  id: string
155
155
  isCritical?: boolean
156
+ isDisabled?: boolean
157
+ isLoading?: boolean
156
158
  label: string
157
159
  }
158
160
 
@@ -195,25 +197,18 @@ const LoaderColor = '#5341F9'
195
197
  const uniqueId = ref(randomString())
196
198
  const pageNumber = ref(0)
197
199
  const cpTableContainer = ref<HTMLElement | null>(null)
200
+ const contextualMenu = ref<InstanceType<typeof CpContextualMenu>>()
198
201
 
199
202
  const hasQuickOptions = computed(() => !!quickOptions.value.length)
203
+ const hasRowOptions = computed(() => props.enableRowOptions && props.rowOptions.length)
200
204
  const hasMoreQuickActionsThanLimit = computed(() => props.rowOptions.length >= props.quickOptionsLimit)
201
205
 
202
- const defaultRowOptions = computed<RowOptions>(() => {
203
- if (!props.enableRowOptions || !props.rowOptions.length) {
204
- return {
205
- id: 'default',
206
- label: 'More',
207
- icon: 'more-vertical',
208
- action: () => {},
209
- }
210
- }
206
+ const defaultRowOption = computed<RowOptions>(() => {
211
207
  return {
212
208
  id: 'more',
213
209
  label: 'More',
214
210
  icon: 'more-vertical',
215
- action: ({ rowData, rowIndex }: { rowData: Record<string, unknown>; rowIndex: number }, $event: Event) =>
216
- handleRowRightClick({ rowData, rowIndex }, $event),
211
+ action: (rowData: Record<string, unknown>, $event: MouseEvent) => showContextualMenu($event),
217
212
  }
218
213
  })
219
214
 
@@ -222,10 +217,18 @@ const quickOptions = computed(() => {
222
217
 
223
218
  if (hasMoreQuickActionsThanLimit.value) {
224
219
  const slicedOptions = props.rowOptions.slice(0, props.quickOptionsLimit)
225
- return [...slicedOptions, defaultRowOptions.value]
220
+ return [...slicedOptions, defaultRowOption.value]
226
221
  }
227
222
 
228
- return [...props.rowOptions, defaultRowOptions.value]
223
+ return [...props.rowOptions, defaultRowOption.value]
224
+ })
225
+
226
+ const currentRowData = ref<Record<string, unknown>>({})
227
+ const contextualMenuItems = computed(() => {
228
+ return props.rowOptions.map((option) => ({
229
+ ...option,
230
+ command: ({ originalEvent }: { originalEvent: MouseEvent }) => option.action(currentRowData.value, originalEvent),
231
+ }))
229
232
  })
230
233
 
231
234
  const containerDOMElement = computed(() => cpTableContainer.value)
@@ -363,7 +366,20 @@ const paginationResultsDetails = computed(() => {
363
366
  return `${formattedNumberOfResults} ${pluralizedCount}`
364
367
  })
365
368
 
366
- const getQuickOptionTooltip = (option: RowOptions) => (!option.disabled ? option.label : '')
369
+ const handleContextMenu = (
370
+ { rowData, rowIndex }: { rowData: Record<string, unknown>; rowIndex: number },
371
+ event: MouseEvent,
372
+ ) => {
373
+ if (!hasRowOptions.value || isFullWidthRow(rowData)) return
374
+ currentRowData.value = getRowPayload(rowIndex)
375
+
376
+ showContextualMenu(event)
377
+ }
378
+
379
+ const showContextualMenu = (event: MouseEvent) => contextualMenu.value?.show(event)
380
+ const hideContextualMenu = () => contextualMenu.value?.hide()
381
+
382
+ const getQuickOptionTooltip = (option: RowOptions) => (!option.isDisabled ? option.label : '')
367
383
 
368
384
  const getQuickOptionClasses = (option: RowOptions) => {
369
385
  return { 'cpTable__action--isCritical': option.isCritical }
@@ -378,16 +394,6 @@ const handleRowClick = (rowData: Record<string, unknown>, rowIndex: number) => {
378
394
  emit('onRowClick', data)
379
395
  }
380
396
 
381
- const handleRowRightClick = (
382
- { rowData, rowIndex }: { rowData: Record<string, unknown>; rowIndex: number },
383
- event: Event,
384
- ) => {
385
- if (isFullWidthRow(rowData)) return
386
-
387
- const data = getRowPayload(rowIndex)
388
- emit('onRowRightClick', { data, event })
389
- }
390
-
391
397
  const handleNavigationClick = (isNext = true) => {
392
398
  resetScrollPosition()
393
399
 
@@ -504,7 +510,7 @@ const areRowOptionsEnabled = (rowData: Record<string, unknown>) => props.enableR
504
510
 
505
511
  const resetPagination = () => (pageNumber.value = 0)
506
512
 
507
- defineExpose({ resetPagination })
513
+ defineExpose({ hideContextualMenu, resetPagination })
508
514
  </script>
509
515
 
510
516
  <style lang="scss">
@@ -108,17 +108,6 @@ export const Default: Story = {
108
108
  }),
109
109
  }
110
110
 
111
- export const WithPagination: Story = {
112
- args: {
113
- ...Default.args,
114
- pagination: {
115
- enabled: true,
116
- limit: 3,
117
- format: PAGINATION_FORMATS.PAGES,
118
- },
119
- },
120
- }
121
-
122
111
  export const ClickableRows: Story = {
123
112
  args: {
124
113
  ...Default.args,
@@ -126,24 +115,28 @@ export const ClickableRows: Story = {
126
115
  },
127
116
  }
128
117
 
129
- export const WithRowOptions: Story = {
118
+ export const Loading: Story = {
130
119
  args: {
131
120
  ...Default.args,
132
- enableRowOptions: true,
121
+ isLoading: true,
133
122
  },
134
123
  }
135
124
 
136
- export const Loading: Story = {
125
+ export const Empty: Story = {
137
126
  args: {
138
127
  ...Default.args,
139
- isLoading: true,
128
+ data: [],
140
129
  },
141
130
  }
142
131
 
143
- export const Empty: Story = {
132
+ export const WithPagination: Story = {
144
133
  args: {
145
134
  ...Default.args,
146
- data: [],
135
+ pagination: {
136
+ enabled: true,
137
+ limit: 3,
138
+ format: PAGINATION_FORMATS.PAGES,
139
+ },
147
140
  },
148
141
  }
149
142
 
@@ -194,26 +187,26 @@ export const WithCustomRowOptions: Story = {
194
187
  rowOptions: [
195
188
  {
196
189
  id: 'see',
197
- label: 'see',
190
+ label: 'See',
198
191
  icon: 'eye',
199
192
  action: () => console.log('See'),
200
193
  },
201
194
  {
202
195
  id: 'edit',
203
- label: 'edit',
196
+ label: 'Edit',
204
197
  icon: 'edit-2',
205
- action: () => console.log('Edit'),
198
+ action: (payload) => console.log('Edit', payload),
206
199
  },
207
200
  {
208
201
  id: 'disable',
209
- label: 'disable',
202
+ label: 'Disable',
210
203
  icon: 'history',
211
- disabled: true,
204
+ isDisabled: true,
212
205
  action: () => console.log('History'),
213
206
  },
214
207
  {
215
208
  id: 'delete',
216
- label: 'delete',
209
+ label: 'Delete',
217
210
  icon: 'trash',
218
211
  isCritical: true,
219
212
  action: () => console.log('Delete'),