cd-icon-picker 1.2.1 → 1.2.2

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": "cd-icon-picker",
3
- "version": "1.2.1",
3
+ "version": "1.2.2",
4
4
  "description": "Vue 3 icon picker supporting TDesign & RemixIcon, with custom SVG via :diy-icon.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/Icon.vue CHANGED
@@ -1,5 +1,6 @@
1
1
  <template>
2
- <SvgIcon v-if="isSvgIcon" :size="String(size)" :name="getSvgIcon" :class="[$attrs.class, 'cd-icon']" :spin="spin" />
2
+ <img v-if="isImageUrl" :src="icon" :style="getImageStyle" :class="[$attrs.class, 'cd-icon']" />
3
+ <SvgIcon v-else-if="isSvgIcon" :size="String(size)" :name="getSvgIcon" :class="[$attrs.class, 'cd-icon']" :spin="spin" />
3
4
  <span v-else-if="isCompanyIcon" v-html="getCompanySvg" :class="['cd-icon', $attrs.class, spin && 'svg-icon-spin']" :style="getStyle"></span>
4
5
  <i v-else-if="isRemixIcon" :class="['cd-icon', $attrs.class, icon, spin && 'svg-icon-spin']" :style="getStyle"></i>
5
6
  <t-icon v-else :name="icon" :size="String(size)" :color="color" :spin="spin" :class="[$attrs.class, 'cd-icon']" />
@@ -36,6 +37,7 @@ export default defineComponent({
36
37
  },
37
38
  },
38
39
  setup(props) {
40
+ const isImageUrl = computed(() => /^https?:\/\/.+\.(png|jpg|jpeg|gif|svg|webp)/i.test(props.icon || ''));
39
41
  const isSvgIcon = computed(() => props.icon?.endsWith(SVG_END_WITH_FLAG));
40
42
  const getSvgIcon = computed(() => props.icon?.replace(SVG_END_WITH_FLAG, ''));
41
43
  const isRemixIcon = computed(() => props.icon?.startsWith('ri-'));
@@ -57,7 +59,15 @@ export default defineComponent({
57
59
  color: props.color || undefined,
58
60
  };
59
61
  });
60
- return { isSvgIcon, getSvgIcon, isRemixIcon, getStyle, isCompanyIcon, getCompanySvg };
62
+ const getImageStyle = computed((): Record<string, any> => {
63
+ const s = `${String(props.size).replace('px', '')}px`;
64
+ return {
65
+ width: s,
66
+ height: s,
67
+ objectFit: 'contain',
68
+ };
69
+ });
70
+ return { isImageUrl, isSvgIcon, getSvgIcon, isRemixIcon, getStyle, isCompanyIcon, getCompanySvg, getImageStyle };
61
71
  },
62
72
  });
63
73
  </script>
@@ -62,6 +62,13 @@
62
62
  <div class="cd-picker-search">
63
63
  <t-input :placeholder="searchPlaceholder" @input="debounceHandleSearchChange" clearable />
64
64
  </div>
65
+ <div v-if="sourceType === 'custom'" class="cd-picker-custom-url" style="padding: 12px; border-bottom: 1px solid #eee;">
66
+ <t-input v-model="customImageUrl" placeholder="输入图片URL (https://...)" clearable>
67
+ <template #suffix>
68
+ <t-button size="small" @click="handleAddCustomImage">添加</t-button>
69
+ </template>
70
+ </t-input>
71
+ </div>
65
72
  <div v-if="getPaginationList.length" class="cd-picker-content">
66
73
  <ul class="cd-picker-grid">
67
74
  <li
@@ -141,8 +148,8 @@ const categoryType = ref<string>('all');
141
148
 
142
149
  const customIcons = computed(() => {
143
150
  const d = props.diyIcon as any;
144
- if (Array.isArray(d)) return d as string[];
145
- return (d?.icons ?? []) as string[];
151
+ const baseIcons = Array.isArray(d) ? (d as string[]) : ((d?.icons ?? []) as string[]);
152
+ return [...baseIcons, ...customImageList.value];
146
153
  });
147
154
 
148
155
  const currentSelect = ref('');
@@ -152,6 +159,8 @@ const pageSize = computed(() => props.pageSize);
152
159
  const color = ref(props.color);
153
160
  const colorPickerVisible = ref(false);
154
161
  const presetColors = ['#000000', '#e74c3c', '#3498db', '#2ecc71', '#f39c12', '#9b59b6', '#1abc9c', '#34495e'];
162
+ const customImageUrl = ref('');
163
+ const customImageList = ref<string[]>([]);
155
164
 
156
165
  const displayValue = computed({
157
166
  get() {
@@ -284,7 +293,7 @@ function handleConfirm() {
284
293
 
285
294
  emit('update:value', icon);
286
295
  emit('update:color', color.value);
287
- emit('change', sourceType.value as any, icon as any);
296
+ emit('change', sourceType.value as any, icon as any, color.value);
288
297
  }
289
298
 
290
299
  function handleCancel() {
@@ -296,6 +305,20 @@ function handleCancel() {
296
305
  currentSelect.value = v;
297
306
  }
298
307
 
308
+ function handleAddCustomImage() {
309
+ const url = customImageUrl.value.trim();
310
+ if (!url) return;
311
+ if (!isImageUrl(url)) {
312
+ alert('请输入有效的图片 URL');
313
+ return;
314
+ }
315
+ if (!customImageList.value.includes(url)) {
316
+ customImageList.value.push(url);
317
+ }
318
+ currentSelect.value = url;
319
+ customImageUrl.value = '';
320
+ }
321
+
299
322
  watch(
300
323
  () => sourceType.value,
301
324
  v => {