frappe-ui 0.1.28 → 0.1.30

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": "frappe-ui",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "description": "A set of components and utilities for rapid UI development",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
@@ -19,6 +19,7 @@
19
19
  v-for="column in list.columns"
20
20
  :key="column.key"
21
21
  :item="column"
22
+ @updateWidth="(w) => (column.width = w)"
22
23
  />
23
24
  </slot>
24
25
  </div>
@@ -1,22 +1,83 @@
1
1
  <template>
2
2
  <div
3
- class="flex items-center space-x-2 text-sm text-gray-600"
3
+ ref="columnRef"
4
+ class="group flex items-center justify-between"
4
5
  :class="alignmentMap[item.align]"
5
6
  >
6
- <slot name="prefix" v-bind="{ item }" />
7
- <div>
8
- {{ item.label }}
7
+ <div
8
+ class="flex items-center space-x-2 truncate text-sm text-gray-600"
9
+ :class="$attrs.class"
10
+ >
11
+ <slot name="prefix" v-bind="{ item }" />
12
+ <div class="truncate">
13
+ {{ item.label }}
14
+ </div>
15
+ <slot name="suffix" v-bind="{ item }" />
9
16
  </div>
10
- <slot name="suffix" v-bind="{ item }" />
17
+ <slot v-if="list.options.resizeColumn" name="resizer" v-bind="{ item }">
18
+ <div
19
+ class="flex h-4 w-2 cursor-col-resize justify-center"
20
+ @mousedown="startResizing"
21
+ >
22
+ <div
23
+ ref="resizer"
24
+ class="h-full w-[2px] rounded-full transition-all duration-300 ease-in-out group-hover:bg-gray-400"
25
+ />
26
+ </div>
27
+ </slot>
11
28
  </div>
12
29
  </template>
13
30
 
14
31
  <script setup>
15
32
  import { alignmentMap } from './utils'
33
+ import { ref, computed, inject } from 'vue'
34
+
16
35
  const props = defineProps({
17
36
  item: {
18
37
  type: Object,
19
38
  required: true,
20
39
  },
21
40
  })
41
+
42
+ const emit = defineEmits(['updateWidth'])
43
+
44
+ const resizer = ref(null)
45
+ const columnRef = ref(null)
46
+
47
+ const widthInPx = computed(() => {
48
+ if (typeof props.item.width === 'string') {
49
+ const parsedWidth = parseInt(props.item.width)
50
+ if (props.item.width.includes('rem')) {
51
+ return parsedWidth * 16
52
+ } else if (props.item.width.includes('px')) {
53
+ return parsedWidth
54
+ }
55
+ }
56
+ return columnRef.value.offsetWidth
57
+ })
58
+
59
+ const startResizing = (e) => {
60
+ const initialX = e.clientX
61
+ const initialWidth = widthInPx.value
62
+ const onMouseMove = (e) => {
63
+ document.body.classList.add('select-none')
64
+ document.body.classList.add('cursor-col-resize')
65
+ resizer.value.style.backgroundColor = 'rgb(199 199 199)'
66
+ let newWidth = initialWidth + (e.clientX - initialX)
67
+
68
+ props.item.width = `${newWidth < 50 ? 50 : newWidth}px`
69
+ emit('updateWidth', props.item.width)
70
+ }
71
+ const onMouseUp = () => {
72
+ document.body.classList.remove('select-none')
73
+ document.body.classList.remove('cursor-col-resize')
74
+ resizer.value.style.backgroundColor = ''
75
+ window.removeEventListener('mousemove', onMouseMove)
76
+ window.removeEventListener('mouseup', onMouseUp)
77
+ }
78
+ window.addEventListener('mousemove', onMouseMove)
79
+ window.addEventListener('mouseup', onMouseUp)
80
+ }
81
+
82
+ const list = inject('list')
22
83
  </script>
@@ -42,6 +42,7 @@ const props = defineProps({
42
42
  onRowClick: null,
43
43
  showTooltip: true,
44
44
  selectable: true,
45
+ resizeColumn: true,
45
46
  },
46
47
  },
47
48
  })
