@tak-ps/vue-tabler 3.78.2 → 3.79.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.
@@ -106,7 +106,8 @@
106
106
  </div>
107
107
  </template>
108
108
 
109
- <script>
109
+ <script setup>
110
+ import { ref, watch, onMounted } from 'vue'
110
111
  import TablerInput from './input/Input.vue';
111
112
  import TablerToggle from './input/Toggle.vue';
112
113
  import TablerEnum from './input/Enum.vue';
@@ -116,83 +117,63 @@ import {
116
117
  IconTrash,
117
118
  } from '@tabler/icons-vue';
118
119
 
119
- export default {
120
- name: 'TablerSchema',
121
- components: {
122
- IconPlus,
123
- IconTrash,
124
- TablerInput,
125
- TablerToggle,
126
- TablerEnum,
127
- TablerLoading
120
+ const props = defineProps({
121
+ modelValue: {
122
+ type: Object,
123
+ required: true
128
124
  },
129
- props: {
130
- modelValue: {
131
- type: Object,
132
- required: true
133
- },
134
- schema: {
135
- type: Object,
136
- required: true
137
- },
138
- disabled: {
139
- type: Boolean,
140
- default: false
141
- }
142
- },
143
- emits: [
144
- 'update:modelValue'
145
- ],
146
- data: function() {
147
- return {
148
- loading: true,
149
- s: {},
150
- data: {},
151
- };
152
- },
153
- watch: {
154
- data: {
155
- deep: true,
156
- handler: function() {
157
- this.$emit('update:modelValue', this.data);
158
- }
159
- },
125
+ schema: {
126
+ type: Object,
127
+ required: true
160
128
  },
161
- mounted: async function() {
162
- this.loading = true;
163
- this.data = JSON.parse(JSON.stringify(this.modelValue));
164
- this.s = JSON.parse(JSON.stringify(this.schema));
129
+ disabled: {
130
+ type: Boolean,
131
+ default: false
132
+ }
133
+ })
165
134
 
166
- if (this.s.type === 'object' && this.s.properties) {
167
- for (const req of (this.s.required || [])) {
168
- this.s.properties[req].required = true;
169
- }
135
+ const emit = defineEmits(['update:modelValue'])
170
136
 
171
- for (const key in this.s.properties) {
172
- if (!this.data[key] && this.s.properties[key].type === 'array') {
173
- this.data[key] = [];
174
- }
175
- }
137
+ const loading = ref(true)
138
+ const s = ref({})
139
+ const data = ref({})
140
+
141
+ const push = (key) => {
142
+ if (!props.schema.properties[key].items) data.value[key].push('');
143
+ if (props.schema.properties[key].items.type === 'object') {
144
+ data.value[key].push({});
145
+ } else if (props.schema.properties[key].items.type === 'array') {
146
+ data.value[key].push([]);
147
+ } else if (props.schema.properties[key].items.type === 'boolean') {
148
+ data.value[key].push(false);
149
+ } else {
150
+ data.value[key].push('');
151
+ }
152
+ }
153
+
154
+ // Watch for data changes
155
+ watch(data, () => {
156
+ emit('update:modelValue', data.value);
157
+ }, { deep: true })
158
+
159
+ // Mounted lifecycle
160
+ onMounted(async () => {
161
+ loading.value = true;
162
+ data.value = JSON.parse(JSON.stringify(props.modelValue));
163
+ s.value = JSON.parse(JSON.stringify(props.schema));
164
+
165
+ if (s.value.type === 'object' && s.value.properties) {
166
+ for (const req of (s.value.required || [])) {
167
+ s.value.properties[req].required = true;
176
168
  }
177
169
 
178
- this.loading = false;
179
- },
180
- methods: {
181
- remove: function(key, arr, i) {
182
- this.data[key].splice(i, 1)
183
- },
184
- push: function(key) {
185
- if (!this.schema.properties[key].items) this.data[key].push('');
186
- if (this.schema.properties[key].items.type === 'object') {
187
- this.data[key].push({});
188
- } else if (this.schema.properties[key].items.type === 'array') {
189
- this.data[key].push([]);
190
- } else if (this.schema.properties[key].items.type === 'boolean') {
191
- this.data[key].push(false);
192
- } else {
193
- this.data[key].push('');
170
+ for (const key in s.value.properties) {
171
+ if (!data.value[key] && s.value.properties[key].type === 'array') {
172
+ data.value[key] = [];
194
173
  }
195
174
  }
196
175
  }
197
- }
176
+
177
+ loading.value = false;
178
+ })
198
179
  </script>
@@ -0,0 +1,109 @@
1
+ <template>
2
+ <div
3
+ class='hover-expandable rounded position-relative px-2 py-2'
4
+ :class='{ &apos;is-expanded&apos;: isExpanded }'
5
+ >
6
+ <div class='mb-2'>
7
+ <slot />
8
+ </div>
9
+
10
+ <div
11
+ ref='contentWrapperRef'
12
+ class='expandable-content-wrapper'
13
+ >
14
+ <div class='expandable-content-inner p-3'>
15
+ <slot name='expanded' />
16
+ </div>
17
+ </div>
18
+
19
+ <div
20
+ class='arrow-container'
21
+ title='Toggle content'
22
+ @click='toggle'
23
+ >
24
+ <IconChevronDown
25
+ size='24'
26
+ stroke='1.5'
27
+ class='arrow'
28
+ :class='{ &apos;expanded&apos;: isExpanded }'
29
+ />
30
+ </div>
31
+ </div>
32
+ </template>
33
+
34
+ <script setup>
35
+ import { ref } from 'vue';
36
+ import {
37
+ IconChevronDown
38
+ } from '@tabler/icons-vue';
39
+
40
+ const isExpanded = ref(false);
41
+
42
+ const contentWrapperRef = ref(null);
43
+
44
+ function toggle() {
45
+ isExpanded.value = !isExpanded.value;
46
+ const el = contentWrapperRef.value;
47
+
48
+ if (el) {
49
+ if (isExpanded.value) {
50
+ el.style.maxHeight = el.scrollHeight + 'px';
51
+ } else {
52
+ el.style.maxHeight = null;
53
+ }
54
+ }
55
+ };
56
+ </script>
57
+
58
+ <style scoped>
59
+ .hover-expandable {
60
+ border: 1px solid var(--tblr-border-color);
61
+ transition: border-color 0.2s ease;
62
+ }
63
+
64
+ .hover-expandable:not(.is-expanded):hover {
65
+ border: 1px solid color-mix(in srgb, var(--tblr-border-color), white 25%);
66
+ }
67
+
68
+ .hover-expandable:not(.is-expanded):hover .arrow-container {
69
+ border-color: var(--tblr-primary-rgb);
70
+ }
71
+
72
+ .hover-expandable:not(.is-expanded):hover .arrow {
73
+ color: var(--tblr-secondary-color, white);
74
+ }
75
+
76
+ .expandable-content-wrapper {
77
+ max-height: 0;
78
+ overflow: hidden;
79
+ transition: max-height 0.3s ease-out;
80
+ }
81
+
82
+ .arrow-container {
83
+ border: 1px solid var(--tblr-border-color);
84
+ border-radius: 50%;
85
+ background-color: var(--tblr-border-color);
86
+ color: var(--tblr-body-color);
87
+ position: absolute;
88
+ bottom: -12px;
89
+ left: 50%;
90
+ transform: translateX(-50%);
91
+ width: 24px;
92
+ height: 24px;
93
+ display: flex;
94
+ align-items: center;
95
+ justify-content: center;
96
+ cursor: pointer;
97
+ transition: background-color 0.2s ease, border-color 0.2s ease;
98
+ }
99
+
100
+ .arrow {
101
+ transition: transform 0.3s ease-out, color 0.2s ease;
102
+ }
103
+
104
+ .arrow.expanded {
105
+ transform: rotate(180deg);
106
+ }
107
+ </style>
108
+
109
+
@@ -36,90 +36,89 @@
36
36
  </div>
37
37
  </template>
38
38
 
39
- <script>
40
- import TablerLabel from '../internal/Label.vue';
39
+ <script setup>
40
+ import { ref, watch, onMounted } from 'vue'
41
+ import TablerLabel from '../internal/Label.vue'
41
42
 
42
- export default {
43
- name: 'TablerColour',
44
- components: {
45
- TablerLabel
43
+ const props = defineProps({
44
+ modelValue: {
45
+ type: String,
46
+ required: true
46
47
  },
47
- props: {
48
- modelValue: {
49
- type: String,
50
- required: true
51
- },
52
- autofocus: {
53
- type: Boolean,
54
- default: false
55
- },
56
- default: {
57
- type: String,
58
- required: false
59
- },
60
- required: {
61
- type: Boolean,
62
- required: false
63
- },
64
- description: {
65
- type: String,
66
- required: false
67
- },
68
- disabled: {
69
- type: Boolean,
70
- default: false,
71
- },
72
- label: String,
48
+ autofocus: {
49
+ type: Boolean,
50
+ default: false
73
51
  },
74
- emits: [
75
- 'blur', 'update:modelValue'
76
- ],
77
- data: function() {
78
- return {
79
- current: '',
80
- invertColours: {
81
- '#1d273b': 'dark',
82
- '#ffffff': 'white',
83
- '#206bc4': 'blue',
84
- '#4299e1': 'azure',
85
- '#4263eb': 'indigo',
86
- '#ae3ec9': 'purple',
87
- '#d6336c': 'pink',
88
- '#d63939': 'red',
89
- '#f76707': 'orange',
90
- '#f59f00': 'yellow',
91
- '#74b816': 'lime'
92
- },
93
- colours: {
94
- dark: '#1d273b',
95
- white: '#ffffff',
96
- blue: '#206bc4',
97
- azure: '#4299e1',
98
- indigo: '#4263eb',
99
- purple: '#ae3ec9',
100
- pink: '#d6336c',
101
- red: '#d63939',
102
- orange: '#f76707',
103
- yellow: '#f59f00',
104
- lime: '#74b816'
105
- }
106
- }
52
+ default: {
53
+ type: String,
54
+ default: ''
107
55
  },
108
- watch: {
109
- modelValue: function() {
110
- this.current = this.invertColours[this.modelValue];
111
- },
112
- current: function() {
113
- if (this.colours[this.current] === this.modelValue) return;
114
- this.$emit('update:modelValue', this.colours[this.current]);
115
- }
56
+ required: {
57
+ type: Boolean,
58
+ default: false
116
59
  },
117
- mounted: function() {
118
- if (!this.modelValue && this.default) {
119
- this.current = this.invertColours[this.default]
120
- } else {
121
- this.current = this.invertColours[this.modelValue];
122
- }
123
- }
60
+ description: {
61
+ type: String,
62
+ default: ''
63
+ },
64
+ disabled: {
65
+ type: Boolean,
66
+ default: false,
67
+ },
68
+ label: {
69
+ type: String,
70
+ default: ''
71
+ },
72
+ })
73
+
74
+ const emit = defineEmits([
75
+ 'blur', 'update:modelValue'
76
+ ])
77
+
78
+ const current = ref('')
79
+
80
+ const invertColours = {
81
+ '#1d273b': 'dark',
82
+ '#ffffff': 'white',
83
+ '#206bc4': 'blue',
84
+ '#4299e1': 'azure',
85
+ '#4263eb': 'indigo',
86
+ '#ae3ec9': 'purple',
87
+ '#d6336c': 'pink',
88
+ '#d63939': 'red',
89
+ '#f76707': 'orange',
90
+ '#f59f00': 'yellow',
91
+ '#74b816': 'lime'
124
92
  }
93
+
94
+ const colours = {
95
+ dark: '#1d273b',
96
+ white: '#ffffff',
97
+ blue: '#206bc4',
98
+ azure: '#4299e1',
99
+ indigo: '#4263eb',
100
+ purple: '#ae3ec9',
101
+ pink: '#d6336c',
102
+ red: '#d63939',
103
+ orange: '#f76707',
104
+ yellow: '#f59f00',
105
+ lime: '#74b816'
106
+ }
107
+
108
+ watch(() => props.modelValue, (newValue) => {
109
+ current.value = invertColours[newValue]
110
+ })
111
+
112
+ watch(current, (newValue) => {
113
+ if (colours[newValue] === props.modelValue) return
114
+ emit('update:modelValue', colours[newValue])
115
+ })
116
+
117
+ onMounted(() => {
118
+ if (!props.modelValue && props.default) {
119
+ current.value = invertColours[props.default]
120
+ } else {
121
+ current.value = invertColours[props.modelValue]
122
+ }
123
+ })
125
124
  </script>
@@ -27,70 +27,64 @@
27
27
  </div>
28
28
  </template>
29
29
 
30
- <script>
31
- import TablerLabel from '../internal/Label.vue';
30
+ <script setup>
31
+ import { ref, watch } from 'vue'
32
+ import TablerLabel from '../internal/Label.vue'
32
33
 
33
- export default {
34
- name: 'TablerEnum',
35
- components: {
36
- TablerLabel
34
+ const props = defineProps({
35
+ modelValue: {
36
+ type: String,
37
+ required: true
37
38
  },
38
- props: {
39
- modelValue: {
40
- type: String,
41
- required: true
42
- },
43
- autofocus: {
44
- type: Boolean,
45
- default: false
46
- },
47
- default: {
48
- type: String,
49
- required: false
50
- },
51
- required: {
52
- type: Boolean,
53
- required: false
54
- },
55
- description: {
56
- type: String,
57
- required: false
58
- },
59
- options: {
60
- type: Array,
61
- required: true
62
- },
63
- disabled: {
64
- type: Boolean,
65
- default: false,
66
- },
67
- label: String,
39
+ autofocus: {
40
+ type: Boolean,
41
+ default: false
68
42
  },
69
- emits: [
70
- 'blur',
71
- 'update:modelValue'
72
- ],
73
- data: function() {
74
- const data = {
75
- current: ''
76
- }
43
+ default: {
44
+ type: String,
45
+ default: ''
46
+ },
47
+ required: {
48
+ type: Boolean,
49
+ default: false
50
+ },
51
+ description: {
52
+ type: String,
53
+ default: ''
54
+ },
55
+ options: {
56
+ type: Array,
57
+ required: true
58
+ },
59
+ disabled: {
60
+ type: Boolean,
61
+ default: false,
62
+ },
63
+ label: {
64
+ type: String,
65
+ default: ''
66
+ },
67
+ })
77
68
 
78
- if (!this.modelValue && this.default) {
79
- data.current = this.default
80
- } else {
81
- data.current = this.modelValue;
82
- }
69
+ const emit = defineEmits([
70
+ 'blur',
71
+ 'update:modelValue'
72
+ ])
83
73
 
84
- return data;
85
- },
86
- watch: {
87
- modelValue: function() {
88
- this.current = this.modelValue;
89
- },
90
- current: function() {
91
- if (this.current === this.modelValue) return;
92
- this.$emit('update:modelValue', this.current);
93
- }
94
- }
74
+ // Initialize current value
75
+ const current = ref('')
76
+ if (!props.modelValue && props.default) {
77
+ current.value = props.default
78
+ } else {
79
+ current.value = props.modelValue
95
80
  }
81
+
82
+ watch(() => props.modelValue, (newValue) => {
83
+ current.value = newValue
84
+ })
85
+
86
+ watch(current, (newValue) => {
87
+ if (newValue === props.modelValue) return
88
+ emit('update:modelValue', newValue)
89
+ })
96
90
  </script>
@@ -41,63 +41,66 @@
41
41
  </div>
42
42
  </template>
43
43
 
44
- <script>
45
- import TablerLabel from '../internal/Label.vue';
44
+ <script setup>
45
+ import { ref, computed, onMounted } from 'vue'
46
+ import TablerLabel from '../internal/Label.vue'
46
47
 
47
- export default {
48
- name: 'TablerFileInput',
49
- components: {
50
- TablerLabel
48
+ const props = defineProps({
49
+ modelValue: {
50
+ type: [String, Number],
51
+ required: true
51
52
  },
52
- props: {
53
- modelValue: {
54
- type: [String, Number],
55
- required: true
56
- },
57
- autofocus: {
58
- type: Boolean,
59
- default: false
60
- },
61
- loading: {
62
- type: Boolean,
63
- default: false
64
- },
65
- required: {
66
- type: Boolean,
67
- default: false,
68
- },
69
- disabled: {
70
- type: Boolean,
71
- default: false,
72
- },
73
- accept: {
74
- type: String,
75
- },
76
- description: {
77
- type: String,
78
- default: '',
79
- },
80
- label: String,
81
- placeholder: String,
82
- error: String,
53
+ autofocus: {
54
+ type: Boolean,
55
+ default: false
83
56
  },
84
- emits: ['blur', 'change'],
85
- data: function() {
86
- return {
87
- help: false,
88
- internal_error: '',
89
- }
57
+ loading: {
58
+ type: Boolean,
59
+ default: false
90
60
  },
91
- computed: {
92
- errorstr: function() {
93
- if (this.error) return this.error;
94
- return this.internal_error;
95
- },
61
+ required: {
62
+ type: Boolean,
63
+ default: false,
96
64
  },
97
- mounted: function() {
98
- if (this.autofocus) {
99
- this.$refs['text-input'].focus();
100
- }
65
+ disabled: {
66
+ type: Boolean,
67
+ default: false,
68
+ },
69
+ accept: {
70
+ type: String,
71
+ default: ''
72
+ },
73
+ description: {
74
+ type: String,
75
+ default: '',
76
+ },
77
+ label: {
78
+ type: String,
79
+ default: ''
80
+ },
81
+ placeholder: {
82
+ type: String,
83
+ default: ''
84
+ },
85
+ error: {
86
+ type: String,
87
+ default: ''
88
+ },
89
+ })
90
+
91
+ defineEmits(['blur', 'change'])
92
+
93
+ const textInput = ref(null)
94
+ const internal_error = ref('')
95
+
96
+ const errorstr = computed(() => {
97
+ if (props.error) return props.error
98
+ return internal_error.value
99
+ })
100
+
101
+ onMounted(() => {
102
+ if (props.autofocus) {
103
+ textInput.value.focus()
101
104
  }
102
- }
105
+ })
103
106
  </script>