sprintify-ui 0.10.22 → 0.10.24

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.
Files changed (33) hide show
  1. package/dist/sprintify-ui.es.js +4203 -4203
  2. package/dist/types/components/BaseAutocomplete.vue.d.ts +17 -11
  3. package/dist/types/components/BaseAutocompleteDrawer.vue.d.ts +3 -1
  4. package/dist/types/components/BaseAutocompleteFetch.vue.d.ts +29 -23
  5. package/dist/types/components/BaseBelongsTo.vue.d.ts +25 -19
  6. package/dist/types/components/BaseBelongsToFetch.vue.d.ts +21 -15
  7. package/dist/types/components/BaseDropdownAutocomplete.vue.d.ts +13 -17
  8. package/dist/types/components/BaseHasMany.vue.d.ts +31 -25
  9. package/dist/types/components/BaseHasManyFetch.vue.d.ts +27 -21
  10. package/dist/types/components/BaseTagAutocomplete.vue.d.ts +17 -11
  11. package/dist/types/components/BaseTagAutocompleteFetch.vue.d.ts +33 -27
  12. package/dist/types/composables/hasOptions.d.ts +1 -1
  13. package/dist/types/types/index.d.ts +1 -1
  14. package/package.json +1 -1
  15. package/src/components/BaseAutocomplete.stories.js +7 -0
  16. package/src/components/BaseAutocomplete.vue +3 -9
  17. package/src/components/BaseAutocompleteDrawer.vue +2 -0
  18. package/src/components/BaseAutocompleteFetch.stories.js +8 -1
  19. package/src/components/BaseAutocompleteFetch.vue +6 -5
  20. package/src/components/BaseBelongsTo.stories.js +7 -0
  21. package/src/components/BaseBelongsTo.vue +1 -1
  22. package/src/components/BaseBelongsToFetch.stories.js +7 -0
  23. package/src/components/BaseDropdownAutocomplete.stories.js +9 -7
  24. package/src/components/BaseDropdownAutocomplete.vue +6 -11
  25. package/src/components/BaseHasMany.stories.js +7 -2
  26. package/src/components/BaseHasMany.vue +1 -1
  27. package/src/components/BaseHasManyFetch.stories.js +7 -0
  28. package/src/components/BaseTagAutocomplete.stories.js +7 -0
  29. package/src/components/BaseTagAutocomplete.vue +2 -2
  30. package/src/components/BaseTagAutocompleteFetch.stories.js +7 -0
  31. package/src/components/BaseTagAutocompleteFetch.vue +7 -6
  32. package/src/composables/hasOptions.ts +28 -10
  33. package/src/types/index.ts +1 -1
