innoboxrr-vue-datatable 2.3.0 → 3.0.0

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.
@@ -1,81 +0,0 @@
1
- <template>
2
-
3
- <a
4
- class="block px-4 py-2 dark:hover:text-white dark:text-slate-400"
5
- :href="link"
6
- :target="target">
7
-
8
- <Icon
9
- class="fe-mr-sm"
10
- :icon="resolved"
11
- :width="size"
12
- :height="size"
13
- aria-hidden="true" />
14
-
15
- <span :class="textClass">{{ text }}</span>
16
-
17
- </a>
18
-
19
- </template>
20
-
21
- <script setup>
22
-
23
- /**
24
- * Antes esto pintaba `<span class="uk-icon" uk-icon="icon: fa-plus">` y
25
- * llamaba a `globalThis.UIkit.update()` al montar. Para que ese icono
26
- * apareciera hacian falta tres dependencias que ningun package.json
27
- * declaraba: uikit, fontawesome y uikit-custom-icons, que hacia de puente
28
- * entre las dos.
29
- *
30
- * Ahora el nombre se resuelve contra el mapa de innoboxrr-form-core, que
31
- * es el mismo que usa la rama React.
32
- */
33
-
34
- import { computed, onScopeDispose, ref } from 'vue'
35
- import { Icon } from '@iconify/vue'
36
- import { iconFor, onIconChange } from 'innoboxrr-form-core'
37
-
38
- const props = defineProps({
39
- link: {
40
- type: String,
41
- default: '#'
42
- },
43
- text: {
44
- type: String,
45
- required: true
46
- },
47
- icon: {
48
- type: String,
49
- required: true
50
- },
51
- ratio: {
52
- type: Number,
53
- required: false,
54
- default: 1
55
- },
56
- textClass: {
57
- type: String,
58
- default: ""
59
- },
60
- target: {
61
- type: String,
62
- default: "_self"
63
- }
64
- })
65
-
66
- // Un cambio de mapa en caliente repinta lo ya montado.
67
- const version = ref(0)
68
-
69
- onScopeDispose(onIconChange(() => version.value++))
70
-
71
- const resolved = computed(() => {
72
- version.value
73
-
74
- return iconFor(props.icon)
75
- })
76
-
77
- // `ratio` era el multiplicador de UIkit sobre 16px. Se conserva para no
78
- // romper a quien ya lo pasa.
79
- const size = computed(() => props.ratio * 16)
80
-
81
- </script>
@@ -1,84 +0,0 @@
1
- <template>
2
-
3
- <router-link
4
- :to="pathObject"
5
- class="block px-4 py-2 dark:hover:text-white dark:text-slate-400">
6
-
7
- <Icon
8
- class="fe-mr-sm"
9
- :icon="resolved"
10
- :width="size"
11
- :height="size"
12
- aria-hidden="true" />
13
-
14
- <span :class="textClass">{{ text }}</span>
15
-
16
- </router-link>
17
-
18
- </template>
19
-
20
- <script setup>
21
-
22
- import { computed, onScopeDispose, ref } from 'vue'
23
- import { Icon } from '@iconify/vue'
24
- import { iconFor, onIconChange } from 'innoboxrr-form-core'
25
-
26
- const props = defineProps({
27
- name: {
28
- type: String,
29
- required: true
30
- },
31
- // Vue 3 exige factoria en los defaults de objeto: un literal comparte
32
- // la misma instancia entre todas las filas de la tabla.
33
- params: {
34
- type: Object,
35
- default: () => ({})
36
- },
37
- query: {
38
- type: Object,
39
- default: () => ({})
40
- },
41
- text: {
42
- type: String,
43
- required: true
44
- },
45
- icon: {
46
- type: String,
47
- required: true
48
- },
49
- ratio: {
50
- type: Number,
51
- required: false,
52
- default: 1
53
- },
54
- textClass: {
55
- type: String,
56
- default: ""
57
- },
58
- })
59
-
60
- // Estaba en data(), asi que se calculaba una sola vez al crear el
61
- // componente: al reutilizar la fila para otro registro el enlace seguia
62
- // apuntando al anterior.
63
- const pathObject = computed(() => ({
64
- name: props.name,
65
- params: props.params,
66
- query: props.query,
67
- }))
68
-
69
- // Un cambio de mapa en caliente repinta lo ya montado.
70
- const version = ref(0)
71
-
72
- onScopeDispose(onIconChange(() => version.value++))
73
-
74
- const resolved = computed(() => {
75
- version.value
76
-
77
- return iconFor(props.icon)
78
- })
79
-
80
- // `ratio` era el multiplicador de UIkit sobre 16px. Se conserva para no
81
- // romper a quien ya lo pasa.
82
- const size = computed(() => props.ratio * 16)
83
-
84
- </script>
@@ -1,118 +0,0 @@
1
- <template>
2
-
3
- <div
4
- :id="id"
5
- ref="panel"
6
- popover
7
- :class="classFor('menu')"
8
- @beforetoggle="onBeforeToggle">
9
-
10
- <ul class="fe-menu-list">
11
-
12
- <slot></slot>
13
-
14
- </ul>
15
-
16
- </div>
17
-
18
- </template>
19
-
20
- <script setup>
21
-
22
- /**
23
- * El menu de acciones de una fila.
24
- *
25
- * Antes lo movia `uk-dropdown`, que ademas de la clase traia el JavaScript
26
- * de UIkit: abrir, cerrar al pulsar fuera, cerrar con Escape, capa
27
- * superior y posicionamiento, todo dentro de un framework de 12 MB que
28
- * ningun package.json declaraba.
29
- *
30
- * La mitad de eso ya lo hace el navegador. La **Popover API** —el atributo
31
- * `popover` y el `popovertarget` del boton— aporta de fabrica la capa
32
- * superior, el cierre al pulsar fuera y el cierre con Escape, sin una
33
- * linea de JavaScript. Lo unico que falta es colocarlo, y de eso se ocupa
34
- * Floating UI, que son unos 6 kB y es la pieza que usan por debajo Reka
35
- * UI, Radix y el propio Flowbite.
36
- *
37
- * El boton que lo abre solo necesita `popovertarget` con este mismo id:
38
- *
39
- * <button :popovertarget="`dropdown_${row.id}`">…</button>
40
- * <NavDropdownComponent :id="`dropdown_${row.id}`" pos="left" />
41
- */
42
-
43
- import { computed, ref } from 'vue'
44
- import { autoUpdate, computePosition, flip, offset, shift } from '@floating-ui/dom'
45
- import { classFor } from 'innoboxrr-form-core'
46
-
47
- const props = defineProps({
48
- id: {
49
- type: String,
50
- required: true,
51
- },
52
- // Se conservan los nombres que usaba UIkit para no romper a quien ya
53
- // los pasa; `bottom-left` y compania se traducen a los de Floating UI.
54
- pos: {
55
- type: String,
56
- default: 'bottom-left',
57
- },
58
- offset: {
59
- type: Number,
60
- default: 4,
61
- },
62
- })
63
-
64
- const panel = ref(null)
65
-
66
- /** Deja de seguir al disparador cuando el menu se cierra. */
67
- let stopFollowing = null
68
-
69
- const placement = computed(() => {
70
- const [side, align] = props.pos.split('-')
71
-
72
- if (! align) {
73
- return side
74
- }
75
-
76
- // UIkit dice `bottom-left` para «debajo, alineado a la izquierda»;
77
- // Floating UI lo llama `bottom-start`.
78
- return `${side}-${align === 'left' ? 'start' : 'end'}`
79
- })
80
-
81
- const onBeforeToggle = (event) => {
82
- if (event.newState !== 'open') {
83
- stopFollowing?.()
84
- stopFollowing = null
85
-
86
- return
87
- }
88
-
89
- // El boton es quien apunta a este panel, asi que se encuentra por el
90
- // atributo y no hace falta que nadie lo pase como prop.
91
- const trigger = document.querySelector(`[popovertarget="${props.id}"]`)
92
-
93
- if (! trigger || ! panel.value) {
94
- return
95
- }
96
-
97
- // autoUpdate recoloca al hacer scroll o redimensionar: un menu abierto
98
- // que se queda flotando donde estaba es peor que uno mal colocado.
99
- stopFollowing = autoUpdate(trigger, panel.value, () => {
100
- computePosition(trigger, panel.value, {
101
- placement: placement.value,
102
- middleware: [
103
- offset(props.offset),
104
- // Si no cabe abajo, se va arriba; si se sale por un lado,
105
- // se desplaza para caber.
106
- flip(),
107
- shift({ padding: 8 }),
108
- ],
109
- }).then(({ x, y }) => {
110
- Object.assign(panel.value.style, {
111
- left: `${x}px`,
112
- top: `${y}px`,
113
- })
114
- })
115
- })
116
- }
117
-
118
- </script>
@@ -1,79 +0,0 @@
1
- <template>
2
-
3
- <ul v-if="length > 3" class="fe-pagination fe-justify-center" fe-mb>
4
-
5
- <li v-if="firstLink != null">
6
-
7
- <a href="#" @click="emit('go', firstLink)">
8
-
9
- <span fe-page-prev></span>
10
-
11
- </a>
12
-
13
- </li>
14
-
15
- <li
16
- v-for="link in middleLinks"
17
- :key="link.label"
18
- :class="{ 'fe-disabled': link.url == null, 'fe-active': link.active, }">
19
-
20
- <a href="#" @click="emit('go', link.url)">
21
-
22
- {{ link.label }}
23
-
24
- </a>
25
-
26
- </li>
27
-
28
- <li v-if="lastLink != null">
29
-
30
- <a href="#" @click="emit('go', lastLink)">
31
-
32
- <span fe-page-next></span>
33
-
34
- </a>
35
-
36
- </li>
37
-
38
- </ul>
39
-
40
- </template>
41
-
42
- <script setup>
43
-
44
- import { computed } from 'vue'
45
-
46
- const props = defineProps({
47
- links: {
48
- type: Array,
49
- required: true,
50
- }
51
- })
52
-
53
- const emit = defineEmits(['go'])
54
-
55
- const length = computed(() => props.links.length)
56
-
57
- const firstLink = computed(() => length.value > 0 ? props.links[0].url : null)
58
-
59
- const lastLink = computed(() => {
60
-
61
- const last = props.links[length.value - 1]
62
-
63
- return length.value > 0 && last !== undefined ? last.url : null
64
-
65
- })
66
-
67
- const middleLinks = computed(() => props.links.slice(1, -1))
68
-
69
- </script>
70
-
71
- <style scoped>
72
-
73
- .fe-pagination > .fe-active > * {
74
- color: #666;
75
- font-weight: 600;
76
- border-bottom: 3px solid var(--primary-color);
77
- }
78
-
79
- </style>