@@ -64,6 +65,7 @@ let _options = computed(() => {
64
65
  onRowClick: props.options.onRowClick || null,
65
66
  showTooltip: defaultTrue(props.options.showTooltip),
66
67
  selectable: defaultTrue(props.options.selectable),
68
+ resizeColumn: defaultTrue(props.options.resizeColumn),
67
69
  }
68
70
  })
69
71
 
@@ -77,6 +77,8 @@ required to be passed in the `row` object.
77
77
  select/multiselect rows and perform some action on them - default is true
78
78
  4. showTooltip (Boolean) - if true, tooltip will be shown on hover of row -
79
79
  default is true
80
+ 5. resizeColumn (Boolean) - if true, column can be resized by dragging the
81
+ resizer on the right side of the column header - default is true
80
82
 
81
83
  ---
82
84
 
@@ -15,9 +15,10 @@ import { reactive } from 'vue'
15
15
  const state = reactive({
16
16
  selectable: true,
17
17
  showTooltip: true,
18
+ resizeColumn: true,
18
19
  })
19
20
 
20
- const simple_columns = [
21
+ const simple_columns = reactive([
21
22
  {
22
23
  label: 'Name',
23
24
  key: 'name',
@@ -36,7 +37,7 @@ const simple_columns = [
36
37
  label: 'Status',
37
38
  key: 'status',
38
39
  },
39
- ]
40
+ ])
40
41
 
41
42
  const simple_rows = [
42
43
  {
@@ -55,7 +56,7 @@ const simple_rows = [
55
56
  },
56
57
  ]
57
58
 
58
- const custom_columns = [
59
+ const custom_columns = reactive([
59
60
  {
60
61
  label: 'Name',
61
62
  key: 'name',
@@ -78,7 +79,7 @@ const custom_columns = [
78
79
  key: 'status',
79
80
  icon: 'check-circle',
80
81
  },
81
- ]
82
+ ])
82
83
 
83
84
  const custom_rows = [
84
85
  {
@@ -127,6 +128,7 @@ const custom_rows = [
127
128
  getRowRoute: (row) => ({ name: 'User', params: { userId: row.id } }),
128
129
  selectable: state.selectable,
129
130
  showTooltip: state.showTooltip,
131
+ resizeColumn: state.resizeColumn,
130
132
  }"
131
133
  row-key="id"
132
134
  />
@@ -140,6 +142,7 @@ const custom_rows = [
140
142
  onRowClick: (row) => console.log(row),
141
143
  selectable: state.selectable,
142
144
  showTooltip: state.showTooltip,
145
+ resizeColumn: state.resizeColumn,
143
146
  }"
144
147
  row-key="id"
145
148
  >
@@ -203,6 +206,7 @@ const custom_rows = [
203
206
  <template #controls>
204
207
  <HstCheckbox v-model="state.selectable" title="Selectable" />
205
208
  <HstCheckbox v-model="state.showTooltip" title="Show tooltip" />
209
+ <HstCheckbox v-model="state.resizeColumn" title="Resize Column" />
206
210
  </template>
207
211
  </Story>
208
212
  </template>
@@ -16,14 +16,18 @@ let createMixin = (mixinOptions) => ({
16
16
  if (typeof options == 'function') {
17
17
  watch(
18
18
  () => {
19
+ let out = null
19
20
  try {
20
- return options.call(this)
21
+ out = options.call(this)
21
22
  } catch (error) {
22
23
  console.warn('Failed to get resource options\n\n', error)
23
- return null
24
+ out = null
24
25
  }
26
+ return JSON.stringify(out)
25
27
  },
26
- (options, oldOptions) => {
28
+ (_options, _oldOptions) => {
29
+ let options = _options ? JSON.parse(_options) : null
30
+ let oldOptions = _oldOptions ? JSON.parse(_oldOptions) : null
27
31
  if (!options) {
28
32
  return
29
33
  }
@@ -37,6 +41,7 @@ let createMixin = (mixinOptions) => ({
37
41
  },
38
42
  {
39
43
  immediate: true,
44
+ deep: true,
40
45
  }
41
46
  )
42
47
  } else {