@veritree/ui 0.39.2 → 0.39.3

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.
@@ -245,8 +245,10 @@ export const floatingUiItemMixin = {
245
245
  return;
246
246
  }
247
247
 
248
- // unselect all items before selecting new item
249
- this.items.forEach((item) => item.unselect());
248
+ // unselect all items before selecting new one
249
+ for (const item of this.items) {
250
+ item.unselect();
251
+ }
250
252
 
251
253
  /**
252
254
  * Select item passing the event type to decide if
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veritree/ui",
3
- "version": "0.39.2",
3
+ "version": "0.39.3",
4
4
  "description": "veritree ui library",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -47,6 +47,7 @@
47
47
  headless && busy ? 'button--busy' : busy ? 'invisible' : null,
48
48
  ]"
49
49
  >
50
+ <!-- @slot Use this slot for the button content -->
50
51
  <slot></slot>
51
52
  </span>
52
53
  </component>
@@ -55,36 +56,98 @@
55
56
  <script>
56
57
  import VTSpinner from '../Spinner/VTSpinner.vue';
57
58
 
59
+ /**
60
+ * The veritree button.
61
+ * @displayName VTButton
62
+ */
58
63
  export default {
59
64
  name: 'VTButton',
60
65
 
61
66
  components: { VTSpinner },
62
67
 
63
68
  props: {
69
+ /**
70
+ * Specifies the visual style variant of the button
71
+ *
72
+ * @values
73
+ * - 'primary': The default primary style for the button
74
+ * - 'secondary': A secondary style for the button
75
+ * - 'tertiary': A tertiary style for the button
76
+ */
64
77
  variant: {
65
78
  type: String,
66
79
  default: 'primary',
67
80
  },
81
+
82
+ /**
83
+ * Specifies the size of the button
84
+ *
85
+ * @values
86
+ * - 'small': A smaller size for the button
87
+ * - 'large': A larger size for the button
88
+ */
68
89
  size: {
69
90
  type: String,
70
91
  default: 'large',
71
92
  },
93
+
94
+ /**
95
+ * Specifies the target URL of the button when clicked, using Vue Router's syntax for dynamic routes.
96
+ * @values
97
+ *
98
+ * - String: A static URL string
99
+ * - Object: A Vue Router route object
100
+ * - null: The button will not be clickable
101
+ */
102
+
72
103
  to: {
73
104
  type: [String, Object],
74
105
  default: null,
75
106
  },
107
+
108
+ /**
109
+ * Specifies the target URL of the button when clicked, using standard URL syntax.
110
+ * @values
111
+ *
112
+ * - String: A static URL string
113
+ * - Object: An object to be serialized into URL parameters
114
+ * - null: The button will not be clickable
115
+ */
76
116
  href: {
77
117
  type: [String, Object],
78
118
  default: null,
79
119
  },
120
+
121
+ /**
122
+ * Determines whether the button will use its default atomic style (tailwind) or its default class
123
+ *
124
+ * @values
125
+ * - true: The button will have no default style and can be fully customized with a custom class
126
+ * - false: The button will use its default atomic style (tailwind) and can be further customized with additional classes
127
+ */
80
128
  headless: {
81
129
  type: Boolean,
82
130
  default: false,
83
131
  },
132
+
133
+ /**
134
+ * Determines whether the button is currently in a loading or processing state
135
+ *
136
+ * @values
137
+ * - true: The button is in a loading or processing state and should not be interacted with until the processing is complete
138
+ * - false: The button is not in a loading or processing state and can be interacted with as usual
139
+ */
140
+
84
141
  busy: {
85
142
  type: Boolean,
86
143
  default: false,
87
144
  },
145
+
146
+ /**
147
+ * Determines whether the button is disabled or not
148
+ *
149
+ * @values true, false
150
+ */
88
151
  disabled: {
89
152
  type: Boolean,
90
153
  default: false,
@@ -7,6 +7,7 @@
7
7
  ? 'dialog-header'
8
8
  : '-mx-4 -mt-4 flex items-center justify-between gap-x-3 p-4 md:-mx-6 md:-mt-6 md:p-6',
9
9
  ]"
10
+ @click.stop
10
11
  >
11
12
  <slot></slot>
12
13
  </component>
@@ -16,16 +16,39 @@ export default {
16
16
  provide() {
17
17
  return {
18
18
  apiListbox: () => {
19
+ const $mutable = {};
20
+
21
+ // Used to get and update the value computed
22
+ // that will then emit the value up to the
23
+ // parent component
24
+ Object.defineProperty($mutable, 'valueComputed', {
25
+ enumerable: true,
26
+ get: () => this.valueComputed,
27
+ set: (value) => (this.valueComputed = value),
28
+ });
29
+
30
+ /**
31
+ * This function registers a trigger by setting its value to the componentTrigger property of the current object.
32
+ * @param {VueComponent} trigger - The trigger to be registered.
33
+ */
19
34
  const registerTrigger = (trigger) => {
20
35
  if (!trigger) return;
21
36
  this.componentTrigger = trigger;
22
37
  };
23
38
 
39
+ /**
40
+ * Registers content to be used in the children components by setting its value to the componentContent property of the current object.
41
+ * @param {any} content - The content to be registered.
42
+ */
24
43
  const registerContent = (content) => {
25
44
  if (!content) return;
26
45
  this.componentContent = content;
27
46
  };
28
47
 
48
+ /**
49
+ * Registers search to be used in the children components by setting its value to the componentSearch property of the current object.
50
+ * @param {any} search - The search to be registered.
51
+ */
29
52
  const registerSearch = (search) => {
30
53
  if (!search) return;
31
54
  this.componentSearch = search;
@@ -52,8 +75,7 @@ export default {
52
75
  };
53
76
 
54
77
  const emit = (value) => {
55
- this.$emit('input', value);
56
- this.$emit('change', value);
78
+ this.valueComputed = value;
57
79
  };
58
80
 
59
81
  return {
@@ -63,8 +85,9 @@ export default {
63
85
  componentContent: this.componentContent,
64
86
  componentSearch: this.componentSearch,
65
87
  items: this.items,
88
+ multiple: this.multiple,
66
89
  search: this.search,
67
- selectedValue: this.value,
90
+ $mutable,
68
91
  registerTrigger,
69
92
  registerContent,
70
93
  registerSearch,
@@ -79,22 +102,55 @@ export default {
79
102
  },
80
103
 
81
104
  props: {
105
+ /**
106
+ * The value of the component. Can be a string, number, object, or array.
107
+ * @type {string|number|object|array}
108
+ * @default null
109
+ */
82
110
  value: {
83
- type: [String, Number, Object],
111
+ type: [String, Number, Object, Array],
84
112
  default: null,
85
113
  },
114
+ /**
115
+ * Determines whether the button will use its default atomic style (tailwind) or its default class
116
+ * @type {boolean}
117
+ * @values
118
+ * - true: The button will have no default style and can be fully customized with a custom class
119
+ * - false: The button will use its default atomic style (tailwind) and can be further customized with additional classes
120
+ * @default null
121
+ */
86
122
  headless: {
87
123
  type: Boolean,
88
124
  default: false,
89
125
  },
126
+ /**
127
+ * The placement of the component relative to its trigger element.
128
+ * @type {string}
129
+ * @values 'top', 'top-start', 'top-end', 'bottom', 'bottom-start', 'bottom-end', 'left', 'left-start', 'left-end', 'right', 'right-start', 'right-end'
130
+ * @default 'bottom-start'
131
+ */
90
132
  placement: {
91
133
  type: String,
92
134
  default: 'bottom-start',
93
135
  },
136
+ /**
137
+ * Determines whether the component should be aligned to the right of its trigger element.
138
+ * @type {boolean}
139
+ * @default false
140
+ */
94
141
  right: {
95
142
  type: Boolean,
96
143
  default: false,
97
144
  },
145
+ /**
146
+ * Determines whether the component should allow multiple selections.
147
+ * @type {boolean}
148
+ * @default false
149
+ */
150
+ multiple: {
151
+ type: Boolean,
152
+ default: false,
153
+ },
98
154
  },
99
155
 
100
156
  data() {
@@ -103,6 +159,7 @@ export default {
103
159
  componentSearch: null,
104
160
  search: '',
105
161
  items: [],
162
+ itemsChecked: [],
106
163
  /**
107
164
  * Explaining the need for the floatingUiMinWidth data
108
165
  *
@@ -125,6 +182,16 @@ export default {
125
182
  id() {
126
183
  return `listbox-${this.componentId}`;
127
184
  },
185
+
186
+ valueComputed: {
187
+ get() {
188
+ return this.value;
189
+ },
190
+ set(newValue) {
191
+ this.$emit('input', newValue);
192
+ this.$emit('change', newValue);
193
+ },
194
+ },
128
195
  },
129
196
  };
130
197
  </script>
@@ -16,9 +16,16 @@
16
16
  @keydown.enter.prevent="onClick"
17
17
  @keydown.tab.prevent
18
18
  >
19
- <!-- <span v-if="multiple">
20
- <input type="radio" v-model="options" :value="value" />
21
- </span> -->
19
+ <span v-if="apiListbox().multiple">
20
+ <input
21
+ v-model="apiListbox().$mutable.valueComputed"
22
+ :id="`${id}-checkbox`"
23
+ :value="value"
24
+ type="checkbox"
25
+ @click.stop
26
+ @change="onChange"
27
+ />
28
+ </span>
22
29
  <slot></slot>
23
30
  <span v-if="wasSelected" class="ml-auto">
24
31
  <IconCheckOutline class="text-secondary-200 h-5 w-5" />
@@ -53,7 +60,6 @@ export default {
53
60
  // apiInjected is used in the mixin floating-ui-item
54
61
  apiInjected: this.apiListbox,
55
62
  componentName: 'listbox-item',
56
- options: [],
57
63
  };
58
64
  },
59
65
 
@@ -79,7 +85,7 @@ export default {
79
85
  wasSelected() {
80
86
  return (
81
87
  JSON.stringify(this.value) ===
82
- JSON.stringify(this.apiListbox().selectedValue)
88
+ JSON.stringify(this.apiListbox().$mutable.valueComputed)
83
89
  );
84
90
  },
85
91
  },
@@ -1,10 +1,9 @@
1
1
  <template>
2
2
  <component
3
3
  :is="as"
4
- :class="{
5
- ListboxLabel: headless,
6
- 'mb-2 block text-xs font-normal uppercase': !headless,
7
- }"
4
+ :class="[
5
+ headless ? 'listbox-label' : 'mb-2 block text-xs font-normal uppercase',
6
+ ]"
8
7
  >
9
8
  <slot></slot>
10
9
  </component>
@@ -123,6 +123,7 @@ export default {
123
123
 
124
124
  onClick(e) {
125
125
  this.init(e);
126
+ this.$emit('click');
126
127
  },
127
128
 
128
129
  onKeyDownOrUp(e) {