@citizenplane/pimp 14.0.3 → 14.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/dist/pimp.es.js +1042 -1036
- package/dist/pimp.umd.js +16 -16
- package/package.json +1 -1
- package/src/components/CpMultiselect.vue +25 -3
- package/src/components/CpTable.vue +2 -1
- package/src/stories/CpMultiselect.stories.ts +3 -23
- package/src/stories/CpTable.stories.ts +48 -0
package/package.json
CHANGED
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
:option-label
|
|
29
29
|
:placeholder
|
|
30
30
|
:pt="passThroughConfig"
|
|
31
|
-
:suggestions="
|
|
31
|
+
:suggestions="dynamicOptions"
|
|
32
32
|
:typeahead
|
|
33
33
|
@click="handleClick"
|
|
34
34
|
@complete="handleSearch"
|
|
@@ -126,6 +126,7 @@ interface Props {
|
|
|
126
126
|
modelValue?: Record<string, unknown>[] | Record<string, unknown> | string[] | null
|
|
127
127
|
multiple?: boolean
|
|
128
128
|
name?: string
|
|
129
|
+
onSearch?: (query: string) => void
|
|
129
130
|
optionDisabled?: string | ((option: unknown) => boolean)
|
|
130
131
|
optionLabel?: string
|
|
131
132
|
options?: unknown[]
|
|
@@ -141,7 +142,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
141
142
|
label: '',
|
|
142
143
|
name: '',
|
|
143
144
|
placeholder: '',
|
|
144
|
-
optionLabel:
|
|
145
|
+
optionLabel: 'name',
|
|
145
146
|
trackBy: undefined,
|
|
146
147
|
emptyMessage: 'No results found',
|
|
147
148
|
errorMessage: '',
|
|
@@ -149,6 +150,7 @@ const props = withDefaults(defineProps<Props>(), {
|
|
|
149
150
|
optionDisabled: 'disabled',
|
|
150
151
|
options: () => [],
|
|
151
152
|
size: 'md',
|
|
153
|
+
onSearch: undefined,
|
|
152
154
|
})
|
|
153
155
|
|
|
154
156
|
const emit = defineEmits<Emits>()
|
|
@@ -218,7 +220,27 @@ const displayClearButton = computed(() => {
|
|
|
218
220
|
return props.isClearable && !isEmpty(selectModel.value)
|
|
219
221
|
})
|
|
220
222
|
|
|
221
|
-
const
|
|
223
|
+
const hasRegisteredOnSearch = computed(() => props.onSearch !== undefined)
|
|
224
|
+
|
|
225
|
+
const handleSearch = (event: { query: string }) => {
|
|
226
|
+
if (hasRegisteredOnSearch.value) {
|
|
227
|
+
return emit('search', event.query)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// If no onSearch is registered, toggle the dropdown (if hidden) to show the options
|
|
231
|
+
if (!isDropdownOpen.value) {
|
|
232
|
+
toggleDropdown()
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const dynamicOptions = computed(() => {
|
|
237
|
+
if (hasRegisteredOnSearch.value) return props.options
|
|
238
|
+
|
|
239
|
+
return props.options.filter((option: unknown) => {
|
|
240
|
+
const optionLabel = typeof option === 'object' ? (option as Record<string, unknown>)[props.optionLabel] : option
|
|
241
|
+
return (optionLabel as string).toLowerCase().includes(searchQuery.value.toLowerCase())
|
|
242
|
+
})
|
|
243
|
+
})
|
|
222
244
|
const handleClear = () => (selectModel.value = null)
|
|
223
245
|
const handleOverlayShown = () => emit('overlayShown')
|
|
224
246
|
const handleOverlayHidden = () => emit('overlayHidden')
|
|
@@ -77,6 +77,7 @@
|
|
|
77
77
|
<cp-icon size="16" :type="option.icon" />
|
|
78
78
|
</button>
|
|
79
79
|
<button
|
|
80
|
+
v-if="hasMoreQuickActionsThanLimit"
|
|
80
81
|
class="cpTable__action cpTable__action--isDefault"
|
|
81
82
|
type="button"
|
|
82
83
|
@click.stop="handleContextMenu({ rowData, rowIndex }, $event)"
|
|
@@ -209,7 +210,7 @@ const cpTableContainer = ref<HTMLElement | null>(null)
|
|
|
209
210
|
const contextualMenu = ref<InstanceType<typeof CpContextualMenu>>()
|
|
210
211
|
|
|
211
212
|
const hasRowOptions = computed(() => props.enableRowOptions && props.rowOptions.length)
|
|
212
|
-
const hasMoreQuickActionsThanLimit = computed(() => props.rowOptions.length
|
|
213
|
+
const hasMoreQuickActionsThanLimit = computed(() => props.rowOptions.length > props.quickOptionsLimit)
|
|
213
214
|
|
|
214
215
|
const quickOptions = computed(() => {
|
|
215
216
|
if (!props.enableRowOptions || !props.rowOptions.length || props.quickOptionsLimit === 0) return []
|
|
@@ -113,43 +113,23 @@ const meta = {
|
|
|
113
113
|
export default meta
|
|
114
114
|
type Story = StoryObj<typeof meta>
|
|
115
115
|
|
|
116
|
-
export const
|
|
116
|
+
export const DefaultSearchHandler: Story = {
|
|
117
117
|
args: {
|
|
118
118
|
placeholder: 'Select a supplier',
|
|
119
119
|
multiple: false,
|
|
120
120
|
options: supplierOptions,
|
|
121
|
-
optionLabel: 'name',
|
|
122
121
|
trackBy: 'id',
|
|
123
122
|
isClearable: true,
|
|
124
123
|
},
|
|
125
124
|
render: (args) => ({
|
|
126
125
|
components: { CpMultiselect },
|
|
127
126
|
setup() {
|
|
128
|
-
const searchQuery = ref('')
|
|
129
|
-
const isLoading = ref(false)
|
|
130
|
-
|
|
131
|
-
const originalOptions = ref(args.options)
|
|
132
|
-
const dynamicOptions = ref(toValue(originalOptions))
|
|
133
127
|
const selectedSupplier = ref(null)
|
|
134
|
-
|
|
135
|
-
const handleSearch = async (query: string) => {
|
|
136
|
-
isLoading.value = true
|
|
137
|
-
searchQuery.value = query
|
|
138
|
-
|
|
139
|
-
await new Promise((resolve) => setTimeout(resolve, 500))
|
|
140
|
-
|
|
141
|
-
dynamicOptions.value = originalOptions.value?.filter((option) => {
|
|
142
|
-
return (option as IOption).name.toLowerCase().includes(searchQuery.value.toLowerCase())
|
|
143
|
-
})
|
|
144
|
-
|
|
145
|
-
isLoading.value = false
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
return { args, selectedSupplier, dynamicOptions, handleSearch, isLoading }
|
|
128
|
+
return { args, selectedSupplier }
|
|
149
129
|
},
|
|
150
130
|
template: `
|
|
151
131
|
<div style="padding: 20px;width: 25rem;">
|
|
152
|
-
<CpMultiselect v-model="selectedSupplier" v-bind="args"
|
|
132
|
+
<CpMultiselect v-model="selectedSupplier" v-bind="args">
|
|
153
133
|
<template #prefix>
|
|
154
134
|
<cp-partner-badge type="supplier" size="sm" />
|
|
155
135
|
</template>
|
|
@@ -219,6 +219,54 @@ export const WithCustomRowOptions: Story = {
|
|
|
219
219
|
}),
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
+
export const WithoutDefaultAction: Story = {
|
|
223
|
+
args: {
|
|
224
|
+
...Default.args,
|
|
225
|
+
enableRowOptions: true,
|
|
226
|
+
quickOptionsLimit: 2,
|
|
227
|
+
enableColumnEdition: true,
|
|
228
|
+
},
|
|
229
|
+
render: (args) => ({
|
|
230
|
+
components: { CpTable },
|
|
231
|
+
setup() {
|
|
232
|
+
const isEditLoading = ref(false)
|
|
233
|
+
|
|
234
|
+
const rowOptions = computed(() => [
|
|
235
|
+
{
|
|
236
|
+
id: 'see',
|
|
237
|
+
label: 'See',
|
|
238
|
+
icon: 'eye',
|
|
239
|
+
action: () => console.log('See'),
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
id: 'delete',
|
|
243
|
+
label: 'Delete',
|
|
244
|
+
icon: 'trash',
|
|
245
|
+
isCritical: true,
|
|
246
|
+
action: () => console.log('Delete'),
|
|
247
|
+
},
|
|
248
|
+
])
|
|
249
|
+
|
|
250
|
+
return { args, isEditLoading, rowOptions }
|
|
251
|
+
},
|
|
252
|
+
template: `
|
|
253
|
+
<CpTable v-bind="args" :row-options="rowOptions">
|
|
254
|
+
<template #status="{ cell }">
|
|
255
|
+
<span :style="{
|
|
256
|
+
padding: '4px 8px',
|
|
257
|
+
borderRadius: '4px',
|
|
258
|
+
fontSize: '12px',
|
|
259
|
+
backgroundColor: cell === 'Active' ? '#10B981' : '#EF4444',
|
|
260
|
+
color: 'white'
|
|
261
|
+
}">
|
|
262
|
+
{{ cell }}
|
|
263
|
+
</span>
|
|
264
|
+
</template>
|
|
265
|
+
</CpTable>
|
|
266
|
+
`,
|
|
267
|
+
}),
|
|
268
|
+
}
|
|
269
|
+
|
|
222
270
|
export const WithOnlyDefaultAction: Story = {
|
|
223
271
|
args: {
|
|
224
272
|
...Default.args,
|