sprintify-ui 0.0.77 → 0.0.79

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.
@@ -3,9 +3,19 @@ import ShowValue from '@/../.storybook/components/ShowValue.vue';
3
3
  import { options } from '@/../.storybook/utils';
4
4
  import { createFieldStory } from '../../.storybook/utils';
5
5
 
6
+ const sizes = ['xs', 'sm', 'base'];
7
+
6
8
  export default {
7
9
  title: 'Form/BaseBelongsTo',
8
10
  component: BaseBelongsTo,
11
+ argTypes: {
12
+ size: {
13
+ control: {
14
+ type: 'select',
15
+ options: sizes,
16
+ },
17
+ },
18
+ },
9
19
  args: {
10
20
  url: 'https://effettandem.com/api/content/articles',
11
21
  field: 'title',
@@ -28,6 +38,36 @@ const Template = (args) => ({
28
38
  export const Demo = Template.bind({});
29
39
  Demo.args = {};
30
40
 
41
+ export const AlwaysShowDropdown = Template.bind({});
42
+ AlwaysShowDropdown.args = {
43
+ inline: true,
44
+ dropdownShow: 'always',
45
+ };
46
+
47
+ export const NoFocus = Template.bind({});
48
+ NoFocus.args = {
49
+ visibleFocus: false,
50
+ };
51
+
52
+ export const Inline = Template.bind({});
53
+ Inline.args = {
54
+ inline: true,
55
+ };
56
+
57
+ export const Sizes = (args) => ({
58
+ components: { BaseBelongsTo },
59
+ setup() {
60
+ const value = ref(null);
61
+ return { args, sizes, value };
62
+ },
63
+ template: `
64
+ <div v-for="size in sizes" class="mb-1">
65
+ <p class="text-xs text-slate-600 leading-tight">{{ size }}</p>
66
+ <BaseBelongsTo v-model="value" v-bind="args" :size="size"></BaseBelongsTo>
67
+ </div>
68
+ `,
69
+ });
70
+
31
71
  export const Disabled = Template.bind({});
32
72
  Disabled.args = {
33
73
  currentModel: options[0],
@@ -9,6 +9,11 @@
9
9
  :value-key="primaryKey"
10
10
  :label-key="field"
11
11
  :has-error="hasError"
12
+ :inline="inline"
13
+ :size="size"
14
+ :dropdown-show="dropdownShow"
15
+ :model-value-show="modelValueShow"
16
+ :visible-focus="visibleFocus"
12
17
  @update:model-value="onUpdate"
13
18
  >
14
19
  <template #option="optionProps">
@@ -77,6 +82,26 @@ const props = defineProps({
77
82
  default: false,
78
83
  type: Boolean,
79
84
  },
85
+ inline: {
86
+ default: false,
87
+ type: Boolean,
88
+ },
89
+ size: {
90
+ default: 'base',
91
+ type: String as PropType<'xs' | 'sm' | 'base'>,
92
+ },
93
+ dropdownShow: {
94
+ default: 'focus',
95
+ type: String as PropType<'focus' | 'always'>,
96
+ },
97
+ modelValueShow: {
98
+ default: true,
99
+ type: Boolean,
100
+ },
101
+ visibleFocus: {
102
+ default: true,
103
+ type: Boolean,
104
+ },
80
105
  });
81
106
 
82
107
  const http = config.http;
@@ -519,7 +519,15 @@ function onRouteChange() {
519
519
  |--------------------------------------------------------------------------
520
520
  */
521
521
 
522
- function fetch(force = false) {
522
+ function fetchWithLoading(force = false) {
523
+ fetch(force, true);
524
+ }
525
+
526
+ function fetchWithoutLoading(force = false) {
527
+ fetch(force, false);
528
+ }
529
+
530
+ function fetch(force = false, showLoading = true) {
523
531
  const urlSplit = url.value.split(/[?#]/);
524
532
 
525
533
  const baseUrl = urlSplit[0];
@@ -540,7 +548,10 @@ function fetch(force = false) {
540
548
  return;
541
549
  }
542
550
 
543
- loading.value = true;
551
+ if (showLoading) {
552
+ loading.value = true;
553
+ }
554
+
544
555
  lastUrl = fullUrl;
545
556
 
546
557
  http
@@ -685,6 +696,8 @@ onMounted(() => {
685
696
 
686
697
  defineExpose({
687
698
  fetch,
699
+ fetchWithLoading,
700
+ fetchWithoutLoading,
688
701
  scrollIntoView,
689
702
  query,
690
703
  });
@@ -1,10 +1,13 @@
1
+ import BaseBadge from './BaseBadge.vue';
2
+ import BaseAutocomplete from './BaseAutocomplete.vue';
1
3
  import BaseDropdown from './BaseDropdown.vue';
4
+ import { options } from '../../.storybook/utils';
2
5
 
3
6
  export default {
4
7
  title: 'Components/BaseDropdown',
5
8
  component: BaseDropdown,
6
9
  args: {
7
- placement: 'top-start',
10
+ placement: 'bottom-start',
8
11
  offset: [0, 8],
9
12
  },
10
13
  };
@@ -15,8 +18,7 @@ const Template = (args) => ({
15
18
  return { args };
16
19
  },
17
20
  template: `
18
- <div style="height: 2000px">
19
- <BaseDropdown v-bind="args" style="margin-top: 200px;">
21
+ <BaseDropdown v-bind="args">
20
22
  <template #button>
21
23
  <div class="btn btn-primary">Click me</div>
22
24
  </template>
@@ -28,9 +30,73 @@ const Template = (args) => ({
28
30
  </div>
29
31
  </template>
30
32
  </BaseDropdown>
31
- </div>
32
33
  `,
33
34
  });
34
35
 
35
36
  export const Demo = Template.bind({});
36
- Demo.args = {};
37
+
38
+ export const Animated = Template.bind({});
39
+ Animated.args = {
40
+ animated: true,
41
+ };
42
+
43
+ export const WithAutocomplete = (args) => ({
44
+ components: { BaseDropdown, BaseAutocomplete, BaseBadge },
45
+ setup() {
46
+ const value = ref(null);
47
+ const autocomplete = ref(null);
48
+
49
+ function onOpen() {
50
+ if (autocomplete.value) {
51
+ setTimeout(() => {
52
+ autocomplete.value.open();
53
+ }, 1);
54
+ }
55
+ }
56
+
57
+ function onClose() {
58
+ if (autocomplete.value) {
59
+ setTimeout(() => {
60
+ autocomplete.value.setKeywords('');
61
+ }, 10);
62
+ }
63
+ }
64
+
65
+ function onUpdate(v, close) {
66
+ if (v) {
67
+ close();
68
+ }
69
+ }
70
+ return { args, options, value, onOpen, onClose, onUpdate, autocomplete };
71
+ },
72
+ template: `
73
+ <BaseDropdown @open="onOpen" @close="onClose" v-bind="args">
74
+ <template #button>
75
+ <BaseBadge>{{ value ? value.label : 'Select a Character' }}</BaseBadge>
76
+ </template>
77
+ <template #dropdown="{close}">
78
+ <div class="bg-white shadow border border-slate-300 py-1 px-1 rounded" style="min-width: 250px">
79
+ <BaseAutocomplete
80
+ ref="autocomplete"
81
+ required
82
+ v-model="value"
83
+ label-key="label"
84
+ value-key="value"
85
+ size="xs"
86
+ :options="options"
87
+ :inline="true"
88
+ :visibleFocus="false"
89
+ dropdownShow="always"
90
+ :modelValueShow="false"
91
+ @update:modelValue="onUpdate($event, close)"
92
+ ></BaseAutocomplete>
93
+ </div>
94
+ </template>
95
+ </BaseDropdown>
96
+ `,
97
+ });
98
+
99
+ WithAutocomplete.args = {
100
+ placement: 'bottom-start',
101
+ offset: [0, 3],
102
+ };
@@ -1,10 +1,28 @@
1
1
  <template>
2
2
  <div>
3
- <button ref="button" type="button" @click="showDropdown = !showDropdown">
3
+ <button ref="button" type="button" @click="toggle()">
4
4
  <slot name="button"></slot>
5
5
  </button>
6
- <div v-show="showDropdown" ref="dropdown">
7
- <slot name="dropdown"></slot>
6
+ <div ref="dropdown" class="z-menu">
7
+ <Transition
8
+ :enter-active-class="
9
+ animated ? 'duration-100 transition ease-out' : ''
10
+ "
11
+ enter-from-class="transform scale-90 opacity-0"
12
+ enter-to-class="transform scale-100 opacity-100"
13
+ :leave-active-class="animated ? 'duration-75 transition ease-in' : ''"
14
+ leave-from-class="transform scale-100 opacity-100"
15
+ leave-to-class="transform scale-90 opacity-0"
16
+ >
17
+ <div v-show="showDropdown" ref="dropdown" class="inline-block">
18
+ <slot
19
+ name="dropdown"
20
+ :close="close"
21
+ :open="open"
22
+ :toggle="toggle"
23
+ ></slot>
24
+ </div>
25
+ </Transition>
8
26
  </div>
9
27
  </div>
10
28
  </template>
@@ -31,8 +49,14 @@ const props = defineProps({
31
49
  },
32
50
  type: Array as unknown as PropType<[number, number]>,
33
51
  },
52
+ animated: {
53
+ default: false,
54
+ type: Boolean,
55
+ },
34
56
  });
35
57
 
58
+ const emit = defineEmits(['close', 'open']);
59
+
36
60
  onMounted(() => {
37
61
  if (button.value && dropdown.value) {
38
62
  createPopper(button.value, dropdown.value, {
@@ -48,4 +72,73 @@ onMounted(() => {
48
72
  });
49
73
  }
50
74
  });
75
+
76
+ function toggle() {
77
+ if (showDropdown.value) {
78
+ close();
79
+ } else {
80
+ open();
81
+ }
82
+ }
83
+
84
+ function open() {
85
+ activate();
86
+ showDropdown.value = true;
87
+ emit('open');
88
+ }
89
+
90
+ function close() {
91
+ deactivate();
92
+ showDropdown.value = false;
93
+ emit('close');
94
+ }
95
+
96
+ function activate() {
97
+ window.addEventListener('keydown', onKeydown);
98
+ window.addEventListener('mousedown', onMouseDown);
99
+ }
100
+
101
+ function deactivate() {
102
+ window.removeEventListener('keydown', onKeydown);
103
+ window.removeEventListener('mousedown', onMouseDown);
104
+ }
105
+
106
+ function onKeydown(event: KeyboardEvent) {
107
+ if (event.code == 'Escape') {
108
+ if (showDropdown.value) {
109
+ close();
110
+ }
111
+ }
112
+ }
113
+
114
+ function onMouseDown(event: MouseEvent) {
115
+ if (!dropdown.value) {
116
+ return;
117
+ }
118
+ // Get the element that was clicked
119
+ const clickedElement = event.target as HTMLElement | null;
120
+
121
+ if (!clickedElement) {
122
+ return;
123
+ }
124
+
125
+ // Button is clicked
126
+ if (
127
+ button.value == clickedElement ||
128
+ button.value?.contains(clickedElement)
129
+ ) {
130
+ return;
131
+ }
132
+
133
+ // `el` is the element you're detecting clicks outside of
134
+ if (dropdown.value.contains(clickedElement)) {
135
+ // do nothing..
136
+ } else {
137
+ close();
138
+ }
139
+ }
140
+
141
+ onBeforeUnmount(() => {
142
+ deactivate();
143
+ });
51
144
  </script>