@@ -134,11 +134,11 @@ const props = defineProps({
134
134
  },
135
135
  labelKey: {
136
136
  required: true,
137
- type: String,
137
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
138
138
  },
139
139
  valueKey: {
140
140
  required: true,
141
- type: String,
141
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
142
142
  },
143
143
  name: {
144
144
  default: undefined,
@@ -286,14 +286,8 @@ const filteredNormalizedOptions = computed((): NormalizedOption[] => {
286
286
  let options = normalizedOptions.value;
287
287
 
288
288
  if (props.showEmptyOption) {
289
- const emptyOption = {
290
- [props.valueKey]: null,
291
- [props.labelKey]: props.emptyOptionLabel,
292
- option: null,
293
- };
294
-
295
289
  options = [
296
- { value: null, label: props.emptyOptionLabel, option: emptyOption },
290
+ { value: null, label: props.emptyOptionLabel, option: null },
297
291
  ...options,
298
292
  ];
299
293
  }
@@ -39,6 +39,8 @@
39
39
  <slot
40
40
  name="option"
41
41
  :option="option.option"
42
+ :value="option.value"
43
+ :label="option.label"
42
44
  :selected="isSelected(option)"
43
45
  :active="focusOption && focusOption.value == option.value"
44
46
  >
@@ -35,6 +35,13 @@ const Template = (args) => ({
35
35
  export const Demo = Template.bind({});
36
36
  Demo.args = {};
37
37
 
38
+ export const LabelFunction = Template.bind({});
39
+ LabelFunction.args = {
40
+ labelKey: (option) => {
41
+ return option.title + " - " + option.uuid;
42
+ }
43
+ };
44
+
38
45
  export const AlwaysShowDropdown = Template.bind({});
39
46
  AlwaysShowDropdown.args = {
40
47
  inline: true,
@@ -57,7 +64,7 @@ Disabled.args = {
57
64
  export const ShowEmptyOption = Template.bind({});
58
65
  ShowEmptyOption.args = {
59
66
  showEmptyOption: true,
60
- emptyOptionLabel: "No Jedi",
67
+ emptyOptionLabel: "No Todo",
61
68
  };
62
69
 
63
70
  export const Inline = Template.bind({});
@@ -98,11 +98,11 @@ const props = defineProps({
98
98
  },
99
99
  labelKey: {
100
100
  required: true,
101
- type: String,
101
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
102
102
  },
103
103
  valueKey: {
104
104
  required: true,
105
- type: String,
105
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
106
106
  },
107
107
  name: {
108
108
  default: undefined,
@@ -244,7 +244,8 @@ let requestId = '';
244
244
  async function search() {
245
245
  fetching.value = true;
246
246
  showLoading.value = true;
247
- requestId = uniqueId();
247
+ const requestIdInternal = uniqueId();
248
+ requestId = requestIdInternal;
248
249
 
249
250
  config.http
250
251
  .get(props.url, {
@@ -255,7 +256,7 @@ async function search() {
255
256
  })
256
257
  .then((response: any) => {
257
258
 
258
- if (requestId !== requestId) {
259
+ if (requestIdInternal !== requestId) {
259
260
  return;
260
261
  }
261
262
 
@@ -274,7 +275,7 @@ async function search() {
274
275
  })
275
276
  .finally(() => {
276
277
 
277
- if (requestId !== requestId) {
278
+ if (requestIdInternal !== requestId) {
278
279
  return;
279
280
  }
280
281
 
@@ -35,6 +35,13 @@ const Template = (args) => ({
35
35
  export const Demo = Template.bind({});
36
36
  Demo.args = {};
37
37
 
38
+ export const LabelFunction = Template.bind({});
39
+ LabelFunction.args = {
40
+ labelKey: (option) => {
41
+ return option.label + " (" + option.size + ")";
42
+ },
43
+ };
44
+
38
45
  export const AlwaysShowDropdown = Template.bind({});
39
46
  AlwaysShowDropdown.args = {
40
47
  inline: true,
@@ -66,7 +66,7 @@ const props = defineProps({
66
66
  },
67
67
  field: {
68
68
  required: true,
69
- type: String,
69
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
70
70
  },
71
71
  required: {
72
72
  default: false,
@@ -37,6 +37,13 @@ const Template = (args) => ({
37
37
  export const Demo = Template.bind({});
38
38
  Demo.args = {};
39
39
 
40
+ export const LabelFunction = Template.bind({});
41
+ LabelFunction.args = {
42
+ labelKey: (option) => {
43
+ return option.name + " (" + option.uuid + ")";
44
+ },
45
+ };
46
+
40
47
  export const AlwaysShowDropdown = Template.bind({});
41
48
  AlwaysShowDropdown.args = {
42
49
  inline: true,
@@ -37,7 +37,7 @@ const template = `<template #button="{ newValue }">
37
37
  Select a character
38
38
  </div>
39
39
  </div>
40
- </template>
40
+ </template>
41
41
  <template #option="{ option }">
42
42
  <div class="flex items-center gap-2 text-sm py-1 px-2">
43
43
  <div
@@ -108,9 +108,9 @@ export const AutocompleteFetch = (args) => ({
108
108
  </BaseBadge>
109
109
  </div>
110
110
  </template>
111
- <template #option="{ option }">
111
+ <template #option="{ label }">
112
112
  <BaseBadge :contrast="option?.id ? 'high' : 'low'">
113
- {{ option.name }}
113
+ {{ label }}
114
114
  </BaseBadge>
115
115
  </template>
116
116
  </BaseDropdownAutocomplete>
@@ -120,8 +120,10 @@ export const AutocompleteFetch = (args) => ({
120
120
 
121
121
  AutocompleteFetch.args = {
122
122
  valueKey: "id",
123
- labelKey: "name",
124
- url: "https://effettandem.com/api/content/tags",
123
+ labelKey(option) {
124
+ return option.title + ' - ' + option.uuid;
125
+ },
126
+ url: "https://faker.witify.io/api/todos",
125
127
  multiple: false,
126
128
  };
127
129
 
@@ -200,7 +202,7 @@ export const TagAutocompleteFetch = (args) => ({
200
202
 
201
203
  TagAutocompleteFetch.args = {
202
204
  valueKey: "id",
203
- labelKey: "name",
204
- url: "https://effettandem.com/api/content/tags",
205
+ labelKey: "title",
206
+ url: "https://faker.witify.io/api/todos",
205
207
  multiple: true,
206
208
  };
@@ -38,14 +38,13 @@
38
38
  <div class="flex grow items-center">
39
39
  <slot
40
40
  name="option"
41
- :option="optionProps.option"
42
- :active="optionProps.active"
41
+ v-bind="optionProps"
43
42
  :size="size"
44
43
  />
45
44
  </div>
46
45
  <div class="shrink-0">
47
46
  <BaseIcon
48
- v-if="(optionProps.selected ?? false) || (optionProps.option[valueKey] == null && newValue == null)"
47
+ v-if="(optionProps.selected ?? false) || (optionProps.value == null && newValue == null)"
49
48
  icon="mdi:check"
50
49
  class="h-4 w-4 text-slate-500"
51
50
  />
@@ -90,11 +89,11 @@ const props = defineProps({
90
89
  },
91
90
  labelKey: {
92
91
  default: 'name',
93
- type: String,
92
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
94
93
  },
95
94
  valueKey: {
96
95
  default: 'id',
97
- type: String,
96
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
98
97
  },
99
98
  size: {
100
99
  type: String as PropType<'xs' | 'sm' | 'base'>,
@@ -191,15 +190,11 @@ function getNewValue(value: RawOption | RawOption[] | null | undefined) {
191
190
  return value;
192
191
  }
193
192
 
194
- if (value == null) {
193
+ if (!value) {
195
194
  return null;
196
195
  }
197
196
 
198
- if (value[props.valueKey] ?? null) {
199
- return value;
200
- }
201
-
202
- return null;
197
+ return value;
203
198
  }
204
199
 
205
200
  function update() {
@@ -2,8 +2,6 @@ import BaseHasMany from "./BaseHasMany.vue";
2
2
  import ShowValue from "@/../.storybook/components/ShowValue.vue";
3
3
  import { createFieldStory, options, sizes } from "../../.storybook/utils";
4
4
  import BaseAppSnackbars from "./BaseAppSnackbars.vue";
5
- import QueryString from "qs";
6
- import { random } from "lodash";
7
5
 
8
6
  export default {
9
7
  title: "Form/BaseHasMany",
@@ -43,6 +41,13 @@ const Template = (args) => {
43
41
  export const Demo = Template.bind({});
44
42
  Demo.args = {};
45
43
 
44
+ export const LabelFunction = Template.bind({});
45
+ LabelFunction.args = {
46
+ labelKey: (option) => {
47
+ return option.label + " (" + option.size + ")";
48
+ },
49
+ };
50
+
46
51
  export const Disabled = (args) => {
47
52
  return {
48
53
  components: { BaseHasMany, ShowValue },
@@ -66,7 +66,7 @@ const props = defineProps({
66
66
  },
67
67
  field: {
68
68
  required: true,
69
- type: String,
69
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
70
70
  },
71
71
  required: {
72
72
  default: false,
@@ -52,6 +52,13 @@ const Template = (args) => {
52
52
  export const Demo = Template.bind({});
53
53
  Demo.args = {};
54
54
 
55
+ export const LabelFunction = Template.bind({});
56
+ LabelFunction.args = {
57
+ labelKey: (option) => {
58
+ return option.name + " (" + option.uuid + ")";
59
+ },
60
+ };
61
+
55
62
  export const Disabled = (args) => {
56
63
  return {
57
64
  components: { BaseHasManyFetch, ShowValue },
@@ -40,6 +40,13 @@ const Template = (args) => ({
40
40
  export const Demo = Template.bind({});
41
41
  Demo.args = {};
42
42
 
43
+ export const LabelFunction = Template.bind({});
44
+ LabelFunction.args = {
45
+ labelKey: (option) => {
46
+ return option.label + " (" + option.size + ")";
47
+ },
48
+ };
49
+
43
50
  export const Max = Template.bind({});
44
51
  Max.args = {
45
52
  max: 3,
@@ -116,11 +116,11 @@ const props = defineProps({
116
116
  },
117
117
  labelKey: {
118
118
  required: true,
119
- type: String,
119
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
120
120
  },
121
121
  valueKey: {
122
122
  required: true,
123
- type: String,
123
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
124
124
  },
125
125
  name: {
126
126
  default: undefined,
@@ -41,6 +41,13 @@ const Template = (args) => {
41
41
  export const Demo = Template.bind({});
42
42
  Demo.args = {};
43
43
 
44
+ export const LabelFunction = Template.bind({});
45
+ LabelFunction.args = {
46
+ labelKey: (option) => {
47
+ return option.name + " (" + option.uuid + ")";
48
+ },
49
+ };
50
+
44
51
  export const Disabled = (args) => {
45
52
  return {
46
53
  components: { BaseTagAutocompleteFetch },
@@ -74,7 +74,7 @@ import { t } from '@/i18n';
74
74
  const props = defineProps({
75
75
  modelValue: {
76
76
  required: true,
77
- type: Array as PropType<RawOption[]>,
77
+ type: [Array, null] as PropType<RawOption[] | null>,
78
78
  },
79
79
  url: {
80
80
  required: true,
@@ -82,11 +82,11 @@ const props = defineProps({
82
82
  },
83
83
  labelKey: {
84
84
  required: true,
85
- type: String,
85
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
86
86
  },
87
87
  valueKey: {
88
88
  required: true,
89
- type: String,
89
+ type: [String, Function] as PropType<string | ((option: RawOption) => string)>,
90
90
  },
91
91
  placeholder: {
92
92
  default: undefined,
@@ -183,7 +183,8 @@ const search = () => {
183
183
  showLoading.value = true;
184
184
  firstSearch.value = true;
185
185
 
186
- requestId = uniqueId();
186
+ const requestIdInternal = uniqueId();
187
+ requestId = requestIdInternal;
187
188
 
188
189
  http
189
190
  .get(props.url, {
@@ -194,7 +195,7 @@ const search = () => {
194
195
  })
195
196
  .then((response: any) => {
196
197
 
197
- if (requestId != requestId) {
198
+ if (requestIdInternal !== requestId) {
198
199
  return;
199
200
  }
200
201
 
@@ -213,7 +214,7 @@ const search = () => {
213
214
  })
214
215
  .finally(() => {
215
216
 
216
- if (requestId != requestId) {
217
+ if (requestIdInternal !== requestId) {
217
218
  return;
218
219
  }
219
220
 
@@ -1,12 +1,12 @@
1
1
  import { Ref } from 'vue';
2
2
  import { NormalizedOption, RawOption } from '@/types';
3
- import { get, isArray, isObject } from 'lodash';
3
+ import { get, isArray, isFunction, isObject, isString } from 'lodash';
4
4
 
5
5
  export function useHasOptions(
6
6
  modelValue: Ref<RawOption[] | RawOption | null | undefined>,
7
7
  options: Ref<RawOption[]>,
8
- labelKey: Ref<string>,
9
- valueKey: Ref<string>,
8
+ labelKey: Ref<string | ((option: RawOption) => string)>,
9
+ valueKey: Ref<string | ((option: RawOption) => string | number)>,
10
10
  multiple: Ref<boolean> = ref(false)
11
11
  ) {
12
12
  const normalizedModelValue = computed(
@@ -15,10 +15,10 @@ export function useHasOptions(
15
15
  if (!isArray(modelValue.value)) {
16
16
  return [];
17
17
  }
18
- return modelValue.value.map((option) => {
18
+ return modelValue.value.map((option: RawOption) => {
19
19
  return {
20
- label: get(option, labelKey.value) as string,
21
- value: get(option, valueKey.value) as string | number,
20
+ label: getLabel(option),
21
+ value: getValue(option),
22
22
  option: option,
23
23
  } as NormalizedOption;
24
24
  });
@@ -28,8 +28,8 @@ export function useHasOptions(
28
28
  }
29
29
 
30
30
  return {
31
- label: get(modelValue.value, labelKey.value as never, '') as string,
32
- value: get(modelValue.value, valueKey.value as never) as string | number,
31
+ label: getLabel(modelValue.value),
32
+ value: getValue(modelValue.value),
33
33
  option: modelValue.value,
34
34
  } as NormalizedOption;
35
35
  }
@@ -39,8 +39,8 @@ export function useHasOptions(
39
39
  const normalizedOptions = computed((): NormalizedOption[] => {
40
40
  return options.value.map((option) => {
41
41
  return {
42
- label: get(option, labelKey.value, '') as string,
43
- value: get(option, valueKey.value) as string | number,
42
+ label: getLabel(option),
43
+ value: getValue(option),
44
44
  option: option,
45
45
  } as NormalizedOption;
46
46
  });
@@ -60,6 +60,24 @@ export function useHasOptions(
60
60
  return false;
61
61
  }
62
62
 
63
+ function getLabel(option: RawOption): string {
64
+ if (isFunction(labelKey.value)) {
65
+ return labelKey.value(option);
66
+ } else if (isString(labelKey.value)) {
67
+ return get(option, labelKey.value, '') as string;
68
+ }
69
+ return '';
70
+ }
71
+
72
+ function getValue(option: RawOption): string | number {
73
+ if (isFunction(valueKey.value)) {
74
+ return valueKey.value(option);
75
+ } else if (isString(valueKey.value)) {
76
+ return get(option, valueKey.value) as string | number;
77
+ }
78
+ return '';
79
+ }
80
+
63
81
  return {
64
82
  normalizedOptions,
65
83
  normalizedModelValue,
@@ -40,7 +40,7 @@ export type OptionValue = string | number | null;
40
40
  export type RawOption = Record<string, any>;
41
41
 
42
42
  export type NormalizedOption = {
43
- option: RawOption;
43
+ option: RawOption | null;
44
44
  value: OptionValue;
45
45
  label: string;
46
46
  };